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