]> 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
   /* 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
      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_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_padding_ = 0;
+  before_title_min_distance_ = 0;
 
   Output_def *l = pscore_->layout ();
 
   SCM spacing_spec = l->c_variable ("between-system-spacing");
 
   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"));
   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 (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);
 
   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);
   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;
 
   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);
                         || 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->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_;
 }
   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"));
   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;
 
   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"));
   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
 }
 
 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 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_;
   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_;
   bool last_markup_line_;
   bool first_markup_line_;
   bool tight_spacing_;
+  Real first_refpoint_offset_;
 
   Line_details ()
   {
 
   Line_details ()
   {
@@ -80,6 +83,8 @@ struct Line_details {
     padding_ = 0;
     title_padding_ = 0;
     bottom_padding_ = 0;
     padding_ = 0;
     title_padding_ = 0;
     bottom_padding_ = 0;
+    min_distance_ = 0;
+    title_min_distance_ = 0;
     space_ = 0;
     inverse_hooke_ = 1;
     tight_spacing_ = false;
     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;
     last_markup_line_ = false;
     first_markup_line_ = false;
     tallness_ = 0;
+    first_refpoint_offset_ = 0;
   }
 
   Line_details (Prob *pb, Output_def *paper);
   }
 
   Line_details (Prob *pb, Output_def *paper);
@@ -150,9 +156,14 @@ private:
   vsize systems_;
   bool ragged_right_;
   bool ragged_last_;
   vsize systems_;
   bool ragged_right_;
   bool ragged_last_;
+
+  Real between_system_min_distance_;
+  Real between_system_padding_;
   Real between_system_space_;
   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 before_title_padding_;
-  Real between_system_padding_;
 
   /* the (i,j)th entry is the configuration for breaking between
     columns i and j */
 
   /* 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];
          /*
          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);
          */
          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_;
 
          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_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];
   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;
       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++)
     {
 
   for (vsize i = 0; i < cached_line_details_.size (); i++)
     {
-      Real padding = 0;
       Real ext_len;
       if (cur_rod_height > 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
       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]);
       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;
     }
       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_;
 
   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)
 {
 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 ();
     last_line_ = line;
 
   rod_height_ -= first_line_.full_height ();