]> git.donarmstrong.com Git - lilypond.git/commitdiff
Uses only unpure-pure containers to articulate unpure-pure relationships (issue 3199)
authorMike Solomon <mike@apollinemike.com>
Tue, 5 Mar 2013 20:03:55 +0000 (21:03 +0100)
committerMike Solomon <mike@apollinemike.com>
Tue, 5 Mar 2013 20:03:55 +0000 (21:03 +0100)
Previously, LilyPond used several different lists in define-grobs.scm
to define relationships between unpure and pure functions.  This patch
eliminates these lists, using unpure-pure containers to articulate
these relationships.

The modifications required to implement this change are described below:

-) axis-group-interface.cc
A Scheme function is no longer needed to determine pure relevant grobs.
All grobs can have their Y-extents meaningfully pure-evaluated now. The
worst-case scenario is that they evaluate to false. Dead grobs, on the
other hand, are never pure relevant. The calls to is_live are the only
holdovers from the old pure-relevant? scheme function.

-) grob-closure.cc
We allow unpure-pure containers in simple closures.

-) grob-property.cc
call_pure_function no longer looks up a Scheme module. Because there are
no hard-coded lists in Scheme any more, the function is smaller and
writing it in C++ gets slight efficiency gains.

-) grob.cc
pure_stencil_height used to be a Scheme function in define-grobs.scm.
Because it is much simpler (it no longer makes references to lists defined
in Scheme), it can be implemented in C++.

-) pure-from-neighbor-engraver.cc
Similar to axis-group-interface.cc, the pure-relevant distinction is
no longer important.

-) side-position-interface.cc
In order to avoid issues with alterBroken, we only check pure properties
before line breaking.

-) simple-closure.cc
Simple closures were incorrectly evaluated when containing unpure-pure
containers. This rectifies that.

-) stencil-integral.cc
Several pure equivalent functions needed to be written for skylines.

-) define-grobs.scm
Multiple overrides must be changed to unpure-pure containers. Previous
hard-coded lists are all deleted and several functions moved to C++ (see
above).

-) output-lib.scm
Several common unpure-pure containers used in define-grobs.scm are
defined here. Several functions from define-grobs.scm pertaining to
grob offsets are moved to this file.

22 files changed:
input/regression/scheme-text-spanner.ly
lily/axis-group-interface.cc
lily/beam-engraver.cc
lily/grob-closure.cc
lily/grob-property.cc
lily/grob-scheme.cc
lily/grob.cc
lily/include/grob.hh
lily/lily-guile.cc
lily/melody-engraver.cc
lily/pure-from-neighbor-engraver.cc
lily/rest-collision.cc
lily/semi-tie-column.cc
lily/separation-item.cc
lily/side-position-interface.cc
lily/simple-closure.cc
lily/slur.cc
lily/stencil-integral.cc
lily/system.cc
ly/music-functions-init.ly
scm/define-grobs.scm
scm/output-lib.scm

index 1e7598b25b5089c8cbeca1427d025b98c98f80ed..6a26177850485c28644c927dbc2275638c4b600c 100644 (file)
@@ -126,7 +126,7 @@ start and stop.")
          grob
          (if (eq? axis X)
              ly:side-position-interface::x-aligned-side
-             ly:side-position-interface::y-aligned-side)
+             side-position-interface::y-aligned-side)
          (axis-offset-symbol axis)))))
 
 schemeTextSpannerEngraver =
index 1ed1f7f8fcc109e3d65ea2ed83d556b3b936f217..0d786c3a2959aa201470f761c27ee3cd6a98645d 100644 (file)
@@ -258,6 +258,9 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
           && !has_interface (g))
         continue;
 
+      if (!g->is_live ())
+        continue;
+
       bool outside_staff = scm_is_number (g->get_property ("outside-staff-priority"));
       Real padding = robust_scm2double (g->get_property ("outside-staff-padding"), get_default_outside_staff_padding ());
 
@@ -493,20 +496,20 @@ Axis_group_interface::internal_calc_pure_relevant_grobs (Grob *me, string grob_s
   extract_grob_set (me, grob_set_name.c_str (), elts);
 
   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 (elts[i] && elts[i]->is_live ())
         {
-          for (LEFT_and_RIGHT (d))
+          relevant_grobs.push_back (elts[i]);
+          if (Item *it = dynamic_cast<Item *> (elts[i]))
             {
-              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);
+              for (LEFT_and_RIGHT (d))
+                {
+                  Item *piece = it->find_prebroken_piece (d);
+                  if (piece && piece->is_live ())
+                    relevant_grobs.push_back (piece);
+                }
             }
         }
     }
@@ -573,7 +576,7 @@ Axis_group_interface::pure_group_height (Grob *me, int start, int end)
       programming_error ("no pure Y common refpoint");
       return Interval ();
     }
-  Real my_coord = me->relative_coordinate (common, Y_AXIS);
+  Real my_coord = me->pure_relative_y_coordinate (common, start, end);
   Interval r (relative_pure_height (me, start, end));
 
   return r - my_coord;
index a89435de6871a6ff391ac34075cea7e3c3f44527..00b9081b3e34889ed1d6cf26323b7d6efe3e3e2a 100644 (file)
@@ -30,6 +30,7 @@
 #include "spanner.hh"
 #include "stream-event.hh"
 #include "stem.hh"
+#include "unpure-pure-container.hh"
 #include "warn.hh"
 
 #include "translator.icc"
@@ -243,7 +244,10 @@ Beam_engraver::acknowledge_rest (Grob_info info)
   if (beam_
       && !scm_is_number (info.grob ()->get_property_data ("staff-position")))
     chain_offset_callback (info.grob (),
-                           Beam::rest_collision_callback_proc, Y_AXIS);
+                           ly_make_unpure_pure_container
+                             (Beam::rest_collision_callback_proc,
+                              Beam::pure_rest_collision_callback_proc),
+                           Y_AXIS);
 }
 
 void
index 4f6c0adc81f5219836e20c2bb92754f347a20eab..4c63fe3c0c55436c4a608e0747582ff026c6ffd7 100644 (file)
@@ -1,5 +1,6 @@
 #include "grob.hh"
 #include "simple-closure.hh"
+#include "unpure-pure-container.hh"
 
 SCM
 axis_offset_symbol (Axis a)
@@ -38,7 +39,7 @@ add_offset_callback (Grob *g, SCM proc, Axis a)
       return;
     }
 
-  if (ly_is_procedure (data))
+  if (ly_is_procedure (data) || is_unpure_pure_container (data))
     data = ly_make_simple_closure (scm_list_1 (data));
   else if (is_simple_closure (data))
     data = simple_closure_expression (data);
