]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/page-breaking.cc
Docs xref checking: append rather than prepend Documentation/ to search path
[lilypond.git] / lily / page-breaking.cc
index e03a5c97c154f6a2576378fe1cb4e3b74fae4fd3..e064a81f086b1506ff2cc3f6d6974dc8094171f2 100644 (file)
@@ -1,10 +1,20 @@
 /*
-  page-breaking.cc -- implement a superclass and utility
-  functions shared by various page-breaking algorithms
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
+  Copyright (C) 2006--2009 Joe Neeman <joeneeman@gmail.com>
 
-  (c) 2006--2009 Joe Neeman <joeneeman@gmail.com>
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
@@ -89,8 +99,10 @@ compress_lines (const vector<Line_details> &orig)
        {
          Line_details const &old = ret.back ();
          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 () + old.padding_;
+         compressed.extent_[UP] = old.extent_[UP] + orig[i].extent_.length () + padding;
          compressed.space_ += old.space_;
          compressed.inverse_hooke_ += old.inverse_hooke_;
 
@@ -488,14 +500,7 @@ Page_breaking::create_system_list ()
     {
       if (Paper_score *ps = dynamic_cast<Paper_score*> (unsmob_music_output (scm_car (s))))
        {
-         SCM system_count = ps->layout ()->c_variable ("system-count");
-
-         if (scm_is_number (system_count))
-           s = scm_append (scm_list_3 (scm_list_1 (scm_car (s)),
-                                       scm_vector_to_list (ps->get_paper_systems ()),
-                                       scm_cdr (s)));
-         else
-           system_specs_.push_back (System_spec (ps));
+         system_specs_.push_back (System_spec (ps));
        }
       else
         {
@@ -520,8 +525,25 @@ Page_breaking::find_chunks_and_breaks (Break_predicate is_break)
     {
       if (system_specs_[i].pscore_)
        {
-         vector<Grob*> cols
-           = system_specs_[i].pscore_->root_system ()->used_columns ();
+         vector<Grob*> cols;
+
+         SCM system_count = system_specs_[i].pscore_->layout ()->c_variable ("system-count");
+         if (scm_is_number (system_count))
+           {
+             // With system-count given, the line configuration for
+             // this score is fixed.  We need to ensure that chunk
+             // boundaries only occur at line breaks.
+             Constrained_breaking breaking (system_specs_[i].pscore_);
+             vector<Line_details> details = breaking.line_details (0, VPOS, scm_to_int (system_count));
+
+             cols.push_back (system_specs_[i].pscore_->root_system ()->used_columns ()[0]);
+             for (vsize j = 0; j < details.size (); j++)
+               cols.push_back (details[j].last_column_);
+           }
+         else
+           cols = system_specs_[i].pscore_->root_system ()->used_columns ();
+
+         int last_chunk_idx = 0;
          vector<vsize> line_breaker_columns;
          line_breaker_columns.push_back (0);
 
@@ -535,10 +557,22 @@ Page_breaking::find_chunks_and_breaks (Break_predicate is_break)
                                                       cols[j],
                                                       last);
 
+             // NOTE: even in the breaks_ list, forced_line_count_
+             // refers to the number of lines between a
+             // Break_position and the start of that /chunk/.  This
+             // is needed for system_count_bounds to work correctly,
+             // since it mixes Break_positions from breaks_ and
+             // chunks_.
+             if (scm_is_number (system_count))
+               cur_pos.forced_line_count_ = j - last_chunk_idx;
+
              if (break_point || (i == system_specs_.size () - 1 && last))
                breaks_.push_back (cur_pos);
              if (chunk_end || last)
-               chunks_.push_back (cur_pos);
+               {
+                 chunks_.push_back (cur_pos);
+                 last_chunk_idx = j;
+               }
 
              if ((break_point || chunk_end) && !last)
                line_breaker_columns.push_back (j);
@@ -614,7 +648,10 @@ Page_breaking::system_count_bounds (vector<Break_position> const &chunks,
   for (vsize i = 0; i + 1 < chunks.size (); i++)
     {
       vsize sys = next_system (chunks[i]);
-      if (system_specs_[sys].pscore_)
+
+      if (chunks[i+1].forced_line_count_)
+       ret[i] = chunks[i+1].forced_line_count_;
+      else if (system_specs_[sys].pscore_)
        {
          vsize start;
          vsize end;
@@ -697,7 +734,10 @@ Page_breaking::set_to_ideal_line_configuration (vsize start, vsize end)
   for (vsize i = 0; i+1 < current_chunks_.size (); i++)
     {
       vsize sys = next_system (current_chunks_[i]);
-      if (system_specs_[sys].pscore_)
+
+      if (current_chunks_[i+1].forced_line_count_)
+       div.push_back (current_chunks_[i+1].forced_line_count_);
+      else if (system_specs_[sys].pscore_)
        {
          line_breaker_args (sys, current_chunks_[i], current_chunks_[i+1], &start, &end);
          div.push_back (line_breaking_[sys].best_solution (start, end).size ());
@@ -723,11 +763,6 @@ Page_breaking::cache_line_details (vsize configuration_index)
   if (cached_configuration_index_ != configuration_index)
     {
       cached_configuration_index_ = configuration_index;
-      Real padding = 0;
-      SCM spacing_spec = book_->paper_->c_variable ("between-system-spacing");
-      SCM page_breaking_spacing_spec = book_->paper_->c_variable ("page-breaking-between-system-spacing");
-      Page_layout_problem::read_spacing_spec (spacing_spec, &padding, ly_symbol2scm ("padding"));
-      Page_layout_problem::read_spacing_spec (page_breaking_spacing_spec, &padding, ly_symbol2scm ("padding"));
 
       Line_division &div = current_configurations_[configuration_index];
       uncompressed_line_details_.clear ();
@@ -746,10 +781,7 @@ Page_breaking::cache_line_details (vsize configuration_index)
          else
            {
              assert (div[i] == 1);
-             uncompressed_line_details_.push_back (Line_details (system_specs_[sys].prob_));
-             uncompressed_line_details_.back ().padding_ =
-                robust_scm2double (system_specs_[sys].prob_->get_property ("next-padding"),
-                                   padding);
+             uncompressed_line_details_.push_back (Line_details (system_specs_[sys].prob_, book_->paper_));
            }
        }
       cached_line_details_ = compress_lines (uncompressed_line_details_);
@@ -821,8 +853,12 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
   for (vsize i = 0; i < cached_line_details_.size (); i++)
     {
       Real ext_len = cached_line_details_[i].extent_.length ();
-      Real next_rod_height = cur_rod_height + ext_len
-       + ((cur_rod_height > 0) ? cached_line_details_[i].padding_: 0);
+      Real padding = 0;
+      if (cur_rod_height > 0)
+       padding = cached_line_details_[i].title_ ?
+         cached_line_details_[i-1].title_padding_ : cached_line_details_[i-1].padding_;
+
+      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)
        + min_whitespace_at_bottom_of_page (cached_line_details_[i]);
@@ -1338,9 +1374,9 @@ Page_breaking::last_break_position () const
 Real
 Page_breaking::min_whitespace_at_top_of_page (Line_details const &line) const
 {
-  SCM first_system_spacing = book_->paper_->c_variable ("first-system-spacing");
+  SCM first_system_spacing = book_->paper_->c_variable ("top-system-spacing");
   if (line.title_)
-    first_system_spacing = book_->paper_->c_variable ("first-system-title-spacing");
+    first_system_spacing = book_->paper_->c_variable ("top-title-spacing");
 
   Real min_distance = -infinity_f;
   Real padding = 0;
@@ -1359,7 +1395,7 @@ Page_breaking::min_whitespace_at_top_of_page (Line_details const &line) const
 Real
 Page_breaking::min_whitespace_at_bottom_of_page (Line_details const &line) const
 {
-  SCM last_system_spacing = book_->paper_->c_variable ("last-system-spacing");
+  SCM last_system_spacing = book_->paper_->c_variable ("bottom-system-spacing");
   Real min_distance = -infinity_f;
   Real padding = 0;