Here is my latest patch to add a new page-breaker. This actually adds 2
page breakers now:

ly:page-turn-breaking will only allow page turns at specified places
within the score. By default, a page turn can only appear at the end of
a score. This can be altered in two ways:
1) by adding \allowPageTurn or \pageTurn in certain places throughout
the score
2) by adding Page_turn_engraver to a Staff (or Voice) context.
Page_turn_engraver will scan the context for noteheads. Wherever there
is a sufficiently long gap in noteheads, a page turn will be permitted.
This length is tuned by the context property minPageTurnLength

ly:optimal-breaking does not care about page turns. The main advantage
over the current page breaker is that it is capable of changing the
horizontal spacing so that the vertical spacing is better. If you use
this, you probably want to set ragged-last-bottom = ##f.

I propose that ly:optimal-breaking be eventually made the default page
breaker (I'm sure there are plenty of issues to work out first, though).

Both page-breakers can be tuned with the (book-wide) paper block
variables "page-spacing-weight" (default 1.0) which specifies the
importance of good page spacing relative to line spacing and
"blank-last-page-force" (default 0) which specifies the penalty for
ending the piece on a left-hand page. ly:page-turn-breaking will also
consider leaving blank pages mid-score. The penalty for these pages can
be tuned with "blank-page-force" (default 10).

The new files are attached in a tar archive (I cc to Han-Wen just in
case the list strips it). There are 13 of them, so I thought it would be
easier.

2006-07-25  Joe Neeman  <[EMAIL PROTECTED]>

        * scm/page.scm (make-page): make it friendlier to call (esp. from C++)

        * scm/layout-page-layout.scm (make-page-from-systems): new function
        (optimal-page-breaks): use the new page-breaking calling convention

        * scm/define-context-properties.scm (all-user-translation-properties):
        add revokePageTurns

        * lily/paper-column-engraver.cc (stop_translation_timestep): add
        revokePageTurns  functionality. If there is a special barline within
        the breakable region, break there instead of at the end of the region.

        * lily/paper-book.cc (pages): use the new page-breaking calling
convention

Attachment: page_breaking_newfiles.tar.gz
Description: application/compressed-tar

Index: ChangeLog
===================================================================
RCS file: /sources/lilypond/lilypond/ChangeLog,v
retrieving revision 1.5202
diff -u -r1.5202 ChangeLog
--- ChangeLog	25 Jul 2006 01:16:05 -0000	1.5202
+++ ChangeLog	25 Jul 2006 01:34:03 -0000
@@ -1,5 +1,19 @@
 2006-07-25  Joe Neeman  <[EMAIL PROTECTED]>
 
+	* scm/page.scm (make-page): make it friendlier to call (esp. from C++)
+
+	* scm/layout-page-layout.scm (make-page-from-systems): new function
+	(optimal-page-breaks): use the new page-breaking calling convention
+
+	* scm/define-context-properties.scm (all-user-translation-properties):
+	add revokePageTurns
+
+	* lily/paper-column-engraver.cc (stop_translation_timestep): add
+	revokePageTurns  functionality. If there is a special barline within
+	the breakable region, break there instead of at the end of the region.
+
+	* lily/paper-book.cc (pages): use the new page-breaking calling convention
+
 	* lily/grob.cc:
 	* lily/gourlay-breaking.cc: Oops, these should have been included in my last
 	commit
Index: lily/paper-book.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/paper-book.cc,v
retrieving revision 1.132
diff -u -r1.132 paper-book.cc
--- lily/paper-book.cc	15 Feb 2006 13:02:17 -0000	1.132
+++ lily/paper-book.cc	25 Jul 2006 01:24:47 -0000
@@ -381,7 +381,7 @@
 
   pages_ = SCM_EOL;
   SCM proc = paper_->c_variable ("page-breaking");
-  pages_ = scm_apply_0 (proc, scm_list_2 (systems (), self_scm ()));
+  pages_ = scm_apply_0 (proc, scm_list_1(self_scm ()));
   return pages_;
 }
 
