part last page and book last page.
#(set-default-paper-size "a6")
+\paper {
+ oddFooterMarkup = "toplevel paper footer"
+ id ="\ntoplevel paper\n"
+}
+
\book {
%% book-level paper, which is inherited by all bookparts
- \paper { ragged-last-bottom = ##t }
+ \paper {
+ id = "\nbook level paper\n"
+ ragged-last-bottom = ##t
+ %% Page footer: add a different part-tagline at part last page
+ oddFooterMarkup = \markup {
+ \column {
+ \fill-line {
+ %% Copyright header field only on book first page.
+ \on-the-fly #first-page \fromproperty #'header:copyright
+ }
+ \fill-line {
+ %% Part tagline header field only on each part last page.
+ \on-the-fly #part-last-page \fromproperty #'header:parttagline
+ }
+ \fill-line {
+ %% Tagline header field only on book last page.
+ \on-the-fly #last-page \fromproperty #'header:tagline
+ }
+ toto
+ }
+ }
+ }
%% book-level header, which is inherited by the first bookpart
- \header { title = "Book title" }
+ \header {
+ title = "Book title"
+ copyright = "Copyright line on book first page"
+ parttagline = "Part tagline"
+ tagline = "Book tagline"
+ }
+
%% first book part
\bookpart {
+ %% a different page breaking function may be used on each part
+ \paper { #(define page-breaking optimal-page-breaks) }
\header { subtitle = "First part" }
\markup { The first book part }
+ \markup { a page break }
+ \pageBreak
+ \markup { first part last page }
\markup \wordwrap { with ragged-last-bottom (see the space below this text) }
}
%% an other book part
Real
Page_breaking::page_height (int page_num, bool last) const
{
+ bool last_part = ly_scm2bool (book_->paper_->c_variable ("part-is-last"));
SCM mod = scm_c_resolve_module ("scm page");
SCM calc_height = scm_c_module_lookup (mod, "calc-printable-height");
SCM make_page = scm_c_module_lookup (mod, "make-page");
SCM page = scm_apply_0 (make_page, scm_list_n (
book_->self_scm (),
ly_symbol2scm ("page-number"), scm_from_int (page_num),
- ly_symbol2scm ("is-last"), scm_from_bool (last),
+ ly_symbol2scm ("is-last"), scm_from_bool (last_part && last),
+ ly_symbol2scm ("is-part-last"), scm_from_bool (last),
SCM_UNDEFINED));
SCM height = scm_apply_1 (calc_height, page, SCM_EOL);
return scm_to_double (height) - page_top_space_;
{
SCM page_num = scm_from_int (i + first_page_number);
bool last_from_part = (i == lines_per_page.size () - 1);
- SCM last_from_book = scm_from_bool (last_part && last_from_part);
+ bool last_from_book = (last_part && last_from_part);
SCM rag = scm_from_bool (ragged () || (last_from_part && ragged_last ()));
SCM line_count = scm_from_int (lines_per_page[i]);
SCM lines = scm_list_head (systems, line_count);
SCM page = scm_apply_0 (make_page,
- scm_list_n (book, lines, page_num,
- rag, last_from_book, SCM_UNDEFINED));
-
+ scm_list_n (book, lines, page_num, rag,
+ scm_from_bool (last_from_book),
+ scm_from_bool (last_from_part),
+ SCM_UNDEFINED));
/* collect labels */
for (SCM l = lines ; scm_is_pair (l) ; l = scm_cdr (l))
{
}
}
+%% Book first page and last page predicates
#(define (first-page layout props arg)
+ (define (ancestor layout)
+ "Return the topmost layout ancestor"
+ (let ((parent (ly:output-def-parent layout)))
+ (if (not (ly:output-def? parent))
+ layout
+ (ancestor parent))))
(if (= (chain-assoc-get 'page:page-number props -1)
- (ly:output-def-lookup layout 'first-page-number))
+ (ly:output-def-lookup (ancestor layout) 'first-page-number))
(interpret-markup layout props arg)
empty-stencil))
(interpret-markup layout props arg)
empty-stencil))
+%% Part first page and last page predicates
+#(define (part-first-page layout props arg)
+ (if (= (chain-assoc-get 'page:page-number props -1)
+ (ly:output-def-lookup layout 'first-page-number))
+ (interpret-markup layout props arg)
+ empty-stencil))
+
+#(define (part-last-page layout props arg)
+ (if (chain-assoc-get 'page:part-last? props #f)
+ (interpret-markup layout props arg)
+ empty-stencil))
+
#(define (not-first-page layout props arg)
(if (not (= (chain-assoc-get 'page:page-number props -1)
(ly:output-def-lookup layout 'first-page-number)))
(= (interval-start system-extent)
(interval-end system-extent))))))
-(define (stretch-and-draw-page paper-book systems page-number ragged last)
+(define (stretch-and-draw-page paper-book systems page-number ragged book-last part-last)
(define (max-stretch sys)
(if (ly:grob? sys)
(ly:grob-property sys 'max-stretch)
(let* ((page (make-page paper-book
'page-number page-number
- 'is-last last))
+ 'is-last book-last
+ 'is-part-last part-last))
(paper (ly:paper-book-paper paper-book))
(height (page-printable-height page))
; there is a certain amount of impreciseness going on here:
inter-system-space))
user)))
-(define (walk-paths done-lines best-paths current-lines last current-best
- paper-book page-alist)
+(define (walk-paths done-lines best-paths current-lines is-last-part
+ is-last-page current-best paper-book page-alist)
"Return the best optimal-page-break-node that contains
CURRENT-LINES. DONE-LINES.reversed ++ CURRENT-LINES is a consecutive
ascending range of lines, and BEST-PATHS contains the optimal breaks
(let* ((paper (ly:paper-book-paper paper-book))
(this-page (make-page
paper-book
- 'is-last last
+ 'is-last (and is-last-part is-last-page)
+ 'is-part-last is-last-page
'page-number (if (null? best-paths)
(ly:output-def-lookup paper 'first-page-number)
(1+ (page-page-number (first best-paths))))))
(ragged-all (eq? #t (ly:output-def-lookup paper 'ragged-bottom)))
(ragged-last (eq? #t (ly:output-def-lookup paper 'ragged-last-bottom)))
- (ragged (or ragged-all (and ragged-last last)))
+ (ragged (or ragged-all (and ragged-last is-last-page)))
(space-to-fill (page-maximum-space-to-fill this-page current-lines paper))
(vertical-spacing (space-systems space-to-fill current-lines ragged paper #f))
(satisfied-constraints (car vertical-spacing))
(force (if satisfied-constraints
- (if (and last ragged-last)
+ (if (and is-last-page ragged-last)
0.0
satisfied-constraints)
10000))
(list
"\nuser pen " user-penalty
"\nsatisfied-constraints" satisfied-constraints
- "\nlast? " last "ragged?" ragged
+ "\nlast? " is-last-page "ragged?" ragged
"\nis-better " is-better " total-penalty " total-penalty "\n"
"\nconfig " positions
"\nforce " force
satisfied-constraints)
(walk-paths (cdr done-lines) (cdr best-paths)
(cons (car done-lines) current-lines)
- last new-best
+ is-last-part is-last-page new-best
paper-book page-alist)
new-best)))
-(define (walk-lines done best-paths todo paper-book page-alist)
+(define (walk-lines done best-paths todo paper-book page-alist is-last-part)
"Return the best page breaking as a single
page node for optimally breaking TODO ++
DONE.reversed. BEST-PATHS is a list of break nodes corresponding to
(if (null? todo)
(car best-paths)
(let* ((this-line (car todo))
- (last (null? (cdr todo)))
- (next (walk-paths done best-paths (list this-line) last #f
- paper-book page-alist)))
+ (is-last-page (null? (cdr todo)))
+ (next (walk-paths done best-paths (list this-line) is-last-part
+ is-last-page #f paper-book page-alist)))
(walk-lines (cons this-line done)
(cons next best-paths)
(cdr todo)
paper-book
- page-alist))))
+ page-alist
+ is-last-part))))
(define-public (optimal-page-breaks paper-book)
"Return pages as a list starting with 1st page. Each page is a 'page Prob."
(lines (ly:paper-book-systems paper-book))
(page-alist (layout->page-init paper))
(force-equalization-factor (ly:output-def-lookup
- paper 'verticalequalizationfactor 0.3)))
+ paper 'verticalequalizationfactor 0.3))
+ (part-is-last (ly:output-def-lookup paper 'part-is-last)))
(ly:message (_ "Calculating page breaks..."))
- (let* ((best-break-node (walk-lines '() '() lines paper-book page-alist))
+ (let* ((best-break-node (walk-lines '() '() lines paper-book page-alist part-is-last))
(break-nodes (get-path best-break-node '())))
- (page-set-property! (car (last-pair break-nodes)) 'is-last #t)
+ ;(page-set-property! (car (last-pair break-nodes)) 'is-last part-is-last)
+ ;(page-set-property! (car (last-pair break-nodes)) 'is-part-last #t)
(if #f; (ly:get-option 'verbose)
(begin
(display (list
\f
-(define (page-headfoot layout scopes number
- sym separation-symbol dir last?)
+(define (page-headfoot layout scopes number sym separation-symbol dir
+ is-book-last-page is-part-last-page)
"Create a stencil including separating space."
(stencil (ly:make-stencil "" '(0 . 0) '(0 . 0)))
(head-stencil
(if (procedure? header-proc)
- (header-proc layout scopes number last?)
- #f))
- )
+ (header-proc layout scopes number is-book-last-page is-part-last-page)
+ #f)))
(if (and (number? sep)
(ly:stencil? head-stencil)
(layout (ly:paper-book-paper paper-book))
(scopes (ly:paper-book-scopes paper-book))
(number (page-page-number page))
- (last? (page-property page 'is-last))
- )
+ (is-book-last-page (page-property page 'is-last))
+ (is-part-last-page (page-property page 'is-part-last)))
(page-headfoot layout scopes number
(if (= dir UP)
(if (= dir UP)
'head-separation
'foot-separation)
- dir last?)))
+ dir is-book-last-page is-part-last-page)))
(define (page-header page)
(page-header-or-footer page UP))
;;;;;;;;;;;;;;;;;;
-(define-public ((marked-up-headfoot what-odd what-even) layout scopes page-number last?)
+(define-public ((marked-up-headfoot what-odd what-even)
+ layout scopes page-number is-book-last-page is-part-last-page)
"Read variables WHAT-ODD, WHAT-EVEN from LAYOUT, and interpret them
as markup. The PROPS argument will include variables set in SCOPES and
(cons 'header:tagline
(ly:modules-lookup scopes 'tagline
(ly:output-def-lookup layout 'tagline)))
- (cons 'page:last? last?)
+ (cons 'page:last? is-book-last-page)
+ (cons 'page:part-last? is-part-last-page)
(cons 'page:page-number-string
(number->string page-number))
(cons 'page:page-number page-number)))