]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/axis-group-interface.cc
Use object callbacks for pure-height caching.
[lilypond.git] / lily / axis-group-interface.cc
index 4ce0a01a65918d486bb1d7be9dca9603eb8ef9be..578549a3d4abc10cfd2027708167b58bdfcbb3c2 100644 (file)
@@ -1,9 +1,20 @@
 /*
-  axis-group-interface.cc -- implement Axis_group_interface
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
+  Copyright (C) 2000--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
-  (c) 2000--2009 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
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "axis-group-interface.hh"
@@ -77,6 +88,15 @@ Axis_group_interface::relative_group_extent (vector<Grob*> const &elts,
 
 Interval
 Axis_group_interface::cached_pure_height (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));
+
+  return iv;
+}
+
+Interval
+Axis_group_interface::rest_of_line_pure_height (Grob *me, int start, int end)
 {
   SCM adjacent_pure_heights = me->get_property ("adjacent-pure-heights");
 
@@ -133,7 +153,7 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
 {
   Grob *me = unsmob_grob (smob);
 
-  Grob *common = calc_pure_elts_and_common (me);
+  Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
   extract_grob_set (me, "pure-relevant-items", items);
   extract_grob_set (me, "pure-relevant-spanners", spanners);
 
@@ -149,6 +169,7 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
     {
       int start = Paper_column::get_rank (cols[breaks[i]]);
       int end = Paper_column::get_rank (cols[breaks[i+1]]);
+
       Interval begin_line_iv;
       Interval mid_line_iv;
 
@@ -208,7 +229,7 @@ Axis_group_interface::relative_pure_height (Grob *me, int start, int end)
   if (p && Align_interface::has_interface (p))
     return Axis_group_interface::cached_pure_height (me, start, end);
 
-  Grob *common = calc_pure_elts_and_common (me);
+  Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
   extract_grob_set (me, "pure-relevant-items", items);
   extract_grob_set (me, "pure-relevant-spanners", spanners);
 
@@ -360,56 +381,94 @@ Axis_group_interface::staff_extent (Grob *me, Grob *refp, Axis ext_a, Grob *staf
 }
 
 
-Grob *
-Axis_group_interface::calc_pure_elts_and_common (Grob *me)
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_relevant_grobs, 1);
+SCM
+Axis_group_interface::calc_pure_relevant_grobs (SCM smob)
 {
-  if (Grob *c = unsmob_grob (me->get_object ("pure-Y-common")))
-    return c;
+  Grob *me = unsmob_grob (smob);
   
   extract_grob_set (me, "elements", elts);
 
-  vector<Grob*> relevant_items;
-  vector<Grob*> relevant_spanners;
+  vector<Grob*> relevant_grobs;
   SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?");
 
   for (vsize i = 0; i < elts.size (); i++)
     {
       if (to_boolean (scm_apply_1 (pure_relevant_p, elts[i]->self_scm (), SCM_EOL)))
+       relevant_grobs.push_back (elts[i]);
+
+      if (Item *it = dynamic_cast<Item*> (elts[i]))
        {
-         if (dynamic_cast<Item*> (elts[i]))
-           relevant_items.push_back (elts[i]);
-         else if (dynamic_cast<Spanner*> (elts[i]))
-           relevant_spanners.push_back (elts[i]);
+         Direction d = LEFT;
+         do
+           {
+             Item *piece = it->find_prebroken_piece (d);
+             if (piece && to_boolean (scm_apply_1 (pure_relevant_p, piece->self_scm (), SCM_EOL)))
+               relevant_grobs.push_back (piece);
+           }
+         while (flip (&d) != LEFT);
        }
-           
-
-      Item *it = dynamic_cast<Item*> (elts[i]);
-      Direction d = LEFT;
-      if (it)
-       do
-         {
-           Item *piece = it->find_prebroken_piece (d);
-           if (piece && to_boolean (scm_apply_1 (pure_relevant_p, piece->self_scm (), SCM_EOL)))
-             relevant_items.push_back (piece);
-         }
-       while (flip (&d) != LEFT);
     }
-  vector_sort (relevant_items, Item::less);
 
-  Grob *common = common_refpoint_of_array (relevant_items, me, Y_AXIS);
-  common = common_refpoint_of_array (relevant_spanners, common, Y_AXIS);
+  SCM grobs_scm = Grob_array::make_array ();
+  unsmob_grob_array (grobs_scm)->set_array (relevant_grobs);
 
-  me->set_object ("pure-Y-common", common->self_scm ());
-  
-  SCM items_scm = Grob_array::make_array ();
-  SCM spanners_scm = Grob_array::make_array ();
+  return grobs_scm;
+}
+
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_relevant_items, 1);
+SCM
+Axis_group_interface::calc_pure_relevant_items (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+
+  extract_grob_set (me, "pure-relevant-grobs", elts);
+
+  vector<Grob*> relevant_items;
+  for (vsize i = 0; i < elts.size (); i++)
+    if (Item *it = dynamic_cast<Item*> (elts[i]))
+      relevant_items.push_back (it);
+
+  vector_sort (relevant_items, Item::less);
 
+  SCM items_scm = Grob_array::make_array ();
   unsmob_grob_array (items_scm)->set_array (relevant_items);
+  return items_scm;
+}
+
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_relevant_spanners, 1);
+SCM
+Axis_group_interface::calc_pure_relevant_spanners (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+
+  extract_grob_set (me, "pure-relevant-grobs", elts);
+
+  vector<Grob*> relevant_spanners;
+  for (vsize i = 0; i < elts.size (); i++)
+    if (dynamic_cast<Spanner*> (elts[i]))
+      relevant_spanners.push_back (elts[i]);
+
+  SCM spanners_scm = Grob_array::make_array ();
   unsmob_grob_array (spanners_scm)->set_array (relevant_spanners);
-  me->set_object ("pure-relevant-items", items_scm);
-  me->set_object ("pure-relevant-spanners", spanners_scm);
+  return spanners_scm;
+}
+
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_y_common, 1);
+SCM
+Axis_group_interface::calc_pure_y_common (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
 
-  return common;
+  extract_grob_set (me, "pure-relevant-grobs", elts);
+  Grob *common = common_refpoint_of_array (elts, me, Y_AXIS);
+  if (!common)
+    {
+      me->programming_error ("No common parent found in calc_pure_y_common.");
+      return SCM_EOL;
+    }
+
+  return common->self_scm ();
 }
 
 SCM
@@ -422,7 +481,7 @@ Axis_group_interface::calc_common (Grob *me, Axis axis)
       me->programming_error ("No common parent found in calc_common axis.");
       return SCM_EOL;
     }
-  
+
   return common->self_scm ();
 }
 
@@ -444,8 +503,13 @@ Axis_group_interface::calc_y_common (SCM grob)
 Interval
 Axis_group_interface::pure_group_height (Grob *me, int start, int end)
 {
-  Grob *common = calc_pure_elts_and_common (me);
-       
+  Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
+
+  if (!common)
+    {
+      programming_error ("no pure Y common refpoint");
+      return Interval ();
+    }
   Real my_coord = me->relative_coordinate (common, Y_AXIS);
   Interval r (relative_pure_height (me, start, end));
 
@@ -673,22 +737,52 @@ Axis_group_interface::print (SCM smob)
   return ret.smobbed_copy ();
 }
 
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_next_staff_spacing, 3)
+SCM
+Axis_group_interface::calc_pure_next_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));
+}
+
 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_next_staff_spacing, 1)
 SCM
 Axis_group_interface::calc_next_staff_spacing (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  return calc_maybe_pure_next_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)
+{
   Grob *grouper = unsmob_grob (me->get_object ("staff-grouper"));
 
   if (grouper)
     {
-      Grob *last_in_group = Staff_grouper_interface::get_last_grob (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_property ("after-last-staff-spacing");
+       return grouper->get_maybe_pure_property ("after-last-staff-spacing", pure, start, end);
       else
-       return grouper->get_property ("between-staff-spacing");
+       return grouper->get_maybe_pure_property ("between-staff-spacing", pure, start, end);
     }
-  return me->get_property ("default-next-staff-spacing");
+  return me->get_maybe_pure_property ("default-next-staff-spacing", pure, start, end);
+}
+
+Real
+Axis_group_interface::minimum_distance (Grob *g1, Grob *g2, Axis a)
+{
+  SCM sym = ly_symbol2scm ((a == Y_AXIS) ? "vertical-skylines" : "horizontal-skylines");
+
+  Skyline_pair *s1 = Skyline_pair::unsmob (g1->get_property (sym));
+  Skyline_pair *s2 = Skyline_pair::unsmob (g2->get_property (sym));
+  if (s1 && s2)
+    return (*s1)[DOWN].distance ((*s2)[UP]);
+  return 0;
 }
 
 ADD_INTERFACE (Axis_group_interface,
@@ -708,12 +802,15 @@ ADD_INTERFACE (Axis_group_interface,
               "inter-staff-spacing "
               "keep-fixed-while-stretching "
               "max-stretch "
+              "non-affinity-spacing "
               "next-staff-spacing "
               "no-alignment "
               "pure-Y-common "
+              "pure-relevant-grobs "
               "pure-relevant-items "
               "pure-relevant-spanners "
               "staff-affinity "
               "staff-grouper "
+              "system-Y-offset "
               "vertical-skylines "
               );