2
2
slur-engraver.cc -- implement Slur_engraver
4
(c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
4
source file of the GNU LilyPond music typesetter
6
(c) 1997--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
12
#include "directional-element-interface.hh"
13
#include "international.hh"
14
#include "note-column.hh"
10
#include "note-column.hh"
13
#include "engraver.hh"
17
TODO: junk nested slur functionality.
21
It is possible that a slur starts and ends on the same note. At
22
least, it is for phrasing slurs: a note can be both beginning and
19
25
class Slur_engraver : public Engraver
21
Link_array<Music> events_;
22
Link_array<Music> new_slur_evs_;
23
Link_array<Grob> slur_stack_;
24
Link_array<Grob> end_slurs_;
27
Drul_array<Music *> events_;
28
Music *running_slur_start_;
30
vector<Grob*> end_slurs_;
27
32
void set_melisma (bool);
30
virtual bool try_music (Music*);
31
virtual void acknowledge_grob (Grob_info);
32
virtual void stop_translation_timestep ();
35
virtual bool try_music (Music *);
37
DECLARE_ACKNOWLEDGER (accidental);
38
DECLARE_ACKNOWLEDGER (dynamic_line_spanner);
39
DECLARE_ACKNOWLEDGER (fingering);
40
DECLARE_ACKNOWLEDGER (note_column);
41
DECLARE_ACKNOWLEDGER (script);
42
DECLARE_ACKNOWLEDGER (text_script);
43
DECLARE_ACKNOWLEDGER (tie);
44
DECLARE_ACKNOWLEDGER (tuplet_number);
45
void acknowledge_extra_object (Grob_info);
46
void stop_translation_timestep ();
33
47
virtual void finalize ();
34
virtual void process_music ();
48
void process_music ();
37
51
TRANSLATOR_DECLARATIONS (Slur_engraver);
89
80
Slur_engraver::set_melisma (bool m)
91
daddy_context_->set_property ("slurMelismaBusy", m ? SCM_BOOL_T :SCM_BOOL_F);
95
Slur_engraver::acknowledge_grob (Grob_info info)
97
if (Note_column::has_interface (info.grob_))
100
for (int i = 0; i < slur_stack_.size (); i++)
101
Slur::add_column (slur_stack_[i], e);
102
for (int i = 0; i < end_slurs_.size (); i++)
103
Slur::add_column (end_slurs_[i], e);
82
context ()->set_property ("slurMelismaBusy", m ? SCM_BOOL_T : SCM_BOOL_F);
86
Slur_engraver::acknowledge_note_column (Grob_info info)
88
Grob *e = info.grob ();
89
for (vsize i = slurs_.size (); i--;)
90
Slur::add_column (slurs_[i], e);
91
for (vsize i = end_slurs_.size (); i--;)
92
Slur::add_column (end_slurs_[i], e);
96
Slur_engraver::acknowledge_extra_object (Grob_info info)
98
if (slurs_.empty () && end_slurs_.empty ())
101
Grob *e = info.grob ();
102
SCM avoid = e->get_property ("avoid-slur");
103
if (Tie::has_interface (e)
104
|| avoid == ly_symbol2scm ("inside"))
106
for (vsize i = slurs_.size (); i--;)
107
Slur::add_extra_encompass (slurs_[i], e);
108
for (vsize i = end_slurs_.size (); i--;)
109
Slur::add_extra_encompass (end_slurs_[i], e);
111
else if (avoid == ly_symbol2scm ("outside")
112
|| avoid == ly_symbol2scm ("around"))
114
Grob *slur = slurs_.size () ? slurs_[0] : 0;
115
slur = (end_slurs_.size () && !slur)
116
? end_slurs_[0] : slur;
120
chain_offset_callback (e, Slur::outside_slur_callback_proc, Y_AXIS);
121
e->set_object ("slur", slur->self_scm ());
125
e->warning ("Ignoring grob for slur. avoid-slur not set?");
129
Slur_engraver::acknowledge_accidental (Grob_info info)
131
acknowledge_extra_object (info);
135
Slur_engraver::acknowledge_dynamic_line_spanner (Grob_info info)
137
acknowledge_extra_object (info);
141
Slur_engraver::acknowledge_fingering (Grob_info info)
143
acknowledge_extra_object (info);
147
Slur_engraver::acknowledge_tuplet_number (Grob_info info)
149
acknowledge_extra_object (info);
154
Slur_engraver::acknowledge_script (Grob_info info)
156
if (!info.grob ()->internal_has_interface (ly_symbol2scm ("dynamic-interface")))
157
acknowledge_extra_object (info);
161
Slur_engraver::acknowledge_text_script (Grob_info info)
163
acknowledge_extra_object (info);
167
Slur_engraver::acknowledge_tie (Grob_info info)
169
acknowledge_extra_object (info);
108
173
Slur_engraver::finalize ()
110
for (int i = 0; i < slur_stack_.size (); i++)
113
Let's not typeset unterminated stuff
115
slur_stack_[i]->suicide ();
117
slur_stack_.clear ();
119
for (int i=0; i < events_.size (); i++)
121
events_[i]->origin ()->warning (_ ("unterminated slur"));
176
slurs_[0]->warning (_ ("unterminated slur"));
126
180
Slur_engraver::process_music ()
128
Link_array<Grob> start_slurs;
129
for (int i=0; i< new_slur_evs_.size (); i++)
131
Music* slur_ev = new_slur_evs_[i];
132
// end slur: move the slur to other array
133
Direction d = to_dir (slur_ev->get_property ("span-direction"));
136
if (slur_stack_.is_empty ())
137
/* How to shut up this warning, when Voice_devnull_engraver has
138
eaten start event? */
139
slur_ev->origin ()->warning (_f ("can't find start of slur"));
142
Grob* slur = slur_stack_.pop ();
144
end_slurs_.push (slur);
150
// push a new slur onto stack.
151
// (use temp. array to wait for all slur STOPs)
152
Grob* slur = make_spanner ("Slur");
153
Slur::set_interface (slur); // cannot remove yet!
156
if (Direction updown = to_dir (slur_ev->get_property ("direction")))
158
slur->set_property ("direction", gh_int2scm (updown));
161
start_slurs.push (slur);
162
events_.push (slur_ev);
163
announce_grob (slur, slur_ev->self_scm ());
167
slur_stack_.concat (start_slurs);
169
set_melisma (slur_stack_.size ());
171
new_slur_evs_.clear ();
184
if (slurs_.size () == 0)
185
events_[STOP]->origin ()->warning (_ ("can't end slur"));
191
if (events_[START] && slurs_.empty ())
193
Music *ev = events_[START];
195
bool double_slurs = to_boolean (get_property ("doubleSlurs"));
197
Grob *slur = make_spanner ("Slur", events_[START]->self_scm ());
198
Direction updown = to_dir (ev->get_property ("direction"));
199
if (updown && !double_slurs)
200
set_grob_direction (slur, updown);
202
slurs_.push_back (slur);
206
set_grob_direction (slur, DOWN);
207
slur = make_spanner ("Slur", events_[START]->self_scm ());
208
set_grob_direction (slur, UP);
209
slurs_.push_back (slur);
212
set_melisma (slurs_.size ());
175
216
Slur_engraver::stop_translation_timestep ()
177
for (int i = 0; i < end_slurs_.size (); i++)
179
typeset_grob (end_slurs_[i]);
181
218
end_slurs_.clear ();
182
new_slur_evs_.clear ();
219
events_[START] = events_[STOP] = 0;
187
ENTER_DESCRIPTION (Slur_engraver,
188
/* descr */ "Build slurs from Slur_evs",
190
/* accepts */ "slur-event",
191
/* acks */ "note-column-interface",
192
/* reads */ "slurMelismaBusy",
222
#include "translator.icc"
224
ADD_ACKNOWLEDGER (Slur_engraver, accidental);
225
ADD_ACKNOWLEDGER (Slur_engraver, dynamic_line_spanner);
226
ADD_ACKNOWLEDGER (Slur_engraver, fingering);
227
ADD_ACKNOWLEDGER (Slur_engraver, note_column);
228
ADD_ACKNOWLEDGER (Slur_engraver, script);
229
ADD_ACKNOWLEDGER (Slur_engraver, text_script);
230
ADD_ACKNOWLEDGER (Slur_engraver, tie);
231
ADD_ACKNOWLEDGER (Slur_engraver, tuplet_number);
232
ADD_TRANSLATOR (Slur_engraver,
233
/* doc */ "Build slur grobs from slur events",
235
/* accept */ "slur-event",
236
/* read */ "slurMelismaBusy doubleSlurs",