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) 1998--2012 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 1998--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 |
11 LilyPond is distributed in the hope that it will be useful, | 11 LilyPond is distributed in the hope that it will be useful, |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 GNU General Public License for more details. | 14 GNU General Public License for more details. |
15 | 15 |
16 You should have received a copy of the GNU General Public License | 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/>. | 17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>. |
18 */ | 18 */ |
19 | 19 |
20 #include "side-position-interface.hh" | 20 #include "side-position-interface.hh" |
21 | 21 |
22 #include <cmath> // ceil. | 22 #include <cmath> // ceil. |
23 #include <algorithm> | 23 #include <algorithm> |
| 24 #include <map> |
24 | 25 |
25 using namespace std; | 26 using namespace std; |
26 | 27 |
27 #include "accidental-interface.hh" | 28 #include "accidental-interface.hh" |
28 #include "axis-group-interface.hh" | 29 #include "axis-group-interface.hh" |
29 #include "directional-element-interface.hh" | 30 #include "directional-element-interface.hh" |
30 #include "grob.hh" | 31 #include "grob.hh" |
31 #include "grob-array.hh" | 32 #include "grob-array.hh" |
32 #include "main.hh" | 33 #include "main.hh" |
33 #include "misc.hh" | 34 #include "misc.hh" |
34 #include "note-head.hh" | 35 #include "note-head.hh" |
| 36 #include "note-column.hh" |
35 #include "pointer-group-interface.hh" | 37 #include "pointer-group-interface.hh" |
36 #include "skyline-pair.hh" | 38 #include "skyline-pair.hh" |
37 #include "staff-symbol-referencer.hh" | 39 #include "staff-symbol-referencer.hh" |
38 #include "staff-symbol.hh" | 40 #include "staff-symbol.hh" |
39 #include "stem.hh" | 41 #include "stem.hh" |
40 #include "string-convert.hh" | 42 #include "string-convert.hh" |
41 #include "system.hh" | 43 #include "system.hh" |
42 #include "warn.hh" | 44 #include "warn.hh" |
43 | 45 |
44 void | 46 void |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 extract_grob_set (me, "side-support-elements", support); | 169 extract_grob_set (me, "side-support-elements", support); |
168 | 170 |
169 Grob *common[2]; | 171 Grob *common[2]; |
170 for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) | 172 for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) |
171 common[ax] = common_refpoint_of_array (support, ax == a ? me->get_parent (ax
) : me, ax); | 173 common[ax] = common_refpoint_of_array (support, ax == a ? me->get_parent (ax
) : me, ax); |
172 | 174 |
173 Grob *staff_symbol = Staff_symbol_referencer::get_staff_symbol (me); | 175 Grob *staff_symbol = Staff_symbol_referencer::get_staff_symbol (me); |
174 Direction dir = get_grob_direction (me); | 176 Direction dir = get_grob_direction (me); |
175 | 177 |
176 Skyline my_dim; | 178 Skyline my_dim; |
177 Real skyline_padding = 0.1; | 179 Skyline_pair *sp = Skyline_pair::unsmob (me->get_property ("vertical-skylines"
)); |
178 if (me->get_property_data ("vertical-skylines") != SCM_EOL | 180 if (sp && a == Y_AXIS && !pure) |
179 && a == Y_AXIS | 181 { |
180 && !pure) | 182 Skyline_pair copy = Skyline_pair (*sp); |
181 { | |
182 Skyline_pair copy = Skyline_pair (*Skyline_pair::unsmob (me->get_property
("vertical-skylines"))); | |
183 copy.shift (me->relative_coordinate (common[X_AXIS], X_AXIS)); | 183 copy.shift (me->relative_coordinate (common[X_AXIS], X_AXIS)); |
184 copy.raise (me->get_parent (X_AXIS)->relative_coordinate (common[Y_AXIS],
Y_AXIS)); | 184 copy.raise (me->get_parent (Y_AXIS)->relative_coordinate (common[Y_AXIS],
Y_AXIS)); |
185 my_dim = copy[-dir]; | 185 my_dim = copy[-dir]; |
186 } | 186 } |
187 else | 187 else |
188 { | 188 { |
189 Box off; | 189 Box off; |
190 for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) | 190 for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) |
191 { | 191 { |
192 if (ax == a) | 192 if (ax == a) |
193 off[ax] = me->get_parent (ax)->maybe_pure_coordinate (common[ax], ax
, pure, start, end) | 193 off[ax] = me->get_parent (ax)->maybe_pure_coordinate (common[ax], ax
, pure, start, end) |
194 + me->maybe_pure_extent (me, ax, pure, start, end); | 194 + me->maybe_pure_extent (me, ax, pure, start, end); |
195 else | 195 else |
196 off[ax] = me->maybe_pure_extent (common[ax], ax, pure, start, end); | 196 off[ax] = me->maybe_pure_extent (common[ax], ax, pure, start, end); |
197 } | 197 } |
198 | 198 |
199 if (off[X_AXIS].is_empty () || off[Y_AXIS].is_empty ()) | 199 if (off[X_AXIS].is_empty () || off[Y_AXIS].is_empty ()) |
200 return scm_from_double (0.0); | 200 return scm_from_double (0.0); |
201 | 201 |
202 my_dim = Skyline (off, skyline_padding, other_axis (a), -dir); | 202 my_dim = Skyline (off, other_axis (a), -dir); |
203 } | 203 } |
204 bool include_staff | 204 bool include_staff |
205 = staff_symbol | 205 = staff_symbol |
206 && a == Y_AXIS | 206 && a == Y_AXIS |
207 && scm_is_number (me->get_property ("staff-padding")) | 207 && scm_is_number (me->get_property ("staff-padding")) |
208 && !to_boolean (me->get_property ("quantize-position")); | 208 && !to_boolean (me->get_property ("quantize-position")); |
209 | 209 |
210 vector<Box> boxes; | 210 vector<Box> boxes; |
| 211 vector<Skyline_pair> skyps; |
211 Real min_h = dir == LEFT ? infinity_f : -infinity_f; | 212 Real min_h = dir == LEFT ? infinity_f : -infinity_f; |
| 213 map<Grob *, vector<Grob *> > note_column_map; // for parts of a note column |
212 for (vsize i = 0; i < support.size (); i++) | 214 for (vsize i = 0; i < support.size (); i++) |
213 { | 215 { |
214 Grob *e = support[i]; | 216 Grob *e = support[i]; |
215 | 217 |
216 // In the case of a stem, we will find a note head as well | 218 // In the case of a stem, we will find a note head as well |
217 // ignoring the stem solves cyclic dependencies if the stem is | 219 // ignoring the stem solves cyclic dependencies if the stem is |
218 // attached to a cross-staff beam. | 220 // attached to a cross-staff beam. |
219 if (a == Y_AXIS | 221 if (a == Y_AXIS |
220 && Stem::has_interface (e) | 222 && Stem::has_interface (e) |
221 && dir == - get_grob_direction (e)) | 223 && dir == - get_grob_direction (e)) |
222 continue; | 224 continue; |
223 | 225 |
224 if (e) | 226 if (e) |
225 { | 227 { |
226 if (Accidental_interface::has_interface (e)) | 228 if (Accidental_interface::has_interface (e)) |
227 { | 229 { |
228 vector<Box> bs = Accidental_interface::accurate_boxes (e, common); | 230 vector<Box> bs = Accidental_interface::accurate_boxes (e, common); |
229 boxes.insert (boxes.end (), bs.begin (), bs.end ()); | 231 boxes.insert (boxes.end (), bs.begin (), bs.end ()); |
230 } | 232 } |
231 else | 233 else |
232 { | 234 { |
| 235 if (Note_column::has_interface (e->get_parent (X_AXIS)) |
| 236 && to_boolean (me->get_property ("add-stem-support"))) |
| 237 { |
| 238 note_column_map[e->get_parent (X_AXIS)].push_back (e); |
| 239 continue; |
| 240 } |
| 241 |
| 242 Skyline_pair *sp = Skyline_pair::unsmob (e->get_property ("vertica
l-skylines")); |
| 243 if (sp && a == Y_AXIS && !pure) |
| 244 { |
| 245 Skyline_pair copy = Skyline_pair (*sp); |
| 246 copy.shift (e->relative_coordinate (common[X_AXIS], X_AXIS)); |
| 247 copy.raise (e->relative_coordinate (common[Y_AXIS], Y_AXIS)); |
| 248 skyps.push_back (copy); |
| 249 continue; |
| 250 } |
233 Box b; | 251 Box b; |
234 for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) | 252 for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) |
235 b[ax] = e->maybe_pure_extent (common[ax], ax, pure, start, end); | 253 b[ax] = e->maybe_pure_extent (common[ax], ax, pure, start, end); |
236 | 254 |
237 if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ()) | 255 if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ()) |
238 continue; | 256 continue; |
239 | 257 |
240 boxes.push_back (b); | 258 boxes.push_back (b); |
241 min_h = minmax (dir, b[a][-dir], min_h); | 259 min_h = minmax (dir, b[a][-dir], min_h); |
242 } | 260 } |
243 } | 261 } |
244 } | 262 } |
245 | 263 |
246 Skyline dim (boxes, skyline_padding, other_axis (a), dir); | 264 // this loop ensures that parts of a note column will be in the same box |
| 265 // pushes scripts and such over stems instead of just over heads |
| 266 for (map<Grob *, vector<Grob *> >::iterator i = note_column_map.begin (); i !=
note_column_map.end (); i++) |
| 267 { |
| 268 Box big; |
| 269 for (vsize j = 0; j < (*i).second.size (); j++) |
| 270 { |
| 271 Grob *e = (*i).second[j]; |
| 272 Box b; |
| 273 for (Axis ax = X_AXIS; ax < NO_AXES; incr (ax)) |
| 274 b[ax] = e->maybe_pure_extent (common[ax], ax, pure, start, end); |
| 275 |
| 276 if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ()) |
| 277 continue; |
| 278 |
| 279 big.unite (b); |
| 280 } |
| 281 if (!big[X_AXIS].is_empty () && !big[Y_AXIS].is_empty ()) |
| 282 boxes.push_back (big); |
| 283 } |
| 284 |
| 285 Skyline dim (boxes, other_axis (a), dir); |
| 286 if (skyps.size ()) |
| 287 { |
| 288 Skyline_pair merged (skyps); |
| 289 dim.merge (merged[dir]); |
| 290 } |
247 if (!boxes.size ()) | 291 if (!boxes.size ()) |
248 dim.set_minimum_height (0.0); | 292 dim.set_minimum_height (0.0); |
249 else | 293 else |
250 dim.set_minimum_height (min_h); | 294 dim.set_minimum_height (min_h); |
251 | 295 |
252 if (include_staff) | 296 if (include_staff) |
253 { | 297 { |
254 Interval staff_extents; | 298 Interval staff_extents; |
255 common[Y_AXIS] = staff_symbol->common_refpoint (common[Y_AXIS], Y_AXIS); | 299 common[Y_AXIS] = staff_symbol->common_refpoint (common[Y_AXIS], Y_AXIS); |
256 staff_extents = staff_symbol->maybe_pure_extent (common[Y_AXIS], Y_AXIS, p
ure, start, end); | 300 staff_extents = staff_symbol->maybe_pure_extent (common[Y_AXIS], Y_AXIS, p
ure, start, end); |
257 dim.set_minimum_height (minmax (dir, min_h, staff_extents[dir])); | 301 dim.set_minimum_height (minmax (dir, min_h, staff_extents[dir])); |
258 } | 302 } |
259 | 303 |
260 Real total_off = dir * dim.distance (my_dim); | 304 Real dist = dim.distance (my_dim, 0.1); // 0.1 m4g1c value...fix... |
| 305 Real total_off = !isinf (dist) ? dir * dist : 0.0; |
| 306 |
261 return finish_offset (me, dir, total_off, current_offset); | 307 return finish_offset (me, dir, total_off, current_offset); |
262 } | 308 } |
263 | 309 |
264 MAKE_SCHEME_CALLBACK (Side_position_interface, y_aligned_on_support_refpoints, 1
); | 310 MAKE_SCHEME_CALLBACK (Side_position_interface, y_aligned_on_support_refpoints, 1
); |
265 SCM | 311 SCM |
266 Side_position_interface::y_aligned_on_support_refpoints (SCM smob) | 312 Side_position_interface::y_aligned_on_support_refpoints (SCM smob) |
267 { | 313 { |
268 return general_side_position (unsmob_grob (smob), Y_AXIS, false, false, false,
0, 0, 0); | 314 return general_side_position (unsmob_grob (smob), Y_AXIS, false, false, false,
0, 0, 0); |
269 } | 315 } |
270 | 316 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 if (to_boolean (me->get_property ("quantize-position"))) | 400 if (to_boolean (me->get_property ("quantize-position"))) |
355 { | 401 { |
356 Grob *common = me->common_refpoint (staff, Y_AXIS); | 402 Grob *common = me->common_refpoint (staff, Y_AXIS); |
357 Real my_off = me->get_parent (Y_AXIS)->maybe_pure_coordinate (common,
Y_AXIS, pure, start, end); | 403 Real my_off = me->get_parent (Y_AXIS)->maybe_pure_coordinate (common,
Y_AXIS, pure, start, end); |
358 Real staff_off = staff->maybe_pure_coordinate (common, Y_AXIS, pure, s
tart, end); | 404 Real staff_off = staff->maybe_pure_coordinate (common, Y_AXIS, pure, s
tart, end); |
359 Real ss = Staff_symbol::staff_space (staff); | 405 Real ss = Staff_symbol::staff_space (staff); |
360 Real position = 2 * (my_off + o - staff_off) / ss; | 406 Real position = 2 * (my_off + o - staff_off) / ss; |
361 Real rounded = directed_round (position, dir); | 407 Real rounded = directed_round (position, dir); |
362 Grob *head = me->get_parent (X_AXIS); | 408 Grob *head = me->get_parent (X_AXIS); |
363 | 409 |
364 if (fabs (position) <= 2 * Staff_symbol_referencer::staff_radius (me)
+ 1 | 410 Interval staff_span = Staff_symbol::line_span (staff); |
| 411 staff_span.widen (1); |
| 412 if (staff_span.contains (position) |
365 /* In case of a ledger lines, quantize even if we're outside the s
taff. */ | 413 /* In case of a ledger lines, quantize even if we're outside the s
taff. */ |
366 || (Note_head::has_interface (head) | 414 || (Note_head::has_interface (head) |
367 | 415 |
368 && abs (Staff_symbol_referencer::get_position (head)) > abs (p
osition))) | 416 && abs (Staff_symbol_referencer::get_position (head)) > abs (p
osition))) |
369 { | 417 { |
370 o += (rounded - position) * 0.5 * ss; | 418 o += (rounded - position) * 0.5 * ss; |
371 if (Staff_symbol_referencer::on_line (me, int (rounded))) | 419 if (Staff_symbol_referencer::on_line (me, int (rounded))) |
372 o += dir * 0.5 * ss; | 420 o += dir * 0.5 * ss; |
373 } | 421 } |
374 } | 422 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 "Position a victim object (this one) next to other objects" | 516 "Position a victim object (this one) next to other objects" |
469 " (the support). The property @code{direction} signifies where" | 517 " (the support). The property @code{direction} signifies where" |
470 " to put the victim object relative to the support (left or" | 518 " to put the victim object relative to the support (left or" |
471 " right, up or down?)\n" | 519 " right, up or down?)\n" |
472 "\n" | 520 "\n" |
473 "The routine also takes the size of the staff into account if" | 521 "The routine also takes the size of the staff into account if" |
474 " @code{staff-padding} is set. If undefined, the staff symbol" | 522 " @code{staff-padding} is set. If undefined, the staff symbol" |
475 " is ignored.", | 523 " is ignored.", |
476 | 524 |
477 /* properties */ | 525 /* properties */ |
| 526 "add-stem-support " |
478 "direction " | 527 "direction " |
479 "minimum-space " | 528 "minimum-space " |
480 "padding " | 529 "padding " |
481 "quantize-position " | 530 "quantize-position " |
482 "side-axis " | 531 "side-axis " |
483 "side-support-elements " | 532 "side-support-elements " |
484 "slur-padding " | 533 "slur-padding " |
485 "staff-padding " | 534 "staff-padding " |
486 "use-skylines " | 535 "use-skylines " |
487 ); | 536 ); |
LEFT | RIGHT |