2 dynamic-engraver.cc -- implement Dynamic_engraver
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 #include "dimensions.hh"
10 #include "crescendo.hh"
11 #include "musical-request.hh"
12 #include "paper-column.hh"
13 #include "note-column.hh"
15 #include "side-position-interface.hh"
16 #include "engraver.hh"
17 #include "group-interface.hh"
18 #include "directional-element-interface.hh"
19 #include "translator-group.hh"
20 #include "axis-group-interface.hh"
26 * direction of text-dynamic-request if not equal to direction of
31 print text & hairpin dynamics.
33 class Dynamic_engraver : public Engraver
36 Spanner * finished_cresc_p_;
39 Text_script_req* text_req_l_;
41 Span_req * current_cresc_req_;
42 Drul_array<Span_req*> accepted_spanreqs_drul_;
44 Spanner* line_spanner_;
45 Spanner* finished_line_spanner_;
47 Link_array<Note_column> pending_column_arr_;
48 Link_array<Score_element> pending_element_arr_;
53 VIRTUAL_COPY_CONS(Translator);
57 virtual void do_removal_processing ();
58 virtual void acknowledge_element (Score_element_info);
59 virtual bool do_try_music (Music *req_l);
60 virtual void do_process_music ();
61 virtual void do_pre_move_processing ();
62 virtual void do_post_move_processing ();
65 ADD_THIS_TRANSLATOR (Dynamic_engraver);
68 Dynamic_engraver::Dynamic_engraver ()
71 finished_cresc_p_ = 0;
73 finished_line_spanner_ = 0;
74 current_cresc_req_ = 0;
78 accepted_spanreqs_drul_[START] = 0;
79 accepted_spanreqs_drul_[STOP] = 0;
83 Dynamic_engraver::do_post_move_processing ()
86 accepted_spanreqs_drul_[START] = 0;
87 accepted_spanreqs_drul_[STOP] = 0;
91 Dynamic_engraver::do_try_music (Music * m)
93 if (Text_script_req* d = dynamic_cast <Text_script_req*> (m))
95 if (d->style_str_ == "dynamic")
101 else if (Span_req* s = dynamic_cast <Span_req*> (m))
103 if ((s->span_type_str_ == "crescendo"
104 || s->span_type_str_ == "decrescendo"))
106 accepted_spanreqs_drul_[s->span_dir_] = s;
114 Dynamic_engraver::do_process_music ()
116 if (accepted_spanreqs_drul_[START] || accepted_spanreqs_drul_[STOP] || text_req_l_)
121 line_spanner_ = new Spanner (get_property ("basicDynamicLineSpannerProperties"));
123 Side_position::set_axis (line_spanner_, Y_AXIS);
124 Axis_group_interface::set_interface (line_spanner_);
125 Axis_group_interface::set_axes (line_spanner_, Y_AXIS, Y_AXIS);
126 announce_element (line_spanner_,
127 text_req_l_ ? text_req_l_ : accepted_spanreqs_drul_[START]);
133 TODO: should finish and create new spanner if vertical dyn-direction is changed.
135 else if (!accepted_spanreqs_drul_[START] && !text_req_l_)
137 finished_line_spanner_ = line_spanner_;
142 todo: resurrect dynamic{direction, padding,minimumspace}
145 During a (de)crescendo, pending request will not be cleared,
146 and a line-spanner will always be created, as \< \! are already
149 Maybe always creating a line-spanner for a (de)crescendo (see
150 below) is not a good idea:
154 the \p will be centred on the line-spanner, and thus clash
155 with the hairpin. When axis-group code is in place, the \p
156 should move below the hairpin, which is probably better?
158 Urg, but line-spanner must always have at least same duration
159 as (de)crecsendo, b.o. line-breaking.
165 String loud = text_req_l_->text_str_;
167 text_p_ = new Item (get_property ("basicDynamicTextProperties"));
168 text_p_->set_elt_property ("text", ly_str02scm (loud.ch_C ()));
169 if (Direction d=text_req_l_->get_direction ())
170 Directional_element_interface::set (line_spanner_, d);
172 Axis_group_interface::add_element (line_spanner_, text_p_);
174 text_p_->add_offset_callback (Side_position::aligned_on_self,
176 announce_element (text_p_, text_req_l_);
179 if (accepted_spanreqs_drul_[STOP])
183 accepted_spanreqs_drul_[STOP]->origin ()->warning
184 (_ ("can't find start of (de)crescendo"));
188 assert (!finished_cresc_p_);
189 Score_element* cc = unsmob_element (get_property ("currentMusicalColumn"));
191 cresc_p_->set_bound (RIGHT, cc);
193 finished_cresc_p_ = cresc_p_;
195 current_cresc_req_ = 0;
199 if (accepted_spanreqs_drul_[START])
201 if (current_cresc_req_)
203 accepted_spanreqs_drul_[START]->origin ()->warning
204 (current_cresc_req_->span_dir_ == 1
205 ? _ ("already have a crescendo")
206 : _ ("already have a decrescendo"));
210 current_cresc_req_ = accepted_spanreqs_drul_[START];
211 cresc_p_ = new Spanner (get_property ("basicCrescendoProperties"));
212 Crescendo::set_interface (cresc_p_);
213 cresc_p_->set_elt_property
215 gh_int2scm ((accepted_spanreqs_drul_[START]->span_type_str_ == "crescendo")
216 ? BIGGER : SMALLER));
218 SCM s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Text").ch_C());
221 cresc_p_->set_elt_property ("start-text", s);
222 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
223 + "Text", SCM_UNDEFINED);
226 s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Spanner").ch_C());
232 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
234 cresc_p_->set_elt_property ("spanner", s);
235 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
236 + "Spanner", SCM_UNDEFINED);
239 Score_element *cc = unsmob_element (get_property ("currentMusicalColumn"));
240 cresc_p_->set_bound (LEFT, cc);
244 We know how wide the text is, if we can be sure that the
245 text already has relevant pointers into the paperdef,
246 and it has its font-size property set.
248 Since font-size may be set by a context higher up, we
249 can not be sure of the size.
252 We shouldn't try to do this stuff here, the Item should
253 do it when the score is finished. We could maybe
254 set a callback to have the Item do the alignment if
255 it is not a special symbol, like Crescendo.
261 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
262 LEFT, text_p_->self_scm ());
263 if (finished_cresc_p_)
264 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
265 RIGHT, text_p_->self_scm ());
268 Axis_group_interface::add_element (line_spanner_, cresc_p_);
269 cresc_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
270 cresc_p_->add_offset_callback
271 (Side_position::aligned_on_self, Y_AXIS);
272 announce_element (cresc_p_, accepted_spanreqs_drul_[START]);
278 Dynamic_engraver::do_pre_move_processing ()
284 Dynamic_engraver::do_removal_processing ()
291 typeset_element (cresc_p_ );
292 finished_cresc_p_ = cresc_p_;
294 current_cresc_req_->origin ()->warning (_ ("unterminated (de)crescendo"));
298 finished_line_spanner_ = line_spanner_;
304 current_cresc_req_->origin ()->warning (_ ("unterminated (de)crescendo"));
305 cresc_p_->suicide ();
309 line_spanner_->suicide ();
315 Dynamic_engraver::typeset_all ()
317 if (finished_cresc_p_)
319 typeset_element (finished_cresc_p_);
320 finished_cresc_p_ =0;
325 typeset_element (text_p_);
328 if (finished_line_spanner_)
330 Side_position::add_staff_support (finished_line_spanner_);
332 if (!finished_line_spanner_->get_bound (LEFT))
335 = unsmob_element (get_property ("currentMusicalColumn"));
336 finished_line_spanner_->set_bound (LEFT, cmc);
338 if (!finished_line_spanner_->get_bound (RIGHT))
339 finished_line_spanner_->set_bound (RIGHT,
340 finished_line_spanner_->get_bound (LEFT));
343 extend_spanner_over_elements (finished_line_spanner_);
344 typeset_element (finished_line_spanner_);
345 finished_line_spanner_ = 0;
350 Dynamic_engraver::acknowledge_element (Score_element_info i)
352 if (Note_column::has_interface (i.elem_l_))
356 Side_position::add_support (line_spanner_,i.elem_l_);
357 add_bound_item (line_spanner_,dynamic_cast<Item*>(i.elem_l_));