Left: | ||
Right: |
OLD | NEW |
---|---|
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 15 matching lines...) Expand all Loading... | |
26 #include "note-head.hh" | 26 #include "note-head.hh" |
27 #include "output-def.hh" | 27 #include "output-def.hh" |
28 #include "pointer-group-interface.hh" | 28 #include "pointer-group-interface.hh" |
29 #include "item.hh" | 29 #include "item.hh" |
30 #include "rhythmic-head.hh" | 30 #include "rhythmic-head.hh" |
31 #include "staff-symbol-referencer.hh" | 31 #include "staff-symbol-referencer.hh" |
32 #include "side-position-interface.hh" | 32 #include "side-position-interface.hh" |
33 #include "stem.hh" | 33 #include "stem.hh" |
34 #include "warn.hh" | 34 #include "warn.hh" |
35 | 35 |
36 void | |
37 check_meshing_chords (Grob *me, | |
38 Drul_array<vector<Real> > *offsets, | |
39 Drul_array<vector<Slice> > const &extents, | |
40 Drul_array<vector<Grob *> > const &clash_groups) | |
41 | 36 |
37 Collision_type determine_collision_type(Grob *me, | |
38 Drul_array<Grob *> stems, | |
39 vector<int> ups, | |
40 vector<int> dps, | |
41 Grob *head_up, | |
42 Grob *head_down) | |
42 { | 43 { |
43 if (!extents[UP].size () || !extents[DOWN].size ()) | |
44 return; | |
45 | |
46 Grob *clash_up = clash_groups[UP][0]; | |
47 Grob *clash_down = clash_groups[DOWN][0]; | |
48 | |
49 /* Every note column should have a stem, but avoid a crash. */ | |
50 if (!Note_column::get_stem (clash_up) || !Note_column::get_stem (clash_down)) | |
51 return; | |
52 | |
53 Drul_array<Grob *> stems (Note_column::get_stem (clash_down), | |
54 Note_column::get_stem (clash_up)); | |
55 | |
56 Grob *head_up = Note_column::first_head (clash_up); | |
57 Grob *head_down = Note_column::first_head (clash_down); | |
58 | |
59 /* Staff-positions of all noteheads on each stem */ | |
60 vector<int> ups = Stem::note_head_positions (stems[UP]); | |
61 vector<int> dps = Stem::note_head_positions (stems[DOWN]); | |
62 | |
63 /* Too far apart to collide. */ | |
64 if (ups[0] > dps.back () + 1) | |
65 return; | |
66 | |
67 /* If the chords just 'touch' their extreme noteheads, | |
68 then we can align their stems. | |
69 */ | |
70 bool touch = false; | |
71 if (ups[0] >= dps.back () | |
72 && (dps.size () < 2 || ups[0] >= dps[dps.size () - 2] + 2) | |
73 && (ups.size () < 2 || ups[1] >= dps.back () + 2)) | |
74 touch = true; | |
75 | 44 |
76 /* Filter out the 'o's in this configuration, since they're no | 45 /* Filter out the 'o's in this configuration, since they're no |
Keith
2012/03/31 21:04:35
It explains the two assignment lines below. We us
Milimetr88
2012/04/14 13:56:18
Oh, well, it's my mistake - indeed dps is not need
Keith
2012/04/14 19:12:01
The use of ups[0] on line 230 is correct(*) whethe
| |
77 * part in the collision. | 46 * part in the collision. |
78 * | 47 * |
79 * | | 48 * | |
80 * x|o | 49 * x|o |
81 * x|o | 50 * x|o |
82 * x | 51 * x |
83 * | 52 * |
84 */ | 53 */ |
85 ups = Stem::note_head_positions (stems[UP], true); | 54 ups = Stem::note_head_positions (stems[UP], true); |
86 dps = Stem::note_head_positions (stems[DOWN], true); | 55 dps = Stem::note_head_positions (stems[DOWN], true); |
87 | 56 |
88 /* Merge heads if the notes lie the same line, or if the "stem-up-note" is | 57 /* Merge heads if the notes lie the same line, or if the "stem-up-note" is |
89 above the "stem-down-note". */ | 58 above the "stem-down-note". */ |
90 bool merge_possible = (ups[0] >= dps[0]) && (ups.back () >= dps.back ()); | 59 bool merge_possible = (ups.front () >= dps.front ()) && (ups.back () >= dps.ba ck ()); |
91 | 60 |
92 /* Do not merge notes typeset in different style. */ | 61 /* Do not merge notes typeset in different style. */ |
93 if (!ly_is_equal (head_up->get_property ("style"), | 62 if (!ly_is_equal (head_up->get_property ("style"), |
94 head_down->get_property ("style"))) | 63 head_down->get_property ("style"))) |
95 merge_possible = false; | 64 merge_possible = false; |
96 | 65 |
97 int up_ball_type = Rhythmic_head::duration_log (head_up); | 66 int up_ball_type = Rhythmic_head::duration_log (head_up); |
98 int down_ball_type = Rhythmic_head::duration_log (head_down); | 67 int down_ball_type = Rhythmic_head::duration_log (head_down); |
99 | 68 |
100 /* Do not merge whole notes (or longer, like breve, longa, maxima). */ | 69 /* Do not merge whole notes (or longer, like breve, longa, maxima). */ |
101 if (merge_possible && (up_ball_type <= 0 || down_ball_type <= 0)) | 70 if (merge_possible && (up_ball_type <= 0 || down_ball_type <= 0)) |
102 merge_possible = false; | 71 merge_possible = false; |
103 | 72 |
73 /* Don't merge differently dotted notes, unless merge-differently-dotted is se t */ | |
104 if (merge_possible | 74 if (merge_possible |
105 && Rhythmic_head::dot_count (head_up) != Rhythmic_head::dot_count (head_do wn) | 75 && Rhythmic_head::dot_count (head_up) != Rhythmic_head::dot_count (head_do wn) |
106 && !to_boolean (me->get_property ("merge-differently-dotted"))) | 76 && !to_boolean (me->get_property ("merge-differently-dotted"))) |
107 merge_possible = false; | 77 merge_possible = false; |
108 | 78 |
109 /* Can only merge different heads if merge-differently-headed is set. */ | 79 /* Can only merge different heads if merge-differently-headed is set. */ |
110 if (merge_possible | 80 if (merge_possible |
111 && up_ball_type != down_ball_type | 81 && up_ball_type != down_ball_type |
112 && !to_boolean (me->get_property ("merge-differently-headed"))) | 82 && !to_boolean (me->get_property ("merge-differently-headed"))) |
113 merge_possible = false; | 83 merge_possible = false; |
(...skipping 17 matching lines...) Expand all Loading... | |
131 * | 101 * |
132 * the noteheads may be closer than this case (close half collide) | 102 * the noteheads may be closer than this case (close half collide) |
133 * | 103 * |
134 * | | 104 * | |
135 * | | 105 * | |
136 * x | 106 * x |
137 * x | 107 * x |
138 * | | 108 * | |
139 * | | 109 * | |
140 * | 110 * |
141 */ | 111 */ |
142 | 112 |
143 bool close_half_collide = false; | 113 bool close_half_collide = false; |
144 bool distant_half_collide = false; | 114 bool distant_half_collide = false; |
145 bool full_collide = false; | 115 bool full_collide = false; |
146 | 116 |
147 for (vsize i = 0, j = 0; i < ups.size () && j < dps.size ();) | 117 for (vsize i = 0, j = 0; i < ups.size () && j < dps.size ();) |
148 { | 118 { |
149 if (abs (ups[i] - dps[j]) == 1) | 119 if (abs (ups[i] - dps[j]) == 1) |
150 { | 120 { |
151 merge_possible = false; | 121 merge_possible = false; |
(...skipping 16 matching lines...) Expand all Loading... | |
168 else | 138 else |
169 { | 139 { |
170 i++; | 140 i++; |
171 j++; | 141 j++; |
172 } | 142 } |
173 } | 143 } |
174 | 144 |
175 full_collide = full_collide || (close_half_collide | 145 full_collide = full_collide || (close_half_collide |
176 && distant_half_collide); | 146 && distant_half_collide); |
177 | 147 |
148 return Collision_type(merge_possible, full_collide, close_half_collide, | |
149 distant_half_collide, up_ball_type, down_ball_type); | |
150 } | |
151 | |
152 void | |
153 check_meshing_chords (Grob *me, | |
154 Drul_array<vector<Real> > *offsets, | |
155 Drul_array<vector<Slice> > const &extents, | |
156 Drul_array<vector<Grob *> > const &clash_groups) | |
157 | |
158 { | |
159 if (!extents[UP].size () || !extents[DOWN].size ()) | |
160 return; | |
161 | |
162 Grob *clash_up = clash_groups[UP][0]; | |
163 Grob *clash_down = clash_groups[DOWN][0]; | |
164 | |
165 /* Every note column should have a stem, but avoid a crash. */ | |
166 if (!Note_column::get_stem (clash_up) || !Note_column::get_stem (clash_down)) | |
167 return; | |
168 | |
169 Drul_array<Grob *> stems (Note_column::get_stem (clash_down), | |
170 Note_column::get_stem (clash_up)); | |
171 | |
172 Grob *head_up = Note_column::first_head (clash_up); | |
173 Grob *head_down = Note_column::first_head (clash_down); | |
174 | |
175 /* Staff-positions of all noteheads on each stem */ | |
176 vector<int> ups = Stem::note_head_positions (stems[UP]); | |
177 vector<int> dps = Stem::note_head_positions (stems[DOWN]); | |
178 | |
179 /* Too far apart to collide. */ | |
180 if (ups.front () > dps.back () + 1) | |
181 return; | |
182 | |
183 /* If the chords just 'touch' their extreme noteheads, | |
184 then we can align their stems. | |
185 */ | |
186 bool touch = false; | |
187 if (ups[0] >= dps.back () | |
188 && (dps.size () < 2 || ups[0] >= dps[dps.size () - 2] + 2) | |
189 && (ups.size () < 2 || ups[1] >= dps.back () + 2)) | |
190 touch = true; | |
191 | |
192 Collision_type collision_type = | |
193 determine_collision_type(me, stems, ups, dps, head_up, head_down); | |
194 | |
195 // bool merge_possible = collision_type.merge_possible; | |
196 // bool full_collide = collision_type.full_collide; | |
197 // bool close_half_collide = colli | |
198 | |
199 Real shift_amount = 1; | |
200 bool stem_to_stem = false; // stem_to_stem means that stems from notes from tw o chords would overlap: | |
201 | |
202 /* | | | |
203 * |O | O | |
204 * | => || | |
205 * O| O | | |
206 * | | | |
207 */ | |
208 | |
209 | |
178 /* Determine which chord goes on the left, and which goes right. | 210 /* Determine which chord goes on the left, and which goes right. |
179 Up-stem usually goes on the right, but if chords just 'touch' we can put | 211 Up-stem usually goes on the right, but if chords just 'touch' we can put |
180 both stems on a common vertical line. In the presense of collisions, | 212 both stems on a common vertical line. In the presense of collisions, |
181 right hand heads may obscure dots, so dotted heads to go the right. | 213 right hand heads may obscure dots, so dotted heads to go the right. |
182 */ | 214 */ |
183 Real shift_amount = 1; | 215 if ((collision_type.full_collide |
184 bool stem_to_stem = false; | 216 || ((collision_type.close_half_collide || collision_type.distant_half_col lide) |
185 if ((full_collide | |
186 || ((close_half_collide || distant_half_collide) | |
187 && to_boolean (me->get_property ("prefer-dotted-right")))) | 217 && to_boolean (me->get_property ("prefer-dotted-right")))) |
188 && Rhythmic_head::dot_count (head_up) < Rhythmic_head::dot_count (head_dow n)) | 218 && Rhythmic_head::dot_count (head_up) < Rhythmic_head::dot_count (head_dow n)) |
189 { | 219 { |
190 shift_amount = -1; | 220 shift_amount = -1; |
191 if (!touch) | 221 if (!touch) |
192 // remember to leave clearance between stems | 222 // remember to leave clearance between stems |
193 stem_to_stem = true; | 223 stem_to_stem = true; |
194 } | 224 } |
195 else if (touch) | 225 else if (touch) |
196 { | 226 { |
197 // Up-stem note on a line has a raised dot, so no risk of collision | 227 // Up-stem note on a line has a raised dot, so no risk of collision |
198 Grob *staff = Staff_symbol_referencer::get_staff_symbol (me); | 228 Grob *staff = Staff_symbol_referencer::get_staff_symbol (me); |
199 if ((full_collide | 229 if ((collision_type.full_collide |
200 || (!Staff_symbol_referencer::on_line (staff, ups[0]) | 230 || (!Staff_symbol_referencer::on_line (staff, ups[0]) |
201 && to_boolean (me->get_property ("prefer-dotted-right")))) | 231 && to_boolean (me->get_property ("prefer-dotted-right")))) |
202 && Rhythmic_head::dot_count (head_up) > Rhythmic_head::dot_count (head _down)) | 232 && Rhythmic_head::dot_count (head_up) > Rhythmic_head::dot_count (head _down)) |
203 touch = false; | 233 touch = false; |
204 else | 234 else |
205 shift_amount = -1; | 235 shift_amount = -1; |
206 } | 236 } |
207 | 237 |
208 /* The solfa is a triangle, which is inverted depending on stem | 238 /* The solfa is a triangle, which is inverted depending on stem |
Milimetr88
2012/04/14 13:56:18
What does solfa mean? I couldn't find it on Google
Keith
2012/04/14 19:12:01
Solfège. Here it was probably a typo for "The fa
| |
209 direction. In case of a collision, one of them should be removed, | 239 direction. In case of a collision, one of them should be removed, |
210 so the resulting note does not look like a block. | 240 so the resulting note does not look like a block. |
211 */ | 241 */ |
212 SCM up_style = head_up->get_property ("style"); | 242 SCM up_style = head_up->get_property ("style"); |
213 SCM down_style = head_down->get_property ("style"); | 243 SCM down_style = head_down->get_property ("style"); |
214 if (merge_possible | 244 if (collision_type.merge_possible |
215 && (up_style == ly_symbol2scm ("fa") || up_style == ly_symbol2scm ("faThin ")) | 245 && (up_style == ly_symbol2scm ("fa") || up_style == ly_symbol2scm ("faThin ")) |
216 && (down_style == ly_symbol2scm ("fa") || down_style == ly_symbol2scm ("fa Thin"))) | 246 && (down_style == ly_symbol2scm ("fa") || down_style == ly_symbol2scm ("fa Thin"))) |
217 { | 247 { |
218 Offset att = Offset (0.0, -1.0); | 248 Offset att = Offset (0.0, -1.0); |
219 head_up->set_property ("stem-attachment", ly_offset2scm (att)); | 249 head_up->set_property ("stem-attachment", ly_offset2scm (att)); |
220 head_up->set_property ("transparent", SCM_BOOL_T); | 250 head_up->set_property ("transparent", SCM_BOOL_T); |
221 } | 251 } |
222 | 252 |
223 if (merge_possible) | 253 if (collision_type.merge_possible) |
224 { | 254 { |
225 shift_amount = 0; | 255 shift_amount = 0; |
226 | 256 |
227 /* If possible, don't wipe any heads. Else, wipe shortest head, | 257 /* If possible, don't wipe any heads. Else, wipe shortest head, |
228 or head with smallest amount of dots. Note: when merging | 258 or head with smallest amount of dots. Note: when merging |
229 different heads, dots on the smaller one disappear. */ | 259 different heads, dots on the smaller one disappear. */ |
230 Grob *wipe_ball = 0; | 260 Grob *wipe_ball = 0; |
231 Grob *dot_wipe_head = head_up; | 261 Grob *dot_wipe_head = head_up; |
232 | 262 |
233 if (up_ball_type == down_ball_type) | 263 if (collision_type.up_ball_type == collision_type.down_ball_type) |
234 { | 264 { |
235 if (Rhythmic_head::dot_count (head_down) < Rhythmic_head::dot_count (h ead_up)) | 265 if (Rhythmic_head::dot_count (head_down) < Rhythmic_head::dot_count (h ead_up)) |
236 { | 266 { |
237 wipe_ball = head_down; | 267 wipe_ball = head_down; |
238 dot_wipe_head = head_down; | 268 dot_wipe_head = head_down; |
239 } | 269 } |
240 else if (Rhythmic_head::dot_count (head_down) > Rhythmic_head::dot_cou nt (head_up)) | 270 else if (Rhythmic_head::dot_count (head_down) > Rhythmic_head::dot_cou nt (head_up)) |
241 { | 271 { |
242 dot_wipe_head = head_up; | 272 dot_wipe_head = head_up; |
243 wipe_ball = head_up; | 273 wipe_ball = head_up; |
244 } | 274 } |
245 else | 275 else |
246 dot_wipe_head = head_up; | 276 dot_wipe_head = head_up; |
247 } | 277 } |
248 else if (down_ball_type > up_ball_type) | 278 else if (collision_type.down_ball_type > collision_type.up_ball_type) |
249 { | 279 { |
250 wipe_ball = head_down; | 280 wipe_ball = head_down; |
251 dot_wipe_head = head_down; | 281 dot_wipe_head = head_down; |
252 } | 282 } |
253 else if (down_ball_type < up_ball_type) | 283 else if (collision_type.down_ball_type < collision_type.up_ball_type) |
254 { | 284 { |
255 wipe_ball = head_up; | 285 wipe_ball = head_up; |
256 dot_wipe_head = head_up; | 286 dot_wipe_head = head_up; |
257 /* | 287 /* |
258 If upper head is eighth note or shorter, and lower head is half note , | 288 If upper head is eighth note or shorter, and lower head is half note , |
259 shift by the difference between the open and filled note head widths , | 289 shift by the difference between the open and filled note head widths , |
260 otherwise upper stem will be misaligned slightly. | 290 otherwise upper stem will be misaligned slightly. |
261 */ | 291 */ |
262 if (Stem::duration_log (stems[DOWN]) == 1 | 292 if (Stem::duration_log (stems[DOWN]) == 1 |
263 && Stem::duration_log (stems[UP]) >= 3) | 293 && Stem::duration_log (stems[UP]) >= 3) |
264 shift_amount = (1 - head_up->extent (head_up, X_AXIS).length () | 294 shift_amount = (1 - head_up->extent (head_up, X_AXIS).length () |
265 / head_down->extent (head_down, X_AXIS).length ()) * 0.5; | 295 / head_down->extent (head_down, X_AXIS).length ()) * 0.5; |
266 } | 296 } |
267 | 297 |
268 if (dot_wipe_head) | 298 if (dot_wipe_head) |
269 { | 299 { |
270 if (Grob *d = unsmob_grob (dot_wipe_head->get_object ("dot"))) | 300 if (Grob *d = unsmob_grob (dot_wipe_head->get_object ("dot"))) |
271 d->suicide (); | 301 d->suicide (); |
272 } | 302 } |
273 | 303 |
274 if (wipe_ball && wipe_ball->is_live ()) | 304 if (wipe_ball && wipe_ball->is_live ()) |
275 wipe_ball->set_property ("transparent", SCM_BOOL_T); | 305 wipe_ball->set_property ("transparent", SCM_BOOL_T); |
276 } | 306 } |
307 | |
308 /* | |
309 shift_amount should depend on line thickness, not staff space, at least in | |
310 some cases (like stem-to-stem, where it should be bigger for smaller font si ze) | |
311 */ | |
312 | |
277 /* TODO: these numbers are magic; should devise a set of grob props | 313 /* TODO: these numbers are magic; should devise a set of grob props |
278 to tune this behavior. */ | 314 to tune this behavior. */ |
279 else if (stem_to_stem) | 315 else if (stem_to_stem) |
280 shift_amount *= 0.65; | 316 shift_amount *= 0.65; |
281 else if (touch) | 317 else if (touch) |
282 shift_amount *= 0.5; | 318 shift_amount *= 0.5; |
283 else if (close_half_collide) | 319 else if (collision_type.close_half_collide) |
284 shift_amount *= 0.52; | 320 shift_amount *= 0.52; |
285 else if (full_collide) | 321 else if (collision_type.full_collide) |
286 shift_amount *= 0.5; | 322 shift_amount *= 0.5; |
287 else if (distant_half_collide) | 323 else if (collision_type.distant_half_collide) |
288 shift_amount *= 0.4; | 324 shift_amount *= 0.4; |
289 | 325 |
290 /* we're meshing. */ | 326 /* we're meshing. */ |
291 else if (Rhythmic_head::dot_count (head_up) || Rhythmic_head::dot_count (head_ down)) | 327 else if (Rhythmic_head::dot_count (head_up) || Rhythmic_head::dot_count (head_ down)) |
292 shift_amount *= 0.1; | 328 shift_amount *= 0.1; |
293 else | 329 else |
294 shift_amount *= 0.17; | 330 shift_amount *= 0.17; |
295 | 331 |
296 /* | 332 /* |
297 */ | 333 */ |
298 if (full_collide | 334 if (collision_type.full_collide |
299 && down_ball_type *up_ball_type == 0) | 335 && collision_type.down_ball_type * collision_type.up_ball_type == 0) |
300 { | 336 { |
301 if (up_ball_type == 0 && down_ball_type == 1) | 337 if (collision_type.up_ball_type == 0 && collision_type.down_ball_type == 1 ) |
302 shift_amount *= 1.25; | 338 shift_amount *= 1.25; |
303 else if (up_ball_type == 0 && down_ball_type == 2) | 339 else if (collision_type.up_ball_type == 0 && collision_type.down_ball_type == 2) |
304 shift_amount *= 1.35; | 340 shift_amount *= 1.35; |
305 else if (down_ball_type == 0 && up_ball_type == 1) | 341 else if (collision_type.down_ball_type == 0 && collision_type.up_ball_type == 1) |
306 shift_amount *= 0.7; | 342 shift_amount *= 0.7; |
307 else if (down_ball_type == 0 && up_ball_type == 2) | 343 else if (collision_type.down_ball_type == 0 && collision_type.up_ball_type == 2) |
308 shift_amount *= 0.75; | 344 shift_amount *= 0.75; |
309 } | 345 } |
310 | 346 |
311 /* If any dotted notes ended up on the left, | 347 /* If any dotted notes ended up on the left, |
312 tell the Dot_Columnn to avoid the note heads on the right. | 348 tell the Dot_Columnn to avoid the note heads on the right. |
313 */ | 349 */ |
314 if (shift_amount < -1e-6 | 350 if (shift_amount < -1e-6 |
315 && Rhythmic_head::dot_count (head_up)) | 351 && Rhythmic_head::dot_count (head_up)) |
316 { | 352 { |
317 Grob *d = unsmob_grob (head_up->get_object ("dot")); | 353 Grob *d = unsmob_grob (head_up->get_object ("dot")); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
353 if (dir != CENTER) | 389 if (dir != CENTER) |
354 { | 390 { |
355 Grob *stem = unsmob_grob (head_down->get_object ("stem")); | 391 Grob *stem = unsmob_grob (head_down->get_object ("stem")); |
356 extract_grob_set (stem, "note-heads", heads); | 392 extract_grob_set (stem, "note-heads", heads); |
357 for (vsize i = 0; i < heads.size (); i++) | 393 for (vsize i = 0; i < heads.size (); i++) |
358 unsmob_grob (heads[i]->get_object ("dot")) | 394 unsmob_grob (heads[i]->get_object ("dot")) |
359 ->set_property ("direction", scm_from_int (dir)); | 395 ->set_property ("direction", scm_from_int (dir)); |
360 } | 396 } |
361 } | 397 } |
362 | 398 |
363 Direction d = UP; | 399 |
364 do | 400 /* |
401 Update positions of clashing chords. | |
402 Move up-stem chord to the right and down-stem chord to the left by shift_amou nt. | |
403 */ | |
404 for_UP_and_DOWN (d) | |
Keith
2012/03/31 21:04:35
The code-indenting program we use
http://astyle.
Graham Percival
2012/04/01 05:00:25
Ouch. I don't find that for loop to be particular
Milimetr88
2012/04/14 13:56:18
Ok, could I assume that you will take care of mody
| |
365 { | 405 { |
366 for (vsize i = 0; i < clash_groups[d].size (); i++) | 406 for (vsize i = 0; i < clash_groups[d].size (); i++) |
367 (*offsets)[d][i] += d * shift_amount; | 407 (*offsets)[d][i] += d * shift_amount; |
368 } | 408 } |
369 while ((flip (&d)) != UP); | 409 |
370 } | 410 } |
371 | 411 |
412 | |
372 MAKE_SCHEME_CALLBACK (Note_collision_interface, calc_positioning_done, 1) | 413 MAKE_SCHEME_CALLBACK (Note_collision_interface, calc_positioning_done, 1) |
373 SCM | 414 SCM |
374 Note_collision_interface::calc_positioning_done (SCM smob) | 415 Note_collision_interface::calc_positioning_done (SCM smob) |
375 { | 416 { |
376 Grob *me = unsmob_grob (smob); | 417 Grob *me = unsmob_grob (smob); |
377 me->set_property ("positioning-done", SCM_BOOL_T); | 418 me->set_property ("positioning-done", SCM_BOOL_T); |
378 | 419 |
379 Drul_array<vector<Grob *> > clash_groups = get_clash_groups (me); | 420 Drul_array<vector<Grob *> > clash_groups = get_clash_groups (me); |
380 | 421 |
381 Direction d = UP; | 422 for_UP_and_DOWN (d) |
382 do | |
383 { | 423 { |
384 for (vsize i = clash_groups[d].size (); i--;) | 424 for (vsize i = clash_groups[d].size (); i--;) |
385 { | 425 { |
386 /* | 426 /* |
387 Trigger positioning | 427 Trigger positioning |
388 */ | 428 */ |
389 clash_groups[d][i]->extent (me, X_AXIS); | 429 clash_groups[d][i]->extent (me, X_AXIS); |
390 } | 430 } |
391 } | 431 } |
392 while (flip (&d) != UP); | |
393 | 432 |
394 SCM autos (automatic_shift (me, clash_groups)); | 433 SCM autos (automatic_shift (me, clash_groups)); |
395 SCM hand (forced_shift (me)); | 434 SCM hand (forced_shift (me)); |
396 | 435 |
397 Real wid = 0.0; | 436 Real wid = 0.0; |
398 do | 437 |
438 for_UP_and_DOWN (d) | |
399 { | 439 { |
400 if (clash_groups[d].size ()) | 440 if (clash_groups[d].size ()) |
401 { | 441 { |
402 Grob *h = clash_groups[d][0]; | 442 Grob *h = clash_groups[d][0]; |
403 Grob *fh = Note_column::first_head (h); | 443 Grob *fh = Note_column::first_head (h); |
404 if (fh) | 444 if (fh) |
405 wid = fh->extent (h, X_AXIS).length (); | 445 wid = fh->extent (h, X_AXIS).length (); |
406 } | 446 } |
407 } | 447 } |
408 while (flip (&d) != UP); | |
409 | 448 |
410 vector<Grob *> done; | 449 vector<Grob *> done; |
411 Real left_most = 1e6; | 450 Real left_most = 1e6; |
412 | 451 |
413 vector<Real> amounts; | 452 vector<Real> amounts; |
414 for (; scm_is_pair (hand); hand = scm_cdr (hand)) | 453 for (; scm_is_pair (hand); hand = scm_cdr (hand)) |
415 { | 454 { |
416 Grob *s = unsmob_grob (scm_caar (hand)); | 455 Grob *s = unsmob_grob (scm_caar (hand)); |
417 Real amount = scm_to_double (scm_cdar (hand)) * wid; | 456 Real amount = scm_to_double (scm_cdar (hand)) * wid; |
418 | 457 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 Grob *se = elements[i]; | 492 Grob *se = elements[i]; |
454 if (Note_column::has_interface (se)) | 493 if (Note_column::has_interface (se)) |
455 { | 494 { |
456 if (!Note_column::dir (se)) | 495 if (!Note_column::dir (se)) |
457 se->programming_error ("note-column has no direction"); | 496 se->programming_error ("note-column has no direction"); |
458 else | 497 else |
459 clash_groups[Note_column::dir (se)].push_back (se); | 498 clash_groups[Note_column::dir (se)].push_back (se); |
460 } | 499 } |
461 } | 500 } |
462 | 501 |
463 Direction d = UP; | 502 for_UP_and_DOWN (d) |
464 do | |
465 { | 503 { |
466 vector<Grob *> &clashes (clash_groups[d]); | 504 vector<Grob *> &clashes (clash_groups[d]); |
467 vector_sort (clashes, Note_column::shift_less); | 505 vector_sort (clashes, Note_column::shift_less); |
468 } | 506 } |
469 while ((flip (&d)) != UP); | |
470 | 507 |
471 return clash_groups; | 508 return clash_groups; |
472 } | 509 } |
473 | 510 |
474 /* | 511 /* |
475 This complicated routine moves note columns around horizontally to | 512 This complicated routine moves note columns around horizontally to |
476 ensure that notes don't clash. | 513 ensure that notes don't clash. |
477 */ | 514 */ |
478 SCM | 515 SCM |
479 Note_collision_interface::automatic_shift (Grob *me, | 516 Note_collision_interface::automatic_shift (Grob *me, |
480 Drul_array<vector<Grob *> > clash_gro ups) | 517 Drul_array<vector<Grob *> > clash_gro ups) |
481 { | 518 { |
482 Drul_array < vector<int> > shifts; | 519 Drul_array < vector<int> > shifts; |
483 SCM tups = SCM_EOL; | 520 SCM tups = SCM_EOL; |
484 | 521 |
485 Direction d = UP; | 522 for_UP_and_DOWN (d) |
486 do | |
487 { | 523 { |
488 vector<int> &shift (shifts[d]); | 524 vector<int> &shift (shifts[d]); |
489 vector<Grob *> &clashes (clash_groups[d]); | 525 vector<Grob *> &clashes (clash_groups[d]); |
490 | 526 |
491 for (vsize i = 0; i < clashes.size (); i++) | 527 for (vsize i = 0; i < clashes.size (); i++) |
492 { | 528 { |
493 SCM sh | 529 SCM sh |
494 = clashes[i]->get_property ("horizontal-shift"); | 530 = clashes[i]->get_property ("horizontal-shift"); |
495 | 531 |
496 if (scm_is_number (sh)) | 532 if (scm_is_number (sh)) |
497 shift.push_back (scm_to_int (sh)); | 533 shift.push_back (scm_to_int (sh)); |
498 else | 534 else |
499 shift.push_back (0); | 535 shift.push_back (0); |
500 } | 536 } |
501 | 537 |
502 for (vsize i = 1; i < shift.size (); i++) | 538 for (vsize i = 1; i < shift.size (); i++) |
503 { | 539 { |
504 if (shift[i - 1] == shift[i]) | 540 if (shift[i - 1] == shift[i]) |
505 { | 541 { |
506 clashes[0]->warning (_ ("ignoring too many clashing note columns") ); | 542 clashes[0]->warning (_ ("ignoring too many clashing note columns") ); |
507 return tups; | 543 return tups; |
508 } | 544 } |
509 } | 545 } |
510 } | 546 } |
511 while ((flip (&d)) != UP); | |
512 | 547 |
513 Drul_array<vector<Slice> > extents; | 548 Drul_array<vector<Slice> > extents; // vertical extents |
514 Drul_array<vector<Real> > offsets; | 549 Drul_array<vector<Real> > offsets; |
515 d = UP; | 550 |
516 do | 551 for_UP_and_DOWN (d) |
517 { | 552 { |
518 for (vsize i = 0; i < clash_groups[d].size (); i++) | 553 for (vsize i = 0; i < clash_groups[d].size (); i++) |
519 { | 554 { |
520 Slice s (Note_column::head_positions_interval (clash_groups[d][i])); | 555 Slice s (Note_column::head_positions_interval (clash_groups[d][i])); |
521 s[LEFT]--; | 556 /* |
522 s[RIGHT]++; | 557 * s gets extents in posititions, but a single note head |
558 * occupies 3 positions, since the symbol has thickness, | |
559 * hence the -- and ++ | |
560 */ | |
561 s[DOWN]--; | |
562 s[UP]++; | |
523 extents[d].push_back (s); | 563 extents[d].push_back (s); |
524 offsets[d].push_back (d * 0.5 * i); | 564 offsets[d].push_back (d * 0.5 * i); |
525 } | 565 } |
526 } | 566 } |
527 while ((flip (&d)) != UP); | |
528 | 567 |
529 /* | 568 /* |
530 * do horizontal shifts of each direction | 569 * do horizontal shifts of each direction |
531 * | 570 * |
532 * | | 571 * | |
533 * x|| | 572 * x|| |
534 * x|| | 573 * x|| |
535 * x| | 574 * x| |
536 */ | 575 */ |
537 | 576 |
538 do | 577 for_UP_and_DOWN (d) // please, make a comment to this loop (better than the ab ove one...) |
Graham Percival
2012/04/01 05:00:25
adding a comment to say "please comment this" does
Milimetr88
2012/04/14 13:56:18
Once again, what could be done to get a comment to
| |
539 { | 578 { |
540 for (vsize i = 1; i < clash_groups[d].size (); i++) | 579 for (vsize i = 1; i < clash_groups[d].size (); i++) |
541 { | 580 { |
542 Slice prev = extents[d][i - 1]; | 581 Slice prev = extents[d][i - 1]; |
543 prev.intersect (extents[d][i]); | 582 prev.intersect (extents[d][i]); |
544 if (prev.length () > 0 | 583 if (prev.length () > 0 |
545 || (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0] [d]) < 0)) | 584 || (extents[-d].size () && d * (extents[d][i][-d] - extents[-d][0] [d]) < 0)) // please, comment this condition |
Milimetr88
2012/04/14 14:36:23
I'll delete that one day ;)
| |
546 for (vsize j = i; j < clash_groups[d].size (); j++) | 585 for (vsize j = i; j < clash_groups[d].size (); j++) |
547 offsets[d][j] += d * 0.5; | 586 offsets[d][j] += d * 0.5; |
548 } | 587 } |
549 } | 588 } |
550 while ((flip (&d)) != UP); | |
551 | 589 |
552 /* | 590 /* |
553 see input/regression/dot-up-voice-collision.ly | 591 see input/regression/dot-up-voice-collision.ly |
554 */ | 592 */ |
555 for (vsize i = 0; i < clash_groups[UP].size (); i++) | 593 for (vsize i = 0; i < clash_groups[UP].size (); i++) |
556 { | 594 { |
557 Grob *g = clash_groups[UP][i]; | 595 Grob *g = clash_groups[UP][i]; |
558 Grob *dc = Note_column::dot_column (g); | 596 Grob *dc = Note_column::dot_column (g); |
559 | 597 |
560 if (dc) | 598 if (dc) |
561 for (vsize j = i + 1; j < clash_groups[UP].size (); j++) | 599 for (vsize j = i + 1; j < clash_groups[UP].size (); j++) |
562 { | 600 { |
563 Grob *stem = Note_column::get_stem (clash_groups[UP][j]); | 601 Grob *stem = Note_column::get_stem (clash_groups[UP][j]); |
564 Side_position_interface::add_support (dc, stem); | 602 Side_position_interface::add_support (dc, stem); |
565 } | 603 } |
566 } | 604 } |
567 | 605 |
568 /* | 606 /* |
569 Check if chords are meshing | 607 Check if chords are meshing |
570 */ | 608 */ |
571 | 609 |
572 check_meshing_chords (me, &offsets, extents, clash_groups); | 610 check_meshing_chords (me, &offsets, extents, clash_groups); |
573 | 611 |
574 do | 612 for_UP_and_DOWN (d) |
575 { | 613 { |
576 for (vsize i = 0; i < clash_groups[d].size (); i++) | 614 for (vsize i = 0; i < clash_groups[d].size (); i++) |
577 tups = scm_cons (scm_cons (clash_groups[d][i]->self_scm (), | 615 tups = scm_cons (scm_cons (clash_groups[d][i]->self_scm (), |
578 scm_from_double (offsets[d][i])), | 616 scm_from_double (offsets[d][i])), |
579 tups); | 617 tups); |
580 } | 618 } |
581 while (flip (&d) != UP); | |
582 | 619 |
583 return tups; | 620 return tups; |
584 } | 621 } |
585 | 622 |
586 SCM | 623 SCM |
587 Note_collision_interface::forced_shift (Grob *me) | 624 Note_collision_interface::forced_shift (Grob *me) |
588 { | 625 { |
589 SCM tups = SCM_EOL; | 626 SCM tups = SCM_EOL; |
590 | 627 |
591 extract_grob_set (me, "elements", elements); | 628 extract_grob_set (me, "elements", elements); |
(...skipping 22 matching lines...) Expand all Loading... | |
614 " the interesting properties are to be set in" | 651 " the interesting properties are to be set in" |
615 " @ref{note-column-interface}: these are @code{force-hshift}" | 652 " @ref{note-column-interface}: these are @code{force-hshift}" |
616 " and @code{horizontal-shift}.", | 653 " and @code{horizontal-shift}.", |
617 | 654 |
618 /* properties */ | 655 /* properties */ |
619 "merge-differently-dotted " | 656 "merge-differently-dotted " |
620 "merge-differently-headed " | 657 "merge-differently-headed " |
621 "positioning-done " | 658 "positioning-done " |
622 "prefer-dotted-right " | 659 "prefer-dotted-right " |
623 ); | 660 ); |
OLD | NEW |