2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2011--2012 Mike Solomon <mike@mikesolomon.org>
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"
26 #include "pointer-group-interface.hh"
27 #include "engraver.hh"
30 The Span_bar_stub_engraver creates SpanBarStub grobs in the contexts
31 that a grouping context contains. For example, if a PianoStaff contains
32 two Staffs, a Dynamics, and a Lyrics, SpanBarStubs will be created in
33 all contexts that do not have bar lines (Dynamics and Lyrics).
35 We only want to create these SpanBarStubs in contexts that the SpanBar
36 traverses. However, Contexts do not contain layout information and it
37 is thus difficult to know if they will eventually be above or below other
38 Contexts. To determine this we use the VerticalAxisGroup created in the
39 Context. We relate VerticalAxisGroups to Contexts in the variable
40 axis_groups_ and weed out unused contexts after each translation timestep.
42 Note that SpanBarStubs exist for pure height calculations ONLY.
43 They should never be visually present on the page and should never
44 be engraved in contexts where BarLines are engraved.
47 class Span_bar_stub_engraver : public Engraver
49 vector<Grob *> spanbars_;
53 TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
55 DECLARE_ACKNOWLEDGER (span_bar);
56 DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
57 void process_acknowledged ();
58 void stop_translation_timestep ();
59 virtual void derived_mark () const;
62 Span_bar_stub_engraver::Span_bar_stub_engraver ()
64 axis_groups_ = SCM_EOL;
68 Span_bar_stub_engraver::derived_mark () const
70 scm_gc_mark (axis_groups_);
74 Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i)
76 spanbars_.push_back (i.grob ());
80 Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
82 axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_);
86 Span_bar_stub_engraver::process_acknowledged ()
88 if (!spanbars_.size ())
91 if (!scm_is_pair (axis_groups_))
93 programming_error ("At least one vertical axis group needs to be created in the first time step.");
96 Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob_grob (scm_caar (axis_groups_)));
97 if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
100 for (vsize i = 0; i < spanbars_.size (); i++)
102 extract_grob_set (spanbars_[i], "elements", bars);
103 vector<vsize> bar_axis_indices;
104 for (vsize j = 0; j < bars.size (); j++)
106 int i = Grob::get_vertical_axis_group_index (bars[j]);
108 bar_axis_indices.push_back ((vsize) i);
110 vector<Context *> affected_contexts;
111 vector<Grob *> y_parents;
112 vector<bool> keep_extent;
113 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
115 Context *c = unsmob_context (scm_cdar (s));
116 Grob *g = unsmob_grob (scm_caar (s));
119 if (c->is_removable ())
122 vsize j = Grob::get_vertical_axis_group_index (g);
123 if (j > bar_axis_indices[0]
124 && j < bar_axis_indices.back ()
125 && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
128 for (; k < bar_axis_indices.size (); k++)
129 if (bar_axis_indices[k] > j)
134 if (c && c->get_parent_context ())
136 keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
137 y_parents.push_back (g);
138 affected_contexts.push_back (c);
143 for (vsize j = 0; j < affected_contexts.size (); j++)
145 Item *it = new Item (updated_grob_properties (affected_contexts[j], ly_symbol2scm ("SpanBarStub")));
146 it->set_parent (spanbars_[i], X_AXIS);
147 Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
148 gi.rerouting_daddy_context_ = affected_contexts[j];
158 // removes all unused contexts
160 Span_bar_stub_engraver::stop_translation_timestep ()
162 SCM axis_groups = SCM_EOL;
163 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
165 Context *c = unsmob_context (scm_cdar (s));
166 Grob *g = unsmob_grob (scm_caar (s));
169 if (c->is_removable ())
171 axis_groups = scm_cons (scm_car (s), axis_groups);
173 axis_groups_ = axis_groups;
176 #include "translator.icc"
178 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
179 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
180 ADD_TRANSLATOR (Span_bar_stub_engraver,
182 "Make stubs for span bars in all contexts that the span bars cross.",