]> git.donarmstrong.com Git - lilypond.git/commitdiff
Improve the accuracy of pure-heights for systems with many staves.
authorJoe Neeman <joeneeman@gmail.com>
Thu, 14 May 2009 18:37:59 +0000 (11:37 -0700)
committerJoe Neeman <joeneeman@gmail.com>
Thu, 14 May 2009 19:59:19 +0000 (12:59 -0700)
lily/align-interface.cc
lily/axis-group-interface.cc
lily/include/axis-group-interface.hh
scm/define-grob-properties.scm

index 27839aca920d46ce08dcce76b34271d064ac1168..d69930c3aa5ec715ab7bf2a42020506c966fab4b 100644 (file)
@@ -84,6 +84,8 @@ Align_interface::stretch_after_break (SCM grob)
    an empty extent, delete it from the list instead. If the extent is
    non-empty but there is no skyline available (or pure is true), just
    create a flat skyline from the bounding box */
+// TODO(jneem): the pure and non-pure parts seem to share very little
+// code. Split them into 2 functions, perhaps?
 static void
 get_skylines (Grob *me,
              vector<Grob*> *const elements,
@@ -137,9 +139,32 @@ get_skylines (Grob *me,
            {
              Box b;
              b[a] = extent;
-             b[other_axis (a)] = Interval (-infinity_f, infinity_f);
+             b[other_axis (a)] = Interval (0, infinity_f);
              skylines.insert (b, 0, other_axis (a));
            }
+
+         // This is a hack to get better accuracy on the pure-height of VerticalAlignment.
+         // It's quite common for a treble clef to be the highest element of one system
+         // and for a low note (or lyrics) to be the lowest note on another. The two will
+         // never collide, but the pure-height stuff only works with bounding boxes, so it
+         // doesn't know that. The result is a significant over-estimation of the pure-height,
+         // especially on systems with many staves. To correct for this, we build a skyline
+         // in two parts: the part we did above contains most of the grobs (note-heads, etc.)
+         // while the bit we're about to do only contains the breakable grobs at the beginning
+         // of the system. This way, the tall treble clefs are only compared with the treble
+         // clefs of the other staff and they will be ignored if the staff above is, for example,
+         // lyrics.
+         if (Axis_group_interface::has_interface (g))
+           {
+             Interval begin_of_line_extent = Axis_group_interface::begin_of_line_pure_height (g, start);
+             if (!begin_of_line_extent.is_empty ())
+               {
+                 Box b;
+                 b[a] = begin_of_line_extent;
+                 b[other_axis (a)] = Interval (-infinity_f, -1);
+                 skylines.insert (b, 0, other_axis (a));
+               }
+           }
        }
 
       if (skylines.is_empty ())
index 639c8b6267a12a6450cfe7739009e7e6b311cdbb..d14a56c08440ebdfecfff635ba1c6469272b28fc 100644 (file)
@@ -74,26 +74,37 @@ Axis_group_interface::relative_group_extent (vector<Grob*> const &elts,
   return r;
 }
 
+Interval
+Axis_group_interface::cached_pure_height (Grob *me, int start, int end)
+{
+  SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights");
 
-/*
-  FIXME: pure extent handling has a lot of ad-hoc caching.
-  This should be done with grob property callbacks.
+  if (!scm_is_pair (adjacent_pure_heights)
+      || !scm_is_vector (scm_cdr (adjacent_pure_heights)))
+    return Interval (0, 0);
 
-  --hwn
-*/
+  return combine_pure_heights (me, scm_cdr (adjacent_pure_heights), start, end);
+}
 
 Interval
-Axis_group_interface::cached_pure_height (Grob *me, int start, int end)
+Axis_group_interface::begin_of_line_pure_height (Grob *me, int start)
+{
+  SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights");
+
+  if (!scm_is_pair (adjacent_pure_heights)
+      || !scm_is_vector (scm_car (adjacent_pure_heights)))
+    return Interval (0, 0);
+
+  return combine_pure_heights (me, scm_car (adjacent_pure_heights), start, start+1);
+}
+
+Interval
+Axis_group_interface::combine_pure_heights (Grob *me, SCM measure_extents, int start, int end)
 {
   Paper_score *ps = get_root_system (me)->paper_score ();
   vector<vsize> breaks = ps->get_break_indices ();
   vector<Grob*> cols = ps->get_columns ();
 
-  SCM extents = me->get_property ("adjacent-pure-heights");
-
-  if (!scm_is_vector (extents))
-    return Interval (0, 0);
-
   Interval ext;
   for (vsize i = 0; i + 1 < breaks.size (); i++)
     {
@@ -102,12 +113,19 @@ Axis_group_interface::cached_pure_height (Grob *me, int start, int end)
        break;
 
       if (r >= start)
-       ext.unite (ly_scm2interval (scm_c_vector_ref (extents, i)));
+       ext.unite (ly_scm2interval (scm_c_vector_ref (measure_extents, i)));
     }
 
   return ext;
 }
 
+// adjacent-pure-heights is a pair of vectors, each of which has one element
+// for every measure in the score. The first vector stores, for each measure,
+// the combined height of the elements that are present only when the bar
+// is at the beginning of a line. The second vector stores, for each measure,
+// the combined height of the elements that are present only when the bar
+// is not at the beginning of a line.
+
 MAKE_SCHEME_CALLBACK (Axis_group_interface, adjacent_pure_heights, 1)
 SCM
 Axis_group_interface::adjacent_pure_heights (SCM smob)
@@ -122,13 +140,16 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
   vector<vsize> breaks = ps->get_break_indices ();
   vector<Grob*> cols = ps->get_columns ();
 
-  SCM ret = scm_c_make_vector (breaks.size () - 1, SCM_EOL);
+  SCM begin_line_heights = scm_c_make_vector (breaks.size () - 1, SCM_EOL);
+  SCM mid_line_heights = scm_c_make_vector (breaks.size () - 1, SCM_EOL);
+
   vsize it_index = 0;
   for (vsize i = 0; i + 1 < breaks.size (); i++)
     {
       int start = Paper_column::get_rank (cols[breaks[i]]);
       int end = Paper_column::get_rank (cols[breaks[i+1]]);
-      Interval iv;
+      Interval begin_line_iv;
+      Interval mid_line_iv;
 
       for (vsize j = it_index; j < items.size (); j++)
        {
@@ -139,8 +160,10 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
              && !to_boolean (it->get_property ("cross-staff")))
            {
              Interval dims = items[j]->pure_height (common, start, end);
+             Interval &target_iv = it->pure_is_visible (start-1, end) ? mid_line_iv : begin_line_iv;
+
              if (!dims.is_empty ())
-               iv.unite (dims);
+               target_iv.unite (dims);
            }
 
          if (rank < end)
@@ -156,14 +179,16 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
              && !to_boolean (spanners[j]->get_property ("cross-staff")))
            {
              Interval dims = spanners[j]->pure_height (common, start, end);
+
              if (!dims.is_empty ())
-               iv.unite (dims);
+               mid_line_iv.unite (dims);
            }
        }
 
