]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/axis-group-interface.cc
Doc-es: various updates.
[lilypond.git] / lily / axis-group-interface.cc
index 0d786c3a2959aa201470f761c27ee3cd6a98645d..ac6f85feb8e25bb810875d47567708194d762cd3 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 2000--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  Copyright (C) 2000--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
   LilyPond is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -51,19 +51,6 @@ Axis_group_interface::get_default_outside_staff_padding ()
   return default_outside_staff_padding_;
 }
 
-MAKE_SCHEME_CALLBACK (Axis_group_interface, cross_staff, 1);
-SCM
-Axis_group_interface::cross_staff (SCM smob)
-{
-  Grob *me = unsmob_grob (smob);
-  extract_grob_set (me, "elements", elts);
-  for (vsize i = 0; i < elts.size (); i++)
-    if (to_boolean (elts[i]->get_property ("cross-staff")))
-      return SCM_BOOL_T;
-
-  return SCM_BOOL_F;
-}
-
 void
 Axis_group_interface::add_element (Grob *me, Grob *e)
 {
@@ -94,7 +81,7 @@ Axis_group_interface::has_axis (Grob *me, Axis a)
 {
   SCM axes = me->get_property ("axes");
 
-  return (SCM_BOOL_F != scm_memq (scm_from_int (a), axes));
+  return scm_is_true (scm_memq (scm_from_int (a), axes));
 }
 
 Interval
@@ -112,10 +99,9 @@ Axis_group_interface::relative_maybe_bound_group_extent (vector<Grob *> const &e
   for (vsize i = 0; i < elts.size (); i++)
     {
       Grob *se = elts[i];
-      if (has_interface (se)
-          || !to_boolean (se->get_property ("cross-staff")))
+      if (!to_boolean (se->get_property ("cross-staff")))
         {
-          Interval dims = (bound && has_interface (se)
+          Interval dims = (bound && has_interface<Axis_group_interface> (se)
                            ? generic_bound_extent (se, common, a)
                            : se->extent (common, a));
           if (!dims.is_empty ())
@@ -164,6 +150,8 @@ Interval
 Axis_group_interface::part_of_line_pure_height (Grob *me, bool begin, int start, int end)
 {
   Spanner *sp = dynamic_cast<Spanner *> (me);
+  if (!sp)
+    return Interval (0, 0);
   SCM cache_symbol = begin
                      ? ly_symbol2scm ("begin-of-line-pure-height")
                      : ly_symbol2scm ("rest-of-line-pure-height");
@@ -235,9 +223,9 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, adjacent_pure_heights, 1)
 SCM
 Axis_group_interface::adjacent_pure_heights (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
 
-  Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
+  Grob *common = unsmob<Grob> (me->get_object ("pure-Y-common"));
   extract_grob_set (me, "pure-relevant-grobs", elts);
 
   Paper_score *ps = get_root_system (me)->paper_score ();
@@ -254,8 +242,7 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
     {
       Grob *g = elts[i];
 
-      if (to_boolean (g->get_property ("cross-staff"))
-          && !has_interface (g))
+      if (to_boolean (g->get_property ("cross-staff")))
         continue;
 
       if (!g->is_live ())
@@ -297,7 +284,7 @@ Axis_group_interface::adjacent_pure_heights (SCM smob)
 
           if (g->pure_is_visible (start, visibility_end))
             {
-              Interval dims = g->pure_height (common, start, end);
+              Interval dims = g->pure_y_extent (common, start, end);
               if (!dims.is_empty ())
                 {
                   if (rank_span[LEFT] <= start)
@@ -343,10 +330,10 @@ Axis_group_interface::relative_pure_height (Grob *me, int start, int end)
      reasonably safe to assume that if our parent is a VerticalAlignment,
      we can assume additivity and cache things nicely. */
   Grob *p = me->get_parent (Y_AXIS);
-  if (p && Align_interface::has_interface (p))
+  if (has_interface<Align_interface> (p))
     return Axis_group_interface::sum_partial_pure_heights (me, start, end);
 
-  Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
+  Grob *common = unsmob<Grob> (me->get_object ("pure-Y-common"));
   extract_grob_set (me, "pure-relevant-grobs", elts);
 
   Interval r;
@@ -357,9 +344,9 @@ Axis_group_interface::relative_pure_height (Grob *me, int start, int end)
       if (rank_span[LEFT] <= end && rank_span[RIGHT] >= start
           && g->pure_is_visible (start, end)
           && !(to_boolean (g->get_property ("cross-staff"))
-               && Stem::has_interface (g)))
+               && has_interface<Stem> (g)))
         {
-          Interval dims = g->pure_height (common, start, end);
+          Interval dims = g->pure_y_extent (common, start, end);
           if (!dims.is_empty ())
             r.unite (dims);
         }
@@ -371,7 +358,7 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, width, 1);
 SCM
 Axis_group_interface::width (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
   return generic_group_extent (me, X_AXIS);
 }
 
@@ -379,7 +366,7 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, height, 1);
 SCM
 Axis_group_interface::height (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
   return generic_group_extent (me, Y_AXIS);
 }
 
@@ -389,7 +376,7 @@ Axis_group_interface::pure_height (SCM smob, SCM start_scm, SCM end_scm)
 {
   int start = robust_scm2int (start_scm, 0);
   int end = robust_scm2int (end_scm, INT_MAX);
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
 
   /* Maybe we are in the second pass of a two-pass spacing run. In that
      case, the Y-extent of a system is already given to us */
@@ -409,7 +396,7 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_skylines, 1);
 SCM
 Axis_group_interface::calc_skylines (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
   Skyline_pair skylines = skyline_spacing (me);
   return skylines.smobbed_copy ();
 }
@@ -424,7 +411,7 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, combine_skylines, 1);
 SCM
 Axis_group_interface::combine_skylines (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
   extract_grob_set (me, "elements", elements);
   Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS);
   Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS);
@@ -436,10 +423,10 @@ Axis_group_interface::combine_skylines (SCM smob)
   for (vsize i = 0; i < elements.size (); i++)
     {
       SCM skyline_scm = elements[i]->get_property ("vertical-skylines");
-      if (Skyline_pair::unsmob (skyline_scm))
+      if (unsmob<Skyline_pair> (skyline_scm))
         {
           Real offset = elements[i]->relative_coordinate (y_common, Y_AXIS);
-          Skyline_pair other = *Skyline_pair::unsmob (skyline_scm);
+          Skyline_pair other = *unsmob<Skyline_pair> (skyline_scm);
           other.raise (offset);
           other.shift (elements[i]->relative_coordinate (x_common, X_AXIS));
           ret.merge (other);
@@ -456,7 +443,9 @@ Axis_group_interface::generic_group_extent (Grob *me, Axis a)
   /* trigger the callback to do skyline-spacing on the children */
   if (a == Y_AXIS)
     for (vsize i = 0; i < elts.size (); i++)
-      (void) elts[i]->get_property ("vertical-skylines");
+      if (!(has_interface<Stem> (elts[i])
+            && to_boolean (elts[i]->get_property ("cross-staff"))))
+        (void) elts[i]->get_property ("vertical-skylines");
 
   Grob *common = common_refpoint_of_array (elts, me, a);
 
@@ -486,12 +475,19 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_relevant_grobs, 1);
 SCM
 Axis_group_interface::calc_pure_relevant_grobs (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
+  /* TODO: Filter out elements that belong to a different Axis_group,
+     such as the tie in
+     << \new Staff=A { c'1~ \change Staff=B c'}
+        \new Staff=B { \clef bass R1 R } >>
+    because thier location relative to this Axis_group is not known before
+    page layout.  For now, we need to trap this case in calc_pure_y_common.
+  */
   return internal_calc_pure_relevant_grobs (me, "elements");
 }
 
 SCM
-Axis_group_interface::internal_calc_pure_relevant_grobs (Grob *me, string grob_set_name)
+Axis_group_interface::internal_calc_pure_relevant_grobs (Grob *me, const string &grob_set_name)
 {
   extract_grob_set (me, grob_set_name.c_str (), elts);
 
@@ -500,23 +496,33 @@ Axis_group_interface::internal_calc_pure_relevant_grobs (Grob *me, string grob_s
   for (vsize i = 0; i < elts.size (); i++)
     {
       if (elts[i] && elts[i]->is_live ())
+        relevant_grobs.push_back (elts[i]);
+      /*
+        TODO (mikesol): it is probably bad that we're reading prebroken
+        pieces from potentially suicided elements.  This behavior
+        has been in current master since at least 2.16.
+
+        We need to fully suicide all Items, meaning that their
+        prebroken pieces should not be accessible, which means that
+        Item::handle_prebroken_dependencies should only be called
+        AFTER this list is composed.  The list composition function
+        should probably not check for suicided items or NULL pointers
+        but leave that to the various methods that use it.
+      */
+      if (Item *it = dynamic_cast<Item *> (elts[i]))
         {
-          relevant_grobs.push_back (elts[i]);
-          if (Item *it = dynamic_cast<Item *> (elts[i]))
+          for (LEFT_and_RIGHT (d))
             {
-              for (LEFT_and_RIGHT (d))
-                {
-                  Item *piece = it->find_prebroken_piece (d);
-                  if (piece && piece->is_live ())
-                    relevant_grobs.push_back (piece);
-                }
+              Item *piece = it->find_prebroken_piece (d);
+              if (piece && piece->is_live ())
+                relevant_grobs.push_back (piece);
             }
         }
     }
 
   vector_sort (relevant_grobs, pure_staff_priority_less);
   SCM grobs_scm = Grob_array::make_array ();
-  unsmob_grob_array (grobs_scm)->set_array (relevant_grobs);
+  unsmob<Grob_array> (grobs_scm)->set_array (relevant_grobs);
 
   return grobs_scm;
 }
@@ -525,10 +531,16 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_y_common, 1);
 SCM
 Axis_group_interface::calc_pure_y_common (SCM smob)
 {
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
 
   extract_grob_set (me, "pure-relevant-grobs", elts);
   Grob *common = common_refpoint_of_array (elts, me, Y_AXIS);
+  if (common != me && has_interface<Align_interface> (common))
+    {
+      me->programming_error("My pure_y_common is a VerticalAlignment,"
+                            " which might contain several staves.");
+      common = me;
+    }
   if (!common)
     {
       me->programming_error ("No common parent found in calc_pure_y_common.");
@@ -556,20 +568,20 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_x_common, 1);
 SCM
 Axis_group_interface::calc_x_common (SCM grob)
 {
-  return calc_common (unsmob_grob (grob), X_AXIS);
+  return calc_common (unsmob<Grob> (grob), X_AXIS);
 }
 
 MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_y_common, 1);
 SCM
 Axis_group_interface::calc_y_common (SCM grob)
 {
-  return calc_common (unsmob_grob (grob), Y_AXIS);
+  return calc_common (unsmob<Grob> (grob), Y_AXIS);
 }
 
 Interval
 Axis_group_interface::pure_group_height (Grob *me, int start, int end)
 {
-  Grob *common = unsmob_grob (me->get_object ("pure-Y-common"));
+  Grob *common = unsmob<Grob> (me->get_object ("pure-Y-common"));
 
   if (!common)
     {
@@ -587,7 +599,7 @@ Axis_group_interface::get_children (Grob *me, vector<Grob *> *found)
 {
   found->push_back (me);
 
-  if (!has_interface (me))
+  if (!has_interface<Axis_group_interface> (me))
     return;
 
   extract_grob_set (me, "elements", elements);
@@ -634,7 +646,7 @@ pure_staff_priority_less (Grob *const &g1, Grob *const &g2)
 static void
 add_interior_skylines (Grob *me, Grob *x_common, Grob *y_common, vector<Skyline_pair> *skylines)
 {
-  if (Grob_array *elements = unsmob_grob_array (me->get_object ("elements")))
+  if (Grob_array *elements = unsmob<Grob_array> (me->get_object ("elements")))
     {
       for (vsize i = 0; i < elements->size (); i++)
         add_interior_skylines (elements->grob (i), x_common, y_common, skylines);
@@ -642,7 +654,7 @@ add_interior_skylines (Grob *me, Grob *x_common, Grob *y_common, vector<Skyline_
   else if (!scm_is_number (me->get_property ("outside-staff-priority"))
            && !to_boolean (me->get_property ("cross-staff")))
     {
-      Skyline_pair *maybe_pair = Skyline_pair::unsmob (me->get_property ("vertical-skylines"));
+      Skyline_pair *maybe_pair = unsmob<Skyline_pair> (me->get_property ("vertical-skylines"));
       if (!maybe_pair)
         return;
       if (maybe_pair->is_empty ())
@@ -672,8 +684,8 @@ avoid_outside_staff_collisions (Grob *elt,
   for (vsize j = 0; j < other_v_skylines.size (); j++)
     {
       Skyline_pair const &v_other = other_v_skylines[j];
-      Real pad = (padding + other_padding[j]);
-      Real horizon_pad = (horizon_padding + other_horizon_padding[j]);
+      Real pad = max (padding, other_padding[j]);
+      Real horizon_pad = max (horizon_padding, other_horizon_padding[j]);
 
       // We need to push elt up by at least this much to be above v_other.
       Real up = (*v_skyline)[DOWN].distance (v_other[UP], horizon_pad) + pad;
@@ -695,10 +707,10 @@ valid_outside_staff_placement_directive (Grob *me)
 {
   SCM directive = me->get_property ("outside-staff-placement-directive");
 
-  if ((directive == ly_symbol2scm ("left-to-right-greedy"))
-      || (directive == ly_symbol2scm ("left-to-right-polite"))
-      || (directive == ly_symbol2scm ("right-to-left-greedy"))
-      || (directive == ly_symbol2scm ("right-to-left-polite")))
+  if (scm_is_eq (directive, ly_symbol2scm ("left-to-right-greedy"))
+      || scm_is_eq (directive, ly_symbol2scm ("left-to-right-polite"))
+      || scm_is_eq (directive, ly_symbol2scm ("right-to-left-greedy"))
+      || scm_is_eq (directive, ly_symbol2scm ("right-to-left-polite")))
     return directive;
 
   me->warning (_f ("\"%s\" is not a valid outside-staff-placement-directive",
@@ -725,11 +737,11 @@ add_grobs_of_one_priority (Grob *me,
   SCM directive
     = valid_outside_staff_placement_directive (me);
 
-  bool l2r = ((directive == ly_symbol2scm ("left-to-right-greedy"))
-              || (directive == ly_symbol2scm ("left-to-right-polite")));
+  bool l2r = (scm_is_eq (directive, ly_symbol2scm ("left-to-right-greedy"))
+              || scm_is_eq (directive, ly_symbol2scm ("left-to-right-polite")));
 
-  bool polite = ((directive == ly_symbol2scm ("left-to-right-polite"))
-                 || (directive == ly_symbol2scm ("right-to-left-polite")));
+  bool polite = (scm_is_eq (directive, ly_symbol2scm ("left-to-right-polite"))
+                 || scm_is_eq (directive, ly_symbol2scm ("right-to-left-polite")));
 
   vector<Box> boxes;
   vector<Skyline_pair> skylines_to_merge;
@@ -762,7 +774,9 @@ add_grobs_of_one_priority (Grob *me,
         {
           Grob *elt = elements[i];
           Real padding
-            = robust_scm2double (elt->get_property ("outside-staff-padding"), 0.25);
+            = robust_scm2double (elt->get_property ("outside-staff-padding"),
+                                 Axis_group_interface
+                                 ::get_default_outside_staff_padding ());
           Real horizon_padding
             = robust_scm2double (elt->get_property ("outside-staff-horizontal-padding"), 0.0);
           Interval x_extent = elt->extent (x_common, X_AXIS);
@@ -782,8 +796,8 @@ add_grobs_of_one_priority (Grob *me,
             }
           last_end[dir] = x_extent[RIGHT];
 
-          Skyline_pair *v_orig = Skyline_pair::unsmob (elt->get_property ("vertical-skylines"));
-          if (v_orig->is_empty ())
+          Skyline_pair *v_orig = unsmob<Skyline_pair> (elt->get_property ("vertical-skylines"));
+          if (!v_orig || v_orig->is_empty ())
             continue;
 
           // Find the riders associated with this grob, and merge their
@@ -794,7 +808,7 @@ add_grobs_of_one_priority (Grob *me,
           for (GrobMapIterator j = range.first; j != range.second; j++)
             {
               Grob *rider = j->second;
-              Skyline_pair *v_rider = Skyline_pair::unsmob (rider->get_property ("vertical-skylines"));
+              Skyline_pair *v_rider = unsmob<Skyline_pair> (rider->get_property ("vertical-skylines"));
               if (v_rider)
                 {
                   Skyline_pair copy (*v_rider);
@@ -854,7 +868,7 @@ Axis_group_interface::outside_staff_ancestor (Grob *me)
 Skyline_pair
 Axis_group_interface::skyline_spacing (Grob *me)
 {
-  extract_grob_set (me, Grob_array::unsmob (me->get_object ("vertical-skyline-elements")) ? "vertical-skyline-elements" : "elements", fakeelements);
+  extract_grob_set (me, unsmob<Grob_array> (me->get_object ("vertical-skyline-elements")) ? "vertical-skyline-elements" : "elements", fakeelements);
   vector<Grob *> elements (fakeelements);
   for (vsize i = 0; i < elements.size (); i++)
     /*
@@ -882,7 +896,12 @@ Axis_group_interface::skyline_spacing (Grob *me)
   Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS);
   Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS);
 
-  assert (y_common == me);
+  if (y_common != me)
+    {
+      me->programming_error("Some of my vertical-skyline-elements"
+                            " are outside my VerticalAxisGroup.");
+      y_common = me;
+    }
 
   // A rider is a grob that is not outside-staff, but has an outside-staff
   // ancestor.  In that case, the rider gets moved along with its ancestor.
@@ -896,7 +915,7 @@ Axis_group_interface::skyline_spacing (Grob *me)
     {
       Grob *elt = elements[i];
       Grob *ancestor = outside_staff_ancestor (elt);
-      if (!ancestor)
+      if (!(to_boolean (elt->get_property ("cross-staff")) || ancestor))
         add_interior_skylines (elt, x_common, y_common, &inside_staff_skylines);
       if (ancestor)
         riders.insert (pair<Grob *, Grob *> (ancestor, elt));
@@ -927,7 +946,7 @@ Axis_group_interface::skyline_spacing (Grob *me)
       vector<Grob *> current_elts;
       current_elts.push_back (elements[i]);
       while (i + 1 < elements.size ()
-             && scm_is_eq (elements[i + 1]->get_property ("outside-staff-priority"), priority))
+             && ly_is_equal (elements[i + 1]->get_property ("outside-staff-priority"), priority))
         {
           if (!to_boolean (elements[i + 1]->get_property ("cross-staff")))
             current_elts.push_back (elements[i + 1]);
@@ -964,9 +983,9 @@ Axis_group_interface::print (SCM smob)
   if (!debug_skylines)
     return SCM_BOOL_F;
 
-  Grob *me = unsmob_grob (smob);
+  Grob *me = unsmob<Grob> (smob);
   Stencil ret;
-  if (Skyline_pair *s = Skyline_pair::unsmob (me->get_property ("vertical-skylines")))
+  if (Skyline_pair *s = unsmob<Skyline_pair> (me->get_property ("vertical-skylines")))
     {
       ret.add_stencil (Lookup::points_to_line_stencil (0.1, (*s)[UP].to_points (X_AXIS))
                        .in_color (255, 0, 255));
@@ -980,7 +999,7 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_pure_staff_staff_spacing, 3)
 SCM
 Axis_group_interface::calc_pure_staff_staff_spacing (SCM smob, SCM start, SCM end)
 {
-  return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob),
+  return calc_maybe_pure_staff_staff_spacing (unsmob<Grob> (smob),
                                               true,
                                               scm_to_int (start),
                                               scm_to_int (end));
@@ -990,7 +1009,7 @@ MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_staff_staff_spacing, 1)
 SCM
 Axis_group_interface::calc_staff_staff_spacing (SCM smob)
 {
-  return calc_maybe_pure_staff_staff_spacing (unsmob_grob (smob),
+  return calc_maybe_pure_staff_staff_spacing (unsmob<Grob> (smob),
                                               false,
                                               0,
                                               INT_MAX);
@@ -999,7 +1018,7 @@ Axis_group_interface::calc_staff_staff_spacing (SCM smob)
 SCM
 Axis_group_interface::calc_maybe_pure_staff_staff_spacing (Grob *me, bool pure, int start, int end)
 {
-  Grob *grouper = unsmob_grob (me->get_object ("staff-grouper"));
+  Grob *grouper = unsmob<Grob> (me->get_object ("staff-grouper"));
 
   if (grouper)
     {
@@ -1024,12 +1043,10 @@ ADD_INTERFACE (Axis_group_interface,
                "bound-alignment-interfaces "
                "default-staff-staff-spacing "
                "elements "
-               "max-stretch "
                "no-alignment "
                "nonstaff-nonstaff-spacing "
                "nonstaff-relatedstaff-spacing "
                "nonstaff-unrelatedstaff-spacing "
-               "outside-staff-placement-directive "
                "pure-relevant-grobs "
                "pure-relevant-items "
                "pure-relevant-spanners "
@@ -1038,7 +1055,6 @@ ADD_INTERFACE (Axis_group_interface,
                "staff-grouper "
                "staff-staff-spacing "
                "system-Y-offset "
-               "vertical-skyline-elements "
                "X-common "
                "Y-common "
               );