From: Neil Puttock Date: Sun, 30 May 2010 22:17:24 +0000 (+0100) Subject: Fix #305: Allow alignment spanner to be broken for dynamics. X-Git-Tag: release/2.13.23-1~29^2~1 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=f75fe46f1727ea0d28840781b0db54474c61442d;p=lilypond.git Fix #305: Allow alignment spanner to be broken for dynamics. Introduce a new event class which will trigger the end of a DynamicLineSpanner prematurely, thus allowing dynamics to be positioned independently. --- diff --git a/input/regression/dynamics-alignment-breaker.ly b/input/regression/dynamics-alignment-breaker.ly new file mode 100644 index 0000000000..872dff72bf --- /dev/null +++ b/input/regression/dynamics-alignment-breaker.ly @@ -0,0 +1,21 @@ +\version "2.13.23" + +\header { + texidoc = "Hairpins, DynamicTextSpanners and dynamics can be +positioned independently using @code{\\breakDynamicSpan}, which +causes the alignment spanner to end prematurely. +" +} + +\relative c' { + c1^\< + \dimTextDim + c1_\> + f,1\p + + c'1^\< + \breakDynamicSpan + c1_\> + \breakDynamicSpan + f,1\p +} diff --git a/lily/dynamic-align-engraver.cc b/lily/dynamic-align-engraver.cc index 074569d63a..96d19b7ded 100644 --- a/lily/dynamic-align-engraver.cc +++ b/lily/dynamic-align-engraver.cc @@ -2,7 +2,7 @@ This file is part of LilyPond, the GNU music typesetter. Copyright (C) 2008--2010 Han-Wen Nienhuys - + LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,6 +34,7 @@ class Dynamic_align_engraver : public Engraver { TRANSLATOR_DECLARATIONS (Dynamic_align_engraver); + DECLARE_TRANSLATOR_LISTENER (break_span); DECLARE_ACKNOWLEDGER (note_column); DECLARE_ACKNOWLEDGER (dynamic); DECLARE_END_ACKNOWLEDGER (dynamic); @@ -43,19 +44,21 @@ protected: private: void create_line_spanner (Stream_event *cause); - Spanner* line_; - - vector ended_; - vector started_; - vector scripts_; - vector support_; - - set running_; + Spanner *line_; + vector ended_; + vector started_; + vector scripts_; + vector support_; + + set running_; + + bool early_end_; }; Dynamic_align_engraver::Dynamic_align_engraver () { line_ = 0; + early_end_ = false; } ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic); @@ -63,17 +66,17 @@ ADD_ACKNOWLEDGER (Dynamic_align_engraver, note_column); ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic); void -Dynamic_align_engraver::create_line_spanner (Stream_event* event) +Dynamic_align_engraver::create_line_spanner (Stream_event *event) { if (!line_) line_ = make_spanner ("DynamicLineSpanner", - event ? event->self_scm() : SCM_EOL); + event ? event->self_scm () : SCM_EOL); } void Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info) { - if (Spanner::has_interface(info.grob())) + if (Spanner::has_interface (info.grob ())) ended_.push_back (info.spanner ()); } @@ -83,17 +86,25 @@ Dynamic_align_engraver::acknowledge_note_column (Grob_info info) support_.push_back (info.grob ()); } +IMPLEMENT_TRANSLATOR_LISTENER (Dynamic_align_engraver, break_span); +void +Dynamic_align_engraver::listen_break_span (Stream_event *event) +{ + if (event->in_event_class ("break-dynamic-span-event")) + early_end_ = true; +} + void Dynamic_align_engraver::acknowledge_dynamic (Grob_info info) { Stream_event *cause = info.event_cause (); create_line_spanner (cause); - if (Spanner::has_interface(info.grob())) + if (Spanner::has_interface (info.grob ())) started_.push_back (info.spanner ()); - else if (info.item()) - scripts_.push_back (info.item()); + else if (info.item ()) + scripts_.push_back (info.item ()); else - info.grob ()->programming_error ("Unknown dynamic grob."); + info.grob ()->programming_error ("unknown dynamic grob"); Axis_group_interface::add_element (line_, info.grob ()); @@ -107,20 +118,21 @@ Dynamic_align_engraver::acknowledge_dynamic (Grob_info info) void Dynamic_align_engraver::stop_translation_timestep () { - for (vsize i = 0; i < started_.size(); i++) + for (vsize i = 0; i < started_.size (); i++) running_.insert (started_[i]); - for (vsize i = 0; i < ended_.size(); i++) + for (vsize i = 0; i < ended_.size (); i++) { Spanner *sp = ended_[i]; - set::iterator it = running_.find (sp); - if (it != running_.end()) + set::iterator it = running_.find (sp); + if (it != running_.end ()) running_.erase (it); else - started_[i]->programming_error ("Lost track of this dynamic spanner."); + started_[i]->programming_error ("lost track of this dynamic spanner"); } - bool end = line_ && running_.empty (); + bool end = line_ && (running_.empty () + || early_end_); Direction d = LEFT; do { @@ -128,18 +140,19 @@ Dynamic_align_engraver::stop_translation_timestep () && ((d == LEFT && !line_->get_bound (LEFT)) || (end && d == RIGHT && !line_->get_bound (RIGHT)))) { - vector const &spanners = - (d == LEFT) ? started_ : ended_; - + vector const &spanners + = (d == LEFT) ? started_ : ended_; + Grob *bound = 0; - if (scripts_.size()) + if (scripts_.size ()) bound = scripts_[0]; - else if (spanners.size()) + else if (spanners.size ()) bound = spanners[0]->get_bound (d); else { - programming_error ("Started DynamicLineSpanner but have no left bound."); bound = unsmob_grob (get_property ("currentMusicalColumn")); + if (!early_end_) + programming_error ("started DynamicLineSpanner but have no left bound"); } line_->set_bound (d, bound); @@ -150,8 +163,11 @@ Dynamic_align_engraver::stop_translation_timestep () for (vsize i = 0; line_ && i < support_.size (); i++) Side_position_interface::add_support (line_, support_[i]); - if (end) - line_ = 0; + if (end) + { + line_ = 0; + early_end_ = false; + } ended_.clear (); started_.clear (); @@ -159,10 +175,9 @@ Dynamic_align_engraver::stop_translation_timestep () support_.clear (); } - ADD_TRANSLATOR (Dynamic_align_engraver, /* doc */ - "Align hairpins and dynamic texts on a horizontal line", + "Align hairpins and dynamic texts on a horizontal line.", /* create */ "DynamicLineSpanner ", diff --git a/ly/spanners-init.ly b/ly/spanners-init.ly index 065827ab59..6ebb6fbdbe 100644 --- a/ly/spanners-init.ly +++ b/ly/spanners-init.ly @@ -104,3 +104,5 @@ sostenutoOff = #(make-span-event 'SostenutoEvent STOP) %dim = \set crescendoText = "dim." newSpacingSection = #(make-event-chord (list (make-music 'SpacingSectionEvent))) + +breakDynamicSpan = #(make-music 'BreakDynamicSpanEvent) diff --git a/scm/define-event-classes.scm b/scm/define-event-classes.scm index d9bbceb3c2..4de8c5d97b 100644 --- a/scm/define-event-classes.scm +++ b/scm/define-event-classes.scm @@ -34,9 +34,9 @@ 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 completize-extender-event)) + layout-instruction-event completize-extender-event break-span-event)) - (layout-instruction-event . (apply-output-event )) + (layout-instruction-event . (apply-output-event)) (script-event . (articulation-event text-script-event)) (part-combine-event . (solo-one-event solo-two-event unisono-event)) (break-event . (line-break-event page-break-event page-turn-event)) @@ -46,6 +46,7 @@ text-span-event trill-span-event tremolo-span-event tuplet-span-event)) (span-dynamic-event . (decrescendo-event crescendo-event)) + (break-span-event . (break-dynamic-span-event)) (pedal-event . (sostenuto-event sustain-event una-corda-event)) (rhythmic-event . (lyric-event melodic-event multi-measure-rest-event percent-event @@ -95,10 +96,11 @@ root))) ;; All leaf event classes that no translator listens to -;; directly. Avoids printing a warning. +;; directly. Avoids printing a warning. (define unlistened-music-event-classes '(harmonic-event line-break-event page-break-event page-turn-event label-event - solo-one-event solo-two-event skip-event unisono-event)) + solo-one-event solo-two-event skip-event unisono-event + break-dynamic-span-event)) ;; produce neater representation of music event tree. ;; TODO: switch to this representation for the event-classes list? @@ -174,4 +176,3 @@ (define-public (ly:simplify-scheme e) (list 'quasiquote (simplify e))) - diff --git a/scm/define-music-types.scm b/scm/define-music-types.scm index e9dcee38cf..a0762025de 100644 --- a/scm/define-music-types.scm +++ b/scm/define-music-types.scm @@ -80,7 +80,7 @@ Syntax: @var{note}@code{-\\arpeggio}") Syntax: @var{note}@code{x}@code{y}, where @code{x} is a direction (@code{^} for up or @code{_} for down), or LilyPond's choice -(no direction specified)), and where @code{y} is an articulation +(no direction specified), and where @code{y} is an articulation (such as @code{-.}, @code{->}, @code{\\tenuto}, @code{\\downbow}). See the Notation Reference for details.") (types . (general-music event articulation-event script-event)) @@ -119,6 +119,11 @@ Syntax for manual control: @code{c8-[ c c-] c8}") (types . (general-music event beam-forbid-event)) )) + (BreakDynamicSpanEvent + . ((description . "End an alignment spanner for dynamics here.") + (types . (general-music break-span-event break-dynamic-span-event event)) + )) + (BendAfterEvent . ((description . "A drop/fall/doit jazz articulation.") (types . (general-music bend-after-event event))))