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 cresc_p_->set_bound (RIGHT, unsmob_element (get_property ("currentMusicalColumn")));
190 finished_cresc_p_ = cresc_p_;
192 current_cresc_req_ = 0;
196 if (accepted_spanreqs_drul_[START])
198 if (current_cresc_req_)
200 accepted_spanreqs_drul_[START]->origin ()->warning
201 (current_cresc_req_->span_dir_ == 1
202 ? _ ("already have a crescendo")
203 : _ ("already have a decrescendo"));
207 current_cresc_req_ = accepted_spanreqs_drul_[START];
208 cresc_p_ = new Spanner (get_property ("basicCrescendoProperties"));
209 Crescendo::set_interface (cresc_p_);
210 cresc_p_->set_elt_property
212 gh_int2scm ((accepted_spanreqs_drul_[START]->span_type_str_ == "crescendo")
213 ? BIGGER : SMALLER));
215 SCM s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Text").ch_C());
218 cresc_p_->set_elt_property ("start-text", s);
219 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
220 + "Text", SCM_UNDEFINED);
223 s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Spanner").ch_C());
229 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
231 cresc_p_->set_elt_property ("spanner", s);
232 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
233 + "Spanner", SCM_UNDEFINED);
236 cresc_p_->set_bound (LEFT, unsmob_element (get_property ("currentMusicalColumn")));
240 We know how wide the text is, if we can be sure that the
241 text already has relevant pointers into the paperdef,
242 and it has its font-size property set.
244 Since font-size may be set by a context higher up, we
245 can not be sure of the size.
248 We shouldn't try to do this stuff here, the Item should
249 do it when the score is finished. We could maybe
250 set a callback to have the Item do the alignment if
251 it is not a special symbol, like Crescendo.
257 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
258 LEFT, text_p_->self_scm ());
259 if (finished_cresc_p_)
260 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
261 RIGHT, text_p_->self_scm ());
264 Axis_group_interface::add_element (line_spanner_, cresc_p_);
265 cresc_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
266 cresc_p_->add_offset_callback
267 (Side_position::aligned_on_self, Y_AXIS);
268 announce_element (cresc_p_, accepted_spanreqs_drul_[START]);
274 Dynamic_engraver::do_pre_move_processing ()
280 Dynamic_engraver::do_removal_processing ()
287 typeset_element (cresc_p_ );
288 finished_cresc_p_ = cresc_p_;
290 current_cresc_req_->origin ()->warning (_ ("unterminated (de)crescendo"));
294 finished_line_spanner_ = line_spanner_;
300 current_cresc_req_->origin ()->warning (_ ("unterminated (de)crescendo"));
301 cresc_p_->suicide ();
305 line_spanner_->suicide ();
311 Dynamic_engraver::typeset_all ()
313 if (finished_cresc_p_)
315 typeset_element (finished_cresc_p_);
316 finished_cresc_p_ =0;
321 typeset_element (text_p_);
324 if (finished_line_spanner_)
326 Side_position::add_staff_support (finished_line_spanner_);
328 if (!finished_line_spanner_->get_bound (LEFT))
331 = unsmob_element (get_property ("currentMusicalColumn"));
332 finished_line_spanner_->set_bound (LEFT, cmc);
334 if (!finished_line_spanner_->get_bound (RIGHT))
335 finished_line_spanner_->set_bound (RIGHT,
336 finished_line_spanner_->get_bound (LEFT));
339 typeset_element (finished_line_spanner_);
340 finished_line_spanner_ = 0;
345 Dynamic_engraver::acknowledge_element (Score_element_info i)
347 if (Note_column::has_interface (i.elem_l_))
351 Side_position::add_support (line_spanner_,i.elem_l_);
352 add_bound_item (line_spanner_,dynamic_cast<Item*>(i.elem_l_));