]> git.donarmstrong.com Git - lilypond.git/commitdiff
Add systems-per-page variable in \paper.
authorJoe Neeman <joeneeman@gmail.com>
Sun, 9 Nov 2008 19:34:42 +0000 (11:34 -0800)
committerJoe Neeman <joeneeman@gmail.com>
Sun, 9 Nov 2008 19:34:42 +0000 (11:34 -0800)
lily/include/constrained-breaking.hh
lily/include/page-breaking.hh
lily/include/page-spacing.hh
lily/optimal-page-breaking.cc
lily/page-breaking.cc
lily/page-spacing.cc

index 81eff5c2eac56877ca763799245d2a7f9b868572..85d6df2b1a584c693ec817394cbe4e93f3775963 100644 (file)
@@ -55,8 +55,8 @@ struct Line_details {
     page_penalty_ = 0;
     turn_penalty_ = 0;
     title_ = false;
-    compressed_lines_count_ = 0;
-    compressed_nontitle_lines_count_ = 0;
+    compressed_lines_count_ = 1;
+    compressed_nontitle_lines_count_ = 1;
   }
 
   Line_details (Prob *pb)
@@ -74,8 +74,8 @@ struct Line_details {
     page_penalty_ = robust_scm2double (pb->get_property ("page-break-penalty"), 0);
     turn_penalty_ = robust_scm2double (pb->get_property ("page-turn-penalty"), 0);
     title_ = to_boolean (pb->get_property ("is-title"));
-    compressed_lines_count_ = 0;
-    compressed_nontitle_lines_count_ = 0;
+    compressed_lines_count_ = 1;
+    compressed_nontitle_lines_count_ = title_ ? 0 : 1;
   }
 };
 
index 7bf43aa0db6d1782d1da79ca47bcc633dec7679e..205d9348e7ea024b1b0052fae38caa84f821ee09 100644 (file)
@@ -129,14 +129,16 @@ protected:
   vsize current_configuration_count () const;
   Line_division current_configuration (vsize configuration_index) const;
   Page_spacing_result space_systems_on_n_pages (vsize configuration_index,
-                                               vsize n, vsize first_page_num);
+                                               vsize n, vsize first_page_num,
+                                               int systems_per_page=0);
   Page_spacing_result space_systems_on_n_or_one_more_pages (vsize configuration_index, vsize n,
-                                                           vsize first_page_num);
+                                                           vsize first_page_num,
+                                                           int systems_per_page=0);
   Page_spacing_result space_systems_on_best_pages (vsize configuration_index,
                                                   vsize first_page_num);
   Page_spacing_result space_systems_with_fixed_number_per_page (vsize configuration_index,
-                                                               int systems_per_page,
-                                                               vsize first_page_num);
+                                                               vsize first_page_num,
+                                                               int systems_per_page);
   Page_spacing_result pack_systems_on_least_pages (vsize configuration_index,
                                                   vsize first_page_num);
   vsize min_page_count (vsize configuration_index, vsize first_page_num);
index fe7056c597c1fa1bcdf30a19c7b979756ef3ba16..c2dbc2ea6e8aa55ff614126dec327414389e7150 100644 (file)
 #include "constrained-breaking.hh"
 #include "page-spacing-result.hh"
 