Index: lily/paper-column-engraver.cc
===================================================================
RCS file: /sources/lilypond/lilypond/lily/paper-column-engraver.cc,v
retrieving revision 1.19
diff -u -r1.19 paper-column-engraver.cc
--- lily/paper-column-engraver.cc	11 Jul 2006 05:58:00 -0000	1.19
+++ lily/paper-column-engraver.cc	25 Jul 2006 01:24:47 -0000
@@ -8,6 +8,7 @@
 
 #include "paper-column-engraver.hh"
 #include "system.hh"
+#include "international.hh"
 #include "item.hh"
 #include "paper-column.hh"
 #include "staff-spacing.hh"
@@ -26,9 +27,9 @@
   musical_column_ = 0;
   breaks_ = 0;
   system_ = 0;
-  first_ = true;
+  last_special_barline_column_ = 0;
   last_breakable_column_ = 0;
-  last_breakable_moment_ = Moment (-1);
+  first_ = true;
 }
 
 void
@@ -84,6 +85,7 @@
 				     ly_symbol2scm ("spacing-wishes"),
 				     gi.grob ());
 }
+
 void
 Paper_column_engraver::acknowledge_note_spacing (Grob_info gi)
 {
@@ -169,6 +171,56 @@
     }
 }
 
+/* return either
+   - the last column with a special (ie. not "|" or "") barline
+   - the last column
+   after the given moment
+*/
+Paper_column*
+Paper_column_engraver::find_turnable_column (Moment after_this)
+{
+  if (last_special_barline_column_)
+    {
+      Moment m = *unsmob_moment (last_special_barline_column_->get_property ("when"));
+      if (m >= after_this)
+	return last_special_barline_column_;
+    }
+  if (last_breakable_column_)
+    {
+      Moment m = *unsmob_moment (last_breakable_column_->get_property ("when"));
+      if (m >= after_this)
+	return last_breakable_column_;
+    }
+  return 0;
+}
+
+void
+Paper_column_engraver::revoke_page_turns (Moment after_this, Real new_penalty)
+{
+  if (!page_turnable_columns_.size ())
+    return;
+
+  for (vsize i = page_turnable_columns_.size () - 1; i--;)
+    {
+      Paper_column *col = page_turnable_columns_[i];
+      Moment mom = *unsmob_moment (col->get_property ("when"));
+      if (mom >= after_this)
+	{
+	  if (isinf (new_penalty))
+	    {
+	      col->del_property ( ly_symbol2scm ("page-turn-permission"));
+	      page_turnable_columns_.erase (page_turnable_columns_.begin () + i);
+	    }
+	  else
+	    {
+	      Real prev_pen = robust_scm2double (col->get_property ("page-turn-penalty"), 0);
+	      if (new_penalty > prev_pen)
+		col->set_property ("page-turn-penalty", scm_from_double (new_penalty));
+	    }
+	}
+    }
+}
+
 void
 Paper_column_engraver::stop_translation_timestep ()
 {
@@ -194,25 +246,50 @@
     {
       breaks_++;
       last_breakable_column_ = command_column_;
-      last_breakable_moment_ = now_mom ();
+
+      SCM which_bar = get_property ("whichBar");
+      if (scm_is_string (which_bar))
+	{
+	  string bar = ly_scm2string (which_bar);
+	  if (bar != "" && bar != "|")
+	    last_special_barline_column_ = command_column_;
+	}
+
       if (! (breaks_%8))
 	progress_indication ("[" + to_string (breaks_) + "]");
     }
 
   SCM page_br = get_property ("allowPageTurn");
-  if (scm_is_pair (page_br) && last_breakable_moment_ >= Rational (0))
+  if (scm_is_pair (page_br) && last_breakable_column_)
     {
       SCM pen = scm_cdr (page_br);
       Moment *m = unsmob_moment (scm_car (page_br));
-      if (m && scm_is_number (pen) && *m <= last_breakable_moment_)
+      if (m)
 	{
-	  last_breakable_column_->set_property ("page-turn-permission", ly_symbol2scm ("allow"));
-	  last_breakable_column_->set_property ("page-turn-penalty", pen);
+	  Paper_column *turn = find_turnable_column (*m);
+	  if (turn)
+	    {
+	      turn->set_property ("page-turn-permission", ly_symbol2scm ("allow"));
+	      turn->set_property ("page-turn-penalty", pen);
+	      page_turnable_columns_.push_back (turn);
+	    }
 	}
     }
 
+  /* The page-turn-engraver is allowed to change its mind and revoke previously-allowed
+     page turns (for example if there is a volta repeat where a turn is inconvenient) */
+  SCM revokes = get_property ("revokePageTurns");
+  if (scm_is_pair (revokes))
+    {
+      Moment *start = unsmob_moment (scm_car (revokes));
+      Real pen = robust_scm2double (scm_cdr (revokes), infinity_f);
+      if (start)
+	revoke_page_turns (*start, pen);
+    }
+
   context ()->get_score_context ()->unset_property (ly_symbol2scm ("forbidBreak"));
   context ()->get_score_context ()->unset_property (ly_symbol2scm ("allowPageTurn"));
+  context ()->get_score_context ()->unset_property (ly_symbol2scm ("revokePageTurns"));
 
   first_ = false;
   break_events_.clear ();
@@ -249,9 +326,13 @@
 		/* accept */ "break-event",
 		/* read */
                 "forbidBreak "
-                "allowPageTurn",
+                "allowPageTurn "
+		"revokePageTurns "
+		,
 		/* write */
                 "forbidBreak "
                 "allowPageTurn "
+		"revokePageTurns "
 		"currentCommandColumn "
-		"currentMusicalColumn");
+		"currentMusicalColumn "
+		);
Index: lily/include/paper-column-engraver.hh
===================================================================
RCS file: /sources/lilypond/lilypond/lily/include/paper-column-engraver.hh,v
retrieving revision 1.9
diff -u -r1.9 paper-column-engraver.hh
--- lily/include/paper-column-engraver.hh	9 May 2006 02:15:56 -0000	1.9
+++ lily/include/paper-column-engraver.hh	25 Jul 2006 01:24:49 -0000
@@ -17,6 +17,9 @@
   void set_columns (Paper_column *, Paper_column *);
   TRANSLATOR_DECLARATIONS (Paper_column_engraver);
 
