On Tue, 28 Mar 2006 20:20, Han-Wen Nienhuys wrote: > Han-Wen Nienhuys wrote: > > Can you resend the patch using more idiomatic code? Thanks! > > Also, can you include a small regression test sample, so it's obvious > when we break something?
I'm not quite sure if we reached a conclusion on the default behaviour of tremolos and I'm also not quite sure what the protocol is for adding things to interfaces (I added "style" to stem-tremolo-interface. It can be 'rectangle or 'default) but here is another try anyway. I also enclose a regression test and an image of the output. 2006-03-28 Joe Neeman <[EMAIL PROTECTED]> * 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
\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 | }
Index: lily/include/stem-tremolo.hh =================================================================== RCS file: /sources/lilypond/lilypond/lily/include/stem-tremolo.hh,v retrieving revision 1.34 diff -u -r1.34 stem-tremolo.hh --- lily/include/stem-tremolo.hh 10 Feb 2006 01:05:05 -0000 1.34 +++ lily/include/stem-tremolo.hh 29 Mar 2006 12:28:34 -0000 @@ -19,9 +19,12 @@ 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 (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); }; Index: lily/stem.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/stem.cc,v retrieving revision 1.304 diff -u -r1.304 stem.cc --- lily/stem.cc 2 Mar 2006 10:50:40 -0000 1.304 +++ lily/stem.cc 29 Mar 2006 12:28:35 -0000 @@ -335,17 +335,21 @@ + 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 @@ 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 @@ * 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 @@ 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 @@ * 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; Index: lily/stem-tremolo.cc =================================================================== RCS file: /sources/lilypond/lilypond/lily/stem-tremolo.cc,v retrieving revision 1.99 diff -u -r1.99 stem-tremolo.cc --- lily/stem-tremolo.cc 10 Feb 2006 01:05:05 -0000 1.99 +++ lily/stem-tremolo.cc 29 Mar 2006 12:28:35 -0000 @@ -58,7 +58,38 @@ 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, style, 1) +SCM +Stem_tremolo::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 +101,42 @@ 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<Offset> 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) @@ -100,7 +154,7 @@ 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 +171,7 @@ /* 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 +200,8 @@ : 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,29 +215,15 @@ 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 (); } @@ -190,6 +231,7 @@ ADD_INTERFACE (Stem_tremolo, "stem-tremolo-interface", "A beam slashing a stem to indicate a tremolo.", "stem " + "style " "slope " "beam-width " "beam-thickness " Index: scm/define-grobs.scm =================================================================== RCS file: /sources/lilypond/lilypond/scm/define-grobs.scm,v retrieving revision 1.327 diff -u -r1.327 define-grobs.scm --- scm/define-grobs.scm 20 Mar 2006 23:42:21 -0000 1.327 +++ scm/define-grobs.scm 29 Mar 2006 12:28:35 -0000 @@ -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::style) (beam-thickness . 0.48) ; staff-space (meta . ((class . Item) (interfaces . (stem-tremolo-interface))))))
<<attachment: tremolos.jpeg>>
_______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel