]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix 1053.
authorBoris Shingarov <b1@shingarov.com>
Thu, 22 Apr 2010 20:35:38 +0000 (13:35 -0700)
committerJoe Neeman <joeneeman@gmail.com>
Thu, 22 Apr 2010 20:37:50 +0000 (13:37 -0700)
Adds the begin-of-line/rest-of-line hack for spacing between systems,
as well as within them.

lily/constrained-breaking.cc
lily/include/constrained-breaking.hh
lily/include/page-breaking.hh
lily/include/system.hh
lily/page-breaking.cc
lily/page-spacing.cc
lily/system.cc

index 0db98ccaafb90d2efb779f4f10002656400f584f..a22e105e4d5715e0277d057d2a85ee58404384cf 100644 (file)
@@ -458,7 +458,8 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v
   int start_rank = Paper_column::get_rank (all_[breaks_[start]]);
   int end_rank = Paper_column::get_rank (all_[breaks_[end]]);
   System *sys = pscore_->root_system ();
-  Interval extent = sys->pure_height (sys, start_rank, end_rank);
+  Interval begin_of_line_extent = sys->begin_of_line_pure_height (start_rank, end_rank);
+  Interval rest_of_line_extent = sys->rest_of_line_pure_height (start_rank, end_rank);
 
   Grob *c = all_[breaks_[end]];
   out->last_column_ = c;
@@ -476,20 +477,19 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v
   out->turn_permission_ = min_permission (out->page_permission_,
                                          out->turn_permission_);
 
-  // TODO: see the hack regarding begin_of_line and
-  // rest_of_line extents in align-interface.  Perhaps we
-  // should do the same thing here so that the effect extends
-  // between systems as well as within systems.  It isn't as
-  // crucial here, however, because the effect is largest when
-  // dealing with large systems.
-  out->extent_ = (extent.is_empty ()
-                 || isnan (extent[LEFT])
-                 || isnan (extent[RIGHT]))
-    ? Interval (0, 0) : extent;
+  begin_of_line_extent = (begin_of_line_extent.is_empty ()
+                         || isnan (begin_of_line_extent[LEFT])
+                         || isnan (begin_of_line_extent[RIGHT]))
+    ? Interval (0, 0) : begin_of_line_extent;
+  rest_of_line_extent = (rest_of_line_extent.is_empty ()
+                        || isnan (rest_of_line_extent[LEFT])
+                        || isnan (rest_of_line_extent[RIGHT]))
+    ? Interval (0, 0) : rest_of_line_extent;
+  out->shape_ = Line_shape (begin_of_line_extent, rest_of_line_extent);
   out->padding_ = between_system_padding_;
   out->title_padding_ = before_title_padding_;
   out->space_ = between_system_space_;
-  out->inverse_hooke_ = extent.length () + between_system_space_;
+  out->inverse_hooke_ = out->full_height () + between_system_space_;
 }
 
 Real
@@ -512,7 +512,9 @@ Line_details::Line_details (Prob *pb, Output_def *paper)
 
   last_column_ = 0;
   force_ = 0;
-  extent_ = unsmob_stencil (pb->get_property ("stencil")) ->extent (Y_AXIS);
+  Interval stencil_extent = unsmob_stencil (pb->get_property ("stencil"))->extent (Y_AXIS);
+  shape_ = Line_shape (stencil_extent, stencil_extent); // pretend it goes all the way across
+  tallness_ = 0;
   bottom_padding_ = 0;
   space_ = 0.0;
   inverse_hooke_ = 1.0;
@@ -530,3 +532,33 @@ Line_details::Line_details (Prob *pb, Output_def *paper)
   SCM first_scm = pb->get_property ("first-markup-line");
   first_markup_line_ = to_boolean (first_scm);
 }
+
+Real
+Line_details::full_height () const
+{
+  Interval ret;
+  ret.unite(shape_.begin_);
+  ret.unite(shape_.rest_);
+  return ret.length();
+}
+
+Real
+Line_details::tallness () const
+{
+  return tallness_;
+}
+
+Line_shape::Line_shape (Interval begin, Interval rest)
+{
+  begin_ = begin;
+  rest_ = rest;
+}
+
+Line_shape
+Line_shape::piggyback (Line_shape mount, Real padding) const
+{
+  Real elevation = max (begin_[UP]-mount.begin_[DOWN], rest_[UP]-mount.rest_[DOWN]);
+  Interval begin = Interval (begin_[DOWN], elevation + mount.begin_[UP] + padding);
+  Interval rest = Interval (rest_[DOWN], elevation + mount.rest_[UP] + padding);
+  return Line_shape (begin, rest);
+}
index e6d898e6a0903e7623143a508c17bfe880aab1ce..ff848537490f29c8365a5d79ad43116ec35197bd 100644 (file)
 #include "matrix.hh"
 #include "prob.hh"
 
