]> git.donarmstrong.com Git - lilypond.git/blob - lily/cluster-engraver.cc
Doc-es: various updates.
[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 class Cluster_spanner_engraver : public Engraver
33 {
34
35 protected:
36   TRANSLATOR_DECLARATIONS (Cluster_spanner_engraver);
37   void listen_cluster_note (Stream_event *);
38   void acknowledge_note_column (Grob_info);
39   void stop_translation_timestep ();
40   virtual void process_music ();
41   virtual void finalize ();
42 private:
43   vector<Stream_event *> cluster_notes_;
44   Item *beacon_;
45
46   void typeset_grobs ();
47   Spanner *spanner_;
48   Spanner *finished_spanner_;
49 };
50
51 Cluster_spanner_engraver::Cluster_spanner_engraver (Context *c)
52   : Engraver (c)
53 {
54   spanner_ = 0;
55   finished_spanner_ = 0;
56   beacon_ = 0;
57 }
58
59 void
60 Cluster_spanner_engraver::finalize ()
61 {
62   typeset_grobs ();
63   finished_spanner_ = spanner_;
64   spanner_ = 0;
65   typeset_grobs ();
66 }
67
68 void
69 Cluster_spanner_engraver::typeset_grobs ()
70 {
71   if (finished_spanner_)
72     {
73       if (!finished_spanner_->get_bound (RIGHT))
74         {
75           finished_spanner_->set_bound (RIGHT,
76                                         finished_spanner_->get_bound (LEFT));
77
78         }
79
80       finished_spanner_ = 0;
81     }
82   beacon_ = 0;
83 }
84
85 void
86 Cluster_spanner_engraver::listen_cluster_note (Stream_event *ev)
87 {
88   cluster_notes_.push_back (ev);
89 }
90
91 void
92 Cluster_spanner_engraver::process_music ()
93 {
94   if (cluster_notes_.size ())
95     {
96       SCM c0scm = get_property ("middleCPosition");
97
98       int c0 = scm_is_number (c0scm) ? scm_to_int (c0scm) : 0;
99       int pmax = INT_MIN;
100       int pmin = INT_MAX;
101
102       for (vsize i = 0; i < cluster_notes_.size (); i++)
103         {
104           Pitch *pit = unsmob<Pitch> (cluster_notes_[i]->get_property ("pitch"));
105
106           int p = (pit ? pit->steps () : 0) + c0;
107
108           pmax = max (pmax, p);
109           pmin = min (pmin, p);
110         }
111
112       beacon_ = make_item ("ClusterSpannerBeacon", cluster_notes_[0]->self_scm ());
113       beacon_->set_property ("positions",
114                              scm_cons (scm_from_int (pmin),
115                                        scm_from_int (pmax)));
116     }
117
118   if (beacon_ && !spanner_)
119     spanner_ = make_spanner ("ClusterSpanner", cluster_notes_[0]->self_scm ());
120
121   if (beacon_ && spanner_)
122     {
123       add_bound_item (spanner_, beacon_);
124       Pointer_group_interface::add_grob (spanner_, ly_symbol2scm ("columns"), beacon_);
125     }
126 }
127
128 void
129 Cluster_spanner_engraver::stop_translation_timestep ()
130 {
131   typeset_grobs ();
132   cluster_notes_.clear ();
133 }
134
135 void
136 Cluster_spanner_engraver::acknowledge_note_column (Grob_info info)
137 {
138   if (!beacon_ && has_interface<Note_column> (info.grob ()))
139     {
140       finished_spanner_ = spanner_;
141       spanner_ = 0;
142     }
143 }
144
145 void
146 Cluster_spanner_engraver::boot ()
147 {
148   ADD_LISTENER (Cluster_spanner_engraver, cluster_note);
149   ADD_ACKNOWLEDGER (Cluster_spanner_engraver, note_column);
150 }
151
152 ADD_TRANSLATOR (Cluster_spanner_engraver,
153                 /* doc */
154                 "Engrave a cluster using @code{Spanner} notation.",
155
156                 /* create */
157                 "ClusterSpanner "
158                 "ClusterSpannerBeacon ",
159
160                 /* read */
161                 "",
162
163                 /* write */
164                 ""
165                );
166