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

Delta Between Two Patch Sets: lily/phrasing-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/
Left Patch Set: Moves cross-staff skyline logic to page-layout-problem.cc Created 12 years, 7 months ago
Right Patch Set: Better approximations 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:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
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 <map> 33 #include <algorithm>
34 34
35 /* 35 /*
36 NOTE NOTE NOTE 36 NOTE NOTE NOTE
37 37
38 This is largely similar to Slur_engraver. Check if fixes 38 This is largely similar to Slur_engraver. Check if fixes
39 apply there too. 39 apply there too.
40 40
41 (on principle, engravers don't use inheritance for code sharing) 41 (on principle, engravers don't use inheritance for code sharing)
42
43 For info on SlurStubs, check out slur-engraver.cc.
42 44
43 */ 45 */
44 46
45 /* 47 /*
46 It is possible that a slur starts and ends on the same note. At 48 It is possible that a slur starts and ends on the same note. At
47 least, it is for phrasing slurs: a note can be both beginning and 49 least, it is for phrasing slurs: a note can be both beginning and
48 ending of a phrase. 50 ending of a phrase.
49 */ 51 */
50 class Phrasing_slur_engraver : public Engraver 52 class Phrasing_slur_engraver : public Engraver
51 { 53 {
52 vector<Stream_event *> start_events_; 54 vector<Stream_event *> start_events_;
53 vector<Stream_event *> stop_events_; 55 vector<Stream_event *> stop_events_;
54 vector<Grob *> slurs_; 56 vector<Slur_info> slur_infos_;
55 vector<Grob *> end_slurs_; 57 vector<Slur_info> end_slur_infos_;
56 map<Grob *, vector<Grob *> > slur_stubs_;
57 vector<Grob_info> objects_to_acknowledge_; 58 vector<Grob_info> objects_to_acknowledge_;
58 59
59 protected: 60 protected:
60 DECLARE_TRANSLATOR_LISTENER (phrasing_slur); 61 DECLARE_TRANSLATOR_LISTENER (phrasing_slur);
61 DECLARE_ACKNOWLEDGER (inline_accidental); 62 DECLARE_ACKNOWLEDGER (inline_accidental);
62 DECLARE_ACKNOWLEDGER (fingering); 63 DECLARE_ACKNOWLEDGER (fingering);
63 DECLARE_ACKNOWLEDGER (note_column); 64 DECLARE_ACKNOWLEDGER (note_column);
64 DECLARE_ACKNOWLEDGER (slur); 65 DECLARE_ACKNOWLEDGER (slur);
65 DECLARE_ACKNOWLEDGER (script); 66 DECLARE_ACKNOWLEDGER (script);
66 DECLARE_ACKNOWLEDGER (dots); 67 DECLARE_ACKNOWLEDGER (dots);
67 DECLARE_ACKNOWLEDGER (text_script); 68 DECLARE_ACKNOWLEDGER (text_script);
68 DECLARE_ACKNOWLEDGER (tie); 69 DECLARE_END_ACKNOWLEDGER (tie);
69 DECLARE_ACKNOWLEDGER (tuplet_number); 70 DECLARE_ACKNOWLEDGER (tuplet_number);
70 71
71 void acknowledge_extra_object (Grob_info); 72 void acknowledge_extra_object (Grob_info);
72 void stop_translation_timestep (); 73 void stop_translation_timestep ();
73 void process_music (); 74 void process_music ();
74 75
75 virtual void finalize (); 76 virtual void finalize ();
76 virtual void derived_mark () const; 77 virtual void derived_mark () const;
77 78
78 public: 79 public:
(...skipping 23 matching lines...) Expand all
102 else if (d == STOP) 103 else if (d == STOP)
103 stop_events_.push_back (ev); 104 stop_events_.push_back (ev);
104 else ev->origin ()->warning (_f ("direction of %s invalid: %d", 105 else ev->origin ()->warning (_f ("direction of %s invalid: %d",
105 "phrasing-slur-event", int (d))); 106 "phrasing-slur-event", int (d)));
106 } 107 }
107 108
108 void 109 void
109 Phrasing_slur_engraver::acknowledge_note_column (Grob_info info) 110 Phrasing_slur_engraver::acknowledge_note_column (Grob_info info)
110 { 111 {
111 Grob *e = info.grob (); 112 Grob *e = info.grob ();
112 for (vsize i = slurs_.size (); i--;) 113 for (vsize i = slur_infos_.size (); i--;)
113 Slur::add_column (slurs_[i], e); 114 {
114 for (vsize i = end_slurs_.size (); i--;) 115 Slur::add_column (slur_infos_[i].slur_, e);
115 Slur::add_column (end_slurs_[i], e); 116 Grob *stub = make_spanner ("SlurStub", slur_infos_[i].slur_->self_scm ());
116 117 slur_infos_[i].stubs_.push_back (stub);
117 for (vsize j = 0; j < slurs_.size (); j++) 118 }
118 { 119 for (vsize i = end_slur_infos_.size (); i--;)
119 if (slur_stubs_.find (slurs_[j]) == slur_stubs_.end ()) 120 {
120 slur_stubs_[slurs_[j]] = vector<Grob *> (); 121 Slur::add_column (end_slur_infos_[i].slur_, e);
121 122 Grob *stub = make_spanner ("SlurStub", slur_infos_[i].slur_->self_scm ());
122 Grob *stub = make_spanner ("SlurStub", info.grob ()->self_scm ()); 123 end_slur_infos_[i].stubs_.push_back (stub);
123 slur_stubs_[slurs_[j]].push_back (stub);
124 }
125
126 for (vsize j = 0; j < end_slurs_.size (); j++)
127 {
128 if (slur_stubs_.find (end_slurs_[j]) == slur_stubs_.end ())
129 slur_stubs_[end_slurs_[j]] = vector<Grob *> ();
130
131 Grob *stub = make_spanner ("SlurStub", info.grob ()->self_scm ());
132 slur_stubs_[end_slurs_[j]].push_back (stub);
133 } 124 }
134 } 125 }
135 126
136 void 127 void
137 Phrasing_slur_engraver::acknowledge_extra_object (Grob_info info) 128 Phrasing_slur_engraver::acknowledge_extra_object (Grob_info info)
138 { 129 {
139 objects_to_acknowledge_.push_back (info); 130 objects_to_acknowledge_.push_back (info);
140 } 131 }
141 132
142 void 133 void
(...skipping 28 matching lines...) Expand all
171 acknowledge_extra_object (info); 162 acknowledge_extra_object (info);
172 } 163 }
173 164
174 void 165 void
175 Phrasing_slur_engraver::acknowledge_text_script (Grob_info info) 166 Phrasing_slur_engraver::acknowledge_text_script (Grob_info info)
176 { 167 {
177 acknowledge_extra_object (info); 168 acknowledge_extra_object (info);
178 } 169 }
179 170
180 void 171 void
181 Phrasing_slur_engraver::acknowledge_tie (Grob_info info) 172 Phrasing_slur_engraver::acknowledge_end_tie (Grob_info info)
182 { 173 {
183 acknowledge_extra_object (info); 174 acknowledge_extra_object (info);
184 } 175 }
185 176
186 void 177 void
187 Phrasing_slur_engraver::acknowledge_slur (Grob_info info) 178 Phrasing_slur_engraver::acknowledge_slur (Grob_info info)
188 { 179 {
189 if (!info.grob ()->internal_has_interface (ly_symbol2scm ("slur-stub-interface "))) 180 if (!info.grob ()->internal_has_interface (ly_symbol2scm ("cross-staff-stub-in terface")))
190 acknowledge_extra_object (info); 181 acknowledge_extra_object (info);
191 } 182 }
192 183
193 void 184 void
194 Phrasing_slur_engraver::finalize () 185 Phrasing_slur_engraver::finalize ()
195 { 186 {
196 for (vsize i = 0; i < slurs_.size (); i++) 187 for (vsize i = 0; i < slur_infos_.size (); i++)
197 { 188 {
198 slurs_[i]->warning (_ ("unterminated phrasing slur")); 189 slur_infos_[i].slur_->warning (_ ("unterminated phrasing slur"));
199 slurs_[i]->suicide (); 190 slur_infos_[i].slur_->suicide ();
200 } 191 for (vsize j = 0; j < slur_infos_[i].stubs_.size (); j++)
201 slurs_.clear (); 192 slur_infos_[i].stubs_[j]->suicide ();
202 slur_stubs_.clear (); 193 }
194 slur_infos_.clear ();
203 } 195 }
204 196
205 void 197 void
206 Phrasing_slur_engraver::process_music () 198 Phrasing_slur_engraver::process_music ()
207 { 199 {
208 for (vsize i = 0; i < stop_events_.size (); i++) 200 for (vsize i = 0; i < stop_events_.size (); i++)
209 { 201 {
210 Stream_event *ev = stop_events_[i]; 202 Stream_event *ev = stop_events_[i];
211 string id = robust_scm2string (ev->get_property ("spanner-id"), ""); 203 string id = robust_scm2string (ev->get_property ("spanner-id"), "");
212 204
213 // Find the slurs that are ended with this event (by checking the spanner- id) 205 // Find the slurs that are ended with this event (by checking the spanner- id)
214 bool ended = false; 206 bool ended = false;
215 for (vsize j = slurs_.size (); j--;) 207 for (vsize j = slur_infos_.size (); j--;)
216 { 208 {
217 if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), " ")) 209 if (id == robust_scm2string (slur_infos_[j].slur_->get_property ("span ner-id"), ""))
218 { 210 {
219 ended = true; 211 ended = true;
220 end_slurs_.push_back (slurs_[j]); 212 end_slur_infos_.push_back (slur_infos_[j].slur_);
221 slurs_.erase (slurs_.begin () + j); 213 slur_infos_.erase (slur_infos_.begin () + j);
222 } 214 }
223 } 215 }
224 if (ended) 216 if (ended)
225 { 217 {
226 // Ignore redundant stop events for this id 218 // Ignore redundant stop events for this id
227 for (vsize j = stop_events_.size (); --j > i;) 219 for (vsize j = stop_events_.size (); --j > i;)
228 { 220 {
229 if (id == robust_scm2string (stop_events_[j]->get_property ("spann er-id"), "")) 221 if (id == robust_scm2string (stop_events_[j]->get_property ("spann er-id"), ""))
230 stop_events_.erase (stop_events_.begin () + j); 222 stop_events_.erase (stop_events_.begin () + j);
231 } 223 }
232 } 224 }
233 else 225 else
234 ev->origin ()->warning (_ ("cannot end phrasing slur")); 226 ev->origin ()->warning (_ ("cannot end phrasing slur"));
235 } 227 }
236 228
237 vsize old_slurs = slurs_.size (); 229 vsize old_slurs = slur_infos_.size ();
238 for (vsize i = start_events_.size (); i--;) 230 for (vsize i = start_events_.size (); i--;)
239 { 231 {
240 Stream_event *ev = start_events_[i]; 232 Stream_event *ev = start_events_[i];
241 string id = robust_scm2string (ev->get_property ("spanner-id"), ""); 233 string id = robust_scm2string (ev->get_property ("spanner-id"), "");
242 Direction updown = to_dir (ev->get_property ("direction")); 234 Direction updown = to_dir (ev->get_property ("direction"));
243 235
244 bool completed; 236 bool completed;
245 for (vsize j = slurs_.size (); !(completed = (j-- == 0));) 237 for (vsize j = slur_infos_.size (); !(completed = (j-- == 0));)
246 { 238 {
247 // Check if we already have a slur with the same spanner-id. 239 // Check if we already have a slur with the same spanner-id.
248 if (id == robust_scm2string (slurs_[j]->get_property ("spanner-id"), " ")) 240 if (id == robust_scm2string (slur_infos_[j].slur_->get_property ("span ner-id"), ""))
249 { 241 {
250 if (j < old_slurs) 242 if (j < old_slurs)
251 { 243 {
252 // We already have an old slur, so give a warning 244 // We already have an old slur, so give a warning
253 // and completely ignore the new slur. 245 // and completely ignore the new slur.
254 ev->origin ()->warning (_ ("already have phrasing slur")); 246 ev->origin ()->warning (_ ("already have phrasing slur"));
255 start_events_.erase (start_events_.begin () + i); 247 start_events_.erase (start_events_.begin () + i);
256 break; 248 break;
257 } 249 }
258 250
259 // If this slur event has no direction, it will not 251 // If this slur event has no direction, it will not
260 // contribute anything new to the existing slur(s), so 252 // contribute anything new to the existing slur(s), so
261 // we can ignore it. 253 // we can ignore it.
262 254
263 if (!updown) 255 if (!updown)
264 break; 256 break;
265 257
266 Stream_event *c = unsmob_stream_event (slurs_[j]->get_property ("c ause")); 258 Stream_event *c = unsmob_stream_event (slur_infos_[j].slur_->get_p roperty ("cause"));
267 259
268 if (!c) 260 if (!c)
269 { 261 {
270 slurs_[j]->programming_error ("phrasing slur without a cause") ; 262 slur_infos_[j].slur_->programming_error ("phrasing slur withou t a cause");
271 continue; 263 continue;
272 } 264 }
273 265
274 Direction slur_dir = to_dir (c->get_property ("direction")); 266 Direction slur_dir = to_dir (c->get_property ("direction"));
275 267
276 // If the existing slur does not have a direction yet, 268 // If the existing slur does not have a direction yet,
277 // we'd rather take the new one. 269 // we'd rather take the new one.
278 270
279 if (!slur_dir) 271 if (!slur_dir)
280 { 272 {
281 slurs_[j]->suicide (); 273 slur_infos_[j].slur_->suicide ();
282 slurs_.erase (slurs_.begin () + j); 274 for (vsize k = 0; k < slur_infos_[i].stubs_.size (); k++)
275 slur_infos_[j].stubs_[k]->suicide ();
276 slur_infos_.erase (slur_infos_.begin () + j);
283 continue; 277 continue;
284 } 278 }
285 279
286 // If the existing slur has the same direction as ours, drop ours 280 // If the existing slur has the same direction as ours, drop ours
287 281
288 if (slur_dir == updown) 282 if (slur_dir == updown)
289 break; 283 break;
290 } 284 }
291 } 285 }
292 // If the loop completed, our slur is new 286 // If the loop completed, our slur is new
293 if (completed) 287 if (completed)
294 { 288 {
295 Grob *slur = make_spanner ("PhrasingSlur", ev->self_scm ()); 289 Grob *slur = make_spanner ("PhrasingSlur", ev->self_scm ());
296 slur->set_property ("spanner-id", ly_string2scm (id)); 290 slur->set_property ("spanner-id", ly_string2scm (id));
297 if (updown) 291 if (updown)
298 set_grob_direction (slur, updown); 292 set_grob_direction (slur, updown);
299 slurs_.push_back (slur); 293 slur_infos_.push_back (slur);
300 } 294 }
301 } 295 }
302 } 296 }
303 297
304 void 298 void
305 Phrasing_slur_engraver::stop_translation_timestep () 299 Phrasing_slur_engraver::stop_translation_timestep ()
306 { 300 {
307 if (Grob *g = unsmob_grob (get_property ("currentCommandColumn"))) 301 if (Grob *g = unsmob_grob (get_property ("currentCommandColumn")))
308 { 302 {
309 for (vsize i = 0; i < end_slurs_.size (); i++) 303 for (vsize i = 0; i < end_slur_infos_.size (); i++)
310 Slur::add_extra_encompass (end_slurs_[i], g); 304 Slur::add_extra_encompass (end_slur_infos_[i].slur_, g);
311 305
312 if (!start_events_.size ()) 306 if (!start_events_.size ())
313 for (vsize i = 0; i < slurs_.size (); i++) 307 for (vsize i = 0; i < slur_infos_.size (); i++)
314 Slur::add_extra_encompass (slurs_[i], g); 308 Slur::add_extra_encompass (slur_infos_[i].slur_, g);
315 } 309 }
316 310
317 for (vsize i = 0; i < end_slurs_.size (); i++) 311 for (vsize i = 0; i < end_slur_infos_.size (); i++)
318 { 312 {
319 Spanner *s = dynamic_cast<Spanner *> (end_slurs_[i]); 313 Spanner *s = dynamic_cast<Spanner *> (end_slur_infos_[i].slur_);
320 if (!s->get_bound (RIGHT)) 314 if (!s->get_bound (RIGHT))
321 s->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn")) ); 315 s->set_bound (RIGHT, unsmob_grob (get_property ("currentMusicalColumn")) );
322 announce_end_grob (s, SCM_EOL); 316 announce_end_grob (s, SCM_EOL);
323 } 317 }
324 318
325 for (vsize i = 0; i < objects_to_acknowledge_.size (); i++) 319 for (vsize i = 0; i < objects_to_acknowledge_.size (); i++)
326 Slur::auxiliary_acknowledge_extra_object (objects_to_acknowledge_[i], slurs_ , end_slurs_); 320 Slur::auxiliary_acknowledge_extra_object (objects_to_acknowledge_[i], slur_i nfos_, end_slur_infos_);
327 321
328 for (vsize i = 0; i < end_slurs_.size (); i++) 322 for (vsize i = 0; i < end_slur_infos_.size (); i++)
329 if (slur_stubs_.find (end_slurs_[i]) != slur_stubs_.end ()) 323 {
330 { 324 // There are likely SlurStubs we don't need. Get rid of them.
331 // We likely SlurStubs we don't need. Get rid of them. 325 vector<Grob *> vags;
332 map<Grob *, Grob *> vag_to_slur; 326 vector<Grob *> stubs;
333 for (vsize j = 0; j < slur_stubs_[end_slurs_[i]].size (); j++) 327 for (vsize j = 0; j < end_slur_infos_[i].stubs_.size (); j++)
334 { 328 {
335 Grob *vag = Grob::get_vertical_axis_group (slur_stubs_[end_slurs_[i] ][j]); 329 Grob *stub = end_slur_infos_[i].stubs_[j];
336 if (vag) 330 Grob *vag = Grob::get_vertical_axis_group (stub);
337 { 331 if (vag)
338 if (vag_to_slur.find (vag) != vag_to_slur.end ()) 332 {
339 slur_stubs_[end_slurs_[i]][j]->suicide (); 333 vector<Grob *>::const_iterator it =
340 else 334 find (vags.begin (), vags.end (), vag);
341 vag_to_slur[vag] = slur_stubs_[end_slurs_[i]][j]; 335 if (it != vags.end ())
342 } 336 stub->suicide ();
343 else 337 else
344 { 338 {
345 end_slurs_[i]->programming_error ("Cannot find vertical axis gro up for NoteColumn."); 339 vags.push_back (vag);
346 slur_stubs_[end_slurs_[i]][j]->suicide (); 340 stubs.push_back (stub);
347 } 341 }
348 } 342 }
349 map<Grob *, Grob *>::const_iterator it; 343 else
350 for (it = vag_to_slur.begin (); 344 {
351 it != vag_to_slur.end (); 345 end_slur_infos_[i].slur_->programming_error ("Cannot find vertical axis group for NoteColumn.");
352 it++) 346 stub->suicide ();
353 Slur::main_to_stub (end_slurs_[i], it->second); 347 }
354 348 }
355 slur_stubs_.erase (end_slurs_[i]); 349 for (vsize j = 0; j < stubs.size (); j++)
356 } 350 Slur::main_to_stub (end_slur_infos_[i].slur_, stubs[j]);
351 }
357 352
358 objects_to_acknowledge_.clear (); 353 objects_to_acknowledge_.clear ();
359 end_slurs_.clear (); 354 end_slur_infos_.clear ();
360 start_events_.clear (); 355 start_events_.clear ();
361 stop_events_.clear (); 356 stop_events_.clear ();
362 } 357 }
363 358
364 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, inline_accidental); 359 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, inline_accidental);
365 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, fingering) 360 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, fingering)
366 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, note_column); 361 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, note_column);
367 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, slur); 362 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, slur);
368 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, script); 363 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, script);
369 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, dots); 364 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, dots);
370 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, text_script); 365 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, text_script);
371 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, tie); 366 ADD_END_ACKNOWLEDGER (Phrasing_slur_engraver, tie);
372 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, tuplet_number); 367 ADD_ACKNOWLEDGER (Phrasing_slur_engraver, tuplet_number);
373 368
374 ADD_TRANSLATOR (Phrasing_slur_engraver, 369 ADD_TRANSLATOR (Phrasing_slur_engraver,
375 /* doc */ 370 /* doc */
376 "Print phrasing slurs. Similar to @ref{Slur_engraver}.", 371 "Print phrasing slurs. Similar to @ref{Slur_engraver}.",
377 372
378 /* create */ 373 /* create */
379 "PhrasingSlur ", 374 "PhrasingSlur ",
380 375
381 /* read */ 376 /* read */
382 "", 377 "",
383 378
384 /* write */ 379 /* write */
385 "" 380 ""
386 ); 381 );
LEFTRIGHT

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