X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fstem.cc;h=11cf6def8b6e66d4d02045fb85b1dd31aa77a76c;hb=90fcc649dc06ad006158945acc15a69e24e942cd;hp=9d39552f574563dd1fa166ec38e86215a58c1acf;hpb=4799b41d843d95ede966cf96bc8fa98f1c9c5f60;p=lilypond.git diff --git a/lily/stem.cc b/lily/stem.cc index 9d39552f57..11cf6def8b 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -1,9 +1,7 @@ /* - stem.cc -- implement Stem + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter - - (c) 1996--2007 Han-Wen Nienhuys + Copyright (C) 1996--2011 Han-Wen Nienhuys Jan Nieuwenhuizen TODO: This is way too hairy @@ -11,6 +9,19 @@ TODO: fix naming. Stem-end, chord-start, etc. is all confusing naming. + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include "stem.hh" @@ -229,11 +240,10 @@ Stem::is_normal_stem (Grob *me) MAKE_SCHEME_CALLBACK (Stem, pure_height, 3) SCM -Stem::pure_height (SCM smob, SCM start, SCM end) +Stem::pure_height (SCM smob, + SCM /* start */, + SCM /* end */) { - (void) start; - (void) end; - Grob *me = unsmob_grob (smob); Interval iv; @@ -245,7 +255,13 @@ Stem::pure_height (SCM smob, SCM start, SCM end) if (!to_boolean (me->get_property ("cross-staff"))) { - Real len = scm_to_double (calc_length (smob)) * ss / 2; + Real len_in_halfspaces; + SCM user_set_len_scm = me->get_property_data ("length"); + if (scm_is_number (user_set_len_scm)) + len_in_halfspaces = scm_to_double (user_set_len_scm); + else + len_in_halfspaces = scm_to_double (calc_length (smob)); + Real len = len_in_halfspaces * ss / 2; Direction dir = get_grob_direction (me); Interval hp = head_positions (me); @@ -255,7 +271,10 @@ Stem::pure_height (SCM smob, SCM start, SCM end) iv = Interval (-len, 0); if (!hp.is_empty ()) - iv.translate (hp[dir] * ss / 2); + { + iv.translate (hp[dir] * ss / 2); + iv.add_point (hp[-dir] * ss / 2); + } /* extend the stem (away from the head) to cover the staff */ if (dir == UP) @@ -313,7 +332,7 @@ Stem::calc_length (SCM smob) Real ss = Staff_symbol_referencer::staff_space (me); Real length = 7; - SCM s = scm_cdr (scm_assq (ly_symbol2scm ("lengths"), details)); + SCM s = ly_assoc_get (ly_symbol2scm ("lengths"), details, SCM_EOL); if (scm_is_pair (s)) length = 2 * scm_to_double (robust_list_ref (durlog - 2, s)); @@ -324,7 +343,7 @@ Stem::calc_length (SCM smob) Interval hp = head_positions (me); if (dir && dir * hp[dir] >= 0) { - SCM sshorten = scm_cdr (scm_assq (ly_symbol2scm ("stem-shorten"), details)); + SCM sshorten = ly_assoc_get (ly_symbol2scm ("stem-shorten"), details, SCM_EOL); SCM scm_shorten = scm_is_pair (sshorten) ? robust_list_ref (max (duration_log (me) - 2, 0), sshorten) : SCM_EOL; Real shorten = 2* robust_scm2double (scm_shorten, 0); @@ -558,7 +577,7 @@ Stem::height (SCM smob) programming_error ("no stem direction"); dir = UP; } - iv[dir] += dir * Beam::get_thickness (beam) * 0.5; + iv[dir] += dir * Beam::get_beam_thickness (beam) * 0.5; } return ly_interval2scm (iv); @@ -570,29 +589,25 @@ Stem::stem_end_position (Grob *me) return robust_scm2double (me->get_property ("stem-end-position"), 0); } -Stencil -Stem::flag (Grob *me) +MAKE_SCHEME_CALLBACK (Stem, calc_flag, 1); +SCM +Stem::calc_flag (SCM smob) { - int log = duration_log (me); - if (log < 3 - || unsmob_grob (me->get_object ("beam"))) - return Stencil (); + Grob *me = unsmob_grob (smob); - if (!is_normal_stem (me)) - return Stencil (); - + int log = duration_log (me); /* TODO: maybe property stroke-style should take different values, e.g. "" (i.e. no stroke), "single" and "double" (currently, it's '() or "grace"). */ string flag_style; - SCM flag_style_scm = me->get_property ("flag-style"); + SCM flag_style_scm = me->get_property ("flag-style"); if (scm_is_symbol (flag_style_scm)) flag_style = ly_symbol2string (flag_style_scm); if (flag_style == "no-flag") - return Stencil (); + return Stencil ().smobbed_copy (); bool adjust = true; @@ -607,14 +622,14 @@ Stem::flag (Grob *me) */ { if (adjust) - { - int p = (int) (rint (stem_end_position (me))); - staffline_offs - = Staff_symbol_referencer::on_line (me, p) ? "0" : "1"; - } + { + int p = (int) (rint (stem_end_position (me))); + staffline_offs + = Staff_symbol_referencer::on_line (me, p) ? "0" : "1"; + } else - staffline_offs = "2"; - } + staffline_offs = "2"; + } else staffline_offs = ""; @@ -631,17 +646,45 @@ Stem::flag (Grob *me) { string stroke_style = ly_scm2string (stroke_style_scm); if (!stroke_style.empty ()) - { - string font_char = to_string (dir) + stroke_style; - Stencil stroke = fm->find_by_name ("flags." + font_char); - if (stroke.is_empty ()) - me->warning (_f ("flag stroke `%s' not found", font_char)); - else - flag.add_stencil (stroke); - } - } + { + string font_char = flag_style + to_string (dir) + stroke_style; + Stencil stroke = fm->find_by_name ("flags." + font_char); + if (stroke.is_empty ()) + { + font_char = to_string (dir) + stroke_style; + stroke = fm->find_by_name ("flags." + font_char); + } + if (stroke.is_empty ()) + me->warning (_f ("flag stroke `%s' not found", font_char)); + else + flag.add_stencil (stroke); + } + } + + return flag.smobbed_copy (); +} + + +Stencil +Stem::flag (Grob *me) +{ + int log = duration_log (me); + if (log < 3 + || unsmob_grob (me->get_object ("beam"))) + return Stencil (); - return flag; + if (!is_normal_stem (me)) + return Stencil (); + + // This get_property call already evaluates the scheme function with + // the grob passed as argument! Thus, we only have to check if a valid + // stencil is returned. + SCM flag_style_scm = me->get_property ("flag"); + if (Stencil *flag = unsmob_stencil (flag_style_scm)) { + return *flag; + } else { + return Stencil (); + } } MAKE_SCHEME_CALLBACK (Stem, width, 1); @@ -702,7 +745,7 @@ Stem::print (SCM smob) if (!lh && stemlet && !beam) return SCM_EOL; - if (robust_scm2int (lh->get_property ("duration-log"), 0) < 1) + if (lh && robust_scm2int (lh->get_property ("duration-log"), 0) < 1) return SCM_EOL; if (is_invisible (me)) @@ -717,7 +760,7 @@ Stem::print (SCM smob) else if (stemlet) { Real beam_translation = Beam::get_beam_translation (beam); - Real beam_thickness = Beam::get_thickness (beam); + Real beam_thickness = Beam::get_beam_thickness (beam); int beam_count = beam_multiplicity (me).length () + 1; y2 -= d @@ -861,31 +904,36 @@ Stem::calc_stem_info (SCM smob) } Real beam_translation = Beam::get_beam_translation (beam); - Real beam_thickness = Beam::get_thickness (beam); + Real beam_thickness = Beam::get_beam_thickness (beam); int beam_count = Beam::get_direction_beam_count (beam, my_dir); Real length_fraction = robust_scm2double (me->get_property ("length-fraction"), 1.0); /* Simple standard stem length */ SCM details = me->get_property ("details"); - SCM lengths = scm_cdr (scm_assq (ly_symbol2scm ("beamed-lengths"), details)); + SCM lengths = ly_assoc_get (ly_symbol2scm ("beamed-lengths"), details, SCM_EOL); Real ideal_length - = scm_to_double (robust_list_ref (beam_count - 1, lengths)) - * staff_space - * length_fraction - - /* stem only extends to center of beam - */ - - 0.5 * beam_thickness; + = (scm_is_pair (lengths) + ? (scm_to_double (robust_list_ref (beam_count - 1, lengths)) + * staff_space + * length_fraction + /* + stem only extends to center of beam + */ + - 0.5 * beam_thickness) + : 0.0); /* Condition: sane minimum free stem length (chord to beams) */ - lengths = scm_cdr (scm_assq (ly_symbol2scm ("beamed-minimum-free-lengths"), details)); + lengths = ly_assoc_get (ly_symbol2scm ("beamed-minimum-free-lengths"), + details, SCM_EOL); Real ideal_minimum_free - = scm_to_double (robust_list_ref (beam_count - 1, lengths)) - * staff_space - * length_fraction; + = (scm_is_pair (lengths) + ? (scm_to_double (robust_list_ref (beam_count - 1, lengths)) + * staff_space + * length_fraction) + : 0.0); Real height_of_my_trem = 0.0; Grob *trem = unsmob_grob (me->get_object ("tremolo-flag")); @@ -902,7 +950,7 @@ Stem::calc_stem_info (SCM smob) It seems that also for ideal minimum length, we must use the maximum beam count (for this direction): - \score{ \notes\relative c''{ [a8 a32] }} + \score { \relative c'' { a8[ a32] } } must be horizontal. */ Real height_of_my_beams = beam_thickness @@ -952,13 +1000,15 @@ Stem::calc_stem_info (SCM smob) ideal_y -= robust_scm2double (beam->get_property ("shorten"), 0); - SCM bemfl = scm_cdr (scm_assq (ly_symbol2scm ("beamed-extreme-minimum-free-lengths"), - details)); + SCM bemfl = ly_assoc_get (ly_symbol2scm ("beamed-extreme-minimum-free-lengths"), + details, SCM_EOL); Real minimum_free - = scm_to_double (robust_list_ref (beam_count - 1, bemfl)) - * staff_space - * length_fraction; + = (scm_is_pair (bemfl) + ? (scm_to_double (robust_list_ref (beam_count - 1, bemfl)) + * staff_space + * length_fraction) + : 0.0); Real minimum_length = max (minimum_free, height_of_my_trem) + height_of_my_beams @@ -1028,10 +1078,13 @@ ADD_INTERFACE (Stem, "avoid-note-head " "beam " "beaming " + "beamlet-default-length " + "beamlet-max-length-proportion " "default-direction " "details " "direction " "duration-log " + "flag " "flag-style " "french-beaming " "length "