2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2011--2012 Mike Solomon <mike@apollinemike.com>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
22 #include "align-interface.hh"
23 #include "bar-line.hh"
27 #include "pointer-group-interface.hh"
28 #include "span-bar.hh"
29 #include "engraver.hh"
32 The Span_bar_stub_engraver creates SpanBarStub grobs in the contexts
33 that a grouping context contains. For example, if a PianoStaff contains
34 two Staffs, a Dynamics, and a Lyrics, SpanBarStubs will be created in
35 all contexts that do not have bar lines (Dynamics and Lyrics).
37 We only want to create these SpanBarStubs in contexts that the SpanBar
38 traverses. However, Contexts do not contain layout information and it
39 is thus difficult to know if they will eventually be above or below other
40 Contexts. To determine this we use the VerticalAxisGroup created in the
41 Context. We relate VerticalAxisGroups to Contexts in the variable
42 axis_groups_ and weed out unused contexts after each translation timestep.
44 Note that SpanBarStubs exist for pure height calculations ONLY.
45 They should never be visually present on the page and should never
46 be engraved in contexts where BarLines are engraved.
49 class Span_bar_stub_engraver : public Engraver
51 vector<Grob *> spanbars_;
55 TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
57 DECLARE_ACKNOWLEDGER (span_bar);
58 DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
59 void process_acknowledged ();
60 void stop_translation_timestep ();
61 virtual void derived_mark () const;
64 Span_bar_stub_engraver::Span_bar_stub_engraver ()
66 axis_groups_ = SCM_EOL;
70 Span_bar_stub_engraver::derived_mark () const
72 scm_gc_mark (axis_groups_);
76 Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i)
78 spanbars_.push_back (i.grob ());
82 Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
84 axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_);
88 Span_bar_stub_engraver::process_acknowledged ()
90 if (!spanbars_.size ())
93 if (!scm_is_pair (axis_groups_))
95 programming_error ("At least one vertical axis group needs to be created in the first time step.");
98 Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob_grob (scm_caar (axis_groups_)));
99 if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
102 for (vsize i = 0; i < spanbars_.size (); i++)
104 extract_grob_set (spanbars_[i], "elements", bars);
105 vector<vsize> bar_axis_indices;
106 for (vsize j = 0; j < bars.size (); j++)
108 int i = Grob::get_vertical_axis_group_index (bars[j]);
110 bar_axis_indices.push_back ((vsize) i);
112 vector<Context *> affected_contexts;
113 vector<Grob *> y_parents;
114 vector<bool> keep_extent;
115 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
117 Context *c = unsmob_context (scm_cdar (s));
118 Grob *g = unsmob_grob (scm_caar (s));
121 if (c->is_removable ())
124 vsize j = Grob::get_vertical_axis_group_index (g);
125 if (j > bar_axis_indices[0]
126 && j < bar_axis_indices.back ()
127 && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
130 for (; k < bar_axis_indices.size (); k++)
131 if (bar_axis_indices[k] > j)
136 if (c && c->get_parent_context ())
138 keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
139 y_parents.push_back (g);
140 affected_contexts.push_back (c);
145 for (vsize j = 0; j < affected_contexts.size (); j++)
147 Item *it = new Item (updated_grob_properties (affected_contexts[j], ly_symbol2scm ("SpanBarStub")));
148 it->set_parent (spanbars_[i], X_AXIS);
149 Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
150 gi.rerouting_daddy_context_ = affected_contexts[j];
160 // removes all unused contexts
162 Span_bar_stub_engraver::stop_translation_timestep ()
164 SCM axis_groups = SCM_EOL;
165 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
167 Context *c = unsmob_context (scm_cdar (s));
168 Grob *g = unsmob_grob (scm_caar (s));
171 if (c->is_removable ())
173 axis_groups = scm_cons (scm_car (s), axis_groups);
175 axis_groups_ = axis_groups;
178 #include "translator.icc"
180 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
181 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
182 ADD_TRANSLATOR (Span_bar_stub_engraver,
184 "Make stubs for span bars in all contexts that the span bars cross.",