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"
35 The Span_bar_stub_engraver creates SpanBarStub grobs in the contexts
36 that a grouping context contains. For example, if a PianoStaff contains
37 two Staffs, a Dynamics, and a Lyrics, SpanBarStubs will be created in
38 all contexts that do not have bar lines (Dynamics and Lyrics).
40 We only want to create these SpanBarStubs in contexts that the SpanBar
41 traverses. However, Contexts do not contain layout information and it
42 is thus difficult to know if they will eventually be above or below other
43 Contexts. To determine this we use the VerticalAxisGroup created in the
44 Context. We relate VerticalAxisGroups to Contexts in the variable
45 axis_groups_ and weed out unused contexts after each translation timestep.
47 Note that SpanBarStubs exist for pure height calculations ONLY.
48 They should never be visually present on the page and should never
49 be engraved in contexts where BarLines are engraved.
52 class Span_bar_stub_engraver : public Engraver
54 vector<Grob *> spanbars_;
58 TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
60 DECLARE_ACKNOWLEDGER (span_bar);
61 DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
62 void process_acknowledged ();
63 void stop_translation_timestep ();
64 virtual void derived_mark () const;
67 Span_bar_stub_engraver::Span_bar_stub_engraver ()
69 axis_groups_ = SCM_EOL;
73 Span_bar_stub_engraver::derived_mark () const
75 scm_gc_mark (axis_groups_);
79 Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i)
81 spanbars_.push_back (i.grob ());
85 Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
87 axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_);
91 Span_bar_stub_engraver::process_acknowledged ()
93 if (!spanbars_.size ())
96 if (!scm_is_pair (axis_groups_))
98 programming_error ("At least one vertical axis group needs to be created in the first time step.");
101 Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob<Grob> (scm_caar (axis_groups_)));
102 if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
105 for (vsize i = 0; i < spanbars_.size (); i++)
107 extract_grob_set (spanbars_[i], "elements", bars);
108 vector<vsize> bar_axis_indices;
109 for (vsize j = 0; j < bars.size (); j++)
111 int i = Grob::get_vertical_axis_group_index (bars[j]);
113 bar_axis_indices.push_back ((vsize) i);
115 vector<Context *> affected_contexts;
116 vector<Grob *> y_parents;
117 vector<bool> keep_extent;
118 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
120 Context *c = unsmob<Context> (scm_cdar (s));
121 Grob *g = unsmob<Grob> (scm_caar (s));
124 if (c->is_removable ())
127 vsize j = Grob::get_vertical_axis_group_index (g);
128 if (j > bar_axis_indices[0]
129 && j < bar_axis_indices.back ()
130 && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
133 for (; k < bar_axis_indices.size (); k++)
134 if (bar_axis_indices[k] > j)
139 if (c && c->get_parent_context ())
141 keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
142 y_parents.push_back (g);
143 affected_contexts.push_back (c);
148 for (vsize j = 0; j < affected_contexts.size (); j++)
150 Item *it = new Item (Grob_property_info (affected_contexts[j], ly_symbol2scm ("SpanBarStub")).updated ());
151 it->set_parent (spanbars_[i], X_AXIS);
152 Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
153 gi.rerouting_daddy_context_ = affected_contexts[j];
163 // removes all unused contexts
165 Span_bar_stub_engraver::stop_translation_timestep ()
167 SCM axis_groups = SCM_EOL;
168 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
170 Context *c = unsmob<Context> (scm_cdar (s));
171 Grob *g = unsmob<Grob> (scm_caar (s));
174 if (c->is_removable ())
176 axis_groups = scm_cons (scm_car (s), axis_groups);
178 axis_groups_ = axis_groups;
181 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
182 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
183 ADD_TRANSLATOR (Span_bar_stub_engraver,
185 "Make stubs for span bars in all contexts that the span bars cross.",