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 * padding of orphaned items
33 * direction of orphaned items
36 class Dynamic_line_spanner : public Spanner
39 Dynamic_line_spanner ();
40 VIRTUAL_COPY_CONS(Score_element);
41 void add_column (Item*);
42 Direction get_default_dir () const;
45 Dynamic_line_spanner::Dynamic_line_spanner ()
47 set_elt_property ("transparent", SCM_BOOL_T);
48 side_position (this).set_axis (Y_AXIS);
52 Dynamic_line_spanner::add_column (Item* n)
54 if (!get_bound (LEFT))
63 Dynamic_line_spanner::get_default_dir () const
69 print text & hairpin dynamics.
71 class Dynamic_engraver : public Engraver
74 Crescendo * finished_cresc_p_;
77 Text_script_req* text_req_l_;
78 Span_req * span_start_req_l_;
79 Drul_array<Span_req*> span_req_l_drul_;
81 Dynamic_line_spanner* line_spanner_;
82 Moment last_request_mom_;
84 Note_column* pending_column_;
85 Link_array<Score_element> pending_element_arr_;
90 VIRTUAL_COPY_CONS(Translator);
94 void announce_element (Score_element_info);
96 virtual void do_removal_processing ();
97 virtual void acknowledge_element (Score_element_info);
98 virtual bool do_try_music (Music *req_l);
99 virtual void do_process_music ();
100 virtual void do_pre_move_processing ();
101 virtual void do_post_move_processing ();
104 ADD_THIS_TRANSLATOR (Dynamic_engraver);
107 Dynamic_engraver::announce_element (Score_element_info i)
109 group (i.elem_l_, "interfaces").add_thing (ly_symbol2scm ("dynamic"));
111 Engraver::announce_element (i);
115 Dynamic_engraver::Dynamic_engraver ()
118 finished_cresc_p_ = 0;
120 span_start_req_l_ = 0;
125 span_req_l_drul_[START] = 0;
126 span_req_l_drul_[STOP] = 0;
130 Dynamic_engraver::do_post_move_processing ()
133 span_req_l_drul_[START] = 0;
134 span_req_l_drul_[STOP] = 0;
136 /* ugr; we must attach the Dynamic_line_spanner to something
137 to be sure that the linebreaker will not be confused
139 // if (line_spanner_)
140 // line_spanner_->add_column (LEFT, get_staff_info ().command_pcol_l ());
144 Dynamic_engraver::do_try_music (Music * m)
146 if (Text_script_req* d = dynamic_cast <Text_script_req*> (m))
148 if (d->style_str_ == "dynamic")
154 else if (Span_req* s = dynamic_cast <Span_req*> (m))
156 if ((s->span_type_str_ == "crescendo"
157 || s->span_type_str_ == "decrescendo"))
159 span_req_l_drul_[s->span_dir_] = s;
167 Dynamic_engraver::do_process_music ()
169 if ((span_req_l_drul_[START] || text_req_l_)
171 && pending_element_arr_.size ())
173 line_spanner_ = new Dynamic_line_spanner;
174 assert (pending_column_);
175 line_spanner_->add_column (pending_column_);
176 announce_element (Score_element_info
178 text_req_l_ ? text_req_l_ : span_req_l_drul_[START]));
182 if (line_spanner_ && pending_element_arr_.size ())
184 for (int i = 0; i < pending_element_arr_.size (); i++)
185 pending_element_arr_[i]->set_parent (line_spanner_, Y_AXIS);
186 pending_element_arr_.clear ();
189 if (span_req_l_drul_[START] || span_req_l_drul_[STOP] || text_req_l_)
190 last_request_mom_ = now_mom ();
193 for (int i = 0; i < pending_element_arr_.size (); i++)
195 Score_element* e = pending_element_arr_[i];
196 side_position (e).set_axis (Y_AXIS);
197 side_position (e).add_staff_support ();
202 Direction d = directional_element (e).get ();
205 SCM s = get_property ("dynamicDirection");
207 s = get_property ("verticalDirection");
210 directional_element (e).set (d);
213 SCM s = get_property ("dynamicPadding");
215 e->set_elt_property ("padding", s);
217 pending_element_arr_.clear ();
222 String loud = text_req_l_->text_str_;
224 text_p_ = new Text_item;
225 text_p_->set_elt_property ("text",
226 ly_str02scm (loud.ch_C ()));
227 text_p_->set_elt_property ("style", gh_str02scm ("dynamic"));
228 text_p_->set_elt_property ("script-priority",
230 if (Direction d=text_req_l_->get_direction ())
231 directional_element (text_p_).set (d);
232 pending_element_arr_.push (text_p_);
233 text_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
234 text_p_->add_offset_callback (Side_position_interface::aligned_on_self,
236 announce_element (Score_element_info (text_p_, text_req_l_));
239 if (span_req_l_drul_[STOP])
243 span_req_l_drul_[STOP]->warning
244 (_ ("can't find start of (de)crescendo"));
248 assert (!finished_cresc_p_);
249 cresc_p_->set_bound(RIGHT, get_staff_info ().musical_pcol_l ());
250 finished_cresc_p_ = cresc_p_;
252 span_start_req_l_ = 0;
256 if (span_req_l_drul_[START])
258 if (span_start_req_l_)
260 span_req_l_drul_[START]->warning
261 (span_start_req_l_->span_dir_ == 1
263 _ ("already have a crescendo")
264 : _ ("already have a decrescendo"));
268 span_start_req_l_ = span_req_l_drul_[START];
269 cresc_p_ = new Crescendo;
270 cresc_p_->set_elt_property
272 gh_int2scm ((span_req_l_drul_[START]->span_type_str_ == "crescendo")
273 ? BIGGER : SMALLER));
275 SCM s = get_property (span_req_l_drul_[START]->span_type_str_ + "Text");
278 cresc_p_->set_elt_property ("start-text", s);
279 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
280 + "Text", SCM_UNDEFINED);
283 s = get_property (span_req_l_drul_[START]->span_type_str_ + "Spanner");
284 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
286 cresc_p_->set_elt_property ("spanner", s);
287 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
288 + "Spanner", SCM_UNDEFINED);
291 cresc_p_->set_bound(LEFT, get_staff_info ().musical_pcol_l ());
295 We know how wide the text is, if we can be sure that the
296 text already has relevant pointers into the paperdef,
297 and it has its font-size property set.
299 Since font-size may be set by a context higher up, we
300 can not be sure of the size.
303 We shouldn't try to do this stuff here, the Item should
304 do it when the score is finished. We could maybe
305 set a callback to have the Item do the alignment if
306 it is not a special symbol, like Crescendo.
312 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
314 if (finished_cresc_p_)
315 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
318 pending_element_arr_.push (cresc_p_);
319 cresc_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
320 cresc_p_->add_offset_callback
321 (Side_position_interface::aligned_on_self, Y_AXIS);
322 announce_element (Score_element_info (cresc_p_, span_req_l_drul_[START]));
328 Dynamic_engraver::do_pre_move_processing ()
334 Dynamic_engraver::do_removal_processing ()
338 typeset_element (cresc_p_ );
339 span_start_req_l_->warning (_ ("unterminated (de)crescendo"));
345 side_position (line_spanner_).add_staff_support ();
346 typeset_element (line_spanner_);
352 Dynamic_engraver::typeset_all ()
354 if (finished_cresc_p_)
356 typeset_element (finished_cresc_p_);
357 finished_cresc_p_ =0;
362 typeset_element (text_p_);
367 TODO: This should be optionised:
368 * break when group of dynamic requests ends
370 * continue through piece */
371 if (line_spanner_ && last_request_mom_ < now_mom ())
373 side_position (line_spanner_).add_staff_support ();
374 typeset_element (line_spanner_);
380 Dynamic_engraver::acknowledge_element (Score_element_info i)
382 if (Note_column* n = dynamic_cast<Note_column*> (i.elem_l_))
386 side_position (line_spanner_).add_support (n);
387 line_spanner_->add_column (n);