diff options
author | Han-Wen Nienhuys <hanwen@xs4all.nl> | 2008-05-01 23:22:26 -0300 |
---|---|---|
committer | Han-Wen Nienhuys <hanwen@xs4all.nl> | 2008-05-01 23:22:26 -0300 |
commit | 5457e0162783d5bbcd549857a244d949e93b5ca1 (patch) | |
tree | c9bcbd272ccb49a5bed068335c7425c783d738e2 /lily/dynamic-align-engraver.cc | |
parent | 494225fd3ef286f1e52d22553fc79c12ee1865a4 (diff) |
New dynamics engravers
Dynamic_align_engraver
New_dynamic_engraver
The New_dynamic_engraver handles creation of (de)crescendi and scripts
while Dynamic_align_engraver is responsible for the spanner that keeps
related dynamics on a single line.
Diffstat (limited to 'lily/dynamic-align-engraver.cc')
-rw-r--r-- | lily/dynamic-align-engraver.cc | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/lily/dynamic-align-engraver.cc b/lily/dynamic-align-engraver.cc new file mode 100644 index 0000000000..77feb08628 --- /dev/null +++ b/lily/dynamic-align-engraver.cc @@ -0,0 +1,164 @@ +/* + dynamic-align-engraver.cc -- implement Dynamic_align_engraver + + source file of the GNU LilyPond music typesetter + + (c) 2008 Han-Wen Nienhuys <hanwen@lilypond.org> + +*/ + +#include <set> + +#include "engraver.hh" + +#include "axis-group-interface.hh" +#include "directional-element-interface.hh" +#include "item.hh" +#include "side-position-interface.hh" +#include "spanner.hh" +#include "stream-event.hh" + +#include "translator.icc" + +class Dynamic_align_engraver : public Engraver +{ + TRANSLATOR_DECLARATIONS (Dynamic_align_engraver); + DECLARE_ACKNOWLEDGER (note_column); + DECLARE_ACKNOWLEDGER (dynamic); + DECLARE_END_ACKNOWLEDGER (dynamic); + +protected: + virtual void stop_translation_timestep (); + +private: + void create_line_spanner (Stream_event *cause); + Spanner* line_; + + vector<Spanner*> ended_; + vector<Spanner*> started_; + vector<Grob*> scripts_; + vector<Grob*> support_; + + set<Spanner*> running_; +}; + +Dynamic_align_engraver::Dynamic_align_engraver () +{ + line_ = 0; +} + +ADD_ACKNOWLEDGER (Dynamic_align_engraver, dynamic); +ADD_ACKNOWLEDGER (Dynamic_align_engraver, note_column); +ADD_END_ACKNOWLEDGER (Dynamic_align_engraver, dynamic); + +void +Dynamic_align_engraver::create_line_spanner (Stream_event* event) +{ + if (!line_) + line_ = make_spanner ("DynamicLineSpanner", + event ? event->self_scm() : SCM_EOL); +} + +void +Dynamic_align_engraver::acknowledge_end_dynamic (Grob_info info) +{ + if (Spanner::has_interface(info.grob())) + ended_.push_back (info.spanner ()); +} + +void +Dynamic_align_engraver::acknowledge_note_column (Grob_info info) +{ + support_.push_back (info.grob ()); +} + +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()); + else + info.grob ()->programming_error ("Unknown dynamic grob."); + + Axis_group_interface::add_element (line_, info.grob ()); + + if (cause) + { + if (Direction d = to_dir (cause->get_property ("direction"))) + set_grob_direction (line_, d); + } +} + +void +Dynamic_align_engraver::stop_translation_timestep () +{ + for (vsize i = 0; i < started_.size(); i++) + running_.insert (started_[i]); + for (vsize i = 0; i < ended_.size(); i++) + { + Spanner *sp = ended_[i]; + + set<Spanner*>::iterator it = running_.find (sp); + if (it != running_.end()) + running_.erase (it); + else + started_[i]->programming_error ("Lost track of this dynamic spanner."); + } + + bool end = line_ && running_.empty (); + Direction d = LEFT; + do + { + if (line_ + && ((d == LEFT && !line_->get_bound (LEFT)) + || (end && d == RIGHT && !line_->get_bound (RIGHT)))) + { + vector<Spanner*> const &spanners = + (d == LEFT) ? started_ : ended_; + + Grob *bound = 0; + if (scripts_.size()) + bound = scripts_[0]; + 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")); + } + + line_->set_bound (d, bound); + } + } + while (flip (&d) != LEFT); + + for (vsize i = 0; line_ && i < support_.size (); i++) + Side_position_interface::add_support (line_, support_[i]); + + if (end) + line_ = 0; + + ended_.clear (); + started_.clear (); + scripts_.clear (); + support_.clear (); +} + + +ADD_TRANSLATOR (Dynamic_align_engraver, + /* doc */ + "Align hairpins and dynamic texts on a horizontal line", + + /* create */ + "DynamicLineSpanner ", + + /* read */ + "currentMusicalColumn ", + + /* write */ + "" + ); |