-      scm_vector_set_x (ret, scm_from_int (i), ly_interval2scm (iv));
+      scm_vector_set_x (begin_line_heights, scm_from_int (i), ly_interval2scm (begin_line_iv));
+      scm_vector_set_x (mid_line_heights, scm_from_int (i), ly_interval2scm (mid_line_iv));
     }
-  return ret;
+  return scm_cons (begin_line_heights, mid_line_heights);
 }
 
 Interval
index 6dd2e7b95c27ae404303030e9ff2e67b4b667ee1..f852c92a34165e98bc2b59a8ad0d22b01d2f86db 100644 (file)
@@ -31,7 +31,9 @@ struct Axis_group_interface
   static Interval relative_group_extent (vector<Grob*> const &list,
                                         Grob *common, Axis);
   static Interval relative_pure_height (Grob *me, int start, int end);
+  static Interval combine_pure_heights (Grob *me, SCM, int, int);
   static Interval cached_pure_height (Grob *me, int, int);
+  static Interval begin_of_line_pure_height (Grob *me, int);
 
   static Grob *calc_pure_elts_and_common (Grob*);
   static Skyline_pair skyline_spacing (Grob *me, vector<Grob*> elements);
index 8d166a4d235e399c9c4efc6cbd4aff1c292645c8..af9aa948d0652fec53b2d0f3a59f82f68a6de476 100644 (file)
@@ -841,7 +841,7 @@ constructed from a whole number of squiggles.")
      (accidental-grob ,ly:grob? "The accidental for this note.")
      (accidental-grobs ,list? "An alist with @code{(@var{notename} .
 @var{groblist})} entries.")
-     (adjacent-pure-heights ,vector? "Used by a @code{VerticalAxisGroup} to
+     (adjacent-pure-heights ,pair? "A pair of vectors. Used by a @code{VerticalAxisGroup} to
 cache the @code{Y-extent}s of different column ranges.")
      (adjacent-hairpins ,ly:grob-array? "A list of directly neighboring
 hairpins.")