lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patch] top level page breaking directives


From: Nicolas Sceaux
Subject: Re: [patch] top level page breaking directives
Date: Sun, 06 May 2007 13:37:37 +0200
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin)

Joe Neeman <address@hidden> writes:

> It would be nice if this generalised to having \forcePageTurn and 
> \forbidPageTurn commands. The problem is that you always set 
> page-break-permission and page-turn-permission together. That means that 
> something like \forbidPageTurn \forcePageBreak will never work because 
> \forcePageBreak will set page-turn-permission, overriding everything that 
> \forbidPageTurn does.

Here is a corrected patch.

\forbidPageBreak and \forcePageBreak incluence page breaking, although
sometimes they are not, whereas \forbidPageTurn and \forcePageTurn seem
to have no influence at all (using ly:page-turn-breaking).

Are page break and page turn permissions handled by the page breakers as
"must do" or "may do"? Should page-(turn|break)-penalty also be set?

BTW, using '() as the value for forbidden permission causes some
problems when using ly:music-property, because with this function '() is
the value returned when the property is not set. Thus, we cannot
discriminate between not set value and the actual '() value. That's why
I've used 'forbid in the definition of the commands.

nicolas

diff --git a/lily/book.cc b/lily/book.cc
index bf28d1b..265632a 100644
--- a/lily/book.cc
+++ b/lily/book.cc
@@ -20,6 +20,7 @@ using namespace std;
 #include "warn.hh"
 #include "performance.hh"
 #include "paper-score.hh"
+#include "page-marker.hh"
 
 #include "ly-smobs.icc"
 
@@ -153,7 +154,8 @@ Book::process (Output_def *default_paper
              outputs = scm_cdr (outputs);
            }
        }
-      else if (Text_interface::is_markup (scm_car (s)))
+      else if (Text_interface::is_markup (scm_car (s))
+              || unsmob_page_marker (scm_car (s)))
        paper_book->add_score (scm_car (s));
       else
        assert (0);
diff --git a/lily/include/page-marker.hh b/lily/include/page-marker.hh
new file mode 100644
index 0000000..a925a6c
--- /dev/null
+++ b/lily/include/page-marker.hh
@@ -0,0 +1,30 @@
+/*
+  page-marker.hh -- declare Page_marker
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2007 Nicolas Sceaux <address@hidden>
+*/
+
+#ifndef PAGE_MARKER_HH
+#define PAGE_MARKER_HH
+
+#include "smobs.hh"
+
+class Page_marker
+{
+  DECLARE_SMOBS (Page_marker);
+
+  SCM symbol_; /* either 'page-turn-permission or 'page-break-permission */
+  SCM permission_;  /* 'force, 'allow, or '() */
+
+public:
+  Page_marker (SCM symbol, SCM permission);
+  
+  SCM permission_symbol ();
+  SCM permission_value ();
+};
+
+DECLARE_UNSMOB (Page_marker, page_marker)
+
+#endif /* PAGE_MARKER_HH */
diff --git a/lily/page-marker-scheme.cc b/lily/page-marker-scheme.cc
new file mode 100644
index 0000000..3278a7b
--- /dev/null
+++ b/lily/page-marker-scheme.cc
@@ -0,0 +1,19 @@
+/*
+  page-marker-scheme.cc -- implement Page_marker bindings.
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2007 Nicolas Sceaux <address@hidden>
+*/
+
+#include "page-marker.hh"
+
+LY_DEFINE (ly_make_page_marker, "ly:make-page-marker",
+          2, 0, 0,
+          (SCM symbol, SCM permission),
+          "Return page marker with page breaking and turning permissions.")
+{
+  LY_ASSERT_TYPE (ly_is_symbol, symbol, 1);
+  Page_marker *page_marker = new Page_marker (symbol, permission);
+  return page_marker->unprotect ();
+}
diff --git a/lily/page-marker.cc b/lily/page-marker.cc
new file mode 100644
index 0000000..dd43c35
--- /dev/null
+++ b/lily/page-marker.cc
@@ -0,0 +1,55 @@
+/*
+  page-marker.cc -- implement Page_marker
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 2007 Nicolas Sceaux <address@hidden>
+*/
+
+#include "page-marker.hh"
+#include "ly-smobs.icc"
+
+Page_marker::Page_marker (SCM symbol, SCM permission)
+{
+  symbol_ = symbol;
+  permission_ = permission;
+  smobify_self ();
+}
+
+Page_marker::~Page_marker ()
+{
+}
+
+IMPLEMENT_SMOBS (Page_marker);
+IMPLEMENT_DEFAULT_EQUAL_P (Page_marker);
+IMPLEMENT_TYPE_P (Page_marker, "ly:page-marker?");
+
+SCM
+Page_marker::mark_smob (SCM smob)
+{
+  Page_marker *pm = (Page_marker *) SCM_CELL_WORD_1 (smob);
+  scm_gc_mark (pm->symbol_);
+  scm_gc_mark (pm->permission_);
+  return SCM_EOL;
+}
+
+int
+Page_marker::print_smob (SCM smob, SCM port, scm_print_state*)
+{
+  Page_marker *pm = (Page_marker *) SCM_CELL_WORD_1 (smob);
+  (void)pm;
+  scm_puts ("#<Page_marker>", port);
+  return 1;
+}
+
+SCM
+Page_marker::permission_symbol ()
+{
+  return symbol_;
+}
+
+SCM
+Page_marker::permission_value ()
+{
+  return permission_;
+}
diff --git a/lily/paper-book.cc b/lily/paper-book.cc
index c6bcccd..b8fc43f 100644
--- a/lily/paper-book.cc
+++ b/lily/paper-book.cc
@@ -17,6 +17,7 @@
 #include "text-interface.hh"
 #include "warn.hh"
 #include "program-option.hh"
