LEFT | RIGHT |
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) 1996--2012 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 1996--2012 Han-Wen Nienhuys <hanwen@xs4all.nl> |
5 Jan Nieuwenhuizen <janneke@gnu.org> | 5 Jan Nieuwenhuizen <janneke@gnu.org> |
6 | 6 |
7 LilyPond is free software: you can redistribute it and/or modify | 7 LilyPond is free software: you can redistribute it and/or modify |
8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
9 the Free Software Foundation, either version 3 of the License, or | 9 the Free Software Foundation, either version 3 of the License, or |
10 (at your option) any later version. | 10 (at your option) any later version. |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "beam.hh" | 24 #include "beam.hh" |
25 #include "bezier.hh" | 25 #include "bezier.hh" |
26 #include "directional-element-interface.hh" | 26 #include "directional-element-interface.hh" |
27 #include "font-interface.hh" | 27 #include "font-interface.hh" |
28 #include "item.hh" | 28 #include "item.hh" |
29 #include "pointer-group-interface.hh" | 29 #include "pointer-group-interface.hh" |
30 #include "lookup.hh" | 30 #include "lookup.hh" |
31 #include "main.hh" // DEBUG_SLUR_SCORING | 31 #include "main.hh" // DEBUG_SLUR_SCORING |
32 #include "note-column.hh" | 32 #include "note-column.hh" |
33 #include "output-def.hh" | 33 #include "output-def.hh" |
| 34 #include "skyline-pair.hh" |
34 #include "spanner.hh" | 35 #include "spanner.hh" |
35 #include "staff-symbol-referencer.hh" | 36 #include "staff-symbol-referencer.hh" |
36 #include "stem.hh" | 37 #include "stem.hh" |
37 #include "text-interface.hh" | 38 #include "text-interface.hh" |
38 #include "tie.hh" | 39 #include "tie.hh" |
39 #include "warn.hh" | 40 #include "warn.hh" |
40 #include "slur-scoring.hh" | 41 #include "slur-scoring.hh" |
41 #include "separation-item.hh" | 42 #include "separation-item.hh" |
42 #include "international.hh" | 43 #include "international.hh" |
43 | 44 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 if (common_refpoint_of_array (encompasses, me, Y_AXIS) != parent) | 94 if (common_refpoint_of_array (encompasses, me, Y_AXIS) != parent) |
94 /* this could happen if, for example, we are a cross-staff slur. | 95 /* this could happen if, for example, we are a cross-staff slur. |
95 in this case, we want to be ignored */ | 96 in this case, we want to be ignored */ |
96 return ly_interval2scm (Interval ()); | 97 return ly_interval2scm (Interval ()); |
97 | 98 |
98 for (vsize i = 0; i < encompasses.size (); i++) | 99 for (vsize i = 0; i < encompasses.size (); i++) |
99 { | 100 { |
100 Interval d = encompasses[i]->pure_height (parent, start, end); | 101 Interval d = encompasses[i]->pure_height (parent, start, end); |
101 if (!d.is_empty ()) | 102 if (!d.is_empty ()) |
102 { | 103 { |
103 Direction downup = DOWN; | 104 for (DOWN_and_UP (downup)) |
104 do | |
105 ret.add_point (d[dir]); | 105 ret.add_point (d[dir]); |
106 while (flip (&downup) != DOWN); | |
107 | 106 |
108 if (extremal_heights[LEFT] == infinity_f) | 107 if (extremal_heights[LEFT] == infinity_f) |
109 extremal_heights[LEFT] = d[dir]; | 108 extremal_heights[LEFT] = d[dir]; |
110 extremal_heights[RIGHT] = d[dir]; | 109 extremal_heights[RIGHT] = d[dir]; |
111 } | 110 } |
112 } | 111 } |
113 | 112 |
114 if (ret.is_empty ()) | 113 if (ret.is_empty ()) |
115 return ly_interval2scm (Interval ()); | 114 return ly_interval2scm (Interval ()); |
116 | 115 |
117 Interval extremal_span; | 116 Interval extremal_span; |
118 extremal_span.set_empty (); | 117 extremal_span.set_empty (); |
119 Direction d = LEFT; | 118 for (LEFT_and_RIGHT (d)) |
120 do | |
121 extremal_span.add_point (extremal_heights[d]); | 119 extremal_span.add_point (extremal_heights[d]); |
122 while (flip (&d) != LEFT); | |
123 ret[-dir] = minmax (dir, extremal_span[-dir], ret[-dir]); | 120 ret[-dir] = minmax (dir, extremal_span[-dir], ret[-dir]); |
124 | 121 |
125 /* | 122 /* |
126 The +0.5 comes from the fact that we try to place a slur | 123 The +0.5 comes from the fact that we try to place a slur |
127 0.5 staff spaces from the note-head. | 124 0.5 staff spaces from the note-head. |
128 (see Slur_score_state.get_base_attachments ()) | 125 (see Slur_score_state.get_base_attachments ()) |
129 */ | 126 */ |
130 ret += 0.5 * dir; | 127 ret += 0.5 * dir; |
131 return ly_interval2scm (ret); | 128 return ly_interval2scm (ret); |
132 } | 129 } |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 Interval slur_wid (curve.control_[0][X_AXIS], curve.control_[3][X_AXIS]); | 303 Interval slur_wid (curve.control_[0][X_AXIS], curve.control_[3][X_AXIS]); |
307 | 304 |
308 /* | 305 /* |
309 cannot use is_empty because some 0-extent scripts | 306 cannot use is_empty because some 0-extent scripts |
310 come up with TabStaffs. | 307 come up with TabStaffs. |
311 */ | 308 */ |
312 if (xext.length () <= 0 || yext.length () <= 0) | 309 if (xext.length () <= 0 || yext.length () <= 0) |
313 return offset_scm; | 310 return offset_scm; |
314 | 311 |
315 bool contains = false; | 312 bool contains = false; |
316 Direction d = LEFT; | 313 for (LEFT_and_RIGHT (d)) |
317 do | |
318 contains |= slur_wid.contains (xext[d]); | 314 contains |= slur_wid.contains (xext[d]); |
319 while (flip (&d) != LEFT); | |
320 | 315 |
321 if (!contains) | 316 if (!contains) |
322 return offset_scm; | 317 return offset_scm; |
323 | 318 |
324 Real offset = robust_scm2double (offset_scm, 0); | 319 Real offset = robust_scm2double (offset_scm, 0); |
325 yext.translate (offset); | 320 yext.translate (offset); |
326 | 321 |
327 /* FIXME: slur property, script property? */ | 322 /* FIXME: slur property, script property? */ |
328 Real slur_padding = robust_scm2double (script->get_property ("slur-padding"), | 323 Real slur_padding = robust_scm2double (script->get_property ("slur-padding"), |
329 0.0); | 324 0.0); |
330 yext.widen (slur_padding); | 325 yext.widen (slur_padding); |
331 | 326 |
332 Interval exts[] = {xext, yext}; | 327 Interval exts[] = {xext, yext}; |
333 bool do_shift = false; | 328 bool do_shift = false; |
334 Real EPS = 1.0e-5; | 329 Real EPS = 1.0e-5; |
335 if (avoid == ly_symbol2scm ("outside")) | 330 if (avoid == ly_symbol2scm ("outside")) |
336 { | 331 { |
337 Direction d = LEFT; | 332 for (LEFT_and_RIGHT (d)) |
338 do | |
339 { | 333 { |
340 Real x = minmax (-d, xext[d], curve.control_[d == LEFT ? 0 : 3][X_AXIS
] + -d * EPS); | 334 Real x = minmax (-d, xext[d], curve.control_[d == LEFT ? 0 : 3][X_AXIS
] + -d * EPS); |
341 Real y = curve.get_other_coordinate (X_AXIS, x); | 335 Real y = curve.get_other_coordinate (X_AXIS, x); |
342 do_shift = y == minmax (dir, yext[-dir], y); | 336 do_shift = y == minmax (dir, yext[-dir], y); |
343 if (do_shift) | 337 if (do_shift) |
344 break; | 338 break; |
345 } | 339 } |
346 while (flip (&d) != LEFT); | |
347 } | 340 } |
348 else | 341 else |
349 { | 342 { |
350 for (int a = X_AXIS; a < NO_AXES; a++) | 343 for (int a = X_AXIS; a < NO_AXES; a++) |
351 { | 344 { |
352 Direction d = LEFT; | 345 for (LEFT_and_RIGHT (d)) |
353 do | |
354 { | 346 { |
355 vector<Real> coords = curve.get_other_coordinates (Axis (a), exts[
a][d]); | 347 vector<Real> coords = curve.get_other_coordinates (Axis (a), exts[
a][d]); |
356 for (vsize i = 0; i < coords.size (); i++) | 348 for (vsize i = 0; i < coords.size (); i++) |
357 { | 349 { |
358 do_shift = exts[(a + 1) % NO_AXES].contains (coords[i]); | 350 do_shift = exts[(a + 1) % NO_AXES].contains (coords[i]); |
359 if (do_shift) | 351 if (do_shift) |
360 break; | 352 break; |
361 } | 353 } |
362 if (do_shift) | 354 if (do_shift) |
363 break; | 355 break; |
364 } | 356 } |
365 while (flip (&d) != LEFT); | |
366 if (do_shift) | 357 if (do_shift) |
367 break; | 358 break; |
368 } | 359 } |
369 } | 360 } |
370 | 361 |
371 Real avoidance_offset = do_shift ? curve.minmax (X_AXIS, max (xext[LEFT], curv
e.control_[0][X_AXIS] + EPS), min (xext[RIGHT], curve.control_[3][X_AXIS] - EPS)
, dir) - yext[-dir] : 0.0; | 362 Real avoidance_offset = do_shift ? curve.minmax (X_AXIS, max (xext[LEFT], curv
e.control_[0][X_AXIS] + EPS), min (xext[RIGHT], curve.control_[3][X_AXIS] - EPS)
, dir) - yext[-dir] : 0.0; |
372 | 363 |
373 return scm_from_double (offset + avoidance_offset); | 364 return scm_from_double (offset + avoidance_offset); |
| 365 } |
| 366 |
| 367 MAKE_SCHEME_CALLBACK (Slur, vertical_skylines, 1); |
| 368 SCM |
| 369 Slur::vertical_skylines (SCM smob) |
| 370 { |
| 371 Grob *me = unsmob_grob (smob); |
| 372 vector<Box> boxes; |
| 373 |
| 374 if (!me) |
| 375 return Skyline_pair (boxes, X_AXIS).smobbed_copy (); |
| 376 |
| 377 Bezier curve = Slur::get_curve (me); |
| 378 vsize box_count = robust_scm2vsize (me->get_property ("skyline-quantizing"), 1
0); |
| 379 for (vsize i = 0; i < box_count; i++) |
| 380 { |
| 381 Box b; |
| 382 b.add_point (curve.curve_point (i * 1.0 / box_count)); |
| 383 b.add_point (curve.curve_point ((i + 1) * 1.0 / box_count)); |
| 384 boxes.push_back (b); |
| 385 } |
| 386 |
| 387 return Skyline_pair (boxes, X_AXIS).smobbed_copy (); |
374 } | 388 } |
375 | 389 |
376 /* | 390 /* |
377 * Used by Slur_engraver:: and Phrasing_slur_engraver:: | 391 * Used by Slur_engraver:: and Phrasing_slur_engraver:: |
378 */ | 392 */ |
379 void | 393 void |
380 Slur::auxiliary_acknowledge_extra_object (Grob_info const &info, | 394 Slur::auxiliary_acknowledge_extra_object (Grob_info const &info, |
381 vector<Grob *> &slurs, | 395 vector<Grob *> &slurs, |
382 vector<Grob *> &end_slurs) | 396 vector<Grob *> &end_slurs) |
383 { | 397 { |
384 if (slurs.empty () && end_slurs.empty ()) | 398 if (slurs.empty () && end_slurs.empty ()) |
385 return; | 399 return; |
386 | 400 |
387 Grob *e = info.grob (); | 401 Grob *e = info.grob (); |
388 SCM avoid = e->get_property ("avoid-slur"); | 402 SCM avoid = e->get_property ("avoid-slur"); |
| 403 Grob *slur; |
| 404 if (end_slurs.size () && !slurs.size ()) |
| 405 slur = end_slurs[0]; |
| 406 else |
| 407 slur = slurs[0]; |
| 408 |
389 if (Tie::has_interface (e) | 409 if (Tie::has_interface (e) |
390 || avoid == ly_symbol2scm ("inside")) | 410 || avoid == ly_symbol2scm ("inside")) |
391 { | 411 { |
392 for (vsize i = slurs.size (); i--;) | 412 for (vsize i = slurs.size (); i--;) |
393 add_extra_encompass (slurs[i], e); | 413 add_extra_encompass (slurs[i], e); |
394 for (vsize i = end_slurs.size (); i--;) | 414 for (vsize i = end_slurs.size (); i--;) |
395 add_extra_encompass (end_slurs[i], e); | 415 add_extra_encompass (end_slurs[i], e); |
| 416 if (slur) |
| 417 e->set_object ("slur", slur->self_scm ()); |
396 } | 418 } |
397 else if (avoid == ly_symbol2scm ("outside") | 419 else if (avoid == ly_symbol2scm ("outside") |
398 || avoid == ly_symbol2scm ("around")) | 420 || avoid == ly_symbol2scm ("around")) |
399 { | 421 { |
400 Grob *slur; | |
401 if (end_slurs.size () && !slurs.size ()) | |
402 slur = end_slurs[0]; | |
403 else | |
404 slur = slurs[0]; | |
405 | |
406 if (slur) | 422 if (slur) |
407 { | 423 { |
408 chain_offset_callback (e, outside_slur_callback_proc, Y_AXIS); | 424 chain_offset_callback (e, outside_slur_callback_proc, Y_AXIS); |
409 chain_callback (e, outside_slur_cross_staff_proc, ly_symbol2scm ("cros
s-staff")); | 425 chain_callback (e, outside_slur_cross_staff_proc, ly_symbol2scm ("cros
s-staff")); |
410 e->set_object ("slur", slur->self_scm ()); | 426 e->set_object ("slur", slur->self_scm ()); |
411 } | 427 } |
412 } | 428 } |
413 else if (avoid != ly_symbol2scm ("ignore")) | 429 else if (avoid != ly_symbol2scm ("ignore")) |
414 e->warning (_f ("Ignoring grob for slur: %s. avoid-slur not set?", | 430 e->warning (_f ("Ignoring grob for slur: %s. avoid-slur not set?", |
415 e->name ().c_str ())); | 431 e->name ().c_str ())); |
416 } | 432 } |
417 | 433 |
418 /* | 434 /* |
419 A callback that will be chained together with the original cross-staff | 435 A callback that will be chained together with the original cross-staff |
420 value of a grob that is placed 'outside or 'around a slur. This just says | 436 value of a grob that is placed 'outside or 'around a slur. This just says |
421 that any grob becomes cross-staff if it is placed 'outside or 'around a | 437 that any grob becomes cross-staff if it is placed 'outside or 'around a |
422 cross-staff slur. | 438 cross-staff slur. |
423 */ | 439 */ |
424 MAKE_SCHEME_CALLBACK (Slur, outside_slur_cross_staff, 2) | 440 MAKE_SCHEME_CALLBACK (Slur, outside_slur_cross_staff, 2) |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 "height-limit " | 560 "height-limit " |
545 "inspect-quants " | 561 "inspect-quants " |
546 "inspect-index " | 562 "inspect-index " |
547 "line-thickness " | 563 "line-thickness " |
548 "note-columns " | 564 "note-columns " |
549 "positions " | 565 "positions " |
550 "ratio " | 566 "ratio " |
551 "thickness " | 567 "thickness " |
552 ); | 568 ); |
553 | 569 |
LEFT | RIGHT |