]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix 1240.
authorJoe Neeman <joeneeman@gmail.com>
Thu, 26 Aug 2010 23:28:54 +0000 (16:28 -0700)
committerJoe Neeman <joeneeman@gmail.com>
Mon, 25 Oct 2010 02:23:19 +0000 (19:23 -0700)
Include fixed spacings in the calculation of minimum spacings.

lily/align-interface.cc
lily/grob.cc
lily/include/align-interface.hh
lily/include/grob.hh
lily/include/page-layout-problem.hh
lily/include/system.hh
lily/page-layout-problem.cc
lily/system.cc

index 2385b035fdb058eb3e7c228712c4f3adac586c43..d985a869c51673bc15329bf1d4e0428fc26a820b 100644 (file)
@@ -143,10 +143,17 @@ get_skylines (Grob *me,
   reverse (*ret);
 }
 
+// If include_fixed_spacing is true, the manually fixed spacings
+// induced by stretchable=0 or alignment-distances are included
+// in the minimum translations here.  If you want to find the minimum
+// height of a system, include_fixed_spacing should be true.  If you
+// want to actually lay out the page, then it should be false (or
+// else centered dynamics will break when there is a fixed alignment).
 vector<Real>
 Align_interface::get_minimum_translations (Grob *me,
                                           vector<Grob*> const &all_grobs,
                                           Axis a,
+                                          bool include_fixed_spacing,
                                           bool pure, int start, int end)
 {
   if (!pure && a == Y_AXIS && dynamic_cast<Spanner*> (me) && !me->get_system ())
@@ -165,6 +172,7 @@ Align_interface::get_minimum_translations (Grob *me,
   Skyline down_skyline (stacking_dir);
   Real last_spaceable_element_pos = 0;
   Grob *last_spaceable_element = 0;
+  int spaceable_count = 0;
   for (vsize j = 0; j < elems.size (); j++)
     {
       Real dy = 0;
@@ -184,9 +192,12 @@ Align_interface::get_minimum_translations (Grob *me,
          if (Page_layout_problem::read_spacing_spec (spec, &min_distance, ly_symbol2scm ("minimum-distance")))
            dy = max (dy, min_distance);
 
+         if (include_fixed_spacing)
+           dy = max (dy, Page_layout_problem::get_fixed_spacing (elems[j-1], elems[j], spaceable_count, pure, start, end));
+
          if (Page_layout_problem::is_spaceable (elems[j]) && last_spaceable_element)
            {
-             // Spaceable staves may have min-distance and padding
+             // Spaceable staves may have
              // constraints coming from the previous spaceable staff
              // as well as from the previous staff.
              spec = Page_layout_problem::get_spacing_spec (last_spaceable_element, elems[j], pure, start, end);
@@ -201,6 +212,10 @@ Align_interface::get_minimum_translations (Grob *me,
                                                          &min_distance,
                                                          ly_symbol2scm ("minimum-distance")))
                dy = max (dy, min_distance + stacking_dir*(last_spaceable_element_pos - where));
+
+             if (include_fixed_spacing)
+               dy = max (dy, Page_layout_problem::get_fixed_spacing (last_spaceable_element, elems[j], spaceable_count,
+                                                                     pure, start, end));
            }
        }
 
@@ -214,6 +229,7 @@ Align_interface::get_minimum_translations (Grob *me,
 
       if (Page_layout_problem::is_spaceable (elems[j]))
        {
+         spaceable_count++;
          last_spaceable_element = elems[j];
          last_spaceable_element_pos = where;
        }
@@ -254,7 +270,7 @@ Align_interface::align_elements_to_minimum_distances (Grob *me, Axis a)
 {
   extract_grob_set (me, "elements", all_grobs);
 
-  vector<Real> translates = get_minimum_translations (me, all_grobs, a, false, 0, 0);
+  vector<Real> translates = get_minimum_translations (me, all_grobs, a, true, false, 0, 0);
   if (translates.size ())
     for (vsize j = 0; j < all_grobs.size (); j++)
       all_grobs[j]->translate_axis (translates[j], a);
@@ -264,7 +280,7 @@ Real
 Align_interface::get_pure_child_y_translation (Grob *me, Grob *ch, int start, int end)
 {
   extract_grob_set (me, "elements", all_grobs);
-  vector<Real> translates = get_minimum_translations (me, all_grobs, Y_AXIS, true, start, end);
+  vector<Real> translates = get_minimum_translations (me, all_grobs, Y_AXIS, true, true, start, end);
 
   if (translates.size ())
     {
index 882808180c6f2509cd7c807b5d22fed795f8239e..aa9c1d40f4bee450f9d2940d530719db68b3d986 100644 (file)
@@ -191,6 +191,16 @@ Grob::get_system () const
   return 0;
 }
 
+/* This version of get_system is more reliable than this->get_system ()
+   before line-breaking has been done, at which point there is only
+   one system in the whole score and we can find it just by following
+   parent pointers. */
+System *
+Grob::get_system(Grob *me)
+{
+  Grob *p = me->get_parent (X_AXIS);
+  return p ? get_system (p) : dynamic_cast<System *>(me);
+}
 
 void
 Grob::handle_broken_dependencies ()
index fc3dc12f5e33bf24f5a6d8eb7b56f3089e4aec02..3cc04272a824a51b946665d2c1858faf2d8342ac 100644 (file)
@@ -32,7 +32,8 @@ struct Align_interface
   static void align_elements_to_ideal_distances(Grob *);
   static vector<Real> get_minimum_translations (Grob *, vector<Grob*> const&,
                                                Axis a,
-                                               bool safe, int start, int end);
+                                               bool include_fixed_spacing,
+                                               bool pure, int start, int end);
   static void set_ordered (Grob *);
   static Axis axis (Grob *);
   static void add_element (Grob *, Grob *);
index 96134a05d5eafe42ab3c5135669237df64409cfb..94da56e8841bc05a5ff85d302b1dc3c4b109f4d2 100644 (file)
@@ -107,6 +107,7 @@ public:
 
   /* class hierarchy */
   virtual System *get_system () const;
+  static System *get_system (Grob *);
   virtual void do_break_processing ();
   virtual Grob *find_broken_piece (System *) const;
   virtual void discretionary_processing ();
index 0502ce86783b35fd3fd2585d579c7a54474417ca..83fab7d6167b5e33ae9456709d416576a2460f08 100644 (file)
@@ -35,6 +35,7 @@ public:
   static bool is_spaceable (Grob *g);
   static SCM get_details (Grob *g);
   static SCM get_spacing_spec (Grob *before, Grob *after, bool pure, int start, int end);
+  static Real get_fixed_spacing (Grob *before, Grob *after, int spaceable_index, bool pure, int start, int end);
 
 protected:
   void append_system (System*, Spring const&, Real padding);
index 3bc7250d6f0606ac80fbe84ae2920f3734162be2..ddaaf4ce00d59fe7a8e1788d22f61232ed157e93 100644 (file)
@@ -41,6 +41,8 @@ public:
   Paper_score *paper_score () const;
   Grob *get_vertical_alignment ();
   Grob *get_extremal_staff (Direction dir, Interval const&);
+  Grob *get_pure_bound (Direction dir, int start, int end);
+  Grob *get_maybe_pure_bound (Direction dir, bool pure, int start, int end);
   int get_rank () const;
   void do_break_substitution_and_fixup_refpoints ();
   void post_processing ();
index bf3395b2e3c82deeeb03fbb0532eb40d1a5dcd1d..7292126ddcf52ee2d3f9030304792824cc36064d 100644 (file)
@@ -190,7 +190,7 @@ Page_layout_problem::append_system (System *sys, Spring const& spring, Real padd
 
   extract_grob_set (align, "elements", all_elts);
   vector<Grob*> elts = filter_dead_elements (all_elts);
-  vector<Real> minimum_offsets = Align_interface::get_minimum_translations (align, elts, Y_AXIS,
+  vector<Real> minimum_offsets = Align_interface::get_minimum_translations (align, elts, Y_AXIS, false,
                                                                            false, 0, 0);
 
   Skyline up_skyline (UP);
@@ -627,6 +627,39 @@ Page_layout_problem::read_spacing_spec (SCM spec, Real* dest, SCM sym)
   return false;
 }
 
+// If there is a forced, fixed spacing between BEFORE and AFTER, return it.
+// Otherwise, return -infinity_f.
+// If after is spaceable, it is the (spaceable_index + 1)th spaceable grob in
+// its alignment.
+Real
+Page_layout_problem::get_fixed_spacing (Grob *before, Grob *after, int spaceable_index, bool pure, int start, int end)
+{
+  SCM spec = Page_layout_problem::get_spacing_spec (before, after, pure, start, end);
+  Real ret = -infinity_f;
+  Real stretchability = 0;
+  if (Page_layout_problem::read_spacing_spec (spec, &stretchability, ly_symbol2scm ("stretchability"))
+      && stretchability == 0)
+    Page_layout_problem::read_spacing_spec (spec, &ret, ly_symbol2scm ("space"));
+
+  // If we're pure, then paper-columns have not had their systems set,
+  // and so elts[i]->get_system () is unreliable.
+  System *sys = pure ? Grob::get_system (before) : before->get_system ();
+  Grob *left_bound = sys ? sys->get_maybe_pure_bound (LEFT, pure, start, end) : 0;
+
+  if (is_spaceable (before) && is_spaceable (after) && left_bound)
+    {
+      SCM details = left_bound->get_property ("line-break-system-details");
+      SCM manual_dists = ly_assoc_get (ly_symbol2scm ("alignment-distances"), details, SCM_EOL);
+      if (scm_is_pair (manual_dists))
+       {
+         SCM forced = robust_list_ref (spaceable_index - 1, manual_dists);
+         if (scm_is_number (forced))
+           ret = max (ret, scm_to_double (forced));
+       }
+    }
+  return ret;
+}
+
 static SCM
 add_stretchability (SCM alist, Real stretch)
 {
index 8196736eca5d007565b36d8fe035f50164ced2c5..dd3a46011f9b9cba38aba9e0a9524e4c991c93d0 100644 (file)
@@ -581,7 +581,7 @@ System::pure_refpoint_extent (vsize start, vsize end)
     return Interval ();
 
   extract_grob_set (alignment, "elements", staves);
-  vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+  vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, true, start, end);
 
   for (vsize i = 0; i < offsets.size (); ++i)
     if (Page_layout_problem::is_spaceable (staves[i]))
@@ -608,7 +608,7 @@ System::part_of_line_pure_height (vsize start, vsize end, bool begin)
     return Interval ();
 
   extract_grob_set (alignment, "elements", staves);
-  vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+  vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, true, start, end);
 
   Interval ret;
   for (vsize i = 0; i < staves.size (); ++i)
@@ -704,6 +704,29 @@ System::calc_pure_height (SCM smob, SCM start_scm, SCM end_scm)
   return ly_interval2scm (begin);
 }
 
+Grob*
+System::get_pure_bound (Direction d, int start, int end)
+{
+  vector<vsize> ranks = pscore_->get_break_ranks ();
+  vector<vsize> indices = pscore_->get_break_indices ();
+  vector<Grob*> cols = pscore_->get_columns ();
+
+  vsize target_rank = (d == LEFT ? start : end);
+  vector<vsize>::const_iterator i =
+    lower_bound (ranks.begin (), ranks.end (), target_rank, std::less<vsize> ());
+
+  if (i != ranks.end () && (*i) == target_rank)
+    return cols[indices[i - ranks.begin ()]];
+  else
+    return 0;
+}
+
+Grob*
+System::get_maybe_pure_bound (Direction d, bool pure, int start, int end)
+{
+  return pure ? get_pure_bound (d, start, end) : get_bound (d);
+}
+
 ADD_INTERFACE (System,
               "This is the top-level object: Each object in a score"
               " ultimately has a @code{System} object as its X and"