+/* This is a penalty that we add whenever a page breaking solution
+   is not bad enough to completely discard, but bad enough that
+   it is worse than any "proper" solution. For example, if we didn't
+   manage to fit systems on the desired number of pages or if there was
+   too big for a page.
+
+   This constant is large enough that it dominates any reasonable penalty,
+   but small enough that nothing will overflow to infinity (so that we
+   can still distinguish bad spacings by the number of BAD_SPACING_PENALTYs
+   that they incur.
+*/
+const Real BAD_SPACING_PENALTY = 200000;
+
 
 /* for page_count > 2, we use a dynamic algorithm similar to
    constrained-breaking -- we have a class that stores the intermediate
index 3c26c9abe08c5d15ac932cd4f2ed7f025f6a19f2..7eb04ce24d9fc48cab1b7fdf6e1b1920c7e01f9e 100644 (file)
@@ -40,6 +40,7 @@ Optimal_page_breaking::solve ()
   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");
+  int systems_per_page = robust_scm2int (book_->paper_->c_variable ("systems-per-page"), 0);
 
   set_to_ideal_line_configuration (0, end);
 
@@ -55,9 +56,12 @@ Optimal_page_breaking::solve ()
       /* 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 ();
+      if (systems_per_page > 0)
+       best = space_systems_with_fixed_number_per_page (0, first_page_num, systems_per_page);
+      else
+       best = space_systems_on_best_pages (0, first_page_num);
 
+      page_count = best.systems_per_page_.size ();
       ideal_sys_count = best.system_count ();
       min_sys_count = ideal_sys_count - best.systems_per_page_.back ();
   
@@ -66,9 +70,11 @@ Optimal_page_breaking::solve ()
     }
   else
     {
-      /* todo: the following line will spit out programming errors if the
+      /* TODO: the following line will spit out programming errors if the
         ideal line spacing doesn't fit on PAGE_COUNT pages */
-      best = space_systems_on_n_pages (0, page_count, first_page_num);
+      /* TODO: the interaction between systems_per_page and page_count needs to
+        be considered. */
+      best = space_systems_on_n_pages (0, page_count, first_page_num, systems_per_page);
       min_sys_count = page_count;
     }
 
@@ -92,9 +98,9 @@ Optimal_page_breaking::solve ()
          Page_spacing_result cur;
 
          if (min_p_count == page_count || scm_is_integer (forced_page_count))
-           cur = space_systems_on_n_pages (i, page_count, first_page_num);
+           cur = space_systems_on_n_pages (i, page_count, first_page_num, systems_per_page);
          else
