X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fdynamic-align-engraver.cc;fp=lily%2Fdynamic-align-engraver.cc;h=f62c45f0dc6d3adec09cccf6e700fa1722806a24;hb=e90f0536f9be39ada0bef0aeb0d275dec3b2fb5b;hp=ac5e0e4c21ac6b7eed653a1dff9bff6e66500b9c;hpb=a8c9e8a7ca320ab0df5fd32e717fd62cd7635ce6;p=lilypond.git diff --git a/lily/dynamic-align-engraver.cc b/lily/dynamic-align-engraver.cc index ac5e0e4c21..f62c45f0dc 100644 --- a/lily/dynamic-align-engraver.cc +++ b/lily/dynamic-align-engraver.cc @@ -1,10 +1,21 @@ -/* - dynamic-align-engraver.cc -- implement Dynamic_align_engraver - - source file of the GNU LilyPond music typesetter - - (c) 2008--2009 Han-Wen Nienhuys - +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 2008--2011 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include @@ -23,8 +34,10 @@ class Dynamic_align_engraver : public Engraver { TRANSLATOR_DECLARATIONS (Dynamic_align_engraver); + DECLARE_TRANSLATOR_LISTENER (break_span); DECLARE_ACKNOWLEDGER (note_column); DECLARE_ACKNOWLEDGER (dynamic); + DECLARE_ACKNOWLEDGER (footnote_spanner); DECLARE_END_ACKNOWLEDGER (dynamic); protected: @@ -32,57 +45,87 @@ 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); ADD_ACKNOWLEDGER (Dynamic_align_engraver, note_column); +ADD_ACKNOWLEDGER (Dynamic_align_engraver, footnote_spanner); 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 ()); } +void +Dynamic_align_engraver::acknowledge_footnote_spanner (Grob_info info) +{ + Grob *parent = info.grob ()->get_parent (Y_AXIS); + if (line_ && parent + && parent->internal_has_interface (ly_symbol2scm ("dynamic-interface"))) + Axis_group_interface::add_element (line_, info.grob ()); +} + void 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())) - started_.push_back (info.spanner ()); - else if (info.item()) - scripts_.push_back (info.item()); + if (Spanner::has_interface (info.grob ())) + { + started_.push_back (info.spanner ()); + /* + If we are using text spans instead of hairpins and the line + is hidden, end the alignment spanner early: this allows dynamics + to be spaced individually instead of being linked together. + */ + if (info.grob ()->internal_has_interface (ly_symbol2scm ("dynamic-text-spanner-interface")) + && (info.grob ()->get_property ("style") == ly_symbol2scm ("none"))) + early_end_ = true; + } + 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 ()); @@ -96,20 +139,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 { @@ -117,18 +161,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); @@ -139,8 +184,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 (); @@ -148,10 +196,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 ",