]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/axis-group-interface.cc
Change the behavior of nested StaffGroupers.
[lilypond.git] / lily / axis-group-interface.cc
index 1ec518feff52bd95ed7ac0a7d5e86590539291d0..0b399fd2482e5fa8ef9da603a416471dd9281ac8 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 2000--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 2000--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
   LilyPond is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -90,7 +90,7 @@ Axis_group_interface::relative_group_extent (vector<Grob*> const &elts,
 }
 
 Interval
-Axis_group_interface::cached_pure_height (Grob *me, int start, int end)
+Axis_group_interface::sum_partial_pure_heights (Grob *me, int start, int end)
 {
   Interval iv = begin_of_line_pure_height (me, start);
   iv.unite (rest_of_line_pure_height (me, start, end));
@@ -99,27 +99,47 @@ Axis_group_interface::cached_pure_height (Grob *me, int start, int end)
 }
 
 Interval
-Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end)
+Axis_group_interface::part_of_line_pure_height (Grob *me, bool begin, int start, int end)
 {
+  Spanner *sp = dynamic_cast<Spanner*> (me);
+  SCM cache_symbol = begin
+    ? ly_symbol2scm ("begin-of-line-pure-height")
+    : ly_symbol2scm ("rest-of-line-pure-height");
+  SCM cached = sp->get_cached_pure_property (cache_symbol, start, end);
+  if (scm_is_pair (cached))
+    return robust_scm2interval (cached, Interval (0, 0));
+
   SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights");
+  Interval ret;
 
-  if (!scm_is_pair (adjacent_pure_heights)
-      || !scm_is_vector (scm_cdr (adjacent_pure_heights)))
-    return Interval (0, 0);
+  if (!scm_is_pair (adjacent_pure_heights))
+    ret = Interval (0, 0);
+  else
+    {
+      SCM these_pure_heights = begin
+       ? scm_car (adjacent_pure_heights)
+       : scm_cdr (adjacent_pure_heights);
 
-  return combine_pure_heights (me, scm_cdr (adjacent_pure_heights), start, end);
+      if (scm_is_vector (these_pure_heights))
+       ret = combine_pure_heights (me, these_pure_heights, start, end);
+      else
+       ret = Interval (0, 0);
+    }
+
+  sp->cache_pure_property (cache_symbol, start, end, ly_interval2scm (ret));
+  return ret;
 }
 
 Interval
 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 part_of_line_pure_height (me, true, start, start + 1);
+}
 
-  return combine_pure_heights (me, scm_car (adjacent_pure_heights), start, start+1);
+Interval
+Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end)
+{
+  return part_of_line_pure_height (me, false, start, end);
 }
 
 Interval
@@ -143,14 +163,12 @@ Axis_group_interface::combine_pure_heights (Grob *me, SCM measure_extents, int s
   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)
@@ -165,6 +183,8 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
 
   vector<Interval> begin_line_heights;
   vector<Interval> mid_line_heights;
+  vector<Interval> begin_line_staff_heights;
+  vector<Interval> mid_line_staff_heights;
   begin_line_heights.resize (ranks.size () - 1);
   mid_line_heights.resize (ranks.size () - 1);
 
@@ -178,6 +198,18 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
       bool outside_staff = scm_is_number (g->get_property ("outside-staff-priority"));
       Real padding = robust_scm2double (g->get_property ("outside-staff-padding"), 0.5);
 
+      // When we encounter the first outside-staff grob, make a copy
+      // of the current heights to use as an estimate for the staff heights.
+      // Note that the outside-staff approximation that we use here doesn't
+      // consider any collisions that might occur between outside-staff grobs,
+      // but only the fact that outside-staff grobs may need to be raised above
+      // the staff.
+      if (outside_staff && begin_line_staff_heights.empty ())
+       {
+         begin_line_staff_heights = begin_line_heights;
+         mid_line_staff_heights = mid_line_heights;
+       }
+
       // TODO: consider a pure version of get_grob_direction?
       Direction d = to_dir (g->get_property_data ("direction"));
       d = (d == CENTER) ? UP : d;
@@ -205,14 +237,16 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
                  if (rank_span[LEFT] <= start)
                    {
                      if (outside_staff)
-                       begin_line_heights[j].unite_disjoint (dims, padding, d);
+                       begin_line_heights[j].unite (
+                           begin_line_staff_heights[j].union_disjoint (dims, padding, d));
                      else
                        begin_line_heights[j].unite (dims);
                    }
                   if (rank_span[RIGHT] > start)
                    {
                      if (outside_staff)
-                       mid_line_heights[j].unite_disjoint (dims, padding, d);
+                       mid_line_heights[j].unite (
+                            mid_line_staff_heights[j].union_disjoint (dims, padding, d));
                      else
                        mid_line_heights[j].unite (dims);
                    }
