From: Nicolas Sceaux Date: Thu, 17 May 2007 08:31:28 +0000 (+0200) Subject: Add a new kind of object, Page_marker, at the same level as scores and X-Git-Tag: release/2.11.25-1~9^2~5^2~4 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=5bb1618e65e0b8031b9aed8d5f218986e3d3c5a0;p=lilypond.git Add a new kind of object, Page_marker, at the same level as scores and markups, holding page breaking and page turning information, and which can be used to create top-level page breaking and page turning directives. Thus, \pageBreak, \noPageBreak, etc, can be used at top-level, between scores and top-level markups. --- diff --git a/lily/book.cc b/lily/book.cc index bf28d1b57d..265632a365 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 0000000000..a925a6c9ce --- /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 +*/ + +#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 0000000000..3278a7b013 --- /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 +*/ + +#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 0000000000..dd43c35640 --- /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 +*/ + +#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 ("#", 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 c6bcccde7a..95be368234 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 (unsmob_music_output (sys))) + { + vector cols = ps->get_columns (); + if (cols.size ()) + { + Paper_column *col = dynamic_cast (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 @@ -239,26 +257,19 @@ set_system_penalty (SCM sys, SCM header) if (SCM_VARIABLEP (force) && 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 (unsmob_music_output (sys))) + if (to_boolean (SCM_VARIABLE_REF (force))) { - vector cols = ps->get_columns (); - if (cols.size ()) - { - Paper_column *col = dynamic_cast (cols.back ()); - col->set_property ("page-break-permission", sym); - col->find_prebroken_piece (LEFT)->set_property ("page-break-permission", sym); - } + set_page_permission (sys, ly_symbol2scm ("page-break-permission"), + ly_symbol2scm ("force")); + set_page_permission (sys, ly_symbol2scm ("line-break-permission"), + ly_symbol2scm ("force")); } - else if (Prob *pb = unsmob_prob (sys)) - pb->set_property ("page-break-permission", sym); + else + set_page_permission (sys, ly_symbol2scm ("page-break-permission"), SCM_EOL); } } } - SCM Paper_book::get_score_title (SCM header) { @@ -311,6 +322,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 (mop)) @@ -344,9 +363,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/declarations-init.ly b/ly/declarations-init.ly index 17329521a0..015e6dc754 100644 --- a/ly/declarations-init.ly +++ b/ly/declarations-init.ly @@ -38,16 +38,8 @@ center = #0 %% rather name \newline, \pageBreak ? break = #(make-event-chord (list (make-music 'LineBreakEvent 'break-permission 'force))) noBreak = #(make-event-chord (list (make-music 'LineBreakEvent 'break-permission '()))) -pageBreak = #(make-event-chord (list - (make-music 'LineBreakEvent 'break-permission 'force) - (make-music 'PageBreakEvent 'break-permission 'force))) -noPageBreak = #(make-event-chord (list (make-music 'PageBreakEvent 'break-permission '()))) -pageTurn = #(make-event-chord (list - (make-music 'LineBreakEvent 'break-permission 'force) - (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))) +%% \pageBreak, \noPageBreak, \pageTurn, \noPageTurn, \allowPageTurn are defined +%% as music functions stopStaff = #(make-event-chord (list (make-span-event 'StaffSpanEvent STOP))) startStaff = #(make-event-chord (list (make-span-event 'StaffSpanEvent START))) diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index e6aad14133..8360dcbe84 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -349,6 +349,65 @@ or @code{\"GrobName\"}") grob-name) (set! (ly:grob-property grob property) value)))))) +%% These are music functions (iso music indentifiers), because music identifiers +%% are not allowed at top-level. +pageBreak = +#(define-music-function (location parser) () + (_i "Force a page break. May be used at toplevel (ie between scores or +markups), or inside a score.") + (make-music 'EventChord + 'page-marker #t + 'line-break-permission 'force + 'page-break-permission 'force + 'elements (list (make-music 'LineBreakEvent + 'break-permission 'force) + (make-music 'PageBreakEvent + 'break-permission 'force)))) + +noPageBreak = +#(define-music-function (location parser) () + (_i "Forbid a page break. May be used at toplevel (ie between scores or +markups), or inside a score.") + (make-music 'EventChord + 'page-marker #t + 'page-break-permission 'forbid + 'elements (list (make-music 'PageBreakEvent + 'break-permission '())))) + +pageTurn = +#(define-music-function (location parser) () + (_i "Force a page turn between two scores or top-level markups.") + (make-music 'EventChord + 'page-marker #t + 'line-break-permission 'force + 'page-break-permission 'force + 'page-turn-permission 'force + 'elements (list (make-music 'LineBreakEvent + 'break-permission 'force) + (make-music 'PageBreakEvent + 'break-permission 'force) + (make-music 'PageTurnEvent + 'break-permission 'force)))) + +noPageTurn = +#(define-music-function (location parser) () + (_i "Forbid a page turn. May be used at toplevel (ie between scores or +markups), or inside a score.") + (make-music 'EventChord + 'page-marker #t + 'page-turn-permission 'forbid + 'elements (list (make-music 'PageTurnEvent + 'break-permission '())))) + +allowPageTurn = +#(define-music-function (location parser) () + (_i "Allow a page turn. May be used at toplevel (ie between scores or +markups), or inside a score.") + (make-music 'EventChord + 'page-marker #t + 'page-turn-permission 'allow + 'elements (list (make-music 'PageTurnEvent + 'break-permission 'allow)))) removeWithTag = #(define-music-function diff --git a/scm/lily-library.scm b/scm/lily-library.scm index e6215b9823..2758825016 100644 --- a/scm/lily-library.scm +++ b/scm/lily-library.scm @@ -64,10 +64,28 @@ (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)))))) + (list 'line-break-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."