]> git.donarmstrong.com Git - lilypond.git/blob - lily/span-bar-stub-engraver.cc
Merge branch 'master' into lilypond/translation
[lilypond.git] / lily / span-bar-stub-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2011 Mike Solomon <mike@apollinemike.com>
5
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.
10
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.
15
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/>.
18 */
19
20 #include <map>
21 #include <algorithm>
22
23 #include "align-interface.hh"
24 #include "bar-line.hh"
25 #include "context.hh"
26 #include "grob.hh"
27 #include "item.hh"
28 #include "pointer-group-interface.hh"
29 #include "span-bar.hh"
30 #include "engraver.hh"
31
32 class Span_bar_stub_engraver : public Engraver
33 {
34   vector<Grob *> spanbars_;
35   map<Grob *, Context *> axis_groups_;
36
37 public:
38   TRANSLATOR_DECLARATIONS (Span_bar_stub_engraver);
39 protected:
40   DECLARE_ACKNOWLEDGER (span_bar);
41   DECLARE_ACKNOWLEDGER (hara_kiri_group_spanner);
42   void process_acknowledged ();
43 };
44
45 Span_bar_stub_engraver::Span_bar_stub_engraver ()
46 {
47 }
48
49 void
50 Span_bar_stub_engraver::acknowledge_span_bar (Grob_info i)
51 {
52   spanbars_.push_back (i.grob ());
53 }
54
55 // note that this can get out of hand if there are lots of vertical axis groups...
56
57 void
58 Span_bar_stub_engraver::acknowledge_hara_kiri_group_spanner (Grob_info i)
59 {
60   axis_groups_[i.grob ()] = i.context ();
61 }
62
63 void
64 Span_bar_stub_engraver::process_acknowledged ()
65 {
66   if (!spanbars_.size ())
67     return;
68
69   Grob *vertical_alignment = Grob::get_root_vertical_alignment ((*axis_groups_.begin ()).first);
70   if (!vertical_alignment) // we are at the beginning of a score, so no need for stubs
71     return;
72
73   extract_grob_set (vertical_alignment, "elements", elts);
74
75   for (vsize i = 0; i < spanbars_.size (); i++)
76     {
77       extract_grob_set (spanbars_[i], "elements", bars);
78       vector<vsize> bar_axis_indices;
79       for (vsize j = 0; j < bars.size (); j++)
80         {
81           int i = Grob::get_vertical_axis_group_index (bars[j]);
82           if (i >= 0)
83             bar_axis_indices.push_back ((vsize) i);
84         }
85       vector<Context *> affected_contexts;
86       vector<Grob *> y_parents;
87       vector<bool> keep_extent;
88       for (vsize j = 0; j < elts.size (); j++)
89         {
90           if (j > bar_axis_indices[0]
91               && j < bar_axis_indices.back ()
92               && find (bar_axis_indices.begin (), bar_axis_indices.end (), j) == bar_axis_indices.end ())
93             {
94               vsize k = 0;
95               for (; k < bar_axis_indices.size (); k++)
96                 if (bar_axis_indices[k] > j)
97                   break;
98
99               k--;
100               keep_extent.push_back (to_boolean (bars[k]->get_property ("allow-span-bar")));
101
102               Context *c = axis_groups_[elts[j]];
103               if (c && c->get_parent_context ())
104                 {
105                   y_parents.push_back (elts[j]);
106                   affected_contexts.push_back (c);
107                 }
108             }
109         }
110       reverse (affected_contexts); // from bottom to top
111       reverse (y_parents); // from bottom to top
112       reverse (keep_extent); // from bottom to top
113       for (vsize j = 0; j < affected_contexts.size (); j++)
114         {
115           Item *it = new Item (updated_grob_properties (affected_contexts[j], ly_symbol2scm ("SpanBarStub")));
116           it->set_parent (spanbars_[i], X_AXIS);
117           Grob_info gi = make_grob_info (it, spanbars_[i]->self_scm ());
118           gi.rerouting_daddy_context_ = affected_contexts[j];
119           announce_grob (gi);
120           if (!keep_extent[j])
121             it->set_property ("Y-extent", ly_interval2scm (Interval (infinity_f, -infinity_f)));
122         }
123     }
124   spanbars_.clear ();
125 }
126
127 #include "translator.icc"
128
129 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, span_bar);
130 ADD_ACKNOWLEDGER (Span_bar_stub_engraver, hara_kiri_group_spanner);
131 ADD_TRANSLATOR (Span_bar_stub_engraver,
132                 /* doc */
133                 "Make stubs for span bars in all contexts that the span bars cross.",
134
135                 /* create */
136                 "SpanBarStub ",
137
138                 /* read */
139                 "",
140
141                 /* write */
142                 ""
143                );