]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'master' of git+ssh://jneem@git.sv.gnu.org/srv/git/lilypond
authorJoe Neeman <joeneeman@gmail.com>
Mon, 18 Dec 2006 18:59:33 +0000 (20:59 +0200)
committerJoe Neeman <joeneeman@gmail.com>
Mon, 18 Dec 2006 18:59:33 +0000 (20:59 +0200)
13 files changed:
lily/accidental-placement.cc
lily/align-interface.cc
lily/axis-group-interface.cc
lily/dynamic-engraver.cc
lily/include/accidental-placement.hh
lily/include/axis-group-interface.hh
lily/include/separation-item.hh
lily/include/skyline.hh
lily/script-column.cc
lily/separation-item.cc
lily/skyline.cc
scm/define-grob-properties.scm
scm/define-grobs.scm

index f6bfefff5d944ca100b370bb9e1cdcb9133166ea..6aaf49b2e6ea12c11ab32370de72453f9a9f85ed 100644 (file)
@@ -75,6 +75,24 @@ Accidental_placement::split_accidentals (Grob *accs,
       }
 }
 
+vector<Grob*>
+Accidental_placement::get_break_reminder_accidentals (vector<Grob*> const &elts, Grob *left)
+{
+  vector<Grob*> br;
+  vector<Grob*> ra;
+  vector<Grob*> ret;
+
+  if (dynamic_cast<Item *> (left)->break_status_dir () != RIGHT)
+    return vector<Grob*> ();
+
+  for (vsize i = 0; i < elts.size (); i++)
+    {
+      split_accidentals (elts[i], &br, &ra);
+      ret.insert (ret.end (), br.begin (), br.end ());
+    }
+  return ret;
+}
+
 /*
   Accidentals are special, because they appear and disappear after
   ties at will.
index f2eacf7608893e0c964511a87c812494bc6ec623..2f23220c5a1bfe518f3b5998b8c063101eb54835 100644 (file)
@@ -123,28 +123,71 @@ Align_interface::align_to_fixed_distance (Grob *me, Axis a)
       v.unite (Interval (where, where));
     }
 
-  /*
-    TODO: support self-alignment-{Y, X}
-  */
   for (vsize i = 0; i < translates.size (); i++)
     elems[i]->translate_axis (translates[i] - v.center (), a);
 }
 
