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 DECLARE_ACKNOWLEDGER (span_bar);
59 DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
60 void process_acknowledged ();
61 void stop_translation_timestep ();
62 virtual void derived_mark () const;
65 Span_bar_stub_engraver::Span_bar_stub_engraver ()
67 axis_groups_ = SCM_EOL;
71 Span_bar_stub_engraver::derived_mark () const
73 scm_gc_mark (axis_groups_);
77 Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i)
79 spanbars_.push_back (i.grob ());
83 Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
85 axis_groups_ = scm_cons (scm_cons (i.grob ()->self_scm (), i.context ()->self_scm ()), axis_groups_);
89 Span_bar_stub_engraver::process_acknowledged ()
91 if (!spanbars_.size ())
94 if (!scm_is_pair (axis_groups_))
96 programming_error ("At least one vertical axis group needs to be created in the first time step.");
99 Grob *vertical_alignment = Grob::get_root_vertical_alignment (unsmob<Grob> (scm_caar (axis_groups_)));
100 if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
103 for (vsize i = 0; i < spanbars_.size (); i++)
105 extract_grob_set (spanbars_[i], "elements", bars);
106 vector<vsize> bar_axis_indices;
107 for (vsize j = 0; j < bars.size (); j++)
109 int i = Grob::get_vertical_axis_group_index (bars[j]);
111 bar_axis_indices.push_back ((vsize) i);
113 vector<Context *> affected_contexts;
114 vector<Grob *> y_parents;
115 vector<bool> keep_extent;
116 for (SCM s = axis_groups_; scm_is_pair (s); s = scm_cdr (s))
118 Context *c = unsmob<Context> (scm_cdar (s));
119 Grob *g = unsmob<Grob> (scm_caar (s));
122 if (c->is_removable ())
125 vsize j = Grob::get_vertical_axis_group_index (g);
126 if (j > bar_axis_indices[0]
127 && j < bar_axis_indices.back ()
128 && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
131 for (; k < bar_axis_indices.size (); k++)
132 if (bar_axis_indices[k] > j)
137 if (c && c->get_parent_context ())
139 keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
140 y_parents.push_back (g);
141 affected_contexts.push_back (c);
146 for (vsize j = 0; j < affected_contexts.size (); j++)
148 Item *it = new Item (Grob_property_info (affected_contexts[j], ly_symbol2scm ("SpanBarStub")).updated ());
149 it->set_parent (spanbars_[i], X_AXIS);
150 Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
151 announce_grob (gi, 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 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.",