From 1edd073d300fee9f1280e020227bb5820f37bc20 Mon Sep 17 00:00:00 2001 From: Keith OHara Date: Mon, 25 Apr 2011 14:20:20 -0700 Subject: [PATCH] lily/rest-collision.cc: adjust all rests in column Process all rests in a noteColumn, not just the first; fix issue 1618. Print warning only for rests that are moved but don't fit; fix issue 1547. --- input/regression/rest-polyphonic-2.ly | 19 ++++ lily/rest-collision.cc | 129 +++++++++++++------------- 2 files changed, 85 insertions(+), 63 deletions(-) create mode 100644 input/regression/rest-polyphonic-2.ly diff --git a/input/regression/rest-polyphonic-2.ly b/input/regression/rest-polyphonic-2.ly new file mode 100644 index 0000000000..2d3d00b6ed --- /dev/null +++ b/input/regression/rest-polyphonic-2.ly @@ -0,0 +1,19 @@ +\header { + + texidoc = "Rests avoid notes. Each rest is moved in the direction +of the stems in its voice. Rests may overlap other rests in voices +with the same stem direction, in which case a warning is given, but +is supressed if the rest has a pitch." + +} + +\version "2.15.0" + +\new Staff << + \relative c''' { g8 g g r r2 } \\ + \relative c' { a4\rest c r2 } \\ + \relative c'' { c4 c r2 } \\ + \relative c'' { r2 g } +>> + + diff --git a/lily/rest-collision.cc b/lily/rest-collision.cc index b507062aa0..8be91e3f23 100644 --- a/lily/rest-collision.cc +++ b/lily/rest-collision.cc @@ -201,83 +201,86 @@ Rest_collision::calc_positioning_done (SCM smob) /* Rests and notes. */ - if (rests.size () > 1) - warning (_ ("too many colliding rests")); - Grob *rcol = 0; - Direction dir = CENTER; + // Count how many rests we move + Drul_array rcount (0, 0); - for (vsize i = rests.size (); !rcol && i--;) - if (Note_column::dir (rests[i])) - { - rcol = rests[i]; - dir = Note_column::dir (rcol); - } - - if (!rcol) - return SCM_BOOL_T; - - Grob *rest = Note_column::get_rest (rcol); - Grob *common = common_refpoint_of_array (notes, rcol, Y_AXIS); - - Interval restdim = rest->extent (common, Y_AXIS); - if (restdim.is_empty ()) - return SCM_BOOL_T; - - Real staff_space = Staff_symbol_referencer::staff_space (rcol); - Real minimum_dist = robust_scm2double (me->get_property ("minimum-distance"), 1.0) * staff_space; - - Interval notedim; - for (vsize i = 0; i < notes.size (); i++) + for (vsize i = 0; i < rests.size (); i++) { - if (Note_column::dir (notes[i]) == -dir - // If the note has already happened (but it has a long duration, so there is a collision), - // don't look at the stem. If we do, the rest gets shifted down a lot and it looks bad. - || dynamic_cast (notes[i])->get_column () != dynamic_cast (rest)->get_column ()) + Grob *rcol = rests[i]; + Direction dir = Note_column::dir (rcol); + if (!dir) + continue; + + Grob *rest = Note_column::get_rest (rcol); + // Do not compute a translation for pre-positioned rests, + // nor count them for the "too many colliding rests" warning + if (scm_is_number (rest->get_property ("staff-position"))) + continue; + + Grob *common = common_refpoint_of_array (notes, rcol, Y_AXIS); + Interval restdim = rest->extent (common, Y_AXIS); + if (restdim.is_empty ()) + continue; + + Real staff_space = Staff_symbol_referencer::staff_space (rcol); + Real minimum_dist = robust_scm2double (me->get_property ("minimum-distance"), 1.0) * staff_space; + + Interval notedim; + for (vsize i = 0; i < notes.size (); i++) { - /* try not to look at the stem, as looking at a beamed - note may trigger beam positioning prematurely. - - This happens with dotted rests, which need Y - positioning to compute X-positioning. - */ - Grob *head = Note_column::first_head (notes[i]); - if (head) - notedim.unite (head->extent (common, Y_AXIS)); + if (Note_column::dir (notes[i]) == -dir + // If the note has already happened (but it has a long + // duration, so there is a collision), don't look at the stem. + // If we do, the rest gets shifted down a lot and it looks bad. + || dynamic_cast (notes[i])->get_column () != dynamic_cast (rest)->get_column ()) + { + /* try not to look at the stem, as looking at a beamed + note may trigger beam positioning prematurely. + + This happens with dotted rests, which need Y + positioning to compute X-positioning. + */ + Grob *head = Note_column::first_head (notes[i]); + if (head) + notedim.unite (head->extent (common, Y_AXIS)); + else + programming_error ("Note_column without first_head()"); + } else - programming_error ("Note_column without first_head()"); + notedim.unite (notes[i]->extent (common, Y_AXIS)); } - else - notedim.unite (notes[i]->extent (common, Y_AXIS)); - } - Real y = dir * max (0.0, - -dir * restdim[-dir] + dir * notedim[dir] + minimum_dist); - - int stafflines = Staff_symbol_referencer::line_count (me); - if (!stafflines) - { - programming_error ("no staff line count"); - stafflines = 5; - } + Real y = dir * max (0.0, + -dir * restdim[-dir] + dir * notedim[dir] + minimum_dist); - // move discretely by half spaces. - int discrete_y = dir * int (ceil (y / (0.5 * dir * staff_space))); + int stafflines = Staff_symbol_referencer::line_count (me); + if (!stafflines) + { + programming_error ("no staff line count"); + stafflines = 5; + } - // move by whole spaces inside the staff. - if (fabs (Staff_symbol_referencer::get_position (rest) - + discrete_y) < stafflines + 1) - { - discrete_y = dir * int (ceil (dir * discrete_y / 2.0) * 2.0); - } + // move discretely by half spaces. + int discrete_y = dir * int (ceil (y / (0.5 * dir * staff_space))); - Rest::translate (rest, discrete_y); + // move by whole spaces inside the staff. + if (fabs (Staff_symbol_referencer::get_position (rest) + + discrete_y) < stafflines + 1) + { + discrete_y = dir * int (ceil (dir * discrete_y / 2.0) * 2.0); + } + + Rest::translate (rest, discrete_y); + if (rcount[dir]++) + rest->warning (_ ("too many colliding rests")); + } } return SCM_BOOL_T; } ADD_INTERFACE (Rest_collision, - "Move around ordinary rests (not multi-measure-rests) to avoid" - " conflicts.", + "Move ordinary rests (not multi-measure nor pitched rests)" + " to avoid conflicts.", /* properties */ "minimum-distance " -- 2.39.2