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 "dimension-cache.hh"
11 #include "crescendo.hh"
12 #include "musical-request.hh"
14 #include "paper-def.hh"
15 #include "paper-column.hh"
16 #include "staff-symbol.hh"
17 #include "note-column.hh"
19 #include "side-position-interface.hh"
20 #include "engraver.hh"
22 #include "rhythmic-head.hh"
23 #include "group-interface.hh"
24 #include "directional-element-interface.hh"
25 #include "staff-symbol-referencer.hh"
26 #include "translator-group.hh"
27 #include "axis-group-interface.hh"
33 * direction of text-dynamic-request if not equal to direction of
38 print text & hairpin dynamics.
40 class Dynamic_engraver : public Engraver
43 Crescendo * finished_cresc_p_;
46 Text_script_req* text_req_l_;
48 Span_req * current_cresc_req_;
49 Drul_array<Span_req*> accepted_spanreqs_drul_;
51 Spanner* line_spanner_;
52 Spanner* finished_line_spanner_;
54 Link_array<Note_column> pending_column_arr_;
55 Link_array<Score_element> pending_element_arr_;
60 VIRTUAL_COPY_CONS(Translator);
64 virtual void do_removal_processing ();
65 virtual void acknowledge_element (Score_element_info);
66 virtual bool do_try_music (Music *req_l);
67 virtual void do_process_music ();
68 virtual void do_pre_move_processing ();
69 virtual void do_post_move_processing ();
72 ADD_THIS_TRANSLATOR (Dynamic_engraver);
75 Dynamic_engraver::Dynamic_engraver ()
78 finished_cresc_p_ = 0;
80 finished_line_spanner_ = 0;
81 current_cresc_req_ = 0;
85 accepted_spanreqs_drul_[START] = 0;
86 accepted_spanreqs_drul_[STOP] = 0;
90 Dynamic_engraver::do_post_move_processing ()
93 accepted_spanreqs_drul_[START] = 0;
94 accepted_spanreqs_drul_[STOP] = 0;
98 Dynamic_engraver::do_try_music (Music * m)
100 if (Text_script_req* d = dynamic_cast <Text_script_req*> (m))
102 if (d->style_str_ == "dynamic")
108 else if (Span_req* s = dynamic_cast <Span_req*> (m))
110 if ((s->span_type_str_ == "crescendo"
111 || s->span_type_str_ == "decrescendo"))
113 accepted_spanreqs_drul_[s->span_dir_] = s;
121 Dynamic_engraver::do_process_music ()
123 if (accepted_spanreqs_drul_[START] || accepted_spanreqs_drul_[STOP] || text_req_l_)
128 line_spanner_ = new Spanner (get_property ("basicDynamicLineSpannerProperties"));
130 Side_position_interface (line_spanner_).set_axis (Y_AXIS);
131 Axis_group_interface (line_spanner_).set_interface ();
132 Axis_group_interface (line_spanner_).set_axes (Y_AXIS, Y_AXIS);
133 announce_element (Score_element_info
135 text_req_l_ ? text_req_l_ : accepted_spanreqs_drul_[START]));
141 TODO: should finish and create new spanner if vertical dyn-direction is changed.
143 else if (!accepted_spanreqs_drul_[START] && !text_req_l_)
145 finished_line_spanner_ = line_spanner_;
150 todo: resurrect dynamic{direction, padding,minimumspace}
153 During a (de)crescendo, pending request will not be cleared,
154 and a line-spanner will always be created, as \< \! are already
157 Maybe always creating a line-spanner for a (de)crescendo (see
158 below) is not a good idea:
162 the \p will be centred on the line-spanner, and thus clash
163 with the hairpin. When axis-group code is in place, the \p
164 should move below the hairpin, which is probably better?
166 Urg, but line-spanner must always have at least same duration
167 as (de)crecsendo, b.o. line-breaking.
173 String loud = text_req_l_->text_str_;
175 text_p_ = new Item (get_property ("basicDynamicTextProperties"));
176 text_p_->set_elt_property ("text", ly_str02scm (loud.ch_C ()));
177 if (Direction d=text_req_l_->get_direction ())
178 Directional_element_interface (line_spanner_).set (d);
180 Axis_group_interface (line_spanner_).add_element (text_p_);
182 text_p_->add_offset_callback (Side_position_interface::aligned_on_self,
184 announce_element (Score_element_info (text_p_, text_req_l_));
187 if (accepted_spanreqs_drul_[STOP])
191 accepted_spanreqs_drul_[STOP]->warning
192 (_ ("can't find start of (de)crescendo"));
196 assert (!finished_cresc_p_);
197 cresc_p_->set_bound (RIGHT, unsmob_element (get_property ("currentMusicalColumn")));
198 finished_cresc_p_ = cresc_p_;
200 current_cresc_req_ = 0;
204 if (accepted_spanreqs_drul_[START])
206 if (current_cresc_req_)
208 accepted_spanreqs_drul_[START]->warning
209 (current_cresc_req_->span_dir_ == 1
211 _ ("already have a crescendo")
212 : _ ("already have a decrescendo"));
216 current_cresc_req_ = accepted_spanreqs_drul_[START];
217 cresc_p_ = new Crescendo (get_property ("basicCrescendoProperties"));
218 cresc_p_->set_elt_property
220 gh_int2scm ((accepted_spanreqs_drul_[START]->span_type_str_ == "crescendo")
221 ? BIGGER : SMALLER));
223 SCM s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Text").ch_C());
226 cresc_p_->set_elt_property ("start-text", s);
227 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
228 + "Text", SCM_UNDEFINED);
231 s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Spanner").ch_C());
237 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
239 cresc_p_->set_elt_property ("spanner", s);
240 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
241 + "Spanner", SCM_UNDEFINED);
244 cresc_p_->set_bound (LEFT, unsmob_element (get_property ("currentMusicalColumn")));
248 We know how wide the text is, if we can be sure that the
249 text already has relevant pointers into the paperdef,
250 and it has its font-size property set.
252 Since font-size may be set by a context higher up, we
253 can not be sure of the size.
256 We shouldn't try to do this stuff here, the Item should
257 do it when the score is finished. We could maybe
258 set a callback to have the Item do the alignment if
259 it is not a special symbol, like Crescendo.
265 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
267 if (finished_cresc_p_)
268 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
272 Axis_group_interface (line_spanner_).add_element (cresc_p_);
273 cresc_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
274 cresc_p_->add_offset_callback
275 (Side_position_interface::aligned_on_self, Y_AXIS);
276 announce_element (Score_element_info (cresc_p_, accepted_spanreqs_drul_[START]));
282 Dynamic_engraver::do_pre_move_processing ()
288 Dynamic_engraver::do_removal_processing ()
294 typeset_element (cresc_p_ );
295 finished_cresc_p_ = cresc_p_;
296 current_cresc_req_->warning (_ ("unterminated (de)crescendo"));
300 finished_line_spanner_ = line_spanner_;
306 Dynamic_engraver::typeset_all ()
308 if (finished_cresc_p_)
310 typeset_element (finished_cresc_p_);
311 finished_cresc_p_ =0;
316 typeset_element (text_p_);
319 if (finished_line_spanner_)
321 Side_position_interface (finished_line_spanner_).add_staff_support ();
323 if (!finished_line_spanner_->get_bound (LEFT))
326 = unsmob_element (get_property ("currentMusicalColumn"));
327 finished_line_spanner_->set_bound (LEFT, cmc);
329 if (!finished_line_spanner_->get_bound (RIGHT))
330 finished_line_spanner_->set_bound (RIGHT,
331 finished_line_spanner_->get_bound (LEFT));
334 typeset_element (finished_line_spanner_);
335 finished_line_spanner_ = 0;
340 Dynamic_engraver::acknowledge_element (Score_element_info i)
342 if (Note_column* n = dynamic_cast<Note_column*> (i.elem_l_))
346 Side_position_interface (line_spanner_).add_support (n);
347 add_bound_item (line_spanner_,n);