-/*
-  Hairy function to put elements where they should be. Can be tweaked
-  from the outside by setting extra-space in its
-  children
-
-  We assume that the children the refpoints of the children are still
-  found at 0.0 -- we will fuck up with thresholds if children's
-  extents are already moved to locations such as (-16, -8), since the
-  dy needed to put things in a row doesn't relate to the distances
-  between original refpoints.
-
-  TODO: maybe we should rethink and throw out thresholding altogether.
-  The original function has been taken over by
-  align_to_fixed_distance ().
-*/
+/* for each grob, find its upper and lower skylines. If the grob has
+   an empty extent, delete it from the list instead. If the extent is
+   non-empty but there is no skyline available (or pure is true), just
+   create a flat skyline from the bounding box */
+static void
+get_skylines (Grob *me,
+             vector<Grob*> *const elements,
+             Axis a,
+             bool pure, int start, int end,
+             vector<Skyline_pair> *const ret)
+{
+  Grob *other_axis_common = common_refpoint_of_array (*elements, me, other_axis (a));
+  for (vsize i = elements->size (); i--;)
+    {
+      Grob *g = (*elements)[i];
+      Interval extent = g->maybe_pure_extent (g, a, pure, start, end);
+      Interval other_extent = pure ? Interval (-infinity_f, infinity_f)
+       : g->extent (other_axis_common, other_axis (a));
+      Box b = (a == X_AXIS) ? Box (extent, other_extent) : Box (other_extent, extent);
+      
+      if (extent.is_empty ())
+       {
+         elements->erase (elements->begin () + i);
+         continue;
+       }
+
+      Skyline_pair skylines;
+      if (!pure
+         && Skyline_pair::unsmob (g->get_property ("skylines")))
+       skylines = *Skyline_pair::unsmob (g->get_property ("skylines"));
+      else
+       {
+         if (!pure)
+           programming_error ("no skylines for alignment-child\n");
+         
+         skylines = Skyline_pair (b, 0, other_axis (a));
+       }
+
+      /* each skyline is calculated relative to (potentially) a different other_axis
+        coordinate. In order to compare the skylines effectively, we need to shift them
+        to some absolute reference point */
+      if (!pure)
+       {
+         /* this is perhaps an abuse of minimum-?-extent: maybe we should create
+            another property? But it seems that the only (current) use of
+            minimum-Y-extent is to separate vertically-aligned elements */
+         SCM min_extent = g->get_property (a == X_AXIS ? "minimum-X-extent" : "minimum-Y-extent");
+         if (is_number_pair (min_extent))
+           {
+             b[a] = ly_scm2interval (min_extent);
+             skylines.insert (b, 0, other_axis (a));
+           }
+         Real offset = g->relative_coordinate (other_axis_common, other_axis (a));
+         skylines.shift (-offset);
+       }
+
+
+      ret->push_back (skylines);
+    }
+  reverse (*ret);
+}
 
 vector<Real>
 Align_interface::get_extents_aligned_translates (Grob *me,
@@ -169,63 +212,29 @@ Align_interface::get_extents_aligned_translates (Grob *me,
   Direction stacking_dir = robust_scm2dir (me->get_property ("stacking-dir"),
                                           DOWN);
 
-  Interval threshold = robust_scm2interval (me->get_property ("threshold"),
-                                           Interval (0, Interval::infinity ()));
+  vector<Grob*> elems (all_grobs); // writable copy
+  vector<Skyline_pair> skylines;
 
-  vector<Interval> dims;
-  vector<Grob*> elems;
+  get_skylines (me, &elems, a, pure, start, end, &skylines);
 
-  for (vsize i = 0; i < all_grobs.size (); i++)
-    {
-      Interval y = all_grobs[i]->maybe_pure_extent (all_grobs[i], a, pure, start, end);
-      if (!y.is_empty ())
-       {
-         Grob *e = dynamic_cast<Grob *> (all_grobs[i]);
-
-         elems.push_back (e);
-         dims.push_back (y);
-       }
-    }
-
-  /*
-    Read self-alignment-X and self-alignment-Y. This may seem like
-    code duplication. (and really: it is), but this is necessary to
-    prevent ugly cyclic dependencies that arise when you combine
-    self-alignment on a child with alignment of children.
-  */
-  SCM align ((a == X_AXIS)
-            ? me->get_property ("self-alignment-X")
-            : me->get_property ("self-alignment-Y"));
-
-  Interval total;
   Real where = 0;
-  Real extra_space = 0.0;
   SCM extra_space_handle = scm_assq (ly_symbol2scm ("alignment-extra-space"), line_break_details);
+  Real extra_space = robust_scm2double (scm_is_pair (extra_space_handle)
+                                       ? scm_cdr (extra_space_handle)
+                                       : SCM_EOL,
+                                       0.0);
 
-  extra_space = robust_scm2double (scm_is_pair (extra_space_handle)
-                                  ? scm_cdr (extra_space_handle)
-                                  : SCM_EOL,
-                                  extra_space);
-
-  Real padding = robust_scm2double (me->get_property ("padding"),
-                                   0.0);
+  Real padding = robust_scm2double (me->get_property ("padding"), 0.0);
   vector<Real> translates;
   for (vsize j = 0; j < elems.size (); j++)
     {
-      Real dy = -dims[j][-stacking_dir];
-      if (j)
-       dy += dims[j - 1][stacking_dir];
-
-      /*
-       we want dy to be > 0
-      */
-      dy *= stacking_dir;
-      if (j)
-       dy = min (max (dy, threshold[SMALLER]), threshold[BIGGER]);
-
+      Real dy = 0;
+      if (j == 0)
+       dy = skylines[j][-stacking_dir].max_height ();
+      else
+       dy = skylines[j-1][stacking_dir].distance (skylines[j][-stacking_dir]);
 
       where += stacking_dir * (dy + padding + extra_space / elems.size ());
-      total.unite (dims[j] + where);
       translates.push_back (where);
     }
 
@@ -243,25 +252,16 @@ Align_interface::get_extents_aligned_translates (Grob *me,
        }
     }
 
-  
-  Real center_offset = 0.0;
-  
-  /*
-    also move the grobs that were empty, to maintain spatial order.
-  */
   vector<Real> all_translates;
-  if (translates.size ())
+
+  if (!translates.empty ())
     {
       Real w = translates[0];
-
-      if (scm_is_number (align))
-       center_offset = total.linear_combination (scm_to_double (align));
-
       for  (vsize i = 0, j = 0; j < all_grobs.size (); j++)
        {
          if (i < elems.size () && all_grobs[j] == elems[i])
            w = translates[i++];
-         all_translates.push_back (w - center_offset);
+         all_translates.push_back (w);
        }
     }
   return all_translates;
index 9149f667bc42443cee407e82373b8078af67ae64..4319bb8b92cd0594311142bed40928dddeec28ae 100644 (file)
@@ -179,13 +179,54 @@ Axis_group_interface::pure_height (SCM smob, SCM start_scm, SCM end_scm)
 
   return pure_group_height (me, start, end);
 }