+/*
+ * Begin/rest-of-line hack.  This geometrical shape is a crude approximation
+ * of Skyline, but it is better than a rectangle.
+ */
+struct Line_shape
+{
+  Interval begin_;
+  Interval rest_;
+
+  Line_shape ()
+  {
+  }
+  Line_shape (Interval begin, Interval rest);
+  Line_shape piggyback (Line_shape mount, Real padding) const;
+};
+
 struct Line_details {
   Grob *last_column_;
   Real force_;
-  Interval extent_;   /* Y-extent of the system */
+  Line_shape shape_;
+  Real tallness_; /* Y-extent, adjusted according to begin/rest-of-line*/
 
   Real padding_;  /* compulsory space after this system (if we're not
                     last on a page) */
@@ -75,9 +92,12 @@ struct Line_details {
     compressed_nontitle_lines_count_ = 1;
     last_markup_line_ = false;
     first_markup_line_ = false;
+    tallness_ = 0;
   }
 
   Line_details (Prob *pb, Output_def *paper);
+  Real full_height () const;
+  Real tallness () const;
 };
 
 /*
index b643a11c9cc9bc5b4fea3857f5e5f9c5dbd2a4c6..3c4076c0daa79ae9d63afa1c015f9870b5b4015a 100644 (file)
@@ -189,6 +189,7 @@ private:
   vsize current_end_breakpoint_;
 
   void cache_line_details (vsize configuration_index);
+  void compute_line_heights ();
   void clear_line_details_cache ();
   vsize cached_configuration_index_;
   vector<Line_details> cached_line_details_;
index 509a65db2c5dbbb1afc31ca57dd1afe01d794bec..b8fa6644d43b3359ffbe81badeeba0e37be996c7 100644 (file)
@@ -65,9 +65,15 @@ public:
   void typeset_grob (Grob *);
   void pre_processing ();
 
+  Interval begin_of_line_pure_height (vsize start, vsize end);
+  Interval rest_of_line_pure_height (vsize start, vsize end);
+
 protected:
   virtual void derived_mark () const;
   virtual Grob *clone () const;
+
+private:
+  Interval part_of_line_pure_height (vsize start, vsize end, bool begin);
 };
 
 void set_loose_columns (System *which, Column_x_positions const *posns);
index 7dbac44278ef34c2f9cd0073c599932306c5212f..0ef1a309e9e5531b904fed613b4f583ac128323d 100644 (file)
@@ -101,8 +101,7 @@ compress_lines (const vector<Line_details> &orig)
          Line_details compressed = orig[i];
          Real padding = orig[i].title_ ? old.title_padding_ : old.padding_;
 
-         compressed.extent_[DOWN] = old.extent_[DOWN];
-         compressed.extent_[UP] = old.extent_[UP] + orig[i].extent_.length () + padding;
+         compressed.shape_ = old.shape_.piggyback (orig[i].shape_, padding);
          compressed.space_ += old.space_;
          compressed.inverse_hooke_ += old.inverse_hooke_;
 
@@ -836,6 +835,28 @@ Page_breaking::line_divisions_rec (vsize system_count,
     }
 }
 
+void
+Page_breaking::compute_line_heights ()
+{
+  Real prev_hanging = 0;
+  Real prev_hanging_begin = 0;
+  Real prev_hanging_rest = 0;
+  for (vsize i = 0; i < cached_line_details_.size (); i++)
+    {
+      Line_shape shape = cached_line_details_[i].shape_;
+      Real a = shape.begin_[UP];
+      Real b = shape.rest_[UP];
+      Real midline_hanging = max (prev_hanging_begin + a, prev_hanging_rest + b);
+      Real hanging_begin = midline_hanging - shape.begin_[DOWN];
+      Real hanging_rest = midline_hanging - shape.rest_[DOWN];
+      Real hanging = max (hanging_begin, hanging_rest);
+      cached_line_details_[i].tallness_ = hanging - prev_hanging;
+      prev_hanging = hanging;
+      prev_hanging_begin = hanging_begin;
+      prev_hanging_rest = hanging_rest;
+    }
+}
+
 vsize
 Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
 {
@@ -847,18 +868,26 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
   int line_count = 0;
 
   cache_line_details (configuration);
+  compute_line_heights ();
 
   if (cached_line_details_.size ())
     cur_page_height -= min_whitespace_at_top_of_page (cached_line_details_[0]);
 
   for (vsize i = 0; i < cached_line_details_.size (); i++)
     {
-      Real ext_len = cached_line_details_[i].extent_.length ();
       Real padding = 0;
+      Real ext_len;
       if (cur_rod_height > 0)
-       padding = cached_line_details_[i].title_ ?
-         cached_line_details_[i-1].title_padding_ : cached_line_details_[i-1].padding_;
-
+        {
+          padding = cached_line_details_[i].title_ ?
+            cached_line_details_[i-1].title_padding_ :
+            cached_line_details_[i-1].padding_;
+          ext_len = cached_line_details_[i].tallness_;
+        }
+      else
+        {
+          ext_len = cached_line_details_[i].full_height();
+        }
       Real next_rod_height = cur_rod_height + ext_len + padding;
       Real next_spring_height = cur_spring_height + cached_line_details_[i].space_;
       Real next_height = next_rod_height + (ragged () ? next_spring_height : 0)
@@ -871,7 +900,7 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
              && cached_line_details_[i-1].page_permission_ == ly_symbol2scm ("force")))
        {
          line_count = cached_line_details_[i].compressed_nontitle_lines_count_;
-         cur_rod_height = ext_len;
+         cur_rod_height = cached_line_details_[i].full_height();
          cur_spring_height = cached_line_details_[i].space_;
          page_starter = i;
 
@@ -909,7 +938,7 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
   if (!too_few_lines (line_count - cached_line_details_.back ().compressed_nontitle_lines_count_)
       && cur_height > cur_page_height
       /* don't increase the page count if the last page had only one system */
