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"
18 #include "text-item.hh"
19 #include "side-position-interface.hh"
20 #include "engraver.hh"
22 #include "note-head.hh"
23 #include "group-interface.hh"
24 #include "directional-element-interface.hh"
25 #include "staff-symbol-referencer.hh"
26 #include "translator-group.hh"
32 * direction of text-dynamic-request if not equalt to direction
36 class Dynamic_line_spanner : public Spanner
39 Dynamic_line_spanner ();
40 VIRTUAL_COPY_CONS(Score_element);
41 void add_column (Item*);
44 virtual void after_line_breaking ();
47 Dynamic_line_spanner::Dynamic_line_spanner ()
49 set_elt_property ("transparent", SCM_BOOL_T);
50 side_position (this).set_axis (Y_AXIS);
54 Dynamic_line_spanner::add_column (Item* n)
56 if (!get_bound (LEFT))
65 Dynamic_line_spanner::after_line_breaking ()
70 We hebben hier een probleempje: er is een verschil tussen
71 dynamics zonder en met line-spanner.
72 Allen zijn gecentreerd (aligned-on-self), wat okee is,
73 maar de losse hebben zelf een padding tov de staff.
75 Deze padding werkt niet op items die in line-spanner zitten:
76 de padding werkt op line-spanner zelf.
77 De line-spanner moet dus eigenlijk zoveel naar beneden of boven
78 als er items uitsteken, maar Hmm.
81 Direction dir = directional_element (this).get ();
85 //translate_axis (extent (Y_AXIS)[dir], Y_AXIS);
86 translate_axis (staff_symbol_referencer (this).staff_space () * dir, Y_AXIS);
90 print text & hairpin dynamics.
92 class Dynamic_engraver : public Engraver
95 Crescendo * finished_cresc_p_;
98 Text_script_req* text_req_l_;
99 Span_req * span_start_req_l_;
100 Drul_array<Span_req*> span_req_l_drul_;
102 Dynamic_line_spanner* line_spanner_;
103 Moment last_request_mom_;
105 Note_column* pending_column_;
106 Link_array<Score_element> pending_element_arr_;
111 VIRTUAL_COPY_CONS(Translator);
115 void announce_element (Score_element_info);
117 virtual void do_removal_processing ();
118 virtual void acknowledge_element (Score_element_info);
119 virtual bool do_try_music (Music *req_l);
120 virtual void do_process_music ();
121 virtual void do_pre_move_processing ();
122 virtual void do_post_move_processing ();
125 ADD_THIS_TRANSLATOR (Dynamic_engraver);
128 Dynamic_engraver::announce_element (Score_element_info i)
130 group (i.elem_l_, "interfaces").add_thing (ly_symbol2scm ("dynamic"));
132 Engraver::announce_element (i);
136 Dynamic_engraver::Dynamic_engraver ()
139 finished_cresc_p_ = 0;
141 span_start_req_l_ = 0;
146 span_req_l_drul_[START] = 0;
147 span_req_l_drul_[STOP] = 0;
151 Dynamic_engraver::do_post_move_processing ()
154 span_req_l_drul_[START] = 0;
155 span_req_l_drul_[STOP] = 0;
157 /* ugr; we must attach the Dynamic_line_spanner to something
158 to be sure that the linebreaker will not be confused
160 // if (line_spanner_)
161 // line_spanner_->add_column (LEFT, get_staff_info ().command_pcol_l ());
165 Dynamic_engraver::do_try_music (Music * m)
167 if (Text_script_req* d = dynamic_cast <Text_script_req*> (m))
169 if (d->style_str_ == "dynamic")
175 else if (Span_req* s = dynamic_cast <Span_req*> (m))
177 if ((s->span_type_str_ == "crescendo"
178 || s->span_type_str_ == "decrescendo"))
180 span_req_l_drul_[s->span_dir_] = s;
188 Dynamic_engraver::do_process_music ()
190 if ((span_req_l_drul_[START] || text_req_l_)
192 && pending_element_arr_.size ())
194 line_spanner_ = new Dynamic_line_spanner;
195 assert (pending_column_);
196 line_spanner_->add_column (pending_column_);
197 announce_element (Score_element_info
199 text_req_l_ ? text_req_l_ : span_req_l_drul_[START]));
203 if (line_spanner_ && pending_element_arr_.size ())
205 for (int i = 0; i < pending_element_arr_.size (); i++)
206 pending_element_arr_[i]->set_parent (line_spanner_, Y_AXIS);
207 pending_element_arr_.clear ();
210 if (span_req_l_drul_[START] || span_req_l_drul_[STOP] || text_req_l_)
211 last_request_mom_ = now_mom ();
214 for (int i = 0; i < pending_element_arr_.size (); i++)
216 Score_element* e = pending_element_arr_[i];
217 side_position (e).set_axis (Y_AXIS);
218 side_position (e).add_staff_support ();
223 Direction d = directional_element (e).get ();
226 SCM s = get_property ("dynamicDirection");
228 s = get_property ("verticalDirection");
231 directional_element (e).set (d);
234 SCM s = get_property ("dynamicPadding");
236 e->set_elt_property ("padding", s);
237 s = get_property ("dynamicMinimumSpace");
239 e->set_elt_property ("minimum-space", s);
241 pending_element_arr_.clear ();
246 String loud = text_req_l_->text_str_;
248 text_p_ = new Text_item;
249 text_p_->set_elt_property ("text",
250 ly_str02scm (loud.ch_C ()));
251 text_p_->set_elt_property ("style", gh_str02scm ("dynamic"));
252 text_p_->set_elt_property ("script-priority",
254 if (Direction d=text_req_l_->get_direction ())
255 directional_element (text_p_).set (d);
256 pending_element_arr_.push (text_p_);
257 text_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
258 text_p_->add_offset_callback (Side_position_interface::aligned_on_self,
260 announce_element (Score_element_info (text_p_, text_req_l_));
263 if (span_req_l_drul_[STOP])
267 span_req_l_drul_[STOP]->warning
268 (_ ("can't find start of (de)crescendo"));
272 assert (!finished_cresc_p_);
273 cresc_p_->set_bound(RIGHT, get_staff_info ().musical_pcol_l ());
274 finished_cresc_p_ = cresc_p_;
276 span_start_req_l_ = 0;
280 if (span_req_l_drul_[START])
282 if (span_start_req_l_)
284 span_req_l_drul_[START]->warning
285 (span_start_req_l_->span_dir_ == 1
287 _ ("already have a crescendo")
288 : _ ("already have a decrescendo"));
292 span_start_req_l_ = span_req_l_drul_[START];
293 cresc_p_ = new Crescendo;
294 cresc_p_->set_elt_property
296 gh_int2scm ((span_req_l_drul_[START]->span_type_str_ == "crescendo")
297 ? BIGGER : SMALLER));
299 SCM s = get_property (span_req_l_drul_[START]->span_type_str_ + "Text");
302 cresc_p_->set_elt_property ("start-text", s);
303 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
304 + "Text", SCM_UNDEFINED);
307 s = get_property (span_req_l_drul_[START]->span_type_str_ + "Spanner");
308 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
310 cresc_p_->set_elt_property ("spanner", s);
311 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
312 + "Spanner", SCM_UNDEFINED);
315 cresc_p_->set_bound(LEFT, get_staff_info ().musical_pcol_l ());
319 We know how wide the text is, if we can be sure that the
320 text already has relevant pointers into the paperdef,
321 and it has its font-size property set.
323 Since font-size may be set by a context higher up, we
324 can not be sure of the size.
327 We shouldn't try to do this stuff here, the Item should
328 do it when the score is finished. We could maybe
329 set a callback to have the Item do the alignment if
330 it is not a special symbol, like Crescendo.
336 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
338 if (finished_cresc_p_)
339 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
342 pending_element_arr_.push (cresc_p_);
343 cresc_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
344 cresc_p_->add_offset_callback
345 (Side_position_interface::aligned_on_self, Y_AXIS);
346 announce_element (Score_element_info (cresc_p_, span_req_l_drul_[START]));
352 Dynamic_engraver::do_pre_move_processing ()
358 Dynamic_engraver::do_removal_processing ()
362 typeset_element (cresc_p_ );
363 span_start_req_l_->warning (_ ("unterminated (de)crescendo"));
369 side_position (line_spanner_).add_staff_support ();
370 typeset_element (line_spanner_);
376 Dynamic_engraver::typeset_all ()
378 if (finished_cresc_p_)
380 typeset_element (finished_cresc_p_);
381 finished_cresc_p_ =0;
386 typeset_element (text_p_);
391 TODO: This should be optionised:
392 * break when group of dynamic requests ends
394 * continue through piece */
395 if (line_spanner_ && last_request_mom_ < now_mom ())
397 side_position (line_spanner_).add_staff_support ();
398 typeset_element (line_spanner_);
404 Dynamic_engraver::acknowledge_element (Score_element_info i)
406 if (Note_column* n = dynamic_cast<Note_column*> (i.elem_l_))
410 side_position (line_spanner_).add_support (n);
411 line_spanner_->add_column (n);