summaryrefslogtreecommitdiff
path: root/lily/dynamic-align-engraver.cc
diff options
context:
space:
mode:
authorHan-Wen Nienhuys <hanwen@xs4all.nl>2008-05-01 23:22:26 -0300
committerHan-Wen Nienhuys <hanwen@xs4all.nl>2008-05-01 23:22:26 -0300
commit5457e0162783d5bbcd549857a244d949e93b5ca1 (patch)
treec9bcbd272ccb49a5bed068335c7425c783d738e2 /lily/dynamic-align-engraver.cc
parent494225fd3ef286f1e52d22553fc79c12ee1865a4 (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.cc164
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 */
+ ""
+ );