X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fstem.cc;h=5b1a3d5041423e488e9cdc40eba25f4f7bf7a34a;hb=1c72394c0ae30ba289f869059ec2532eac8d4015;hp=bde62f57120d3099f189121f6b7fe38555866de0;hpb=1efdabf3b2349ea7fa3183dca5bba5104c347c36;p=lilypond.git diff --git a/lily/stem.cc b/lily/stem.cc index bde62f5712..5b1a3d5041 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--2009 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" @@ -244,7 +255,13 @@ Stem::pure_height (SCM smob, 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); @@ -254,7 +271,10 @@ Stem::pure_height (SCM smob, 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) @@ -311,6 +331,7 @@ Stem::calc_length (SCM smob) int durlog = duration_log (me); Real ss = Staff_symbol_referencer::staff_space (me); + Real staff_rad = Staff_symbol_referencer::staff_radius (me); Real length = 7; SCM s = ly_assoc_get (ly_symbol2scm ("lengths"), details, SCM_EOL); if (scm_is_pair (s)) @@ -326,11 +347,25 @@ Stem::calc_length (SCM smob) 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); - - /* On boundary: shorten only half */ - if (abs (head_positions (me)[dir]) <= 1) - shorten *= 0.5; + Real shorten_property = 2 * robust_scm2double (scm_shorten, 0); + /* change in length between full-size and shortened stems is executed gradually. + "transition area" = stems between full-sized and fully-shortened. + */ + Real quarter_stem_length = 2 * scm_to_double (robust_list_ref (0, s)); + /* shortening_step = difference in length between consecutive stem lengths + in transition area. The bigger the difference between full-sized + and shortened stems, the bigger shortening_step is. + (but not greater than 1/2 and not smaller than 1/4). + value 6 is heuristic; it determines the suggested transition slope steepnesas. + */ + Real shortening_step = min (max (0.25, (shorten_property / 6)), 0.5); + /* Shortening of unflagged stems should begin on the first stem that sticks + more than 1 staffspace (2 units) out of the staff. + Shortening of flagged stems begins in the same moment as unflagged ones, + but not earlier than on the middle line note. + */ + Real which_step = (min (1.0, quarter_stem_length - (2 * staff_rad) - 2.0)) + abs(hp[dir]); + Real shorten = min (max (0.0, (shortening_step * which_step)), shorten_property); length -= shorten; } @@ -698,6 +733,32 @@ Stem::thickness (Grob *me) * Staff_symbol_referencer::line_thickness (me); } +MAKE_SCHEME_CALLBACK (Stem, calc_stem_begin_position, 1); +SCM +Stem::calc_stem_begin_position (SCM smob) +{ + Grob *me = unsmob_grob (smob); + Direction d = get_grob_direction (me); + Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; + Grob *lh + = to_boolean (me->get_property ("avoid-note-head")) + ? last_head (me) + : first_head (me); + + Real pos = Staff_symbol_referencer::get_position (lh); + + if (Grob *head = support_head (me)) + { + Interval head_height = head->extent (head, Y_AXIS); + Real y_attach = Note_head::stem_attachment_coordinate (head, Y_AXIS); + + y_attach = head_height.linear_combination (y_attach); + pos += d * y_attach / half_space; + } + + return scm_from_double (pos); +} + MAKE_SCHEME_CALLBACK (Stem, print, 1); SCM Stem::print (SCM smob) @@ -736,7 +797,7 @@ Stem::print (SCM smob) Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; if (lh) - y2 = Staff_symbol_referencer::get_position (lh); + y2 = robust_scm2double (me->get_property ("stem-begin-position"), 0.0); else if (stemlet) { Real beam_translation = Beam::get_beam_translation (beam); @@ -751,18 +812,6 @@ Stem::print (SCM smob) Interval stem_y (min (y1, y2), max (y2, y1)); - if (Grob *head = support_head (me)) - { - /* - must not take ledgers into account. - */ - Interval head_height = head->extent (head, Y_AXIS); - Real y_attach = Note_head::stem_attachment_coordinate (head, Y_AXIS); - - y_attach = head_height.linear_combination (y_attach); - stem_y[Direction (-d)] += d * y_attach / half_space; - } - // URG Real stem_width = thickness (me); Real blot @@ -894,21 +943,26 @@ Stem::calc_stem_info (SCM smob) 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 = ly_assoc_get (ly_symbol2scm ("beamed-minimum-free-lengths"), details, SCM_EOL); + 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")); @@ -925,7 +979,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 @@ -979,9 +1033,11 @@ Stem::calc_stem_info (SCM smob) 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 @@ -1068,6 +1124,7 @@ ADD_INTERFACE (Stem, "note-heads " "positioning-done " "rests " + "stem-begin-position " "stem-end-position " "stem-info " "stemlet-length "