+  Paper_column *find_turnable_column (Moment after_this);
+  void revoke_page_turns (Moment after_this, Real new_penalty);
+
 protected:
   void stop_translation_timestep ();
   void start_translation_timestep ();
@@ -38,8 +41,9 @@
   bool first_;
   Moment last_moment_;
 
-  Moment last_breakable_moment_;
+  Paper_column *last_special_barline_column_;
   Paper_column *last_breakable_column_;
+  vector<Paper_column*> page_turnable_columns_;
 public:
 };
 
Index: ly/paper-defaults.ly
===================================================================
RCS file: /sources/lilypond/lilypond/ly/paper-defaults.ly,v
retrieving revision 1.25
diff -u -r1.25 paper-defaults.ly
--- ly/paper-defaults.ly	15 Jul 2006 10:32:44 -0000	1.25
+++ ly/paper-defaults.ly	25 Jul 2006 01:24:49 -0000
@@ -76,6 +76,12 @@
     %%
     ragged-last-bottom= ##t
 
+    %%
+    %% settings for the page breaker
+    %%
+    blank-last-page-force = 0
+    blank-last-force = 10
+
     #(define font-defaults
       '((font-encoding . fetaMusic)))
 
Index: scm/define-context-properties.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/define-context-properties.scm,v
retrieving revision 1.79
diff -u -r1.79 define-context-properties.scm
--- scm/define-context-properties.scm	20 Jul 2006 09:29:42 -0000	1.79
+++ scm/define-context-properties.scm	25 Jul 2006 01:24:49 -0000
@@ -339,6 +339,7 @@
      (restNumberThreshold ,number?
 			  "If a multimeasure rest has more measures
 than this, a number is printed. ")
+     (revokePageTurns ,pair? "Signals to the paper-column-engraver to revoke (or increase the penalties for) all the page turns within a time interval. Used to disable page turns that occur within an unturnable volta repeat.")
      (shapeNoteStyles ,vector? "Vector of symbols, listing style for each note
 head relative to the tonic (qv.) of the scale.")
      (skipBars ,boolean? "If set to true, then
Index: scm/layout-page-layout.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/layout-page-layout.scm,v
retrieving revision 1.19
diff -u -r1.19 layout-page-layout.scm
--- scm/layout-page-layout.scm	24 Jul 2006 11:50:27 -0000	1.19
+++ scm/layout-page-layout.scm	25 Jul 2006 01:24:49 -0000
@@ -13,7 +13,7 @@
   #:use-module (scm page)
   #:use-module (scm layout-page-dump)
   #:use-module (lily)
-  #:export (post-process-pages optimal-page-breaks))
+  #:export (post-process-pages optimal-page-breaks make-page-from-systems))
 
 (define (post-process-pages layout pages)
   (if (ly:output-def-lookup layout 'write-page-layout #f)
@@ -160,6 +160,19 @@
                  (+ y topskip))
                (cdr space-result)))))
 
+(define (make-page-from-systems p-book lines p-num ragged? last?)
+  (let*
+    ((page (make-page
+            p-book
+            'lines lines
+            'page-number p-num
+            'prev prev
+            'is-last last?))
+     (height (page-printable-height page))
+     (posns (cdr (space-systems height lines ragged? (ly:paper-book-paper p-book)))))
+    (page-set-property! page 'configuration posns)
+    page))
+
 (define (walk-paths done-lines best-paths current-lines last? current-best
                     paper-book page-alist)
   "Return the best optimal-page-break-node that contains
@@ -170,8 +183,7 @@
 CURRENT-BEST is the best result sofar, or #f."
   (let* ((paper (ly:paper-book-paper paper-book))
          (this-page (make-page
-                     page-alist
-                     'paper-book paper-book
+                     paper-book
                      'is-last last?
                      'page-number (if (null? best-paths)
                                       (ly:output-def-lookup paper 'first-page-number)
@@ -258,9 +270,10 @@
                     paper-book
                     page-alist))))
 
-(define-public (optimal-page-breaks lines paper-book)
+(define-public (optimal-page-breaks paper-book)
   "Return pages as a list starting with 1st page. Each page is a 'page Prob."
   (let* ((paper (ly:paper-book-paper paper-book))
+	 (lines (ly:paper-book-systems paper-book))
          (page-alist (layout->page-init paper)) 
          (force-equalization-factor (ly:output-def-lookup
                                      paper 'verticalequalizationfactor 0.3)))
Index: scm/page.scm
===================================================================
RCS file: /sources/lilypond/lilypond/scm/page.scm,v
retrieving revision 1.13
diff -u -r1.13 page.scm
--- scm/page.scm	24 Jul 2006 11:50:27 -0000	1.13
+++ scm/page.scm	25 Jul 2006 01:24:49 -0000
@@ -37,10 +37,11 @@
 
 (define page-module (current-module))
 
-(define (make-page init  . args)
+(define (make-page p-book  . args)
   (let*
       ((p (apply ly:make-prob (append
-			       (list 'page init)
+			       (list 'page (layout->page-init (ly:paper-book-paper p-book))
+				     'paper-book p-book)
 			       args))))
 
     (page-set-property! p 'head-stencil (page-header p))
@@ -196,7 +197,6 @@
       ((p-book (page-property page 'paper-book))
        (layout (ly:paper-book-paper p-book))
        (scopes (ly:paper-book-scopes p-book))
-       (lines (page-lines page))
        (number (page-page-number page))
        (last? (page-property page 'is-last))
        )
Index: ly/declarations-init.ly
===================================================================
RCS file: /sources/lilypond/lilypond/ly/declarations-init.ly,v
retrieving revision 1.100
diff -u -r1.100 declarations-init.ly
--- ly/declarations-init.ly	9 May 2006 02:15:56 -0000	1.100
+++ ly/declarations-init.ly	25 Jul 2006 02:31:56 -0000
@@ -46,6 +46,7 @@
 				(make-music 'PageBreakEvent 'break-permission 'force)
 				(make-music 'PageTurnEvent 'break-permission 'force)))
 noPageTurn = #(make-event-chord (list (make-music 'PageTurnEvent 'break-permission '())))
+allowPageTurn = #(make-event-chord (list (make-music 'PageTurnEvent 'break-permission 'allow)))
 
 stopStaff = #(make-event-chord (list (make-span-event 'StaffSpanEvent STOP)))
 startStaff = #(make-event-chord (list (make-span-event 'StaffSpanEvent START)))
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to