Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1292)

Side by Side Diff: lily/slur-engraver.cc

Issue 6498077: Approximates cross-staff slurs in VerticalAxisGroup vertical-skylines. Base URL: http://git.savannah.gnu.org/gitweb/?p=lilypond.git/trunk/
Patch Set: Copies properties from surrogate Created 12 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 This file is part of LilyPond, the GNU music typesetter. 2 This file is part of LilyPond, the GNU music typesetter.
3 3
4 Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl> 4 Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
5 5
6 LilyPond is free software: you can redistribute it and/or modify 6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or 8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version. 9 (at your option) any later version.
10 10
(...skipping 12 matching lines...) Expand all
23 #include "directional-element-interface.hh" 23 #include "directional-element-interface.hh"
24 #include "international.hh" 24 #include "international.hh"
25 #include "note-column.hh" 25 #include "note-column.hh"
26 #include "slur.hh" 26 #include "slur.hh"
27 #include "spanner.hh" 27 #include "spanner.hh"
28 #include "stream-event.hh" 28 #include "stream-event.hh"
29 #include "warn.hh" 29 #include "warn.hh"
30 30
31 #include "translator.icc" 31 #include "translator.icc"
32 32
33 #include <algorithm>
34
33 /* 35 /*
34 NOTE NOTE NOTE 36 NOTE NOTE NOTE
35 37
36 This is largely similar to Phrasing_slur_engraver. Check if fixes 38 This is largely similar to Phrasing_slur_engraver. Check if fixes
37 apply there too. 39 apply there too.
38 40
39 (on principle, engravers don't use inheritance for code sharing) 41 (on principle, engravers don't use inheritance for code sharing)
40 42
41 */ 43 */
42 44
43 /* 45 /*
44 It is possible that a slur starts and ends on the same note. At 46 It is possible that a slur starts and ends on the same note. At
45 least, it is for phrasing slurs: a note can be both beginning and 47 least, it is for phrasing slurs: a note can be both beginning and
46 ending of a phrase. 48 ending of a phrase.
47 */ 49 */
50
51 Slur_info::Slur_info (Grob *slur)
52 {
53 slur_ = slur;
54 }
55
48 class Slur_engraver : public Engraver 56 class Slur_engraver : public Engraver
49 { 57 {
50 vector<Stream_event *> start_events_; 58 vector<Stream_event *> start_events_;
51 vector<Stream_event *> stop_events_; 59 vector<Stream_event *> stop_events_;
52 vector<Grob *> slurs_; 60 vector<Slur_info> slur_infos_;
53 vector<Grob *> end_slurs_; 61 vector<Slur_info> end_slur_infos_;
54 vector<Grob_info> objects_to_acknowledge_; 62 vector<Grob_info> objects_to_acknowledge_;
55 63
56 void set_melisma (bool); 64 void set_melisma (bool);
57 65
58 protected: 66 protected:
59 DECLARE_TRANSLATOR_LISTENER (slur); 67 DECLARE_TRANSLATOR_LISTENER (slur);
60 DECLARE_ACKNOWLEDGER (inline_accidental); 68 DECLARE_ACKNOWLEDGER (inline_accidental);
61 DECLARE_ACKNOWLEDGER (fingering); 69 DECLARE_ACKNOWLEDGER (fingering);
62 DECLARE_ACKNOWLEDGER (note_column); 70 DECLARE_ACKNOWLEDGER (note_column);
63 DECLARE_ACKNOWLEDGER (script); 71 DECLARE_ACKNOWLEDGER (script);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 113
106 void 114 void
107 Slur_engraver::set_melisma (bool m) 115 Slur_engraver::set_melisma (bool m)
108 { 116 {
109 context ()->set_property ("slurMelismaBusy", m ? SCM_BOOL_T : SCM_BOOL_F); 117 context ()->set_property ("slurMelismaBusy", m ? SCM_BOOL_T : SCM_BOOL_F);
110 } 118 }
111 119
112 void 120 void
113 Slur_engraver::acknowledge_note_column (Grob_info info) 121 Slur_engraver::acknowledge_note_column (Grob_info info)
114 { 122 {
123 /*
124 * For every active slur, we create a slur stub.
dak 2012/12/13 12:08:37 Meaning notecolumns x slurs stubs.
125 * As we do not yet know what vertical axis groups note columns belong to,
126 * we create a stub for each note and then suicide duplicate stubs on
127 * axis groups.
128 * These slurs should be used ONLY to approximate cross-staff slurs
129 * in vertical skylines.
130 */
131 ··
115 Grob *e = info.grob (); 132 Grob *e = info.grob ();
116 for (vsize i = slurs_.size (); i--;) 133 for (vsize i = slur_infos_.size (); i--;)
117 Slur::add_column (slurs_[i], e); 134 {
118 for (vsize i = end_slurs_.size (); i--;) 135 Slur::add_column (slur_infos_[i].slur_, e);
119 Slur::add_column (end_slurs_[i], e); 136 Grob *stub = make_spanner ("SlurStub", info.grob ()->self_scm ());
137 slur_infos_[i].stubs_.push_back (stub);
138 }
139 for (vsize i = end_slur_infos_.size (); i--;)
140 {
141 Slur::add_column (end_slur_infos_[i].slur_, e);
142 Grob *stub = make_spanner ("SlurStub", info.grob ()->self_scm ());
143 end_slur_infos_[i].stubs_.push_back (stub);
144 }
120 } 145 }
121 146
122 void 147 void
123 Slur_engraver::acknowledge_extra_object (Grob_info info) 148 Slur_engraver::acknowledge_extra_object (Grob_info info)
124 { 149 {
125 objects_to_acknowledge_.push_back (info); 150 objects_to_acknowledge_.push_back (info);
126 } 151 }
127 152
128 void 153 void
129 Slur_engraver::acknowledge_inline_accidental (Grob_info info) 154 Slur_engraver::acknowledge_inline_accidental (Grob_info info)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 189
165 void 190 void
166 Slur_engraver::acknowledge_end_tie (Grob_info info) 191 Slur_engraver::acknowledge_end_tie (Grob_info info)
167 { 192 {
168 acknowledge_extra_object (info); 193 acknowledge_extra_object (info);
169 } 194 }
170 195
171 void 196 void
172 Slur_engraver::finalize () 197 Slur_engraver::finalize ()
173 { 198 {
174 for (vsize i = 0; i < slurs_.size (); i++) 199 for (vsize i = 0; i < slur_infos_.size (); i++)
175 { 200 {
176 slurs_[i]->warning (_ ("unterminated slur")); 201 slur_infos_[i].slur_->warning (_ ("unterminated slur"));
177 slurs_[i]->suicide (); 202 slur_infos_[i].slur_->suicide ();
203 for (vsize j = 0; j < slur_infos_[i].stubs_.size (); j++)
204 slur_infos_[i].stubs_[j]->suicide ();
178 } 205 }
179 slurs_.clear (); 206
207 slur_infos_.clear ();
180 } 208 }
181 209
182 void 210 void
183 Slur_engraver::process_music () 211 Slur_engraver::process_music ()
184 { 212 {
185 for (vsize i = 0; i < stop_events_.size (); i++) 213 for (vsize i = 0; i < stop_events_.size (); i++)
186 { 214 {
187 Stream_event *ev = stop_events_[i]; 215 Stream_event *ev = stop_events_[i];
188 string id = robust_scm2string (ev->get_property ("spanner-id"), ""); 216 string id = robust_scm2string (ev->get_property ("spanner-id"), "");
189 217
190 // Find the slurs that are ended with this event (by checking the spanner- id) 218 // Find the slurs that are ended with this event (by checking the spanner- id)
191 bool ended = false; 219 bool ended = false;
192 for (vsize j = slurs_.size (); j--;) 220 for (vsize j = slur_infos_.size (); j--;)
193 { 221 {
194 if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), " ")) 222 if (id == robust_scm2string (slur_infos_[j].slur_->get_property ("span ner-id"), ""))
195 { 223 {
196 ended = true; 224 ended = true;
197 end_slurs_.push_back (slurs_[j]); 225 end_slur_infos_.push_back (slur_infos_[j]);
198 slurs_.erase (slurs_.begin () + j); 226 slur_infos_.erase (slur_infos_.begin () + j);
199 } 227 }
200 } 228 }
201 if (ended) 229 if (ended)
202 { 230 {
203 // Ignore redundant stop events for this id 231 // Ignore redundant stop events for this id
204 for (vsize j = stop_events_.size (); --j > i;) 232 for (vsize j = stop_events_.size (); --j > i;)
205 { 233 {
206 if (id == robust_scm2string (stop_events_[j]->get_property ("spann er-id"), "")) 234 if (id == robust_scm2string (stop_events_[j]->get_property ("spann er-id"), ""))
207 stop_events_.erase (stop_events_.begin () + j); 235 stop_events_.erase (stop_events_.begin () + j);
208 } 236 }
209 } 237 }
210 else 238 else
211 ev->origin ()->warning (_ ("cannot end slur")); 239 ev->origin ()->warning (_ ("cannot end slur"));
212 } 240 }
213 241
214 vsize old_slurs = slurs_.size (); 242 vsize old_slurs = slur_infos_.size ();
215 for (vsize i = start_events_.size (); i--;) 243 for (vsize i = start_events_.size (); i--;)
216 { 244 {
217 Stream_event *ev = start_events_[i]; 245 Stream_event *ev = start_events_[i];
218 string id = robust_scm2string (ev->get_property ("spanner-id"), ""); 246 string id = robust_scm2string (ev->get_property ("spanner-id"), "");
219 Direction updown = to_dir (ev->get_property ("direction")); 247 Direction updown = to_dir (ev->get_property ("direction"));
220 248
221 bool completed; 249 bool completed;
222 for (vsize j = slurs_.size (); !(completed = (j-- == 0));) 250 for (vsize j = slur_infos_.size (); !(completed = (j-- == 0));)
223 { 251 {
224 // Check if we already have a slur with the same spanner-id. 252 // Check if we already have a slur with the same spanner-id.
225 if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), " ")) 253 if (id == robust_scm2string (slur_infos_[j].slur_->get_property ("span ner-id"), ""))
226 { 254 {
227 if (j < old_slurs) 255 if (j < old_slurs)
228 { 256 {
229 // We already have an old slur, so give a warning 257 // We already have an old slur, so give a warning
230 // and completely ignore the new slur. 258 // and completely ignore the new slur.
231 ev->origin ()->warning (_ ("already have slur")); 259 ev->origin ()->warning (_ ("already have slur"));
232 start_events_.erase (start_events_.begin () + i); 260 start_events_.erase (start_events_.begin () + i);
233 break; 261 break;
234 } 262 }
235 263
236 // If this slur event has no direction, it will not 264 // If this slur event has no direction, it will not
237 // contribute anything new to the existing slur(s), so 265 // contribute anything new to the existing slur(s), so
238 // we can ignore it. 266 // we can ignore it.
239 267
240 if (!updown) 268 if (!updown)
241 break; 269 break;
242 270
243 Stream_event *c = unsmob_stream_event (slurs_[j]->get_property ("c ause")); 271 Stream_event *c = unsmob_stream_event (slur_infos_[j].slur_->get_p roperty ("cause"));
244 272
245 if (!c) 273 if (!c)
246 { 274 {
247 slurs_[j]->programming_error ("slur without a cause"); 275 slur_infos_[j].slur_->programming_error ("slur without a cause ");
248 continue; 276 continue;
249 } 277 }
250 278
251 Direction slur_dir = to_dir (c->get_property ("direction")); 279 Direction slur_dir = to_dir (c->get_property ("direction"));
252 280
253 // If the existing slur does not have a direction yet, 281 // If the existing slur does not have a direction yet,
254 // we'd rather take the new one. 282 // we'd rather take the new one.
255 283
256 if (!slur_dir) 284 if (!slur_dir)
257 { 285 {
258 slurs_[j]->suicide (); 286 slur_infos_[j].slur_->suicide ();
259 slurs_.erase (slurs_.begin () + j); 287 for (vsize k = 0; k < slur_infos_[j].stubs_.size (); k++)
288 slur_infos_[j].stubs_[k]->suicide ();
289 slur_infos_.erase (slur_infos_.begin () + j);
260 continue; 290 continue;
261 } 291 }
262 292
263 // If the existing slur has the same direction as ours, drop ours 293 // If the existing slur has the same direction as ours, drop ours
264 294
265 if (slur_dir == updown) 295 if (slur_dir == updown)
266 break; 296 break;
267 } 297 }
268 } 298 }
269 // If the loop completed, our slur is new 299 // If the loop completed, our slur is new
270 if (completed) 300 if (completed)
271 { 301 {
272 Grob *slur = make_spanner ("Slur", ev->self_scm ()); 302 Grob *slur = make_spanner ("Slur", ev->self_scm ());
273 slur->set_property ("spanner-id", ly_string2scm (id)); 303 slur->set_property ("spanner-id", ly_string2scm (id));
274 if (updown) 304 if (updown)
275 set_grob_direction (slur, updown); 305 set_grob_direction (slur, updown);
276 slurs_.push_back (slur); 306 slur_infos_.push_back (Slur_info (slur));
277 307
278 if (to_boolean (get_property ("doubleSlurs"))) 308 if (to_boolean (get_property ("doubleSlurs")))
279 { 309 {
280 set_grob_direction (slur, DOWN); 310 set_grob_direction (slur, DOWN);
281 slur = make_spanner ("Slur", ev->self_scm ()); 311 slur = make_spanner ("Slur", ev->self_scm ());
282 slur->set_property ("spanner-id", ly_string2scm (id)); 312 slur->set_property ("spanner-id", ly_string2scm (id));
283 set_grob_direction (slur, UP); 313 set_grob_direction (slur, UP);
284 slurs_.push_back (slur); 314 slur_infos_.push_back (Slur_info (slur));
285 } 315 }
286 } 316 }
287 } 317 }
288 set_melisma (slurs_.size ()); 318 set_melisma (slur_infos_.size ());
289 } 319 }
290 320
291 void 321 void
292 Slur_engraver::stop_translation_timestep () 322 Slur_engraver::stop_translation_timestep ()
293 { 323 {
294 if (Grob *g = unsmob_grob (get_property ("currentCommandColumn"))) 324 if (Grob *g = unsmob_grob (get_property ("currentCommandColumn")))
295 { 325 {
296 for (vsize i = 0; i < end_slurs_.size (); i++) 326 for (vsize i = 0; i < end_slur_infos_.size (); i++)
297 Slur::add_extra_encompass (end_slurs_[i], g); 327 Slur::add_extra_encompass (end_slur_infos_[i].slur_, g);
298 328
299 if (!start_events_.size ()) 329 if (!start_events_.size ())
300 for (vsize i = 0; i < slurs_.size (); i++) 330 for (vsize i = 0; i < slur_infos_.size (); i++)
301 Slur::add_extra_encompass (slurs_[i], g); 331 Slur::add_extra_encompass (slur_infos_[i].slur_, g);
302 } 332 }
303 333
304 for (vsize i = 0; i < end_slurs_.size (); i++) 334 for (vsize i = 0; i < end_slur_infos_.size (); i++)
305 { 335 {
306 Spanner *s = dynamic_cast<Spanner *> (end_slurs_[i]); 336 Spanner *s = dynamic_cast<Spanner *> (end_slur_infos_[i].slur_);
307 if (!s->get_bound (RIGHT)) 337 if (!s->get_bound (RIGHT))
308 s->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn")) ); 338 s->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn")) );
309 announce_end_grob (s, SCM_EOL); 339 announce_end_grob (s, SCM_EOL);
310 } 340 }
311 341
312 for (vsize i = 0; i < objects_to_acknowledge_.size (); i++) 342 for (vsize i = 0; i < objects_to_acknowledge_.size (); i++)
313 Slur::auxiliary_acknowledge_extra_object (objects_to_acknowledge_[i], slurs_ , end_slurs_); 343 Slur::auxiliary_acknowledge_extra_object (objects_to_acknowledge_[i], slur_i nfos_, end_slur_infos_);
344
345 for (vsize i = 0; i < end_slur_infos_.size (); i++)
346 {
347 // There are likely SlurStubs we don't need. Get rid of them
348 // and only keep one per VerticalAxisGroup.
349 vector<Grob *> vags;
350 vector<Grob *> stubs;
351 for (vsize j = 0; j < end_slur_infos_[i].stubs_.size (); j++)
352 {
353 Grob *stub = end_slur_infos_[i].stubs_[j];
354 Grob *vag = Grob::get_vertical_axis_group (stub);
355 if (vag)
356 {
357 vector<Grob *>::const_iterator it =
358 find (vags.begin (), vags.end (), vag);
359 if (it != vags.end ())
360 stub->suicide ();
361 else
362 {
363 vags.push_back (vag);
364 stubs.push_back (stub);
365 }
366 }
367 else
368 {
369 end_slur_infos_[i].slur_->programming_error ("Cannot find vertical axis group for NoteColumn.");
370 stub->suicide ();
371 }
372 }
373 for (vsize j = 0; j < stubs.size (); j++)
374 Slur::main_to_stub (end_slur_infos_[i].slur_, stubs[j]);
375 }
314 376
315 objects_to_acknowledge_.clear (); 377 objects_to_acknowledge_.clear ();
316 end_slurs_.clear (); 378 end_slur_infos_.clear ();
317 start_events_.clear (); 379 start_events_.clear ();
318 stop_events_.clear (); 380 stop_events_.clear ();
319 } 381 }
320 382
321 ADD_ACKNOWLEDGER (Slur_engraver, inline_accidental); 383 ADD_ACKNOWLEDGER (Slur_engraver, inline_accidental);
322 ADD_ACKNOWLEDGER (Slur_engraver, fingering); 384 ADD_ACKNOWLEDGER (Slur_engraver, fingering);
323 ADD_ACKNOWLEDGER (Slur_engraver, note_column); 385 ADD_ACKNOWLEDGER (Slur_engraver, note_column);
324 ADD_ACKNOWLEDGER (Slur_engraver, script); 386 ADD_ACKNOWLEDGER (Slur_engraver, script);
325 ADD_ACKNOWLEDGER (Slur_engraver, text_script); 387 ADD_ACKNOWLEDGER (Slur_engraver, text_script);
326 ADD_ACKNOWLEDGER (Slur_engraver, dots); 388 ADD_ACKNOWLEDGER (Slur_engraver, dots);
327 ADD_END_ACKNOWLEDGER (Slur_engraver, tie); 389 ADD_END_ACKNOWLEDGER (Slur_engraver, tie);
328 ADD_ACKNOWLEDGER (Slur_engraver, tuplet_number); 390 ADD_ACKNOWLEDGER (Slur_engraver, tuplet_number);
329 ADD_TRANSLATOR (Slur_engraver, 391 ADD_TRANSLATOR (Slur_engraver,
330 /* doc */ 392 /* doc */
331 "Build slur grobs from slur events.", 393 "Build slur grobs from slur events.",
332 394
333 /* create */ 395 /* create */
334 "Slur ", 396 "Slur ",
335 397
336 /* read */ 398 /* read */
337 "slurMelismaBusy " 399 "slurMelismaBusy "
338 "doubleSlurs ", 400 "doubleSlurs ",
339 401
340 /* write */ 402 /* write */
341 "" 403 ""
342 ); 404 );
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b