summaryrefslogtreecommitdiff
path: root/lily/dynamic-align-engraver.cc
diff options
context:
space:
mode:
authorNeil Puttock <n.puttock@gmail.com>2010-05-30 23:17:24 +0100
committerNeil Puttock <n.puttock@gmail.com>2010-05-30 23:17:24 +0100
commitf75fe46f1727ea0d28840781b0db54474c61442d (patch)
tree298b8dc96e06b60df4f1d1e24d4486d91ff85576 /lily/dynamic-align-engraver.cc
parent8350ebcd996773355a5b37b06d72207e7f2f0966 (diff)
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.
Diffstat (limited to 'lily/dynamic-align-engraver.cc')
-rw-r--r--lily/dynamic-align-engraver.cc79
1 files changed, 47 insertions, 32 deletions
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 <hanwen@lilypond.org>
-
+
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<Spanner*> ended_;
- vector<Spanner*> started_;
- vector<Grob*> scripts_;
- vector<Grob*> support_;
-
- set<Spanner*> running_;
+ Spanner *line_;
+ vector<Spanner *> ended_;
+ vector<Spanner *> started_;
+ vector<Grob *> scripts_;
+ vector<Grob *> support_;
+
+ set<Spanner *> 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<Spanner*>::iterator it = running_.find (sp);
- if (it != running_.end())
+ 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.");
+ 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<Spanner*> const &spanners =
- (d == LEFT) ? started_ : ended_;
-
+ vector<Spanner *> 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 ",