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--2019 Han-Wen Nienhuys <hanwen@xs4all.nl> | 4 Copyright (C) 1997--2019 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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 here = alignment_off; | 250 here = alignment_off; |
251 for (vsize i = 0; i < offsets.size (); i++) | 251 for (vsize i = 0; i < offsets.size (); i++) |
252 { | 252 { |
253 here += offsets[i]; | 253 here += offsets[i]; |
254 elems[i]->translate_axis (here, X_AXIS); | 254 elems[i]->translate_axis (here, X_AXIS); |
255 } | 255 } |
256 | 256 |
257 return SCM_BOOL_T; | 257 return SCM_BOOL_T; |
258 } | 258 } |
259 | 259 |
260 MAKE_SCHEME_CALLBACK (Break_alignable_interface, self_align_callback, 1) | 260 Grob* |
261 SCM | 261 Break_alignable_interface::find_parent (Grob* me) |
262 Break_alignable_interface::self_align_callback (SCM grob) | |
263 { | 262 { |
264 Grob *me = unsmob<Grob> (grob); | |
265 Item *alignment = dynamic_cast<Item *> (me->get_parent (X_AXIS)); | 263 Item *alignment = dynamic_cast<Item *> (me->get_parent (X_AXIS)); |
266 if (!has_interface<Break_alignment_interface> (alignment)) | 264 if (!has_interface<Break_alignment_interface> (alignment)) |
267 return scm_from_int (0); | 265 return 0; |
268 | 266 |
269 SCM symbol_list = me->get_property ("break-align-symbols"); | 267 SCM symbol_list = me->get_property ("break-align-symbols"); |
270 vector<Grob *> elements = Break_alignment_interface::ordered_elements (alignme
nt); | 268 vector<Grob *> elements = Break_alignment_interface::ordered_elements (alignme
nt); |
271 if (elements.size () == 0) | 269 if (elements.size () == 0) |
272 return scm_from_int (0); | 270 return 0; |
273 | 271 |
274 int break_aligned_grob = -1; | 272 Grob *break_aligned_grob = 0; |
275 for (; scm_is_pair (symbol_list); symbol_list = scm_cdr (symbol_list)) | 273 for (; scm_is_pair (symbol_list); symbol_list = scm_cdr (symbol_list)) |
276 { | 274 { |
277 SCM sym = scm_car (symbol_list); | 275 SCM sym = scm_car (symbol_list); |
278 for (vsize i = 0; i < elements.size (); i++) | 276 for (vsize i = 0; i < elements.size (); i++) |
279 { | 277 { |
280 if (scm_is_eq (sym, elements[i]->get_property ("break-align-symbol"))) | 278 if (scm_is_eq (sym, elements[i]->get_property ("break-align-symbol"))) |
281 { | 279 { |
282 if (Item::break_visible (elements[i]) | 280 if (Item::break_visible (elements[i]) |
283 // TODO SCM: simplify syntax? | 281 // TODO SCM: simplify syntax? |
284 && !elements[i]->extent (elements[i], X_AXIS).is_empty ()) | 282 && !elements[i]->extent (elements[i], X_AXIS).is_empty ()) |
285 { | 283 { |
286 break_aligned_grob = i; | 284 return elements[i]; |
287 goto found_break_aligned_grob; /* ugh. need to break out of 2
loops */ | |
288 } | 285 } |
289 else if (break_aligned_grob == -1) | 286 else if (!break_aligned_grob) |
290 break_aligned_grob = i; | 287 break_aligned_grob = elements[i]; |
291 } | 288 } |
292 } | 289 } |
293 } | 290 } |
294 | 291 |
295 found_break_aligned_grob: | 292 return break_aligned_grob; |
296 if (break_aligned_grob == -1) | 293 } |
| 294 |
| 295 MAKE_SCHEME_CALLBACK (Break_alignable_interface, self_align_callback, 1) |
| 296 SCM |
| 297 Break_alignable_interface::self_align_callback (SCM grob) |
| 298 { |
| 299 Grob *me = unsmob<Grob> (grob); |
| 300 Grob *alignment_parent = find_parent (me); |
| 301 if (!alignment_parent) |
297 return scm_from_int (0); | 302 return scm_from_int (0); |
298 | 303 |
299 Grob *alignment_parent = elements[break_aligned_grob]; | |
300 Grob *common = me->common_refpoint (alignment_parent, X_AXIS); | 304 Grob *common = me->common_refpoint (alignment_parent, X_AXIS); |
301 Real anchor = robust_scm2double (alignment_parent->get_property ("break-align-
anchor"), 0); | 305 Real anchor = robust_scm2double (alignment_parent->get_property ("break-align-
anchor"), 0); |
302 | 306 |
303 return scm_from_double (alignment_parent->relative_coordinate (common, X_AXIS) | 307 return scm_from_double (alignment_parent->relative_coordinate (common, X_AXIS) |
304 - me->relative_coordinate (common, X_AXIS) | 308 - me->relative_coordinate (common, X_AXIS) |
305 + anchor); | 309 + anchor); |
306 } | 310 } |
307 | 311 |
| 312 SCM |
| 313 Break_alignable_interface::self_alignment_on_breakable (SCM grob, |
| 314 int relative_side) |
| 315 { |
| 316 Grob *me = unsmob<Grob> (grob); |
| 317 Grob *alignment_parent = find_parent (me); |
| 318 if (!alignment_parent) |
| 319 return scm_from_int (CENTER); |
| 320 |
| 321 SCM a = alignment_parent->get_property ("break-align-anchor-alignment"); |
| 322 return scm_from_double (robust_scm2double (a, CENTER) * relative_side); |
| 323 } |
| 324 |
| 325 MAKE_SCHEME_CALLBACK (Break_alignable_interface, |
| 326 self_alignment_cis_breakable, 1) |
| 327 SCM |
| 328 Break_alignable_interface::self_alignment_cis_breakable (SCM grob) |
| 329 { |
| 330 return self_alignment_on_breakable(grob, 1); |
| 331 } |
| 332 |
| 333 MAKE_SCHEME_CALLBACK (Break_alignable_interface, |
| 334 self_alignment_trans_breakable, 1) |
| 335 SCM |
| 336 Break_alignable_interface::self_alignment_trans_breakable (SCM grob) |
| 337 { |
| 338 return self_alignment_on_breakable(grob, -1); |
| 339 } |
| 340 |
308 MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_average_anchor, 1) | 341 MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_average_anchor, 1) |
309 SCM | 342 SCM |
310 Break_aligned_interface::calc_average_anchor (SCM grob) | 343 Break_aligned_interface::calc_average_anchor (SCM grob) |
311 { | 344 { |
312 Grob *me = unsmob<Grob> (grob); | 345 Grob *me = unsmob<Grob> (grob); |
313 Real avg = 0.0; | 346 Real avg = 0.0; |
314 int count = 0; | 347 int count = 0; |
315 | 348 |
316 /* average the anchors of those children that have it set */ | 349 /* average the anchors of those children that have it set */ |
317 extract_grob_set (me, "elements", elts); | 350 extract_grob_set (me, "elements", elts); |
318 for (vsize i = 0; i < elts.size (); i++) | 351 for (vsize i = 0; i < elts.size (); i++) |
319 { | 352 { |
320 SCM anchor = elts[i]->get_property ("break-align-anchor"); | 353 SCM anchor = elts[i]->get_property ("break-align-anchor"); |
321 if (scm_is_number (anchor)) | 354 if (scm_is_number (anchor)) |
322 { | 355 { |
323 count++; | 356 count++; |
324 avg += scm_to_double (anchor); | 357 avg += scm_to_double (anchor); |
325 } | 358 } |
326 } | 359 } |
327 | 360 |
328 return scm_from_double (count > 0 ? avg / count : 0); | 361 return scm_from_double (count > 0 ? avg / count : 0); |
329 } | 362 } |
330 | 363 |
| 364 MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_joint_anchor_alignment, 1) |
| 365 SCM |
| 366 Break_aligned_interface::calc_joint_anchor_alignment (SCM grob) |
| 367 { |
| 368 // If all elements with non-zero alignment agree in sign, return that |
| 369 // direction. Otherwise, return center. Just enough thought has been put |
| 370 // into this algorithm to serve our immediate needs. |
| 371 |
| 372 Grob *me = unsmob<Grob> (grob); |
| 373 int direction = 0; |
| 374 |
| 375 extract_grob_set (me, "elements", elts); |
| 376 for (vsize i = 0; i < elts.size (); i++) |
| 377 { |
| 378 SCM s = elts[i]->get_property ("break-align-anchor-alignment"); |
| 379 double alignment = robust_scm2double (s, 0.0); |
| 380 if (alignment < 0.0) { |
| 381 if (direction > 0) |
| 382 return scm_from_int (CENTER); // conflict |
| 383 direction = -1; |
| 384 } else if (alignment > 0.0) { |
| 385 if (direction < 0) |
| 386 return scm_from_int (CENTER); // conflict |
| 387 direction = 1; |
| 388 } |
| 389 } |
| 390 |
| 391 return scm_from_int (direction); |
| 392 } |
| 393 |
331 MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_extent_aligned_anchor, 1) | 394 MAKE_SCHEME_CALLBACK (Break_aligned_interface, calc_extent_aligned_anchor, 1) |
332 SCM | 395 SCM |
333 Break_aligned_interface::calc_extent_aligned_anchor (SCM smob) | 396 Break_aligned_interface::calc_extent_aligned_anchor (SCM smob) |
334 { | 397 { |
335 Grob *me = unsmob<Grob> (smob); | 398 Grob *me = unsmob<Grob> (smob); |
336 Real alignment = robust_scm2double (me->get_property ("break-align-anchor-alig
nment"), 0.0); | 399 Real alignment = robust_scm2double (me->get_property ("break-align-anchor-alig
nment"), 0.0); |
337 Interval iv = me->extent (me, X_AXIS); | 400 Interval iv = me->extent (me, X_AXIS); |
338 | 401 |
339 if (isinf (iv[LEFT]) && isinf (iv[RIGHT])) /* avoid NaN */ | 402 if (isinf (iv[LEFT]) && isinf (iv[RIGHT])) /* avoid NaN */ |
340 return scm_from_double (0.0); | 403 return scm_from_double (0.0); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 | 473 |
411 ADD_INTERFACE (Break_aligned_interface, | 474 ADD_INTERFACE (Break_aligned_interface, |
412 "Breakable items.", | 475 "Breakable items.", |
413 | 476 |
414 /* properties */ | 477 /* properties */ |
415 "break-align-anchor " | 478 "break-align-anchor " |
416 "break-align-anchor-alignment " | 479 "break-align-anchor-alignment " |
417 "break-align-symbol " | 480 "break-align-symbol " |
418 "space-alist " | 481 "space-alist " |
419 ); | 482 ); |
OLD | NEW |