LEFT | RIGHT |
(no file at all) | |
| 1 /* |
| 2 This file is part of LilyPond, the GNU music typesetter. |
| 3 |
| 4 Copyright (C) 2020--2020 David Stephen Grant <david@davidgrant.no> |
| 5 |
| 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 |
| 8 the Free Software Foundation, either version 3 of the License, or |
| 9 (at your option) any later version. |
| 10 |
| 11 LilyPond is distributed in the hope that it will be useful, |
| 12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 GNU General Public License for more details. |
| 15 |
| 16 You should have received a copy of the GNU General Public License |
| 17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>. |
| 18 */ |
| 19 |
| 20 #include "vowel-transition.hh" |
| 21 |
| 22 #include "axis-group-interface.hh" |
| 23 #include "lookup.hh" |
| 24 #include "output-def.hh" |
| 25 #include "paper-column.hh" |
| 26 #include "moment.hh" |
| 27 #include "rod.hh" |
| 28 #include "spanner.hh" |
| 29 #include "system.hh" |
| 30 |
| 31 MAKE_SCHEME_CALLBACK (Vowel_transition, set_spacing_rods, 1); |
| 32 SCM |
| 33 Vowel_transition::set_spacing_rods (SCM smob) |
| 34 { |
| 35 Grob *me = unsmob<Grob> (smob); |
| 36 |
| 37 SCM minimum_length = me->get_property ("minimum-length"); |
| 38 SCM broken_length = me->get_property ("minimum-length-after-break"); |
| 39 if (scm_is_number (minimum_length) |
| 40 || scm_is_number (broken_length)) |
| 41 { |
| 42 Spanner *sp = dynamic_cast<Spanner *> (me); |
| 43 System *root = get_root_system (me); |
| 44 Drul_array<Item *> bounds (sp->get_bound (LEFT), |
| 45 sp->get_bound (RIGHT)); |
| 46 if (!bounds[LEFT] || !bounds[RIGHT]) |
| 47 return SCM_UNSPECIFIED; |
| 48 std::vector<Item *> cols (root->broken_col_range (bounds[LEFT]->get_column
(), |
| 49 bounds[RIGHT]->get_colum
n ())); |
| 50 Drul_array<Real> padding = { 0.0, 0.0 }; |
| 51 Drul_array<Real> padding_broken = { 0.0, 0.0 }; |
| 52 for (LEFT_and_RIGHT (d)) |
| 53 { |
| 54 SCM bounds = sp->get_property ("bound-details"); |
| 55 SCM details = ly_assoc_get |
| 56 ((d == LEFT |
| 57 ? ly_symbol2scm ("left") |
| 58 : ly_symbol2scm ("right")), bounds, SCM_BOOL_F); |
| 59 SCM details_broken = ly_assoc_get |
| 60 ((d == LEFT |
| 61 ? ly_symbol2scm ("left-broken") |
| 62 : ly_symbol2scm ("right-broken")), bounds, SCM_BOOL_
F); |
| 63 if ( !scm_is_false (details)) |
| 64 padding[d] = |
| 65 robust_scm2double (ly_assoc_get (ly_symbol2scm ("padding"), |
| 66 details, SCM_BOOL_F), 0.0); |
| 67 if ( !scm_is_false (details_broken)) |
| 68 padding_broken[d] = |
| 69 robust_scm2double (ly_assoc_get (ly_symbol2scm ("padding"), |
| 70 details_broken, SCM_BOOL_F), 0.0)
; |
| 71 } |
| 72 |
| 73 if (cols.size ()) |
| 74 { |
| 75 /* Before line break */ |
| 76 Rod r1; |
| 77 r1.item_drul_[LEFT] = sp->get_bound (LEFT); |
| 78 r1.item_drul_[RIGHT] = cols[0]->find_prebroken_piece (LEFT); |
| 79 r1.distance_ = robust_scm2double (minimum_length, 0); |
| 80 r1.distance_ += padding[LEFT]; |
| 81 r1.distance_ += padding_broken[RIGHT]; |
| 82 r1.distance_ += bounds_protrusion (&r1); |
| 83 r1.add_to_cols (); |
| 84 |
| 85 /* After line break */ |
| 86 Rod r2; |
| 87 r2.item_drul_[LEFT] = cols.back ()->find_prebroken_piece (RIGHT); |
| 88 r2.item_drul_[RIGHT] = sp->get_bound (RIGHT); |
| 89 Interval_t<Moment> segment_time = spanned_time_interval (r2.item_drul_
[LEFT], |
| 90 r2.item_drul_
[RIGHT]); |
| 91 segment_time [LEFT].grace_part_ = 0; |
| 92 /* |
| 93 Calculate and add space only if the vowel transition is to be drawn. |
| 94 I.e., either it does not end on the first note after breaking, |
| 95 or property after-line-breaking is set to #t. |
| 96 */ |
| 97 if ((segment_time.length () != Moment (0, 0)) |
| 98 || to_boolean (me->get_property ("after-line-breaking"))) |
| 99 { |
| 100 r2.distance_ = (scm_is_number (broken_length) |
| 101 ? robust_scm2double (broken_length, 0) |
| 102 : robust_scm2double (minimum_length, 0)); |
| 103 r2.distance_ += padding_broken[LEFT]; |
| 104 r2.distance_ += padding[RIGHT]; |
| 105 r2.distance_ += bounds_protrusion (&r2); |
| 106 r2.add_to_cols (); |
| 107 } |
| 108 } |
| 109 |
| 110 Rod r; |
| 111 r.distance_ = robust_scm2double (minimum_length, 0); |
| 112 r.item_drul_[LEFT] = sp->get_bound (LEFT); |
| 113 r.item_drul_[RIGHT] = sp->get_bound (RIGHT); |
| 114 for (LEFT_and_RIGHT (d)) |
| 115 r.distance_ += padding[d]; |
| 116 r.distance_ += bounds_protrusion (&r); |
| 117 r.add_to_cols (); |
| 118 |
| 119 if (Item *left_pbp = sp->get_bound (RIGHT)->find_prebroken_piece (LEFT)) |
| 120 { |
| 121 r.item_drul_[RIGHT] = left_pbp; |
| 122 r.add_to_cols (); |
| 123 } |
| 124 } |
| 125 |
| 126 return SCM_UNSPECIFIED; |
| 127 } |
| 128 |
| 129 Real |
| 130 Vowel_transition::bounds_protrusion (const Rod *r) |
| 131 { |
| 132 /* Calculate protrusion of bounds into rod */ |
| 133 Real w = 0; |
| 134 for (LEFT_and_RIGHT (d)) |
| 135 { |
| 136 if (r->item_drul_[d]) |
| 137 w += -d * r->item_drul_[d]->extent (r->item_drul_[d], X_AXIS)[-d]; |
| 138 } |
| 139 return w; |
| 140 } |
LEFT | RIGHT |