]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'master' of git+ssh://git.sv.gnu.org/srv/git/lilypond
authorJan Nieuwenhuizen <janneke@gnu.org>
Sun, 18 Nov 2007 10:16:07 +0000 (11:16 +0100)
committerJan Nieuwenhuizen <Jan Nieuwenhuizen janneke@gnu.org>
Sun, 18 Nov 2007 10:16:07 +0000 (11:16 +0100)
Documentation/topdocs/NEWS.tely
input/regression/page-breaking-page-count1.ly [new file with mode: 0644]
input/regression/page-breaking-page-count2.ly [new file with mode: 0644]
input/regression/page-breaking-page-count3.ly [new file with mode: 0644]
lily/axis-group-interface.cc
lily/constrained-breaking.cc
lily/include/page-breaking.hh
lily/optimal-page-breaking.cc
lily/page-breaking.cc
lily/page-spacing.cc

index fbf099e94e38752c2cf862114155c9aa6406e05f..8224a136631ac328dc59fd2c4e7716c7d099b5f0 100644 (file)
@@ -65,6 +65,10 @@ which scares away people.
 
 @end ignore
 
+@item
+It is now possible to specify, using the @code{page-count} variable in
+the paper block, the number of pages that will be used.
+
 @item
 A new page breaking function, @code{ly:minimal-breaking}, is dedicated
 to books with many pages or a lot of texts.
