From 05349bcf5d3be935173bb0cef4bc674174f68f9c Mon Sep 17 00:00:00 2001 From: Neil Puttock Date: Sun, 18 Apr 2010 20:13:15 +0100 Subject: [PATCH] Fix #786. Send a CompletizeExtenderEvent at the end of each lyrics block so that the Extender_engraver can tie up loose ends with any pending extender. * input/regression (display-lily-tests.ly): add extra space to \lyricsto and \addlyrics test to account for silenced display method * lily/extender-engraver.cc: add listener for CompletizeExtenderEvent which will call completize_extender () if necessary revert previous fix which checked for empty LyricText grob * lily/hyphen-engraver.cc: revert fix as above * lily/lyric-engraver.cc (process_music): don't create empty LyricText grobs * scm/define-event-classes.scm (event-classes): add completize-extender-event as child of music-event * scm/define-music-display-methods.scm: add display method for CompletizeExtenderEvent (returns empty string) * scm/define-music-types.scm (music-descriptions): add CompletizeExtenderEvent * scm/ly-syntax-constructors.scm (lyric-combine-music): insert CompletizeExtenderEvent at the end of the sequential music (i.e., following the last lyric) --- input/regression/display-lily-tests.ly | 6 ++-- lily/extender-engraver.cc | 61 +++++++++++++++------------------- lily/hyphen-engraver.cc | 18 ++++------ lily/lyric-engraver.cc | 9 ++--- scm/define-event-classes.scm | 2 +- scm/define-music-display-methods.scm | 4 ++- scm/define-music-types.scm | 7 ++++ scm/ly-syntax-constructors.scm | 5 +++ 8 files changed, 56 insertions(+), 56 deletions(-) diff --git a/input/regression/display-lily-tests.ly b/input/regression/display-lily-tests.ly index 35e18c7aee..1a88515126 100644 --- a/input/regression/display-lily-tests.ly +++ b/input/regression/display-lily-tests.ly @@ -1,4 +1,4 @@ -\version "2.12.0" +\version "2.13.19" #(use-modules (srfi srfi-13) (ice-9 format)) @@ -100,9 +100,9 @@ stderr of this run." \test "" ##[ \lyricmode { a -- b } #] % HyphenEvent \test "" ##[ \lyricmode { a __ b } #] % ExtenderEvent \test "" ##[ \lyricmode { "a " } #] % LyricEvent -\test "" ##[ \lyricsto "foo" { bla bla } #] % LyricCombineMusic +\test "" ##[ \lyricsto "foo" { bla bla } #] % LyricCombineMusic \test "" ##[ { { c d } - \addlyrics { bla bla } } #] + \addlyrics { bla bla } } #] %% Drums \test "" ##[ \drums { hihat } #] diff --git a/lily/extender-engraver.cc b/lily/extender-engraver.cc index 097b47912b..250430ba3f 100644 --- a/lily/extender-engraver.cc +++ b/lily/extender-engraver.cc @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with LilyPond. If not, see . */ + #include "context.hh" #include "engraver.hh" #include "international.hh" @@ -28,8 +29,6 @@ #include "stream-event.hh" #include "warn.hh" #include "spanner.hh" -#include "paper-column.hh" - #include "translator.icc" void completize_extender (Spanner *sp); @@ -39,13 +38,13 @@ class Extender_engraver : public Engraver Stream_event *ev_; Spanner *extender_; Spanner *pending_extender_; - bool current_lyric_is_skip_; public: TRANSLATOR_DECLARATIONS (Extender_engraver); protected: DECLARE_TRANSLATOR_LISTENER (extender); + DECLARE_TRANSLATOR_LISTENER (completize_extender); DECLARE_ACKNOWLEDGER (lyric_syllable); virtual void finalize (); @@ -56,7 +55,6 @@ protected: Extender_engraver::Extender_engraver () { - current_lyric_is_skip_ = false; extender_ = 0; pending_extender_ = 0; ev_ = 0; @@ -69,6 +67,24 @@ Extender_engraver::listen_extender (Stream_event *ev) ASSIGN_EVENT_ONCE (ev_, ev); } + +/* + A CompletizeExtenderEvent is sent at the end of each lyrics block + to ensure any pending extender can be correctly terminated if the lyrics + end before the associated voice (this prevents the right bound being extended + to the next note-column if no lyric follows the extender) +*/ +IMPLEMENT_TRANSLATOR_LISTENER (Extender_engraver, completize_extender); +void +Extender_engraver::listen_completize_extender (Stream_event * /* ev */) +{ + if (pending_extender_) + { + completize_extender (pending_extender_); + pending_extender_ = 0; + } +} + void Extender_engraver::process_music () { @@ -83,10 +99,7 @@ Extender_engraver::acknowledge_lyric_syllable (Grob_info i) if (extender_) extender_->set_bound (LEFT, item); - SCM text = item->get_property ("text"); - current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" ")); - - if (pending_extender_ && !current_lyric_is_skip_) + if (pending_extender_) { pending_extender_->set_object ("next", item->self_scm ()); completize_extender (pending_extender_); @@ -110,31 +123,12 @@ Extender_engraver::stop_translation_timestep () ly_symbol2scm ("heads"), h); } - if (pending_extender_) - { - Pointer_group_interface::add_grob (pending_extender_, - ly_symbol2scm ("heads"), h); - /* - The following check addresses the case where the lyrics end before - the associated voice. The current_lyric_is_skip_ check is - necessary to handle manual melismata, which should not result in - extenders being completized. We also need to make sure that we're not - in the middle of a note (happens when this function is called because - of an event in a voice other than our associated one). - */ - if (!melisma_busy (voice) && !current_lyric_is_skip_) - { - Moment now = voice->now_mom (); - Paper_column *column = (dynamic_cast (h))->get_column (); - Moment *start_mom = column ? unsmob_moment (column->get_property ("when")) : 0; - if (!column || (start_mom->main_part_ == now.main_part_)) - { - completize_extender (pending_extender_); - pending_extender_ = 0; - } - } - } - } + if (pending_extender_) + { + Pointer_group_interface::add_grob (pending_extender_, + ly_symbol2scm ("heads"), h); + } + } else { if (pending_extender_ @@ -143,7 +137,6 @@ Extender_engraver::stop_translation_timestep () completize_extender (pending_extender_); pending_extender_ = 0; } - } if (extender_) { diff --git a/lily/hyphen-engraver.cc b/lily/hyphen-engraver.cc index 24b8665e80..223fd1f05a 100644 --- a/lily/hyphen-engraver.cc +++ b/lily/hyphen-engraver.cc @@ -36,7 +36,6 @@ class Hyphen_engraver : public Engraver Spanner *hyphen_; Spanner *finished_hyphen_; - bool current_lyric_is_skip_; public: TRANSLATOR_DECLARATIONS (Hyphen_engraver); @@ -54,7 +53,6 @@ protected: Hyphen_engraver::Hyphen_engraver () { - current_lyric_is_skip_ = false; hyphen_ = 0; finished_hyphen_ = 0; finished_ev_ = 0; @@ -65,16 +63,14 @@ void Hyphen_engraver::acknowledge_lyric_syllable (Grob_info i) { Item *item = i.item (); - SCM text = item->get_property ("text"); - current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" ")); - - if (!hyphen_ && !current_lyric_is_skip_) + + if (!hyphen_) hyphen_ = make_spanner ("LyricSpace", item->self_scm ()); if (hyphen_) hyphen_->set_bound (LEFT, item); - - if (finished_hyphen_ && !current_lyric_is_skip_) + + if (finished_hyphen_) finished_hyphen_->set_bound (RIGHT, item); } @@ -141,8 +137,8 @@ Hyphen_engraver::stop_translation_timestep () finished_hyphen_ = 0; finished_ev_ = 0; } - - if (finished_hyphen_ && hyphen_ && !current_lyric_is_skip_) + + if (finished_hyphen_ && hyphen_) { programming_error ("hyphen not finished yet"); finished_hyphen_ = 0; @@ -154,7 +150,7 @@ Hyphen_engraver::stop_translation_timestep () finished_hyphen_ = hyphen_; finished_ev_ = ev_; } - + hyphen_ = 0; ev_ = 0; } diff --git a/lily/lyric-engraver.cc b/lily/lyric-engraver.cc index 999efaaa75..0e18fbef22 100644 --- a/lily/lyric-engraver.cc +++ b/lily/lyric-engraver.cc @@ -75,11 +75,8 @@ Lyric_engraver::process_music () if (last_text_) last_text_->set_property ("self-alignment-X", scm_from_int (LEFT)); } - /* - "Empty" LyricText objects are needed to allow the Extender_engraver to - distinguish between the end of a lyrics block and manual melismata. - */ - text_ = make_item ("LyricText", event_->self_scm ()); + else + text_ = make_item ("LyricText", event_->self_scm ()); } } @@ -167,7 +164,7 @@ Lyric_engraver::stop_translation_timestep () if (melisma_busy (voice) && !to_boolean (get_property ("ignoreMelismata"))) text_->set_property ("self-alignment-X", - get_property("lyricMelismaAlignment")); + get_property ("lyricMelismaAlignment")); } else { diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm index 70387c8c26..d9bbceb3c2 100644 --- a/scm/define-event-classes.scm +++ b/scm/define-event-classes.scm @@ -34,7 +34,7 @@ harmonic-event hyphen-event laissez-vibrer-event mark-event multi-measure-text-event note-grouping-event pes-or-flexa-event repeat-tie-event spacing-section-event - layout-instruction-event)) + layout-instruction-event completize-extender-event)) (layout-instruction-event . (apply-output-event )) (script-event . (articulation-event text-script-event)) diff --git a/scm/define-music-display-methods.scm b/scm/define-music-display-methods.scm index cda14bcbde..e0df840e89 100644 --- a/scm/define-music-display-methods.scm +++ b/scm/define-music-display-methods.scm @@ -1202,4 +1202,6 @@ Otherwise, return #f." (music->lily-string ?lyric-sequence parser))) #f))) - +;; Silence internal event sent at end of each lyrics block +(define-display-method CompletizeExtenderEvent (expr parser) + "") diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm index 60d66e03c6..e9dcee38cf 100644 --- a/scm/define-music-types.scm +++ b/scm/define-music-types.scm @@ -138,6 +138,13 @@ Syntax: @var{note}@code{\\breathe}") rhythmic-event event)) )) + (CompletizeExtenderEvent + . ((description . "Used internally to signal the end of a lyrics block to +ensure extenders are completed correctly when a @code{Lyrics} context ends +before its associated @code{Voice} context.") + (types . (general-music completize-extender-event event)) + )) + (ContextChange . ((description . "Change staves in Piano staff. diff --git a/scm/ly-syntax-constructors.scm b/scm/ly-syntax-constructors.scm index 3150c87929..2a2629fab3 100644 --- a/scm/ly-syntax-constructors.scm +++ b/scm/ly-syntax-constructors.scm @@ -196,6 +196,11 @@ (call-with-output-string (lambda (p) (format p "uniqueContext~s" unique-counter)))) (define (lyric-combine-music sync music loc) + ;; CompletizeExtenderEvent is added following the last lyric in MUSIC + ;; to signal to the Extender_engraver that any pending extender should + ;; be completed if the lyrics end before the associated voice. + (append! (ly:music-property music 'elements) + (list (make-music 'CompletizeExtenderEvent))) (make-music 'LyricCombineMusic 'element music 'associated-context sync -- 2.11.4.GIT