@@ -66,7 +67,7 @@ chain_callback (Grob *g, SCM proc, SCM sym)
 {
   SCM data = g->get_property_data (sym);
 
-  if (ly_is_procedure (data))
+  if (ly_is_procedure (data) || is_unpure_pure_container (data))
     data = ly_make_simple_closure (scm_list_1 (data));
   else if (is_simple_closure (data))
     data = simple_closure_expression (data);
index 9120aefdf29939b5f16c6e60fb7218fdcafeba68..f9773e5ec5a4878b12f66f1535970a5696e6ff8a 100644 (file)
@@ -181,6 +181,7 @@ Grob::internal_get_property (SCM sym) const
 
   if (is_unpure_pure_container (val))
     val = unpure_pure_container_unpure_part (val);
+
   if (ly_is_procedure (val)
       || is_simple_closure (val))
     {
@@ -321,9 +322,35 @@ Grob::internal_has_interface (SCM k)
 SCM
 call_pure_function (SCM unpure, SCM args, int start, int end)
 {
-  SCM scm_call_pure_function = ly_lily_module_constant ("call-pure-function");
+  if (is_unpure_pure_container (unpure))
+    {
+      SCM pure = unpure_pure_container_pure_part (unpure);
+
+      if (is_simple_closure (pure))
+        {
+          SCM expr = simple_closure_expression (pure);
+          return evaluate_with_simple_closure (scm_car (args), expr, true, start, end);
+        }
+
+      if (ly_is_procedure (pure))
+        return scm_apply_0 (pure,
+                            scm_append (scm_list_2 (scm_list_3 (scm_car (args),
+                                                                scm_from_int (start),
+                                                                scm_from_int (end)),
+                                                    scm_cdr (args))));
+
+      return pure;
+    }
+
+  if (is_simple_closure (unpure))
+    {
+      SCM expr = simple_closure_expression (unpure);
+      return evaluate_with_simple_closure (scm_car (args), expr, true, start, end);
+    }
+
+  if (!ly_is_procedure (unpure))
+    return unpure;
 
-  return scm_apply_0 (scm_call_pure_function,
-                      scm_list_4 (unpure, args, scm_from_int (start), scm_from_int (end)));
+  return SCM_BOOL_F;
 }
 
index e5976a569b799b4db7a4fa6562afe6ee4953cb0f..9ae9c14fcbd3698a57adff41dfecf6edb80d5529 100644 (file)
@@ -25,6 +25,7 @@
 #include "paper-score.hh"
 #include "simple-closure.hh"
 #include "system.hh"
+#include "unpure-pure-container.hh"
 #include "warn.hh"              // error ()
 
 LY_DEFINE (ly_grob_property_data, "ly:grob-property-data",
@@ -450,7 +451,7 @@ LY_DEFINE (ly_grob_chain_callback, "ly:grob-chain-callback",
   Grob *gr = unsmob_grob (grob);
 
   LY_ASSERT_SMOB (Grob, grob, 1);
-  LY_ASSERT_TYPE (ly_is_procedure, proc, 2);
+  SCM_ASSERT_TYPE (ly_is_procedure (proc) || is_unpure_pure_container (proc), proc, SCM_ARG2, __FUNCTION__, "procedure or unpure pure container");
   LY_ASSERT_TYPE (ly_is_symbol, sym, 3);
 
   chain_callback (gr, proc, sym);
index 8ece3cd6f99c152a812867ab39d7967834ec6504..a6b862e04eee586495fd6e1b3aff343e0340678b 100644 (file)
@@ -36,6 +36,7 @@
 #include "stencil.hh"
 #include "stream-event.hh"
 #include "system.hh"
+#include "unpure-pure-container.hh"
 #include "warn.hh"
 
 #include "ly-smobs.icc"
@@ -79,11 +80,17 @@ Grob::Grob (SCM basicprops)
   if (get_property_data ("X-extent") == SCM_EOL)
     set_property ("X-extent", Grob::stencil_width_proc);
   if (get_property_data ("Y-extent") == SCM_EOL)
-    set_property ("Y-extent", Grob::stencil_height_proc);
+    set_property ("Y-extent",
+                  ly_make_unpure_pure_container (Grob::stencil_height_proc,
+                                                 Grob::pure_stencil_height_proc));
   if (get_property_data ("vertical-skylines") == SCM_EOL)
-    set_property ("vertical-skylines", Grob::simple_vertical_skylines_from_extents_proc);
+    set_property ("vertical-skylines",
+                  ly_make_unpure_pure_container (Grob::simple_vertical_skylines_from_extents_proc,
+                                                 Grob::pure_simple_vertical_skylines_from_extents_proc));
   if (get_property_data ("horizontal-skylines") == SCM_EOL)
-    set_property ("horizontal-skylines", Grob::simple_horizontal_skylines_from_extents_proc);
+    set_property ("horizontal-skylines",
+                  ly_make_unpure_pure_container (Grob::simple_horizontal_skylines_from_extents_proc,
+                                                 Grob::pure_simple_horizontal_skylines_from_extents_proc));
 }
 
 Grob::Grob (Grob const &s)
@@ -488,10 +495,7 @@ Interval
 Grob::pure_height (Grob *refp, int start, int end)
 {
   SCM iv_scm = get_pure_property ("Y-extent", start, end);
-  // TODO: Why is this Interval (0,0)
-  // Shouldn't it just be an empty interval?
-  // 0,0 puts an arbitrary point at 0,0 which will influence spacing
-  Interval iv = robust_scm2interval (iv_scm, Interval (0, 0));
+  Interval iv = robust_scm2interval (iv_scm, Interval ());
   Real offset = pure_relative_y_coordinate (refp, start, end);
 
   SCM min_ext = get_property ("minimum-Y-extent");
@@ -857,6 +861,18 @@ Grob::stencil_height (SCM smob)
   return grob_stencil_extent (me, Y_AXIS);
 }
 
+MAKE_SCHEME_CALLBACK (Grob, pure_stencil_height, 3);
+SCM
+Grob::pure_stencil_height (SCM smob, SCM /* beg */, SCM /* end */)
+{
+  Grob *me = unsmob_grob (smob);
+  if (unsmob_stencil (me->get_property_data ("stencil")))
+    return grob_stencil_extent (me, Y_AXIS);
+
+  return ly_interval2scm (Interval ());
+
+}
+
 MAKE_SCHEME_CALLBACK (Grob, y_parent_positioning, 1);
 SCM
 Grob::y_parent_positioning (SCM smob)
index a98b19a9f6ea4098041e3468eeaf270f6762d758..70c9c0a94e0a92ad2e9dfb3006473411b86da50f 100644 (file)
@@ -69,15 +69,18 @@ public:
   /* standard callbacks */
   DECLARE_SCHEME_CALLBACK (x_parent_positioning, (SCM));
   DECLARE_SCHEME_CALLBACK (y_parent_positioning, (SCM));
+  DECLARE_SCHEME_CALLBACK (pure_stencil_height, (SCM smob, SCM, SCM));
   DECLARE_SCHEME_CALLBACK (stencil_height, (SCM smob));
   DECLARE_SCHEME_CALLBACK (stencil_width, (SCM smob));
   DECLARE_SCHEME_CALLBACK (pure_simple_vertical_skylines_from_extents, (SCM smob, SCM, SCM));
   DECLARE_SCHEME_CALLBACK (simple_vertical_skylines_from_extents, (SCM smob));
   DECLARE_SCHEME_CALLBACK (vertical_skylines_from_stencil, (SCM smob));
+  DECLARE_SCHEME_CALLBACK (pure_vertical_skylines_from_element_stencils, (SCM smob, SCM, SCM));
   DECLARE_SCHEME_CALLBACK (vertical_skylines_from_element_stencils, (SCM smob));
   DECLARE_SCHEME_CALLBACK (pure_simple_horizontal_skylines_from_extents, (SCM smob, SCM, SCM));
   DECLARE_SCHEME_CALLBACK (simple_horizontal_skylines_from_extents, (SCM smob));
   DECLARE_SCHEME_CALLBACK (horizontal_skylines_from_stencil, (SCM smob));
+  DECLARE_SCHEME_CALLBACK (pure_horizontal_skylines_from_element_stencils, (SCM smob, SCM, SCM));
   DECLARE_SCHEME_CALLBACK (horizontal_skylines_from_element_stencils, (SCM smob));
 
   /* R/O access */
@@ -164,6 +167,7 @@ public:
   bool check_cross_staff (Grob *common);
   static bool less (Grob *g1, Grob *g2);
   static SCM maybe_pure_internal_simple_skylines_from_extents (Grob *, Axis, bool, int, int, bool, bool);
+  static SCM internal_skylines_from_element_stencils (Grob *me, Axis a, bool pure, int beg, int end);
   static SCM internal_skylines_from_element_stencils (SCM, Axis);
 };
 
index ddda5185792522cc60afc155cc04a40fca0e8dcd..1ad0635d3653456a0f5e600246a20d7b5658205c 100644 (file)
@@ -394,6 +394,8 @@ type_check_assignment (SCM sym, SCM val, SCM type_symbol)
   if (val == SCM_EOL || val == SCM_BOOL_F)
     return ok;
 
+  // If undefined, some internal function caused it...should never happen.
+  assert (val != SCM_UNDEFINED);
   if (!scm_is_symbol (sym))
     return false;
 
index 0ebd1324506ebf7b404a3ab640ba57e746cf4f91..c6ab972c74994c27752d1881200a52c073651dea 100644 (file)
@@ -33,6 +33,7 @@ protected:
   DECLARE_ACKNOWLEDGER (slur);
   TRANSLATOR_DECLARATIONS (Melody_engraver);
   void stop_translation_timestep ();
+  void process_acknowledged ();
   void process_music ();
 };
 
@@ -49,8 +50,12 @@ Melody_engraver::process_music ()
     melody_item_ = 0;
 }
 
+/*
+  Used to be in stop_translation_timestep, but grobs can't
+  be created here.
+*/
 void
-Melody_engraver::stop_translation_timestep ()
+Melody_engraver::process_acknowledged ()
 {
   if (stem_
       && !is_direction (stem_->get_property_data ("neutral-direction")))
@@ -66,6 +71,11 @@ Melody_engraver::stop_translation_timestep ()
           Melody_spanner::add_stem (melody_item_, stem_);
         }
     }
+}
+
+void
+Melody_engraver::stop_translation_timestep ()
+{
   stem_ = 0;
 }
 
index bfb560925335d0ca70512e26ddcd6ef2c2fd974c..24925d29b8599b027703cc76cd0add07114f214b 100644 (file)
@@ -46,9 +46,7 @@ Pure_from_neighbor_engraver::Pure_from_neighbor_engraver ()
 void
 Pure_from_neighbor_engraver::acknowledge_item (Grob_info i)
 {
-  SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?");
-  if (!Pure_from_neighbor_interface::has_interface (i.item ())
-      && to_boolean (scm_call_1 (pure_relevant_p, i.item ()->self_scm ())))
+  if (!Pure_from_neighbor_interface::has_interface (i.item ()))
     pure_relevants_.push_back (i.item ());
 }
 
index e2b0db5ef2352e6e6d002259d90386bb97579bee..46435b73ad5b26356e21ceb5ef369635eafe19df 100644 (file)
@@ -34,6 +34,7 @@ using namespace std;
 #include "staff-symbol-referencer.hh"
 #include "stem.hh"
 #include "grob.hh"
+#include "unpure-pure-container.hh"
 #include "warn.hh"
 
 MAKE_SCHEME_CALLBACK_WITH_OPTARGS (Rest_collision, force_shift_callback_rest, 2, 1, "");
@@ -72,7 +73,10 @@ Rest_collision::add_column (Grob *me, Grob *p)
   if (rest)
     {
       chain_offset_callback (rest,
-                             Rest_collision::force_shift_callback_rest_proc, Y_AXIS);
+                             ly_make_unpure_pure_container
+                               (Rest_collision::force_shift_callback_rest_proc,
+                                ly_lily_module_constant ("pure-chain-offset-callback")),
+                              Y_AXIS);
     }
 }
 
