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"
30 #include "translator.icc"
33 The Span_bar_stub_engraver creates SpanBarStub grobs in the contexts
34 that a grouping context contains. For example, if a PianoStaff contains
35 two Staffs, a Dynamics, and a Lyrics, SpanBarStubs will be created in
36 all contexts that do not have bar lines (Dynamics and Lyrics).
38 We only want to create these SpanBarStubs in contexts that the SpanBar
39 traverses. However, Contexts do not contain layout information and it
40 is thus difficult to know if they will eventually be above or below other
41 Contexts. To determine this we use the VerticalAxisGroup created in the
42 Context. We relate VerticalAxisGroups to Contexts in the variable
43 axis_groups_ and weed out unused contexts after each translation timestep.
45 Note that SpanBarStubs exist for pure height calculations ONLY.
46 They should never be visually present on the page and should never
47 be engraved in contexts where BarLines are engraved.
50 class Span_bar_stub_engraver : public Engraver
52 vector<Grob *> spanbars_;
56 TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
58 void acknowledge_span_bar (Grob_info);
59 void acknowledge_hara_kiri_group_spanner (Grob_info);
60 void process_acknowledged ();
61 void stop_translation_timestep ();
62 virtual void derived_mark () const;
65 Span_bar_stub_engraver::Span_bar_stub_engraver (Context *c)
68 axis_groups_ = SCM_EOL;
72 Span_bar_stub_engraver::derived_mark () const
74 scm_gc_mark (axis_groups_);
78 Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i)
80 spanbars_.push_back (i.grob ());
84 Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
86 axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_);
90 Span_bar_stub_engraver::process_acknowledged ()
92 if (!spanbars_.size ())
95 if (!scm_is_pair (axis_groups_))
97 programming_error ("At least one vertical axis group needs to be created in the first time step.");
100 Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob<Grob> (scm_caar (axis_groups_)));
101 if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
104 for (vsize i = 0; i < spanbars_.size (); i++)
106 extract_grob_set (spanbars_[i], "elements", bars);
107 vector<vsize> bar_axis_indices;
108 for (vsize j = 0; j < bars.size (); j++)
110 int i = Grob::get_vertical_axis_group_index (bars[j]);
112 bar_axis_indices.push_back ((vsize) i);
114 vector<Context *> affected_contexts;
115 vector<Grob *> y_parents;
116 vector<bool> keep_extent;
117 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
119 Context *c = unsmob<Context> (scm_cdar (s));
120 Grob *g = unsmob<Grob> (scm_caar (s));
123 if (c->is_removable ())
126 vsize j = Grob::get_vertical_axis_group_index (g);
127 if (j > bar_axis_indices[0]
128 && j < bar_axis_indices.back ()
129 && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
132 for (; k < bar_axis_indices.size (); k++)
133 if (bar_axis_indices[k] > j)
138 if (c && c->get_parent_context ())
140 keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
141 y_parents.push_back (g);
142 affected_contexts.push_back (c);
147 for (vsize j = 0; j < affected_contexts.size (); j++)
149 Item *it = new Item (Grob_property_info (affected_contexts[j], ly_symbol2scm ("SpanBarStub")).updated ());
150 it->set_parent (spanbars_[i], X_AXIS);
151 Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
152 announce_grob (gi, affected_contexts[j]);
161 // removes all unused contexts
163 Span_bar_stub_engraver::stop_translation_timestep ()
165 SCM axis_groups = SCM_EOL;
166 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
168 Context *c = unsmob<Context> (scm_cdar (s));
169 Grob *g = unsmob<Grob> (scm_caar (s));
172 if (c->is_removable ())
174 axis_groups = scm_cons (scm_car (s), axis_groups);
176 axis_groups_ = axis_groups;
180 Span_bar_stub_engraver::boot ()
182 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
183 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
186 ADD_TRANSLATOR (Span_bar_stub_engraver,
188 "Make stubs for span bars in all contexts that the span bars cross.",