]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix 1112.
authorJoe Neeman <joeneeman@gmail.com>
Mon, 14 Jun 2010 16:30:55 +0000 (19:30 +0300)
committerJoe Neeman <joeneeman@gmail.com>
Tue, 13 Jul 2010 22:52:38 +0000 (15:52 -0700)
Add support for minimum-distance into the page-breaker.

input/regression/page-breaking-min-distance.ly [new file with mode: 0644]
lily/constrained-breaking.cc
lily/include/constrained-breaking.hh
lily/page-breaking.cc
lily/page-spacing.cc

diff --git a/input/regression/page-breaking-min-distance.ly b/input/regression/page-breaking-min-distance.ly
new file mode 100644 (file)
index 0000000..ad8dbdb
--- /dev/null
@@ -0,0 +1,18 @@
+\version "2.13.22"
+
+\header {
+  texidoc = "minimum-distance is correctly accounted for in page breaking."
+}
+
+\book {
+  \paper {
+    between-scores-system-spacing #'minimum-distance = #'20
+    paper-height = 8\cm
+  }
+
+  \score { c'1 }
+  \score { c'1 }
+  \score { c'1 }
+  \score { c'1 }
+}
+
index 8e08d1fc87dc25d81924b53c6d92692b1612da51..0779c133a1d807e73ad3a3485ce0165f4cfb39b1 100644 (file)
@@ -383,30 +383,51 @@ Constrained_breaking::initialize ()
   /* NOTE: currently, we aren't using the space_ field of a
      Line_details for anything.  That's because the approximations
      used for scoring a page configuration don't actually space things
-     properly (for speed reasong) using springs anchored at the staff
+     properly (for speed reasons) using springs anchored at the staff
      refpoints.  Rather, the "space" is placed between the extent
      boxes.  To get a good result, therefore, the "space" value for
      page breaking needs to be much smaller than the "space" value for
-     page layout.  Currently, we just make it zero always.
+     page layout.  Currently, we just make it zero always, which means
+     that we will always prefer a tighter vertical layout.
   */
   between_system_space_ = 0;
   between_system_padding_ = 0;
+  between_system_min_distance_ = 0;
+  between_scores_system_padding_ = 0;
+  between_scores_system_min_distance_ = 0;
   before_title_padding_ = 0;
+  before_title_min_distance_ = 0;
 
   Output_def *l = pscore_->layout ();
 
   SCM spacing_spec = l->c_variable ("between-system-spacing");
+  SCM between_scores_spec = l->c_variable ("between-scores-system-spacing");
   SCM title_spec = l->c_variable ("before-title-spacing");
   SCM page_breaking_spacing_spec = l->c_variable ("page-breaking-between-system-spacing");
   Page_layout_problem::read_spacing_spec (spacing_spec,
                                          &between_system_padding_,
                                          ly_symbol2scm ("padding"));
+  Page_layout_problem::read_spacing_spec (between_scores_spec,
+                                         &between_scores_system_padding_,
+                                         ly_symbol2scm ("padding"));
   Page_layout_problem::read_spacing_spec (page_breaking_spacing_spec,
                                          &between_system_padding_,
                                          ly_symbol2scm ("padding"));
   Page_layout_problem::read_spacing_spec (title_spec,
                                          &before_title_padding_,
                                          ly_symbol2scm ("padding"));
+  Page_layout_problem::read_spacing_spec (between_scores_spec,
+                                         &between_scores_system_min_distance_,
+                                         ly_symbol2scm ("minimum-distance"));
+  Page_layout_problem::read_spacing_spec (spacing_spec,
+                                         &between_system_min_distance_,
+                                         ly_symbol2scm ("minimum-distance"));
+  Page_layout_problem::read_spacing_spec (page_breaking_spacing_spec,
+                                         &between_system_min_distance_,
+                                         ly_symbol2scm ("minimum-distance"));
+  Page_layout_problem::read_spacing_spec (title_spec,
+                                         &before_title_min_distance_,
+                                         ly_symbol2scm ("minimum-distance"));
 
   Interval first_line = line_dimensions_int (pscore_->layout (), 0);
   Interval other_lines = line_dimensions_int (pscore_->layout (), 1);
@@ -460,6 +481,7 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v
   System *sys = pscore_->root_system ();
   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);
+  bool last = (end == breaks_.size () - 1);
 
   Grob *c = all_[breaks_[end]];
   out->last_column_ = c;
@@ -486,8 +508,10 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v
                         || 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->padding_ = last ? between_scores_system_padding_ : between_system_padding_;
   out->title_padding_ = before_title_padding_;
+  out->min_distance_ = last ? between_scores_system_min_distance_ : between_system_min_distance_;
+  out->title_min_distance_ = before_title_min_distance_;
   out->space_ = between_system_space_;
   out->inverse_hooke_ = out->full_height () + between_system_space_;
 }
@@ -509,6 +533,8 @@ Line_details::Line_details (Prob *pb, Output_def *paper)
   title_padding_ = 0;
   Page_layout_problem::read_spacing_spec (spec, &padding_, ly_symbol2scm ("padding"));
   Page_layout_problem::read_spacing_spec (title_spec, &title_padding_, ly_symbol2scm ("padding"));
+  Page_layout_problem::read_spacing_spec (spec, &min_distance_, ly_symbol2scm ("minimum-distance"));
+  Page_layout_problem::read_spacing_spec (title_spec, &title_min_distance_, ly_symbol2scm ("minimum-distance"));
 
   last_column_ = 0;
   force_ = 0;
@@ -532,6 +558,7 @@ 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);
   tight_spacing_ = to_boolean (pb->get_property ("tight-spacing"));
+  first_refpoint_offset_ = 0;
 }
 
 Real
