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"
13 #include "paper-def.hh"
14 #include "paper-column.hh"
15 #include "staff-symbol.hh"
16 #include "note-column.hh"
17 #include "text-item.hh"
18 #include "side-position-interface.hh"
19 #include "engraver.hh"
21 #include "note-head.hh"
22 #include "group-interface.hh"
23 #include "directional-element-interface.hh"
24 #include "staff-symbol-referencer.hh"
25 #include "translator-group.hh"
28 Wat mij betreft wel DYN_LINE
34 class Dynamic_line_spanner : public Spanner
37 Dynamic_line_spanner ();
39 void add_column (Note_column*);
40 Direction get_default_dir () const;
42 virtual void do_post_processing ();
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 (Note_column* n)
54 if (!spanned_drul_[LEFT])
56 set_bounds (RIGHT, n);
62 Dynamic_line_spanner::get_default_dir () const
68 Dynamic_line_spanner::do_post_processing ()
70 Spanner::do_post_processing ();
71 Direction dir = directional_element (this).get ();
73 dir = get_default_dir ();
76 Hier is ook vast iets voor?
78 Staff_symbol_referencer_interface si (this);
79 Real above_staff = si.line_count () + 2;
82 // Aargh, nu snap ik waarom ik het niet snap
83 // zie Staff_symbol_referencer_interface::set_position
85 if (si.position_f () * dir < above_staff)
86 si.set_position (above_staff * (int)dir);
88 SCM s = get_elt_property ("padding");
91 si.set_position (si.position_f () + gh_scm2double (s) * (int) dir);
95 Real pos = si.position_f () * dir;
96 if (pos * dir < above_staff)
99 SCM s = get_elt_property ("padding");
101 dy += gh_scm2double (s);
103 Real half_space = si.staff_space () / 2;
104 translate_axis (dy*half_space*dir, Y_AXIS);
112 Baseline alignment / character metrics of dynamic symbols.
116 print text & hairpin dynamics.
118 class Dynamic_engraver : public Engraver
121 Crescendo * finished_cresc_p_;
122 Crescendo * cresc_p_;
124 Text_script_req* text_req_l_;
125 Span_req * span_start_req_l_;
126 Drul_array<Span_req*> span_req_l_drul_;
129 Dynamic_line_spanner* line_spanner_;
131 Spanner* line_spanner_;
133 Moment last_request_mom_;
138 VIRTUAL_COPY_CONS(Translator);
142 void announce_element (Score_element_info);
144 virtual void do_removal_processing ();
145 virtual void acknowledge_element (Score_element_info);
146 virtual bool do_try_music (Music *req_l);
147 virtual void do_process_requests ();
148 virtual void do_pre_move_processing ();
149 virtual void do_post_move_processing ();
152 ADD_THIS_TRANSLATOR (Dynamic_engraver);
155 Dynamic_engraver::announce_element (Score_element_info i)
157 group (i.elem_l_, "interfaces").add_thing (ly_symbol2scm ("dynamic"));
159 Engraver::announce_element (i);
163 Dynamic_engraver::Dynamic_engraver ()
166 finished_cresc_p_ = 0;
168 span_start_req_l_ = 0;
172 span_req_l_drul_[START] = 0;
173 span_req_l_drul_[STOP] = 0;
177 Dynamic_engraver::do_post_move_processing ()
180 span_req_l_drul_[START] = 0;
181 span_req_l_drul_[STOP] = 0;
185 Dynamic_engraver::do_try_music (Music * m)
187 if (Text_script_req* d = dynamic_cast <Text_script_req*> (m))
189 if (d->style_str_ == "dynamic")
195 else if (Span_req* s = dynamic_cast <Span_req*> (m))
197 if ((s->span_type_str_ == "crescendo"
198 || s->span_type_str_ == "decrescendo"))
200 span_req_l_drul_[s->span_dir_] = s;
208 Dynamic_engraver::do_process_requests ()
210 if ((span_req_l_drul_[START] || text_req_l_) && !line_spanner_)
213 line_spanner_ = new Dynamic_line_spanner;
215 line_spanner_ = new Spanner;
216 line_spanner_->set_elt_property ("transparent", SCM_BOOL_T);
217 side_position (line_spanner_).set_axis (Y_AXIS);
219 announce_element (Score_element_info
221 text_req_l_ ? text_req_l_ : span_req_l_drul_[START]));
225 if (span_req_l_drul_[START] || text_req_l_)
226 last_request_mom_ = now_mom ();
232 Generic property will handle this for a Dynamic_line_spanner
234 Direction dir = DOWN;
235 SCM s = get_property ("dynamicDirection");
238 s = get_property ("verticalDirection");
241 if (isdir_b (s) && to_dir (s))
244 line_spanner_->set_elt_property ("direction", gh_int2scm ((int)dir));
246 s = get_property ("dynamicPadding");
249 padding = gh_scm2double (s);
252 line_spanner_->set_elt_property ("padding", gh_double2scm (padding));
258 String loud = text_req_l_->text_str_;
260 text_p_ = new Text_item;
261 text_p_->set_elt_property ("text",
262 ly_str02scm (loud.ch_C ()));
263 text_p_->set_elt_property ("style", gh_str02scm ("dynamic"));
264 text_p_->set_elt_property ("script-priority",
267 assert (line_spanner_);
268 text_p_->set_parent (line_spanner_, Y_AXIS);
269 announce_element (Score_element_info (text_p_, text_req_l_));
272 if (span_req_l_drul_[STOP])
276 span_req_l_drul_[STOP]->warning
277 (_ ("can't find start of (de)crescendo"));
281 assert (!finished_cresc_p_);
282 cresc_p_->set_bounds(RIGHT, get_staff_info ().musical_pcol_l ());
283 finished_cresc_p_ = cresc_p_;
285 span_start_req_l_ = 0;
289 if (span_req_l_drul_[START])
291 if (span_start_req_l_)
293 span_req_l_drul_[START]->warning
294 (span_start_req_l_->span_dir_ == 1
296 _ ("already have a crescendo")
297 : _ ("already have a decrescendo"));
301 span_start_req_l_ = span_req_l_drul_[START];
302 cresc_p_ = new Crescendo;
303 cresc_p_->set_elt_property
305 gh_int2scm ((span_req_l_drul_[START]->span_type_str_ == "crescendo")
306 ? BIGGER : SMALLER));
308 SCM s = get_property (span_req_l_drul_[START]->span_type_str_ + "Text");
311 cresc_p_->set_elt_property ("start-text", s);
312 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
313 + "Text", SCM_UNDEFINED);
316 s = get_property (span_req_l_drul_[START]->span_type_str_ + "Spanner");
317 if (gh_string_p (s)) //&& ly_scm2string (s) != "hairpin")
319 cresc_p_->set_elt_property ("spanner", s);
320 daddy_trans_l_->set_property (span_req_l_drul_[START]->span_type_str_
321 + "Spanner", SCM_UNDEFINED);
324 cresc_p_->set_bounds(LEFT, get_staff_info ().musical_pcol_l ());
325 cresc_p_->set_bounds(RIGHT, get_staff_info ().musical_pcol_l ());
327 // arrragh, brr, urg: we know how wide text is, no?
330 index_set_cell (cresc_p_->get_elt_property ("dynamic-drul"),
332 if (finished_cresc_p_)
333 index_set_cell (finished_cresc_p_->get_elt_property ("dynamic-drul"),
337 assert (line_spanner_);
338 cresc_p_->set_parent (line_spanner_, Y_AXIS);
339 announce_element (Score_element_info (cresc_p_, span_req_l_drul_[START]));
345 Dynamic_engraver::do_pre_move_processing ()
351 Dynamic_engraver::do_removal_processing ()
355 typeset_element (cresc_p_ );
356 span_start_req_l_->warning (_ ("unterminated (de)crescendo"));
363 Direction dir = directional_element (line_spanner_).get ();
364 Real staff_space = Staff_symbol_referencer_interface (line_spanner_).staff_space ();
365 SCM s = line_spanner_->get_elt_property ("padding");
366 line_spanner_->translate_axis (gh_scm2double (s) * staff_space * (int)dir, Y_AXIS);
368 typeset_element (line_spanner_);
375 Dynamic_engraver::typeset_all ()
377 if (finished_cresc_p_)
379 finished_cresc_p_->set_bounds (RIGHT, get_staff_info ().musical_pcol_l ());
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
396 if (line_spanner_ && last_request_mom_ < now_mom ())
399 Direction dir = directional_element (line_spanner_).get ();
400 Real staff_space = Staff_symbol_referencer_interface (line_spanner_).staff_space ();
401 SCM s = line_spanner_->get_elt_property ("padding");
402 line_spanner_->translate_axis (gh_scm2double (s) * staff_space * (int)dir, Y_AXIS);
404 typeset_element (line_spanner_);
410 Dynamic_engraver::acknowledge_element (Score_element_info i)
414 if (Note_column* n = dynamic_cast<Note_column*> (i.elem_l_))
416 side_position (line_spanner_).add_support (n);
418 line_spanner_->add_column (n);
420 if (!line_spanner_->spanned_drul_[LEFT])
421 line_spanner_->set_bounds (LEFT, n);
422 line_spanner_->set_bounds (RIGHT, n);
424 line_spanner_->add_dependency (n);