+
+MAKE_SCHEME_CALLBACK (Axis_group_interface, calc_skylines, 1);
+SCM
+Axis_group_interface::calc_skylines (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  extract_grob_set (me, "elements", elts);
+  return skyline_spacing (me, elts).smobbed_copy ();
+}
+
+/* whereas calc_skylines calculates skylines for axis-groups with a lot of
+   visible children, combine_skylines is designed for axis-groups whose only
+   children are other axis-groups (ie. VerticalAlignment). Rather than
+   calculating all the skylines from scratch, we just merge the skylines
+   of the children.
+*/
+MAKE_SCHEME_CALLBACK (Axis_group_interface, combine_skylines, 1);
+SCM
+Axis_group_interface::combine_skylines (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  extract_grob_set (me, "elements", elements);
+  Grob *y_common = common_refpoint_of_array (elements, me, Y_AXIS);
+
+  assert (y_common == me);
+
+  Skyline_pair ret;
+  for (vsize i = 0; i < elements.size (); i++)
+    {
+      SCM skyline_scm = elements[i]->get_property ("skylines");
+      if (Skyline_pair::unsmob (skyline_scm))
+       {
+         Real offset = elements[i]->relative_coordinate (y_common, Y_AXIS);
+         Skyline_pair other = *Skyline_pair::unsmob (skyline_scm);
+         other.raise (offset);
+         ret.merge (other);
+       }
+    }
+  return ret.smobbed_copy ();
+}
   
 SCM
 Axis_group_interface::generic_group_extent (Grob *me, Axis a)
 {
+  /* trigger the callback to do skyline-spacing on the children */
+  (void) me->get_property ("skylines");
+
   extract_grob_set (me, "elements", elts);
-  if (a == Y_AXIS && to_boolean (me->get_property ("skyline-spacing")))
-    skyline_spacing (me, elts);
   Grob *common = common_refpoint_of_array (elts, me, a);
 
   Real my_coord = me->relative_coordinate (common, a);
@@ -258,8 +299,8 @@ Axis_group_interface::get_children (Grob *me, vector<Grob*> *found)
 bool
 staff_priority_less (Grob * const &g1, Grob * const &g2)
 {
-  int priority_1 = robust_scm2int (g1->get_property ("outside-staff-priority"), INT_MIN);
-  int priority_2 = robust_scm2int (g2->get_property ("outside-staff-priority"), INT_MIN);
+  Real priority_1 = robust_scm2double (g1->get_property ("outside-staff-priority"), -infinity_f);
+  Real priority_2 = robust_scm2double (g2->get_property ("outside-staff-priority"), -infinity_f);
 
   if (priority_1 < priority_2)
     return true;
@@ -307,7 +348,7 @@ add_boxes (Grob *me, Grob *x_common, Grob *y_common, vector<Box> *const boxes)
    edge of the just-placed grob).  Otherwise, we skip it until the next pass.
 */
 static void
-add_grobs_of_one_priority (Drul_array<Skyline> *const skylines,
+add_grobs_of_one_priority (Skyline_pair *const skylines,
                           vector<Grob*> elements,
                           Grob *x_common,
                           Grob *y_common)
@@ -354,7 +395,7 @@ add_grobs_of_one_priority (Drul_array<Skyline> *const skylines,
                  elements[i]->translate_axis (dir*dist, Y_AXIS);
                }
              (*skylines)[dir].insert (b, 0, X_AXIS);
-             elements[i]->del_property ("outside-staff-padding");
+             elements[i]->set_property ("outside-staff-priority", SCM_BOOL_F);
              last_affected_position[dir] = b[X_AXIS][RIGHT];
            }
          elements.erase (elements.begin () + i);
@@ -362,13 +403,15 @@ add_grobs_of_one_priority (Drul_array<Skyline> *const skylines,
     }
 }
 
-void
+Skyline_pair
 Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements)
 {
   vector_sort (elements, staff_priority_less);
   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);
+
   vsize i = 0;
   vector<Box> boxes;
 
@@ -376,8 +419,7 @@ Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements)
         && !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++)
     add_boxes (elements[i], x_common, y_common, &boxes);
 
-  Drul_array<Skyline> skylines (Skyline (boxes, 0, X_AXIS, DOWN),
-                               Skyline (boxes, 0, X_AXIS, UP));
+  Skyline_pair skylines (boxes, 0, X_AXIS);
   for (; i < elements.size (); i++)
     {
       SCM priority = elements[i]->get_property ("outside-staff-priority");
@@ -389,6 +431,7 @@ Axis_group_interface::skyline_spacing (Grob *me, vector<Grob*> elements)
 
       add_grobs_of_one_priority (&skylines, current_elts, x_common, y_common);
     }
+  return skylines;
 }
 
 ADD_INTERFACE (Axis_group_interface,
@@ -400,6 +443,6 @@ ADD_INTERFACE (Axis_group_interface,
               "elements "
               "common-refpoint-of-elements "
               "pure-relevant-elements "
-              "skyline-spacing "
+              "skylines "
               "cached-pure-extents "
               );
index 5c3d0feecdf2627da0f4ffca841dc5ef864298a9..8f64db11363add6c9653bacb8efed2f7cc0a9254 100644 (file)
@@ -64,7 +64,6 @@ class Dynamic_engraver : public Engraver
 
   TRANSLATOR_DECLARATIONS (Dynamic_engraver);
   DECLARE_ACKNOWLEDGER (accidental);
-  DECLARE_ACKNOWLEDGER (script);
   DECLARE_ACKNOWLEDGER (stem_tremolo);
   DECLARE_ACKNOWLEDGER (note_column);
   DECLARE_ACKNOWLEDGER (slur);
@@ -454,27 +453,7 @@ Dynamic_engraver::acknowledge_note_column (Grob_info info)
     finished_cresc_->set_bound (RIGHT, info.grob ());
 }
 
