]> git.donarmstrong.com Git - lilypond.git/commitdiff
pure-rest-collision-callback: Remain on staff lines; issue 2468
authorKeith OHara <k-ohara5a5a@oco.net>
Sun, 22 Apr 2012 06:57:23 +0000 (23:57 -0700)
committerKeith OHara <k-ohara5a5a@oco.net>
Wed, 2 May 2012 04:41:04 +0000 (21:41 -0700)
Same as f5abf75fb0a62527ea1c6339861aee34b210cc24, but with correct
argument-passing order.

input/regression/dot-column-rest-collision.ly
lily/beam.cc
lily/include/beam.hh

index 3419f7304fa7f56dc60411c884d1e7381edf6793..49f811ce371cf222e2440e6de48b6082e5189f7e 100644 (file)
@@ -1,10 +1,12 @@
 \header {
-  texidoc = "Dot columns do not trigger beam slanting too early."
+  texidoc = "Dot columns do not trigger beam slanting too early.
+This input should compile with no programming error message,
+and the dots should be correctly placed on their rests."
 }
 
 \version "2.14.0"
 \paper{ ragged-right=##t }
 <<
-  { e''8 e''8 g'' g''} \\
-  { e8 r4. }
+  { e''8 e'' g'' g'' g''16[ r8. r8. g''16] } \\
+  { e8 r4. c'16[ r8. <a' b' c''>8. e'16] }
 >>
index e2d12931875f1118989dd0fd9024b85965f82c84..49253434c05d94faab4e471b44cc42898841f1e9 100644 (file)
@@ -1289,36 +1289,39 @@ Beam::rest_collision_callback (SCM smob, SCM prev_offset)
   return scm_from_double (offset + staff_space * shift);
 }
 
+/*
+  Estimate the position of a rest under a beam,
+  as the average position of its neighboring heads.
+*/
 MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Beam, pure_rest_collision_callback, 4, 1, "");
 SCM
 Beam::pure_rest_collision_callback (SCM smob,
-                                    SCM, /* prev_offset */
                                     SCM, /* start */
-                                    SCM /* end */)
+                                    SCM, /* end */
+                                    SCM prev_offset)
 {
-  Real amount = 0.0;
+  Real previous = robust_scm2double (prev_offset, 0.0);
 
   Grob *me = unsmob_grob (smob);
   Grob *stem = unsmob_grob (me->get_object ("stem"));
   if (!stem)
-    return scm_from_double (amount);
+    return scm_from_double (previous);
   Grob *beam = unsmob_grob (stem->get_object ("beam"));
   if (!beam
       || !Beam::normal_stem_count (beam)
       || !is_direction (beam->get_property_data ("direction")))
-    return scm_from_double (amount);
+    return scm_from_double (previous);
 
   Real ss = Staff_symbol_referencer::staff_space (me);
 
   /*
     This gives the extrema of rest positions.
-    In general, beams are never typeset more than one staff space away
-    from the staff in either direction.
+    Even with noteheads on ledgers, beams typically remain within the staff,
+    and push rests at most one staff-space (2 positions) from the staff.
   */
   Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
   Interval rest_max_pos = staff ? Staff_symbol::line_span (staff) : Interval (0.0, 0.0);
-  rest_max_pos.widen (1);
-  rest_max_pos *= ss / 2;
+  rest_max_pos.widen (2);
 
   extract_grob_set (beam, "stems", stems);
   vector<Grob *> my_stems;
@@ -1339,7 +1342,7 @@ Beam::pure_rest_collision_callback (SCM smob,
   Grob *right;
 
   if (idx == (vsize) - 1 || my_stems.size () == 1)
-    return scm_from_double (amount);
+    return scm_from_double (previous);
   else if (idx == 0)
     left = right = my_stems[1];
   else if (idx == my_stems.size () - 1)
@@ -1349,15 +1352,19 @@ Beam::pure_rest_collision_callback (SCM smob,
       left = my_stems[idx - 1];
       right = my_stems[idx + 1];
     }
-  Direction beamdir = get_grob_direction (beam);
-  /*
-    Take the position between the two bounding head_positions,
-    then bound it by the minimum and maximum positions outside the staff.
-    4.0 = 2.0 to get out of staff space * 2.0 for the average
-  */
-  amount = min (max ((Stem::head_positions (left)[beamdir] + Stem::head_positions (right)[beamdir]) / 4.0, rest_max_pos[DOWN]), rest_max_pos[UP]);
 
-  return scm_from_double (amount);
+  /* In stems with several heads, use the one closest to the beam. */
+  Direction beamdir = get_grob_direction (beam);
+  Real shift = min (max ( (Stem::head_positions (left)[beamdir]
+                           + Stem::head_positions (right)[beamdir]) / 2.0,
+                          rest_max_pos[DOWN]),
+                    rest_max_pos[UP]
+                   ) * ss / 2.0
+               - previous;
+  /* Always move by a whole number of staff spaces */
+  shift = ceil (fabs (shift / ss)) * ss * sign (shift);
+
+  return scm_from_double (previous + shift);
 }
 
 bool
index 5c60e14c8076e9fa6ca49011139a2e316ec21d67..116ae6aa5730a72ad616594c69bc89bb34991672 100644 (file)
@@ -70,7 +70,7 @@ public:
   static vector<Beam_segment> get_beam_segments (Grob *me_grob, Grob **common);
 
   DECLARE_SCHEME_CALLBACK (rest_collision_callback, (SCM element, SCM prev_off));
-  DECLARE_SCHEME_CALLBACK (pure_rest_collision_callback, (SCM element, SCM prev_off, SCM, SCM));
+  DECLARE_SCHEME_CALLBACK (pure_rest_collision_callback, (SCM element, SCM, SCM, SCM prev_off));
   DECLARE_SCHEME_CALLBACK (print, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_beaming, (SCM));
   DECLARE_SCHEME_CALLBACK (calc_stem_shorten, (SCM));