2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2011--2015 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"
25 #include "grob-properties.hh"
27 #include "pointer-group-interface.hh"
28 #include "engraver.hh"
31 The Span_bar_stub_engraver creates SpanBarStub grobs in the contexts
32 that a grouping context contains. For example, if a PianoStaff contains
33 two Staffs, a Dynamics, and a Lyrics, SpanBarStubs will be created in
34 all contexts that do not have bar lines (Dynamics and Lyrics).
36 We only want to create these SpanBarStubs in contexts that the SpanBar
37 traverses. However, Contexts do not contain layout information and it
38 is thus difficult to know if they will eventually be above or below other
39 Contexts. To determine this we use the VerticalAxisGroup created in the
40 Context. We relate VerticalAxisGroups to Contexts in the variable
41 axis_groups_ and weed out unused contexts after each translation timestep.
43 Note that SpanBarStubs exist for pure height calculations ONLY.
44 They should never be visually present on the page and should never
45 be engraved in contexts where BarLines are engraved.
48 class Span_bar_stub_engraver : public Engraver
50 vector<Grob *> spanbars_;
54 TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
56 DECLARE_ACKNOWLEDGER (span_bar);
57 DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
58 void process_acknowledged ();
59 void stop_translation_timestep ();
60 virtual void derived_mark () const;
63 Span_bar_stub_engraver::Span_bar_stub_engraver ()
65 axis_groups_ = SCM_EOL;
69 Span_bar_stub_engraver::derived_mark () const
71 scm_gc_mark (axis_groups_);
75 Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i)
77 spanbars_.push_back (i.grob ());
81 Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
83 axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_);
87 Span_bar_stub_engraver::process_acknowledged ()
89 if (!spanbars_.size ())
92 if (!scm_is_pair (axis_groups_))
94 programming_error ("At least one vertical axis group needs to be created in the first time step.");
97 Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob<Grob> (scm_caar (axis_groups_)));
98 if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
101 for (vsize i = 0; i < spanbars_.size (); i++)
103 extract_grob_set (spanbars_[i], "elements", bars);
104 vector<vsize> bar_axis_indices;
105 for (vsize j = 0; j < bars.size (); j++)
107 int i = Grob::get_vertical_axis_group_index (bars[j]);
109 bar_axis_indices.push_back ((vsize) i);
111 vector<Context *> affected_contexts;
112 vector<Grob *> y_parents;
113 vector<bool> keep_extent;
114 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
116 Context *c = unsmob<Context> (scm_cdar (s));
117 Grob *g = unsmob<Grob> (scm_caar (s));
120 if (c->is_removable ())
123 vsize j = Grob::get_vertical_axis_group_index (g);
124 if (j > bar_axis_indices[0]
125 && j < bar_axis_indices.back ()
126 && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
129 for (; k < bar_axis_indices.size (); k++)
130 if (bar_axis_indices[k] > j)
135 if (c && c->get_parent_context ())
137 keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
138 y_parents.push_back (g);
139 affected_contexts.push_back (c);
144 for (vsize j = 0; j < affected_contexts.size (); j++)
146 Item *it = new Item (Grob_property_info (affected_contexts[j], ly_symbol2scm ("SpanBarStub")).updated ());
147 it->set_parent (spanbars_[i], X_AXIS);
148 Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
149 gi.rerouting_daddy_context_ = affected_contexts[j];
159 // removes all unused contexts
161 Span_bar_stub_engraver::stop_translation_timestep ()
163 SCM axis_groups = SCM_EOL;
164 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
166 Context *c = unsmob<Context> (scm_cdar (s));
167 Grob *g = unsmob<Grob> (scm_caar (s));
170 if (c->is_removable ())
172 axis_groups = scm_cons (scm_car (s), axis_groups);
174 axis_groups_ = axis_groups;
177 #include "translator.icc"
179 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
180 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
181 ADD_TRANSLATOR (Span_bar_stub_engraver,
183 "Make stubs for span bars in all contexts that the span bars cross.",