+#include "page-marker.hh"
 
 #include "ly-smobs.icc"
 
@@ -226,8 +227,25 @@ Paper_book::score_title (SCM header)
   return title;
 }
 
+void
+set_page_permission (SCM sys, SCM symbol, SCM permission)
+{
+  if (Paper_score *ps = dynamic_cast<Paper_score*> (unsmob_music_output (sys)))
+    {
+      vector<Grob*> cols = ps->get_columns ();
+      if (cols.size ())
+       {
+         Paper_column *col = dynamic_cast<Paper_column*> (cols.back ());
+         col->set_property (symbol, permission);
+         col->find_prebroken_piece (LEFT)->set_property (symbol, permission);
+       }
+    }
+  else if (Prob *pb = unsmob_prob (sys))
+    pb->set_property (symbol, permission);
+}
+
 /* read the breakbefore property of a score block and set up the preceding
-   system-spec to honour it. That is, SYM should be the system spec that
+   system-spec to honour it. That is, SYS should be the system spec that
    immediately precedes the score (from which HEADER is taken)
    in the get_system_specs () list */
 void
@@ -240,25 +258,13 @@ set_system_penalty (SCM sys, SCM header)
          && scm_is_bool (SCM_VARIABLE_REF (force)))
        {
          bool b = to_boolean (SCM_VARIABLE_REF (force));
-         SCM sym = b ? ly_symbol2scm ("force") : SCM_EOL;
-
-         if (Paper_score *ps = dynamic_cast<Paper_score*> (unsmob_music_output 
(sys)))
-           {
-             vector<Grob*> cols = ps->get_columns ();
-             if (cols.size ())
-               {
-                 Paper_column *col = dynamic_cast<Paper_column*> (cols.back 
());
-                 col->set_property ("page-break-permission", sym);
-                 col->find_prebroken_piece (LEFT)->set_property 
("page-break-permission", sym);
-               }
-           }
-         else if (Prob *pb = unsmob_prob (sys))
-           pb->set_property ("page-break-permission", sym);
+         SCM symbol = ly_symbol2scm ("page-break-permission");
+         SCM permission = b ? ly_symbol2scm ("force") : SCM_EOL;
+         set_page_permission (sys, symbol, permission);
        }
     }
 }
 