index f47171fb5a380ef8764a5abbc96e9f5c1135a24f..3dc8a2b0e6f97b3c2844155f9020c5ede6d64b8b 100644 (file)
@@ -34,6 +34,7 @@ ADD_INTERFACE (Semi_tie_column,
                "The interface for a column of l.v. (laissez vibrer) ties.",
 
                /* properties */
+               "direction "
                "positioning-done "
                "head-direction "
                "tie-configuration "
index 6ff2928072541611bda6db49d7cb64626d8ab4c3..8a32363eb4d2b0d8c6df9c321f429cbee8886e8d 100644 (file)
@@ -150,10 +150,19 @@ Separation_item::boxes (Grob *me, Grob *left)
       Interval extra_height = robust_scm2interval (elts[i]->get_property ("extra-spacing-height"),
                                                    Interval (0.0, 0.0));
 
-      x[LEFT] += extra_width[LEFT];
-      x[RIGHT] += extra_width[RIGHT];
-      y[DOWN] += extra_height[DOWN];
-      y[UP] += extra_height[UP];
+      // The conventional empty extent is (+inf.0 . -inf.0)
+      //  but (-inf.0 . +inf.0) is used as extra-spacing-height
+      //  on items that must not overlap other note-columns.
+      // If these two uses of inf combine, leave the empty extent.
+
+      if (!isinf (x[LEFT]))
+        x[LEFT] += extra_width[LEFT];
+      if (!isinf (x[RIGHT]))
+        x[RIGHT] += extra_width[RIGHT];
+      if (!isinf (y[DOWN]))
+        y[DOWN] += extra_height[DOWN];
+      if (!isinf (y[UP]))
+        y[UP] += extra_height[UP];
 
       if (!x.is_empty () && !y.is_empty ())
         out.push_back (Box (x, y));
index 49c6ece55a1c8853214e28965a7c253df284f5da..095b8b49c344db5566303b987dd890eea42136a4 100644 (file)
@@ -46,6 +46,7 @@ using namespace std;
 #include "string-convert.hh"
 #include "system.hh"
 #include "warn.hh"
+#include "unpure-pure-container.hh"
 
 void
 Side_position_interface::add_support (Grob *me, Grob *e)
@@ -184,7 +185,7 @@ Side_position_interface::calc_cross_staff (SCM smob)
 SCM
 Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, int end,
                                        Real *current_off)