-void
-Dynamic_engraver::acknowledge_script (Grob_info info)
-{
-  if (!line_spanner_ || !script_)
-    return;
-
-  SCM p = info.grob ()->get_property ("script-priority");
-
-  /*
-    UGH.
-
-    DynamicText doesn't really have a script-priority field.
-  */
-  if (scm_is_number (p)
-      && scm_to_int (p)
-      < scm_to_int (script_->get_property ("script-priority")))
-    Side_position_interface::add_support (line_spanner_, info.grob ());
-}
-
 ADD_ACKNOWLEDGER (Dynamic_engraver, accidental);
-ADD_ACKNOWLEDGER (Dynamic_engraver, script);
 ADD_ACKNOWLEDGER (Dynamic_engraver, note_column);
 ADD_ACKNOWLEDGER (Dynamic_engraver, slur);
 ADD_ACKNOWLEDGER (Dynamic_engraver, stem_tremolo);
index c34fc0b76615ca275e21bd36a18abf2f52ebb5ae..5d09bdc2df699cfbd555051536c434db5b39d589 100644 (file)
@@ -18,6 +18,8 @@ public:
   DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element));
   static void add_accidental (Grob *, Grob *);
 
+  static vector<Grob*> get_break_reminder_accidentals (vector<Grob*> const &elts,
+                                                      Grob *left);
   static Interval get_relevant_accidental_extent (Grob *me,
                                                  Item *item_col,
                                                  Grob *acc);
index b38537c661adb815447b0ad0912f46a73922e5e9..4272b1a8901acaa2a8678dee0f5ebad2c00c070d 100644 (file)
@@ -12,6 +12,7 @@
 #include "std-vector.hh"
 #include "lily-proto.hh"
 #include "grob-interface.hh"