-
 SCM
 Paper_book::get_score_title (SCM header)
 {
@@ -311,6 +317,14 @@ Paper_book::get_system_specs ()
          if (header_0_ == SCM_EOL)
            header_0_ = header;
        }
+      else if (Page_marker *page_marker = unsmob_page_marker (scm_car (s)))
+       {
+         /* a page marker: set previous element page break or turn permission 
*/
+         if (scm_is_pair (system_specs))
+           set_page_permission (scm_car (system_specs),
+                                page_marker->permission_symbol (),
+                                page_marker->permission_value ());
+       }
       else if (Music_output *mop = unsmob_music_output (scm_car (s)))
        {
          if (Paper_score *pscore = dynamic_cast<Paper_score *> (mop))
@@ -344,9 +358,6 @@ Paper_book::get_system_specs ()
          
          // TODO: init props
          Prob *ps = make_paper_system (SCM_EOL);
-         /* we don't have a way of specifying page-{break,turn} on
-            markup blocks, so for now we just set everything turnable
-           and breakable by default */
          ps->set_property ("page-break-permission", ly_symbol2scm ("allow"));
          ps->set_property ("page-turn-permission", ly_symbol2scm ("allow"));
          
diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly
index e6aad14..489f0d0 100644
--- a/ly/music-functions-init.ly
+++ b/ly/music-functions-init.ly
@@ -213,6 +213,34 @@ endSpanners =
        
        (ly:input-message location (_ "argument endSpanners is not an 
EventChord: ~a" music))))
 
+forbidPageBreak =
+#(define-music-function (location parser) ()
+   (_i "Forbid page break between two scores or top-level markups.")
+   (make-music 'Music 
+              'page-marker #t
+              'page-break-permission 'forbid))
+
+forcePageBreak =
+#(define-music-function (location parser) ()
+   (_i "Force a page break between two scores or top-level markups.")
+   (make-music 'Music 
+              'page-marker #t
+              'page-break-permission 'force))
+
+forbidPageTurn =
+#(define-music-function (location parser) ()
+   (_i "Forbid page turn between two scores or top-level markups.")
+   (make-music 'Music 
+              'page-marker #t
+              'page-turn-permission 'forbid))
+
+forcePageTurn =
+#(define-music-function (location parser) ()
+   (_i "Force a page turn between two scores or top-level markups.")
+   (make-music 'Music 
+              'page-marker #t
+              'page-turn-permission 'force))
+
 featherDurations=
 #(define-music-function (parser location factor argument) (ly:moment? 
ly:music?)
    (_i "Rearrange durations in ARGUMENT so there is an
diff --git a/scm/lily-library.scm b/scm/lily-library.scm
index e6215b9..7a86701 100644
--- a/scm/lily-library.scm
+++ b/scm/lily-library.scm
@@ -64,10 +64,27 @@
    (cons score (ly:parser-lookup parser 'toplevel-scores))))
 
 (define-public (collect-music-for-book parser music)
-  ;; discard music if its 'void property is true.
-  (let ((void-music (ly:music-property music 'void)))
-    (if (or (null? void-music) (not void-music))
-        (collect-scores-for-book parser (scorify-music music parser)))))
+  (define (music-property symbol)
+    (let ((value (ly:music-property music symbol)))
+      (if (not (null? value))
+         value
+         #f)))
+  (cond ((music-property 'page-marker)
+        ;; a page marker: set page break/turn permissions
+        (for-each (lambda (symbol)
+                    (let ((permission (music-property symbol)))
+                      (if (symbol? permission)
+                          (collect-scores-for-book
+                           parser
+                           (ly:make-page-marker symbol
+                                                (if (eqv? 'forbid permission)
+                                                    '()
+                                                    permission))))))
+                  '(page-break-permission page-turn-permission)))
+       ((not (music-property 'void))
+        ;; a regular music expression: make a score with this music
+        ;; void music is discarded
+        (collect-scores-for-book parser (scorify-music music parser)))))
 
 (define-public (scorify-music music parser)
   "Preprocess MUSIC."

reply via email to

[Prev in Thread] Current Thread [Next in Thread]