-{//printf (" %s\n", me->name ().c_str ());
+{
   Direction dir = get_grob_direction (me);
 
   set<Grob *> support = get_support_set (me);
@@ -198,12 +199,13 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
                                            ax);
 
   Grob *staff_symbol = Staff_symbol_referencer::get_staff_symbol (me);
+  bool quantize_position = to_boolean (me->get_maybe_pure_property ("quantize-position", pure, start, end));
 
   bool include_staff
     = staff_symbol
       && a == Y_AXIS
-      && scm_is_number (me->get_property ("staff-padding"))
-      && !to_boolean (me->get_property ("quantize-position"));
+      && scm_is_number (me->get_maybe_pure_property ("staff-padding", pure, start, end))
+      && !quantize_position;
 
   if (include_staff)
     common[Y_AXIS] = staff_symbol->common_refpoint (common[Y_AXIS], Y_AXIS);
@@ -250,7 +252,7 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
   for (it = support.begin (); it != support.end (); it++)
     {
       Grob *e = *it;
-//printf ("    %s\n", e->name ().c_str ());
+
       // In the case of a stem, we will find a note head as well
       // ignoring the stem solves cyclic dependencies if the stem is
       // attached to a cross-staff beam.
@@ -286,7 +288,7 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
                Skyline_pair copy = Skyline_pair (*sp);
                if (a == Y_AXIS
                    && Stem::has_interface (e)
-                   && to_boolean (me->get_property ("add-stem-support")))
+                   && to_boolean (me->get_maybe_pure_property ("add-stem-support", pure, start, end)))
                  copy[dir].set_minimum_height (copy[dir].max_height ());
                copy.shift (a == X_AXIS ? yc : xc);
                copy.raise (a == X_AXIS ? xc : yc);
@@ -339,12 +341,12 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
     dim.set_minimum_height (dim.max_height ());
 
   Real ss = Staff_symbol_referencer::staff_space (me);
-  Real dist = dim.distance (my_dim, robust_scm2double (me->get_property ("horizon-padding"), 0.0));
+  Real dist = dim.distance (my_dim, robust_scm2double (me->get_maybe_pure_property ("horizon-padding", pure, start, end), 0.0));
   Real total_off = !isinf (dist) ? dir * dist : 0.0;
 
-  total_off += dir * ss * robust_scm2double (me->get_property ("padding"), 0.0);
+  total_off += dir * ss * robust_scm2double (me->get_maybe_pure_property ("padding", pure, start, end), 0.0);
 
-  Real minimum_space = ss * robust_scm2double (me->get_property ("minimum-space"), -1);
+  Real minimum_space = ss * robust_scm2double (me->get_maybe_pure_property ("minimum-space", pure, start, end), -1);
 
   if (minimum_space >= 0
       && dir
@@ -375,7 +377,7 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
   Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
   if (staff && a == Y_AXIS)
     {
-      if (to_boolean (me->get_property ("quantize-position")))
+      if (quantize_position)
         {
           Grob *common = me->common_refpoint (staff, Y_AXIS);
           Real my_off = me->get_parent (Y_AXIS)->maybe_pure_coordinate (common, Y_AXIS, pure, start, end);
@@ -398,13 +400,13 @@ Side_position_interface::aligned_side (Grob *me, Axis a, bool pure, int start, i
                 total_off += dir * 0.5 * ss;
             }
         }
-      else if (scm_is_number (me->get_property ("staff-padding")) && dir)
+      else if (scm_is_number (me->get_maybe_pure_property ("staff-padding", pure, start, end)) && dir)
         {
           Interval iv = me->maybe_pure_extent (me, a, pure, start, end);
 
           Real staff_padding
             = Staff_symbol_referencer::staff_space (me)
-              * scm_to_double (me->get_property ("staff-padding"));
+              * scm_to_double (me->get_maybe_pure_property ("staff-padding", pure, start, end));
 
           Grob *parent = me->get_parent (Y_AXIS);
           Grob *common = me->common_refpoint (staff, Y_AXIS);
@@ -429,7 +431,7 @@ Side_position_interface::set_axis (Grob *me, Axis a)
       chain_offset_callback (me,
                              (a == X_AXIS)
                              ? x_aligned_side_proc
-                             : y_aligned_side_proc,
+                             : ly_make_unpure_pure_container (y_aligned_side_proc, pure_y_aligned_side_proc),
                              a);
     }
 }
index 0c5dca8e95873af67d1d0433b50d8ae6950abfbb..59f9fd995b78c4f00a677db6c37cacb6e652129f 100644 (file)
@@ -18,6 +18,7 @@
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "simple-closure.hh"
+#include "unpure-pure-container.hh"
 
 #include "grob.hh"
 
@@ -64,27 +65,34 @@ evaluate_with_simple_closure (SCM delayed_argument,
   if (is_simple_closure (expr))
     {
       SCM inside = simple_closure_expression (expr);
+      SCM proc = is_unpure_pure_container (scm_car (inside))
+               ? (pure ? scm_car (inside) : unpure_pure_container_unpure_part (scm_car (inside)))
+               : scm_car (inside);
       SCM args = scm_cons (delayed_argument,
                            evaluate_args (delayed_argument, scm_cdr (inside),
                                           pure, start, end));
       if (scm_cdr (args) == SCM_UNSPECIFIED)
         return SCM_UNSPECIFIED;
       if (pure)
-        return call_pure_function (scm_car (inside), args, start, end);
-      return scm_apply_0 (scm_car (inside), args);
+        return call_pure_function (proc, args, start, end);
+      return scm_apply_0 (proc, args);
     }
   else if (!scm_is_pair (expr))
     return expr;
   else if (scm_car (expr) == ly_symbol2scm ("quote"))
     return scm_cadr (expr);
-  else if (ly_is_procedure (scm_car (expr)))
+  else if (is_unpure_pure_container (scm_car (expr))
+           || ly_is_procedure (scm_car (expr)))
     {
+      SCM proc = is_unpure_pure_container (scm_car (expr))
+               ? (pure ? scm_car (expr) : unpure_pure_container_unpure_part (scm_car (expr)))
+               : scm_car (expr);
       SCM args = evaluate_args (delayed_argument, scm_cdr (expr), pure, start, end);
       if (args == SCM_UNSPECIFIED)
         return SCM_UNSPECIFIED;
       if (pure)
-        return call_pure_function (scm_car (expr), args, start, end);
-      return scm_apply_0 (scm_car (expr), args);
+        return call_pure_function (proc, args, start, end);
+      return scm_apply_0 (proc, args);
     }
   else
     // ugh. deviation from standard. Should print error?
index eb9913dc160b94a6e8821f757d067832fb30c7aa..0aa96c787d1d7ba482ed0170e3990ee703258236 100644 (file)
@@ -40,6 +40,7 @@
 #include "warn.hh"
 #include "slur-scoring.hh"
 #include "separation-item.hh"
+#include "unpure-pure-container.hh"
 #include "international.hh"
 
 MAKE_SCHEME_CALLBACK (Slur, calc_direction, 1)
@@ -421,7 +422,10 @@ Slur::auxiliary_acknowledge_extra_object (Grob_info const &info,
     {
       if (slur)
         {
-          chain_offset_callback (e, outside_slur_callback_proc, Y_AXIS);
+          chain_offset_callback (e,
+                                 ly_make_unpure_pure_container (outside_slur_callback_proc,
+                                                                pure_outside_slur_callback_proc),
+                                 Y_AXIS);
           chain_callback (e, outside_slur_cross_staff_proc, ly_symbol2scm ("cross-staff"));
           e->set_object ("slur", slur->self_scm ());
         }
index 601893b5cb23913bbc5d925c31a29edde89aba23..58b2ff46ca55277930db2657c1d920a67485de77 100644 (file)
@@ -1088,9 +1088,8 @@ Grob::horizontal_skylines_from_stencil (SCM smob)
 }
 
 SCM
-Grob::internal_skylines_from_element_stencils (SCM smob, Axis a)
+Grob::internal_skylines_from_element_stencils (Grob *me, Axis a, bool pure, int beg, int end)
 {
-  Grob *me = unsmob_grob (smob);
 
   extract_grob_set (me, "elements", elts);
   vector<Real> x_pos;
@@ -1100,14 +1099,15 @@ Grob::internal_skylines_from_element_stencils (SCM smob, Axis a)
   for (vsize i = 0; i < elts.size (); i++)
     {
       x_pos.push_back (elts[i]->relative_coordinate (x_common, X_AXIS));
-      y_pos.push_back (elts[i]->relative_coordinate (y_common, Y_AXIS));
+      y_pos.push_back (elts[i]->maybe_pure_coordinate (y_common, Y_AXIS, pure, beg, end));
     }
   Real my_x = me->relative_coordinate (x_common, X_AXIS);
-  Real my_y = me->relative_coordinate (y_common, Y_AXIS);
+  Real my_y = me->maybe_pure_coordinate (y_common, Y_AXIS, pure, beg, end);
+
   Skyline_pair res;
   for (vsize i = 0; i < elts.size (); i++)
     {
-      Skyline_pair *skyp = Skyline_pair::unsmob (elts[i]->get_property (a == X_AXIS ? "vertical-skylines" : "horizontal-skylines"));
+      Skyline_pair *skyp = Skyline_pair::unsmob (elts[i]->get_maybe_pure_property (a == X_AXIS ? "vertical-skylines" : "horizontal-skylines", pure, beg, end));
       if (skyp)
         {
           /*
@@ -1141,12 +1141,34 @@ MAKE_SCHEME_CALLBACK (Grob, vertical_skylines_from_element_stencils, 1);
 SCM
 Grob::vertical_skylines_from_element_stencils (SCM smob)
 {
-  return internal_skylines_from_element_stencils (smob, X_AXIS);
+  Grob *me = unsmob_grob (smob);
+  return internal_skylines_from_element_stencils (me, X_AXIS, false, 0, INT_MAX);
 }
 
 MAKE_SCHEME_CALLBACK (Grob, horizontal_skylines_from_element_stencils, 1);
 SCM
 Grob::horizontal_skylines_from_element_stencils (SCM smob)
 {
-  return internal_skylines_from_element_stencils (smob, Y_AXIS);
+  Grob *me = unsmob_grob (smob);
+  return internal_skylines_from_element_stencils (me, Y_AXIS, false, 0, INT_MAX);
+}
+
+MAKE_SCHEME_CALLBACK (Grob, pure_vertical_skylines_from_element_stencils, 3);
+SCM
+Grob::pure_vertical_skylines_from_element_stencils (SCM smob, SCM beg_scm, SCM end_scm)
+{
+  Grob *me = unsmob_grob (smob);
+  int beg = robust_scm2int (beg_scm, 0);
+  int end = robust_scm2int (end_scm, 0);
+  return internal_skylines_from_element_stencils (me, X_AXIS, true, beg, end);
+}
+
+MAKE_SCHEME_CALLBACK (Grob, pure_horizontal_skylines_from_element_stencils, 3);
+SCM
+Grob::pure_horizontal_skylines_from_element_stencils (SCM smob, SCM beg_scm, SCM end_scm)
+{
+  Grob *me = unsmob_grob (smob);
+  int beg = robust_scm2int (beg_scm, 0);
+  int end = robust_scm2int (end_scm, 0);
+  return internal_skylines_from_element_stencils (me, Y_AXIS, true, beg, end);
 }
index e3da76687d9676704963b711c3a2e583236ccfa0..b2e0d53a880405a5037811a2f057a25e1bad2749 100644 (file)
@@ -914,21 +914,19 @@ System::calc_pure_relevant_grobs (SCM smob)
 
   extract_grob_set (me, "elements", elts);
   vector<Grob *> relevant_grobs;
-  SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?");
 
   for (vsize i = 0; i < elts.size (); ++i)
     {
       if (!Axis_group_interface::has_interface (elts[i]))
         {
-          if (to_boolean (scm_apply_1 (pure_relevant_p, elts[i]->self_scm (), SCM_EOL)))
-            relevant_grobs.push_back (elts[i]);
+          relevant_grobs.push_back (elts[i]);
 
           if (Item *it = dynamic_cast<Item *> (elts[i]))
             {
               for (LEFT_and_RIGHT (d))
                 {
                   Item *piece = it->find_prebroken_piece (d);
-                  if (piece && to_boolean (scm_apply_1 (pure_relevant_p, piece->self_scm (), SCM_EOL)))
+                  if (piece && piece->is_live ())
                     relevant_grobs.push_back (piece);
                 }
             }
index 2669cc6bfb08916d4bcca73f4c425b9ec6a1921b..379eb933ba192169821a9177991c19e52816ee96 100644 (file)
@@ -438,9 +438,7 @@ harmonics played on a fretted instrument by touching the strings at @var{fret}."
   #{
     \set harmonicDots = ##t
     \temporary \override TabNoteHead.stencil = #(tab-note-head::print-custom-fret-label (number->string fret))
-    \temporary \override NoteHead.Y-extent = #(ly:make-unpure-pure-container ly:grob::stencil-height
-                                       (lambda (grob start end)
-                                               (ly:grob::stencil-height grob)))
+    \temporary \override NoteHead.Y-extent = #grob::always-Y-extent-from-stencil
     \temporary \override NoteHead.stencil = #(lambda (grob) (ly:grob-set-property! grob 'style 'harmonic-mixed)
                                             (ly:note-head::print grob))
     #(make-harmonic
index ff02523046dbf87de3edd7431d5a19ab2ce9fa05..effaf131faa22f1dce75d52d8738b4c4eeb71ae7 100644 (file)
@@ -24,6 +24,7 @@
 
 ;; TODO: junk the meta field in favor of something more compact?
 
+
 (define-public all-grob-descriptions
   `(
     (Accidental
        (glyph-name . ,accidental-interface::glyph-name)
        (glyph-name-alist . ,standard-alteration-glyph-name-alist)
        (stencil . ,ly:accidental-interface::print)
-       (horizontal-skylines . ,ly:accidental-interface::horizontal-skylines)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (horizontal-skylines . ,(ly:make-unpure-pure-container ly:accidental-interface::horizontal-skylines))
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (X-extent . ,ly:accidental-interface::width)
-       (Y-extent . ,ly:accidental-interface::height)
+       (Y-extent . ,accidental-interface::height)
        (meta . ((class . Item)
                 (interfaces . (accidental-interface
                                inline-accidental-interface
@@ -49,7 +50,7 @@
        (glyph-name-alist . ,standard-alteration-glyph-name-alist)
        (parenthesized . #t)
        (stencil . ,ly:accidental-interface::print)
-       (Y-extent . ,ly:accidental-interface::height)
+       (Y-extent . ,accidental-interface::height)
        (meta . ((class . Item)
                 (interfaces . (accidental-interface
                                inline-accidental-interface
@@ -90,8 +91,8 @@
                          (list ly:self-alignment-interface::centered-on-x-parent))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
-       (Y-extent . ,ly:accidental-interface::height)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-extent . ,accidental-interface::height)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Item)
                 (interfaces . (accidental-interface
                                accidental-suggestion-interface
                        (time-signature . (extra-space . 0.0))
                        (first-note . (fixed-space . 0.0))))
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
+       (Y-extent . ,axis-group-interface::height)
        (meta . ((class . Item)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (side-axis . ,X)
        (stencil . ,ly:accidental-interface::print)
        (X-offset . ,ly:side-position-interface::x-aligned-side)
-       (Y-extent . ,ly:accidental-interface::height)
+       (Y-extent . ,accidental-interface::height)
        (meta . ((class . Item)
                 (interfaces . (accidental-interface
                                break-aligned-interface
        (duration-log . 2)
        (glyph-name . ,note-head::calc-glyph-name)
        (stencil . ,ly:note-head::print)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,staff-symbol-referencer::callback)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (ambitus-interface
                                font-interface
        (staff-position . 0.0)
        (stencil . ,ly:arpeggio::print)
        (X-extent . ,ly:arpeggio::width)
+       (Y-extent . ,(grob::unpure-Y-extent-from-stencil ly:arpeggio::pure-height))
        (X-offset . ,ly:side-position-interface::x-aligned-side)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (Y-offset . ,staff-symbol-referencer::callback)
        (meta . ((class . Item)
                 (interfaces . (arpeggio-interface
                                font-interface
                        (next-note . (semi-fixed-space . 0.9))
                        (right-edge . (extra-space . 0.0))))
        (stencil . ,ly:bar-line::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                  (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                       (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
                          (list ly:break-alignable-interface::self-align-callback))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta .
              ((class . Item)
               (interfaces . (break-alignable-interface
     (BassFigure
      . (
        (stencil . ,ly:text-interface::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (bass-figure-interface
                                font-interface
        (padding . 0.2)
        (positioning-done . ,ly:align-interface::align-to-minimum-distances)
        (stacking-dir . ,DOWN)
-       (Y-extent . ,ly:axis-group-interface::height)
+       (Y-extent . ,axis-group-interface::height)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (padding . 0.5)
        (side-axis . ,Y)
        (staff-padding . 1.0)
-       (Y-extent . ,ly:axis-group-interface::height)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-extent . ,axis-group-interface::height)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (adjacent-pure-heights . ,ly:axis-group-interface::adjacent-pure-heights)
        (axes . (,Y))
        (vertical-skylines . ,ly:axis-group-interface::calc-skylines)
-       (Y-extent . ,ly:axis-group-interface::height)
+       (Y-extent . ,axis-group-interface::height)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (quantized-positions . ,ly:beam::set-stem-lengths)
 
        (shorten . ,ly:beam::calc-stem-shorten)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (stencil . ,ly:beam::print)
 
        (meta . ((class . Spanner)
        (stencil . ,ly:text-interface::print)
        (text . ,(make-musicglyph-markup "scripts.rcomma"))
        (Y-offset . ,ly:breathing-sign::offset-callback)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (break-aligned-interface
                                breathing-sign-interface
        (extra-spacing-height . (0.2 . -0.2))
        (extra-spacing-width . (-0.5 . 0.5))
        (word-space . 0.0)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (chord-name-interface
                                font-interface
                        (next-note . (extra-space . 1.0))
                        (right-edge . (extra-space . 0.5))))
        (stencil . ,ly:clef::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-offset . ,staff-symbol-referencer::callback)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                  (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                       (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
        ;; todo: add X self alignment?
        (stencil . ,ly:text-interface::print)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                side-position-interface
                        (next-note . (extra-space . 1.0))
                        (right-edge . (extra-space . 0.5))))
        (stencil . ,ly:clef::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-offset . ,staff-symbol-referencer::callback)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                  (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                       (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
                        (next-note . (extra-space . 1.0))
                        (right-edge . (extra-space . 0.5))))
        (stencil . ,ly:clef::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (Y-offset . ,staff-symbol-referencer::callback)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                  (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                       (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
                        (right-edge . (extra-space . 0.1))))
        (stencil . ,ly:custos::print)
        (style . vaticana)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (Y-offset . ,staff-symbol-referencer::callback)
        (meta . ((class . Item)
                 (interfaces  . (break-aligned-interface
                                 custos-interface
        (dot-count . ,dots::calc-dot-count)
        (staff-position . ,dots::calc-staff-position)
        (stencil . ,ly:dots::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (extra-spacing-height . (-0.5 . 0.5))
        (meta . ((class . Item)
                 (interfaces . (dots-interface
        (slash-negative-kern . 1.6)
        (slope . 1.0)
        (stencil . ,ly:percent-repeat-item-interface::double-percent)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (thickness . 0.48)
        (meta . ((class . Item)
                 (interfaces . (break-aligned-interface
                          (list ly:self-alignment-interface::centered-on-y-parent))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
-       (Y-extent . ,grob::all-heights-from-stencil)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                percent-repeat-interface
        (slash-negative-kern . 1.6)
        (slope . 1.0)
        (stencil . ,ly:percent-repeat-item-interface::beat-slash)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (thickness . 0.48)
        (meta . ((class . Item)
                 (interfaces . (font-interface
        (side-axis . ,Y)
        (slur-padding . 0.3)
        (staff-padding . 0.1)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-element-stencils)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-element-stencils)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-extent . ,axis-group-interface::height)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (self-alignment-X . ,CENTER)
        (self-alignment-Y . ,CENTER)
        (stencil . ,ly:text-interface::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
-       (Y-offset . ,ly:self-alignment-interface::y-aligned-on-self)
+       (Y-offset . ,self-alignment-interface::y-aligned-on-self)
        (meta . ((class . Item)
                 (interfaces . (dynamic-interface
                                dynamic-text-interface
        (springs-and-rods . ,ly:spanner::set-spacing-rods)
        (stencil . ,ly:line-spanner::print)
        (style . dashed-line)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (meta . ((class . Spanner)
                 (interfaces . (dynamic-interface
                                dynamic-text-spanner-interface
        (side-axis . ,Y)
        (stencil . ,ly:line-spanner::print)
        (style . line)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (interfaces . (episema-interface
                                font-interface
        (staff-padding . 0.5)
        (stencil . ,ly:text-interface::print)
        (text . ,fingering::calc-text)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (finger-interface
                                font-interface
        (stencil . ,ly:flag::print)
        (X-extent . ,ly:flag::width)
        (X-offset . ,ly:flag::calc-x-offset)
-       (Y-offset . ,ly:flag::calc-y-offset)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,(ly:make-unpure-pure-container ly:flag::calc-y-offset ly:flag::pure-calc-y-offset))
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (flag-interface
                                 font-interface))))))
        (stencil . ,fret-board::calc-stencil)
        (extra-spacing-height . (0.2 . -0.2))
        (extra-spacing-width . (-0.5 . 0.5))
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (chord-name-interface
                                font-interface
        (simple-Y . #t)
        (stencil . ,ly:line-spanner::print)
        (style . line)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (X-extent . #f)
        (Y-extent . #f)
        (zigzag-width . 0.75)
        (stencil . ,ly:hairpin::print)
        (thickness . 1.0)
        (to-barline . #t)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-offset . ,ly:self-alignment-interface::y-aligned-on-self)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
+       (Y-extent . ,(grob::unpure-Y-extent-from-stencil ly:hairpin::pure-height))
+       (Y-offset . ,self-alignment-interface::y-aligned-on-self)
        (meta . ((class . Spanner)
                 (interfaces . (dynamic-interface
                                hairpin-interface
        (staff-padding . 0.2)
        (stencil . ,ly:horizontal-bracket::print)
        (thickness . 1.0)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (interfaces . (horizontal-bracket-interface
                                line-interface
        (side-axis . ,Y)
        (staff-padding . 0.5)
        (stencil . ,ly:text-interface::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                self-alignment-interface
                        (right-edge . (extra-space . 0.5))
                        (first-note . (fixed-space . 2.5))))
        (stencil . ,ly:key-signature-interface::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (extra-spacing-width . (0.0 . 1.0))
        (extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height-including-staff)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (Y-offset . ,staff-symbol-referencer::callback)
        (meta . ((class . Item)
                  (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                       (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
                        (right-edge . (extra-space . 0.5))
                        (first-note . (fixed-space . 2.5))))
        (stencil . ,ly:key-signature-interface::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (extra-spacing-width . (0.0 . 1.0))
        (extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height-including-staff)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-offset . ,staff-symbol-referencer::callback)
        (meta . ((class . Item)
                  (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                       (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
        (stencil  . ,laissez-vibrer::print)
        (thickness . 1.0)
        (extra-spacing-height . (-0.5 . 0.5))
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (semi-tie-interface))))))
 
        (minimum-length-fraction . 0.25)
        (springs-and-rods . ,ly:ledger-line-spanner::set-spacing-rods)
        (stencil . ,ly:ledger-line-spanner::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (X-extent . #f)
        (Y-extent . #f)
        (meta . ((class . Spanner)
        (padding . 0.07)
        (springs-and-rods . ,ly:lyric-hyphen::set-spacing-rods)
        (stencil . ,ly:lyric-hyphen::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (thickness . 1.3)
        (Y-extent . (0 . 0))
        (meta . ((class . Spanner)
        (text . ,(grob::calc-property-by-copy 'text))
        (word-space . 0.6)
        (skyline-horizontal-padding . 0.1)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
        (X-offset . ,ly:self-alignment-interface::aligned-on-x-parent)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                lyric-syllable-interface
        (staff-padding . 3)
        (stencil . ,ly:measure-grouping::print)
        (thickness . 1)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (interfaces . (measure-grouping-interface
                                side-position-interface))))))
        (padding . 0.8)
        (side-axis . ,Y)
        (stencil . ,ly:text-interface::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (X-offset . ,(ly:make-simple-closure
                      `(,+
                        ,(ly:make-simple-closure
        (self-alignment-X . ,LEFT)
        (break-align-symbols . (time-signature))
        (non-break-align-symbols . (multi-measure-rest-interface))
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (break-alignable-interface
                                font-interface
        (thick-thickness . 6.6)
        ;; See Wanske pp. 125
        (usable-duration-logs . ,(iota 4 -3))
-       (Y-extent . ,ly:multi-measure-rest::height)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (Y-extent . ,(ly:make-unpure-pure-container ly:multi-measure-rest::height))
+       (Y-offset . ,staff-symbol-referencer::callback)
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
                                multi-measure-interface
                          (list ly:self-alignment-interface::x-aligned-on-self))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-centered-on-y-parent)))))
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
                                multi-measure-interface
                          (list ly:self-alignment-interface::x-centered-on-y-parent))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
                                multi-measure-interface
        (positioning-done . ,ly:note-collision-interface::calc-positioning-done)
        (prefer-dotted-right . #t)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
+       (Y-extent . ,axis-group-interface::height)
        (meta . ((class . Item)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (horizontal-skylines . ,ly:separation-item::calc-skylines)
        (skyline-vertical-padding . 0.15)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
+       (Y-extent . ,axis-group-interface::height)
        (meta . ((class . Item)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (stem-attachment . ,ly:note-head::calc-stem-attachment)
        (stencil . ,ly:note-head::print)
        (X-offset . ,ly:note-head::stem-x-shift)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,staff-symbol-referencer::callback)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                gregorian-ligature-interface
     (NoteName
      . (
        (stencil . ,ly:text-interface::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                note-name-interface
                          (list ly:self-alignment-interface::x-aligned-on-self))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::centered-on-x-parent)))))
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                octavate-eight-interface
        (staff-padding . 1.0)
        (stencil . ,ly:ottava-bracket::print)
        (style . dashed-line)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
                                horizontal-bracket-interface
                          (list ly:self-alignment-interface::x-centered-on-y-parent))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
                                percent-repeat-interface
        (springs-and-rods . ,ly:spanner::set-spacing-rods)
        (stencil . ,ly:slur::print)
        (thickness . 1.1)
-       (vertical-skylines . ,ly:slur::vertical-skylines)
-       (Y-extent . ,ly:slur::height)
+       (vertical-skylines . ,(ly:make-unpure-pure-container ly:slur::vertical-skylines ly:grob::pure-simple-vertical-skylines-from-extents))
+       (Y-extent . ,slur::height)
        (meta . ((class . Spanner)
                 (interfaces . (slur-interface))))))
 
        (stencil . ,ly:piano-pedal-bracket::print)
        (style . line)
        (thickness .  1.0)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (meta . ((class . Spanner)
                 (interfaces . (line-interface
                                piano-pedal-bracket-interface
        (padding . 0.8)
        (self-alignment-X . ,CENTER)
        (stencil . ,ly:text-interface::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
        (X-offset . ,(ly:make-simple-closure
                      `(,+
                        ,(ly:make-simple-closure
                          (list ly:break-alignable-interface::self-align-callback))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,side-position-interface::y-aligned-side)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (break-alignable-interface
                                font-interface
        (slash-negative-kern . 0.85)
        (slope . 1.7)
        (stencil . ,ly:percent-repeat-item-interface::beat-slash)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (thickness . 0.48)
        (meta . ((class . Item)
                 (interfaces . (percent-repeat-interface
        (stencil  . ,ly:tie::print)
        (thickness . 1.0)
        (extra-spacing-height . (-0.5 . 0.5))
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (semi-tie-interface))))))
 
        (minimum-distance . 0.25)
        (stencil . ,ly:rest::print)
        (X-extent . ,ly:rest::width)
-       (Y-extent . ,ly:rest::height)
-       (Y-offset . ,ly:rest::y-offset-callback)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (Y-extent . ,(ly:make-unpure-pure-container ly:rest::height ly:rest::pure-height))
+       (Y-offset . ,(ly:make-unpure-pure-container ly:rest::y-offset-callback))
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                rest-interface
        (staff-padding . 0.25)
 
        (stencil . ,ly:script-interface::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (X-offset . ,script-interface::calc-x-offset)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                script-interface
        (springs-and-rods . ,ly:spanner::set-spacing-rods)
        (stencil . ,ly:slur::print)
        (thickness . 1.2)
-       (vertical-skylines . ,ly:slur::vertical-skylines)
-       (Y-extent . ,ly:slur::height)
+       (vertical-skylines . ,(ly:make-unpure-pure-container ly:slur::vertical-skylines ly:grob::pure-simple-vertical-skylines-from-extents))
+       (Y-extent . ,slur::height)
        (meta . ((class . Spanner)
                 (interfaces . (slur-interface))))))
 
        (padding . 0.0) ;; padding relative to SostenutoPedalLineSpanner
        (self-alignment-X . ,CENTER)
        (stencil . ,ly:text-interface::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                piano-pedal-script-interface
        (padding . 1.2)
        (side-axis . ,Y)
        (staff-padding . 1.0)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-element-stencils)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-element-stencils)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-extent . ,axis-group-interface::height)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
     (SpanBar
      . (
        (allow-span-bar . #t)
-       (bar-extent . ,ly:axis-group-interface::height)
+       (bar-extent . ,axis-group-interface::height)
        (before-line-breaking . ,ly:span-bar::before-line-breaking)
        (break-align-symbol . staff-bar)
        (cross-staff . #t)
      . (
         (X-extent . ,grob::x-parent-width)
        (extra-spacing-height . ,pure-from-neighbor-interface::extra-spacing-height)
-       (Y-extent . #f)
+       ; we want this to be ignored, so empty, but the extra spacing height
+       ; should preserve the span bar's presence for horizontal spacing
+       (Y-extent . ,pure-from-neighbor-interface::unobtrusive-height)
        (meta . ((class . Item)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:pure-from-neighbor-interface::calc-pure-relevant-grobs)))
        (ledger-line-thickness . (1.0 . 0.1))
        (line-count . 5)
        (stencil . ,ly:staff-symbol::print)
-       (Y-extent . ,ly:staff-symbol::height)
+       (Y-extent . ,(ly:make-unpure-pure-container ly:staff-symbol::height))
        (meta . ((class . Spanner)
                 (interfaces . (staff-symbol-interface))))))
 
        (side-axis . ,X)
        (stencil . ,ly:text-interface::print)
        (X-offset . ,ly:side-position-interface::x-aligned-side)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                side-position-interface
 
        (direction . ,ly:stem::calc-direction)
        (duration-log . ,stem::calc-duration-log)
-        (length . ,ly:stem::calc-length)
+        (length . ,(ly:make-unpure-pure-container ly:stem::calc-length ly:stem::pure-calc-length))
        (neutral-direction . ,DOWN)
        (positioning-done . ,ly:stem::calc-positioning-done)
        (stem-info . ,ly:stem::calc-stem-info)
-       (stem-begin-position . ,ly:stem::calc-stem-begin-position)
+       (stem-begin-position . ,(ly:make-unpure-pure-container ly:stem::calc-stem-begin-position ly:stem::pure-calc-stem-begin-position))
        (stencil . ,ly:stem::print)
        (thickness . 1.3)
        (X-extent . ,ly:stem::width)
        (X-offset . ,ly:stem::offset-callback)
-       (Y-extent . ,ly:stem::height)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
+       (Y-extent . ,(ly:make-unpure-pure-container ly:stem::height ly:stem::pure-height))
+       (Y-offset . ,staff-symbol-referencer::callback)
        (meta . ((class . Item)
                 (interfaces . (stem-interface))))))
 
        (stencil . ,ly:stem-tremolo::print)
        (style . ,ly:stem-tremolo::calc-style)
        (X-extent . ,ly:stem-tremolo::width)
+       (Y-extent . ,(grob::unpure-Y-extent-from-stencil ly:stem-tremolo::pure-height))
        (X-offset . ,(ly:make-simple-closure
                      `(,+
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::centered-on-x-parent))
                        ,(ly:make-simple-closure
                          (list ly:self-alignment-interface::x-aligned-on-self)))))
-       (Y-offset . ,ly:stem-tremolo::calc-y-offset)
+        (Y-offset . ,(ly:make-unpure-pure-container ly:stem-tremolo::calc-y-offset ly:stem-tremolo::pure-calc-y-offset))
        (meta . ((class . Item)
                 (interfaces . (self-alignment-interface
                                 stem-tremolo-interface))))))
        (staff-padding . 0.5)
        (stencil . ,print-circled-text-callback)
        (text . ,string-number::calc-text)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                self-alignment-interface
        (staff-padding . 0.5)
        (stencil . ,ly:text-interface::print)
        (text . ,stroke-finger::calc-text)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                self-alignment-interface
        (padding . 0.0)  ;; padding relative to SustainPedalLineSpanner
        (self-alignment-X . ,CENTER)
        (stencil . ,ly:sustain-pedal::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                piano-pedal-interface
        (padding . 1.2)
        (side-axis . ,Y)
        (staff-padding . 1.2)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-element-stencils)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-element-stencils)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-extent . ,axis-group-interface::height)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (skyline-horizontal-padding . 1.0)
        (vertical-skylines . ,ly:axis-group-interface::calc-skylines)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:system::height)
+       (Y-extent . ,(ly:make-unpure-pure-container ly:system::height ly:system::calc-pure-height))
        (meta . ((class . System)
                 (object-callbacks . ((footnotes-before-line-breaking . ,ly:system::footnotes-before-line-breaking)
                                      (footnotes-after-line-breaking . ,ly:system::footnotes-after-line-breaking)
        (stencil . ,tab-note-head::print)
        (whiteout . #t)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,staff-symbol-referencer::callback)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces  . (font-interface
                                 note-head-interface
        (slur-padding . 0.5)
        (staff-padding . 0.5)
        (stencil . ,ly:text-interface::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
        ;; todo: add X self alignment?
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                instrument-specific-markup-interface
        (staff-padding . 0.8)
        (stencil . ,ly:line-spanner::print)
        (style . dashed-line)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
 
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
        (neutral-direction . ,UP)
        (springs-and-rods . ,ly:spanner::set-spacing-rods)
        (stencil . ,ly:tie::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (thickness . 1.2)
        (meta . ((class . Spanner)
                 (interfaces . (tie-interface))))))
                        (right-edge . (extra-space . 0.5))
                        (staff-bar . (minimum-space . 2.0))))
        (stencil . ,ly:time-signature::print)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (style . C)
        (meta . ((class . Item)
                  (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
        (side-axis . ,X)
        (stencil . ,ly:accidental-interface::print)
        (X-offset . ,ly:side-position-interface::x-aligned-side)
-       (Y-extent . ,ly:accidental-interface::height)
+       (Y-extent . ,accidental-interface::height)
        (meta . ((class . Item)
                 (interfaces . (accidental-interface
                                font-interface
        (stencil . ,parenthesize-elements)
        (stencils . ,parentheses-item::calc-parenthesis-stencils)
        (X-offset . ,ly:side-position-interface::x-aligned-side)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (axis-group-interface
                                font-interface
        (duration-log . 2)
        (font-size . -4)
        (stencil . ,ly:note-head::print)
-       (Y-offset . ,ly:staff-symbol-referencer::callback)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (Y-offset . ,staff-symbol-referencer::callback)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (meta . ((class . Item)
                 (interfaces . (font-interface
                                ledgered-interface
        (staff-padding . 1.0)
        (stencil . ,ly:line-spanner::print)
        (style . trill)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
                                line-interface
        (staff-padding . 0.25)
        (stencil . ,ly:tuplet-bracket::print)
        (thickness . 1.6)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
        (X-positions . ,ly:tuplet-bracket::calc-x-positions)
 
        (meta . ((class . Spanner)
        (padding . 0.0)  ;; padding relative to UnaCordaPedalLineSpanner
        (self-alignment-X . ,CENTER)
        (stencil . ,ly:text-interface::print)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
-       (Y-extent . ,grob::all-heights-from-stencil)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-stencil)
+       (Y-extent . ,grob::always-Y-extent-from-stencil)
        (X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
        (meta . ((class . Item)
                 (interfaces . (font-interface
        (padding . 1.2)
        (side-axis . ,Y)
        (staff-padding . 1.2)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-element-stencils)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-element-stencils)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
-       (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-extent . ,axis-group-interface::height)
+       (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
        (stacking-dir . -1)
        (vertical-skylines . ,ly:axis-group-interface::combine-skylines)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
+       (Y-extent . ,axis-group-interface::height)
        (meta . ((class . Spanner)
                 (object-callbacks . ((Y-common . ,ly:axis-group-interface::calc-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)
                                        (padding . 1)))
        (nonstaff-unrelatedstaff-spacing . ((padding . 0.5)))
        (outside-staff-placement-directive . left-to-right-polite)
-       (staff-staff-spacing . ,ly:axis-group-interface::calc-staff-staff-spacing)
+       (staff-staff-spacing . ,(ly:make-unpure-pure-container ly:axis-group-interface::calc-staff-staff-spacing ly:axis-group-interface::calc-pure-staff-staff-spacing))
        (stencil . ,ly:axis-group-interface::print)
        (skyline-horizontal-padding . 0.1)
        (vertical-skylines . ,ly:hara-kiri-group-spanner::calc-skylines)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:hara-kiri-group-spanner::y-extent)
+       (Y-extent . ,(ly:make-unpure-pure-container ly:hara-kiri-group-spanner::y-extent ly:hara-kiri-group-spanner::pure-height))
        (Y-offset . ,ly:hara-kiri-group-spanner::force-hara-kiri-callback)
        (meta . ((class . Spanner)
                 (object-callbacks . (
        (stencil . ,ly:volta-bracket-interface::print)
        (thickness . 1.6) ;; line-thickness
        (word-space . 0.6)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-stencil)
+       (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil)
+       (Y-extent . ,(grob::unpure-Y-extent-from-stencil volta-bracket-interface::pure-height))
        (meta . ((class . Spanner)
                 (interfaces . (font-interface
                                horizontal-bracket-interface
        (outside-staff-priority . 600)
        (padding . 1)
        (side-axis . ,Y)
-       (vertical-skylines . ,ly:grob::vertical-skylines-from-element-stencils)
+       (vertical-skylines . ,grob::always-vertical-skylines-from-element-stencils)
        (X-extent . ,ly:axis-group-interface::width)
-       (Y-extent . ,ly:axis-group-interface::height)
-        (Y-offset . ,ly:side-position-interface::y-aligned-side)
+       (Y-extent . ,axis-group-interface::height)
+        (Y-offset . ,side-position-interface::y-aligned-side)
        (meta . ((class . Spanner)
                 (object-callbacks . ((pure-Y-common . ,ly:axis-group-interface::calc-pure-y-common)
                                      (pure-relevant-grobs . ,ly:axis-group-interface::calc-pure-relevant-grobs)))
      all-grob-descriptions)
 
 (set! all-grob-descriptions (sort all-grob-descriptions alist<?))
-
-(define (volta-bracket-interface::pure-height grob start end)
-  (let ((edge-height (ly:grob-property grob 'edge-height)))
-    (if (number-pair? edge-height)
-       (let ((smaller (min (car edge-height) (cdr edge-height)))
-             (larger (max (car edge-height) (cdr edge-height))))
-         (interval-union '(0 . 0) (cons smaller larger)))
-       '(0 . 0))))
-
-;; Sometimes we have grobs with (Y-extent . ,ly:grob::stencil-height)
-;; and the print function is not pure, but there is a easy way to
-;; figure out the Y-extent from the print function.
-(define pure-print-to-height-conversions
-  `(
-    (,ly:arpeggio::print . ,ly:arpeggio::pure-height)
-    (,ly:arpeggio::brew-chord-bracket . ,ly:arpeggio::pure-height)
-    (,ly:arpeggio::brew-chord-slur . ,ly:arpeggio::pure-height)
-    (,ly:hairpin::print . ,ly:hairpin::pure-height)
-    (,ly:stem-tremolo::print . ,ly:stem-tremolo::pure-height)
-    (,ly:volta-bracket-interface::print . ,volta-bracket-interface::pure-height)))
-
-;; ly:grob::stencil-extent is safe if the print callback is safe too
-(define (pure-stencil-height grob start stop)
-  (let* ((sten (ly:grob-property-data grob 'stencil))
-        (pure-height-callback (assoc-get sten pure-print-to-height-conversions)))
-    (cond ((ly:stencil? sten)
-          (ly:grob::stencil-height grob))
-         ((procedure? pure-height-callback)
-          (pure-height-callback grob start stop))
-         (else
-          '(0 . 0)))))
-
-;; Sometimes, a pure callback will be chained to a non-pure callback via
-;; chain_offset_callback, in which case this provides a default by simply
-;; passing through the value from the pure callback.
-(define (pure-chain-offset-callback grob start end prev-offset) prev-offset)
-
-(define pure-conversions-alist
-  `(
-    (,ly:accidental-interface::height . ,ly:accidental-interface::pure-height)
-    (,ly:axis-group-interface::calc-staff-staff-spacing . ,ly:axis-group-interface::calc-pure-staff-staff-spacing)
-    (,ly:axis-group-interface::height . ,ly:axis-group-interface::pure-height)
-    (,ly:beam::rest-collision-callback . ,ly:beam::pure-rest-collision-callback)
-    (,ly:flag::calc-y-offset . ,ly:flag::pure-calc-y-offset)
-    (,ly:grob::horizontal-skylines-from-stencil . ,ly:grob::pure-simple-horizontal-skylines-from-extents)
-    (,ly:grob::horizontal-skylines-from-element-stencils . ,ly:grob::pure-simple-horizontal-skylines-from-extents)
-    (,ly:grob::simple-horizontal-skylines-from-extents . ,ly:grob::pure-simple-horizontal-skylines-from-extents)
-    (,ly:grob::simple-vertical-skylines-from-extents . ,ly:grob::pure-simple-vertical-skylines-from-extents)
-    (,ly:grob::stencil-height . ,pure-stencil-height)
-    (,ly:grob::vertical-skylines-from-stencil . ,ly:grob::pure-simple-vertical-skylines-from-extents)
-    (,ly:grob::vertical-skylines-from-element-stencils . ,ly:grob::pure-simple-vertical-skylines-from-extents)
-    (,ly:hara-kiri-group-spanner::y-extent . ,ly:hara-kiri-group-spanner::pure-height)
-    (,ly:rest-collision::force-shift-callback-rest . ,pure-chain-offset-callback)
-    (,ly:rest::height . ,ly:rest::pure-height)
-    (,ly:self-alignment-interface::y-aligned-on-self . ,ly:self-alignment-interface::pure-y-aligned-on-self)
-    (,ly:side-position-interface::y-aligned-side . ,ly:side-position-interface::pure-y-aligned-side)
-    (,ly:slur::height . ,ly:slur::pure-height)
-    (,ly:slur::outside-slur-callback . ,ly:slur::pure-outside-slur-callback)
-    (,ly:stem::calc-stem-begin-position . ,ly:stem::pure-calc-stem-begin-position)
-    (,ly:stem::calc-stem-end-position . ,ly:stem::pure-calc-stem-end-position)
-    (,ly:stem::calc-length . ,ly:stem::pure-calc-length)
-    (,ly:stem::height . ,ly:stem::pure-height)
-    (,ly:stem-tremolo::calc-y-offset . ,ly:stem-tremolo::pure-calc-y-offset)
-    (,ly:system::height . ,ly:system::calc-pure-height)))
-
-(define pure-functions
-  (list
-   ly:accidental-interface::horizontal-skylines
-   parenthesize-elements
-   laissez-vibrer::print
-   ly:multi-measure-rest::height
-   ly:rest::y-offset-callback
-   ly:staff-symbol-referencer::callback
-   ly:staff-symbol::height))
-
-(define-public (pure-relevant? grob)
-  (let ((extent-callback (ly:grob-property-data grob 'Y-extent)))
-    (not (eq? #f
-             (or
-               (ly:unpure-pure-container? extent-callback)
-              (pair? extent-callback)
-              (memq extent-callback pure-functions)
-              (and
-               (pair? (assq extent-callback pure-conversions-alist))
-               (let ((stencil (ly:grob-property-data grob 'stencil)))
-                 (or
-                  (not (eq? extent-callback ly:grob::stencil-height))
-                  (assq stencil pure-print-to-height-conversions)
-                  (ly:stencil? stencil)))))))))
-
-;; hideous code dup below - to be cleaned up when call pure functino
-;; is eliminated and lilypond works entirely from unpure-pure-containers
-
-(define-public (call-pure-function unpure args start end)
-  (if (ly:unpure-pure-container? unpure)
-      (let ((unpure (ly:unpure-pure-container-pure-part unpure)))
-        (if (ly:simple-closure? unpure)
-          (ly:eval-simple-closure (car args) unpure start end)
-          (if (not (procedure? unpure))
-              unpure
-              (apply unpure
-                     (append
-                       (list (car args) start end)
-                       (cdr args))))))
-      (if (ly:simple-closure? unpure)
-          (ly:eval-simple-closure (car args) unpure start end)
-          (if (not (procedure? unpure))
-              unpure
-              (if (memq unpure pure-functions)
-                  (apply unpure args)
-                  (let ((pure (assq unpure pure-conversions-alist)))
-                    (if pure
-                        (apply (cdr pure)
-                               (append
-                                (list (car args) start end)
-                                (cdr args))))))))))
index 6c43b0aab1dccb695a0c0c032b1424203944ce14..09f526b8af631dab96ac49bfff5ba4fcaf722278 100644 (file)
 
     (ly:text-interface::interpret-markup layout props text)))
 
+(define-public (grob::unpure-Y-extent-from-stencil pure-function)
+  "The unpure height will come from a stencil whereas the pure
+   height will come from @code{pure-function}."
+  (ly:make-unpure-pure-container ly:grob::stencil-height pure-function))
+
+(define-public grob::unpure-horizontal-skylines-from-stencil
+  (ly:make-unpure-pure-container
+    ly:grob::horizontal-skylines-from-stencil
+    ly:grob::pure-simple-horizontal-skylines-from-extents))
+
+(define-public grob::always-horizontal-skylines-from-stencil
+  (ly:make-unpure-pure-container
+    ly:grob::horizontal-skylines-from-stencil))
+
+(define-public grob::unpure-vertical-skylines-from-stencil
+  (ly:make-unpure-pure-container
+    ly:grob::vertical-skylines-from-stencil
+    ly:grob::pure-simple-vertical-skylines-from-extents))
+
+(define-public grob::always-vertical-skylines-from-stencil
+  (ly:make-unpure-pure-container
+    ly:grob::vertical-skylines-from-stencil))
+
+(define-public grob::always-vertical-skylines-from-element-stencils
+  (ly:make-unpure-pure-container
+    ly:grob::vertical-skylines-from-element-stencils
+    ly:grob::pure-vertical-skylines-from-element-stencils))
+
+(define-public grob::always-horizontal-skylines-from-element-stencils
+  (ly:make-unpure-pure-container
+    ly:grob::horizontal-skylines-from-element-stencils
+    ly:grob::pure-horizontal-skylines-from-element-stencils))
+
+;; Sometimes, in horizontal spacing, we want grobs to block other grobs.
+;; They thus need to have a non-empty height.  We give them a point height
+;; so that, minimally, they block grobs directly to the right of them.
+;; Often this is complimented by an extra-spacing-height.
+;; We don't, however, want these grobs to factor into vertical spacing
+;; decisions, so we make their unpure height #f.
+
 ;; Using this as a callback for a grob's Y-extent promises
 ;; that the grob's stencil does not depend on line-spacing.
 ;; We use this promise to figure the space required by Clefs
 ;; and such at the note-spacing stage.
 
-(define-public grob::all-heights-from-stencil
-  (ly:make-unpure-pure-container
-    ly:grob::stencil-height
-    (lambda (grob start end) (ly:grob::stencil-height grob))))
+(define-public grob::always-Y-extent-from-stencil
+  (ly:make-unpure-pure-container ly:grob::stencil-height))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; beam slope
   (any (lambda (x) (ly:grob? (ly:grob-object x 'beam)))
        (ly:grob-array->list (ly:grob-object g 'side-support-elements))))
 
+(define-public side-position-interface::y-aligned-side
+  (ly:make-unpure-pure-container
+    ly:side-position-interface::y-aligned-side
+    ly:side-position-interface::pure-y-aligned-side))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; self-alignment stuff
+
+(define-public self-alignment-interface::y-aligned-on-self
+  (ly:make-unpure-pure-container
+    ly:self-alignment-interface::y-aligned-on-self
+    ly:self-alignment-interface::pure-y-aligned-on-self))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; staff symbol
+
+(define staff-symbol-referencer::callback
+  (ly:make-unpure-pure-container ly:staff-symbol-referencer::callback))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; note heads
 
@@ -457,6 +514,27 @@ and duration-log @var{log}."
                               10000000))))
     (coord-operation - from-neighbors height)))
 
+;; If there are neighbors, we place the height at their midpoint
+;; to avoid protrusion of this pure height out of the vertical
+;; axis group on either side.  This will minimize the impact of the
+;; grob on pure minimum translations.
+
+;; TODO - there is a double call to axis-group-interface::pure-height
+;; here and then in the extra-spacing-height function above. Can/should this
+;; be rolled into one?
+(define-public (pure-from-neighbor-interface::pure-height grob beg end)
+  (let* ((height (ly:axis-group-interface::pure-height
+                  grob
+                  0
+                  10000000))
+         (c (interval-center height)))
+    (if (interval-empty? height) empty-interval (cons c c))))
+
+;; Minimizes the impact of the height on vertical spacing while allowing
+;; it to appear in horizontal skylines of paper columns if necessary.
+(define-public pure-from-neighbor-interface::unobtrusive-height
+  (ly:make-unpure-pure-container #f pure-from-neighbor-interface::pure-height))
+
 (define-public (pure-from-neighbor-interface::account-for-span-bar grob)
   (let* ((esh (pure-from-neighbor-interface::extra-spacing-height grob))
          (hsb (ly:grob-property grob 'has-span-bar))
@@ -637,6 +715,11 @@ and duration-log @var{log}."
   (assoc-get (ly:grob-property grob 'alteration)
              standard-alteration-glyph-name-alist))
 
+(define-public accidental-interface::height
+  (ly:make-unpure-pure-container
+    ly:accidental-interface::height
+    ly:accidental-interface::pure-height))
+
 (define-public cancellation-glyph-name-alist
   '((0 . "accidentals.natural")))
 
@@ -774,6 +857,15 @@ and duration-log @var{log}."
       (- y-center (ly:grob-relative-coordinate me y-ref Y))))))
 
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; offset callbacks
+
+(define-public (pure-chain-offset-callback grob start end prev-offset)
+  "Sometimes, a chained offset callback is unpure and there is
+   no way to write a pure function that estimates its behavior.
+   In this case, we use a pure equivalent that will simply pass
+   the previous calculated offset value."
+  prev-offset)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -954,6 +1046,14 @@ between the two text elements."
     (ly:grob-property grob 'dot-placement-list))))
 
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; slurs
+
+(define-public slur::height
+  (ly:make-unpure-pure-container
+    ly:slur::height
+    ly:slur::pure-height))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; scripts
 
@@ -1069,6 +1169,14 @@ between the two text elements."
      (interval-center extent))))
 
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; axis group interface
+
+(define-public axis-group-interface::height
+  (ly:make-unpure-pure-container
+    ly:axis-group-interface::height
+    ly:axis-group-interface::pure-height))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; ambitus
 
@@ -1111,3 +1219,13 @@ between the two text elements."
 (define-public (laissez-vibrer::print grob)
  (ly:tie::print grob))
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; volta-bracket
+
+(define-public (volta-bracket-interface::pure-height grob start end)
+  (let ((edge-height (ly:grob-property grob 'edge-height)))
+    (if (number-pair? edge-height)
+       (let ((smaller (min (car edge-height) (cdr edge-height)))
+             (larger (max (car edge-height) (cdr edge-height))))
+         (interval-union '(0 . 0) (cons smaller larger)))
+       '(0 . 0))))