From e1abbf35e78b9bb309a3b6d6ca1d44242a2d7e6b Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 29 Mar 2006 15:41:44 +0000 Subject: [PATCH] * input/regression/stem-tremolo-position.ly: new file. * lily/stem-tremolo.cc: remove Stem_tremolo::dim_callback --- ChangeLog | 29 ++++++ input/regression/stem-tremolo-position.ly | 16 +++ lily/include/stem-tremolo.hh | 6 +- lily/stem-tremolo.cc | 118 +++++++++++++--------- lily/stem.cc | 42 ++++---- scm/define-grobs.scm | 3 +- 6 files changed, 147 insertions(+), 67 deletions(-) create mode 100644 input/regression/stem-tremolo-position.ly diff --git a/ChangeLog b/ChangeLog index d5083e89dd..376e724993 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2006-03-29 Han-Wen Nienhuys + + * input/regression/stem-tremolo-position.ly: new file. + + * lily/stem-tremolo.cc: remove Stem_tremolo::dim_callback + +2006-03-28 Joe Neeman + + * lily/stem-tremolo.cc (print): position + the tremolo depending only on the end of the stem + and not on the notehead + (raw_stencil): center, on the middle staff line, the + flag that is closest to the end of the stem (previously + the bottom flag) + (calc_width): add this callback to shorten a tremolo when + it is beamed or it is stemup with a flag + (style): add this callback to make a tremolo rectangular when + it is beamed or it is stemup with a flag + (rotated_box): this is like Lookup::beam but makes a rotated + rectangle instead of a parallelogram + + * lily/stem.cc (calc_stem_info): make sure the stem + is long enough to fit the tremolo + (calc-length): reduce the length of tremolo stems since the + tremolo code is now capable of better positioning + + * scm/define-grobs.scm: make calc_width the default beam-width + callback for stem-tremolo and add the style callback + 2006-03-29 Han-Wen Nienhuys * lily/tuplet-bracket.cc (calc_control_points): handle suicide diff --git a/input/regression/stem-tremolo-position.ly b/input/regression/stem-tremolo-position.ly new file mode 100644 index 0000000000..2074046942 --- /dev/null +++ b/input/regression/stem-tremolo-position.ly @@ -0,0 +1,16 @@ +\header { + texidoc = "Tremolos are positioned a fixed distance from the + end of the beam. Tremolo flags are shortened and made rectangular + on beamed notes or on stem-up notes with a flag. Tremolo flags are + tilted extra on stem-down notes with a flag." +} + +\version "2.9.0" +\layout { + ragged-right = ##T +} + +\relative c' { + c16:32 e: f: a: c,4:8 c4:32 c8:16 \noBeam c16:32 \noBeam c16:64 | + c''16:32 e: f: a: c,4:8 c4:32 c8:16 \noBeam c16:32 \noBeam c16:64 | +} diff --git a/lily/include/stem-tremolo.hh b/lily/include/stem-tremolo.hh index 41d504a8c7..fb8f57ff5e 100644 --- a/lily/include/stem-tremolo.hh +++ b/lily/include/stem-tremolo.hh @@ -17,11 +17,13 @@ class Stem_tremolo public: static bool has_interface (Grob *); - DECLARE_SCHEME_CALLBACK (dim_callback, (SCM smob)); DECLARE_SCHEME_CALLBACK (calc_slope, (SCM)); + DECLARE_SCHEME_CALLBACK (calc_width, (SCM)); DECLARE_SCHEME_CALLBACK (print, (SCM)); DECLARE_SCHEME_CALLBACK (height, (SCM)); - static Stencil raw_stencil (Grob *, Real); + DECLARE_SCHEME_CALLBACK (calc_style, (SCM)); + static Stencil rotated_box (Real slope, Real width, Real thick, Real blot); + static Stencil raw_stencil (Grob *, Real, Direction stemdir); static Real get_beam_translation (Grob *me); }; diff --git a/lily/stem-tremolo.cc b/lily/stem-tremolo.cc index 03019d0237..05de18bab7 100644 --- a/lily/stem-tremolo.cc +++ b/lily/stem-tremolo.cc @@ -18,21 +18,6 @@ #include "stem.hh" #include "warn.hh" -/* TODO: lengthen stem if necessary */ - -MAKE_SCHEME_CALLBACK (Stem_tremolo, dim_callback, 1); - -/* todo: init with cons. */ -SCM -Stem_tremolo::dim_callback (SCM e) -{ - Grob *se = unsmob_grob (e); - - Real space = Staff_symbol_referencer::staff_space (se); - return ly_interval2scm (Interval (-space, space)); -} - - MAKE_SCHEME_CALLBACK (Stem_tremolo, calc_slope, 1) SCM Stem_tremolo::calc_slope (SCM smob) @@ -58,7 +43,38 @@ Stem_tremolo::calc_slope (SCM smob) return scm_from_double (dx ? dy / dx : 0); } else - return scm_from_double (0.25); + /* down stems with flags should have more sloped trems (helps avoid + flag/stem collisions without making the stem very long) */ + return scm_from_double ( + (Stem::duration_log (stem) >= 3 && get_grob_direction (stem) == DOWN) ? + 0.40 : 0.25); +} + +MAKE_SCHEME_CALLBACK (Stem_tremolo, calc_width, 1) +SCM +Stem_tremolo::calc_width (SCM smob) +{ + Grob *me = unsmob_grob (smob); + Grob *stem = unsmob_grob (me->get_object ("stem")); + Direction stemdir = get_grob_direction (stem); + bool beam = Stem::get_beam (stem); + bool flag = Stem::duration_log (stem) >= 3 && !beam; + + /* beamed stems and up-stems with flags have shorter tremolos */ + return scm_from_double (((stemdir == UP && flag) || beam)? 1.0 : 1.5); +} + +MAKE_SCHEME_CALLBACK (Stem_tremolo, calc_style, 1) +SCM +Stem_tremolo::calc_style (SCM smob) +{ + Grob *me = unsmob_grob (smob); + Grob *stem = unsmob_grob (me->get_object ("stem")); + Direction stemdir = get_grob_direction (stem); + bool beam = Stem::get_beam (stem); + bool flag = Stem::duration_log (stem) >= 3 && !beam; + + return ly_symbol2scm (((stemdir == UP && flag) || beam) ? "rectangle" : "default"); } Real @@ -70,19 +86,42 @@ Stem_tremolo::get_beam_translation (Grob *me) return beam ? Beam::get_beam_translation (beam) : 0.81; } +/* FIXME: move to Lookup? */ +Stencil +Stem_tremolo::rotated_box (Real slope, Real width, Real thick, Real blot) +{ + vector pts; + Offset rot (1, slope); + + thick -= 2*blot; + width -= 2*blot; + rot /= sqrt (1 + slope*slope); + pts.push_back (Offset (0, -thick / 2) * rot); + pts.push_back (Offset (width, -thick / 2) * rot); + pts.push_back (Offset (width, thick / 2) * rot); + pts.push_back (Offset (0, thick / 2) * rot); + return Lookup::round_filled_polygon (pts, blot); +} + Stencil -Stem_tremolo::raw_stencil (Grob *me, Real slope) +Stem_tremolo::raw_stencil (Grob *me, Real slope, Direction stemdir) { Real ss = Staff_symbol_referencer::staff_space (me); Real thick = robust_scm2double (me->get_property ("beam-thickness"), 1); Real width = robust_scm2double (me->get_property ("beam-width"), 1); Real blot = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")); + SCM style = me->get_property ("style"); + if (!scm_is_symbol (style)) + style = ly_symbol2scm ("default"); width *= ss; thick *= ss; - Stencil a (Lookup::beam (slope, width, thick, blot)); - a.translate (Offset (-width * 0.5, width * 0.5 * slope)); + Stencil a = style == ly_symbol2scm ("rectangle") ? + rotated_box (slope, width, thick, blot) : + Lookup::beam (slope, width, thick, blot); + a.align_to (X_AXIS, CENTER); + a.align_to (Y_AXIS, CENTER); int tremolo_flags = robust_scm2int (me->get_property ("flag-count"), 0); if (!tremolo_flags) @@ -93,14 +132,13 @@ Stem_tremolo::raw_stencil (Grob *me, Real slope) return Stencil (); } - /* Who the fuck is 0.81 ? --hwn. */ Real beam_translation = get_beam_translation(me); Stencil mol; for (int i = 0; i < tremolo_flags; i++) { Stencil b (a); - b.translate_axis (beam_translation * i, Y_AXIS); + b.translate_axis (beam_translation * i * stemdir * -1, Y_AXIS); mol.add_stencil (b); } return mol; @@ -117,7 +155,7 @@ Stem_tremolo::height (SCM smob) /* Cannot use the real slope, since it looks at the Beam. */ - Stencil s1 (raw_stencil (me, 0.35)); + Stencil s1 (raw_stencil (me, 0.35, UP)); return ly_interval2scm (s1.extent (Y_AXIS)); } @@ -146,7 +184,8 @@ Stem_tremolo::print (SCM grob) : 0.81; Stencil mol = raw_stencil (me, robust_scm2double (me->get_property ("slope"), - 0.25)); + 0.25), stemdir); + Interval mol_ext = mol.extent (Y_AXIS); Real ss = Staff_symbol_referencer::staff_space (me); @@ -160,37 +199,26 @@ Stem_tremolo::print (SCM grob) Real end_y = Stem::stem_end_position (stem) * ss / 2 - - stemdir * (beam_count * beamthickness - + (max (beam_count -1, 0) * beam_translation)); - - /* FIXME: the 0.33 ss is to compensate for the size of the note head. */ - Real chord_start_y = Stem::chord_start_y (stem) + 0.33 * ss * stemdir; - - Real padding = beam_translation; + - stemdir * max (beam_count, 1) * beam_translation; - /* if there is a flag, just above/below the notehead. - if there is not enough space, center on remaining space, - else one beamspace away from stem end. */ if (!beam && Stem::duration_log (stem) >= 3) { - mol.align_to (Y_AXIS, -stemdir); - mol.translate_axis (chord_start_y + 0.5 * stemdir, Y_AXIS); + end_y -= stemdir * (Stem::duration_log (stem) - 2) * beam_translation; + if (stemdir == UP) + end_y -= stemdir * beam_translation * 0.5; } - else if (stemdir * (end_y - chord_start_y) - 2 * padding - mol_ext.length () - < 0.0) - mol.translate_axis (0.5 * (end_y + chord_start_y) - mol_ext.center (), - Y_AXIS); - else - mol.translate_axis (end_y - stemdir * beam_translation -mol_ext [stemdir], - Y_AXIS); + mol.translate_axis (end_y, Y_AXIS); return mol.smobbed_copy (); } ADD_INTERFACE (Stem_tremolo, "stem-tremolo-interface", "A beam slashing a stem to indicate a tremolo.", + + "beam-thickness " + "beam-width " + "flag-count " "stem " + "style " "slope " - "beam-width " - "beam-thickness " - "flag-count"); + ); diff --git a/lily/stem.cc b/lily/stem.cc index 8a59a4909c..1be8f59855 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -335,17 +335,21 @@ Stem::calc_length (SCM smob) + 2 * t_flag->extent (t_flag, Y_AXIS).length () / ss; + /* We don't want to add the whole extent of the flag because the trem + and the flag can overlap partly. beam_translation gives a good + approximation */ if (durlog >= 3) - { - Interval flag_ext = flag (me).extent (Y_AXIS); - if (!flag_ext.is_empty ()) - minlen += 2 * flag_ext.length () / ss; - - /* The clash is smaller for down stems (since the tremolo is - angled up.) */ - if (dir == DOWN) - minlen -= 1.0; - } + { + Real beam_trans = Stem_tremolo::get_beam_translation (t_flag); + /* the obvious choice is (durlog - 2) here, but we need a bit more space. */ + minlen += 2 * (durlog - 1.5) * beam_trans; + + /* up-stems need even a little more space to avoid collisions. This + needs to be in sync with the tremolo positioning code in + Stem_tremolo::print */ + if (dir == UP) + minlen += beam_trans; + } length = max (length, minlen + 1.0); } @@ -798,7 +802,6 @@ Stem::get_stem_info (Grob *me) return si; } -/* TODO: add extra space for tremolos! */ MAKE_SCHEME_CALLBACK(Stem, calc_stem_info, 1); SCM Stem::calc_stem_info (SCM smob) @@ -847,6 +850,13 @@ Stem::calc_stem_info (SCM smob) * staff_space * length_fraction; + Real height_of_my_trem = 0.0; + Grob *trem = unsmob_grob (me->get_object ("tremolo-flag")); + if (trem) + height_of_my_trem = trem->extent (trem, Y_AXIS).length () + /* hack a bit of space around the trem. */ + + beam_translation; + /* UGH It seems that also for ideal minimum length, we must use the maximum beam count (for this direction): @@ -859,6 +869,7 @@ Stem::calc_stem_info (SCM smob) Real ideal_minimum_length = ideal_minimum_free + height_of_my_beams + + height_of_my_trem /* stem only extends to center of beam */ - 0.5 * beam_thickness; @@ -908,18 +919,11 @@ Stem::calc_stem_info (SCM smob) * staff_space * length_fraction; - Real minimum_length = minimum_free + Real minimum_length = max (minimum_free, height_of_my_trem) + height_of_my_beams /* stem only extends to center of beam */ - 0.5 * beam_thickness; - if (Grob *tremolo = unsmob_grob (me->get_object ("tremolo-flag"))) - { - Interval y_ext = tremolo->extent (tremolo, Y_AXIS); - y_ext.widen (0.5); // FIXME. Should be tunable? - minimum_length = max (minimum_length, y_ext.length ()); - } - ideal_y *= my_dir; Real minimum_y = note_start + minimum_length; Real shortest_y = minimum_y * my_dir; diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 1d10225b4d..20cb7b3f2e 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -1451,7 +1451,8 @@ (stencil . ,ly:stem-tremolo::print) (X-extent . #f) (slope . ,ly:stem-tremolo::calc-slope) - (beam-width . 1.6) ; staff-space + (beam-width . ,ly:stem-tremolo::calc-width) ; staff-space + (style . ,ly:stem-tremolo::calc-style) (beam-thickness . 0.48) ; staff-space (meta . ((class . Item) (interfaces . (stem-tremolo-interface)))))) -- 2.39.5