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

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

Issue 4490045: Bugfix for issue 1630 (Closed)
Patch Set: fixing style Created 13 years, 10 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
« no previous file with comments | « lily/completion-note-heads-engraver.cc ('k') | scm/define-music-properties.scm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) 1998--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> 4 Copyright (C) 1998--2011 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 75
76 protected: 76 protected:
77 void stop_translation_timestep (); 77 void stop_translation_timestep ();
78 virtual void derived_mark () const; 78 virtual void derived_mark () const;
79 void start_translation_timestep (); 79 void start_translation_timestep ();
80 DECLARE_ACKNOWLEDGER (note_head); 80 DECLARE_ACKNOWLEDGER (note_head);
81 DECLARE_TRANSLATOR_LISTENER (tie); 81 DECLARE_TRANSLATOR_LISTENER (tie);
82 void process_music (); 82 void process_music ();
83 void typeset_tie (Grob *); 83 void typeset_tie (Grob *);
84 void report_unterminated_tie (Head_event_tuple const &); 84 void report_unterminated_tie (Head_event_tuple const &);
85 bool has_autosplit_end (Stream_event *event);
85 public: 86 public:
86 TRANSLATOR_DECLARATIONS (Tie_engraver); 87 TRANSLATOR_DECLARATIONS (Tie_engraver);
87 }; 88 };
88 89
89 void 90 void
90 Tie_engraver::derived_mark () const 91 Tie_engraver::derived_mark () const
91 { 92 {
92 Engraver::derived_mark (); 93 Engraver::derived_mark ();
93 for (vsize i = 0; i < heads_to_tie_.size (); i++) 94 for (vsize i = 0; i < heads_to_tie_.size (); i++)
94 scm_gc_mark (heads_to_tie_[i].tie_definition_); 95 scm_gc_mark (heads_to_tie_[i].tie_definition_);
(...skipping 14 matching lines...) Expand all
109 110
110 void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start) 111 void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start)
111 { 112 {
112 // If tie_from_chord_created is set, we have another note at the same 113 // If tie_from_chord_created is set, we have another note at the same
113 // moment that created a tie, so this is not necessarily an unterminated 114 // moment that created a tie, so this is not necessarily an unterminated
114 // tie. Happens e.g. for <c e g>~ g 115 // tie. Happens e.g. for <c e g>~ g
115 if (!tie_start.tie_from_chord_created) 116 if (!tie_start.tie_from_chord_created)
116 tie_start.head_->warning (_("unterminated tie")); 117 tie_start.head_->warning (_("unterminated tie"));
117 } 118 }
118 119
120 /*
121 Determines whether the end of an event was created by
122 a split in Completion_heads_engraver or by user input.
123 */
124 bool
125 Tie_engraver::has_autosplit_end (Stream_event *event)
126 {
127 if (event)
128 return to_boolean (event->get_property ("autosplit-end"));
129 return false;
130 }
131
119 void 132 void
120 Tie_engraver::process_music () 133 Tie_engraver::process_music ()
121 { 134 {
122 bool busy = event_; 135 bool busy = event_;
123 for (vsize i = 0; !busy && i < heads_to_tie_.size (); i++) 136 for (vsize i = 0; !busy && i < heads_to_tie_.size (); i++)
124 busy |= (heads_to_tie_[i].tie_event_ 137 busy |= (heads_to_tie_[i].tie_event_
125 || heads_to_tie_[i].tie_stream_event_); 138 || heads_to_tie_[i].tie_stream_event_);
126 139
127 if (busy) 140 if (busy)
128 context ()->set_property ("tieMelismaBusy", SCM_BOOL_T); 141 context ()->set_property ("tieMelismaBusy", SCM_BOOL_T);
129 } 142 }
130 143
131 void 144 void
132 Tie_engraver::acknowledge_note_head (Grob_info i) 145 Tie_engraver::acknowledge_note_head (Grob_info i)
133 { 146 {
134 Grob *h = i.grob (); 147 Grob *h = i.grob ();
135 148
136 now_heads_.push_back (h); 149 now_heads_.push_back (h);
137 for (vsize i = heads_to_tie_.size (); i--;) 150 for (vsize i = heads_to_tie_.size (); i--;)
138 { 151 {
139 Grob *th = heads_to_tie_[i].head_; 152 Grob *th = heads_to_tie_[i].head_;
140 Stream_event *right_ev = unsmob_stream_event (h->get_property ("cause")); 153 Stream_event *right_ev = unsmob_stream_event (h->get_property ("cause"));
141 Stream_event *left_ev = unsmob_stream_event (th->get_property ("cause")); 154 Stream_event *left_ev = unsmob_stream_event (th->get_property ("cause"));
142 155
143 /* 156 /*
144 » maybe should check positions too. 157 maybe should check positions too.
145 */ 158 */
146 if (!right_ev || !left_ev) 159 if (!right_ev || !left_ev)
147 » continue; 160 continue;
148
149 if (ly_is_equal (right_ev->get_property ("pitch"),
150 » » left_ev->get_property ("pitch")))
151 » {
152 » Grob *p = new Spanner (heads_to_tie_[i].tie_definition_);
153 » Moment end = heads_to_tie_[i].end_moment_;
154
155 » SCM cause = heads_to_tie_[i].tie_event_
156 » ? heads_to_tie_[i].tie_event_->self_scm ()
157 » : heads_to_tie_[i].tie_stream_event_->self_scm ();
158
159 » announce_grob (p, cause);
160 » Tie::set_head (p, LEFT, th);
161 » Tie::set_head (p, RIGHT, h);
162 161
163 162
164 » if (is_direction (unsmob_stream_event (cause)->get_property ("directio n"))) 163 /*
165 » { 164 Make a tie only if pitches are equal or if event end was not generated b y
166 » Direction d = to_dir (unsmob_stream_event (cause)->get_property (" direction")); 165 Completion_heads_engraver.
167 » p->set_property ("direction", scm_from_int (d)); 166 */
168 » } 167 if (ly_is_equal (right_ev->get_property ("pitch"), left_ev->get_property ( "pitch"))
168 && (!Tie_engraver::has_autosplit_end (left_ev)))
169 {
170 Grob *p = new Spanner (heads_to_tie_[i].tie_definition_);
171 Moment end = heads_to_tie_[i].end_moment_;
169 172
170 » ties_.push_back (p); 173 SCM cause = heads_to_tie_[i].tie_event_
171 » heads_to_tie_.erase (heads_to_tie_.begin () + i); 174 ? heads_to_tie_[i].tie_event_->self_scm ()
175 » : heads_to_tie_[i].tie_stream_event_->self_scm ();
172 176
173 » // Prevent all other tied notes ending at the same moment (assume 177 announce_grob (p, cause);
174 » // implicitly the notes have also started at the same moment!) 178 Tie::set_head (p, LEFT, th);
175 » // from triggering an "unterminated tie" warning. Needed e.g. for 179 Tie::set_head (p, RIGHT, h);
176 » // <c e g>~ g 180
177 » for (vsize j = heads_to_tie_.size (); j--;) 181
178 » { 182 if (is_direction (unsmob_stream_event (cause)->get_property ("directio n")))
179 » if (heads_to_tie_[j].end_moment_ == end) 183 {
180 » heads_to_tie_[j].tie_from_chord_created = true; 184 Direction d = to_dir (unsmob_stream_event (cause)->get_property (" direction"));
181 » } 185 p->set_property ("direction", scm_from_int (d));
182 » } 186 }
187
188 ties_.push_back (p);
189 heads_to_tie_.erase (heads_to_tie_.begin () + i);
190
191 /*
192 Prevent all other tied notes ending at the same moment (assume
193 implicitly the notes have also started at the same moment!)
194 from triggering an "unterminated tie" warning. Needed e.g. for
195 <c e g>~ g
196 */
197 for (vsize j = heads_to_tie_.size (); j--;)
198 {
199 if (heads_to_tie_[j].end_moment_ == end)
200 heads_to_tie_[j].tie_from_chord_created = true;
201 }
202 }
183 } 203 }
184 204
185 if (ties_.size () && ! tie_column_) 205 if (ties_.size () && ! tie_column_)
186 tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ()); 206 tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ());
187 207
188 if (tie_column_) 208 if (tie_column_)
189 for (vsize i = ties_.size (); i--;) 209 for (vsize i = ties_.size (); i--;)
190 Tie_column::add_tie (tie_column_, ties_[i]); 210 Tie_column::add_tie (tie_column_, ties_[i]);
191 } 211 }
192 212
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 246
227 for (vsize i = 0; i < ties_.size (); i++) 247 for (vsize i = 0; i < ties_.size (); i++)
228 typeset_tie (ties_[i]); 248 typeset_tie (ties_[i]);
229 249
230 ties_.clear (); 250 ties_.clear ();
231 tie_column_ = 0; 251 tie_column_ = 0;
232 } 252 }
233 253
234 vector<Head_event_tuple> new_heads_to_tie; 254 vector<Head_event_tuple> new_heads_to_tie;
235 255
256 /*
257 Whether tie event has been processed and can be deleted or should
258 be kept for later portions of a split note.
259 */
260 bool event_processed = false;
261
236 for (vsize i = 0; i < now_heads_.size (); i++) 262 for (vsize i = 0; i < now_heads_.size (); i++)
237 { 263 {
238 Grob *head = now_heads_[i]; 264 Grob *head = now_heads_[i];
239 Stream_event *left_ev 265 Stream_event *left_ev
240 = unsmob_stream_event (head->get_property ("cause")); 266 = unsmob_stream_event (head->get_property ("cause"));
241 267
242 if (!left_ev) 268 if (!left_ev)
243 { 269 {
244 // may happen for ambitus 270 // may happen for ambitus
245 continue; 271 continue;
246 } 272 }
247 273
248 274
249 SCM left_articulations = left_ev->get_property ("articulations"); 275 SCM left_articulations = left_ev->get_property ("articulations");
250 276
251 Stream_event *tie_event = 0; 277 Stream_event *tie_event = 0;
252 Stream_event *tie_stream_event = event_; 278 Stream_event *tie_stream_event = event_;
253 for (SCM s = left_articulations; 279 for (SCM s = left_articulations;
254 !tie_event && !tie_stream_event && scm_is_pair (s); 280 !tie_event && !tie_stream_event && scm_is_pair (s);
255 s = scm_cdr (s)) 281 s = scm_cdr (s))
256 { 282 {
257 Stream_event *ev = unsmob_stream_event (scm_car (s)); 283 Stream_event *ev = unsmob_stream_event (scm_car (s));
258 if (!ev) 284 if (!ev)
259 continue; 285 continue;
260 286
261 if (ev->in_event_class ("tie-event")) 287 if (ev->in_event_class ("tie-event"))
262 tie_event = ev; 288 tie_event = ev;
263 } 289 }
264 290
265 if (left_ev && (tie_event || tie_stream_event)) 291 if (left_ev && (tie_event || tie_stream_event)
266 » { 292 && (!Tie_engraver::has_autosplit_end (left_ev)))
267 » Head_event_tuple event_tup; 293 {
294 event_processed = true;
268 295
269 » SCM start_definition 296 » Head_event_tuple event_tup;
270 » = updated_grob_properties (context (), ly_symbol2scm ("Tie"));
271 297
272 » event_tup.head_ = head; 298 » SCM start_definition
273 » event_tup.tie_definition_ = start_definition; 299 » = updated_grob_properties (context (), ly_symbol2scm ("Tie"));
274 » event_tup.tie_event_ = tie_event;
275 » event_tup.tie_stream_event_ = tie_stream_event;
276 300
277 » Moment end = now_mom (); 301 » event_tup.head_ = head;
278 » if (end.grace_part_) 302 » event_tup.tie_definition_ = start_definition;
279 » { 303 » event_tup.tie_event_ = tie_event;
280 » end.grace_part_ += get_event_length (left_ev).main_part_; 304 » event_tup.tie_stream_event_ = tie_stream_event;
281 » }
282 » else
283 » {
284 » end += get_event_length (left_ev);
285 » }
286 » event_tup.end_moment_ = end;
287 305
288 » new_heads_to_tie.push_back (event_tup); 306 » Moment end = now_mom ();
289 » } 307 » if (end.grace_part_)
308 » {
309 » end.grace_part_ += get_event_length (left_ev).main_part_;
310 » }
311 » else
312 » {
313 » end += get_event_length (left_ev);
314 » }
315 » event_tup.end_moment_ = end;
316
317 » new_heads_to_tie.push_back (event_tup);
318 » }
290 } 319 }
291 320
292 if (!wait && new_heads_to_tie.size ()) 321 if (!wait && new_heads_to_tie.size ())
293 { 322 {
294 vector<Head_event_tuple>::iterator it=heads_to_tie_.begin (); 323 vector<Head_event_tuple>::iterator it=heads_to_tie_.begin ();
295 for (; it < heads_to_tie_.end (); it++) 324 for (; it < heads_to_tie_.end (); it++)
296 report_unterminated_tie (*it); 325 report_unterminated_tie (*it);
297 heads_to_tie_.clear (); 326 heads_to_tie_.clear ();
298 } 327 }
299 328
300 // hmmm, how to do with copy () ? 329 // hmmm, how to do with copy () ?
301 for (vsize i = 0; i < new_heads_to_tie.size (); i++) 330 for (vsize i = 0; i < new_heads_to_tie.size (); i++)
302 heads_to_tie_.push_back (new_heads_to_tie[i]); 331 heads_to_tie_.push_back (new_heads_to_tie[i]);
303 332
304 event_ = 0; 333 /*
334 Discard event only if it has been processed with at least one
335 appropriate note.
336 */
337 if (event_processed)
338 event_ = 0;
339
305 now_heads_.clear (); 340 now_heads_.clear ();
306 } 341 }
307 342
308 void 343 void
309 Tie_engraver::typeset_tie (Grob *her) 344 Tie_engraver::typeset_tie (Grob *her)
310 { 345 {
311 if (! (Tie::head (her, LEFT) && Tie::head (her, RIGHT))) 346 if (! (Tie::head (her, LEFT) && Tie::head (her, RIGHT)))
312 warning (_ ("lonely tie")); 347 warning (_ ("lonely tie"));
313 348
314 Direction d = LEFT; 349 Direction d = LEFT;
(...skipping 20 matching lines...) Expand all
335 /* create */ 370 /* create */
336 "Tie " 371 "Tie "
337 "TieColumn ", 372 "TieColumn ",
338 373
339 /* read */ 374 /* read */
340 "tieWaitForNote ", 375 "tieWaitForNote ",
341 376
342 /* write */ 377 /* write */
343 "tieMelismaBusy " 378 "tieMelismaBusy "
344 ); 379 );
OLDNEW
« no previous file with comments | « lily/completion-note-heads-engraver.cc ('k') | scm/define-music-properties.scm » ('j') | no next file with comments »

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