From 1ffc669c299776ae2a13cdbbce8daf580ecf1a89 Mon Sep 17 00:00:00 2001 From: hanwen Date: Sun, 14 Jul 2002 16:15:11 +0000 Subject: [PATCH] * lily/beam.cc (quanting): add explicit support for cross-staff beaming: make slope penalty larger. * lily/beam.cc: use common refpoints throughout. This fixes many cross staff issues. --- ChangeLog | 6 + Documentation/regression-test.tely | 10 +- input/regression/beam-cross-staff-slope.ly | 32 ++++ lily/beam.cc | 183 ++++++++++++--------- lily/include/beam.hh | 8 +- ly/engraver-init.ly | 7 +- scm/grob-description.scm | 3 +- 7 files changed, 161 insertions(+), 88 deletions(-) create mode 100644 input/regression/beam-cross-staff-slope.ly diff --git a/ChangeLog b/ChangeLog index 190c3f94eb..3d24a7f4ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2002-07-14 Han-Wen + * lily/beam.cc (quanting): add explicit support for cross-staff + beaming: make slope penalty larger. + + * lily/beam.cc: use common refpoints throughout. This fixes many + cross staff issues. + * lily/paper-column.cc (before_line_breaking): bug fix. * lily/volta-engraver.cc (process_music): do something sensible if diff --git a/Documentation/regression-test.tely b/Documentation/regression-test.tely index cecc2fa4f9..6f57737a4b 100644 --- a/Documentation/regression-test.tely +++ b/Documentation/regression-test.tely @@ -152,6 +152,7 @@ Grace note do weird things with timing. Fragile. @section Beams + @lilypondfile[printfilename]{beams.ly} @lilypondfile[printfilename]{beam-funky.ly} @@ -184,6 +185,13 @@ Grace note do weird things with timing. Fragile. @lilypondfile[printfilename]{triplets.ly} +@lilypondfile[printfilename]{beam-cross-staff.ly} + +@lilypondfile[printfilename]{beam-cross-staff-slope.ly} + + +@section Auto beamer + @lilypondfile[printfilename]{beaming-ternary-metrum.ly} @section Slurs @@ -329,8 +337,6 @@ Grace note do weird things with timing. Fragile. @section PianoStaff -@lilypondfile[printfilename]{beam-cross-staff.ly} - @lilypondfile[printfilename]{slur-cross-staff.ly} @lilypondfile[printfilename]{percent-repeat.ly} diff --git a/input/regression/beam-cross-staff-slope.ly b/input/regression/beam-cross-staff-slope.ly new file mode 100644 index 0000000000..abfc7a3ac8 --- /dev/null +++ b/input/regression/beam-cross-staff-slope.ly @@ -0,0 +1,32 @@ +\header { + texidoc = "Cross staff (kneed) beams +don't cause extreme slopes" +} + +\score { + \notes\context PianoStaff < + \context Staff = up + \relative c'' < + { + \stemDown + f16( \> d \! b \translator Staff = down \stemUp + \clef treble g ~ < g8 )e> + + [e \translator Staff = up + \stemDown + e e] + \translator Staff = down + \stemUp + [ + e8. \translator Staff = up + \stemDown + e8.] + + } \\ + > + \context Staff = down { + \time 3/8 \clef bass s4.*3 } + > + \paper { linewidth = -1. } +} + diff --git a/lily/beam.cc b/lily/beam.cc index 22880a15ac..09f25efa83 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -15,8 +15,6 @@ TODO: * Junk stem_info. * Use Number_pair i.s.o Interval to represent (yl, yr). - - * cross staff - Determine auto knees based on positions if it's set by the user. @@ -33,6 +31,7 @@ Notes: #include // tanh. +#include "align-interface.hh" #include "molecule.hh" #include "directional-element-interface.hh" #include "beaming.hh" @@ -517,13 +516,10 @@ Beam::consider_auto_knees (Grob *me, Direction d) Real gap = gh_scm2double (scm) / staff_space; - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); + Link_array stems= + Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); - Grob *common = me->common_refpoint (stems[0], Y_AXIS); - for (int i=1; i < stems.size (); i++) - if (!Stem::invisible_b (stems[i])) - common = common->common_refpoint (stems[i], Y_AXIS); + Grob *common = common_refpoint_of_array (stems, me, Y_AXIS); int l = 0; for (int i=1; i < stems.size (); i++) @@ -554,7 +550,7 @@ Beam::consider_auto_knees (Grob *me, Direction d) { for (int i=0; i < stems.size (); i++) { - Item *s = stems[i]; + Grob *s = stems[i]; if (Stem::invisible_b (s) || s->get_grob_property ("dir-forced") == SCM_BOOL_T) continue; @@ -702,7 +698,8 @@ Beam::quanting (SCM smob) Array rbase_lengths; Drul_array dirs_found(0,0); - + Grob *common_y = common_refpoint_of_array (stems, me, Y_AXIS); + bool french = to_boolean (me->get_grob_property ("french-beaming")); for (int i= 0; i < stems.size(); i++) { @@ -710,10 +707,10 @@ Beam::quanting (SCM smob) stem_infos.push (Stem::calc_stem_info (s)); dirs_found[stem_infos.top ().dir_] = true; - Real b = calc_stem_y (me, s, Interval (1,0), french && i > 0&& (i < stems.size () -1)); + Real b = calc_stem_y (me, s, common_y , Interval (1,0), french && i > 0&& (i < stems.size () -1)); lbase_lengths.push (b); - Real a = calc_stem_y (me, s, Interval (0,1), french && i > 0&& (i < stems.size () -1)); + Real a = calc_stem_y (me, s, common_y , Interval (0,1), french && i > 0&& (i < stems.size () -1)); rbase_lengths.push (a); } @@ -757,12 +754,20 @@ Beam::quanting (SCM smob) parameters outside of the loop, we can save a lot of time. */ + + + Grob *fvs = first_visible_stem (me); + Grob *lvs = last_visible_stem (me); + + Grob *commony = fvs->common_refpoint (lvs, Y_AXIS); + bool xstaff= (Align_interface::has_interface (commony)); + for (int i = qscores.size (); i--;) if (qscores[i].demerits < 100) { qscores[i].demerits += score_slopes_dy (me, qscores[i].yl, qscores[i].yr, - dy_mus, yr- yl); + dy_mus, yr- yl, xstaff); } Real rad = Staff_symbol_referencer::staff_radius (me); @@ -859,7 +864,8 @@ Beam::score_stem_lengths (Link_arraystems, Real Beam::score_slopes_dy (Grob *me, Real yl, Real yr, - Real dy_mus, Real dy_damp) + Real dy_mus, Real dy_damp, + bool xstaff) { Real dy = yr - yl; @@ -870,8 +876,18 @@ Beam::score_slopes_dy (Grob *me, } dem += MUSICAL_DIRECTION_FACTOR * (0 >? (fabs (dy) - fabs (dy_mus))); - dem += shrink_extra_weight (fabs (dy_damp) - fabs (dy))* IDEAL_SLOPE_FACTOR; + + Real slope_penalty = IDEAL_SLOPE_FACTOR; + + /* + Xstaff beams tend to use extreme slopes to get short stems. We + put in a penalty here. + */ + if (xstaff) + slope_penalty *= 10; + + dem += shrink_extra_weight (fabs (dy_damp) - fabs (dy))* slope_penalty; return dem; } @@ -996,27 +1012,32 @@ Beam::least_squares (SCM smob) return SCM_UNSPECIFIED; } - Interval ideal (Stem::calc_stem_info (first_visible_stem (me)).ideal_y_, - Stem::calc_stem_info (last_visible_stem (me)).ideal_y_); - - Array x_posns ; - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - Grob *common = stems[0]; - for (int i=1; i < stems.size (); i++) - common = stems[i]->common_refpoint (common, X_AXIS); + Link_array stems= + Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); + Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS); + Grob *commony = common_refpoint_of_array (stems, me, Y_AXIS); - Real x0 = first_visible_stem (me)->relative_coordinate (common, X_AXIS); + Real my_y = me->relative_coordinate (commony, Y_AXIS); + + Grob *fvs = first_visible_stem (me); + Grob *lvs = last_visible_stem (me); + + Interval ideal (Stem::calc_stem_info (fvs).ideal_y_ + + fvs->relative_coordinate (commony, Y_AXIS) -my_y, + Stem::calc_stem_info (lvs).ideal_y_ + + lvs->relative_coordinate (commony, Y_AXIS) - my_y); + + Real x0 = first_visible_stem (me)->relative_coordinate (commonx, X_AXIS); for (int i=0; i < stems.size (); i++) { - Item* s = stems[i]; + Grob* s = stems[i]; - Real x = s->relative_coordinate (common, X_AXIS) - x0; + Real x = s->relative_coordinate (commonx, X_AXIS) - x0; x_posns.push (x); } - Real dx = last_visible_stem (me)->relative_coordinate (common, X_AXIS) - x0; + Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS) - x0; Real y =0; Real dydx = 0; @@ -1060,11 +1081,13 @@ Beam::least_squares (SCM smob) Array ideals; for (int i=0; i < stems.size (); i++) { - Item* s = stems[i]; + Grob* s = stems[i]; if (Stem::invisible_b (s)) continue; ideals.push (Offset (x_posns[i], - Stem::calc_stem_info (s).ideal_y_)); + Stem::calc_stem_info (s).ideal_y_ + + s->relative_coordinate (commony, Y_AXIS) + - my_y)); } minimise_least_squares (&dydx, &y, ideals); @@ -1092,23 +1115,22 @@ Beam::shift_region_to_valid (SCM grob) Code dup. */ Array x_posns ; - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); - Grob *common = stems[0]; - for (int i=1; i < stems.size (); i++) - common = stems[i]->common_refpoint (common, X_AXIS); + Link_array stems= + Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); + Grob *commonx = common_refpoint_of_array (stems, me, X_AXIS); + Grob *commony = common_refpoint_of_array (stems, me, Y_AXIS); Grob *fvs = first_visible_stem (me); if (!fvs) return SCM_UNSPECIFIED; - Real x0 =fvs->relative_coordinate (common, X_AXIS); + Real x0 =fvs->relative_coordinate (commonx, X_AXIS); for (int i=0; i < stems.size (); i++) { - Item* s = stems[i]; + Grob* s = stems[i]; - Real x = s->relative_coordinate (common, X_AXIS) - x0; + Real x = s->relative_coordinate (commonx, X_AXIS) - x0; x_posns.push (x); } @@ -1116,7 +1138,7 @@ Beam::shift_region_to_valid (SCM grob) if (!lvs) return SCM_UNSPECIFIED; - Real dx = lvs->relative_coordinate (common, X_AXIS) - x0; + Real dx = lvs->relative_coordinate (commonx, X_AXIS) - x0; Interval pos = ly_scm2interval ( me->get_grob_property ("positions")); Real dy = pos.delta(); @@ -1132,17 +1154,24 @@ Beam::shift_region_to_valid (SCM grob) feasible_left_point.set_full (); for (int i=0; i < stems.size (); i++) { - Item* s = stems[i]; + Grob* s = stems[i]; if (Stem::invisible_b (s)) continue; - Direction d = Stem::get_direction (s); - - Real left_y = Stem::calc_stem_info (s).shortest_y_ + Real left_y = + Stem::calc_stem_info (s).shortest_y_ - dydx * x_posns [i]; + /* + left_y is now relative to the stem S. We want relative to + ourselves, so translate: + */ + left_y += + + s->relative_coordinate (commony, Y_AXIS) + - me->relative_coordinate (commony, Y_AXIS); + Interval flp ; flp.set_full (); flp[-d] = left_y; @@ -1175,8 +1204,8 @@ Beam::check_concave (SCM smob) { Grob *me = unsmob_grob (smob); - Link_array stems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); + Link_array stems = + Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems"); for (int i = 0; i < stems.size ();) { @@ -1309,10 +1338,15 @@ Beam::slope_damping (SCM smob) { Interval pos = ly_scm2interval (me->get_grob_property ("positions")); Real dy = pos.delta (); - - // ugh -> use commonx - Real dx = last_visible_stem (me)->relative_coordinate (0, X_AXIS) - - first_visible_stem (me)->relative_coordinate (0, X_AXIS); + + Grob *fvs = first_visible_stem (me); + Grob *lvs = last_visible_stem (me); + + Grob *commonx = fvs->common_refpoint (lvs, X_AXIS); + + + Real dx = last_visible_stem (me)->relative_coordinate (commonx, X_AXIS) + - first_visible_stem (me)->relative_coordinate (commonx, X_AXIS); Real dydx = dy && dx ? dy/dx : 0; dydx = 0.6 * tanh (dydx) / damping; @@ -1345,9 +1379,8 @@ where_are_the_whole_beams(SCM beaming) in POS, and for stem S. */ Real -Beam::calc_stem_y (Grob *me, Grob* s, Interval pos, bool french) +Beam::calc_stem_y (Grob *me, Grob* s, Grob * common_y, Interval pos, bool french) { - Real thick = gh_scm2double (me->get_grob_property ("thickness")); Real beam_space = get_beam_space (me); // ugh -> use commonx @@ -1381,8 +1414,11 @@ Beam::calc_stem_y (Grob *me, Grob* s, Interval pos, bool french) if (!bm.empty_b()) stem_y +=bm[my_dir] * beam_space; } - - return stem_y; + + Real id = me->relative_coordinate (common_y, Y_AXIS) + - s->relative_coordinate (common_y, Y_AXIS); + + return stem_y + id; } /* @@ -1392,17 +1428,13 @@ Beam::calc_stem_y (Grob *me, Grob* s, Interval pos, bool french) void Beam::set_stem_lengths (Grob *me) { - Link_array stems= - Pointer_group_interface__extract_grobs (me, (Item*)0, "stems"); + Link_array stems= + Pointer_group_interface__extract_grobs (me, (Grob*)0, "stems"); if (stems.size () <= 1) return; - Grob *common = me->common_refpoint (stems[0], Y_AXIS); - for (int i=1; i < stems.size (); i++) - if (!Stem::invisible_b (stems[i])) - common = common->common_refpoint (stems[i], Y_AXIS); - + Grob *common = common_refpoint_of_array (stems, me, Y_AXIS); Interval pos = ly_scm2interval (me->get_grob_property ("positions")); Real staff_space = Staff_symbol_referencer::staff_space (me); @@ -1410,16 +1442,13 @@ Beam::set_stem_lengths (Grob *me) for (int i=0; i < stems.size (); i++) { - Item* s = stems[i]; + Grob* s = stems[i]; if (Stem::invisible_b (s)) continue; - Real stem_y = calc_stem_y (me, s, pos, french && i > 0&& (i < stems.size () -1)); + Real stem_y = calc_stem_y (me, s, common , pos, french && i > 0&& (i < stems.size () -1)); - /* caution: stem measures in staff-positions */ - Real id = me->relative_coordinate (common, Y_AXIS) - - stems[i]->relative_coordinate (common, Y_AXIS); - Stem::set_stemend (s, (stem_y + id) / staff_space * 2); + Stem::set_stemend (s, 2* stem_y / staff_space); } } @@ -1459,12 +1488,12 @@ Beam::set_beaming (Grob *me, Beaming_info_list *beaming) int Beam::forced_stem_count (Grob *me) { - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); + Link_arraystems = + Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems"); int f = 0; for (int i=0; i < stems.size (); i++) { - Item *s = stems[i]; + Grob *s = stems[i]; if (Stem::invisible_b (s)) continue; @@ -1482,8 +1511,8 @@ Beam::forced_stem_count (Grob *me) int Beam::visible_stem_count (Grob *me) { - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); + Link_arraystems = + Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems"); int c = 0; for (int i = stems.size (); i--;) { @@ -1493,11 +1522,11 @@ Beam::visible_stem_count (Grob *me) return c; } -Item* +Grob* Beam::first_visible_stem (Grob *me) { - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); + Link_arraystems = + Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems"); for (int i = 0; i < stems.size (); i++) { @@ -1507,11 +1536,11 @@ Beam::first_visible_stem (Grob *me) return 0; } -Item* +Grob* Beam::last_visible_stem (Grob *me) { - Link_arraystems = - Pointer_group_interface__extract_grobs (me, (Item*) 0, "stems"); + Link_arraystems = + Pointer_group_interface__extract_grobs (me, (Grob*) 0, "stems"); for (int i = stems.size (); i--;) { if (!Stem::invisible_b (stems[i])) diff --git a/lily/include/beam.hh b/lily/include/beam.hh index 02a4556b91..2816f7abfc 100644 --- a/lily/include/beam.hh +++ b/lily/include/beam.hh @@ -16,8 +16,8 @@ class Beam { public: static int visible_stem_count (Grob*); - static Item* first_visible_stem (Grob*); - static Item* last_visible_stem (Grob*); + static Grob* first_visible_stem (Grob*); + static Grob* last_visible_stem (Grob*); static bool has_interface (Grob*); DECLARE_SCHEME_CALLBACK (rest_collision_callback, (SCM element, SCM axis)); Beam (SCM); @@ -38,7 +38,7 @@ public: DECLARE_SCHEME_CALLBACK (slope_damping, (SCM)); DECLARE_SCHEME_CALLBACK (shift_region_to_valid, (SCM)); DECLARE_SCHEME_CALLBACK (quanting, (SCM)); - static Real score_slopes_dy (Grob*, Real,Real,Real,Real); + static Real score_slopes_dy (Grob*, Real,Real,Real,Real, bool); static Real score_stem_lengths (Link_array, Array, Array, Array, @@ -53,7 +53,7 @@ private: static void set_stem_directions (Grob*, Direction ); static void consider_auto_knees (Grob*, Direction d); static void set_stem_shorten (Grob*); - static Real calc_stem_y (Grob*, Grob* s, Interval pos, bool french); + static Real calc_stem_y (Grob*, Grob* s, Grob*c, Interval pos, bool french); static void set_stem_lengths (Grob*); static int forced_stem_count (Grob*); }; diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index d2378d0d70..b3f76b243d 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -199,15 +199,16 @@ PianoStaffContext = \translator{ \name "PianoStaff" \alias "GrandStaff" + verticalAlignmentChildCallback = #Align_interface::fixed_distance_alignment_callback + VerticalAlignment \override #'forced-distance = #12 + VerticalAlignment \override #'self-alignment-Y = #0 + \consists "Vertical_align_engraver" \consists "Instrument_name_engraver" instrument = #'() instr = #'() - verticalAlignmentChildCallback = #Align_interface::fixed_distance_alignment_callback - VerticalAlignment \override #'forced-distance = #12 - VerticalAlignment \override #'self-alignment-Y = #0 % \consistsend "Axis_group_engraver" } diff --git a/scm/grob-description.scm b/scm/grob-description.scm index a7ed6b3309..6b9bf94cdc 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -132,7 +132,7 @@ ,Beam::check_concave ,Beam::slope_damping ,Beam::shift_region_to_valid - ,Beam::quanting +; ,Beam::quanting )) ;; TODO: should be in SLT. @@ -147,7 +147,6 @@ (flag-width-function . ,default-beam-flag-width-function) (damping . 1) (auto-knee-gap . 7) - (font-name . "cmr10") (space-function . ,Beam::space_function) (meta . ((interfaces . (staff-symbol-referencer-interface beam-interface spanner-interface)))) -- 2.39.5