Consider accidentals in optical spacing correction.
[lilypond.git] / lily / piano-pedal-align-engraver.cc
blobc82cb7eae135d361571d7e169fa626fbb25094b5
1 /*
2 piano-pedal-align-engraver.cc -- implement Piano_pedal_align_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2006--2009 Han-Wen Nienhuys <hanwen@lilypond.org>
8 */
11 #include "engraver.hh"
13 #include "spanner.hh"
14 #include "item.hh"
15 #include "side-position-interface.hh"
16 #include "stream-event.hh"
17 #include "warn.hh"
18 #include "axis-group-interface.hh"
22 TODO:
25 * Detach from pedal specifics,
27 * Also use this engraver for dynamics.
32 struct Pedal_align_info
34 Spanner *line_spanner_;
35 Grob *carrying_item_;
36 Spanner *carrying_spanner_;
37 Spanner *finished_carrying_spanner_;
39 Pedal_align_info ()
41 clear ();
44 void clear ()
46 line_spanner_ = 0;
47 carrying_spanner_ = 0;
48 carrying_item_ = 0;
49 finished_carrying_spanner_ = 0;
51 bool is_finished ()
53 bool do_continue = carrying_item_;
55 do_continue |= (carrying_spanner_ && !finished_carrying_spanner_);
56 do_continue |= (carrying_spanner_ && finished_carrying_spanner_ != carrying_spanner_);
58 return !do_continue;
62 class Piano_pedal_align_engraver : public Engraver
64 public:
65 TRANSLATOR_DECLARATIONS (Piano_pedal_align_engraver);
67 protected:
68 virtual void finalize ();
70 DECLARE_ACKNOWLEDGER (piano_pedal_script);
71 DECLARE_ACKNOWLEDGER (piano_pedal_bracket);
72 DECLARE_ACKNOWLEDGER (note_column);
74 DECLARE_END_ACKNOWLEDGER (piano_pedal_bracket);
76 void stop_translation_timestep ();
77 void start_translation_timestep ();
79 private:
80 enum Pedal_type {
81 SOSTENUTO,
82 SUSTAIN,
83 UNA_CORDA,
84 NUM_PEDAL_TYPES
86 Pedal_align_info pedal_info_[NUM_PEDAL_TYPES];
87 vector<Grob *> supports_;
89 Pedal_type get_grob_pedal_type (Grob_info g);
90 Spanner *make_line_spanner (Pedal_type t, SCM);
93 Piano_pedal_align_engraver::Piano_pedal_align_engraver ()
97 void
98 Piano_pedal_align_engraver::start_translation_timestep ()
100 supports_.clear ();
103 void
104 Piano_pedal_align_engraver::stop_translation_timestep ()
106 for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
108 if (pedal_info_[i].line_spanner_)
111 if (pedal_info_[i].carrying_item_)
113 if (!pedal_info_[i].line_spanner_->get_bound (LEFT))
114 pedal_info_[i].line_spanner_->set_bound (LEFT,
115 pedal_info_[i].carrying_item_);
117 pedal_info_[i].line_spanner_->set_bound (RIGHT,
118 pedal_info_[i].carrying_item_);
120 else if (pedal_info_[i].carrying_spanner_
121 || pedal_info_[i].finished_carrying_spanner_
124 if (!pedal_info_[i].line_spanner_->get_bound (LEFT)
125 && pedal_info_[i].carrying_spanner_->get_bound (LEFT))
126 pedal_info_[i].line_spanner_->set_bound (LEFT,
127 pedal_info_[i].carrying_spanner_->get_bound (LEFT));
130 if (pedal_info_[i].finished_carrying_spanner_)
131 pedal_info_[i].line_spanner_->set_bound (RIGHT,
132 pedal_info_[i].finished_carrying_spanner_->get_bound (RIGHT));
135 for (vsize j = 0; j < supports_.size (); j++)
137 Side_position_interface::add_support (pedal_info_[i].line_spanner_, supports_[j]);
140 if (pedal_info_[i].is_finished ())
142 announce_end_grob (pedal_info_[i].line_spanner_, SCM_EOL);
143 pedal_info_[i].clear ();
147 pedal_info_[i].carrying_item_ = 0;
151 Piano_pedal_align_engraver::Pedal_type
152 Piano_pedal_align_engraver::get_grob_pedal_type (Grob_info g)
154 if (g.event_cause ()->in_event_class ("sostenuto-event"))
155 return SOSTENUTO;
156 if (g.event_cause ()->in_event_class ("sustain-event"))
157 return SUSTAIN;
158 if (g.event_cause ()->in_event_class ("una-corda-event"))
159 return UNA_CORDA;
161 programming_error ("Unknown piano pedal type. Defaulting to sustain");
162 return SUSTAIN;
166 Spanner *
167 Piano_pedal_align_engraver::make_line_spanner (Pedal_type t, SCM cause)
169 Spanner *sp = pedal_info_[t].line_spanner_;
170 if (!sp)
172 switch (t)
174 case (SOSTENUTO):
175 sp = make_spanner ("SostenutoPedalLineSpanner", cause);
176 break;
177 case (SUSTAIN):
178 sp = make_spanner ("SustainPedalLineSpanner", cause);
179 break;
180 case (UNA_CORDA):
181 sp = make_spanner ("UnaCordaPedalLineSpanner", cause);
182 break;
183 default:
184 programming_error ("No pedal type fonud!") ;
185 return sp;
188 pedal_info_[t].line_spanner_ = sp;
191 return sp;
194 void
195 Piano_pedal_align_engraver::acknowledge_note_column (Grob_info gi)
197 supports_.push_back (gi.grob ());
200 void
201 Piano_pedal_align_engraver::acknowledge_piano_pedal_bracket (Grob_info gi)
203 Pedal_type type = get_grob_pedal_type (gi);
204 Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
206 Axis_group_interface::add_element (sp, gi.grob ());
207 pedal_info_[type].carrying_spanner_ = gi.spanner ();
210 void
211 Piano_pedal_align_engraver::acknowledge_end_piano_pedal_bracket (Grob_info gi)
213 Pedal_type type = get_grob_pedal_type (gi);
214 pedal_info_[type].finished_carrying_spanner_ = gi.spanner ();
217 void
218 Piano_pedal_align_engraver::acknowledge_piano_pedal_script (Grob_info gi)
220 Pedal_type type = get_grob_pedal_type (gi);
222 Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
223 Axis_group_interface::add_element (sp, gi.grob ());
224 pedal_info_[type].carrying_item_ = gi.grob ();
228 void
229 Piano_pedal_align_engraver::finalize ()
231 for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
233 if (pedal_info_[i].line_spanner_)
235 SCM cc = get_property ("currentCommandColumn");
236 Item *c = unsmob_item (cc);
237 pedal_info_[i].line_spanner_->set_bound (RIGHT, c);
239 pedal_info_[i].clear ();
244 #include "translator.icc"
246 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, note_column);
247 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
248 ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_script);
250 ADD_END_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
253 ADD_TRANSLATOR (Piano_pedal_align_engraver,
254 /* doc */
255 "Align piano pedal symbols and brackets.",
257 /* create */
258 "SostenutoPedalLineSpanner "
259 "SustainPedalLineSpanner "
260 "UnaCordaPedalLineSpanner ",
262 /* read */
263 "currentCommandColumn ",
265 /* write */