-      && cur_rod_height > cached_line_details_.back ().extent_.length ())
+      && cur_rod_height > cached_line_details_.back ().full_height ())
     ret++;
 
   assert (ret <= cached_line_details_.size ());
@@ -1388,7 +1417,8 @@ Page_breaking::min_whitespace_at_top_of_page (Line_details const &line) const
                                          ly_symbol2scm ("padding"));
 
   // FIXME: take into account the height of the header
-  return max (0.0, max (padding, min_distance - line.extent_[UP]));
+  Real translate = max (line.shape_.begin_[UP], line.shape_.rest_[UP]);
+  return max (0.0, max (padding, min_distance - translate));
 }
 
 Real
@@ -1406,7 +1436,8 @@ Page_breaking::min_whitespace_at_bottom_of_page (Line_details const &line) const
                                          ly_symbol2scm ("padding"));
 
   // FIXME: take into account the height of the footer
-  return max (0.0, max (padding, min_distance + line.extent_[DOWN]));
+  Real translate = min (line.shape_.begin_[DOWN], line.shape_.rest_[DOWN]);
+  return max (0.0, max (padding, min_distance + translate));
 }
 
 int
index f78cc1795aef00d30b5811557d5269c1846fab25..ee9fbb3ee10b3748ea95e238c02809296d020467 100644 (file)
@@ -47,12 +47,16 @@ Page_spacing::resize (Real new_height)
 void
 Page_spacing::append_system (const Line_details &line)
 {
-  if (!rod_height_)
-    first_line_ = line;
-
+  if (rod_height_)
+    {
+      rod_height_ += line.tallness_;
+    }
+  else
+    {
+      rod_height_ += line.full_height ();
+      first_line_ = line;
+    }
   rod_height_ += line.title_ ? last_line_.title_padding_ : last_line_.padding_;
-
-  rod_height_ += line.extent_.length ();
   spring_len_ += line.space_;
   inverse_spring_k_ += line.inverse_hooke_;
 
@@ -69,7 +73,9 @@ Page_spacing::prepend_system (const Line_details &line)
   else
     last_line_ = line;
 
-  rod_height_ += line.extent_.length ();
+  rod_height_ -= first_line_.full_height ();
+  rod_height_ += first_line_.tallness_;
+  rod_height_ += line.full_height();
   spring_len_ += line.space_;
   inverse_spring_k_ += line.inverse_hooke_;
 
index 1be38ea570ab8520b531eb6ff02a9eee032fdbba..f938b8322e744377ef68488ee137fd64e521b09f 100644 (file)
@@ -570,6 +570,43 @@ System::get_extremal_staff (Direction dir, Interval const &iv)
   return 0;
 }
 
+Interval
+System::part_of_line_pure_height (vsize start, vsize end, bool begin)
+{
+  Grob *alignment = get_vertical_alignment ();
+  if (!alignment)
+    {
+      programming_error("system does not have a vertical alignment");
+      return Interval();
+    }
+  extract_grob_set (alignment, "elements", staves);
+  vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+
+  Interval ret;
+  for (vsize i = 0; i < staves.size(); ++i)
+    {
+      Interval iv = begin?
+        Axis_group_interface::begin_of_line_pure_height (staves[i], start) :
+        Axis_group_interface::rest_of_line_pure_height (staves[i], start, end);
+      if (i<offsets.size())
+        iv.translate (offsets[i]);
+      ret.unite (iv);
+    }
+  return ret;
+}
+
+Interval
+System::begin_of_line_pure_height (vsize start, vsize end)
+{
+  return part_of_line_pure_height (start, end, true);
+}
+
+Interval
+System::rest_of_line_pure_height (vsize start, vsize end)
+{
+  return part_of_line_pure_height (start, end, false);
+}
+
 ADD_INTERFACE (System,
               "This is the top-level object: Each object in a score"
               " ultimately has a @code{System} object as its X and"