]> git.donarmstrong.com Git - lilypond.git/commitdiff
Cleanups in one-line-page-breaking.
authorJoe Neeman <joeneeman@gmail.com>
Mon, 28 May 2012 00:17:00 +0000 (17:17 -0700)
committerJoe Neeman <joeneeman@gmail.com>
Wed, 13 Jun 2012 06:30:23 +0000 (08:30 +0200)
Make sure that each page is wider than the widest system.

input/regression/one-line-breaking.ly [new file with mode: 0644]
lily/one-line-page-breaking.cc
lily/page-breaking-scheme.cc
lily/page-breaking.cc
lily/paper-book.cc

diff --git a/input/regression/one-line-breaking.ly b/input/regression/one-line-breaking.ly
new file mode 100644 (file)
index 0000000..9dbd804
--- /dev/null
@@ -0,0 +1,9 @@
+\version "2.15.40"
+
+\header {
+  texidoc = "The @var{ly:one-line-breaking} algorithm puts everything on one line."
+}
+
+\paper { page-breaking = #ly:one-line-breaking }
+
+\include "typography-demo.ly"
index 2175e1727a48658de49819109dab82acf92f8c9e..018ef9cff390b4fa9e1b68e9ec0677d22a523b20 100644 (file)
@@ -40,42 +40,53 @@ One_line_page_breaking::~One_line_page_breaking ()
 }
 
 /*
-  This is a somewhat unconventional page-breaking algorithm. Every
+  This is a somewhat unconventional page-breaking algorithm.  Every
   score will be put on a single page, whose width is enough
-  to fit the entire score one one line. Line breaks and page breaks
-  are ignored, as are the page dimensions in the paper block.
+  to fit the entire score one one line.  Line breaks and page breaks
+  are ignored, and the paper-width setting in the paper block
+  will be modified to fit the music.
 */
 SCM
 One_line_page_breaking::solve ()
 {
   SCM all_pages = SCM_EOL;
+  Real max_width = 0;
   for (vsize i = 0; i < system_specs_.size (); ++i)
-    if (Paper_score *ps = system_specs_[i].pscore_)
-      {
-        vector<Grob*> cols = ps->root_system ()->used_columns ();
-
-        // No indent, "infinite" line width, ragged.
-        Column_x_positions pos = get_line_configuration (cols, numeric_limits<Real>::max (), 0, true);
-        vector<Column_x_positions> positions;
-        positions.push_back (pos);
-
-        ps->root_system ()->break_into_pieces (positions);
-        ps->root_system ()->do_break_substitution_and_fixup_refpoints ();
-        Grob *system = ps->root_system ()->broken_intos_[0];
-        Real width = system->extent (system, X_AXIS).length ();
-        Real height = system->extent (system, Y_AXIS).length ();
-        
-        // HACK: probably shouldn't be modifying the paper_; better to modify the page
-        // afterwards.
-        book_->paper_->set_variable (ly_symbol2scm ("paper-width"), scm_from_double (width + 100));
-        // TODO: figure out what the height should be.
-        //book_->paper_->set_variable (ly_symbol2scm ("paper-height"), scm_from_double (height));
-        vector<vsize> lines_per_page;
-        lines_per_page.push_back (1);
-        SCM systems = scm_list_1 (system->self_scm ());
-        SCM pages = make_pages (lines_per_page, systems);
-        all_pages = scm_cons (scm_car (pages), all_pages);
-      }
+    {
+      if (Paper_score *ps = system_specs_[i].pscore_)
+        {
+          vector<Grob*> cols = ps->root_system ()->used_columns ();
+
+          // No indent, "infinite" line width, ragged.
+          Column_x_positions pos = get_line_configuration (cols, numeric_limits<Real>::max (), 0, true);
+          vector<Column_x_positions> positions;
+          positions.push_back (pos);
+
+          ps->root_system ()->break_into_pieces (positions);
+          ps->root_system ()->do_break_substitution_and_fixup_refpoints ();
+          Grob *system = ps->root_system ()->broken_intos_[0];
+
+          vector<vsize> lines_per_page;
+          lines_per_page.push_back (1);
+          SCM systems = scm_list_1 (system->self_scm ());
+          SCM pages = make_pages (lines_per_page, systems);
+
+          max_width = max (max_width, system->extent (system, X_AXIS).length ());
+          all_pages = scm_cons (scm_car (pages), all_pages);
+        }
+      else if (Prob *pb = system_specs_[i].prob_)
+        // Because we don't call Page_breaking::systems in this algorithm,
+        // we need to manually unprotect the titles.
+        pb->unprotect ();
+    }
+
+  // Alter paper-width so that it is large enough to fit every system.
+  // TODO: it might be nice to allow different pages to have different widths.
+  // This would need support in the backends (eg. framework-ps.scm).
+  Real right_margin = robust_scm2double (book_->paper_->c_variable ("right-margin"), 0.0);
+  Real left_margin = robust_scm2double (book_->paper_->c_variable ("left-margin"), 0.0);
+  Real width = max_width + right_margin + left_margin;
+  book_->paper_->set_variable (ly_symbol2scm ("paper-width"), scm_from_double (width));
 
   return scm_reverse_x (all_pages, SCM_EOL);
 }