index fbe12eb05be5e6a81f018a9844911649a30326e2..c461859f7c92e6a549ddeb5d8bc8bb4602f1dab8 100644 (file)
@@ -49,6 +49,8 @@ struct Line_details {
   Real padding_;  /* compulsory space after this system (if we're not
                     last on a page) */
   Real title_padding_;
+  Real min_distance_;
+  Real title_min_distance_;
   Real bottom_padding_;
   Real space_;    /* spring length */
   Real inverse_hooke_;
@@ -72,6 +74,7 @@ struct Line_details {
   bool last_markup_line_;
   bool first_markup_line_;
   bool tight_spacing_;
+  Real first_refpoint_offset_;
 
   Line_details ()
   {
@@ -80,6 +83,8 @@ struct Line_details {
     padding_ = 0;
     title_padding_ = 0;
     bottom_padding_ = 0;
+    min_distance_ = 0;
+    title_min_distance_ = 0;
     space_ = 0;
     inverse_hooke_ = 1;
     tight_spacing_ = false;
@@ -95,6 +100,7 @@ struct Line_details {
     last_markup_line_ = false;
     first_markup_line_ = false;
     tallness_ = 0;
+    first_refpoint_offset_ = 0;
   }
 
   Line_details (Prob *pb, Output_def *paper);
@@ -150,9 +156,14 @@ private:
   vsize systems_;
   bool ragged_right_;
   bool ragged_last_;
+
+  Real between_system_min_distance_;
+  Real between_system_padding_;
   Real between_system_space_;
+  Real between_scores_system_min_distance_;
+  Real between_scores_system_padding_;
+  Real before_title_min_distance_;
   Real before_title_padding_;
-  Real between_system_padding_;
 
   /* the (i,j)th entry is the configuration for breaking between
     columns i and j */
index 83ffd90fd584a5e4f6a708ca0ac8f7d0137a74f3..aeeb7bb1b7eb555db4f37ea162524178d72c8050 100644 (file)
@@ -100,17 +100,17 @@ compress_lines (const vector<Line_details> &orig)
          Line_details const &old = ret.back ();
          Line_details compressed = orig[i];
          /*
-           "padding" is the padding below the current line.  The padding below
-           "old" (taking into account whether "old" is a title) is already
-           accounted for in the extent of the compressed line.  The padding
-           below the compressed line, therefore, should depend on whether its
-           bottom-most line is a title or not.
+           We must account for the padding between the lines that we are compressing.
+           The padding values come from "old," which is the upper system here. Note
+           the meaning of tight-spacing: if a system has tight-spacing, then the padding
+           _before_ it is ignored.
          */
          Real padding = 0;
          if (!orig[i].tight_spacing_)
            padding = orig[i].title_ ? old.title_padding_ : old.padding_;
 
          compressed.shape_ = old.shape_.piggyback (orig[i].shape_, padding);
+         compressed.first_refpoint_offset_ += compressed.shape_.rest_[UP] - old.shape_.rest_[UP];
          compressed.space_ += old.space_;
          compressed.inverse_hooke_ += old.inverse_hooke_;
 
@@ -858,19 +858,38 @@ Page_breaking::compute_line_heights ()
   Real prev_hanging = 0;
   Real prev_hanging_begin = 0;
   Real prev_hanging_rest = 0;
+  Real prev_refpoint_hanging = 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];
+      bool title = cached_line_details_[i].title_;
+      Real refpoint_hanging = max (prev_hanging_begin + a, prev_hanging_rest + b);
+
+      if (i > 0)
+       {
+         Real padding = 0;
+         if (!cached_line_details_[i].tight_spacing_)
+           padding = title
+             ? cached_line_details_[i-1].title_padding_
+             : cached_line_details_[i-1].padding_;
+         Real min_dist = title
+           ? cached_line_details_[i-1].title_min_distance_
+           : cached_line_details_[i-1].min_distance_;
+         refpoint_hanging = max (refpoint_hanging + padding,
+                                 prev_refpoint_hanging + min_dist
+                                 + cached_line_details_[i].first_refpoint_offset_);
+       }
+
+      Real hanging_begin = refpoint_hanging - shape.begin_[DOWN];
+      Real hanging_rest = refpoint_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;
+      prev_refpoint_hanging = refpoint_hanging;
     }
 }
 
@@ -892,21 +911,13 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
 
   for (vsize i = 0; i < cached_line_details_.size (); i++)
     {
-      Real padding = 0;
       Real ext_len;
       if (cur_rod_height > 0)
-        {
-          if (!cached_line_details_[i].tight_spacing_)
-            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_;
-        }
+       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;
+       ext_len = cached_line_details_[i].full_height();
+
+      Real next_rod_height = cur_rod_height + ext_len;
       Real next_spring_height = cur_spring_height + cached_line_details_[i].space_;
       Real next_height = next_rod_height + (ragged () ? next_spring_height : 0)
        + min_whitespace_at_bottom_of_page (cached_line_details_[i]);
index 4120afb514116df57c7ecd5450f2a11ee4680120..33cf18a3fe8a64f52821229f96a3bd73e407ab1c 100644 (file)
@@ -56,8 +56,7 @@ Page_spacing::append_system (const Line_details &line)
       rod_height_ += line.full_height ();
       first_line_ = line;
     }
-  if (!line.tight_spacing_)
-    rod_height_ += line.title_ ? last_line_.title_padding_ : last_line_.padding_;
+
   spring_len_ += line.space_;
   inverse_spring_k_ += line.inverse_hooke_;
 
@@ -69,9 +68,7 @@ Page_spacing::append_system (const Line_details &line)
 void
 Page_spacing::prepend_system (const Line_details &line)
 {
-  if (rod_height_ && !first_line_.tight_spacing_)
-    rod_height_ += first_line_.title_ ? line.title_padding_ : line.padding_;
-  else
+  if (!rod_height_)
     last_line_ = line;
 
   rod_height_ -= first_line_.full_height ();