Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1892 | Rev 3959 | ||
---|---|---|---|
Line 36... | Line 36... | ||
36 | * Carl D. Worth |
36 | * Carl D. Worth |
37 | */ |
37 | */ |
Line 38... | Line 38... | ||
38 | 38 | ||
Line -... | Line 39... | ||
- | 39 | #include "cairoint.h" |
|
39 | #include "cairoint.h" |
40 | |
- | 41 | #include "cairo-box-inline.h" |
|
40 | 42 | #include "cairo-error-private.h" |
|
41 | #include "cairo-error-private.h" |
43 | #include "cairo-list-inline.h" |
Line 42... | Line 44... | ||
42 | #include "cairo-path-fixed-private.h" |
44 | #include "cairo-path-fixed-private.h" |
43 | #include "cairo-slope-private.h" |
45 | #include "cairo-slope-private.h" |
Line 65... | Line 67... | ||
65 | static void |
67 | static void |
66 | _cairo_path_buf_add_points (cairo_path_buf_t *buf, |
68 | _cairo_path_buf_add_points (cairo_path_buf_t *buf, |
67 | const cairo_point_t *points, |
69 | const cairo_point_t *points, |
68 | int num_points); |
70 | int num_points); |
Line 69... | Line -... | ||
69 | - | ||
70 | #define cairo_path_head(path__) (&(path__)->buf.base) |
- | |
71 | #define cairo_path_tail(path__) cairo_path_buf_prev (cairo_path_head (path__)) |
- | |
72 | - | ||
73 | #define cairo_path_buf_next(pos__) \ |
- | |
74 | cairo_list_entry ((pos__)->link.next, cairo_path_buf_t, link) |
- | |
75 | #define cairo_path_buf_prev(pos__) \ |
- | |
76 | cairo_list_entry ((pos__)->link.prev, cairo_path_buf_t, link) |
- | |
77 | - | ||
78 | #define cairo_path_foreach_buf_start(pos__, path__) \ |
- | |
79 | pos__ = cairo_path_head (path__); do |
- | |
80 | #define cairo_path_foreach_buf_end(pos__, path__) \ |
- | |
81 | while ((pos__ = cairo_path_buf_next (pos__)) != cairo_path_head (path__)) |
- | |
82 | 71 | ||
83 | void |
72 | void |
84 | _cairo_path_fixed_init (cairo_path_fixed_t *path) |
73 | _cairo_path_fixed_init (cairo_path_fixed_t *path) |
85 | { |
74 | { |
Line 95... | Line 84... | ||
95 | path->buf.base.points = path->buf.points; |
84 | path->buf.base.points = path->buf.points; |
Line 96... | Line 85... | ||
96 | 85 | ||
97 | path->current_point.x = 0; |
86 | path->current_point.x = 0; |
98 | path->current_point.y = 0; |
87 | path->current_point.y = 0; |
99 | path->last_move_point = path->current_point; |
- | |
- | 88 | path->last_move_point = path->current_point; |
|
100 | path->has_last_move_point = FALSE; |
89 | |
- | 90 | path->has_current_point = FALSE; |
|
- | 91 | path->needs_move_to = TRUE; |
|
101 | path->has_current_point = FALSE; |
92 | path->has_extents = FALSE; |
- | 93 | path->has_curve_to = FALSE; |
|
102 | path->has_curve_to = FALSE; |
94 | path->stroke_is_rectilinear = TRUE; |
103 | path->is_rectilinear = TRUE; |
95 | path->fill_is_rectilinear = TRUE; |
104 | path->maybe_fill_region = TRUE; |
96 | path->fill_maybe_region = TRUE; |
Line 105... | Line 97... | ||
105 | path->is_empty_fill = TRUE; |
97 | path->fill_is_empty = TRUE; |
106 | 98 | ||
107 | path->extents.p1.x = path->extents.p1.y = INT_MAX; |
99 | path->extents.p1.x = path->extents.p1.y = 0; |
Line 108... | Line 100... | ||
108 | path->extents.p2.x = path->extents.p2.y = INT_MIN; |
100 | path->extents.p2.x = path->extents.p2.y = 0; |
109 | } |
101 | } |
110 | 102 | ||
Line 124... | Line 116... | ||
124 | path->buf.base.size_ops = ARRAY_LENGTH (path->buf.op); |
116 | path->buf.base.size_ops = ARRAY_LENGTH (path->buf.op); |
125 | path->buf.base.size_points = ARRAY_LENGTH (path->buf.points); |
117 | path->buf.base.size_points = ARRAY_LENGTH (path->buf.points); |
Line 126... | Line 118... | ||
126 | 118 | ||
127 | path->current_point = other->current_point; |
119 | path->current_point = other->current_point; |
128 | path->last_move_point = other->last_move_point; |
- | |
- | 120 | path->last_move_point = other->last_move_point; |
|
129 | path->has_last_move_point = other->has_last_move_point; |
121 | |
- | 122 | path->has_current_point = other->has_current_point; |
|
- | 123 | path->needs_move_to = other->needs_move_to; |
|
130 | path->has_current_point = other->has_current_point; |
124 | path->has_extents = other->has_extents; |
- | 125 | path->has_curve_to = other->has_curve_to; |
|
131 | path->has_curve_to = other->has_curve_to; |
126 | path->stroke_is_rectilinear = other->stroke_is_rectilinear; |
132 | path->is_rectilinear = other->is_rectilinear; |
127 | path->fill_is_rectilinear = other->fill_is_rectilinear; |
133 | path->maybe_fill_region = other->maybe_fill_region; |
128 | path->fill_maybe_region = other->fill_maybe_region; |
Line 134... | Line 129... | ||
134 | path->is_empty_fill = other->is_empty_fill; |
129 | path->fill_is_empty = other->fill_is_empty; |
Line 135... | Line 130... | ||
135 | 130 | ||
136 | path->extents = other->extents; |
131 | path->extents = other->extents; |
Line 180... | Line 175... | ||
180 | unsigned long |
175 | unsigned long |
181 | _cairo_path_fixed_hash (const cairo_path_fixed_t *path) |
176 | _cairo_path_fixed_hash (const cairo_path_fixed_t *path) |
182 | { |
177 | { |
183 | unsigned long hash = _CAIRO_HASH_INIT_VALUE; |
178 | unsigned long hash = _CAIRO_HASH_INIT_VALUE; |
184 | const cairo_path_buf_t *buf; |
179 | const cairo_path_buf_t *buf; |
185 | int num_points, num_ops; |
180 | unsigned int count; |
Line 186... | Line -... | ||
186 | - | ||
187 | hash = _cairo_hash_bytes (hash, &path->extents, sizeof (path->extents)); |
- | |
188 | 181 | ||
189 | num_ops = num_points = 0; |
182 | count = 0; |
190 | cairo_path_foreach_buf_start (buf, path) { |
183 | cairo_path_foreach_buf_start (buf, path) { |
191 | hash = _cairo_hash_bytes (hash, buf->op, |
184 | hash = _cairo_hash_bytes (hash, buf->op, |
- | 185 | buf->num_ops * sizeof (buf->op[0])); |
|
- | 186 | count += buf->num_ops; |
|
- | 187 | } cairo_path_foreach_buf_end (buf, path); |
|
- | 188 | hash = _cairo_hash_bytes (hash, &count, sizeof (count)); |
|
- | 189 | ||
- | 190 | count = 0; |
|
192 | buf->num_ops * sizeof (buf->op[0])); |
191 | cairo_path_foreach_buf_start (buf, path) { |
193 | hash = _cairo_hash_bytes (hash, buf->points, |
192 | hash = _cairo_hash_bytes (hash, buf->points, |
194 | buf->num_points * sizeof (buf->points[0])); |
- | |
195 | - | ||
196 | num_ops += buf->num_ops; |
193 | buf->num_points * sizeof (buf->points[0])); |
197 | num_points += buf->num_points; |
194 | count += buf->num_points; |
198 | } cairo_path_foreach_buf_end (buf, path); |
- | |
199 | - | ||
200 | hash = _cairo_hash_bytes (hash, &num_ops, sizeof (num_ops)); |
195 | } cairo_path_foreach_buf_end (buf, path); |
Line 201... | Line 196... | ||
201 | hash = _cairo_hash_bytes (hash, &num_points, sizeof (num_points)); |
196 | hash = _cairo_hash_bytes (hash, &count, sizeof (count)); |
202 | 197 | ||
Line 203... | Line 198... | ||
203 | return hash; |
198 | return hash; |
Line 231... | Line 226... | ||
231 | 226 | ||
232 | if (a == b) |
227 | if (a == b) |
Line 233... | Line 228... | ||
233 | return TRUE; |
228 | return TRUE; |
234 | - | ||
235 | /* use the flags to quickly differentiate based on contents */ |
229 | |
236 | if (a->is_empty_fill != b->is_empty_fill || |
- | |
237 | a->has_curve_to != b->has_curve_to || |
- | |
238 | a->maybe_fill_region != b->maybe_fill_region || |
230 | /* use the flags to quickly differentiate based on contents */ |
239 | a->is_rectilinear != b->is_rectilinear) |
231 | if (a->has_curve_to != b->has_curve_to) |
240 | { |
232 | { |
Line 241... | Line 233... | ||
241 | return FALSE; |
233 | return FALSE; |
Line 364... | Line 356... | ||
364 | _cairo_path_fixed_fini (path); |
356 | _cairo_path_fixed_fini (path); |
365 | free (path); |
357 | free (path); |
366 | } |
358 | } |
Line 367... | Line 359... | ||
367 | 359 | ||
368 | static cairo_path_op_t |
360 | static cairo_path_op_t |
369 | _cairo_path_last_op (cairo_path_fixed_t *path) |
361 | _cairo_path_fixed_last_op (cairo_path_fixed_t *path) |
370 | { |
362 | { |
Line 371... | Line 363... | ||
371 | cairo_path_buf_t *buf; |
363 | cairo_path_buf_t *buf; |
372 | 364 | ||
373 | buf = cairo_path_tail (path); |
- | |
Line 374... | Line 365... | ||
374 | if (buf->num_ops == 0) |
365 | buf = cairo_path_tail (path); |
375 | return -1; |
366 | assert (buf->num_ops != 0); |
Line 376... | Line 367... | ||
376 | 367 | ||
377 | return buf->op[buf->num_ops - 1]; |
368 | return buf->op[buf->num_ops - 1]; |
378 | } |
- | |
379 | 369 | } |
|
380 | static inline void |
370 | |
- | 371 | static inline const cairo_point_t * |
|
381 | _cairo_path_fixed_extents_add (cairo_path_fixed_t *path, |
372 | _cairo_path_fixed_penultimate_point (cairo_path_fixed_t *path) |
382 | const cairo_point_t *point) |
373 | { |
383 | { |
374 | cairo_path_buf_t *buf; |
- | 375 | ||
- | 376 | buf = cairo_path_tail (path); |
|
- | 377 | if (likely (buf->num_points >= 2)) { |
|
- | 378 | return &buf->points[buf->num_points - 2]; |
|
- | 379 | } else { |
|
- | 380 | cairo_path_buf_t *prev_buf = cairo_path_buf_prev (buf); |
|
- | 381 | ||
384 | if (point->x < path->extents.p1.x) |
382 | assert (prev_buf->num_points >= 2 - buf->num_points); |
- | 383 | return &prev_buf->points[prev_buf->num_points - (2 - buf->num_points)]; |
|
385 | path->extents.p1.x = point->x; |
384 | } |
- | 385 | } |
|
386 | if (point->y < path->extents.p1.y) |
386 | |
- | 387 | static void |
|
- | 388 | _cairo_path_fixed_drop_line_to (cairo_path_fixed_t *path) |
|
- | 389 | { |
|
387 | path->extents.p1.y = point->y; |
390 | cairo_path_buf_t *buf; |
388 | 391 | ||
- | 392 | assert (_cairo_path_fixed_last_op (path) == CAIRO_PATH_OP_LINE_TO); |
|
389 | if (point->x > path->extents.p2.x) |
393 | |
Line 390... | Line 394... | ||
390 | path->extents.p2.x = point->x; |
394 | buf = cairo_path_tail (path); |
391 | if (point->y > path->extents.p2.y) |
395 | buf->num_points--; |
392 | path->extents.p2.y = point->y; |
396 | buf->num_ops--; |
393 | } |
397 | } |
394 | 398 | ||
395 | cairo_status_t |
399 | cairo_status_t |
396 | _cairo_path_fixed_move_to (cairo_path_fixed_t *path, |
- | |
Line -... | Line 400... | ||
- | 400 | _cairo_path_fixed_move_to (cairo_path_fixed_t *path, |
|
397 | cairo_fixed_t x, |
401 | cairo_fixed_t x, |
398 | cairo_fixed_t y) |
402 | cairo_fixed_t y) |
- | 403 | { |
|
Line 399... | Line -... | ||
399 | { |
- | |
400 | cairo_status_t status; |
404 | _cairo_path_fixed_new_sub_path (path); |
401 | cairo_point_t point; |
- | |
402 | - | ||
- | 405 | ||
Line 403... | Line 406... | ||
403 | point.x = x; |
406 | path->has_current_point = TRUE; |
404 | point.y = y; |
407 | path->current_point.x = x; |
405 | 408 | path->current_point.y = y; |
|
406 | /* If the previous op was also a MOVE_TO, then just change its |
- | |
407 | * point rather than adding a new op. */ |
409 | path->last_move_point = path->current_point; |
408 | if (_cairo_path_last_op (path) == CAIRO_PATH_OP_MOVE_TO) { |
410 | |
Line 409... | Line -... | ||
409 | cairo_path_buf_t *buf; |
- | |
410 | - | ||
411 | buf = cairo_path_tail (path); |
- | |
412 | buf->points[buf->num_points - 1] = point; |
- | |
413 | } else { |
411 | return CAIRO_STATUS_SUCCESS; |
414 | status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1); |
412 | } |
415 | if (unlikely (status)) |
413 | |
- | 414 | static cairo_status_t |
|
416 | return status; |
415 | _cairo_path_fixed_move_to_apply (cairo_path_fixed_t *path) |
417 | 416 | { |
|
418 | if (path->has_current_point && path->is_rectilinear) { |
417 | if (likely (! path->needs_move_to)) |
419 | /* a move-to is first an implicit close */ |
418 | return CAIRO_STATUS_SUCCESS; |
- | 419 | ||
- | 420 | path->needs_move_to = FALSE; |
|
- | 421 | ||
- | 422 | if (path->has_extents) { |
|
420 | path->is_rectilinear = path->current_point.x == path->last_move_point.x || |
423 | _cairo_box_add_point (&path->extents, &path->current_point); |
Line 421... | Line -... | ||
421 | path->current_point.y == path->last_move_point.y; |
- | |
422 | path->maybe_fill_region &= path->is_rectilinear; |
424 | } else { |
423 | } |
- | |
424 | if (path->maybe_fill_region) { |
- | |
Line 425... | Line 425... | ||
425 | path->maybe_fill_region = |
425 | _cairo_box_set (&path->extents, &path->current_point, &path->current_point); |
426 | _cairo_fixed_is_integer (path->last_move_point.x) && |
426 | path->has_extents = TRUE; |
Line 427... | Line 427... | ||
427 | _cairo_fixed_is_integer (path->last_move_point.y); |
427 | } |
428 | } |
428 | |
429 | } |
429 | if (path->fill_maybe_region) { |
- | 430 | path->fill_maybe_region = _cairo_fixed_is_integer (path->current_point.x) && |
|
- | 431 | _cairo_fixed_is_integer (path->current_point.y); |
|
- | 432 | } |
|
- | 433 | ||
- | 434 | path->last_move_point = path->current_point; |
|
- | 435 | ||
- | 436 | return _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &path->current_point, 1); |
|
- | 437 | } |
|
- | 438 | ||
- | 439 | void |
|
- | 440 | _cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path) |
|
430 | 441 | { |
|
431 | path->current_point = point; |
442 | if (! path->needs_move_to) { |
Line 432... | Line 443... | ||
432 | path->last_move_point = point; |
443 | /* If the current subpath doesn't need_move_to, it contains at least one command */ |
433 | path->has_last_move_point = TRUE; |
444 | if (path->fill_is_rectilinear) { |
Line 473... | Line 484... | ||
473 | * that the last_move_point state is updated properly. |
484 | * that the last_move_point state is updated properly. |
474 | */ |
485 | */ |
475 | if (! path->has_current_point) |
486 | if (! path->has_current_point) |
476 | return _cairo_path_fixed_move_to (path, point.x, point.y); |
487 | return _cairo_path_fixed_move_to (path, point.x, point.y); |
Line -... | Line 488... | ||
- | 488 | ||
- | 489 | status = _cairo_path_fixed_move_to_apply (path); |
|
- | 490 | if (unlikely (status)) |
|
- | 491 | return status; |
|
477 | 492 | ||
478 | /* If the previous op was but the initial MOVE_TO and this segment |
493 | /* If the previous op was but the initial MOVE_TO and this segment |
479 | * is degenerate, then we can simply skip this point. Note that |
494 | * is degenerate, then we can simply skip this point. Note that |
480 | * a move-to followed by a degenerate line-to is a valid path for |
495 | * a move-to followed by a degenerate line-to is a valid path for |
481 | * stroking, but at all other times is simply a degenerate segment. |
496 | * stroking, but at all other times is simply a degenerate segment. |
482 | */ |
497 | */ |
483 | if (_cairo_path_last_op (path) != CAIRO_PATH_OP_MOVE_TO) { |
498 | if (_cairo_path_fixed_last_op (path) != CAIRO_PATH_OP_MOVE_TO) { |
484 | if (x == path->current_point.x && y == path->current_point.y) |
499 | if (x == path->current_point.x && y == path->current_point.y) |
485 | return CAIRO_STATUS_SUCCESS; |
500 | return CAIRO_STATUS_SUCCESS; |
Line 486... | Line 501... | ||
486 | } |
501 | } |
487 | 502 | ||
488 | /* If the previous op was also a LINE_TO with the same gradient, |
503 | /* If the previous op was also a LINE_TO with the same gradient, |
489 | * then just change its end-point rather than adding a new op. |
504 | * then just change its end-point rather than adding a new op. |
490 | */ |
- | |
491 | if (_cairo_path_last_op (path) == CAIRO_PATH_OP_LINE_TO) { |
505 | */ |
Line 492... | Line 506... | ||
492 | cairo_path_buf_t *buf; |
506 | if (_cairo_path_fixed_last_op (path) == CAIRO_PATH_OP_LINE_TO) { |
493 | const cairo_point_t *p; |
- | |
494 | - | ||
495 | buf = cairo_path_tail (path); |
- | |
496 | if (likely (buf->num_points >= 2)) { |
- | |
497 | p = &buf->points[buf->num_points-2]; |
- | |
498 | } else { |
- | |
499 | cairo_path_buf_t *prev_buf = cairo_path_buf_prev (buf); |
- | |
500 | p = &prev_buf->points[prev_buf->num_points - (2 - buf->num_points)]; |
507 | const cairo_point_t *p; |
501 | } |
508 | |
502 | 509 | p = _cairo_path_fixed_penultimate_point (path); |
|
503 | if (p->x == path->current_point.x && p->y == path->current_point.y) { |
- | |
504 | /* previous line element was degenerate, replace */ |
510 | if (p->x == path->current_point.x && p->y == path->current_point.y) { |
505 | buf->points[buf->num_points - 1] = point; |
511 | /* previous line element was degenerate, replace */ |
Line 506... | Line 512... | ||
506 | goto FLAGS; |
512 | _cairo_path_fixed_drop_line_to (path); |
507 | } else { |
513 | } else { |
508 | cairo_slope_t prev, self; |
514 | cairo_slope_t prev, self; |
509 | 515 | ||
510 | _cairo_slope_init (&prev, p, &path->current_point); |
516 | _cairo_slope_init (&prev, p, &path->current_point); |
511 | _cairo_slope_init (&self, &path->current_point, &point); |
517 | _cairo_slope_init (&self, &path->current_point, &point); |
- | 518 | if (_cairo_slope_equal (&prev, &self) && |
|
- | 519 | /* cannot trim anti-parallel segments whilst stroking */ |
|
- | 520 | ! _cairo_slope_backwards (&prev, &self)) |
|
- | 521 | { |
|
512 | if (_cairo_slope_equal (&prev, &self) && |
522 | _cairo_path_fixed_drop_line_to (path); |
513 | /* cannot trim anti-parallel segments whilst stroking */ |
523 | /* In this case the flags might be more restrictive than |
514 | ! _cairo_slope_backwards (&prev, &self)) |
524 | * what we actually need. |
515 | { |
525 | * When changing the flags definition we should check if |
516 | buf->points[buf->num_points - 1] = point; |
526 | * changing the line_to point can affect them. |
Line 517... | Line -... | ||
517 | goto FLAGS; |
- | |
518 | } |
- | |
519 | } |
- | |
520 | } |
- | |
521 | - | ||
522 | status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1); |
527 | */ |
523 | if (unlikely (status)) |
528 | } |
524 | return status; |
529 | } |
- | 530 | } |
|
525 | 531 | ||
526 | FLAGS: |
- | |
527 | if (path->is_rectilinear) { |
532 | if (path->stroke_is_rectilinear) { |
528 | path->is_rectilinear = path->current_point.x == x || |
533 | path->stroke_is_rectilinear = path->current_point.x == x || |
529 | path->current_point.y == y; |
534 | path->current_point.y == y; |
530 | path->maybe_fill_region &= path->is_rectilinear; |
535 | path->fill_is_rectilinear &= path->stroke_is_rectilinear; |
531 | } |
536 | path->fill_maybe_region &= path->fill_is_rectilinear; |
532 | if (path->maybe_fill_region) { |
537 | if (path->fill_maybe_region) { |
533 | path->maybe_fill_region = _cairo_fixed_is_integer (x) && |
538 | path->fill_maybe_region = _cairo_fixed_is_integer (x) && |
534 | _cairo_fixed_is_integer (y); |
539 | _cairo_fixed_is_integer (y); |
- | 540 | } |
|
Line 535... | Line 541... | ||
535 | } |
541 | if (path->fill_is_empty) { |
536 | if (path->is_empty_fill) { |
- | |
- | 542 | path->fill_is_empty = path->current_point.x == x && |
|
537 | path->is_empty_fill = path->current_point.x == x && |
543 | path->current_point.y == y; |
538 | path->current_point.y == y; |
- | |
539 | } |
544 | } |
540 | 545 | } |
|
541 | path->current_point = point; |
- | |
542 | if (path->has_last_move_point) { |
546 | |
Line 543... | Line 547... | ||
543 | _cairo_path_fixed_extents_add (path, &path->last_move_point); |
547 | path->current_point = point; |
544 | path->has_last_move_point = FALSE; |
548 | |
545 | } |
549 | _cairo_box_add_point (&path->extents, &point); |
Line 567... | Line 571... | ||
567 | cairo_fixed_t x2, cairo_fixed_t y2) |
571 | cairo_fixed_t x2, cairo_fixed_t y2) |
568 | { |
572 | { |
569 | cairo_status_t status; |
573 | cairo_status_t status; |
570 | cairo_point_t point[3]; |
574 | cairo_point_t point[3]; |
Line -... | Line 575... | ||
- | 575 | ||
- | 576 | /* If this curves does not move, replace it with a line-to. |
|
- | 577 | * This frequently happens with rounded-rectangles and r==0. |
|
- | 578 | */ |
|
- | 579 | if (path->current_point.x == x2 && path->current_point.y == y2) { |
|
- | 580 | if (x1 == x2 && x0 == x2 && y1 == y2 && y0 == y2) |
|
- | 581 | return _cairo_path_fixed_line_to (path, x2, y2); |
|
- | 582 | ||
- | 583 | /* We may want to check for the absence of a cusp, in which case |
|
- | 584 | * we can also replace the curve-to with a line-to. |
|
- | 585 | */ |
|
- | 586 | } |
|
571 | 587 | ||
572 | /* make sure subpaths are started properly */ |
588 | /* make sure subpaths are started properly */ |
573 | if (! path->has_current_point) { |
589 | if (! path->has_current_point) { |
- | 590 | status = _cairo_path_fixed_move_to (path, x0, y0); |
|
- | 591 | assert (status == CAIRO_STATUS_SUCCESS); |
|
- | 592 | } |
|
- | 593 | ||
574 | status = _cairo_path_fixed_move_to (path, x0, y0); |
594 | status = _cairo_path_fixed_move_to_apply (path); |
575 | if (unlikely (status)) |
595 | if (unlikely (status)) |
- | 596 | return status; |
|
- | 597 | ||
- | 598 | /* If the previous op was a degenerate LINE_TO, drop it. */ |
|
- | 599 | if (_cairo_path_fixed_last_op (path) == CAIRO_PATH_OP_LINE_TO) { |
|
- | 600 | const cairo_point_t *p; |
|
- | 601 | ||
- | 602 | p = _cairo_path_fixed_penultimate_point (path); |
|
- | 603 | if (p->x == path->current_point.x && p->y == path->current_point.y) { |
|
- | 604 | /* previous line element was degenerate, replace */ |
|
- | 605 | _cairo_path_fixed_drop_line_to (path); |
|
576 | return status; |
606 | } |
Line 577... | Line 607... | ||
577 | } |
607 | } |
578 | 608 | ||
579 | point[0].x = x0; point[0].y = y0; |
609 | point[0].x = x0; point[0].y = y0; |
- | 610 | point[1].x = x1; point[1].y = y1; |
|
580 | point[1].x = x1; point[1].y = y1; |
611 | point[2].x = x2; point[2].y = y2; |
581 | point[2].x = x2; point[2].y = y2; |
612 | |
582 | status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3); |
- | |
Line 583... | Line 613... | ||
583 | if (unlikely (status)) |
613 | _cairo_box_add_curve_to (&path->extents, &path->current_point, |
584 | return status; |
- | |
585 | - | ||
586 | path->current_point = point[2]; |
614 | &point[0], &point[1], &point[2]); |
587 | path->has_current_point = TRUE; |
615 | |
588 | path->is_empty_fill = FALSE; |
616 | path->current_point = point[2]; |
589 | path->has_curve_to = TRUE; |
- | |
590 | path->is_rectilinear = FALSE; |
- | |
591 | path->maybe_fill_region = FALSE; |
617 | path->has_curve_to = TRUE; |
592 | - | ||
593 | /* coarse bounds */ |
618 | path->stroke_is_rectilinear = FALSE; |
594 | if (path->has_last_move_point) { |
- | |
595 | _cairo_path_fixed_extents_add (path, &path->last_move_point); |
- | |
596 | path->has_last_move_point = FALSE; |
- | |
597 | } |
- | |
Line 598... | Line 619... | ||
598 | _cairo_path_fixed_extents_add (path, &point[0]); |
619 | path->fill_is_rectilinear = FALSE; |
599 | _cairo_path_fixed_extents_add (path, &point[1]); |
620 | path->fill_maybe_region = FALSE; |
Line 600... | Line 621... | ||
600 | _cairo_path_fixed_extents_add (path, &point[2]); |
621 | path->fill_is_empty = FALSE; |
601 | 622 | ||
602 | return CAIRO_STATUS_SUCCESS; |
623 | return _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3); |
Line 628... | Line 649... | ||
628 | cairo_status_t status; |
649 | cairo_status_t status; |
Line 629... | Line 650... | ||
629 | 650 | ||
630 | if (! path->has_current_point) |
651 | if (! path->has_current_point) |
Line 631... | Line -... | ||
631 | return CAIRO_STATUS_SUCCESS; |
- | |
632 | - | ||
633 | /* If the previous op was also a LINE_TO back to the start, discard it */ |
- | |
634 | if (_cairo_path_last_op (path) == CAIRO_PATH_OP_LINE_TO) { |
- | |
635 | if (path->current_point.x == path->last_move_point.x && |
- | |
636 | path->current_point.y == path->last_move_point.y) |
- | |
637 | { |
- | |
638 | cairo_path_buf_t *buf; |
- | |
639 | cairo_point_t *p; |
- | |
640 | - | ||
641 | buf = cairo_path_tail (path); |
- | |
642 | if (likely (buf->num_points >= 2)) { |
652 | return CAIRO_STATUS_SUCCESS; |
643 | p = &buf->points[buf->num_points-2]; |
653 | |
644 | } else { |
654 | /* |
645 | cairo_path_buf_t *prev_buf = cairo_path_buf_prev (buf); |
655 | * Add a line_to, to compute flags and solve any degeneracy. |
646 | p = &prev_buf->points[prev_buf->num_points - (2 - buf->num_points)]; |
- | |
647 | } |
656 | * It will be removed later (if it was actually added). |
648 | 657 | */ |
|
649 | path->current_point = *p; |
658 | status = _cairo_path_fixed_line_to (path, |
650 | buf->num_ops--; |
- | |
651 | buf->num_points--; |
- | |
652 | } |
- | |
653 | } |
- | |
654 | 659 | path->last_move_point.x, |
|
655 | status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0); |
660 | path->last_move_point.y); |
Line -... | Line 661... | ||
- | 661 | if (unlikely (status)) |
|
656 | if (unlikely (status)) |
662 | return status; |
657 | return status; |
663 | |
- | 664 | /* |
|
- | 665 | * If the command used to close the path is a line_to, drop it. |
|
- | 666 | * We must check that last command is actually a line_to, |
|
- | 667 | * because the path could have been closed with a curve_to (and |
|
658 | 668 | * the previous line_to not added as it would be degenerate). |
|
- | 669 | */ |
|
- | 670 | if (_cairo_path_fixed_last_op (path) == CAIRO_PATH_OP_LINE_TO) |
|
- | 671 | _cairo_path_fixed_drop_line_to (path); |
|
- | 672 | ||
659 | return _cairo_path_fixed_move_to (path, |
673 | path->needs_move_to = TRUE; /* After close_path, add an implicit move_to */ |
Line 660... | Line 674... | ||
660 | path->last_move_point.x, |
674 | |
661 | path->last_move_point.y); |
675 | return _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0); |
662 | } |
676 | } |
Line 712... | Line 726... | ||
712 | _cairo_fixed_to_double (points[i].x), |
726 | _cairo_fixed_to_double (points[i].x), |
713 | _cairo_fixed_to_double (points[i].y)); |
727 | _cairo_fixed_to_double (points[i].y)); |
714 | } |
728 | } |
715 | len += snprintf (buf + len, sizeof (buf), "]"); |
729 | len += snprintf (buf + len, sizeof (buf), "]"); |
Line -... | Line 730... | ||
- | 730 | ||
716 | 731 | #define STRINGIFYFLAG(x) (path->x ? #x " " : "") |
|
717 | fprintf (stderr, |
732 | fprintf (stderr, |
718 | "_cairo_path_fixed_add (%s, %s)\n", |
733 | "_cairo_path_fixed_add (%s, %s) [%s%s%s%s%s%s%s%s]\n", |
- | 734 | op_str[(int) op], buf, |
|
- | 735 | STRINGIFYFLAG(has_current_point), |
|
- | 736 | STRINGIFYFLAG(needs_move_to), |
|
- | 737 | STRINGIFYFLAG(has_extents), |
|
- | 738 | STRINGIFYFLAG(has_curve_to), |
|
- | 739 | STRINGIFYFLAG(stroke_is_rectilinear), |
|
- | 740 | STRINGIFYFLAG(fill_is_rectilinear), |
|
- | 741 | STRINGIFYFLAG(fill_is_empty), |
|
- | 742 | STRINGIFYFLAG(fill_maybe_region) |
|
- | 743 | ); |
|
719 | op_str[(int) op], buf); |
744 | #undef STRINGIFYFLAG |
Line 720... | Line 745... | ||
720 | } |
745 | } |
721 | 746 | ||
Line 770... | Line 795... | ||
770 | static void |
795 | static void |
771 | _cairo_path_buf_add_points (cairo_path_buf_t *buf, |
796 | _cairo_path_buf_add_points (cairo_path_buf_t *buf, |
772 | const cairo_point_t *points, |
797 | const cairo_point_t *points, |
773 | int num_points) |
798 | int num_points) |
774 | { |
799 | { |
- | 800 | if (num_points == 0) |
|
- | 801 | return; |
|
- | 802 | ||
775 | memcpy (buf->points + buf->num_points, |
803 | memcpy (buf->points + buf->num_points, |
776 | points, |
804 | points, |
777 | sizeof (points[0]) * num_points); |
805 | sizeof (points[0]) * num_points); |
778 | buf->num_points += num_points; |
806 | buf->num_points += num_points; |
779 | } |
807 | } |
Line 780... | Line 808... | ||
780 | 808 | ||
781 | cairo_status_t |
809 | cairo_status_t |
782 | _cairo_path_fixed_interpret (const cairo_path_fixed_t *path, |
- | |
783 | cairo_direction_t dir, |
810 | _cairo_path_fixed_interpret (const cairo_path_fixed_t *path, |
784 | cairo_path_fixed_move_to_func_t *move_to, |
811 | cairo_path_fixed_move_to_func_t *move_to, |
785 | cairo_path_fixed_line_to_func_t *line_to, |
812 | cairo_path_fixed_line_to_func_t *line_to, |
786 | cairo_path_fixed_curve_to_func_t *curve_to, |
813 | cairo_path_fixed_curve_to_func_t *curve_to, |
787 | cairo_path_fixed_close_path_func_t *close_path, |
814 | cairo_path_fixed_close_path_func_t *close_path, |
788 | void *closure) |
815 | void *closure) |
789 | { |
- | |
790 | const uint8_t num_args[] = { |
816 | { |
791 | 1, /* cairo_path_move_to */ |
- | |
792 | 1, /* cairo_path_op_line_to */ |
- | |
793 | 3, /* cairo_path_op_curve_to */ |
- | |
794 | 0, /* cairo_path_op_close_path */ |
- | |
795 | }; |
817 | const cairo_path_buf_t *buf; |
796 | cairo_status_t status; |
- | |
797 | const cairo_path_buf_t *buf, *first; |
- | |
798 | cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD); |
- | |
799 | int step = forward ? 1 : -1; |
- | |
800 | - | ||
801 | buf = first = forward ? cairo_path_head (path) : cairo_path_tail (path); |
- | |
802 | do { |
- | |
803 | cairo_point_t *points; |
- | |
804 | int start, stop, i; |
- | |
805 | - | ||
806 | if (forward) { |
- | |
807 | start = 0; |
- | |
808 | stop = buf->num_ops; |
- | |
809 | points = buf->points; |
- | |
810 | } else { |
- | |
811 | start = buf->num_ops - 1; |
- | |
812 | stop = -1; |
- | |
813 | points = buf->points + buf->num_points; |
- | |
814 | } |
- | |
815 | - | ||
816 | for (i = start; i != stop; i += step) { |
- | |
Line 817... | Line 818... | ||
817 | cairo_path_op_t op = buf->op[i]; |
818 | cairo_status_t status; |
- | 819 | ||
818 | 820 | cairo_path_foreach_buf_start (buf, path) { |
|
Line -... | Line 821... | ||
- | 821 | const cairo_point_t *points = buf->points; |
|
819 | if (! forward) |
822 | unsigned int i; |
820 | points -= num_args[(int) op]; |
823 | |
821 | 824 | for (i = 0; i < buf->num_ops; i++) { |
|
- | 825 | switch (buf->op[i]) { |
|
822 | switch (op) { |
826 | case CAIRO_PATH_OP_MOVE_TO: |
823 | case CAIRO_PATH_OP_MOVE_TO: |
827 | status = (*move_to) (closure, &points[0]); |
824 | status = (*move_to) (closure, &points[0]); |
828 | points += 1; |
- | 829 | break; |
|
825 | break; |
830 | case CAIRO_PATH_OP_LINE_TO: |
826 | case CAIRO_PATH_OP_LINE_TO: |
831 | status = (*line_to) (closure, &points[0]); |
827 | status = (*line_to) (closure, &points[0]); |
832 | points += 1; |
- | 833 | break; |
|
828 | break; |
834 | case CAIRO_PATH_OP_CURVE_TO: |
829 | case CAIRO_PATH_OP_CURVE_TO: |
835 | status = (*curve_to) (closure, &points[0], &points[1], &points[2]); |
830 | status = (*curve_to) (closure, &points[0], &points[1], &points[2]); |
836 | points += 3; |
831 | break; |
837 | break; |
832 | default: |
838 | default: |
833 | ASSERT_NOT_REACHED; |
839 | ASSERT_NOT_REACHED; |
834 | case CAIRO_PATH_OP_CLOSE_PATH: |
840 | case CAIRO_PATH_OP_CLOSE_PATH: |
- | 841 | status = (*close_path) (closure); |
|
835 | status = (*close_path) (closure); |
842 | break; |
836 | break; |
843 | } |
837 | } |
- | |
838 | if (unlikely (status)) |
- | |
839 | return status; |
- | |
840 | 844 | ||
841 | if (forward) |
845 | if (unlikely (status)) |
Line 842... | Line 846... | ||
842 | points += num_args[(int) op]; |
846 | return status; |
843 | } |
847 | } |
Line 844... | Line 848... | ||
844 | } while ((buf = forward ? cairo_path_buf_next (buf) : cairo_path_buf_prev (buf)) != first); |
848 | } cairo_path_foreach_buf_end (buf, path); |
Line 899... | Line 903... | ||
899 | } |
903 | } |
Line 900... | Line 904... | ||
900 | 904 | ||
901 | cairo_status_t |
905 | cairo_status_t |
902 | _cairo_path_fixed_append (cairo_path_fixed_t *path, |
906 | _cairo_path_fixed_append (cairo_path_fixed_t *path, |
903 | const cairo_path_fixed_t *other, |
- | |
904 | cairo_direction_t dir, |
907 | const cairo_path_fixed_t *other, |
905 | cairo_fixed_t tx, |
908 | cairo_fixed_t tx, |
906 | cairo_fixed_t ty) |
909 | cairo_fixed_t ty) |
907 | { |
910 | { |
Line 908... | Line 911... | ||
908 | cairo_path_fixed_append_closure_t closure; |
911 | cairo_path_fixed_append_closure_t closure; |
909 | 912 | ||
910 | closure.path = path; |
913 | closure.path = path; |
Line 911... | Line 914... | ||
911 | closure.offset.x = tx; |
914 | closure.offset.x = tx; |
912 | closure.offset.y = ty; |
915 | closure.offset.y = ty; |
913 | 916 | ||
914 | return _cairo_path_fixed_interpret (other, dir, |
917 | return _cairo_path_fixed_interpret (other, |
915 | _append_move_to, |
918 | _append_move_to, |
916 | _append_line_to, |
919 | _append_line_to, |
Line 927... | Line 930... | ||
927 | cairo_fixed_t scaley) |
930 | cairo_fixed_t scaley) |
928 | { |
931 | { |
929 | cairo_path_buf_t *buf; |
932 | cairo_path_buf_t *buf; |
930 | unsigned int i; |
933 | unsigned int i; |
Line 931... | Line -... | ||
931 | - | ||
932 | if (path->maybe_fill_region) { |
- | |
933 | path->maybe_fill_region = _cairo_fixed_is_integer (offx) && |
934 | |
934 | _cairo_fixed_is_integer (offy) && |
935 | if (scalex == CAIRO_FIXED_ONE && scaley == CAIRO_FIXED_ONE) { |
935 | _cairo_fixed_is_integer (scalex) && |
936 | _cairo_path_fixed_translate (path, offx, offy); |
936 | _cairo_fixed_is_integer (scaley); |
937 | return; |
Line -... | Line 938... | ||
- | 938 | } |
|
- | 939 | ||
- | 940 | path->last_move_point.x = _cairo_fixed_mul (scalex, path->last_move_point.x) + offx; |
|
- | 941 | path->last_move_point.y = _cairo_fixed_mul (scaley, path->last_move_point.y) + offy; |
|
- | 942 | path->current_point.x = _cairo_fixed_mul (scalex, path->current_point.x) + offx; |
|
- | 943 | path->current_point.y = _cairo_fixed_mul (scaley, path->current_point.y) + offy; |
|
- | 944 | ||
937 | } |
945 | path->fill_maybe_region = TRUE; |
938 | 946 | ||
939 | cairo_path_foreach_buf_start (buf, path) { |
947 | cairo_path_foreach_buf_start (buf, path) { |
940 | for (i = 0; i < buf->num_points; i++) { |
948 | for (i = 0; i < buf->num_points; i++) { |
941 | if (scalex != CAIRO_FIXED_ONE) |
949 | if (scalex != CAIRO_FIXED_ONE) |
Line 942... | Line 950... | ||
942 | buf->points[i].x = _cairo_fixed_mul (buf->points[i].x, scalex); |
950 | buf->points[i].x = _cairo_fixed_mul (buf->points[i].x, scalex); |
943 | buf->points[i].x += offx; |
951 | buf->points[i].x += offx; |
944 | 952 | ||
- | 953 | if (scaley != CAIRO_FIXED_ONE) |
|
- | 954 | buf->points[i].y = _cairo_fixed_mul (buf->points[i].y, scaley); |
|
- | 955 | buf->points[i].y += offy; |
|
- | 956 | ||
- | 957 | if (path->fill_maybe_region) { |
|
945 | if (scaley != CAIRO_FIXED_ONE) |
958 | path->fill_maybe_region = _cairo_fixed_is_integer (buf->points[i].x) && |
946 | buf->points[i].y = _cairo_fixed_mul (buf->points[i].y, scaley); |
959 | _cairo_fixed_is_integer (buf->points[i].y); |
Line -... | Line 960... | ||
- | 960 | } |
|
- | 961 | } |
|
947 | buf->points[i].y += offy; |
962 | } cairo_path_foreach_buf_end (buf, path); |
948 | } |
963 | |
- | 964 | path->fill_maybe_region &= path->fill_is_rectilinear; |
|
- | 965 | ||
- | 966 | path->extents.p1.x = _cairo_fixed_mul (scalex, path->extents.p1.x) + offx; |
|
- | 967 | path->extents.p2.x = _cairo_fixed_mul (scalex, path->extents.p2.x) + offx; |
|
- | 968 | if (scalex < 0) { |
|
Line 949... | Line 969... | ||
949 | } cairo_path_foreach_buf_end (buf, path); |
969 | cairo_fixed_t t = path->extents.p1.x; |
950 | 970 | path->extents.p1.x = path->extents.p2.x; |
|
- | 971 | path->extents.p2.x = t; |
|
- | 972 | } |
|
- | 973 | ||
- | 974 | path->extents.p1.y = _cairo_fixed_mul (scaley, path->extents.p1.y) + offy; |
|
- | 975 | path->extents.p2.y = _cairo_fixed_mul (scaley, path->extents.p2.y) + offy; |
|
951 | path->extents.p1.x = _cairo_fixed_mul (scalex, path->extents.p1.x) + offx; |
976 | if (scaley < 0) { |
Line 952... | Line 977... | ||
952 | path->extents.p2.x = _cairo_fixed_mul (scalex, path->extents.p2.x) + offx; |
977 | cairo_fixed_t t = path->extents.p1.y; |
953 | 978 | path->extents.p1.y = path->extents.p2.y; |
|
954 | path->extents.p1.y = _cairo_fixed_mul (scaley, path->extents.p1.y) + offy; |
979 | path->extents.p2.y = t; |
Line 964... | Line 989... | ||
964 | unsigned int i; |
989 | unsigned int i; |
Line 965... | Line 990... | ||
965 | 990 | ||
966 | if (offx == 0 && offy == 0) |
991 | if (offx == 0 && offy == 0) |
Line 967... | Line -... | ||
967 | return; |
- | |
968 | - | ||
969 | if (path->maybe_fill_region && |
- | |
970 | ! (_cairo_fixed_is_integer (offx) && _cairo_fixed_is_integer (offy))) |
- | |
971 | { |
- | |
972 | path->maybe_fill_region = FALSE; |
- | |
973 | } |
992 | return; |
974 | 993 | ||
975 | path->last_move_point.x += offx; |
994 | path->last_move_point.x += offx; |
976 | path->last_move_point.y += offy; |
995 | path->last_move_point.y += offy; |
Line -... | Line 996... | ||
- | 996 | path->current_point.x += offx; |
|
- | 997 | path->current_point.y += offy; |
|
977 | path->current_point.x += offx; |
998 | |
978 | path->current_point.y += offy; |
999 | path->fill_maybe_region = TRUE; |
979 | 1000 | ||
980 | cairo_path_foreach_buf_start (buf, path) { |
1001 | cairo_path_foreach_buf_start (buf, path) { |
- | 1002 | for (i = 0; i < buf->num_points; i++) { |
|
- | 1003 | buf->points[i].x += offx; |
|
- | 1004 | buf->points[i].y += offy; |
|
- | 1005 | ||
- | 1006 | if (path->fill_maybe_region) { |
|
981 | for (i = 0; i < buf->num_points; i++) { |
1007 | path->fill_maybe_region = _cairo_fixed_is_integer (buf->points[i].x) && |
982 | buf->points[i].x += offx; |
1008 | _cairo_fixed_is_integer (buf->points[i].y); |
Line -... | Line 1009... | ||
- | 1009 | } |
|
- | 1010 | } |
|
983 | buf->points[i].y += offy; |
1011 | } cairo_path_foreach_buf_end (buf, path); |
984 | } |
1012 | |
985 | } cairo_path_foreach_buf_end (buf, path); |
1013 | path->fill_maybe_region &= path->fill_is_rectilinear; |
986 | 1014 | ||
987 | path->extents.p1.x += offx; |
1015 | path->extents.p1.x += offx; |
Line -... | Line 1016... | ||
- | 1016 | path->extents.p1.y += offy; |
|
- | 1017 | path->extents.p2.x += offx; |
|
- | 1018 | path->extents.p2.y += offy; |
|
- | 1019 | } |
|
- | 1020 | ||
- | 1021 | ||
- | 1022 | static inline void |
|
- | 1023 | _cairo_path_fixed_transform_point (cairo_point_t *p, |
|
- | 1024 | const cairo_matrix_t *matrix) |
|
- | 1025 | { |
|
- | 1026 | double dx, dy; |
|
- | 1027 | ||
- | 1028 | dx = _cairo_fixed_to_double (p->x); |
|
- | 1029 | dy = _cairo_fixed_to_double (p->y); |
|
988 | path->extents.p1.y += offy; |
1030 | cairo_matrix_transform_point (matrix, &dx, &dy); |
989 | path->extents.p2.x += offx; |
1031 | p->x = _cairo_fixed_from_double (dx); |
990 | path->extents.p2.y += offy; |
1032 | p->y = _cairo_fixed_from_double (dy); |
991 | } |
1033 | } |
992 | 1034 | ||
Line 1001... | Line 1043... | ||
1001 | **/ |
1043 | **/ |
1002 | void |
1044 | void |
1003 | _cairo_path_fixed_transform (cairo_path_fixed_t *path, |
1045 | _cairo_path_fixed_transform (cairo_path_fixed_t *path, |
1004 | const cairo_matrix_t *matrix) |
1046 | const cairo_matrix_t *matrix) |
1005 | { |
1047 | { |
- | 1048 | cairo_box_t extents; |
|
- | 1049 | cairo_point_t point; |
|
1006 | cairo_path_buf_t *buf; |
1050 | cairo_path_buf_t *buf; |
1007 | unsigned int i; |
1051 | unsigned int i; |
1008 | double dx, dy; |
- | |
1009 | - | ||
1010 | /* XXX current_point, last_move_to */ |
- | |
Line 1011... | Line 1052... | ||
1011 | 1052 | ||
1012 | if (matrix->yx == 0.0 && matrix->xy == 0.0) { |
1053 | if (matrix->yx == 0.0 && matrix->xy == 0.0) { |
1013 | /* Fast path for the common case of scale+transform */ |
- | |
1014 | if (matrix->xx == 1. && matrix->yy == 1.) { |
- | |
1015 | _cairo_path_fixed_translate (path, |
- | |
1016 | _cairo_fixed_from_double (matrix->x0), |
- | |
1017 | _cairo_fixed_from_double (matrix->y0)); |
- | |
1018 | } else { |
1054 | /* Fast path for the common case of scale+transform */ |
1019 | _cairo_path_fixed_offset_and_scale (path, |
1055 | _cairo_path_fixed_offset_and_scale (path, |
1020 | _cairo_fixed_from_double (matrix->x0), |
1056 | _cairo_fixed_from_double (matrix->x0), |
1021 | _cairo_fixed_from_double (matrix->y0), |
1057 | _cairo_fixed_from_double (matrix->y0), |
1022 | _cairo_fixed_from_double (matrix->xx), |
1058 | _cairo_fixed_from_double (matrix->xx), |
1023 | _cairo_fixed_from_double (matrix->yy)); |
- | |
1024 | } |
1059 | _cairo_fixed_from_double (matrix->yy)); |
1025 | return; |
1060 | return; |
Line 1026... | Line -... | ||
1026 | } |
- | |
1027 | - | ||
1028 | path->extents.p1.x = path->extents.p1.y = INT_MAX; |
- | |
1029 | path->extents.p2.x = path->extents.p2.y = INT_MIN; |
- | |
1030 | path->maybe_fill_region = FALSE; |
- | |
1031 | cairo_path_foreach_buf_start (buf, path) { |
1061 | } |
1032 | for (i = 0; i < buf->num_points; i++) { |
1062 | |
Line 1033... | Line 1063... | ||
1033 | dx = _cairo_fixed_to_double (buf->points[i].x); |
1063 | _cairo_path_fixed_transform_point (&path->last_move_point, matrix); |
- | 1064 | _cairo_path_fixed_transform_point (&path->current_point, matrix); |
|
- | 1065 | ||
Line -... | Line 1066... | ||
- | 1066 | buf = cairo_path_head (path); |
|
- | 1067 | if (buf->num_points == 0) |
|
1034 | dy = _cairo_fixed_to_double (buf->points[i].y); |
1068 | return; |
1035 | 1069 | ||
Line 1036... | Line 1070... | ||
1036 | cairo_matrix_transform_point (matrix, &dx, &dy); |
1070 | extents = path->extents; |
- | 1071 | point = buf->points[0]; |
|
1037 | 1072 | _cairo_path_fixed_transform_point (&point, matrix); |
|
- | 1073 | _cairo_box_set (&path->extents, &point, &point); |
|
1038 | buf->points[i].x = _cairo_fixed_from_double (dx); |
1074 | |
1039 | buf->points[i].y = _cairo_fixed_from_double (dy); |
1075 | cairo_path_foreach_buf_start (buf, path) { |
1040 | - | ||
Line 1041... | Line -... | ||
1041 | /* XXX need to eliminate surplus move-to's? */ |
- | |
1042 | _cairo_path_fixed_extents_add (path, &buf->points[i]); |
- | |
1043 | } |
1076 | for (i = 0; i < buf->num_points; i++) { |
1044 | } cairo_path_foreach_buf_end (buf, path); |
- | |
1045 | } |
1077 | _cairo_path_fixed_transform_point (&buf->points[i], matrix); |
Line 1046... | Line 1078... | ||
1046 | 1078 | _cairo_box_add_point (&path->extents, &buf->points[i]); |
|
1047 | cairo_bool_t |
- | |
1048 | _cairo_path_fixed_is_equal (const cairo_path_fixed_t *path, |
- | |
1049 | const cairo_path_fixed_t *other) |
- | |
1050 | { |
1079 | } |
1051 | const cairo_path_buf_t *path_buf, *other_buf; |
- | |
1052 | - | ||
1053 | if (path->current_point.x != other->current_point.x || |
1080 | } cairo_path_foreach_buf_end (buf, path); |
1054 | path->current_point.y != other->current_point.y || |
- | |
1055 | path->has_current_point != other->has_current_point || |
- | |
1056 | path->has_curve_to != other->has_curve_to || |
- | |
Line 1057... | Line 1081... | ||
1057 | path->is_rectilinear != other->is_rectilinear || |
1081 | |
1058 | path->maybe_fill_region != other->maybe_fill_region || |
- | |
1059 | path->last_move_point.x != other->last_move_point.x || |
- | |
1060 | path->last_move_point.y != other->last_move_point.y) |
- | |
1061 | { |
1082 | if (path->has_curve_to) { |
1062 | return FALSE; |
- | |
1063 | } |
- | |
1064 | - | ||
1065 | other_buf = cairo_path_head (other); |
1083 | cairo_bool_t is_tight; |
1066 | cairo_path_foreach_buf_start (path_buf, path) { |
1084 | |
1067 | if (path_buf->num_ops != other_buf->num_ops || |
1085 | _cairo_matrix_transform_bounding_box_fixed (matrix, &extents, &is_tight); |
1068 | path_buf->num_points != other_buf->num_points || |
- | |
1069 | memcmp (path_buf->op, other_buf->op, |
- | |
Line -... | Line 1086... | ||
- | 1086 | if (!is_tight) { |
|
- | 1087 | cairo_bool_t has_extents; |
|
- | 1088 | ||
1070 | sizeof (cairo_path_op_t) * path_buf->num_ops) != 0 || |
1089 | has_extents = _cairo_path_bounder_extents (path, &extents); |
- | 1090 | assert (has_extents); |
|
1071 | memcmp (path_buf->points, other_buf->points, |
1091 | } |
Line 1072... | Line 1092... | ||
1072 | sizeof (cairo_point_t) * path_buf->num_points) != 0) |
1092 | path->extents = extents; |
1073 | { |
1093 | } |
1074 | return FALSE; |
1094 | |
Line 1121... | Line 1141... | ||
1121 | cairo_spline_t spline; |
1141 | cairo_spline_t spline; |
Line 1122... | Line 1142... | ||
1122 | 1142 | ||
Line 1123... | Line 1143... | ||
1123 | cairo_point_t *p0 = &cpf->current_point; |
1143 | cairo_point_t *p0 = &cpf->current_point; |
1124 | 1144 | ||
1125 | if (! _cairo_spline_init (&spline, |
1145 | if (! _cairo_spline_init (&spline, |
1126 | cpf->line_to, |
1146 | (cairo_spline_add_point_func_t)cpf->line_to, |
1127 | cpf->closure, |
1147 | cpf->closure, |
1128 | p0, p1, p2, p3)) |
1148 | p0, p1, p2, p3)) |
1129 | { |
1149 | { |
Line 1143... | Line 1163... | ||
1143 | return cpf->close_path (cpf->closure); |
1163 | return cpf->close_path (cpf->closure); |
1144 | } |
1164 | } |
Line 1145... | Line 1165... | ||
1145 | 1165 | ||
1146 | cairo_status_t |
1166 | cairo_status_t |
1147 | _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path, |
- | |
1148 | cairo_direction_t dir, |
1167 | _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path, |
1149 | cairo_path_fixed_move_to_func_t *move_to, |
1168 | cairo_path_fixed_move_to_func_t *move_to, |
1150 | cairo_path_fixed_line_to_func_t *line_to, |
1169 | cairo_path_fixed_line_to_func_t *line_to, |
1151 | cairo_path_fixed_close_path_func_t *close_path, |
1170 | cairo_path_fixed_close_path_func_t *close_path, |
1152 | void *closure, |
1171 | void *closure, |
1153 | double tolerance) |
1172 | double tolerance) |
1154 | { |
1173 | { |
Line 1155... | Line 1174... | ||
1155 | cpf_t flattener; |
1174 | cpf_t flattener; |
1156 | 1175 | ||
1157 | if (! path->has_curve_to) { |
1176 | if (! path->has_curve_to) { |
1158 | return _cairo_path_fixed_interpret (path, dir, |
1177 | return _cairo_path_fixed_interpret (path, |
1159 | move_to, |
1178 | move_to, |
1160 | line_to, |
1179 | line_to, |
1161 | NULL, |
1180 | NULL, |
Line 1166... | Line 1185... | ||
1166 | flattener.tolerance = tolerance; |
1185 | flattener.tolerance = tolerance; |
1167 | flattener.move_to = move_to; |
1186 | flattener.move_to = move_to; |
1168 | flattener.line_to = line_to; |
1187 | flattener.line_to = line_to; |
1169 | flattener.close_path = close_path; |
1188 | flattener.close_path = close_path; |
1170 | flattener.closure = closure; |
1189 | flattener.closure = closure; |
1171 | return _cairo_path_fixed_interpret (path, dir, |
1190 | return _cairo_path_fixed_interpret (path, |
1172 | _cpf_move_to, |
1191 | _cpf_move_to, |
1173 | _cpf_line_to, |
1192 | _cpf_line_to, |
1174 | _cpf_curve_to, |
1193 | _cpf_curve_to, |
1175 | _cpf_close_path, |
1194 | _cpf_close_path, |
1176 | &flattener); |
1195 | &flattener); |
Line 1196... | Line 1215... | ||
1196 | box->p1.y = p2->y; |
1215 | box->p1.y = p2->y; |
1197 | box->p2.y = p1->y; |
1216 | box->p2.y = p1->y; |
1198 | } |
1217 | } |
1199 | } |
1218 | } |
Line 1200... | Line -... | ||
1200 | - | ||
1201 | /* |
- | |
1202 | * Check whether the given path contains a single rectangle. |
- | |
1203 | */ |
1219 | |
1204 | cairo_bool_t |
1220 | static inline cairo_bool_t |
1205 | _cairo_path_fixed_is_box (const cairo_path_fixed_t *path, |
- | |
1206 | cairo_box_t *box) |
1221 | _path_is_quad (const cairo_path_fixed_t *path) |
1207 | { |
1222 | { |
Line 1208... | Line -... | ||
1208 | const cairo_path_buf_t *buf = cairo_path_head (path); |
- | |
1209 | - | ||
1210 | if (! path->is_rectilinear) |
- | |
1211 | return FALSE; |
1223 | const cairo_path_buf_t *buf = cairo_path_head (path); |
1212 | 1224 | ||
1213 | /* Do we have the right number of ops? */ |
1225 | /* Do we have the right number of ops? */ |
Line 1214... | Line 1226... | ||
1214 | if (buf->num_ops < 4 || buf->num_ops > 6) |
1226 | if (buf->num_ops < 4 || buf->num_ops > 6) |
Line 1242... | Line 1254... | ||
1242 | buf->op[5] != CAIRO_PATH_OP_CLOSE_PATH) |
1254 | buf->op[5] != CAIRO_PATH_OP_CLOSE_PATH) |
1243 | return FALSE; |
1255 | return FALSE; |
1244 | } |
1256 | } |
1245 | } |
1257 | } |
Line -... | Line 1258... | ||
- | 1258 | ||
- | 1259 | return TRUE; |
|
- | 1260 | } |
|
- | 1261 | ||
- | 1262 | static inline cairo_bool_t |
|
- | 1263 | _points_form_rect (const cairo_point_t *points) |
|
- | 1264 | { |
|
- | 1265 | if (points[0].y == points[1].y && |
|
- | 1266 | points[1].x == points[2].x && |
|
- | 1267 | points[2].y == points[3].y && |
|
- | 1268 | points[3].x == points[0].x) |
|
- | 1269 | return TRUE; |
|
- | 1270 | if (points[0].x == points[1].x && |
|
- | 1271 | points[1].y == points[2].y && |
|
- | 1272 | points[2].x == points[3].x && |
|
- | 1273 | points[3].y == points[0].y) |
|
- | 1274 | return TRUE; |
|
- | 1275 | return FALSE; |
|
- | 1276 | } |
|
- | 1277 | ||
- | 1278 | /* |
|
- | 1279 | * Check whether the given path contains a single rectangle. |
|
- | 1280 | */ |
|
- | 1281 | cairo_bool_t |
|
- | 1282 | _cairo_path_fixed_is_box (const cairo_path_fixed_t *path, |
|
- | 1283 | cairo_box_t *box) |
|
- | 1284 | { |
|
- | 1285 | const cairo_path_buf_t *buf; |
|
- | 1286 | ||
- | 1287 | if (! path->fill_is_rectilinear) |
|
- | 1288 | return FALSE; |
|
- | 1289 | ||
- | 1290 | if (! _path_is_quad (path)) |
|
- | 1291 | return FALSE; |
|
- | 1292 | ||
- | 1293 | buf = cairo_path_head (path); |
|
- | 1294 | if (_points_form_rect (buf->points)) { |
|
- | 1295 | _canonical_box (box, &buf->points[0], &buf->points[2]); |
|
- | 1296 | return TRUE; |
|
- | 1297 | } |
|
- | 1298 | ||
- | 1299 | return FALSE; |
|
- | 1300 | } |
|
- | 1301 | ||
- | 1302 | /* Determine whether two lines A->B and C->D intersect based on the |
|
- | 1303 | * algorithm described here: http://paulbourke.net/geometry/pointlineplane/ */ |
|
- | 1304 | static inline cairo_bool_t |
|
- | 1305 | _lines_intersect_or_are_coincident (cairo_point_t a, |
|
- | 1306 | cairo_point_t b, |
|
- | 1307 | cairo_point_t c, |
|
- | 1308 | cairo_point_t d) |
|
- | 1309 | { |
|
- | 1310 | cairo_int64_t numerator_a, numerator_b, denominator; |
|
- | 1311 | cairo_bool_t denominator_negative; |
|
- | 1312 | ||
- | 1313 | denominator = _cairo_int64_sub (_cairo_int32x32_64_mul (d.y - c.y, b.x - a.x), |
|
- | 1314 | _cairo_int32x32_64_mul (d.x - c.x, b.y - a.y)); |
|
- | 1315 | numerator_a = _cairo_int64_sub (_cairo_int32x32_64_mul (d.x - c.x, a.y - c.y), |
|
- | 1316 | _cairo_int32x32_64_mul (d.y - c.y, a.x - c.x)); |
|
- | 1317 | numerator_b = _cairo_int64_sub (_cairo_int32x32_64_mul (b.x - a.x, a.y - c.y), |
|
- | 1318 | _cairo_int32x32_64_mul (b.y - a.y, a.x - c.x)); |
|
- | 1319 | ||
- | 1320 | if (_cairo_int64_is_zero (denominator)) { |
|
- | 1321 | /* If the denominator and numerators are both zero, |
|
- | 1322 | * the lines are coincident. */ |
|
- | 1323 | if (_cairo_int64_is_zero (numerator_a) && _cairo_int64_is_zero (numerator_b)) |
|
- | 1324 | return TRUE; |
|
- | 1325 | ||
- | 1326 | /* Otherwise, a zero denominator indicates the lines are |
|
- | 1327 | * parallel and never intersect. */ |
|
- | 1328 | return FALSE; |
|
- | 1329 | } |
|
- | 1330 | ||
- | 1331 | /* The lines intersect if both quotients are between 0 and 1 (exclusive). */ |
|
- | 1332 | ||
- | 1333 | /* We first test whether either quotient is a negative number. */ |
|
- | 1334 | denominator_negative = _cairo_int64_negative (denominator); |
|
- | 1335 | if (_cairo_int64_negative (numerator_a) ^ denominator_negative) |
|
- | 1336 | return FALSE; |
|
- | 1337 | if (_cairo_int64_negative (numerator_b) ^ denominator_negative) |
|
- | 1338 | return FALSE; |
|
- | 1339 | ||
- | 1340 | /* A zero quotient indicates an "intersection" at an endpoint, which |
|
- | 1341 | * we aren't considering a true intersection. */ |
|
- | 1342 | if (_cairo_int64_is_zero (numerator_a) || _cairo_int64_is_zero (numerator_b)) |
|
- | 1343 | return FALSE; |
|
- | 1344 | ||
- | 1345 | /* If the absolute value of the numerator is larger than or equal to the |
|
- | 1346 | * denominator the result of the division would be greater than or equal |
|
- | 1347 | * to one. */ |
|
- | 1348 | if (! denominator_negative) { |
|
- | 1349 | if (! _cairo_int64_lt (numerator_a, denominator) || |
|
- | 1350 | ! _cairo_int64_lt (numerator_b, denominator)) |
|
- | 1351 | return FALSE; |
|
- | 1352 | } else { |
|
- | 1353 | if (! _cairo_int64_lt (denominator, numerator_a) || |
|
- | 1354 | ! _cairo_int64_lt (denominator, numerator_b)) |
|
- | 1355 | return FALSE; |
|
- | 1356 | } |
|
- | 1357 | ||
- | 1358 | return TRUE; |
|
- | 1359 | } |
|
- | 1360 | ||
- | 1361 | cairo_bool_t |
|
- | 1362 | _cairo_path_fixed_is_simple_quad (const cairo_path_fixed_t *path) |
|
- | 1363 | { |
|
- | 1364 | const cairo_point_t *points; |
|
- | 1365 | ||
- | 1366 | if (! _path_is_quad (path)) |
|
- | 1367 | return FALSE; |
|
- | 1368 | ||
- | 1369 | points = cairo_path_head (path)->points; |
|
- | 1370 | if (_points_form_rect (points)) |
|
- | 1371 | return TRUE; |
|
- | 1372 | ||
- | 1373 | if (_lines_intersect_or_are_coincident (points[0], points[1], |
|
- | 1374 | points[3], points[2])) |
|
- | 1375 | return FALSE; |
|
- | 1376 | ||
- | 1377 | if (_lines_intersect_or_are_coincident (points[0], points[3], |
|
- | 1378 | points[1], points[2])) |
|
- | 1379 | return FALSE; |
|
- | 1380 | ||
- | 1381 | return TRUE; |
|
- | 1382 | } |
|
- | 1383 | ||
- | 1384 | cairo_bool_t |
|
- | 1385 | _cairo_path_fixed_is_stroke_box (const cairo_path_fixed_t *path, |
|
- | 1386 | cairo_box_t *box) |
|
- | 1387 | { |
|
- | 1388 | const cairo_path_buf_t *buf = cairo_path_head (path); |
|
- | 1389 | ||
- | 1390 | if (! path->fill_is_rectilinear) |
|
- | 1391 | return FALSE; |
|
- | 1392 | ||
- | 1393 | /* Do we have the right number of ops? */ |
|
- | 1394 | if (buf->num_ops != 5) |
|
- | 1395 | return FALSE; |
|
- | 1396 | ||
- | 1397 | /* Check whether the ops are those that would be used for a rectangle */ |
|
- | 1398 | if (buf->op[0] != CAIRO_PATH_OP_MOVE_TO || |
|
- | 1399 | buf->op[1] != CAIRO_PATH_OP_LINE_TO || |
|
- | 1400 | buf->op[2] != CAIRO_PATH_OP_LINE_TO || |
|
- | 1401 | buf->op[3] != CAIRO_PATH_OP_LINE_TO || |
|
- | 1402 | buf->op[4] != CAIRO_PATH_OP_CLOSE_PATH) |
|
- | 1403 | { |
|
- | 1404 | return FALSE; |
|
- | 1405 | } |
|
1246 | 1406 | ||
1247 | /* Ok, we may have a box, if the points line up */ |
1407 | /* Ok, we may have a box, if the points line up */ |
1248 | if (buf->points[0].y == buf->points[1].y && |
1408 | if (buf->points[0].y == buf->points[1].y && |
1249 | buf->points[1].x == buf->points[2].x && |
1409 | buf->points[1].x == buf->points[2].x && |
1250 | buf->points[2].y == buf->points[3].y && |
1410 | buf->points[2].y == buf->points[3].y && |
Line 1284... | Line 1444... | ||
1284 | const cairo_path_buf_t *buf; |
1444 | const cairo_path_buf_t *buf; |
Line 1285... | Line 1445... | ||
1285 | 1445 | ||
1286 | if (! _cairo_path_fixed_is_box (path, box)) |
1446 | if (! _cairo_path_fixed_is_box (path, box)) |
Line -... | Line 1447... | ||
- | 1447 | return FALSE; |
|
- | 1448 | ||
- | 1449 | /* This check is valid because the current implementation of |
|
1287 | return FALSE; |
1450 | * _cairo_path_fixed_is_box () only accepts rectangles like: |
1288 | 1451 | * move,line,line,line[,line|close[,close|move]]. */ |
|
1289 | buf = cairo_path_head (path); |
1452 | buf = cairo_path_head (path); |
Line 1290... | Line 1453... | ||
1290 | if (buf->points[0].y == buf->points[1].y) |
1453 | if (buf->num_ops > 4) |
1291 | return TRUE; |
1454 | return TRUE; |
Line 1329... | Line 1492... | ||
1329 | if (_iter->buf == NULL) |
1492 | if (_iter->buf == NULL) |
1330 | return FALSE; |
1493 | return FALSE; |
Line 1331... | Line 1494... | ||
1331 | 1494 | ||
Line 1332... | Line -... | ||
1332 | iter = *_iter; |
- | |
1333 | 1495 | iter = *_iter; |
|
1334 | if (iter.n_op == iter.buf->num_ops && |
- | |
1335 | ! _cairo_path_fixed_iter_next_op (&iter)) |
1496 | |
1336 | { |
- | |
Line 1337... | Line 1497... | ||
1337 | return FALSE; |
1497 | if (iter.n_op == iter.buf->num_ops && ! _cairo_path_fixed_iter_next_op (&iter)) |
1338 | } |
1498 | return FALSE; |
1339 | 1499 | ||
1340 | /* Check whether the ops are those that would be used for a rectangle */ |
1500 | /* Check whether the ops are those that would be used for a rectangle */ |
Line 1348... | Line 1508... | ||
1348 | return FALSE; |
1508 | return FALSE; |
1349 | points[1] = iter.buf->points[iter.n_point++]; |
1509 | points[1] = iter.buf->points[iter.n_point++]; |
1350 | if (! _cairo_path_fixed_iter_next_op (&iter)) |
1510 | if (! _cairo_path_fixed_iter_next_op (&iter)) |
1351 | return FALSE; |
1511 | return FALSE; |
Line -... | Line 1512... | ||
- | 1512 | ||
1352 | 1513 | /* a horizontal/vertical closed line is also a degenerate rectangle */ |
|
- | 1514 | switch (iter.buf->op[iter.n_op]) { |
|
- | 1515 | case CAIRO_PATH_OP_CLOSE_PATH: |
|
- | 1516 | _cairo_path_fixed_iter_next_op (&iter); |
|
- | 1517 | case CAIRO_PATH_OP_MOVE_TO: /* implicit close */ |
|
- | 1518 | box->p1 = box->p2 = points[0]; |
|
- | 1519 | *_iter = iter; |
|
- | 1520 | return TRUE; |
|
1353 | if (iter.buf->op[iter.n_op] != CAIRO_PATH_OP_LINE_TO) |
1521 | default: |
- | 1522 | return FALSE; |
|
- | 1523 | case CAIRO_PATH_OP_LINE_TO: |
|
- | 1524 | break; |
|
- | 1525 | } |
|
1354 | return FALSE; |
1526 | |
1355 | points[2] = iter.buf->points[iter.n_point++]; |
1527 | points[2] = iter.buf->points[iter.n_point++]; |
1356 | if (! _cairo_path_fixed_iter_next_op (&iter)) |
1528 | if (! _cairo_path_fixed_iter_next_op (&iter)) |
Line 1357... | Line 1529... | ||
1357 | return FALSE; |
1529 | return FALSE; |
1358 | 1530 | ||
1359 | if (iter.buf->op[iter.n_op] != CAIRO_PATH_OP_LINE_TO) |
1531 | if (iter.buf->op[iter.n_op] != CAIRO_PATH_OP_LINE_TO) |
1360 | return FALSE; |
- | |
1361 | points[3] = iter.buf->points[iter.n_point++]; |
- | |
Line 1362... | Line 1532... | ||
1362 | if (! _cairo_path_fixed_iter_next_op (&iter)) |
1532 | return FALSE; |
1363 | return FALSE; |
1533 | points[3] = iter.buf->points[iter.n_point++]; |
1364 | 1534 | ||
- | 1535 | /* Now, there are choices. The rectangle might end with a LINE_TO |
|
- | 1536 | * (to the original point), but this isn't required. If it |
|
1365 | /* Now, there are choices. The rectangle might end with a LINE_TO |
1537 | * doesn't, then it must end with a CLOSE_PATH (which may be implicit). */ |
1366 | * (to the original point), but this isn't required. If it |
- | |
1367 | * doesn't, then it must end with a CLOSE_PATH (which may be implicit). */ |
1538 | if (! _cairo_path_fixed_iter_next_op (&iter)) { |
1368 | if (iter.buf->op[iter.n_op] == CAIRO_PATH_OP_LINE_TO) |
1539 | /* implicit close due to fill */ |
1369 | { |
1540 | } else if (iter.buf->op[iter.n_op] == CAIRO_PATH_OP_LINE_TO) { |
1370 | points[4] = iter.buf->points[iter.n_point++]; |
1541 | points[4] = iter.buf->points[iter.n_point++]; |
1371 | if (points[4].x != points[0].x || points[4].y != points[0].y) |
1542 | if (points[4].x != points[0].x || points[4].y != points[0].y) |
- | 1543 | return FALSE; |
|
1372 | return FALSE; |
1544 | _cairo_path_fixed_iter_next_op (&iter); |
- | 1545 | } else if (iter.buf->op[iter.n_op] == CAIRO_PATH_OP_CLOSE_PATH) { |
|
1373 | } |
1546 | _cairo_path_fixed_iter_next_op (&iter); |
1374 | else if (! (iter.buf->op[iter.n_op] == CAIRO_PATH_OP_CLOSE_PATH || |
1547 | } else if (iter.buf->op[iter.n_op] == CAIRO_PATH_OP_MOVE_TO) { |
1375 | iter.buf->op[iter.n_op] == CAIRO_PATH_OP_MOVE_TO)) |
1548 | /* implicit close-path due to new-sub-path */ |
1376 | { |
- | |
1377 | return FALSE; |
- | |
Line 1378... | Line 1549... | ||
1378 | } |
1549 | } else { |
1379 | if (! _cairo_path_fixed_iter_next_op (&iter)) |
1550 | return FALSE; |
1380 | return FALSE; |
1551 | } |
1381 | 1552 | ||
Line 1409... | Line 1580... | ||
1409 | _cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter) |
1580 | _cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter) |
1410 | { |
1581 | { |
1411 | if (iter->buf == NULL) |
1582 | if (iter->buf == NULL) |
1412 | return TRUE; |
1583 | return TRUE; |
Line 1413... | Line 1584... | ||
1413 | 1584 | ||
1414 | if (iter->n_op == iter->buf->num_ops) |
- | |
1415 | return TRUE; |
- | |
1416 | - | ||
1417 | if (iter->buf->op[iter->n_op] == CAIRO_PATH_OP_MOVE_TO && |
- | |
1418 | iter->buf->num_ops == iter->n_op + 1) |
- | |
1419 | { |
- | |
1420 | return TRUE; |
- | |
1421 | } |
- | |
1422 | - | ||
1423 | return FALSE; |
1585 | return iter->n_op == iter->buf->num_ops; |