/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 2011--2012 Mike Solomon <mike@apollinemike.com>
+ Copyright (C) 2011--2015 Mike Solomon <mike@mikesolomon.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
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <map>
#include <algorithm>
#include "align-interface.hh"
-#include "bar-line.hh"
#include "context.hh"
#include "grob.hh"
+#include "grob-properties.hh"
#include "item.hh"
#include "pointer-group-interface.hh"
-#include "span-bar.hh"
#include "engraver.hh"
+#include "translator.icc"
+
/*
- Note that span bar stubs exist for pure height calculations ONLY.
+ The Span_bar_stub_engraver creates SpanBarStub grobs in the contexts
+ that a grouping context contains. For example, if a PianoStaff contains
+ two Staffs, a Dynamics, and a Lyrics, SpanBarStubs will be created in
+ all contexts that do not have bar lines (Dynamics and Lyrics).
+
+ We only want to create these SpanBarStubs in contexts that the SpanBar
+ traverses. However, Contexts do not contain layout information and it
+ is thus difficult to know if they will eventually be above or below other
+ Contexts. To determine this we use the VerticalAxisGroup created in the
+ Context. We relate VerticalAxisGroups to Contexts in the variable
+ axis_groups_ and weed out unused contexts after each translation timestep.
+
+ Note that SpanBarStubs exist for pure height calculations ONLY.
They should never be visually present on the page and should never
be engraved in contexts where BarLines are engraved.
*/
class Span_bar_stub_engraver : public Engraver
{
vector<Grob *> spanbars_;
- map<Grob *, Context *> axis_groups_;
+ SCM axis_groups_;
public:
TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
protected:
- DECLARE_ACKNOWLEDGER (span_bar);
- DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
+ void acknowledge_span_bar (Grob_info);
+ void acknowledge_hara_kiri_group_spanner (Grob_info);
void process_acknowledged ();
+ void stop_translation_timestep ();
+ virtual void derived_mark () const;
};
-Span_bar_stub_engraver::Span_bar_stub_engraver ()
+Span_bar_stub_engraver::Span_bar_stub_engraver (Context *c)
+ : Engraver (c)
+{
+ axis_groups_ = SCM_EOL;
+}
+
+void
+Span_bar_stub_engraver::derived_mark () const
{
+ scm_gc_mark (axis_groups_);
}
void
void
Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
{
- axis_groups_[i.grob ()] = i.context ();
+ axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_);
}
void
if (!spanbars_.size ())
return;
- Grob *vertical_alignment = Grob::get_root_vertical_alignment ((*axis_groups_.begin ()).first);
+ if (!scm_is_pair (axis_groups_))
+ {
+ programming_error ("At least one vertical axis group needs to be created in the first time step.");
+ return;
+ }
+ Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob<Grob> (scm_caar (axis_groups_)));
if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
return;
- extract_grob_set (vertical_alignment, "elements", elts);
-
for (vsize i = 0; i < spanbars_.size (); i++)
{
extract_grob_set (spanbars_[i], "elements", bars);
vector<Context *> affected_contexts;
vector<Grob *> y_parents;
vector<bool> keep_extent;
- for (vsize j = 0; j < elts.size (); j++)
+ for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
{
+ Context *c = unsmob<Context> (scm_cdar (s));
+ Grob *g = unsmob<Grob> (scm_caar (s));
+ if (!c || !g)
+ continue;
+ if (c->is_removable ())
+ continue;
+
+ vsize j = Grob::get_vertical_axis_group_index (g);
if (j > bar_axis_indices[0]
&& j < bar_axis_indices.back ()
&& find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
break;
k--;
- keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
- Context *c = axis_groups_[elts[j]];
if (c && c->get_parent_context ())
{
- y_parents.push_back (elts[j]);
+ keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
+ y_parents.push_back (g);
affected_contexts.push_back (c);
}
}
}
- reverse (affected_contexts); // from bottom to top
- reverse (y_parents); // from bottom to top
- reverse (keep_extent); // from bottom to top
+
for (vsize j = 0; j < affected_contexts.size (); j++)
{
- Item *it = new Item (updated_grob_properties (affected_contexts[j], ly_symbol2scm ("SpanBarStub")));
+ Item *it = new Item (Grob_property_info (affected_contexts[j], ly_symbol2scm ("SpanBarStub")).updated ());
it->set_parent (spanbars_[i], X_AXIS);
Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
- gi.rerouting_daddy_context_ = affected_contexts[j];
- announce_grob (gi);
+ announce_grob (gi, affected_contexts[j]);
if (!keep_extent[j])
- it->suicide ();//it->set_property ("Y-extent", ly_interval2scm (Interval (infinity_f, -infinity_f)));
+ it->suicide ();
}
}
+
spanbars_.clear ();
}
-#include "translator.icc"
+// removes all unused contexts
+void
+Span_bar_stub_engraver::stop_translation_timestep ()
+{
+ SCM axis_groups = SCM_EOL;
+ for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
+ {
+ Context *c = unsmob<Context> (scm_cdar (s));
+ Grob *g = unsmob<Grob> (scm_caar (s));
+ if (!c || !g)
+ continue;
+ if (c->is_removable ())
+ continue;
+ axis_groups = scm_cons (scm_car (s), axis_groups);
+ }
+ axis_groups_ = axis_groups;
+}
+
+void
+Span_bar_stub_engraver::boot ()
+{
+ ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
+ ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
+}
-ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
-ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
ADD_TRANSLATOR (Span_bar_stub_engraver,
/* doc */
"Make stubs for span bars in all contexts that the span bars cross.",