2 new-figured-bass-engraver.cc -- implement New_figured_bass_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
10 #include "engraver.hh"
16 #include "axis-group-interface.hh"
17 #include "align-interface.hh"
18 #include "pointer-group-interface.hh"
19 #include "text-interface.hh"
21 #include "translator.icc"
26 Spanner *continuation_line_;
31 bool is_continuation_;
33 Music *current_music_;
37 is_continuation_ = false;
38 continuation_line_ = 0;
40 alteration_ = SCM_EOL;
46 struct New_figured_bass_engraver : public Engraver
48 TRANSLATOR_DECLARATIONS(New_figured_bass_engraver);
49 void finalize_spanners();
52 Array<Figure_group> groups_;
54 Link_array<Music> new_musics_;
59 virtual bool try_music (Music *);
60 virtual void finalize ();
61 virtual void derived_mark () const;
63 void start_translation_timestep ();
64 void stop_translation_timestep ();
65 void process_music ();
69 New_figured_bass_engraver::derived_mark () const
71 for (int i = 0; i < groups_.size (); i++)
73 scm_gc_mark (groups_[i].number_);
74 scm_gc_mark (groups_[i].alteration_);
79 New_figured_bass_engraver::stop_translation_timestep ()
81 if (groups_.is_empty ()
82 || now_mom ().main_part_ < stop_moment_.main_part_)
86 for (int i = 0; !found && i < groups_.size (); i++)
87 found = found || groups_[i].current_music_;
93 New_figured_bass_engraver::New_figured_bass_engraver ()
96 continuation_ = false;
101 New_figured_bass_engraver::start_translation_timestep ()
103 if (now_mom ().main_part_ < stop_moment_.main_part_)
107 new_musics_.clear ();
108 for (int i = 0; i < groups_.size (); i++)
110 groups_[i].current_music_ = 0;
111 groups_[i].is_continuation_ = false;
113 continuation_ = false;
117 New_figured_bass_engraver::try_music (Music *m)
119 if (m->is_mus_type ("rest-event"))
126 SCM fig = m->get_property ("figure");
127 for (int i = 0; i < groups_.size (); i++)
129 if (ly_is_equal (groups_[i].number_, fig))
131 groups_[i].current_music_ = m;
132 groups_[i].is_continuation_ =
133 ly_is_equal (groups_[i].alteration_,
134 m->get_property ("alteration"));
136 continuation_ = true;
141 new_musics_.push (m);
143 stop_moment_ = now_mom () + m->get_length ();
149 New_figured_bass_engraver::finalize_spanners ()
159 New_figured_bass_engraver::add_brackets ()
161 Link_array<Grob> encompass;
163 for (int i = 0; i < groups_.size (); i ++)
165 if (!groups_[i].current_music_)
168 if (to_boolean (groups_[i].current_music_->get_property ("bracket-start")))
173 if (inside && groups_[i].figure_item_)
174 encompass.push (groups_[i].figure_item_);
176 if (to_boolean (groups_[i].current_music_->get_property ("bracket-stop")))
180 Item * brack = make_item ("BassFigureBracket", groups_[i].current_music_->self_scm ());
181 for (int j = 0; j < encompass.size (); j++)
183 Pointer_group_interface::add_grob (brack,
184 ly_symbol2scm ("elements"),
193 New_figured_bass_engraver::process_music ()
197 finalize_spanners ();
202 && new_musics_.is_empty ())
204 finalize_spanners ();
208 Grob *muscol = dynamic_cast<Item*> (unsmob_grob (get_property ("currentMusicalColumn")));
211 finalize_spanners ();
212 alignment_ = make_spanner ("BassFigureAlignment", SCM_EOL);
213 alignment_->set_bound (LEFT, muscol);
217 for (int i = 0; i < new_musics_.size (); i++)
219 while (k < groups_.size() &&
220 groups_[k].current_music_)
223 if (k >= groups_.size ())
226 groups_.push (group);
230 groups_[k].current_music_ = new_musics_[i];
231 groups_[k].figure_item_ = 0;
235 SCM proc = get_property ("newFiguredBassFormatter");
237 alignment_->set_bound (RIGHT, muscol);
238 if (to_boolean (get_property ("useBassFigureExtenders")))
239 for (int i = 0; i < groups_.size(); i++)
241 if (groups_[i].is_continuation_)
243 if (!groups_[i].continuation_line_)
245 Spanner * line = make_spanner ("BassFigureContinuation", SCM_EOL);
246 Item * item = groups_[i].figure_item_;
247 groups_[i].continuation_line_ = line;
248 line->set_bound (LEFT, item);
251 Don't add as child. This will cache the wrong
252 (pre-break) stencil when callbacks are triggered.
254 line->set_parent (groups_[i].group_, Y_AXIS);
255 Pointer_group_interface::add_grob (line, ly_symbol2scm ("figures"), item);
257 groups_[i].figure_item_ = 0;
261 groups_[i].continuation_line_ = 0;
264 for (int i = 0; i < groups_.size(); i++)
266 Figure_group &group = groups_[i];
268 if (group.continuation_line_)
270 group.continuation_line_->set_bound (RIGHT, muscol);
272 else if (group.current_music_)
275 = make_item ("NewBassFigure",
276 group.current_music_->self_scm ());
277 SCM fig = group.current_music_->get_property ("figure");
280 group.group_ = make_spanner ("BassFigureLine", SCM_EOL);
281 group.group_->set_bound (LEFT, muscol);
282 Align_interface::add_element (alignment_,
284 Align_interface::alignment_callback_proc);
289 group.alteration_ = group.current_music_->get_property ("alteration");
291 SCM text = group.current_music_->get_property ("text");
292 if (!Text_interface::is_markup (text)
293 && ly_is_procedure (proc))
295 text = scm_call_3 (proc, fig, group.current_music_->self_scm (),
296 context ()->self_scm ());
299 item->set_property ("text", text);
301 Axis_group_interface::add_element (group.group_, item);
302 group.figure_item_ = item;
305 groups_[i].group_->set_bound (RIGHT, muscol);
312 New_figured_bass_engraver::finalize ()
314 finalize_spanners ();
318 ADD_TRANSLATOR (New_figured_bass_engraver,
321 "Make figured bass numbers.",
323 "BassFigure BassFigureLine BassFigureAlignment BassFigureBracket",
326 "bass-figure-event rest-event",
329 "useBassFigureExtenders",