-           cur = space_systems_on_n_or_one_more_pages (i, page_count-1, first_page_num);
+           cur = space_systems_on_n_or_one_more_pages (i, page_count-1, first_page_num, systems_per_page);
 
          if (cur.demerits_ < best_for_this_sys_count.demerits_ || isinf (best_for_this_sys_count.demerits_))
            {
@@ -136,7 +142,7 @@ Optimal_page_breaking::solve ()
          if (min_p_count > page_count)
            continue;
          else
-           cur = space_systems_on_n_pages (i, page_count, first_page_num);
+           cur = space_systems_on_n_pages (i, page_count, first_page_num, systems_per_page);
 
          if (cur.demerits_ < best.demerits_ || isinf (best.demerits_))
            {
index 777eab34db322250fe2b03d66bd4c895560ab774..7b0bb8cffb9444b2603e6f8f444d4127bd0e081a 100644 (file)
@@ -67,7 +67,7 @@ uncompress_solution (vector<vsize> const &systems_per_page,
     {
       int compressed_count = 0;
       for (vsize j = start_sys; j < start_sys + systems_per_page[i]; j++)
-       compressed_count += compressed[j].compressed_lines_count_;
+       compressed_count += compressed[j].compressed_lines_count_ - 1;
 
       ret.push_back (systems_per_page[i] + compressed_count);
       start_sys += systems_per_page[i];
@@ -682,11 +682,23 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
   return ret;
 }
 
+// If systems_per_page is positive, we don't really try to space on N pages;
+// we just put the requested number of systems on each page and penalize
+// if the result doesn't have N pages.
 Page_spacing_result
-Page_breaking::space_systems_on_n_pages (vsize configuration, vsize n, vsize first_page_num)
+Page_breaking::space_systems_on_n_pages (vsize configuration, vsize n, vsize first_page_num,
+                                        int systems_per_page)
 {
   Page_spacing_result ret;
 
+  if (systems_per_page > 0)
+    {
+      Page_spacing_result ret = space_systems_with_fixed_number_per_page (configuration, first_page_num,
+                                                                         systems_per_page);
+      ret.demerits_ += (ret.force_.size () == n) ? 0 : BAD_SPACING_PENALTY;
+      return ret;
+    }
+
   cache_line_details (configuration);
   bool valid_n = (n >= min_page_count (configuration, first_page_num)
                  && n <= cached_line_details_.size ());
@@ -728,12 +740,23 @@ Page_breaking::blank_page_penalty () const
   return robust_scm2double (book_->paper_->lookup_variable (penalty_sym), 0.0);
 }
 
+// If systems_per_page is positive, we don't really try to space on N
+// or N+1 pages; see the comment to space_systems_on_n_pages.
 Page_spacing_result
-Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize n, vsize first_page_num)
+Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize n, vsize first_page_num,
+                                                    int systems_per_page)
 {
   Page_spacing_result n_res;
   Page_spacing_result m_res;
 
+  if (systems_per_page > 0)
+    {
+      Page_spacing_result ret = space_systems_with_fixed_number_per_page (configuration, first_page_num,
+                                                                         systems_per_page);
+      ret.demerits_ += (ret.force_.size () == n || ret.force_.size () == (n-1)) ? 0 : BAD_SPACING_PENALTY;
+      return ret;
+    }
+
   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 ();
@@ -798,8 +821,8 @@ Page_breaking::space_systems_on_best_pages (vsize configuration, vsize first_pag
 
 Page_spacing_result
 Page_breaking::space_systems_with_fixed_number_per_page (vsize configuration,
-                                                        int systems_per_page,
-                                                        vsize first_page_num)
+                                                        vsize first_page_num,
+                                                        int systems_per_page)
 {
   Page_spacing_result res;
   Page_spacing space (page_height (first_page_num, false), page_top_space_);
@@ -818,9 +841,13 @@ Page_breaking::space_systems_with_fixed_number_per_page (vsize configuration,
       while (system_count_on_this_page < systems_per_page
             && line < cached_line_details_.size ())
        {
-         space.append_system (cached_line_details_[line]);
-         system_count_on_this_page += cached_line_details_[line].compressed_nontitle_lines_count_;
+         Line_details const &cur_line = cached_line_details_[line];
+         space.append_system (cur_line);
+         system_count_on_this_page += cur_line.compressed_nontitle_lines_count_;
          line++;
+
+         if (cur_line.page_permission_ == ly_symbol2scm ("force"))
+           break;
        }
 
       res.systems_per_page_.push_back (line - page_first_line);
index 19129b3c175a0024dc157aebdcee31b8034e52a7..a6d98d82ef32d0c99cbf7d79e9d3a8c743b859e8 100644 (file)
@@ -154,13 +154,13 @@ Page_spacer::solve (vsize page_count)
   if (extra_systems)
     {
       ret.systems_per_page_.back () += extra_systems;
-      ret.demerits_ += 200000;
+      ret.demerits_ += BAD_SPACING_PENALTY;
     }
   if (extra_pages)
     {
-      ret.force_.insert (ret.force_.end (), extra_pages, 200000);
+      ret.force_.insert (ret.force_.end (), extra_pages, BAD_SPACING_PENALTY);
       ret.systems_per_page_.insert (ret.systems_per_page_.end (), extra_pages, 0);
-      ret.demerits_ += 200000;
+      ret.demerits_ += BAD_SPACING_PENALTY;
     }
 
 
@@ -209,7 +209,7 @@ Page_spacer::calc_subproblem (vsize page, vsize line)
 
          /* we may have to deal with single lines that are taller than a page */
          if (isinf (space.force_) && page_start == line)
-           space.force_ = -200000;
+           space.force_ = -BAD_SPACING_PENALTY;
 
          Real dem = fabs (space.force_) + (prev ? prev->demerits_ : 0);
          Real penalty = 0;