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 clear_spanners();
52 Array<Figure_group> groups_;
54 Link_array<Music> new_musics_;
59 virtual bool try_music (Music *);
60 virtual void derived_mark () const;
62 void start_translation_timestep ();
63 void stop_translation_timestep ();
64 void process_music ();
68 New_figured_bass_engraver::derived_mark () const
70 for (int i = 0; i < groups_.size (); i++)
72 scm_gc_mark (groups_[i].number_);
73 scm_gc_mark (groups_[i].alteration_);
78 New_figured_bass_engraver::stop_translation_timestep ()
80 if (groups_.is_empty ()
81 || now_mom ().main_part_ < stop_moment_.main_part_)
85 for (int i = 0; !found && i < groups_.size (); i++)
86 found = found || groups_[i].current_music_;
92 New_figured_bass_engraver::New_figured_bass_engraver ()
95 continuation_ = false;
100 New_figured_bass_engraver::start_translation_timestep ()
102 if (now_mom ().main_part_ < stop_moment_.main_part_)
106 new_musics_.clear ();
107 for (int i = 0; i < groups_.size (); i++)
109 groups_[i].current_music_ = 0;
110 groups_[i].is_continuation_ = false;
112 continuation_ = false;
116 New_figured_bass_engraver::try_music (Music *m)
118 if (m->is_mus_type ("rest-event"))
125 SCM fig = m->get_property ("figure");
126 for (int i = 0; i < groups_.size (); i++)
128 if (!groups_[i].current_music_
129 && 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 ();
150 New_figured_bass_engraver::clear_spanners ()
160 New_figured_bass_engraver::add_brackets ()
162 Link_array<Grob> encompass;
164 for (int i = 0; i < groups_.size (); i ++)
166 if (!groups_[i].current_music_)
169 if (to_boolean (groups_[i].current_music_->get_property ("bracket-start")))
174 if (inside && groups_[i].figure_item_)
175 encompass.push (groups_[i].figure_item_);
177 if (to_boolean (groups_[i].current_music_->get_property ("bracket-stop")))
181 Item * brack = make_item ("BassFigureBracket", groups_[i].current_music_->self_scm ());
182 for (int j = 0; j < encompass.size (); j++)
184 Pointer_group_interface::add_grob (brack,
185 ly_symbol2scm ("elements"),
194 New_figured_bass_engraver::process_music ()
203 && new_musics_.is_empty ())
209 Grob *muscol = dynamic_cast<Item*> (unsmob_grob (get_property ("currentMusicalColumn")));
213 alignment_ = make_spanner ("BassFigureAlignment", SCM_EOL);
214 alignment_->set_bound (LEFT, muscol);
218 for (int i = 0; i < new_musics_.size (); i++)
220 while (k < groups_.size() &&
221 groups_[k].current_music_)
224 if (k >= groups_.size ())
227 groups_.push (group);
231 groups_[k].current_music_ = new_musics_[i];
232 groups_[k].figure_item_ = 0;
236 SCM proc = get_property ("newFiguredBassFormatter");
238 alignment_->set_bound (RIGHT, muscol);
239 if (to_boolean (get_property ("useBassFigureExtenders")))
240 for (int i = 0; i < groups_.size(); i++)
242 if (groups_[i].is_continuation_)
244 if (!groups_[i].continuation_line_)
246 Spanner * line = make_spanner ("BassFigureContinuation", SCM_EOL);
247 Item * item = groups_[i].figure_item_;
248 groups_[i].continuation_line_ = line;
249 line->set_bound (LEFT, item);
252 Don't add as child. This will cache the wrong
253 (pre-break) stencil when callbacks are triggered.
255 line->set_parent (groups_[i].group_, Y_AXIS);
256 Pointer_group_interface::add_grob (line, ly_symbol2scm ("figures"), item);
258 groups_[i].figure_item_ = 0;
262 groups_[i].continuation_line_ = 0;
265 for (int i = 0; i < groups_.size(); i++)
267 Figure_group &group = groups_[i];
269 if (group.continuation_line_)
271 group.continuation_line_->set_bound (RIGHT, muscol);
273 else if (group.current_music_)
276 = make_item ("NewBassFigure",
277 group.current_music_->self_scm ());
278 SCM fig = group.current_music_->get_property ("figure");
281 group.group_ = make_spanner ("BassFigureLine", SCM_EOL);
282 group.group_->set_bound (LEFT, muscol);
283 Align_interface::add_element (alignment_,
285 Align_interface::alignment_callback_proc);
290 group.alteration_ = group.current_music_->get_property ("alteration");
292 SCM text = group.current_music_->get_property ("text");
293 if (!Text_interface::is_markup (text)
294 && ly_is_procedure (proc))
296 text = scm_call_3 (proc, fig, group.current_music_->self_scm (),
297 context ()->self_scm ());
300 item->set_property ("text", text);
302 Axis_group_interface::add_element (group.group_, item);
303 group.figure_item_ = item;
306 groups_[i].group_->set_bound (RIGHT, muscol);
313 ADD_TRANSLATOR (New_figured_bass_engraver,
316 "Make figured bass numbers.",
319 "BassFigureAlignment "
321 "BassFigureContinuation "
325 "bass-figure-event rest-event",
328 "useBassFigureExtenders",