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) 2012 Mike Solomon <mike@apollinemike.com> | 4 Copyright (C) 2012 Mike Solomon <mike@apollinemike.com> |
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 22 matching lines...) Expand all Loading... |
33 [ 1 ] | 33 [ 1 ] |
34 */ | 34 */ |
35 | 35 |
36 #include <pango/pango-matrix.h> | 36 #include <pango/pango-matrix.h> |
37 #include <complex> | 37 #include <complex> |
38 #include "box.hh" | 38 #include "box.hh" |
39 #include "bezier.hh" | 39 #include "bezier.hh" |
40 #include "font-metric.hh" | 40 #include "font-metric.hh" |
41 #include "grob.hh" | 41 #include "grob.hh" |
42 #include "interval.hh" | 42 #include "interval.hh" |
| 43 #include "freetype.hh" |
43 #include "misc.hh" | 44 #include "misc.hh" |
44 #include "offset.hh" | 45 #include "offset.hh" |
| 46 #include "modified-font-metric.hh" |
| 47 #include "open-type-font.hh" |
| 48 #include "pango-font.hh" |
45 #include "pointer-group-interface.hh" | 49 #include "pointer-group-interface.hh" |
46 #include "lily-guile.hh" | 50 #include "lily-guile.hh" |
47 #include "real.hh" | 51 #include "real.hh" |
48 #include "stencil.hh" | 52 #include "stencil.hh" |
49 #include "string-convert.hh" | 53 #include "string-convert.hh" |
50 #include "skyline.hh" | 54 #include "skyline.hh" |
51 #include "skyline-pair.hh" | 55 #include "skyline-pair.hh" |
52 using namespace std; | 56 using namespace std; |
53 | 57 |
54 Real CURVE_QUANTIZATION = 10; | 58 Real QUANTIZATION_UNIT = 0.2; |
55 | |
56 Real ELLIPSE_QUANTIZATION = 20; | |
57 | 59 |
58 void create_path_cap (vector<Box> &boxes, vector<Drul_array<Offset> > &buildings
, PangoMatrix trans, Offset pt, Real rad, Real slope, Direction d); | 60 void create_path_cap (vector<Box> &boxes, vector<Drul_array<Offset> > &buildings
, PangoMatrix trans, Offset pt, Real rad, Real slope, Direction d); |
59 | 61 |
60 struct Transform_matrix_and_expression { | 62 struct Transform_matrix_and_expression |
| 63 { |
61 PangoMatrix tm_; | 64 PangoMatrix tm_; |
62 SCM expr_; | 65 SCM expr_; |
63 | 66 |
64 Transform_matrix_and_expression (PangoMatrix tm, SCM expr); | 67 Transform_matrix_and_expression (PangoMatrix tm, SCM expr); |
65 }; | 68 }; |
66 | |
67 | 69 |
68 Transform_matrix_and_expression::Transform_matrix_and_expression (PangoMatrix tm
, SCM expr) | 70 Transform_matrix_and_expression::Transform_matrix_and_expression (PangoMatrix tm
, SCM expr) |
69 { | 71 { |
70 tm_ = tm; | 72 tm_ = tm; |
71 expr_ = expr; | 73 expr_ = expr; |
72 } | 74 } |
73 | 75 |
74 PangoMatrix | 76 PangoMatrix |
75 make_transform_matrix (Real p0, Real p1, Real p2, Real p3, Real p4, Real p5) | 77 make_transform_matrix (Real p0, Real p1, Real p2, Real p3, Real p4, Real p5) |
76 { | 78 { |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 buildings, | 249 buildings, |
248 trans, | 250 trans, |
249 Offset (x1, y1), | 251 Offset (x1, y1), |
250 thick / 2, | 252 thick / 2, |
251 perpendicular_slope (slope), | 253 perpendicular_slope (slope), |
252 Direction (sign (-slope))); | 254 Direction (sign (-slope))); |
253 } | 255 } |
254 } | 256 } |
255 | 257 |
256 void | 258 void |
257 make_partial_ellipse_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &bui
ldings, PangoMatrix trans, SCM expr, Real quantization) | 259 make_partial_ellipse_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &bui
ldings, PangoMatrix trans, SCM expr) |
258 { | 260 { |
259 Real x_rad = robust_scm2double (scm_car (expr), 0.0); | 261 Real x_rad = robust_scm2double (scm_car (expr), 0.0); |
260 expr = scm_cdr (expr); | 262 expr = scm_cdr (expr); |
261 Real y_rad = robust_scm2double (scm_car (expr), 0.0); | 263 Real y_rad = robust_scm2double (scm_car (expr), 0.0); |
262 expr = scm_cdr (expr); | 264 expr = scm_cdr (expr); |
263 Real start = robust_scm2double (scm_car (expr), 0.0); | 265 Real start = robust_scm2double (scm_car (expr), 0.0); |
264 expr = scm_cdr (expr); | 266 expr = scm_cdr (expr); |
265 Real end = robust_scm2double (scm_car (expr), 0.0); | 267 Real end = robust_scm2double (scm_car (expr), 0.0); |
266 expr = scm_cdr (expr); | 268 expr = scm_cdr (expr); |
267 Real th = robust_scm2double (scm_car (expr), 0.0); | 269 Real th = robust_scm2double (scm_car (expr), 0.0); |
268 expr = scm_cdr (expr); | 270 expr = scm_cdr (expr); |
269 bool connect = to_boolean (scm_car (expr)); | 271 bool connect = to_boolean (scm_car (expr)); |
270 expr = scm_cdr (expr); | 272 expr = scm_cdr (expr); |
271 bool fill = to_boolean (scm_car (expr)); | 273 bool fill = to_boolean (scm_car (expr)); |
272 ////////////////////// | 274 ////////////////////// |
273 start = M_PI * start / 180; | 275 start = M_PI * start / 180; |
274 end = M_PI * end / 180; | 276 end = M_PI * end / 180; |
275 if (end == start) | 277 if (end == start) |
276 end += (2 * M_PI); | 278 end += (2 * M_PI); |
277 complex<Real> sunit = polar (1.0, start); | 279 complex<Real> sunit = polar (1.0, start); |
278 complex<Real> eunit = polar (1.0, end); | 280 complex<Real> eunit = polar (1.0, end); |
279 Offset sp (real (sunit) * x_rad, imag (sunit) * y_rad); | 281 Offset sp (real (sunit) * x_rad, imag (sunit) * y_rad); |
280 Offset ep (real (eunit) * x_rad, imag (eunit) * y_rad); | 282 Offset ep (real (eunit) * x_rad, imag (eunit) * y_rad); |
281 ////////////////////// | 283 ////////////////////// |
282 Drul_array<vector<Offset> > points; | 284 Drul_array<vector<Offset> > points; |
283 Direction d = DOWN; | 285 Direction d = DOWN; |
| 286 int quantization = max (1, (int) (((x_rad * trans.xx) + (y_rad * trans.yy)) *
M_PI / QUANTIZATION_UNIT)); |
284 do | 287 do |
285 { | 288 { |
286 for (vsize i = 0; i < 1 + quantization; i++) | 289 for (vsize i = 0; i < 1 + quantization; i++) |
287 { | 290 { |
288 Real ang = linear_map (start, end, 0, quantization, i); | 291 Real ang = linear_map (start, end, 0, quantization, i); |
289 complex<Real> coord = polar (1.0, ang); | 292 complex<Real> coord = polar (1.0, ang); |
290 Offset pt (real (coord) * x_rad, | 293 Offset pt (real (coord) * x_rad, |
291 imag (coord) * y_rad); | 294 imag (coord) * y_rad); |
292 Real slope = pt[Y_AXIS] / pt[X_AXIS]; | 295 Real slope = pt[Y_AXIS] / pt[X_AXIS]; |
293 Offset inter = get_point_in_y_direction (pt, perpendicular_slope (slop
e), th / 2, d); | 296 Offset inter = get_point_in_y_direction (pt, perpendicular_slope (slop
e), th / 2, d); |
(...skipping 10 matching lines...) Expand all Loading... |
304 { | 307 { |
305 b.add_point (points[d][i]); | 308 b.add_point (points[d][i]); |
306 b.add_point (points[d][i + 1]); | 309 b.add_point (points[d][i + 1]); |
307 } | 310 } |
308 while (flip (&d) != DOWN); | 311 while (flip (&d) != DOWN); |
309 boxes.push_back (b); | 312 boxes.push_back (b); |
310 } | 313 } |
311 | 314 |
312 if (connect || fill) | 315 if (connect || fill) |
313 { | 316 { |
314 make_draw_line_boxes (boxes, buildings, trans, scm_list_5(scm_from_double
(th), | 317 make_draw_line_boxes (boxes, buildings, trans, scm_list_5 (scm_from_double
(th), |
315 scm_from_double (sp[X_AXIS]
), | 318 scm_from_double
(sp[X_AXIS]), |
316 scm_from_double (sp[Y_AXIS]
), | 319 scm_from_double
(sp[Y_AXIS]), |
317 scm_from_double (ep[X_AXIS]
), | 320 scm_from_double
(ep[X_AXIS]), |
318 scm_from_double (ep[Y_AXIS]
)), | 321 scm_from_double
(ep[Y_AXIS])), |
319 false); | 322 false); |
320 } | 323 } |
321 | 324 |
322 if (th > 0.0) | 325 if (th > 0.0) |
323 { | 326 { |
324 // beg line cap | 327 // beg line cap |
325 complex<Real> coord = polar (1.0, start); | 328 complex<Real> coord = polar (1.0, start); |
326 Offset pt (real (coord) * x_rad, | 329 Offset pt (real (coord) * x_rad, |
327 imag (coord) * y_rad); | 330 imag (coord) * y_rad); |
328 Real slope = pt[Y_AXIS] / pt[X_AXIS]; | 331 Real slope = pt[Y_AXIS] / pt[X_AXIS]; |
329 create_path_cap (boxes, | 332 create_path_cap (boxes, |
(...skipping 13 matching lines...) Expand all Loading... |
343 buildings, | 346 buildings, |
344 trans, | 347 trans, |
345 pt, | 348 pt, |
346 th / 2, | 349 th / 2, |
347 perpendicular_slope (slope), | 350 perpendicular_slope (slope), |
348 Direction (sign (-slope))); | 351 Direction (sign (-slope))); |
349 } | 352 } |
350 } | 353 } |
351 | 354 |
352 void | 355 void |
353 make_partial_ellipse_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &bui
ldings, PangoMatrix trans, SCM expr) | |
354 { | |
355 make_partial_ellipse_boxes (boxes, buildings, trans, expr, ELLIPSE_QUANTIZATIO
N); | |
356 } | |
357 | |
358 void | |
359 make_round_filled_box_boxes (vector<Box> &boxes, PangoMatrix trans, SCM expr) | 356 make_round_filled_box_boxes (vector<Box> &boxes, PangoMatrix trans, SCM expr) |
360 { | 357 { |
361 Real left = robust_scm2double (scm_car (expr), 0.0); | 358 Real left = robust_scm2double (scm_car (expr), 0.0); |
362 expr = scm_cdr (expr); | 359 expr = scm_cdr (expr); |
363 Real right = robust_scm2double (scm_car (expr), 0.0); | 360 Real right = robust_scm2double (scm_car (expr), 0.0); |
364 expr = scm_cdr (expr); | 361 expr = scm_cdr (expr); |
365 Real bottom = robust_scm2double (scm_car (expr), 0.0); | 362 Real bottom = robust_scm2double (scm_car (expr), 0.0); |
366 expr = scm_cdr (expr); | 363 expr = scm_cdr (expr); |
367 Real top = robust_scm2double (scm_car (expr), 0.0); | 364 Real top = robust_scm2double (scm_car (expr), 0.0); |
368 expr = scm_cdr (expr); | 365 expr = scm_cdr (expr); |
(...skipping 20 matching lines...) Expand all Loading... |
389 Real holder = other; | 386 Real holder = other; |
390 other = angle; | 387 other = angle; |
391 angle = holder; | 388 angle = holder; |
392 } | 389 } |
393 other = (slope >= 0 && d == DOWN) || (slope < 0 && d == UP) | 390 other = (slope >= 0 && d == DOWN) || (slope < 0 && d == UP) |
394 ? other + 360.0 | 391 ? other + 360.0 |
395 : other; | 392 : other; |
396 PangoMatrix new_trans (trans); | 393 PangoMatrix new_trans (trans); |
397 pango_matrix_translate (&new_trans, pt[X_AXIS], pt[Y_AXIS]); | 394 pango_matrix_translate (&new_trans, pt[X_AXIS], pt[Y_AXIS]); |
398 make_partial_ellipse_boxes (boxes, buildings, new_trans, | 395 make_partial_ellipse_boxes (boxes, buildings, new_trans, |
399 scm_list_n (scm_from_double (rad), | 396 scm_list_n (scm_from_double (rad), |
400 scm_from_double (rad), | 397 scm_from_double (rad), |
401 scm_from_double (angle), | 398 scm_from_double (angle), |
402 scm_from_double (other), | 399 scm_from_double (other), |
403 scm_from_double (0.0), | 400 scm_from_double (0.0), |
404 SCM_BOOL_F, | 401 SCM_BOOL_F, |
405 SCM_BOOL_F, | 402 SCM_BOOL_F, |
406 SCM_UNDEFINED), | 403 SCM_UNDEFINED)); |
407 3); | |
408 } | 404 } |
409 | 405 |
410 void | 406 void |
411 make_draw_bezier_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &buildin
gs, PangoMatrix trans, SCM expr) | 407 make_draw_bezier_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &buildin
gs, PangoMatrix trans, SCM expr) |
412 { | 408 { |
413 Real th = robust_scm2double (scm_car (expr), 0.0); | 409 Real th = robust_scm2double (scm_car (expr), 0.0); |
414 expr = scm_cdr (expr); | 410 expr = scm_cdr (expr); |
415 Real x0 = robust_scm2double (scm_car (expr), 0.0); | 411 Real x0 = robust_scm2double (scm_car (expr), 0.0); |
416 expr = scm_cdr (expr); | 412 expr = scm_cdr (expr); |
417 Real y0 = robust_scm2double (scm_car (expr), 0.0); | 413 Real y0 = robust_scm2double (scm_car (expr), 0.0); |
418 expr = scm_cdr (expr); | 414 expr = scm_cdr (expr); |
419 Real x1 = robust_scm2double (scm_car (expr), 0.0); | 415 Real x1 = robust_scm2double (scm_car (expr), 0.0); |
420 expr = scm_cdr (expr); | 416 expr = scm_cdr (expr); |
421 Real y1 = robust_scm2double (scm_car (expr), 0.0); | 417 Real y1 = robust_scm2double (scm_car (expr), 0.0); |
422 expr = scm_cdr (expr); | 418 expr = scm_cdr (expr); |
423 Real x2 = robust_scm2double (scm_car (expr), 0.0); | 419 Real x2 = robust_scm2double (scm_car (expr), 0.0); |
424 expr = scm_cdr (expr); | 420 expr = scm_cdr (expr); |
425 Real y2 = robust_scm2double (scm_car (expr), 0.0); | 421 Real y2 = robust_scm2double (scm_car (expr), 0.0); |
426 expr = scm_cdr (expr); | 422 expr = scm_cdr (expr); |
427 Real x3 = robust_scm2double (scm_car (expr), 0.0); | 423 Real x3 = robust_scm2double (scm_car (expr), 0.0); |
428 expr = scm_cdr (expr); | 424 expr = scm_cdr (expr); |
429 Real y3 = robust_scm2double (scm_car (expr), 0.0); | 425 Real y3 = robust_scm2double (scm_car (expr), 0.0); |
430 ////////////////////// | 426 ////////////////////// |
431 Bezier curve; | 427 Bezier curve; |
432 curve.control_[0] = Offset (x0, y0); | 428 curve.control_[0] = Offset (x0, y0); |
433 curve.control_[1] = Offset (x1, y1); | 429 curve.control_[1] = Offset (x1, y1); |
434 curve.control_[2] = Offset (x2, y2); | 430 curve.control_[2] = Offset (x2, y2); |
435 curve.control_[3] = Offset (x3, y3); | 431 curve.control_[3] = Offset (x3, y3); |
| 432 Offset temp0 (x0, y0); |
| 433 Offset temp1 (x1, y1); |
| 434 Offset temp2 (x2, y2); |
| 435 Offset temp3 (x3, y3); |
| 436 pango_matrix_transform_point (&trans, &temp0[X_AXIS], &temp0[Y_AXIS]); |
| 437 pango_matrix_transform_point (&trans, &temp1[X_AXIS], &temp1[Y_AXIS]); |
| 438 pango_matrix_transform_point (&trans, &temp2[X_AXIS], &temp2[Y_AXIS]); |
| 439 pango_matrix_transform_point (&trans, &temp3[X_AXIS], &temp3[Y_AXIS]); |
436 ////////////////////// | 440 ////////////////////// |
437 Drul_array<vector<Offset> > points; | 441 Drul_array<vector<Offset> > points; |
438 Direction d = DOWN; | 442 Direction d = DOWN; |
| 443 int quantization = int (((temp1 - temp0).length () |
| 444 + (temp2 - temp1).length () |
| 445 + (temp3 - temp2).length ()) |
| 446 / QUANTIZATION_UNIT); |
439 do | 447 do |
440 { | 448 { |
441 Offset first = get_point_in_y_direction (curve.control_[0], perpendicular_
slope (curve.slope_at_point (0.0)), th / 2, d); | 449 Offset first = get_point_in_y_direction (curve.control_[0], perpendicular_
slope (curve.slope_at_point (0.0)), th / 2, d); |
442 pango_matrix_transform_point (&trans, &first[X_AXIS], &first[Y_AXIS]); | 450 pango_matrix_transform_point (&trans, &first[X_AXIS], &first[Y_AXIS]); |
443 points[d].push_back (first); | 451 points[d].push_back (first); |
444 for (vsize i = 1; i < CURVE_QUANTIZATION; i++) | 452 for (vsize i = 1; i < quantization; i++) |
445 { | 453 { |
446 Real pt = (i * 1.0) / CURVE_QUANTIZATION; | 454 Real pt = (i * 1.0) / quantization; |
447 Offset inter = get_point_in_y_direction (curve.curve_point (pt), perpe
ndicular_slope (curve.slope_at_point (pt)), th / 2, d); | 455 Offset inter = get_point_in_y_direction (curve.curve_point (pt), perpe
ndicular_slope (curve.slope_at_point (pt)), th / 2, d); |
448 pango_matrix_transform_point (&trans, &inter[X_AXIS], &inter[Y_AXIS]); | 456 pango_matrix_transform_point (&trans, &inter[X_AXIS], &inter[Y_AXIS]); |
449 points[d].push_back (inter); | 457 points[d].push_back (inter); |
450 } | 458 } |
451 Offset last = get_point_in_y_direction (curve.control_[3], curve.slope_at_
point (1.0), th / 2, d); | 459 Offset last = get_point_in_y_direction (curve.control_[3], curve.slope_at_
point (1.0), th / 2, d); |
452 pango_matrix_transform_point (&trans, &last[X_AXIS], &last[Y_AXIS]); | 460 pango_matrix_transform_point (&trans, &last[X_AXIS], &last[Y_AXIS]); |
453 points[d].push_back (last); | 461 points[d].push_back (last); |
454 } | 462 } |
455 while (flip (&d) != DOWN); | 463 while (flip (&d) != DOWN); |
456 | 464 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 expr = scm_cdr (expr); | 584 expr = scm_cdr (expr); |
577 out = scm_cons (scm_list_n (scm_from_double (current[X_AXIS]), | 585 out = scm_cons (scm_list_n (scm_from_double (current[X_AXIS]), |
578 scm_from_double (current[Y_AXIS]), | 586 scm_from_double (current[Y_AXIS]), |
579 scm_from_double (x1), | 587 scm_from_double (x1), |
580 scm_from_double (y1), | 588 scm_from_double (y1), |
581 scm_from_double (x2), | 589 scm_from_double (x2), |
582 scm_from_double (y2), | 590 scm_from_double (y2), |
583 scm_from_double (x3), | 591 scm_from_double (x3), |
584 scm_from_double (y3), | 592 scm_from_double (y3), |
585 SCM_UNDEFINED), | 593 SCM_UNDEFINED), |
586 out); | 594 out); |
587 current = Offset (x3, y3); | 595 current = Offset (x3, y3); |
588 } | 596 } |
589 else if (scm_car (expr) == ly_symbol2scm ("rcurveto")) | 597 else if (scm_car (expr) == ly_symbol2scm ("rcurveto")) |
590 { | 598 { |
591 Real x1 = robust_scm2double (scm_cadr (expr), 0.0); | 599 Real x1 = robust_scm2double (scm_cadr (expr), 0.0); |
592 expr = scm_cddr (expr); | 600 expr = scm_cddr (expr); |
593 Real y1 = robust_scm2double (scm_car (expr), 0.0); | 601 Real y1 = robust_scm2double (scm_car (expr), 0.0); |
594 expr = scm_cdr (expr); | 602 expr = scm_cdr (expr); |
595 Real x2 = robust_scm2double (scm_car (expr), 0.0); | 603 Real x2 = robust_scm2double (scm_car (expr), 0.0); |
596 expr = scm_cdr (expr); | 604 expr = scm_cdr (expr); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 internal_make_path_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &build
ings, PangoMatrix trans, SCM expr, bool use_building) | 647 internal_make_path_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &build
ings, PangoMatrix trans, SCM expr, bool use_building) |
640 { | 648 { |
641 SCM blot = scm_car (expr); | 649 SCM blot = scm_car (expr); |
642 expr = scm_cdr (expr); | 650 expr = scm_cdr (expr); |
643 SCM path = all_commands_to_absolute_and_group (expr); | 651 SCM path = all_commands_to_absolute_and_group (expr); |
644 // note that expr has more stuff that we don't need after this - simply ignore
it | 652 // note that expr has more stuff that we don't need after this - simply ignore
it |
645 ////////////////////// | 653 ////////////////////// |
646 for (SCM s = path; scm_is_pair (s); s = scm_cdr (s)) | 654 for (SCM s = path; scm_is_pair (s); s = scm_cdr (s)) |
647 { | 655 { |
648 scm_to_int (scm_length (scm_car (s))) == 4 | 656 scm_to_int (scm_length (scm_car (s))) == 4 |
649 ? make_draw_line_boxes (boxes, buildings, trans, scm_cons (blo
t, scm_car (s)), use_building) | 657 ? make_draw_line_boxes (boxes, buildings, trans, scm_cons (blot, scm_car (
s)), use_building) |
650 : make_draw_bezier_boxes (boxes, buildings, trans, scm_cons (b
lot, scm_car (s))); | 658 : make_draw_bezier_boxes (boxes, buildings, trans, scm_cons (blot, scm_car
(s))); |
651 } | 659 } |
652 } | 660 } |
653 | 661 |
654 void | 662 void |
655 make_path_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &buildings, Pan
goMatrix trans, SCM expr) | 663 make_path_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &buildings, Pan
goMatrix trans, SCM expr) |
656 { | 664 { |
657 return internal_make_path_boxes (boxes, buildings, trans, scm_cons (scm_car (e
xpr), get_path_list (scm_cdr (expr))), false); | 665 return internal_make_path_boxes (boxes, buildings, trans, scm_cons (scm_car (e
xpr), get_path_list (scm_cdr (expr))), false); |
658 } | 666 } |
659 | 667 |
660 void | 668 void |
(...skipping 16 matching lines...) Expand all Loading... |
677 internal_make_path_boxes (boxes, buildings, trans, scm_cons (blot_diameter, sc
m_reverse_x (l, SCM_EOL)), true); | 685 internal_make_path_boxes (boxes, buildings, trans, scm_cons (blot_diameter, sc
m_reverse_x (l, SCM_EOL)), true); |
678 } | 686 } |
679 | 687 |
680 void | 688 void |
681 make_named_glyph_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &buildin
gs, PangoMatrix trans, SCM expr) | 689 make_named_glyph_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &buildin
gs, PangoMatrix trans, SCM expr) |
682 { | 690 { |
683 SCM fm_scm = scm_car (expr); | 691 SCM fm_scm = scm_car (expr); |
684 Font_metric *fm = unsmob_metrics (fm_scm); | 692 Font_metric *fm = unsmob_metrics (fm_scm); |
685 expr = scm_cdr (expr); | 693 expr = scm_cdr (expr); |
686 SCM glyph = scm_car (expr); | 694 SCM glyph = scm_car (expr); |
| 695 string glyph_s = ly_scm2string (glyph); |
| 696 |
687 ////////////////////// | 697 ////////////////////// |
688 string font_name = String_convert::to_lower (fm->font_name ()); | 698 Open_type_font *open_fm |
689 SCM box_lookup_function = ly_lily_module_constant ("box-data-for-glyph"); | 699 = dynamic_cast<Open_type_font *> |
690 SCM glyph_info = scm_call_2 (box_lookup_function, fm_scm, glyph); | 700 (dynamic_cast<Modified_font_metric *>(fm)->original_font ()); |
691 Stencil m = fm->find_by_name (ly_scm2string (glyph)); | 701 SCM_ASSERT_TYPE (open_fm, fm_scm, SCM_ARG1, __FUNCTION__, "OpenType font"); |
692 // mmx and mmy give the bounding box for the original stencil | 702 |
693 Interval mmx = robust_scm2interval (ly_assoc_get (ly_symbol2scm ("mmx"), glyph
_info, SCM_EOL), Interval (0,0)); | 703 size_t gidx = open_fm->name_to_index (glyph_s); |
694 Interval mmy = robust_scm2interval (ly_assoc_get (ly_symbol2scm ("mmy"), glyph
_info, SCM_EOL), Interval (0,0)); | 704 //Box bbox = open_fm->get_unscaled_indexed_char_dimensions (gidx); |
695 // xex and yex give the bounding box for the current stencil | 705 Box bbox = open_fm->get_unscaled_indexed_char_dimensions (gidx); |
696 Interval xex = m.extent (X_AXIS); | 706 SCM outline = open_fm->get_glyph_outline (gidx); |
697 Interval yex = m.extent (Y_AXIS); | 707 Box real_bbox = fm->get_indexed_char_dimensions (gidx); |
698 Offset scale (xex.length () / mmx.length (), yex.length () / mmy.length ()); | 708 |
699 // the three operations below move the stencil from its original coordinates t
o current coordinates | 709 /* |
700 pango_matrix_translate (&trans, xex[LEFT], yex[DOWN]); | 710 Because extents for named glyphs are cached, the value of |
701 pango_matrix_scale (&trans, scale[X_AXIS], scale[Y_AXIS]); | 711 real_bbox may not be the one that freetype calculates. |
702 pango_matrix_translate (&trans, -mmx[LEFT], -mmy[DOWN]); | 712 |
| 713 They should be close, though. |
| 714 A workaround below is to use the max of the two, which may |
| 715 slightly overshoot an extent but generally doesn't. |
| 716 */ |
| 717 Real xlen = real_bbox[X_AXIS].length () / bbox[X_AXIS].length (); |
| 718 Real ylen = real_bbox[Y_AXIS].length () / bbox[Y_AXIS].length (); |
| 719 assert (abs (xlen - ylen) < 10e-3); |
| 720 |
| 721 pango_matrix_scale (&trans, max (xlen, ylen), max (xlen, ylen)); |
| 722 |
703 ////////////////////// | 723 ////////////////////// |
704 for (SCM s = ly_assoc_get (ly_symbol2scm ("paths"), glyph_info, SCM_EOL); | 724 for (SCM s = outline; |
705 scm_is_pair (s); | 725 scm_is_pair (s); |
706 s = scm_cdr (s)) | 726 s = scm_cdr (s)) |
707 { | 727 { |
708 scm_to_int (scm_length (scm_car (s))) == 4 | 728 scm_to_int (scm_length (scm_car (s))) == 4 |
709 ? make_draw_line_boxes (boxes, buildings, trans, scm_cons (scm
_from_double (0), scm_car (s)), false) | 729 ? make_draw_line_boxes (boxes, buildings, trans, scm_cons (scm_from_double
(0), scm_car (s)), false) |
710 : make_draw_bezier_boxes (boxes, buildings, trans, scm_cons (s
cm_from_double (0), scm_car (s))); | 730 : make_draw_bezier_boxes (boxes, buildings, trans, scm_cons (scm_from_doub
le (0), scm_car (s))); |
711 } | 731 } |
712 } | 732 } |
713 | 733 |
714 void | 734 void |
715 make_glyph_string_boxes (vector<Box> &boxes, PangoMatrix trans, SCM expr) | 735 make_glyph_string_boxes (vector<Box> &boxes, vector<Drul_array<Offset> > &buildi
ngs, PangoMatrix trans, SCM expr) |
716 { | 736 { |
| 737 SCM fm_scm = scm_car (expr); |
| 738 Font_metric *fm = unsmob_metrics (fm_scm); |
| 739 expr = scm_cdr (expr); |
717 expr = scm_cdr (expr); // font-name | 740 expr = scm_cdr (expr); // font-name |
718 expr = scm_cdr (expr); // size | 741 expr = scm_cdr (expr); // size |
719 expr = scm_cdr (expr); // cid? | 742 expr = scm_cdr (expr); // cid? |
720 SCM whxy = scm_cadar (expr); | 743 SCM whxy = scm_cadar (expr); |
721 vector<Real> widths; | 744 vector<Real> widths; |
722 vector<Interval> heights; | 745 vector<Interval> heights; |
723 vector<Real> xos; | 746 vector<Real> xos; |
724 vector<Real> yos; | 747 vector<Real> yos; |
| 748 vector<string> char_ids; |
725 ////////////////////// | 749 ////////////////////// |
| 750 Pango_font *pango_fm = dynamic_cast<Pango_font *> (fm); |
| 751 SCM_ASSERT_TYPE (pango_fm, fm_scm, SCM_ARG1, __FUNCTION__, "Pango font"); |
| 752 |
726 for (SCM s = whxy; scm_is_pair (s); s = scm_cdr (s)) | 753 for (SCM s = whxy; scm_is_pair (s); s = scm_cdr (s)) |
727 { | 754 { |
728 SCM now = scm_car (s); | 755 SCM now = scm_car (s); |
729 widths.push_back (robust_scm2double (scm_car (now), 0.0)); | 756 widths.push_back (robust_scm2double (scm_car (now), 0.0)); |
730 now = scm_cdr (now); | 757 now = scm_cdr (now); |
731 heights.push_back (robust_scm2interval (scm_car (now), Interval (0,0))); | 758 heights.push_back (robust_scm2interval (scm_car (now), Interval (0, 0))); |
732 now = scm_cdr (now); | 759 now = scm_cdr (now); |
733 xos.push_back (robust_scm2double (scm_car (now), 0.0)); | 760 xos.push_back (robust_scm2double (scm_car (now), 0.0)); |
734 now = scm_cdr (now); | 761 now = scm_cdr (now); |
735 yos.push_back (robust_scm2double (scm_car (now), 0.0)); | 762 yos.push_back (robust_scm2double (scm_car (now), 0.0)); |
| 763 now = scm_cdr (now); |
| 764 char_ids.push_back (robust_scm2string (scm_car (now), "")); |
736 } | 765 } |
737 Real cumulative_x = 0.0; | 766 Real cumulative_x = 0.0; |
738 for (vsize i = 0; i < widths.size (); i++) | 767 for (vsize i = 0; i < widths.size (); i++) |
739 { | 768 { |
| 769 PangoMatrix transcopy (trans); |
740 Offset pt0 (cumulative_x + xos[i], heights[i][DOWN] + yos[i]); | 770 Offset pt0 (cumulative_x + xos[i], heights[i][DOWN] + yos[i]); |
741 Offset pt1 (cumulative_x + widths[i] + xos[i], heights[i][UP] + yos[i]); | 771 Offset pt1 (cumulative_x + widths[i] + xos[i], heights[i][UP] + yos[i]); |
742 pango_matrix_transform_point (&trans, &pt0[X_AXIS], &pt0[Y_AXIS]); | |
743 pango_matrix_transform_point (&trans, &pt1[X_AXIS], &pt1[Y_AXIS]); | |
744 Box b; | |
745 b.add_point (pt0); | |
746 b.add_point (pt1); | |
747 boxes.push_back (b); | |
748 cumulative_x += widths[i]; | 772 cumulative_x += widths[i]; |
| 773 |
| 774 Box kerned_bbox; |
| 775 kerned_bbox.add_point (pt0); |
| 776 kerned_bbox.add_point (pt1); |
| 777 size_t gidx = pango_fm->name_to_index (char_ids[i]); |
| 778 Box real_bbox = pango_fm->get_scaled_indexed_char_dimensions (gidx); |
| 779 Box bbox = pango_fm->get_unscaled_indexed_char_dimensions (gidx); |
| 780 SCM outline = pango_fm->get_glyph_outline (gidx); |
| 781 |
| 782 // scales may have rounding error but should be close |
| 783 Real xlen = real_bbox[X_AXIS].length () / bbox[X_AXIS].length (); |
| 784 Real ylen = real_bbox[Y_AXIS].length () / bbox[Y_AXIS].length (); |
| 785 |
| 786 /* |
| 787 TODO: |
| 788 |
| 789 The value will be nan for whitespace, in which case we just want |
| 790 filler, so the kerned bbox is ok. |
| 791 |
| 792 However, if the value is inf, this likely means that LilyPond is |
| 793 using a font that is currently difficult to get the measurements |
| 794 from the Pango_font. This should eventually be fixed. The solution |
| 795 for now is just to use the bounding box. |
| 796 */ |
| 797 if (isnan (xlen) || isnan (ylen) || isinf (xlen) || isinf (ylen)) |
| 798 outline = box_to_scheme_lines (kerned_bbox); |
| 799 else |
| 800 { |
| 801 assert (abs (xlen - ylen) < 10e-3); |
| 802 |
| 803 Real scale_factor = max (xlen, ylen); |
| 804 // the three operations below move the stencil from its original coord
inates to current coordinates |
| 805 pango_matrix_translate (&transcopy, kerned_bbox[X_AXIS][LEFT], kerned_
bbox[Y_AXIS][DOWN] - real_bbox[Y_AXIS][DOWN]); |
| 806 pango_matrix_translate (&transcopy, real_bbox[X_AXIS][LEFT], real_bbox
[Y_AXIS][DOWN]); |
| 807 pango_matrix_scale (&transcopy, scale_factor, scale_factor); |
| 808 pango_matrix_translate (&transcopy, -bbox[X_AXIS][LEFT], -bbox[Y_AXIS]
[DOWN]); |
| 809 } |
| 810 ////////////////////// |
| 811 for (SCM s = outline; |
| 812 scm_is_pair (s); |
| 813 s = scm_cdr (s)) |
| 814 { |
| 815 scm_to_int (scm_length (scm_car (s))) == 4 |
| 816 ? make_draw_line_boxes (boxes, buildings, transcopy, scm_cons (scm_fro
m_double (0), scm_car (s)), false) |
| 817 : make_draw_bezier_boxes (boxes, buildings, transcopy, scm_cons (scm_f
rom_double (0), scm_car (s))); |
| 818 } |
749 } | 819 } |
750 } | 820 } |
751 | 821 |
752 /* | 822 /* |
753 receives a stencil expression and a transform matrix | 823 receives a stencil expression and a transform matrix |
754 depending on the stencil name, dispatches it to the appropriate function | 824 depending on the stencil name, dispatches it to the appropriate function |
755 */ | 825 */ |
756 | 826 |
757 void | 827 void |
758 stencil_dispatcher (vector<Box> &boxes, vector<Drul_array<Offset> > &buildings,
PangoMatrix trans, SCM expr) | 828 stencil_dispatcher (vector<Box> &boxes, vector<Drul_array<Offset> > &buildings,
PangoMatrix trans, SCM expr) |
(...skipping 14 matching lines...) Expand all Loading... |
773 SCM x2 = scm_car (expr); | 843 SCM x2 = scm_car (expr); |
774 make_draw_line_boxes (boxes, buildings, trans, scm_list_5 (th, scm_from_do
uble (0.0), scm_from_double (0.0), x1, x2), true); | 844 make_draw_line_boxes (boxes, buildings, trans, scm_list_5 (th, scm_from_do
uble (0.0), scm_from_double (0.0), x1, x2), true); |
775 } | 845 } |
776 else if (scm_car (expr) == ly_symbol2scm ("circle")) | 846 else if (scm_car (expr) == ly_symbol2scm ("circle")) |
777 { | 847 { |
778 expr = scm_cdr (expr); | 848 expr = scm_cdr (expr); |
779 SCM rad = scm_car (expr); | 849 SCM rad = scm_car (expr); |
780 expr = scm_cdr (expr); | 850 expr = scm_cdr (expr); |
781 SCM th = scm_car (expr); | 851 SCM th = scm_car (expr); |
782 make_partial_ellipse_boxes (boxes, buildings, trans, | 852 make_partial_ellipse_boxes (boxes, buildings, trans, |
783 scm_list_n (rad, | 853 scm_list_n (rad, |
784 rad, | 854 rad, |
785 scm_from_double (0.0), | 855 scm_from_double (0.0), |
786 scm_from_double (360.0), | 856 scm_from_double (360.0), |
787 th, | 857 th, |
788 SCM_BOOL_F, | 858 SCM_BOOL_F, |
789 SCM_BOOL_T, | 859 SCM_BOOL_T, |
790 SCM_UNDEFINED)); | 860 SCM_UNDEFINED)); |
791 } | 861 } |
792 else if (scm_car (expr) == ly_symbol2scm ("ellipse")) | 862 else if (scm_car (expr) == ly_symbol2scm ("ellipse")) |
793 { | 863 { |
794 expr = scm_cdr (expr); | 864 expr = scm_cdr (expr); |
795 SCM x_rad = scm_car (expr); | 865 SCM x_rad = scm_car (expr); |
796 expr = scm_cdr (expr); | 866 expr = scm_cdr (expr); |
797 SCM y_rad = scm_car (expr); | 867 SCM y_rad = scm_car (expr); |
798 expr = scm_cdr (expr); | 868 expr = scm_cdr (expr); |
799 SCM th = scm_car (expr); | 869 SCM th = scm_car (expr); |
800 make_partial_ellipse_boxes (boxes, buildings, trans, | 870 make_partial_ellipse_boxes (boxes, buildings, trans, |
801 scm_list_n (x_rad, | 871 scm_list_n (x_rad, |
802 y_rad, | 872 y_rad, |
803 scm_from_double (0.0), | 873 scm_from_double (0.0), |
804 scm_from_double (360.0), | 874 scm_from_double (360.0), |
805 th, | 875 th, |
806 SCM_BOOL_F, | 876 SCM_BOOL_F, |
807 SCM_BOOL_T, | 877 SCM_BOOL_T, |
808 SCM_UNDEFINED)); | 878 SCM_UNDEFINED)); |
809 } | 879 } |
810 else if (scm_car (expr) == ly_symbol2scm ("partial-ellipse")) | 880 else if (scm_car (expr) == ly_symbol2scm ("partial-ellipse")) |
811 make_partial_ellipse_boxes (boxes, buildings, trans, scm_cdr (expr)); | 881 make_partial_ellipse_boxes (boxes, buildings, trans, scm_cdr (expr)); |
812 else if (scm_car (expr) == ly_symbol2scm ("round-filled-box")) | 882 else if (scm_car (expr) == ly_symbol2scm ("round-filled-box")) |
813 make_round_filled_box_boxes (boxes, trans, scm_cdr (expr)); | 883 make_round_filled_box_boxes (boxes, trans, scm_cdr (expr)); |
814 else if (scm_car (expr) == ly_symbol2scm ("named-glyph")) | 884 else if (scm_car (expr) == ly_symbol2scm ("named-glyph")) |
815 make_named_glyph_boxes (boxes, buildings, trans, scm_cdr (expr)); | 885 make_named_glyph_boxes (boxes, buildings, trans, scm_cdr (expr)); |
816 else if (scm_car (expr) == ly_symbol2scm ("polygon")) | 886 else if (scm_car (expr) == ly_symbol2scm ("polygon")) |
817 make_polygon_boxes (boxes, buildings, trans, scm_cdr (expr)); | 887 make_polygon_boxes (boxes, buildings, trans, scm_cdr (expr)); |
818 else if (scm_car (expr) == ly_symbol2scm ("path")) | 888 else if (scm_car (expr) == ly_symbol2scm ("path")) |
819 make_path_boxes (boxes, buildings, trans, scm_cdr (expr)); | 889 make_path_boxes (boxes, buildings, trans, scm_cdr (expr)); |
820 else if (scm_car (expr) == ly_symbol2scm ("glyph-string")) | 890 else if (scm_car (expr) == ly_symbol2scm ("glyph-string")) |
821 make_glyph_string_boxes (boxes, trans, scm_cdr (expr)); | 891 make_glyph_string_boxes (boxes, buildings, trans, scm_cdr (expr)); |
822 else | 892 else |
823 { | 893 { |
824 #if 0 | 894 #if 0 |
825 warning ("Stencil expression not supported by the veritcal skylines."); | 895 warning ("Stencil expression not supported by the veritcal skylines."); |
826 #endif | 896 #endif |
827 /* | 897 /* |
828 We don't issue a warning here, as we assume that stencil-expression.cc | 898 We don't issue a warning here, as we assume that stencil-expression.cc |
829 is doing stencil-checking correctly. | 899 is doing stencil-checking correctly. |
830 */ | 900 */ |
831 } | 901 } |
832 } | 902 } |
833 | 903 |
834 /* | 904 /* |
835 traverses a stencil expression, returning a vector of Transform_matrix_and_exp
ression | 905 traverses a stencil expression, returning a vector of Transform_matrix_and_exp
ression |
836 the struct Transform_matrix_and_expression contains two members, | 906 the struct Transform_matrix_and_expression contains two members, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 else | 961 else |
892 { | 962 { |
893 vector<Transform_matrix_and_expression> out; | 963 vector<Transform_matrix_and_expression> out; |
894 out.push_back (Transform_matrix_and_expression (trans, expr)); | 964 out.push_back (Transform_matrix_and_expression (trans, expr)); |
895 return out; | 965 return out; |
896 } | 966 } |
897 warning ("Stencil expression not supported by the veritcal skylines."); | 967 warning ("Stencil expression not supported by the veritcal skylines."); |
898 return vector<Transform_matrix_and_expression> (); | 968 return vector<Transform_matrix_and_expression> (); |
899 } | 969 } |
900 | 970 |
| 971 SCM |
| 972 Grob::internal_simple_skylines_from_stencil (SCM smob, Axis a) |
| 973 { |
| 974 Grob *me = unsmob_grob (smob); |
| 975 |
| 976 if (to_boolean (me->get_property ("cross-staff"))) |
| 977 return Skyline_pair ().smobbed_copy (); |
| 978 |
| 979 extract_grob_set (me, "elements", elts); |
| 980 if (elts.size ()) |
| 981 return internal_skylines_from_element_stencils (smob, a); |
| 982 |
| 983 Stencil *s = unsmob_stencil (me->get_property ("stencil")); |
| 984 if (!s) |
| 985 return Skyline_pair ().smobbed_copy (); |
| 986 |
| 987 vector<Box> boxes; |
| 988 boxes.push_back (Box (s->extent (X_AXIS), s->extent (Y_AXIS))); |
| 989 return Skyline_pair (boxes, a).smobbed_copy (); |
| 990 } |
| 991 |
901 MAKE_SCHEME_CALLBACK (Grob, simple_vertical_skylines_from_stencil, 1); | 992 MAKE_SCHEME_CALLBACK (Grob, simple_vertical_skylines_from_stencil, 1); |
902 SCM | 993 SCM |
903 Grob::simple_vertical_skylines_from_stencil (SCM smob) | 994 Grob::simple_vertical_skylines_from_stencil (SCM smob) |
904 { | 995 { |
905 Grob *me = unsmob_grob (smob); | 996 return internal_simple_skylines_from_stencil (smob, X_AXIS); |
906 extract_grob_set (me, "elements", elts); | 997 } |
907 if (elts.size ()) | 998 |
908 return vertical_skylines_from_element_stencils (smob); | 999 MAKE_SCHEME_CALLBACK (Grob, simple_horizontal_skylines_from_stencil, 1); |
909 | |
910 Stencil *s = unsmob_stencil (me->get_property ("stencil")); | |
911 if (!s) | |
912 return Skyline_pair ().smobbed_copy(); | |
913 | |
914 vector<Box> boxes; | |
915 boxes.push_back (Box (s->extent (X_AXIS), s->extent (Y_AXIS))); | |
916 Real pad = robust_scm2double (me->get_property ("skyline-horizontal-padding"),
0.0); | |
917 return Skyline_pair (boxes, pad, X_AXIS).smobbed_copy (); | |
918 } | |
919 | |
920 SCM | 1000 SCM |
921 Stencil::vertical_skylines_from_stencil (SCM sten, Real pad) | 1001 Grob::simple_horizontal_skylines_from_stencil (SCM smob) |
| 1002 { |
| 1003 return internal_simple_skylines_from_stencil (smob, Y_AXIS); |
| 1004 } |
| 1005 |
| 1006 SCM |
| 1007 Stencil::skylines_from_stencil (SCM sten, Real pad, Axis a) |
922 { | 1008 { |
923 Stencil *s = unsmob_stencil (sten); | 1009 Stencil *s = unsmob_stencil (sten); |
924 if (!s) | 1010 if (!s) |
925 return Skyline_pair ().smobbed_copy (); | 1011 return Skyline_pair ().smobbed_copy (); |
926 | 1012 |
927 vector<Transform_matrix_and_expression> data = | 1013 vector<Transform_matrix_and_expression> data |
928 stencil_traverser (make_transform_matrix (1.0,0.0,0.0,1.0,0.0,0.0), | 1014 = stencil_traverser (make_transform_matrix (1.0, 0.0, 0.0, 1.0, 0.0, 0.0), |
929 s->expr ()); | 1015 s->expr ()); |
930 vector<Box> boxes; | 1016 vector<Box> boxes; |
931 vector<Drul_array<Offset> > buildings; | 1017 vector<Drul_array<Offset> > buildings; |
932 for (vsize i = 0; i < data.size (); i++) | 1018 for (vsize i = 0; i < data.size (); i++) |
933 stencil_dispatcher (boxes, buildings, data[i].tm_, data[i].expr_); | 1019 stencil_dispatcher (boxes, buildings, data[i].tm_, data[i].expr_); |
934 | 1020 |
935 // we use the bounding box if there are no boxes | 1021 // we use the bounding box if there are no boxes |
936 if (!boxes.size () && !buildings.size ()) | 1022 if (!boxes.size () && !buildings.size ()) |
937 boxes.push_back (Box (s->extent (X_AXIS), s->extent (Y_AXIS))); | 1023 boxes.push_back (Box (s->extent (X_AXIS), s->extent (Y_AXIS))); |
938 | 1024 |
939 Skyline_pair out (boxes, pad, X_AXIS); | 1025 Skyline_pair out (boxes, a); |
940 out.merge (Skyline_pair (buildings, pad, X_AXIS)); | 1026 out.merge (Skyline_pair (buildings, a)); |
941 | 1027 |
| 1028 for (DOWN_and_UP (d)) |
| 1029 out[d] = out[d].padded (pad); |
| 1030 |
| 1031 out.deholify (); |
942 return out.smobbed_copy (); | 1032 return out.smobbed_copy (); |
943 } | 1033 } |
944 | 1034 |
945 MAKE_SCHEME_CALLBACK (Grob, vertical_skylines_from_stencil, 1); | 1035 MAKE_SCHEME_CALLBACK (Grob, vertical_skylines_from_stencil, 1); |
946 SCM | 1036 SCM |
947 Grob::vertical_skylines_from_stencil (SCM smob) | 1037 Grob::vertical_skylines_from_stencil (SCM smob) |
948 { | 1038 { |
949 Grob *me = unsmob_grob (smob); | 1039 Grob *me = unsmob_grob (smob); |
950 Stencil *s = unsmob_stencil (me->get_property ("stencil")); | |
951 SCM vertical_skylines_cache = ly_lily_module_constant ("vertical-skylines-cach
e"); | |
952 if (Skyline_pair *vsk = | |
953 Skyline_pair::unsmob | |
954 (ly_assoc_get (me->get_property ("vertical-skylines-cache-name"), | |
955 vertical_skylines_cache, | |
956 SCM_BOOL_F))) | |
957 { | |
958 // lucky day - we've already calculated this. just need to shift it... | |
959 Skyline_pair ret (*vsk); | |
960 ret.shift (s->extent (X_AXIS)[LEFT] - ret.left ()); | |
961 ret.raise (s->extent (Y_AXIS)[UP] - ret[UP].max_height ()); | |
962 return ret.smobbed_copy (); | |
963 } | |
964 | 1040 |
965 Real pad = robust_scm2double (me->get_property ("skyline-horizontal-padding"),
0.0); | 1041 Real pad = robust_scm2double (me->get_property ("skyline-horizontal-padding"),
0.0); |
966 SCM out = Stencil::vertical_skylines_from_stencil (me->get_property ("stencil"
), pad); | 1042 SCM out = Stencil::skylines_from_stencil (me->get_property ("stencil"), pad, X
_AXIS); |
967 if (scm_is_symbol (me->get_property ("vertical-skylines-cache-name"))) | 1043 |
968 { | |
969 SCM write_to_skyline_cache = ly_lily_module_constant ("write-to-vertical-s
kylines-cache"); | |
970 (void) scm_call_2 (write_to_skyline_cache, out, me->get_property ("vertica
l-skylines-cache-name")); | |
971 } | |
972 return out; | 1044 return out; |
973 } | 1045 } |
974 | 1046 |
975 MAKE_SCHEME_CALLBACK (Grob, vertical_skylines_from_element_stencils, 1); | 1047 MAKE_SCHEME_CALLBACK (Grob, horizontal_skylines_from_stencil, 1); |
976 SCM | 1048 SCM |
977 Grob::vertical_skylines_from_element_stencils (SCM smob) | 1049 Grob::horizontal_skylines_from_stencil (SCM smob) |
978 { | 1050 { |
979 Grob *me = unsmob_grob (smob); | 1051 Grob *me = unsmob_grob (smob); |
| 1052 |
| 1053 Real pad = robust_scm2double (me->get_property ("skyline-vertical-padding"), 0
.0); |
| 1054 SCM out = Stencil::skylines_from_stencil (me->get_property ("stencil"), pad, Y
_AXIS); |
| 1055 |
| 1056 return out; |
| 1057 } |
| 1058 |
| 1059 SCM |
| 1060 Grob::internal_skylines_from_element_stencils (SCM smob, Axis a) |
| 1061 { |
| 1062 Grob *me = unsmob_grob (smob); |
| 1063 |
980 extract_grob_set (me, "elements", elts); | 1064 extract_grob_set (me, "elements", elts); |
981 vector<Real> x_pos; | 1065 vector<Real> x_pos; |
982 vector<Real> y_pos; | 1066 vector<Real> y_pos; |
983 Grob *x_common = common_refpoint_of_array (elts, me, X_AXIS); | 1067 Grob *x_common = common_refpoint_of_array (elts, me, X_AXIS); |
984 Grob *y_common = common_refpoint_of_array (elts, me, Y_AXIS); | 1068 Grob *y_common = common_refpoint_of_array (elts, me, Y_AXIS); |
985 for (vsize i = 0; i < elts.size (); i++) | 1069 for (vsize i = 0; i < elts.size (); i++) |
986 { | 1070 { |
987 x_pos.push_back (elts[i]->relative_coordinate (x_common, X_AXIS)); | 1071 x_pos.push_back (elts[i]->relative_coordinate (x_common, X_AXIS)); |
988 y_pos.push_back (elts[i]->relative_coordinate (y_common, Y_AXIS)); | 1072 y_pos.push_back (elts[i]->relative_coordinate (y_common, Y_AXIS)); |
989 } | 1073 } |
990 Real my_x = me->relative_coordinate (x_common, X_AXIS); | 1074 Real my_x = me->relative_coordinate (x_common, X_AXIS); |
991 Real my_y = me->relative_coordinate (y_common, Y_AXIS); | 1075 Real my_y = me->relative_coordinate (y_common, Y_AXIS); |
992 Skyline_pair res; | 1076 Skyline_pair res; |
993 for (vsize i = 0; i < elts.size (); i++) | 1077 for (vsize i = 0; i < elts.size (); i++) |
994 { | 1078 { |
995 Skyline_pair *skyp = Skyline_pair::unsmob (elts[i]->get_property ("vertica
l-skylines")); | 1079 Skyline_pair *skyp = Skyline_pair::unsmob (elts[i]->get_property (a == X_A
XIS ? "vertical-skylines" : "horizontal-skylines")); |
996 if (skyp) | 1080 if (skyp) |
997 { | 1081 { |
998 /* | 1082 /* |
999 Here, copying is essential. Otherwise, the skyline pair will | 1083 Here, copying is essential. Otherwise, the skyline pair will |
1000 get doubly shifted! | 1084 get doubly shifted! |
1001 */ | 1085 */ |
| 1086 /* |
| 1087 It took Mike about 6 months of his life to add the `else' clause |
| 1088 below. For horizontal skylines, the raise and shift calls need |
| 1089 to be reversed. This is what was causing the problems in the |
| 1090 shifting with all of the tests. RIP 6 months! |
| 1091 */ |
1002 Skyline_pair copy = Skyline_pair (*skyp); | 1092 Skyline_pair copy = Skyline_pair (*skyp); |
1003 copy.shift (x_pos[i] - my_x); | 1093 if (a == X_AXIS) |
1004 copy.raise (y_pos[i] - my_y); | 1094 { |
| 1095 copy.shift (x_pos[i] - my_x); |
| 1096 copy.raise (y_pos[i] - my_y); |
| 1097 } |
| 1098 else |
| 1099 { |
| 1100 copy.raise (x_pos[i] - my_x); |
| 1101 copy.shift (y_pos[i] - my_y); |
| 1102 } |
1005 res.merge (copy); | 1103 res.merge (copy); |
1006 } | 1104 } |
1007 } | 1105 } |
1008 return res.smobbed_copy (); | 1106 return res.smobbed_copy (); |
1009 } | 1107 } |
| 1108 |
| 1109 MAKE_SCHEME_CALLBACK (Grob, vertical_skylines_from_element_stencils, 1); |
| 1110 SCM |
| 1111 Grob::vertical_skylines_from_element_stencils (SCM smob) |
| 1112 { |
| 1113 return internal_skylines_from_element_stencils (smob, X_AXIS); |
| 1114 } |
| 1115 |
| 1116 MAKE_SCHEME_CALLBACK (Grob, horizontal_skylines_from_element_stencils, 1); |
| 1117 SCM |
| 1118 Grob::horizontal_skylines_from_element_stencils (SCM smob) |
| 1119 { |
| 1120 return internal_skylines_from_element_stencils (smob, Y_AXIS); |
| 1121 } |
LEFT | RIGHT |