From 5ac2664c2207e8dfa1734d786e5c7b214b275521 Mon Sep 17 00:00:00 2001 From: Mike Solomon Date: Fri, 2 Dec 2011 08:06:13 +0100 Subject: [PATCH] Adds a numbering-assertion-function property to the footnote grob. This allows the footnote regtests to verify that the footnotes are being numbered in the correct order. --- .../footnote-auto-numbering-vertical-order.ly | 97 +++++++++++++++++++ input/regression/footnote-auto-numbering.ly | 28 +++++- lily/include/page-layout-problem.hh | 1 + lily/page-layout-problem.cc | 29 ++++-- scm/define-grob-interfaces.scm | 5 +- scm/define-grob-properties.scm | 2 + 6 files changed, 151 insertions(+), 11 deletions(-) create mode 100644 input/regression/footnote-auto-numbering-vertical-order.ly diff --git a/input/regression/footnote-auto-numbering-vertical-order.ly b/input/regression/footnote-auto-numbering-vertical-order.ly new file mode 100644 index 0000000000..c7862a98b3 --- /dev/null +++ b/input/regression/footnote-auto-numbering-vertical-order.ly @@ -0,0 +1,97 @@ +\version "2.15.21" +\header { + texidoc = "This regtest makes sure that footnote numbers are laid out +in the correct vertical order. +" +} + +#(define (make-footnote-numbering-assertion-function n) + (lambda (x) + (if (not (= n x)) + (ly:error (_ "Expecting number ~a, got ~a") n x)))) + +#(define (simultaneous-footnote-numbering-assertion-function x y) + (lambda (grob) + (let ((n (if (grob::has-interface (ly:grob-parent grob Y) + 'beam-interface) + x + y))) + (lambda (x) + (if (not (= n x)) + (ly:error (_ "Expecting number ~a, got ~a") n x)))))) + +\paper { + reset-footnotes-on-new-page = ##f +} + +#(set-default-paper-size "a6") +\book { + \score { + << + \new Staff \relative c' { + d4 e + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 0)) + < f a-\autoFootnote #'(1 . -1) \markup { n } c > + \once \override FootnoteSpanner #'numbering-assertion-function = + #(simultaneous-footnote-numbering-assertion-function 2 4) + \autoFootnoteGrob #'Beam #'(1 . 1) \markup { o } + \autoFootnoteGrob #'Hairpin #'(1 . 1) \markup { p } + a8\< [ b c d ] a4 b c\f | + d a b c |\break + d,4 e + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 6)) + < f a-\autoFootnote #'(1 . -1) \markup { n } c > + \once \override FootnoteSpanner #'numbering-assertion-function = + #(simultaneous-footnote-numbering-assertion-function 8 10) + \autoFootnoteGrob #'Beam #'(1 . 1) \markup { o } + \autoFootnoteGrob #'Hairpin #'(1 . 1) \markup { p } + a8\< [ b c d ] a4 b c | + d a b c\f |\pageBreak + d,4 e + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 12)) + < f a-\autoFootnote #'(1 . -1) \markup { n } c > + \once \override FootnoteSpanner #'numbering-assertion-function = + #(simultaneous-footnote-numbering-assertion-function 14 16) + \autoFootnoteGrob #'Beam #'(1 . 1) \markup { o } + \autoFootnoteGrob #'Hairpin #'(1 . 1) \markup { p } + a8\< [ b c d ] a4 b c | + d a b c\! |\break + } + \new Staff \relative c' { + d4 e + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 1)) + < f a-\autoFootnote #'(1 . -1) \markup { n } c > + \once \override FootnoteSpanner #'numbering-assertion-function = + #(simultaneous-footnote-numbering-assertion-function 3 5) + \autoFootnoteGrob #'Beam #'(1 . 1) \markup { o } + \autoFootnoteGrob #'Hairpin #'(1 . 1) \markup { p } + a8\< [ b c d ] a4 b c\f | + d a b c |\break + d,4 e + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 7)) + < f a-\autoFootnote #'(1 . -1) \markup { n } c > + \once \override FootnoteSpanner #'numbering-assertion-function = + #(simultaneous-footnote-numbering-assertion-function 9 11) + \autoFootnoteGrob #'Beam #'(1 . 1) \markup { o } + \autoFootnoteGrob #'Hairpin #'(1 . 1) \markup { p } + a8\< [ b c d ] a4 b c | + d a b c\f |\pageBreak + d,4 e + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 13)) + < f a-\autoFootnote #'(1 . -1) \markup { n } c > + \once \override FootnoteSpanner #'numbering-assertion-function = + #(simultaneous-footnote-numbering-assertion-function 15 17) + \autoFootnoteGrob #'Beam #'(1 . 1) \markup { o } + \autoFootnoteGrob #'Hairpin #'(1 . 1) \markup { p } + a8\< [ b c d ] a4 b c | + d a b c\! |\break + } + >> + } +} diff --git a/input/regression/footnote-auto-numbering.ly b/input/regression/footnote-auto-numbering.ly index 790278288b..0461597eac 100644 --- a/input/regression/footnote-auto-numbering.ly +++ b/input/regression/footnote-auto-numbering.ly @@ -1,4 +1,4 @@ -\version "2.15.7" +\version "2.15.21" \header { texidoc = "This is an example of automatic footnote numbering where the number is not reset on each page. It uses the default @@ -7,6 +7,21 @@ footnotes. " } +#(define (make-footnote-numbering-assertion-function n) + (lambda (x) + (if (not (= n x)) + (ly:error (_ "Expecting number ~a, got ~a") n x)))) + +#(define (simultaneous-footnote-numbering-assertion-function x y) + (lambda (grob) + (let ((n (if (grob::has-interface (ly:grob-parent grob Y) + 'beam-interface) + x + y))) + (lambda (x) + (if (not (= n x)) + (ly:error (_ "Expecting number ~a, got ~a") n x)))))) + \paper { reset-footnotes-on-new-page = ##f } @@ -23,8 +38,11 @@ footnotes. \markup { h i } \relative c' { -\autoFootnoteGrob #'NoteHead #'(1 . -1) \markup { j } -a b c d } + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 3)) + \autoFootnoteGrob #'NoteHead #'(1 . -1) \markup { j } + a b c d +} \pageBreak @@ -34,7 +52,11 @@ a b c d } \relative c' { d4 e + \once \override FootnoteItem #'numbering-assertion-function = + #(lambda (grob) (make-footnote-numbering-assertion-function 5)) < f a-\autoFootnote #'(1 . -1) \markup { n } c > + \once \override FootnoteSpanner #'numbering-assertion-function = + #(simultaneous-footnote-numbering-assertion-function 6 7) \autoFootnoteGrob #'Beam #'(1 . 1) \markup { o } \autoFootnoteGrob #'Hairpin #'(1 . 1) \markup { p } a8\< [ b c d ] a4 b c | diff --git a/lily/include/page-layout-problem.hh b/lily/include/page-layout-problem.hh index 665f15396b..c0577b9ab0 100644 --- a/lily/include/page-layout-problem.hh +++ b/lily/include/page-layout-problem.hh @@ -34,6 +34,7 @@ public: static bool read_spacing_spec (SCM spec, Real *dest, SCM sym); static bool is_spaceable (Grob *g); static SCM get_details (Grob *g); + static vector get_footnote_grobs (SCM lines); static vsize get_footnote_count (SCM lines); static SCM get_footnotes_from_lines (SCM lines); static void add_footnotes_to_lines (SCM lines, int counter, Paper_book *pb); diff --git a/lily/page-layout-problem.cc b/lily/page-layout-problem.cc index 319ba396f1..f4e2085218 100644 --- a/lily/page-layout-problem.cc +++ b/lily/page-layout-problem.cc @@ -38,10 +38,10 @@ Returns the number of footntoes associated with a given line. */ -vsize -Page_layout_problem::get_footnote_count (SCM lines) +vector +Page_layout_problem::get_footnote_grobs (SCM lines) { - vsize fn_count = 0; + vector footnotes; for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s)) { if (Grob *g = unsmob_grob (scm_car (s))) @@ -52,7 +52,8 @@ Page_layout_problem::get_footnote_count (SCM lines) programming_error ("got a grob for footnotes that wasn't a System"); continue; } - fn_count += sys->num_footnotes (); + extract_grob_set (sys, "footnotes-after-line-breaking", footnote_grobs); + footnotes.insert (footnotes.end (), footnote_grobs.begin (), footnote_grobs.end ()); } else if (Prob *p = unsmob_prob (scm_car (s))) { @@ -60,11 +61,18 @@ Page_layout_problem::get_footnote_count (SCM lines) if (stencils == SCM_EOL) continue; for (SCM st = stencils; scm_is_pair (st); st = scm_cdr (st)) - fn_count++; + footnotes.push_back (0); } } - return fn_count; + return footnotes; +} + +vsize +Page_layout_problem::get_footnote_count (SCM lines) +{ + vector notes = get_footnote_grobs (lines); + return notes.size (); } SCM @@ -137,7 +145,8 @@ Page_layout_problem::add_footnotes_to_lines (SCM lines, int counter, Paper_book Real padding = robust_scm2double (paper->c_variable ("footnote-padding"), 0.0); Real number_raise = robust_scm2double (paper->c_variable ("footnote-number-raise"), 0.0); - vsize fn_count = get_footnote_count (lines); + vector fn_grobs = get_footnote_grobs (lines); + vsize fn_count = fn_grobs.size (); // now, make the footnote stencils with the numbering function SCM numbers = SCM_EOL; @@ -156,6 +165,12 @@ Page_layout_problem::add_footnotes_to_lines (SCM lines, int counter, Paper_book vector footnote_number_stencils; // Holds translated versions of the stencilized numbering markups. for (vsize i = 0; i < fn_count; i++) { + if (fn_grobs[i]) + { + SCM assertion_function = fn_grobs[i]->get_property ("numbering-assertion-function"); + if (ly_is_procedure (assertion_function)) + (void) scm_call_1 (assertion_function, scm_from_int (counter)); + } SCM markup = scm_call_1 (numbering_function, scm_from_int (counter)); Stencil *s = unsmob_stencil (Text_interface::interpret_markup (layout, props, markup)); if (!s) diff --git a/scm/define-grob-interfaces.scm b/scm/define-grob-interfaces.scm index 2047d6c630..b17a6a995d 100644 --- a/scm/define-grob-interfaces.scm +++ b/scm/define-grob-interfaces.scm @@ -84,7 +84,10 @@ note)." (ly:add-interface 'footnote-interface "Make a footnote." - '(automatically-numbered footnote footnote-text)) + '(automatically-numbered + footnote + footnote-text + numbering-assertion-function)) (ly:add-interface 'footnote-spanner-interface diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 2b67674fb1..c26bd3cae1 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -1153,6 +1153,8 @@ entries @code{name} and @code{interfaces}.") (note-collision ,ly:grob? "The @code{NoteCollision} object of a dot column.") + (numbering-assertion-function ,scheme? "The function used to assert +that footnotes are receiving correct automatic numbers.") (positioning-done ,boolean? "Used to signal that a positioning element did its job. This ensures that a positioning is only done once.") -- 2.39.2