@@ -246,7 +280,7 @@ Axis_group_interface::relative_pure_height (Grob *me, int start, int end)
      we can assume additivity and cache things nicely. */
   Grob *p = me->get_parent (Y_AXIS);
   if (p && Align_interface::has_interface (p))
-    return Axis_group_interface::cached_pure_height (me, start, end);
+    return Axis_group_interface::sum_partial_pure_heights (me, start, end);
 
   Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
   extract_grob_set (me, "pure-relevant-grobs", elts);
@@ -350,7 +384,7 @@ Axis_group_interface::combine_skylines (SCM smob)
     }
   return ret.smobbed_copy ();
 }
-  
+
 SCM
 Axis_group_interface::generic_group_extent (Grob *me, Axis a)
 {
@@ -389,7 +423,7 @@ SCM
 Axis_group_interface::calc_pure_relevant_grobs (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
-  
+
   extract_grob_set (me, "elements", elts);
 
   vector<Grob*> relevant_grobs;
@@ -679,7 +713,7 @@ Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements)
       SCM priority = elements[i]->get_property ("outside-staff-priority");
       vector<Grob*> current_elts;
       current_elts.push_back (elements[i]);
-      while (i + 1 < elements.size () 
+      while (i + 1 < elements.size ()
             && scm_eq_p (elements[i+1]->get_property ("outside-staff-priority"), priority))
        {
          if (!to_boolean (elements[i+1]->get_property ("cross-staff")))
@@ -712,40 +746,40 @@ Axis_group_interface::print (SCM smob)
   return ret.smobbed_copy ();
 }
 
-MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_next_staff_spacing, 3)
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_staff_staff_spacing, 3)
 SCM
-Axis_group_interface::calc_pure_next_staff_spacing (SCM smob, SCM start, SCM end)
+Axis_group_interface::calc_pure_staff_staff_spacing (SCM smob, SCM start, SCM end)
 {
-  return calc_maybe_pure_next_staff_spacing (unsmob_grob (smob),
-                                            true,
-                                            scm_to_int (start),
-                                            scm_to_int (end));
+  return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob),
+                                             true,
+                                             scm_to_int (start),
+                                             scm_to_int (end));
 }
 
-MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_next_staff_spacing, 1)
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_staff_staff_spacing, 1)
 SCM
-Axis_group_interface::calc_next_staff_spacing (SCM smob)
+Axis_group_interface::calc_staff_staff_spacing (SCM smob)
 {
-  return calc_maybe_pure_next_staff_spacing (unsmob_grob (smob),
-                                            false,
-                                            0,
-                                            INT_MAX);
+  return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob),
+                                             false,
+                                             0,
+                                             INT_MAX);
 }
 
 SCM
-Axis_group_interface::calc_maybe_pure_next_staff_spacing (Grob *me, bool pure, int start, int end)
+Axis_group_interface::calc_maybe_pure_staff_staff_spacing (Grob *me, bool pure, int start, int end)
 {
   Grob *grouper = unsmob_grob (me->get_object ("staff-grouper"));
 
   if (grouper)
     {
-      Grob *last_in_group = Staff_grouper_interface::get_maybe_pure_last_grob (grouper, pure, start, end);
-      if (me == last_in_group)
-       return grouper->get_maybe_pure_property ("after-last-staff-spacing", pure, start, end);
+      bool within_group = Staff_grouper_interface::maybe_pure_within_group (grouper, me, pure, start, end);
+      if (within_group)
+       return grouper->get_maybe_pure_property ("staff-staff-spacing", pure, start, end);
       else
-       return grouper->get_maybe_pure_property ("between-staff-spacing", pure, start, end);
+       return grouper->get_maybe_pure_property ("staffgroup-staff-spacing", pure, start, end);
     }
-  return me->get_maybe_pure_property ("default-next-staff-spacing", pure, start, end);
+  return me->get_maybe_pure_property ("default-staff-staff-spacing", pure, start, end);
 }
 
 Real
@@ -767,24 +801,24 @@ ADD_INTERFACE (Axis_group_interface,
               // VerticalAxisGroup. We should split off a
               // vertical-axis-group-interface.
               /* properties */
-              "X-common "
-              "Y-common "
               "adjacent-pure-heights "
               "axes "
-              "default-next-staff-spacing "
+              "default-staff-staff-spacing "
               "elements "
-              "inter-loose-line-spacing "
-              "inter-staff-spacing "
               "max-stretch "
-              "non-affinity-spacing "
-              "next-staff-spacing "
               "no-alignment "
-              "pure-Y-common "
+              "nonstaff-nonstaff-spacing "
+              "nonstaff-relatedstaff-spacing "
+              "nonstaff-unrelatedstaff-spacing "
               "pure-relevant-grobs "
               "pure-relevant-items "
               "pure-relevant-spanners "
+              "pure-Y-common "
               "staff-affinity "
               "staff-grouper "
+              "staff-staff-spacing "
               "system-Y-offset "
               "vertical-skylines "
+              "X-common "
+              "Y-common "
               );