+#include "skyline.hh"
 
 struct Axis_group_interface
 {
@@ -20,6 +21,8 @@ struct Axis_group_interface
   DECLARE_SCHEME_CALLBACK (width, (SCM smob));
   DECLARE_SCHEME_CALLBACK (height, (SCM smob));
   DECLARE_SCHEME_CALLBACK (pure_height, (SCM smob, SCM start, SCM end));
+  DECLARE_SCHEME_CALLBACK (calc_skylines, (SCM smob));
+  DECLARE_SCHEME_CALLBACK (combine_skylines, (SCM smob));
   static Interval relative_group_extent (vector<Grob*> const &list,
                                         Grob *common, Axis);
   static Interval relative_pure_height (Grob *me, vector<Grob*> const &list,
@@ -28,7 +31,7 @@ struct Axis_group_interface
   static Interval cached_pure_height (Grob *me, vector<Grob*> const &list,
                                      Grob *common, int, int);
 
-  static void skyline_spacing (Grob *me, vector<Grob*> elements);
+  static Skyline_pair skyline_spacing (Grob *me, vector<Grob*> elements);
   static void add_element (Grob *me, Grob *);
   static void set_axes (Grob *, Axis, Axis);
   static bool has_axis (Grob *, Axis);
index ca63294852c86626712be3d2cf31209ee7fcbfc3..4fb59b5e6209ed16549db80de4c0615fe71a025e 100644 (file)
 #include "lily-proto.hh"
 #include "direction.hh"
 #include "grob-interface.hh"
+#include "skyline.hh"
 
 struct Separation_item
 {
   DECLARE_GROB_INTERFACE();
   DECLARE_SCHEME_CALLBACK(calc_skylines, (SCM));
 
-  static vector<Box> boxes (Grob *me);
-  static Interval conditional_width (Grob *, Grob *);
+  static vector<Box> boxes (Grob *me, Grob *left);
+  static Skyline conditional_skyline (Grob *, Grob *);
   static Interval width (Grob *);
   static Interval relative_width (Grob *, Grob *);
   static Grob *extremal_break_aligned_grob (Grob *, Direction, Interval *);
index 7f3130ecab09f770c4f9c7e4538d501d47ca94b4..36fd9d23e4aff9d2489602c4e8e5e808341abf86 100644 (file)
@@ -28,6 +28,7 @@ struct Building
 
   void precompute ();
   Building (Real start, Real start_height, Real end_height, Real end);
+  Building (Box const &b, Real horizon_padding, Axis a, Direction d);
   void print () const;
 
   Real height (Real x) const;
@@ -35,6 +36,7 @@ struct Building
   void leading_part (Real chop);
   bool conceals_beginning (Building const &other) const;
   bool conceals (Building const &other) const;
+  bool sane () const;
   Building sloped_neighbour (Real horizon_padding, Direction d) const;
 };
 
@@ -55,16 +57,36 @@ public:
   Skyline (Skyline const &src);
   Skyline (Direction sky);
   Skyline (vector<Box> const &bldgs, Real horizon_padding, Axis a, Direction sky);
+  Skyline (Box const &b, Real horizon_padding, Axis a, Direction sky);
   vector<Offset> to_points () const;
   void merge (Skyline const &);
   void insert (Box const &, Real horizon_padding, Axis);
   void print () const;
   void raise (Real);
+  void shift (Real);
   Real distance (Skyline const &) const;
   Real height (Real airplane) const;
   Real max_height () const;
   void set_minimum_height (Real height);
 };
 
+class Skyline_pair
+{
+private:
+  Drul_array<Skyline> skylines_;
+
+  DECLARE_SIMPLE_SMOBS(Skyline_pair);
+public:
+  Skyline_pair ();
+  Skyline_pair (vector<Box> const &boxes, Real horizon_padding, Axis a);
+  Skyline_pair (Box const &, Real horizon_padding, Axis a);
+  void raise (Real);
+  void shift (Real);
+  void insert (Box const &, Real horizon_padding, Axis);
+  void merge (Skyline_pair const &other);
+  Skyline &operator [] (Direction d);
+  Skyline const &operator [] (Direction d) const;
+};
+
 #endif /* SKYLINE_HH */
 
index 726b32727623e1bd4193b66d713dcf39c47f906b..a8fc0c3fc4c9c2067b6f68a86ede5e8c8c8be512 100644 (file)
@@ -133,7 +133,19 @@ Script_column::order_grobs (vector<Grob*> grobs)
        {
          Grob *g = unsmob_grob (scm_car (s));
          if (last)
-           Side_position_interface::add_support (g, last);
+           {
+             SCM outside_staff = last->get_property ("outside-staff-priority");
+             if (scm_is_number (outside_staff))
+               {
+                 /* we allow the outside-staff-priority ordering to override the
+                    script-priority ordering */
+                 if (!scm_is_number (g->get_property ("outside-staff-priority")))
+                   g->set_property ("outside-staff-priority",
+                                    scm_from_double (scm_to_double (outside_staff) + 0.1));
+               }
+             else
+               Side_position_interface::add_support (g, last);
+           }
 
          last = g;
        }
index 20de8fbbd57b6816723815e66c71753dbddd78b0..0a6c085afcf41a7f1f433f9f4b1a2cf319c0792a 100644 (file)
@@ -31,17 +31,12 @@ void
 Separation_item::set_skyline_distance (Drul_array<Item *> items,
                                       Real padding)
 {
-  Drul_array<Skyline*> lines;
-  Direction d = LEFT;
-
-  do
-    {
-      SCM prop = items[d]->get_property ("skylines");
-      lines[d] = Skyline::unsmob (index_get_cell (prop, -d));
-    }
-  while (flip (&d) != LEFT);
-
-  Real dist = padding + lines[LEFT]->distance (*lines[RIGHT]);
+  Drul_array<Skyline_pair*> lines (Skyline_pair::unsmob (items[LEFT]->get_property ("skylines")),
+                                  Skyline_pair::unsmob (items[RIGHT]->get_property ("skylines")));
+  Skyline right = conditional_skyline (items[RIGHT], items[LEFT]);
+  right.merge ((*lines[RIGHT])[LEFT]);
+  
+  Real dist = padding + (*lines[LEFT])[RIGHT].distance (right);
   if (dist > 0)
     {
       Rod rod;
@@ -57,63 +52,19 @@ bool
 Separation_item::set_distance (Drul_array<Item *> items,
                               Real padding)
 {
-  if (!Item::is_non_musical (items[LEFT])
-      && !Item::is_non_musical (items[RIGHT]))
-    {
-      set_skyline_distance (items, padding);
-      return true;
-    }
-  
-  Interval li (Separation_item::width (items[LEFT]));
-  Interval ri (Separation_item::conditional_width (items[RIGHT], items[LEFT]));
-  if (!li.is_empty () && !ri.is_empty ())
-    {
-      Rod rod;
-
-      rod.item_drul_ = items;
-
-      rod.distance_ = li[RIGHT] - ri[LEFT] + padding;
-
-      if (rod.distance_  > 0)
-       rod.add_to_cols ();
-      return true;
-    }
-  return false;
+  set_skyline_distance (items, padding);
+  return true;
 }
 
 /*
   Return the width of ME given that we are considering the object on
   the LEFT.
 */
-Interval
-Separation_item::conditional_width (Grob *me, Grob *left)
+Skyline
+Separation_item::conditional_skyline (Grob *me, Grob *left)
 {
-  Interval w = width (me);
-
-  Item *item = dynamic_cast<Item *> (me);
-  Paper_column *pc = item->get_column ();
-
-  extract_grob_set (me, "conditional-elements", elts);
-  for (vsize i = 0; i < elts.size (); i++)
-    {
-      Item *il = dynamic_cast<Item *> (elts[i]);
-      if (pc != il->get_column ())
-       {
-         programming_error ("Separation_item element from wrong column");
-         continue;
-       }
-
-      if (to_boolean (il->get_property ("no-spacing-rods")))
-       continue;
-
-      if (Accidental_placement::has_interface (il))
-       w.unite (Accidental_placement::get_relevant_accidental_extent (il, pc, left));
-    }
-
-  SCM pad = me->get_property ("padding");
-
-  w.widen (robust_scm2double (pad, 0.0));
-  return w;
+  vector<Box> bs = boxes (me, left);
+  return Skyline (bs, 0.1, Y_AXIS, LEFT);
 }
 
 
@@ -122,31 +73,31 @@ SCM
 Separation_item::calc_skylines (SCM smob)
 {
   Item *me = unsmob_item (smob);
-  SCM lines = scm_cons (SCM_BOOL_F,SCM_BOOL_F);
-
-  Direction d = LEFT;
-  vector<Box> bs = boxes (me);
-  do
-    {
-      /* todo: the horizon_padding is somewhat arbitrary */
-      Skyline l (bs, 0.1, Y_AXIS, d);
-      index_set_cell (lines, d, l.smobbed_copy ());
-    }
-  while (flip (&d) != LEFT);
-
-  return lines;
+  vector<Box> bs = boxes (me, 0);
+  /* todo: the horizon_padding is somewhat arbitrary */
+  return Skyline_pair (bs, 0.1, Y_AXIS).smobbed_copy ();
 }
 
-
+/* if left is non-NULL, get the boxes corresponding to the
+   conditional-elements (conditioned on the grob LEFT). This
+   sounds more general than it is: conditional-elements are
+   always accidentals attached to a tied note.
+*/
 vector<Box>
-Separation_item::boxes (Grob *me)
+Separation_item::boxes (Grob *me, Grob *left)
 {
   Item *item = dynamic_cast<Item *> (me);
 
   int very_large = INT_MAX;
   Paper_column *pc = item->get_column ();
   vector<Box> out;
-  extract_grob_set (me, "elements", elts);
+  extract_grob_set (me, left ? "conditional-elements" : "elements", read_only_elts);
+  vector<Grob*> elts;
+
+  if (left)
+    elts = Accidental_placement::get_break_reminder_accidentals (read_only_elts, left);
+  else
+    elts = read_only_elts;
 
   Grob *ycommon = common_refpoint_of_array (elts, me, Y_AXIS);
   
@@ -162,9 +113,12 @@ Separation_item::boxes (Grob *me)
        continue;
 
       Interval y (il->pure_height (ycommon, 0, very_large));
-      Box b (il->extent (pc, X_AXIS), y);
+      Interval x (il->extent (pc, X_AXIS));
 
-      out.push_back (b);
+      SCM padding = elts[i]->get_property ("padding");
+      x.widen (robust_scm2double (padding, 0));
+      out.push_back (Box (x, y));
     }
 
   return out;      
@@ -174,39 +128,7 @@ Interval
 Separation_item::width (Grob *me)
 {
   SCM sw = me->get_property ("X-extent");
-  if (is_number_pair (sw))
-    return ly_scm2interval (sw);
-
-  Item *item = dynamic_cast<Item *> (me);
-  Paper_column *pc = item->get_column ();
-  Interval w;
-
-  extract_grob_set (me, "elements", elts);
-  for (vsize i = 0; i < elts.size (); i++)
-    {
-      Item *il = dynamic_cast<Item *> (elts[i]);
-      if (pc != il->get_column ())
-       {
-         /* this shouldn't happen, but let's continue anyway. */
-         programming_error ("Separation_item:  I've been drinking too much");
-         continue;             /*UGH UGH*/
-       }
-
-      if (to_boolean (il->get_property ("no-spacing-rods")))
-       continue;
-
-      Interval iv (il->extent (pc, X_AXIS));
-      if (!iv.is_empty ())
-       w.unite (iv);
-    }
-
-  SCM pad = me->get_property ("padding");
-
-  w.widen (robust_scm2double (pad, 0.0));
-
-  me->set_property ("X-extent", ly_interval2scm (w));
-
-  return w;
+  return ly_scm2interval (sw);
 }
 
 Interval
index ab877f28ce605fcb4854984c049885007007c47d..6b53a62ef845174c290f8ea02462afb156392e1a 100644 (file)
@@ -111,6 +111,19 @@ Building::Building (Real start, Real start_height, Real end_height, Real end)
   precompute ();
 }
 
+Building::Building (Box const &b, Real horizon_padding, Axis horizon_axis, Direction sky)
+{
+  Real height = sky * b[other_axis (horizon_axis)][sky];
+
+  iv_ = b[horizon_axis];
+  iv_.widen (horizon_padding + EPS);
+  height_[LEFT] = height;
+  height_[RIGHT] = height;
+
+  if (sane ())
+    precompute ();
+}
+
 void
 Building::precompute ()
 {
@@ -174,6 +187,14 @@ Building::sloped_neighbour (Real horizon_padding, Direction d) const
   return Building (left, left_height, right_height, right);
 }
 
+bool
+Building::sane () const
+{
+  return approx_less_than (iv_[LEFT], iv_[RIGHT])
+    && !isinf (height_[RIGHT])
+    && !isinf (height_[LEFT]);
+}
+
 static void
 skyline_trailing_part (list<Building> *sky, Real x)
 {
@@ -341,14 +362,9 @@ Skyline::Skyline (vector<Box> const &boxes, Real horizon_padding, Axis horizon_a
 
   for (vsize i = 0; i < boxes.size (); i++)
     {
-      Interval iv = boxes[i][horizon_axis];
-      Real height = sky * boxes[i][other_axis (horizon_axis)][sky];
-      
-      iv.widen (horizon_padding);
-      if (!iv.is_empty () && !isinf (height) && !approx_equal (iv[LEFT], iv[RIGHT]))
+      Building front (boxes[i], horizon_padding, horizon_axis, sky);
+      if (front.sane ())
        {
-         iv.widen (EPS);
-         Building front = Building (iv[LEFT], height, height, iv[RIGHT]);
          bldgs.push_front (front);
          if (horizon_padding > 0 && !isinf (front.iv_.length ()))
            {
@@ -362,6 +378,13 @@ Skyline::Skyline (vector<Box> const &boxes, Real horizon_padding, Axis horizon_a
   assert (is_legal_skyline ());
 }
 
+Skyline::Skyline (Box const &b, Real horizon_padding, Axis horizon_axis, Direction sky)
+{
+  sky_ = sky;
+  Building front (b, 0, horizon_axis, sky);
+  single_skyline (front, horizon_padding, &buildings_);
+}
+
 void
 Skyline::merge (Skyline const &other)
 {
@@ -379,14 +402,9 @@ Skyline::insert (Box const &b, Real horizon_padding, Axis a)
 {
   list<Building> other_bld;
   list<Building> my_bld;
-  Interval iv = b[a];
-  Real height = sky_ * b[other_axis (a)][sky_];
-
-  assert (!iv.is_empty ());
-  iv.widen (EPS);
 
   my_bld.splice (my_bld.begin (), buildings_);
-  single_skyline (Building (iv[LEFT], height, height, iv[RIGHT]), horizon_padding, &other_bld);
+  single_skyline (Building (b, 0, a, sky_), horizon_padding, &other_bld);
   internal_merge_skyline (&other_bld, &my_bld, &buildings_);
   assert (is_legal_skyline ());
 }
@@ -404,6 +422,17 @@ Skyline::raise (Real r)
   assert (is_legal_skyline ());
 }
 
+void
+Skyline::shift (Real r)
+{
+  list<Building>::iterator end = buildings_.end ();
+  for (list<Building>::iterator i = buildings_.begin (); i != end; i++)
+    {
+      i->iv_[LEFT] += r;
+      i->iv_[RIGHT] += r;
+    }
+}
+
 Real
 Skyline::distance (Skyline const &other) const
 {
@@ -476,6 +505,61 @@ Skyline::to_points () const
   return out;
 }
 
+Skyline_pair::Skyline_pair ()
+  : skylines_ (Skyline (DOWN), Skyline (UP))
+{
+}
+
+Skyline_pair::Skyline_pair (vector<Box> const &boxes, Real padding, Axis a)
+  : skylines_ (Skyline (boxes, padding, a, DOWN), Skyline (boxes, padding, a, UP))
+{
+}
+
+Skyline_pair::Skyline_pair (Box const &b, Real padding, Axis a)
+  : skylines_ (Skyline (b, padding, a, DOWN), Skyline (b, padding, a, UP))
+{
+}
+
+void
+Skyline_pair::raise (Real r)
+{
+  skylines_[UP].raise (r);
+  skylines_[DOWN].raise (r);
+}
+
+void
+Skyline_pair::shift (Real r)
+{
+  skylines_[UP].shift (r);
+  skylines_[DOWN].shift (r);
+}
+
+void
+Skyline_pair::insert (Box const &b, Real padding, Axis a)
+{
+  skylines_[UP].insert (b, padding, a);
+  skylines_[DOWN].insert (b, padding, a);
+}
+
+void
+Skyline_pair::merge (Skyline_pair const &other)
+{
+  skylines_[UP].merge (other[UP]);
+  skylines_[DOWN].merge (other[DOWN]);
+}
+
+Skyline&
+Skyline_pair::operator [] (Direction d)
+{
+  return skylines_[d];
+}
+
+Skyline const&
+Skyline_pair::operator [] (Direction d) const
+{
+  return skylines_[d];
+}
+
 /****************************************************************/
 
 
@@ -483,6 +567,10 @@ IMPLEMENT_SIMPLE_SMOBS (Skyline);
 IMPLEMENT_TYPE_P (Skyline, "ly:skyline?");
 IMPLEMENT_DEFAULT_EQUAL_P (Skyline);
 
+IMPLEMENT_SIMPLE_SMOBS (Skyline_pair);
+IMPLEMENT_TYPE_P (Skyline_pair, "ly:skyline-pair?");
+IMPLEMENT_DEFAULT_EQUAL_P (Skyline_pair);
+
 SCM
 Skyline::mark_smob (SCM)
 {
@@ -499,3 +587,19 @@ Skyline::print_smob (SCM s, SCM port, scm_print_state *)
 
   return 1;
 }
+
+SCM
+Skyline_pair::mark_smob (SCM)
+{
+  return SCM_EOL;
+}
+
+int
+Skyline_pair::print_smob (SCM s, SCM port, scm_print_state *)
+{
+  Skyline_pair *r = (Skyline_pair *) SCM_CELL_WORD_1 (s);
+  (void) r;
+
+  scm_puts ("#<Skyline-pair>", port);
+  return 1;
+}
index 7fe48c14c5326fd71c76722d2fe33a611f092d13..b46dc5aae7a55f641f85e6125c98dc98798a1b19 100644 (file)
@@ -349,7 +349,7 @@ note that starts here.")
 object.")
      (side-axis ,number? "If the value is #X (or equivalently 1), the object is placed horizontally next to the other object. If the value is #Y or 0, it is placed vertically.")
      (size ,number? "Size of object, relative to standard size.")
-     (skylines ,pair? "A pair of lists of (x height) pairs.")
+     (skylines ,ly:skyline-pair? "Two skylines, one above and one below this grob (or, for some grobs, to the left and to the right).")
      (slope ,number? "The slope of this object.")
      (slur-padding ,number? "Extra distance between slur and script.")
      (space-alist ,list? "A table that specifies distances between
@@ -563,8 +563,6 @@ than a whole rest.")
      (spaceable-staves ,ly:grob-array? "Objects to be spaced during page layout.")
      (skyline-distance ,number? "The distance between this staff and the next one, as determined by a skyline algorithm.")
      (skyline-horizontal-padding ,number? "For determining the vertical distance between 2 staves, it is possible to have a configuration which would result in a tight interleaving of grobs from the top staff and the bottom staff. The larger this parameter is, the farther apart the staves will be placed in such a configuration.")
-     (skyline-spacing ,boolean? "When true, this axis-group will vertically space its children
-using a skyline algorithm.")
 
      
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
index 7aad372102825fbbe3882e3a7d255cfc7b6cfed1..47ef19a696235f613e50a13b3d06eb7c7dfc0dd2 100644 (file)
      . (
        (axes . (,Y))
        (Y-extent . ,ly:axis-group-interface::height)
+       (skylines . ,ly:axis-group-interface::calc-skylines)
        (meta . ((class . Spanner)
                 (interfaces . (axis-group-interface
                                ))))))
        (font-shape . italic)
        (avoid-slur . around)
        (no-spacing-rods . #t)
-       (script-priority . 100)
        (outside-staff-priority . 250)
        (meta . ((class . Item)
                 (interfaces . (font-interface
        
        (Y-offset . ,ly:side-position-interface::y-aligned-side)
        (stencil . ,ly:text-interface::print)
-
-       ;; no Y dimensions, because of lyrics under tenor clef.
-       (Y-extent . (0 . 0))
        (font-shape . italic)
        (padding . 0.6)
        (staff-padding . 0.2)
        (axes . (0 1))
        (X-extent . ,ly:axis-group-interface::width)
        (Y-extent . ,ly:axis-group-interface::height)
-       (skyline-spacing . #t)
+       (skylines . ,ly:axis-group-interface::calc-skylines)
        (skyline-horizontal-padding . 1.0)
        (meta . ((class . System)
                 (interfaces . (system-interface
        (Y-extent . ,ly:axis-group-interface::height)
        (X-extent . ,ly:axis-group-interface::width)
        (stacking-dir . -1)
-       (padding . 0.1) 
+       (padding . 0.1)
+       (skylines . ,ly:axis-group-interface::combine-skylines)
        (meta . ((class . Spanner)
                 (interfaces . (align-interface
                                axis-group-interface))))))
        (Y-offset . ,ly:hara-kiri-group-spanner::force-hara-kiri-callback)
        (Y-extent . ,ly:hara-kiri-group-spanner::y-extent)
        (X-extent . ,ly:axis-group-interface::width)
-       (skyline-spacing . #t)
+       (skylines . ,ly:axis-group-interface::calc-skylines);
        (meta . ((class . Spanner)
                 (interfaces . (axis-group-interface
                                hara-kiri-group-spanner-interface
 
 (define pure-print-callbacks
   (list
+   ly:bar-line::print
    ly:note-head::print
    ly:accidental-interface::print
    ly:dots::print
         (ly:stencil? sten)
         (memq sten pure-print-callbacks))
        (ly:grob::stencil-height grob)
-
        '(0 . 0))))
 
 (define pure-conversions-alist