index 796324cbc26d7a5114aa9df9bb20ab3b5114fd66..12929e510dfeb527e4a508ac6529c3fa250ff394 100644 (file)
@@ -55,7 +55,9 @@ LY_DEFINE (ly_minimal_breaking, "ly:minimal-breaking",
 
 LY_DEFINE (ly_one_line_breaking, "ly:one-line-breaking",
            1, 0, 0, (SCM pb),
-           "Put each score on a single line, and put each line on its own page.")
+           "Put each score on a single line, and put each line on its own"
+           " page.  The paper-width setting will be modified so that"
+           " every page will be wider than the widest line.")
 {
   One_line_page_breaking b (unsmob_paper_book (pb));
   return b.solve ();
index 9956c9f9784450c3a7f7fec8fd2d435af2ff7f10..692244b897063daab340b814da73529beee58642 100644 (file)
@@ -567,9 +567,6 @@ Page_breaking::draw_page (SCM systems, SCM configuration, int page_num, bool las
 
   // Create the page and draw it.
   SCM page = make_page (page_num, last);
-  SCM page_module = scm_c_resolve_module ("scm page");
-  SCM page_stencil = scm_c_module_lookup (page_module, "page-stencil");
-  page_stencil = scm_variable_ref (page_stencil);
 
   Prob *p = unsmob_prob (page);
   p->set_property ("lines", paper_systems);
@@ -583,7 +580,6 @@ Page_breaking::draw_page (SCM systems, SCM configuration, int page_num, bool las
   foot = Page_layout_problem::add_footnotes_to_footer (footnotes, foot, book_);
 
   p->set_property ("foot-stencil", foot.smobbed_copy ());
-  scm_apply_1 (page_stencil, page, SCM_EOL);
 
   return page;
 }
@@ -603,10 +599,11 @@ Page_breaking::make_pages (vector<vsize> lines_per_page, SCM systems)
     label_page_table = SCM_EOL;
 
   // Build a list of (systems configuration . footnote-count) triples.
-  // Note that we lay out
-  // the staves and find the configurations before drawing anything. Some
+  // Note that we lay out the staves and find the configurations,
+  // but we do not draw anything in this function.  It is important
+  // that all staves are laid out vertically before any are drawn; some
   // grobs (like tuplet brackets) look at their neighbours while drawing
-  // themselves. If this happens before the neighbouring staves have
+  // themselves.  If this happens before the neighbouring staves have
   // been laid out, bad side-effects could happen (in particular,
   // Align_interface::align_to_ideal_distances might be called).
   SCM systems_configs_fncounts = SCM_EOL;
@@ -642,7 +639,9 @@ Page_breaking::make_pages (vector<vsize> lines_per_page, SCM systems)
       systems = scm_list_tail (systems, line_count);
     }
 
-  // Now it's safe to make the pages.
+  // TODO: previously, the following loop caused the systems to be
+  // drawn.  Now that we no longer draw anything in Page_breaking,
+  // it is safe to merge these two loops.
   int page_num = first_page_number + lines_per_page.size () - 1;
   for (SCM s = systems_configs_fncounts; scm_is_pair (s); s = scm_cdr (s))
     {
@@ -681,14 +680,6 @@ Page_breaking::make_pages (vector<vsize> lines_per_page, SCM systems)
   return ret;
 }
 
-/* The page-turn-page-breaker needs to have a line-breaker between any two
-   columns with non-NULL page-turn-permission.
-
-   The optimal-breaker needs to have a line-breaker between any two columns
-   with page-break-permission = 'force.
-
-   By using a grob predicate, we can accommodate both of these uses.
-*/
 void
 Page_breaking::create_system_list ()
 {
@@ -712,6 +703,14 @@ Page_breaking::create_system_list ()
     system_specs_.push_back (System_spec ());
 }
 
+/* The page-turn-page-breaker needs to have a line-breaker between any two
+   columns with non-NULL page-turn-permission.
+
+   The optimal-breaker needs to have a line-breaker between any two columns
+   with page-break-permission = 'force.
+
+   By using a grob predicate, we can accommodate both of these uses.
+*/
 void
 Page_breaking::find_chunks_and_breaks (Break_predicate is_break, Prob_break_predicate prob_is_break)
 {
index f6d008f1db2dc01005f7cff47370e556203bd088..aecafbe3a053d66a15d884684ea570e01c011a85 100644 (file)
@@ -652,6 +652,15 @@ Paper_book::pages ()
     {
       SCM page_breaking = paper_->c_variable ("page-breaking");
       pages_ = scm_apply_0 (page_breaking, scm_list_1 (self_scm ()));
+
+      // Create all the page stencils.
+      SCM page_module = scm_c_resolve_module ("scm page");
+      SCM page_stencil = scm_c_module_lookup (page_module, "page-stencil");
+      page_stencil = scm_variable_ref (page_stencil);
+      for (SCM pages = pages_; scm_is_pair (pages); pages = scm_cdr (pages))
+        scm_apply_1 (page_stencil, scm_car (pages), SCM_EOL);
+
+      // Perform any user-supplied post-processing.
       SCM post_process = paper_->c_variable ("page-post-process");
       if (ly_is_procedure (post_process))
         scm_apply_2 (post_process, paper_->self_scm (), pages_, SCM_EOL);