From 3f20c6178c3090afdf495f66b595677388a21629 Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Wed, 16 May 2012 16:47:41 +0200 Subject: [PATCH] Make \footnote work via \tweak --- lily/footnote-engraver.cc | 36 ++++++++++++++++++++- lily/grob.cc | 1 + ly/music-functions-init.ly | 57 ++++++++++++++++++++++++---------- python/convertrules.py | 14 +++++++++ scm/define-grob-properties.scm | 1 + 5 files changed, 91 insertions(+), 18 deletions(-) diff --git a/lily/footnote-engraver.cc b/lily/footnote-engraver.cc index 4a2070a6cd..78d2f0e6d3 100644 --- a/lily/footnote-engraver.cc +++ b/lily/footnote-engraver.cc @@ -19,7 +19,9 @@ #include "engraver.hh" +#include "music.hh" #include "stream-event.hh" +#include "international.hh" #include "item.hh" #include "pointer-group-interface.hh" #include "spanner.hh" @@ -39,6 +41,7 @@ class Footnote_engraver : public Engraver void stop_translation_timestep (); void finalize (); + virtual void derived_mark () const; void footnotify (Grob *, Stream_event *); }; @@ -59,7 +62,14 @@ Footnote_engraver::stop_translation_timestep () void Footnote_engraver::finalize () { - annotated_spanners_.resize (0); + annotated_spanners_.clear (); +} + +void +Footnote_engraver::derived_mark () const +{ + for (vsize i = 0; i < events_.size (); ++i) + scm_gc_mark (events_[i]->self_scm ()); } Footnote_engraver::Footnote_engraver () @@ -91,6 +101,26 @@ Footnote_engraver::footnotify (Grob *g, Stream_event *event) void Footnote_engraver::acknowledge_grob (Grob_info info) { + Music *mus = unsmob_music (info.grob ()->get_property ("footnote-music")); + + if (mus) + { + if (!mus->is_mus_type ("footnote-event")) { + mus->origin ()->programming_error (_ ("Must be footnote-event.")); + return; + } + Stream_event *ev = mus->to_event (context ()); + footnotify (info.grob (), ev); + ev->unprotect (); + return; + } + + // The following performance hog should eventually be removed: + // instead of adding a -\footnote ... \default articulation at the + // end of a note, you can perfectly well use \footnote ... before + // the note. This is just for the sake of automatic convert-ly + // rules. + Stream_event *cause = info.event_cause (); SCM arts = cause ? cause->get_property ("articulations") : SCM_EOL; @@ -101,6 +131,10 @@ Footnote_engraver::acknowledge_grob (Grob_info info) footnotify (info.grob (), e); } + // In contrast, the following code is only called when actual + // footnote events have been listened to. It should not affect + // performance. + for (vsize i = 0; i < events_.size (); i++) { if (info.grob ()->name () == ly_symbol2string (events_[i]->get_property ("symbol"))) diff --git a/lily/grob.cc b/lily/grob.cc index ed96f1d13a..cc39c979f0 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -799,6 +799,7 @@ ADD_INTERFACE (Grob, "extra-X-extent " "extra-Y-extent " "extra-offset " + "footnote-music " "forced-spacing " "interfaces " "layer " diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly index f9f6ef7b35..21f6c51fd7 100644 --- a/ly/music-functions-init.ly +++ b/ly/music-functions-init.ly @@ -342,23 +342,46 @@ featherDurations= argument)) footnote = -#(define-music-function (parser location text offset grob-name footnote) - ((markup?) number-pair? (symbol? '()) markup?) - (_i "Attach @var{text} at @var{offset} with @var{text} referring to -@var{footnote}. If @var{text} is given as @code{\\default}, use -autonumbering instead. Note that, for this to take effect, -auto-numbering must be turned on in the paper block. Otherwise, no -number will appear. Footnotes are applied like articulations. If a -symbol @var{grob-name} is specified, all grobs of that kind at the -current time step are affected.") - (make-music - 'FootnoteEvent - 'X-offset (car offset) - 'Y-offset (cdr offset) - 'automatically-numbered (not text) - 'text (or text (make-null-markup)) - 'footnote-text footnote - 'symbol grob-name)) +#(define-music-function (parser location mark offset grob-name footnote music) + ((markup?) number-pair? (symbol?) markup? (ly:music?)) + (_i "Make the markup @var{footnote} a footnote on @var{music}. The +footnote is marked with a markup @var{mark} moved by @var{offset} with +respect to the marked music. + +If @var{mark} is not given or specified as @var{\\default}, it is +replaced by an automatically generated sequence number. If a symbol +@var{grob-name} is specified, then grobs of that type will be marked +if they have @var{music} as their ultimate cause; by default all grobs +having @var{music} as their @emph{direct} cause will be marked, +similar to the way @code{\\tweak} works. + +If @var{music} is given as @code{\\default}, a footnote event +affecting @emph{all} grobs matching @var{grob-name} at a given time +step is generated. This may be required for creating footnotes on +time signatures, clefs, and other items not cooperating with +@code{\\tweak}. + +Like with @code{\\tweak}, if you use a footnote on a following +post-event, the @code{\\footnote} command itself needs to be attached +to the preceding note or rest as a post-event with @code{-}.") + (let ((mus (make-music + 'FootnoteEvent + 'X-offset (car offset) + 'Y-offset (cdr offset) + 'automatically-numbered (not mark) + 'text (or mark (make-null-markup)) + 'footnote-text footnote + 'symbol (or grob-name '())))) + (if music + (begin + (set! (ly:music-property music 'tweaks) + (acons (if grob-name + (cons grob-name 'footnote-music) + 'footnote-music) + mus + (ly:music-property music 'tweaks))) + music) + mus))) grace = #(def-grace-function startGraceMusic stopGraceMusic diff --git a/python/convertrules.py b/python/convertrules.py index 5c94c59e1f..2bfbdce1eb 100644 --- a/python/convertrules.py +++ b/python/convertrules.py @@ -3346,6 +3346,20 @@ def conv (str): sub_tempo, str) return str +@rule((2, 15, 39), r"\footnote ... -> \footnote ... \default") +def conv (str): + def not_first (s): + def match_fun (m): + if m.group (1): + return m.group (0) + return m.expand (s) + return match_fun + str = re.sub ("(" + matchmarkup + ")|" + + r"(\\footnote(?:\s*" + + matchmarkup + ")?" + matcharg + "(?:" + matcharg + + ")?\s+" + matchmarkup + ")", + not_first (r"\2 \\default"), str) + return str # Guidelines to write rules (please keep this at the end of this file) # diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index fba256f4bf..6502dd9d72 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -307,6 +307,7 @@ include @code{upright}, @code{italic}, @code{caps}.") approximately 12% larger; 6@tie{}steps are exactly a factor@tie{}2 larger. Fractional values are allowed.") (footnote ,boolean? "Should this be a footnote or in-note?") + (footnote-music ,ly:music? "Music creating a footnote.") (footnote-text ,markup? "A footnote for the grob.") (force-hshift ,number? "This specifies a manual shift for notes in collisions. The unit is the note head width of the first voice -- 2.39.2