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 (line_spanner_).set (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
203 _ ("already have a crescendo")
204 : _ ("already have a decrescendo"));
208 current_cresc_req_ = accepted_spanreqs_drul_[START];
209 cresc_p_ = new Spanner (get_property ("basicCrescendoProperties"));
210 Crescendo::set_interface (cresc_p_);
211 cresc_p_->set_elt_property
213 gh_int2scm ((accepted_spanreqs_drul_[START]->span_type_str_ == "crescendo")
214 ? BIGGER : SMALLER));
216 SCM s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Text").ch_C());
219 cresc_p_->set_elt_property ("start-text", s);
220 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
221 + "Text", SCM_UNDEFINED);
224 s = get_property ((accepted_spanreqs_drul_[START]->span_type_str_ + "Spanner").ch_C());
230 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
232 cresc_p_->set_elt_property ("spanner", s);
233 daddy_trans_l_->set_property (accepted_spanreqs_drul_[START]->span_type_str_
234 + "Spanner", SCM_UNDEFINED);
237 cresc_p_->set_bound (LEFT, unsmob_element (get_property ("currentMusicalColumn")));
241 We know how wide the text is, if we can be sure that the
242 text already has relevant pointers into the paperdef,
243 and it has its font-size property set.
245 Since font-size may be set by a context higher up, we
246 can not be sure of the size.
249 We shouldn't try to do this stuff here, the Item should
250 do it when the score is finished. We could maybe
251 set a callback to have the Item do the alignment if
252 it is not a special symbol, like Crescendo.
258 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
259 LEFT, text_p_->self_scm_);
260 if (finished_cresc_p_)
261 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
262 RIGHT, text_p_->self_scm_);
265 Axis_group_interface::add_element (line_spanner_, cresc_p_);
266 cresc_p_->set_elt_property ("self-alignment-Y", gh_int2scm (0));
267 cresc_p_->add_offset_callback
268 (Side_position::aligned_on_self, Y_AXIS);
269 announce_element (cresc_p_, accepted_spanreqs_drul_[START]);
275 Dynamic_engraver::do_pre_move_processing ()
281 Dynamic_engraver::do_removal_processing ()
287 typeset_element (cresc_p_ );
288 finished_cresc_p_ = cresc_p_;
289 current_cresc_req_->origin ()->warning (_ ("unterminated (de)crescendo"));
293 finished_line_spanner_ = line_spanner_;
299 Dynamic_engraver::typeset_all ()
301 if (finished_cresc_p_)
303 typeset_element (finished_cresc_p_);
304 finished_cresc_p_ =0;
309 typeset_element (text_p_);
312 if (finished_line_spanner_)
314 Side_position::add_staff_support (finished_line_spanner_);
316 if (!finished_line_spanner_->get_bound (LEFT))
319 = unsmob_element (get_property ("currentMusicalColumn"));
320 finished_line_spanner_->set_bound (LEFT, cmc);
322 if (!finished_line_spanner_->get_bound (RIGHT))
323 finished_line_spanner_->set_bound (RIGHT,
324 finished_line_spanner_->get_bound (LEFT));
327 typeset_element (finished_line_spanner_);
328 finished_line_spanner_ = 0;
333 Dynamic_engraver::acknowledge_element (Score_element_info i)
335 if (Note_column::has_interface (i.elem_l_))
339 Side_position::add_support (line_spanner_,i.elem_l_);
340 add_bound_item (line_spanner_,dynamic_cast<Item*>(i.elem_l_));