]> git.donarmstrong.com Git - lilypond.git/blob - lily/cluster-engraver.cc
Doc: Included/compile.itexi - CG 4.2 - Updated notes on reqs for compiling
[lilypond.git] / lily / cluster-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2002--2015 Juergen Reuter <reuter@ipd.uka.de>
5   Han-Wen Nienhuys <hanwen@xs4all.nl>
6
7   LilyPond is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   LilyPond is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "engraver.hh"
22 #include "spanner.hh"
23 #include "note-head.hh"
24 #include "note-column.hh"
25 #include "pointer-group-interface.hh"
26 #include "pitch.hh"
27 #include "stream-event.hh"
28 #include "item.hh"
29
30 #include "translator.icc"
31
32 using std::vector;
33
34 class Cluster_spanner_engraver : public Engraver
35 {
36
37 protected:
38   TRANSLATOR_DECLARATIONS (Cluster_spanner_engraver);
39   DECLARE_TRANSLATOR_LISTENER (cluster_note);
40   DECLARE_ACKNOWLEDGER (note_column);
41   void stop_translation_timestep ();
42   virtual void process_music ();
43   virtual void finalize ();
44 private:
45   vector<Stream_event *> cluster_notes_;
46   Item *beacon_;
47
48   void typeset_grobs ();
49   Spanner *spanner_;
50   Spanner *finished_spanner_;
51 };
52
53 Cluster_spanner_engraver::Cluster_spanner_engraver ()
54 {
55   spanner_ = 0;
56   finished_spanner_ = 0;
57   beacon_ = 0;
58 }
59
60 void
61 Cluster_spanner_engraver::finalize ()
62 {
63   typeset_grobs ();
64   finished_spanner_ = spanner_;
65   spanner_ = 0;
66   typeset_grobs ();
67 }
68
69 void
70 Cluster_spanner_engraver::typeset_grobs ()
71 {
72   if (finished_spanner_)
73     {
74       if (!finished_spanner_->get_bound (RIGHT))
75         {
76           finished_spanner_->set_bound (RIGHT,
77                                         finished_spanner_->get_bound (LEFT));
78
79         }
80
81       finished_spanner_ = 0;
82     }
83   beacon_ = 0;
84 }
85
86 IMPLEMENT_TRANSLATOR_LISTENER (Cluster_spanner_engraver, cluster_note);
87 void
88 Cluster_spanner_engraver::listen_cluster_note (Stream_event *ev)
89 {
90   cluster_notes_.push_back (ev);
91 }
92
93 void
94 Cluster_spanner_engraver::process_music ()
95 {
96   if (cluster_notes_.size ())
97     {
98       SCM c0scm = get_property ("middleCPosition");
99
100       int c0 = scm_is_number (c0scm) ? scm_to_int (c0scm) : 0;
101       int pmax = INT_MIN;
102       int pmin = INT_MAX;
103
104       for (vsize i = 0; i < cluster_notes_.size (); i++)
105         {
106           Pitch *pit = unsmob<Pitch> (cluster_notes_[i]->get_property ("pitch"));
107
108           int p = (pit ? pit->steps () : 0) + c0;
109
110           pmax = std::max (pmax, p);
111           pmin = std::min (pmin, p);
112         }
113
114       beacon_ = make_item ("ClusterSpannerBeacon", cluster_notes_[0]->self_scm ());
115       beacon_->set_property ("positions",
116                              scm_cons (scm_from_int (pmin),
117                                        scm_from_int (pmax)));
118     }
119
120   if (beacon_ && !spanner_)
121     spanner_ = make_spanner ("ClusterSpanner", cluster_notes_[0]->self_scm ());
122
123   if (beacon_ && spanner_)
124     {
125       add_bound_item (spanner_, beacon_);
126       Pointer_group_interface::add_grob (spanner_, ly_symbol2scm ("columns"), beacon_);
127     }
128 }
129
130 void
131 Cluster_spanner_engraver::stop_translation_timestep ()
132 {
133   typeset_grobs ();
134   cluster_notes_.clear ();
135 }
136
137 void
138 Cluster_spanner_engraver::acknowledge_note_column (Grob_info info)
139 {
140   if (!beacon_ && has_interface<Note_column> (info.grob ()))
141     {
142       finished_spanner_ = spanner_;
143       spanner_ = 0;
144     }
145 }
146
147 ADD_ACKNOWLEDGER (Cluster_spanner_engraver, note_column);
148 ADD_TRANSLATOR (Cluster_spanner_engraver,
149                 /* doc */
150                 "Engrave a cluster using @code{Spanner} notation.",
151
152                 /* create */
153                 "ClusterSpanner "
154                 "ClusterSpannerBeacon ",
155
156                 /* read */
157                 "",
158
159                 /* write */
160                 ""
161                );
162