diff --git a/input/regression/page-breaking-page-count1.ly b/input/regression/page-breaking-page-count1.ly
new file mode 100644 (file)
index 0000000..ecbfcbb
--- /dev/null
@@ -0,0 +1,13 @@
+\version "2.11.34"
+
+\header {
+  texidoc = "The number of pages in a score can be forced by setting
+@code{page-count} in the (book-level) paper block."
+}
+
+#(set-default-paper-size "a6")
+
+\book {
+  \paper { page-count = 2}
+  \score { {c'1 c'1} }
+}
\ No newline at end of file
diff --git a/input/regression/page-breaking-page-count2.ly b/input/regression/page-breaking-page-count2.ly
new file mode 100644 (file)
index 0000000..c7e01a3
--- /dev/null
@@ -0,0 +1,14 @@
+\version "2.11.34"
+
+\header {
+  texidoc = "The number of pages in a score can be forced by setting
+@code{page-count} in the (book-level) paper block. If there are too
+few systems for the number of pages, we append blank pages."
+}
+
+#(set-default-paper-size "a6")
+
+\book {
+  \paper { page-count = 3}
+  \score { {c'1 c'1} }
+}
\ No newline at end of file
diff --git a/input/regression/page-breaking-page-count3.ly b/input/regression/page-breaking-page-count3.ly
new file mode 100644 (file)
index 0000000..5f5b8b6
--- /dev/null
@@ -0,0 +1,14 @@
+\version "2.11.34"
+
+\header {
+  texidoc = "The number of pages in a score can be forced by setting
+@code{page-count} in the (book-level) paper block. Even if there are
+too many systems for that number of pages, we will squeeze them in."
+}
+
+#(set-default-paper-size "a6")
+
+\book {
+  \paper { page-count = 1}
+  \score { { \repeat unfold 10 {c'1 \break} } }
+}
\ No newline at end of file
index 05536316bbd91e7712067a0c28dbcabe6773105e..0a82fe67131c859afd8aa95ad3df752877fb62d6 100644 (file)
@@ -97,7 +97,7 @@ Axis_group_interface::cached_pure_height (Grob *me, int start, int end)
   for (vsize i = 0; i + 1 < breaks.size (); i++)
     {
       int r = Paper_column::get_rank (cols[breaks[i]]);
-      if (r > end)
+      if (r >= end)
        break;
 
       if (r >= start)
index 0838dea0319a2397a8fea5036446bee721ce7506..1efae87e125047bdd317595a6124408fc5c98e4f 100644 (file)
@@ -265,7 +265,7 @@ Constrained_breaking::min_system_count (vsize start, vsize end)
 int
 Constrained_breaking::max_system_count (vsize start, vsize end)
 {
-  vsize brk = (end >= start_.size ()) ? breaks_.size () : starting_breakpoints_[end];
+  vsize brk = (end >= start_.size ()) ? breaks_.size () - 1 : starting_breakpoints_[end];
   return brk - starting_breakpoints_[start];
 }
 
index 18704fd36b61f68a25ee50858983078ebcc1c9c8..b14c780ba5fdf4db3101ec511608f4ae92f6073f 100644 (file)
@@ -102,6 +102,7 @@ public:
   bool is_last () const;
   Real page_height (int page_number, bool last) const;
   Real page_top_space () const;
+  vsize system_count () const;
 
 protected:
   Paper_book *book_;
@@ -149,6 +150,7 @@ private:
   bool ragged_;
   bool ragged_last_;
   Real page_top_space_;
+  vsize system_count_;
 
   vector<Line_division> current_configurations_;
   vector<Break_position> current_chunks_;
index 34ff7f1b184cb519b418c2b44f53417599a31b4d..fa1e72b31ac4ea3cc3ee14841a12450734f58753 100644 (file)
@@ -39,24 +39,38 @@ Optimal_page_breaking::solve ()
   vsize end = last_break_position ();
   vsize max_sys_count = max_system_count (0, end);
   vsize first_page_num = robust_scm2int (book_->paper_->c_variable ("first-page-number"), 1);
+  SCM forced_page_count = book_->paper_->c_variable ("page-count");
 
-  /* find out the ideal number of pages */
-  message (_ ("Finding the ideal number of pages..."));
   set_to_ideal_line_configuration (0, end);
-  
-  Page_spacing_result best = space_systems_on_best_pages (0, first_page_num);
-  vsize page_count = best.systems_per_page_.size ();
+
+  Page_spacing_result best;
+  vsize page_count = robust_scm2int (forced_page_count, 1);
   Line_division ideal_line_division = current_configuration (0);
   Line_division best_division = ideal_line_division;
+  vsize min_sys_count = 1;
+  vsize ideal_sys_count = system_count ();
+  
+  if (!scm_is_integer (forced_page_count))
+    {
+      /* find out the ideal number of pages */
+      message (_ ("Finding the ideal number of pages..."));
+  
+      best = space_systems_on_best_pages (0, first_page_num);
+      page_count = best.systems_per_page_.size ();
 
-  vsize ideal_sys_count = best.system_count ();
-  vsize min_sys_count = ideal_sys_count - best.systems_per_page_.back ();
+      ideal_sys_count = best.system_count ();
+      min_sys_count = ideal_sys_count - best.systems_per_page_.back ();
   
-  if (page_count > 1 && best.systems_per_page_[page_count - 2] > 1)
-    min_sys_count -= best.systems_per_page_[page_count - 2];
+      if (page_count > 1 && best.systems_per_page_[page_count - 2] > 1)
+       min_sys_count -= best.systems_per_page_[page_count - 2];
+    }
+  else
+    best = space_systems_on_n_pages (0, page_count, first_page_num);
 
   if (page_count == 1)
     message (_ ("Fitting music on 1 page..."));
+  else if (scm_is_integer (forced_page_count))
+    message (_f ("Fitting music on %d pages...", (int)page_count));
   else
     message (_f ("Fitting music on %d or %d pages...", (int)page_count-1, (int)page_count));
 
@@ -72,9 +86,7 @@ Optimal_page_breaking::solve ()
          vsize min_p_count = min_page_count (i, first_page_num);
          Page_spacing_result cur;
 
-         if (min_p_count > page_count)
-           continue;
-         else if (min_p_count == page_count)
+         if (min_p_count == page_count)
            cur = space_systems_on_n_pages (i, page_count, first_page_num);
          else
            cur = space_systems_on_n_or_one_more_pages (i, page_count-1, first_page_num);
index be11ffa3eaf45790b4182c8ace501426c43e64ad..d3a2762bbb350285dd3d00141976c9c235e793e8 100644 (file)
@@ -98,6 +98,7 @@ Page_breaking::next_system (Break_position const &break_pos) const
 Page_breaking::Page_breaking (Paper_book *pb, Break_predicate is_break)
 {
   book_ = pb;
+  system_count_ = 0;
   ragged_ = to_boolean (pb->paper_->c_variable ("ragged-bottom"));
   ragged_last_ = to_boolean (pb->paper_->c_variable ("ragged-last-bottom"));
   page_top_space_ = robust_scm2double (pb->paper_->c_variable ("page-top-space"), 0);
@@ -127,6 +128,12 @@ Page_breaking::page_top_space () const
   return page_top_space_;
 }
 
+vsize
+Page_breaking::system_count () const
+{
+  return system_count_;
+}
+
 /* translate indices into breaks_ into start-end parameters for the line breaker */
 void
 Page_breaking::line_breaker_args (vsize sys,
@@ -451,6 +458,7 @@ Page_breaking::set_current_breakpoints (vsize start,
                                        Line_division lower_bound,
                                        Line_division upper_bound)
 {
+  system_count_ = system_count;
   current_chunks_ = chunk_list (start, end);
   current_start_breakpoint_ = start;
   current_end_breakpoint_ = end;
@@ -506,6 +514,7 @@ Page_breaking::set_to_ideal_line_configuration (vsize start, vsize end)
   current_start_breakpoint_ = start;
   current_end_breakpoint_ = end;
   clear_line_details_cache ();
+  system_count_ = 0;
 
   Line_division div;
   for (vsize i = 0; i+1 < current_chunks_.size (); i++)
@@ -518,6 +527,8 @@ Page_breaking::set_to_ideal_line_configuration (vsize start, vsize end)
        }
       else
        div.push_back (1);
+
+      system_count_ += div.back ();
     }
   current_configurations_.clear ();
   current_configurations_.push_back (div);
@@ -676,16 +687,19 @@ Page_spacing_result
 Page_breaking::space_systems_on_n_pages (vsize configuration, vsize n, vsize first_page_num)
 {
   Page_spacing_result ret;
-  assert (n >= min_page_count (configuration, first_page_num));
 
   cache_line_details (configuration);
-  if (n > cached_line_details_.size ())
-    return Page_spacing_result ();
-  if (n == 1)
+  bool valid_n = (n >= min_page_count (configuration, first_page_num)
+                 && n <= cached_line_details_.size ());
+
+  if (!valid_n)
+    programming_error ("number of pages is out of bounds");
+
+  if (n == 1 && valid_n)
     ret = space_systems_on_1_page (cached_line_details_,
                                   page_height (first_page_num, is_last ()),
                                   ragged () || (is_last () && ragged_last ()));
-  else if (n == 2)
+  else if (n == 2 && valid_n)
     ret = space_systems_on_2_pages (configuration, first_page_num);
   else
     {
@@ -711,8 +725,12 @@ Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize
 
   cache_line_details (configuration);
   vsize min_p_count = min_page_count (configuration, first_page_num);
+  bool valid_n = n >= min_p_count || n <= cached_line_details_.size ();
+
+  if (!valid_n)
+    programming_error ("both page counts are out of bounds");
 
-  if (n == 1)
+  if (n == 1 && valid_n)
     {
       bool rag = ragged () || (is_last () && ragged_last ());
       Real height = page_height (first_page_num, is_last ());
@@ -726,9 +744,9 @@ Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize
     {
       Page_spacer ps (cached_line_details_, first_page_num, this);
       
-      if (n >= min_p_count)
+      if (n >= min_p_count || !valid_n)
        n_res = ps.solve (n);
-      if (n < cached_line_details_.size ())
+      if (n < cached_line_details_.size () || !valid_n)
        m_res = ps.solve (n+1);
     }
 
index 384ce440222a95cc1f5901dd0cdd54113e779eda..19129b3c175a0024dc157aebdcee31b8034e52a7 100644 (file)
@@ -92,11 +92,10 @@ Page_spacer::solve (vsize page_count)
     resize (page_count);
 
   Page_spacing_result ret;
-  ret.force_.resize (page_count);
-  ret.systems_per_page_.resize (page_count);
 
   vsize system = lines_.size () - 1;
-  vsize tack_onto_the_end = 0;
+  vsize extra_systems = 0;
+  vsize extra_pages = 0;
 
   if (isinf (state_.at (system, page_count-1).demerits_))
     {
@@ -112,13 +111,28 @@ Page_spacer::solve (vsize page_count)
 
       if (i)
        {
-         tack_onto_the_end = system - i;
+         extra_systems = system - i;
          system = i;
        }
       else
-       return Page_spacing_result (); /* couldn't salvage it -- probably going to crash */
+       {
+         /* try chopping off pages from the end */
+         vsize j;
+         for (j = page_count; j && isinf (state_.at (system, j-1).demerits_); j--)
+           ;
+
+         if (j)
+           {
+             extra_pages = page_count - j;
+             page_count = j;
+           }
+         else
+           return Page_spacing_result (); /* couldn't salvage it -- probably going to crash */
+       }
     }
 
+  ret.force_.resize (page_count);
+  ret.systems_per_page_.resize (page_count);
   ret.penalty_ = state_.at (system, page_count-1).penalty_
     + lines_.back ().page_penalty_ + lines_.back ().turn_penalty_;
 
@@ -133,9 +147,23 @@ Page_spacer::solve (vsize page_count)
       if (p == 0)
        ret.systems_per_page_[p] = system + 1;
       else
-       ret.systems_per_page_[p] = system - ps.prev_ + tack_onto_the_end;
+       ret.systems_per_page_[p] = system - ps.prev_;
       system = ps.prev_;
     }
+
+  if (extra_systems)
+    {
+      ret.systems_per_page_.back () += extra_systems;
+      ret.demerits_ += 200000;
+    }
+  if (extra_pages)
+    {
+      ret.force_.insert (ret.force_.end (), extra_pages, 200000);
+      ret.systems_per_page_.insert (ret.systems_per_page_.end (), extra_pages, 0);
+      ret.demerits_ += 200000;
+    }
+
+
   ret.demerits_ += ret.penalty_;
   return ret;
 }