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 (Score_element_info
128 text_req_l_
? text_req_l_
: accepted_spanreqs_drul_
[START
]));
134 TODO: should finish and create new spanner if vertical dyn-direction is changed.
136 else if (!accepted_spanreqs_drul_
[START
] && !text_req_l_
)
138 finished_line_spanner_
= line_spanner_
;
143 todo: resurrect dynamic{direction, padding,minimumspace}
146 During a (de)crescendo, pending request will not be cleared,
147 and a line-spanner will always be created, as \< \! are already
150 Maybe always creating a line-spanner for a (de)crescendo (see
151 below) is not a good idea:
155 the \p will be centred on the line-spanner, and thus clash
156 with the hairpin. When axis-group code is in place, the \p
157 should move below the hairpin, which is probably better?
159 Urg, but line-spanner must always have at least same duration
160 as (de)crecsendo, b.o. line-breaking.
166 String loud
= text_req_l_
->text_str_
;
168 text_p_
= new Item (get_property ("basicDynamicTextProperties"));
169 text_p_
->set_elt_property ("text", ly_str02scm (loud
.ch_C ()));
170 if (Direction d
=text_req_l_
->get_direction ())
171 Directional_element_interface (line_spanner_
).set (d
);
173 Axis_group_interface::add_element (line_spanner_
, text_p_
);
175 text_p_
->add_offset_callback (Side_position::aligned_on_self
,
177 announce_element (Score_element_info (text_p_
, text_req_l_
));
180 if (accepted_spanreqs_drul_
[STOP
])
184 accepted_spanreqs_drul_
[STOP
]->warning
185 (_ ("can't find start of (de)crescendo"));
189 assert (!finished_cresc_p_
);
190 cresc_p_
->set_bound (RIGHT
, unsmob_element (get_property ("currentMusicalColumn")));
191 finished_cresc_p_
= cresc_p_
;
193 current_cresc_req_
= 0;
197 if (accepted_spanreqs_drul_
[START
])
199 if (current_cresc_req_
)
201 accepted_spanreqs_drul_
[START
]->warning
202 (current_cresc_req_
->span_dir_
== 1
204 _ ("already have a crescendo")
205 : _ ("already have a decrescendo"));
209 current_cresc_req_
= accepted_spanreqs_drul_
[START
];
210 cresc_p_
= new Spanner (get_property ("basicCrescendoProperties"));
211 Crescendo::set_interface (cresc_p_
);
212 cresc_p_
->set_elt_property
214 gh_int2scm ((accepted_spanreqs_drul_
[START
]->span_type_str_
== "crescendo")
215 ? BIGGER
: SMALLER
));
217 SCM s
= get_property ((accepted_spanreqs_drul_
[START
]->span_type_str_
+ "Text").ch_C());
220 cresc_p_
->set_elt_property ("start-text", s
);
221 daddy_trans_l_
->set_property (accepted_spanreqs_drul_
[START
]->span_type_str_
222 + "Text", SCM_UNDEFINED
);
225 s
= get_property ((accepted_spanreqs_drul_
[START
]->span_type_str_
+ "Spanner").ch_C());
231 if (gh_string_p (s
)) //&& ly_scm2string (s) != "hairpin")
233 cresc_p_
->set_elt_property ("spanner", s
);
234 daddy_trans_l_
->set_property (accepted_spanreqs_drul_
[START
]->span_type_str_
235 + "Spanner", SCM_UNDEFINED
);
238 cresc_p_
->set_bound (LEFT
, unsmob_element (get_property ("currentMusicalColumn")));
242 We know how wide the text is, if we can be sure that the
243 text already has relevant pointers into the paperdef,
244 and it has its font-size property set.
246 Since font-size may be set by a context higher up, we
247 can not be sure of the size.
250 We shouldn't try to do this stuff here, the Item should
251 do it when the score is finished. We could maybe
252 set a callback to have the Item do the alignment if
253 it is not a special symbol, like Crescendo.
259 index_set_cell (cresc_p_
->get_elt_property ("dynamic-drul"),
260 LEFT
, text_p_
->self_scm_
);
261 if (finished_cresc_p_
)
262 index_set_cell (finished_cresc_p_
->get_elt_property ("dynamic-drul"),
263 RIGHT
, text_p_
->self_scm_
);
266 Axis_group_interface::add_element (line_spanner_
, cresc_p_
);
267 cresc_p_
->set_elt_property ("self-alignment-Y", gh_int2scm (0));
268 cresc_p_
->add_offset_callback
269 (Side_position::aligned_on_self
, Y_AXIS
);
270 announce_element (Score_element_info (cresc_p_
, accepted_spanreqs_drul_
[START
]));
276 Dynamic_engraver::do_pre_move_processing ()
282 Dynamic_engraver::do_removal_processing ()
288 typeset_element (cresc_p_
);
289 finished_cresc_p_
= cresc_p_
;
290 current_cresc_req_
->warning (_ ("unterminated (de)crescendo"));
294 finished_line_spanner_
= line_spanner_
;
300 Dynamic_engraver::typeset_all ()
302 if (finished_cresc_p_
)
304 typeset_element (finished_cresc_p_
);
305 finished_cresc_p_
=0;
310 typeset_element (text_p_
);
313 if (finished_line_spanner_
)
315 Side_position::add_staff_support (finished_line_spanner_
);
317 if (!finished_line_spanner_
->get_bound (LEFT
))
320 = unsmob_element (get_property ("currentMusicalColumn"));
321 finished_line_spanner_
->set_bound (LEFT
, cmc
);
323 if (!finished_line_spanner_
->get_bound (RIGHT
))
324 finished_line_spanner_
->set_bound (RIGHT
,
325 finished_line_spanner_
->get_bound (LEFT
));
328 typeset_element (finished_line_spanner_
);
329 finished_line_spanner_
= 0;
334 Dynamic_engraver::acknowledge_element (Score_element_info i
)
336 if (Note_column::has_interface (i
.elem_l_
))
340 Side_position::add_support (line_spanner_
,i
.elem_l_
);
341 add_bound_item (line_spanner_
,dynamic_cast<Item
*>(i
.elem_l_
));