]> git.donarmstrong.com Git - lilypond.git/blob - lily/custos-engraver.cc
0f94d95e07838e3d9a141dfcdff27426e5506ea6
[lilypond.git] / lily / custos-engraver.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2000--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 "item.hh"
23 #include "note-head.hh"
24 #include "pitch.hh"
25 #include "staff-symbol-referencer.hh"
26 #include "stream-event.hh"
27 #include "warn.hh"
28
29 #include "translator.icc"
30
31 using std::vector;
32
33 /*
34  * This class implements an engraver for custos symbols.
35  *
36  * FIXME: note heads inside of ligatures (i.e. ligature heads) are
37  * sometimes not recognized by this engraver. --jr
38  */
39 class Custos_engraver : public Engraver
40 {
41 public:
42   TRANSLATOR_DECLARATIONS (Custos_engraver);
43   void start_translation_timestep ();
44   DECLARE_ACKNOWLEDGER (bar);
45   DECLARE_ACKNOWLEDGER (note_head);
46   void process_acknowledged ();
47   void stop_translation_timestep ();
48   virtual void finalize ();
49
50 private:
51   Item *create_custos ();
52   bool custos_permitted_;
53   vector<Grob *> custodes_;
54   vector<Pitch> pitches_;
55 };
56
57 Custos_engraver::Custos_engraver ()
58 {
59   custos_permitted_ = false;
60 }
61
62 void
63 Custos_engraver::stop_translation_timestep ()
64 {
65   /*
66     delay typeset until we're at the next moment, so we can silence custodes at the end of the piece.
67   */
68   pitches_.clear ();
69
70   custos_permitted_ = false;
71 }
72
73 void
74 Custos_engraver::start_translation_timestep ()
75 {
76   custodes_.clear ();
77 }
78
79 void
80 Custos_engraver::acknowledge_bar (Grob_info /* info */)
81 {
82   custos_permitted_ = true;
83 }
84
85 void
86 Custos_engraver::acknowledge_note_head (Grob_info info)
87 {
88   Stream_event *ev = info.event_cause ();
89   if (ev && ev->in_event_class ("note-event"))
90     {
91
92       /*
93         ideally, we'd do custos->set_parent (Y_AXIS, notehead),
94         but since the note head lives on the other system, we can't
95
96         So we copy the position from the note head pitch.  We
97         don't look at the staff-position, since we can't be sure
98         whether Clef_engraver already applied a vertical shift.
99       */
100       pitches_.push_back (*unsmob<Pitch> (ev->get_property ("pitch")));
101     }
102 }
103
104 void
105 Custos_engraver::process_acknowledged ()
106 {
107   if (scm_is_string (get_property ("whichBar")))
108     custos_permitted_ = true;
109
110   if (custos_permitted_)
111     {
112       for (vsize i = pitches_.size (); i--;)
113         {
114           Item *c = create_custos ();
115
116           int p = pitches_[i].steps ();
117           SCM c0 = get_property ("middleCPosition");
118           if (scm_is_number (c0))
119             p += scm_to_int (c0);
120
121           c->set_property ("staff-position",
122                            scm_from_int (p));
123         }
124
125       pitches_.clear ();
126     }
127 }
128
129 Item *
130 Custos_engraver::create_custos ()
131 {
132   Item *custos = make_item ("Custos", SCM_EOL);
133
134   custodes_.push_back (custos);
135
136   return custos;
137 }
138
139 void
140 Custos_engraver::finalize ()
141 {
142   for (vsize i = custodes_.size (); i--;)
143     custodes_[i]->suicide ();
144   custodes_.clear ();
145 }
146
147 ADD_ACKNOWLEDGER (Custos_engraver, bar);
148 ADD_ACKNOWLEDGER (Custos_engraver, note_head);
149
150 ADD_TRANSLATOR (Custos_engraver,
151                 /* doc */
152                 "Engrave custodes.",
153
154                 /* create */
155                 "Custos ",
156
157                 /* read */
158                 "",
159
160                 /* write */
161                 ""
162                );