1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2002 University of Southern California
5 * Copyright © 2005 Red Hat, Inc.
6 * Copyright © 2011 Intel Corporation
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
37 * Carl D. Worth <cworth@cworth.org>
38 * Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
39 * Chris Wilson <chris@chris-wilson.co.uk>
44 #include "cairo-box-inline.h"
45 #include "cairo-boxes-private.h"
46 #include "cairo-clip-inline.h"
47 #include "cairo-clip-private.h"
48 #include "cairo-composite-rectangles-private.h"
49 #include "cairo-compositor-private.h"
50 #include "cairo-error-private.h"
51 #include "cairo-image-surface-private.h"
52 #include "cairo-pattern-inline.h"
53 #include "cairo-paginated-private.h"
54 #include "cairo-recording-surface-inline.h"
55 #include "cairo-surface-subsurface-private.h"
56 #include "cairo-surface-snapshot-inline.h"
57 #include "cairo-surface-observer-private.h"
58 #include "cairo-region-private.h"
59 #include "cairo-spans-private.h"
60 #include "cairo-traps-private.h"
61 #include "cairo-tristrip-private.h"
63 typedef cairo_int_status_t
64 (*draw_func_t
) (const cairo_traps_compositor_t
*compositor
,
73 const cairo_rectangle_int_t
*extents
,
76 static void do_unaligned_row(void (*blt
)(void *closure
,
85 int x1
= _cairo_fixed_integer_part (b
->p1
.x
) - tx
;
86 int x2
= _cairo_fixed_integer_part (b
->p2
.x
) - tx
;
88 if (! _cairo_fixed_is_integer (b
->p1
.x
)) {
89 blt(closure
, x1
, y
, 1, h
,
90 coverage
* (256 - _cairo_fixed_fractional_part (b
->p1
.x
)));
95 blt(closure
, x1
, y
, x2
-x1
, h
, (coverage
<< 8) - (coverage
>> 8));
97 if (! _cairo_fixed_is_integer (b
->p2
.x
))
98 blt(closure
, x2
, y
, 1, h
,
99 coverage
* _cairo_fixed_fractional_part (b
->p2
.x
));
101 blt(closure
, x1
, y
, 1, h
,
102 coverage
* (b
->p2
.x
- b
->p1
.x
));
105 static void do_unaligned_box(void (*blt
)(void *closure
,
106 int16_t x
, int16_t y
,
107 int16_t w
, int16_t h
,
110 const cairo_box_t
*b
, int tx
, int ty
)
112 int y1
= _cairo_fixed_integer_part (b
->p1
.y
) - ty
;
113 int y2
= _cairo_fixed_integer_part (b
->p2
.y
) - ty
;
115 if (! _cairo_fixed_is_integer (b
->p1
.y
)) {
116 do_unaligned_row(blt
, closure
, b
, tx
, y1
, 1,
117 256 - _cairo_fixed_fractional_part (b
->p1
.y
));
122 do_unaligned_row(blt
, closure
, b
, tx
, y1
, y2
-y1
, 256);
124 if (! _cairo_fixed_is_integer (b
->p2
.y
))
125 do_unaligned_row(blt
, closure
, b
, tx
, y2
, 1,
126 _cairo_fixed_fractional_part (b
->p2
.y
));
128 do_unaligned_row(blt
, closure
, b
, tx
, y1
, 1,
133 const cairo_traps_compositor_t
*compositor
;
134 cairo_surface_t
*dst
;
138 static void blt_in(void *closure
,
139 int16_t x
, int16_t y
,
140 int16_t w
, int16_t h
,
143 struct blt_in
*info
= closure
;
146 if (CAIRO_ALPHA_SHORT_IS_OPAQUE (coverage
))
149 _cairo_box_from_integers (&info
->boxes
.chunks
.base
[0], x
, y
, w
, h
);
151 _cairo_color_init_rgba (&color
, 0, 0, 0, coverage
/ (double) 0xffff);
152 info
->compositor
->fill_boxes (info
->dst
,
153 CAIRO_OPERATOR_IN
, &color
,
158 add_rect_with_offset (cairo_boxes_t
*boxes
, int x1
, int y1
, int x2
, int y2
, int dx
, int dy
)
161 cairo_int_status_t status
;
163 box
.p1
.x
= _cairo_fixed_from_int (x1
- dx
);
164 box
.p1
.y
= _cairo_fixed_from_int (y1
- dy
);
165 box
.p2
.x
= _cairo_fixed_from_int (x2
- dx
);
166 box
.p2
.y
= _cairo_fixed_from_int (y2
- dy
);
168 status
= _cairo_boxes_add (boxes
, CAIRO_ANTIALIAS_DEFAULT
, &box
);
169 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
172 static cairo_int_status_t
173 combine_clip_as_traps (const cairo_traps_compositor_t
*compositor
,
174 cairo_surface_t
*mask
,
175 const cairo_clip_t
*clip
,
176 const cairo_rectangle_int_t
*extents
)
178 cairo_polygon_t polygon
;
179 cairo_fill_rule_t fill_rule
;
180 cairo_antialias_t antialias
;
182 cairo_surface_t
*src
;
184 cairo_rectangle_int_t fixup
;
186 cairo_int_status_t status
;
188 TRACE ((stderr
, "%s\n", __FUNCTION__
));
190 status
= _cairo_clip_get_polygon (clip
, &polygon
,
191 &fill_rule
, &antialias
);
195 _cairo_traps_init (&traps
);
196 status
= _cairo_bentley_ottmann_tessellate_polygon (&traps
,
199 _cairo_polygon_fini (&polygon
);
200 if (unlikely (status
))
203 src
= compositor
->pattern_to_surface (mask
, NULL
, FALSE
,
206 if (unlikely (src
->status
)) {
207 _cairo_traps_fini (&traps
);
211 status
= compositor
->composite_traps (mask
, CAIRO_OPERATOR_IN
, src
,
213 extents
->x
, extents
->y
,
217 _cairo_traps_extents (&traps
, &box
);
218 _cairo_box_round_to_rectangle (&box
, &fixup
);
219 _cairo_traps_fini (&traps
);
220 cairo_surface_destroy (src
);
222 if (unlikely (status
))
225 if (! _cairo_rectangle_intersect (&fixup
, extents
))
226 return CAIRO_STATUS_SUCCESS
;
228 if (fixup
.width
< extents
->width
|| fixup
.height
< extents
->height
) {
231 _cairo_boxes_init (&clear
);
234 if (fixup
.y
!= extents
->y
) {
235 add_rect_with_offset (&clear
,
236 extents
->x
, extents
->y
,
237 extents
->x
+ extents
->width
,
239 extents
->x
, extents
->y
);
242 if (fixup
.x
!= extents
->x
) {
243 add_rect_with_offset (&clear
,
246 fixup
.y
+ fixup
.height
,
247 extents
->x
, extents
->y
);
250 if (fixup
.x
+ fixup
.width
!= extents
->x
+ extents
->width
) {
251 add_rect_with_offset (&clear
,
252 fixup
.x
+ fixup
.width
,
254 extents
->x
+ extents
->width
,
255 fixup
.y
+ fixup
.height
,
256 extents
->x
, extents
->y
);
259 if (fixup
.y
+ fixup
.height
!= extents
->y
+ extents
->height
) {
260 add_rect_with_offset (&clear
,
262 fixup
.y
+ fixup
.height
,
263 extents
->x
+ extents
->width
,
264 extents
->y
+ extents
->height
,
265 extents
->x
, extents
->y
);
268 status
= compositor
->fill_boxes (mask
,
269 CAIRO_OPERATOR_CLEAR
,
270 CAIRO_COLOR_TRANSPARENT
,
273 _cairo_boxes_fini (&clear
);
279 static cairo_status_t
280 __clip_to_surface (const cairo_traps_compositor_t
*compositor
,
281 const cairo_composite_rectangles_t
*composite
,
282 const cairo_rectangle_int_t
*extents
,
283 cairo_surface_t
**surface
)
285 cairo_surface_t
*mask
;
286 cairo_polygon_t polygon
;
287 cairo_fill_rule_t fill_rule
;
288 cairo_antialias_t antialias
;
291 cairo_surface_t
*src
;
293 cairo_int_status_t status
;
295 TRACE ((stderr
, "%s\n", __FUNCTION__
));
297 status
= _cairo_clip_get_polygon (composite
->clip
, &polygon
,
298 &fill_rule
, &antialias
);
302 _cairo_traps_init (&traps
);
303 status
= _cairo_bentley_ottmann_tessellate_polygon (&traps
,
306 _cairo_polygon_fini (&polygon
);
307 if (unlikely (status
))
310 mask
= _cairo_surface_create_scratch (composite
->surface
,
315 if (unlikely (mask
->status
)) {
316 _cairo_traps_fini (&traps
);
320 src
= compositor
->pattern_to_surface (mask
, NULL
, FALSE
,
323 if (unlikely (status
= src
->status
))
326 status
= compositor
->acquire (mask
);
327 if (unlikely (status
))
330 _cairo_boxes_init_from_rectangle (&clear
,
334 status
= compositor
->fill_boxes (mask
,
335 CAIRO_OPERATOR_CLEAR
,
336 CAIRO_COLOR_TRANSPARENT
,
338 if (unlikely (status
))
341 status
= compositor
->composite_traps (mask
, CAIRO_OPERATOR_ADD
, src
,
343 extents
->x
, extents
->y
,
346 if (unlikely (status
))
349 compositor
->release (mask
);
352 cairo_surface_destroy (src
);
353 _cairo_traps_fini (&traps
);
357 compositor
->release (mask
);
359 cairo_surface_destroy (mask
);
363 static cairo_surface_t
*
364 traps_get_clip_surface (const cairo_traps_compositor_t
*compositor
,
365 const cairo_composite_rectangles_t
*composite
,
366 const cairo_rectangle_int_t
*extents
)
368 cairo_surface_t
*surface
= NULL
;
369 cairo_int_status_t status
;
371 TRACE ((stderr
, "%s\n", __FUNCTION__
));
373 status
= __clip_to_surface (compositor
, composite
, extents
, &surface
);
374 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
375 surface
= _cairo_surface_create_scratch (composite
->surface
,
380 if (unlikely (surface
->status
))
383 status
= _cairo_clip_combine_with_surface (composite
->clip
, surface
,
384 extents
->x
, extents
->y
);
386 if (unlikely (status
)) {
387 cairo_surface_destroy (surface
);
388 surface
= _cairo_surface_create_in_error (status
);
394 static void blt_unaligned_boxes(const cairo_traps_compositor_t
*compositor
,
395 cairo_surface_t
*surface
,
403 info
.compositor
= compositor
;
405 _cairo_boxes_init (&info
.boxes
);
406 info
.boxes
.num_boxes
= 1;
407 for (i
= 0; i
< num_boxes
; i
++) {
408 cairo_box_t
*b
= &boxes
[i
];
410 if (! _cairo_fixed_is_integer (b
->p1
.x
) ||
411 ! _cairo_fixed_is_integer (b
->p1
.y
) ||
412 ! _cairo_fixed_is_integer (b
->p2
.x
) ||
413 ! _cairo_fixed_is_integer (b
->p2
.y
))
415 do_unaligned_box(blt_in
, &info
, b
, dx
, dy
);
420 static cairo_surface_t
*
421 create_composite_mask (const cairo_traps_compositor_t
*compositor
,
422 cairo_surface_t
*dst
,
424 draw_func_t draw_func
,
425 draw_func_t mask_func
,
426 const cairo_composite_rectangles_t
*extents
)
428 cairo_surface_t
*surface
, *src
;
429 cairo_int_status_t status
;
432 TRACE ((stderr
, "%s\n", __FUNCTION__
));
434 surface
= _cairo_surface_create_scratch (dst
, CAIRO_CONTENT_ALPHA
,
435 extents
->bounded
.width
,
436 extents
->bounded
.height
,
438 if (unlikely (surface
->status
))
441 src
= compositor
->pattern_to_surface (surface
,
442 &_cairo_pattern_white
.base
,
447 if (unlikely (src
->status
)) {
448 cairo_surface_destroy (surface
);
452 status
= compositor
->acquire (surface
);
453 if (unlikely (status
)) {
454 cairo_surface_destroy (src
);
455 cairo_surface_destroy (surface
);
456 return _cairo_surface_create_in_error (status
);
459 if (!surface
->is_clear
) {
462 _cairo_boxes_init_from_rectangle (&clear
,
464 extents
->bounded
.width
,
465 extents
->bounded
.height
);
466 status
= compositor
->fill_boxes (surface
,
467 CAIRO_OPERATOR_CLEAR
,
468 CAIRO_COLOR_TRANSPARENT
,
470 if (unlikely (status
))
473 surface
->is_clear
= TRUE
;
477 status
= mask_func (compositor
, surface
, draw_closure
,
478 CAIRO_OPERATOR_SOURCE
, src
, src_x
, src_y
,
479 extents
->bounded
.x
, extents
->bounded
.y
,
480 &extents
->bounded
, extents
->clip
);
481 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
482 surface
->is_clear
= FALSE
;
485 if (unlikely (status
!= CAIRO_INT_STATUS_UNSUPPORTED
))
489 /* Is it worth setting the clip region here? */
490 status
= draw_func (compositor
, surface
, draw_closure
,
491 CAIRO_OPERATOR_ADD
, src
, src_x
, src_y
,
492 extents
->bounded
.x
, extents
->bounded
.y
,
493 &extents
->bounded
, NULL
);
494 if (unlikely (status
))
497 surface
->is_clear
= FALSE
;
498 if (extents
->clip
->path
!= NULL
) {
499 status
= combine_clip_as_traps (compositor
, surface
,
500 extents
->clip
, &extents
->bounded
);
501 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
502 status
= _cairo_clip_combine_with_surface (extents
->clip
, surface
,
506 if (unlikely (status
))
508 } else if (extents
->clip
->boxes
) {
509 blt_unaligned_boxes(compositor
, surface
,
510 extents
->bounded
.x
, extents
->bounded
.y
,
511 extents
->clip
->boxes
, extents
->clip
->num_boxes
);
516 compositor
->release (surface
);
517 cairo_surface_destroy (src
);
521 compositor
->release (surface
);
522 if (status
!= CAIRO_INT_STATUS_NOTHING_TO_DO
) {
523 cairo_surface_destroy (surface
);
524 surface
= _cairo_surface_create_in_error (status
);
526 cairo_surface_destroy (src
);
530 /* Handles compositing with a clip surface when the operator allows
531 * us to combine the clip with the mask
533 static cairo_status_t
534 clip_and_composite_with_mask (const cairo_traps_compositor_t
*compositor
,
535 const cairo_composite_rectangles_t
*extents
,
536 draw_func_t draw_func
,
537 draw_func_t mask_func
,
540 cairo_surface_t
*src
,
541 int src_x
, int src_y
)
543 cairo_surface_t
*dst
= extents
->surface
;
544 cairo_surface_t
*mask
;
546 TRACE ((stderr
, "%s\n", __FUNCTION__
));
548 mask
= create_composite_mask (compositor
, dst
, draw_closure
,
549 draw_func
, mask_func
,
551 if (unlikely (mask
->status
))
557 if (src
!= NULL
|| dst
->content
!= CAIRO_CONTENT_ALPHA
) {
558 compositor
->composite (dst
, op
, src
, mask
,
559 extents
->bounded
.x
+ src_x
,
560 extents
->bounded
.y
+ src_y
,
562 extents
->bounded
.x
, extents
->bounded
.y
,
563 extents
->bounded
.width
, extents
->bounded
.height
);
565 compositor
->composite (dst
, op
, mask
, NULL
,
568 extents
->bounded
.x
, extents
->bounded
.y
,
569 extents
->bounded
.width
, extents
->bounded
.height
);
573 cairo_surface_destroy (mask
);
574 return CAIRO_STATUS_SUCCESS
;
577 /* Handles compositing with a clip surface when we have to do the operation
578 * in two pieces and combine them together.
580 static cairo_status_t
581 clip_and_composite_combine (const cairo_traps_compositor_t
*compositor
,
582 const cairo_composite_rectangles_t
*extents
,
583 draw_func_t draw_func
,
586 cairo_surface_t
*src
,
587 int src_x
, int src_y
)
589 cairo_surface_t
*dst
= extents
->surface
;
590 cairo_surface_t
*tmp
, *clip
;
591 cairo_status_t status
;
593 TRACE ((stderr
, "%s\n", __FUNCTION__
));
595 tmp
= _cairo_surface_create_scratch (dst
, dst
->content
,
596 extents
->bounded
.width
,
597 extents
->bounded
.height
,
599 if (unlikely (tmp
->status
))
602 status
= compositor
->acquire (tmp
);
603 if (unlikely (status
)) {
604 cairo_surface_destroy (tmp
);
608 compositor
->composite (tmp
,
609 dst
->is_clear
? CAIRO_OPERATOR_CLEAR
: CAIRO_OPERATOR_SOURCE
,
611 extents
->bounded
.x
, extents
->bounded
.y
,
614 extents
->bounded
.width
, extents
->bounded
.height
);
616 status
= draw_func (compositor
, tmp
, draw_closure
, op
,
618 extents
->bounded
.x
, extents
->bounded
.y
,
619 &extents
->bounded
, NULL
);
621 if (unlikely (status
))
624 clip
= traps_get_clip_surface (compositor
, extents
, &extents
->bounded
);
625 if (unlikely ((status
= clip
->status
)))
629 compositor
->composite (dst
, CAIRO_OPERATOR_SOURCE
, tmp
, clip
,
632 extents
->bounded
.x
, extents
->bounded
.y
,
633 extents
->bounded
.width
, extents
->bounded
.height
);
635 compositor
->lerp (dst
, tmp
, clip
,
638 extents
->bounded
.x
, extents
->bounded
.y
,
639 extents
->bounded
.width
, extents
->bounded
.height
);
641 cairo_surface_destroy (clip
);
644 compositor
->release (tmp
);
645 cairo_surface_destroy (tmp
);
650 /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
651 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
653 static cairo_status_t
654 clip_and_composite_source (const cairo_traps_compositor_t
*compositor
,
655 cairo_surface_t
*dst
,
656 draw_func_t draw_func
,
657 draw_func_t mask_func
,
659 cairo_surface_t
*src
,
662 const cairo_composite_rectangles_t
*extents
)
664 cairo_surface_t
*mask
;
666 TRACE ((stderr
, "%s\n", __FUNCTION__
));
668 /* Create a surface that is mask IN clip */
669 mask
= create_composite_mask (compositor
, dst
, draw_closure
,
670 draw_func
, mask_func
,
672 if (unlikely (mask
->status
))
679 compositor
->composite (dst
, CAIRO_OPERATOR_SOURCE
, src
, mask
,
680 extents
->bounded
.x
+ src_x
, extents
->bounded
.y
+ src_y
,
682 extents
->bounded
.x
, extents
->bounded
.y
,
683 extents
->bounded
.width
, extents
->bounded
.height
);
685 compositor
->lerp (dst
, src
, mask
,
686 extents
->bounded
.x
+ src_x
, extents
->bounded
.y
+ src_y
,
688 extents
->bounded
.x
, extents
->bounded
.y
,
689 extents
->bounded
.width
, extents
->bounded
.height
);
693 cairo_surface_destroy (mask
);
695 return CAIRO_STATUS_SUCCESS
;
699 can_reduce_alpha_op (cairo_operator_t op
)
703 case CAIRO_OPERATOR_OVER
:
704 case CAIRO_OPERATOR_SOURCE
:
705 case CAIRO_OPERATOR_ADD
:
713 reduce_alpha_op (cairo_composite_rectangles_t
*extents
)
715 cairo_surface_t
*dst
= extents
->surface
;
716 cairo_operator_t op
= extents
->op
;
717 const cairo_pattern_t
*pattern
= &extents
->source_pattern
.base
;
718 return dst
->is_clear
&&
719 dst
->content
== CAIRO_CONTENT_ALPHA
&&
720 _cairo_pattern_is_opaque_solid (pattern
) &&
721 can_reduce_alpha_op (op
);
724 static cairo_status_t
725 fixup_unbounded_with_mask (const cairo_traps_compositor_t
*compositor
,
726 const cairo_composite_rectangles_t
*extents
)
728 cairo_surface_t
*dst
= extents
->surface
;
729 cairo_surface_t
*mask
;
731 TRACE ((stderr
, "%s\n", __FUNCTION__
));
733 /* XXX can we avoid querying the clip surface again? */
734 mask
= traps_get_clip_surface (compositor
, extents
, &extents
->unbounded
);
735 if (unlikely (mask
->status
))
739 if (extents
->bounded
.y
!= extents
->unbounded
.y
) {
740 int x
= extents
->unbounded
.x
;
741 int y
= extents
->unbounded
.y
;
742 int width
= extents
->unbounded
.width
;
743 int height
= extents
->bounded
.y
- y
;
745 compositor
->composite (dst
, CAIRO_OPERATOR_DEST_OUT
, mask
, NULL
,
753 if (extents
->bounded
.x
!= extents
->unbounded
.x
) {
754 int x
= extents
->unbounded
.x
;
755 int y
= extents
->bounded
.y
;
756 int width
= extents
->bounded
.x
- x
;
757 int height
= extents
->bounded
.height
;
759 compositor
->composite (dst
, CAIRO_OPERATOR_DEST_OUT
, mask
, NULL
,
760 0, y
- extents
->unbounded
.y
,
767 if (extents
->bounded
.x
+ extents
->bounded
.width
!= extents
->unbounded
.x
+ extents
->unbounded
.width
) {
768 int x
= extents
->bounded
.x
+ extents
->bounded
.width
;
769 int y
= extents
->bounded
.y
;
770 int width
= extents
->unbounded
.x
+ extents
->unbounded
.width
- x
;
771 int height
= extents
->bounded
.height
;
773 compositor
->composite (dst
, CAIRO_OPERATOR_DEST_OUT
, mask
, NULL
,
774 x
- extents
->unbounded
.x
, y
- extents
->unbounded
.y
,
781 if (extents
->bounded
.y
+ extents
->bounded
.height
!= extents
->unbounded
.y
+ extents
->unbounded
.height
) {
782 int x
= extents
->unbounded
.x
;
783 int y
= extents
->bounded
.y
+ extents
->bounded
.height
;
784 int width
= extents
->unbounded
.width
;
785 int height
= extents
->unbounded
.y
+ extents
->unbounded
.height
- y
;
787 compositor
->composite (dst
, CAIRO_OPERATOR_DEST_OUT
, mask
, NULL
,
788 0, y
- extents
->unbounded
.y
,
794 cairo_surface_destroy (mask
);
796 return CAIRO_STATUS_SUCCESS
;
800 add_rect (cairo_boxes_t
*boxes
, int x1
, int y1
, int x2
, int y2
)
803 cairo_int_status_t status
;
805 box
.p1
.x
= _cairo_fixed_from_int (x1
);
806 box
.p1
.y
= _cairo_fixed_from_int (y1
);
807 box
.p2
.x
= _cairo_fixed_from_int (x2
);
808 box
.p2
.y
= _cairo_fixed_from_int (y2
);
810 status
= _cairo_boxes_add (boxes
, CAIRO_ANTIALIAS_DEFAULT
, &box
);
811 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
814 static cairo_status_t
815 fixup_unbounded (const cairo_traps_compositor_t
*compositor
,
816 cairo_composite_rectangles_t
*extents
,
817 cairo_boxes_t
*boxes
)
819 cairo_surface_t
*dst
= extents
->surface
;
820 cairo_boxes_t clear
, tmp
;
822 cairo_int_status_t status
;
824 TRACE ((stderr
, "%s\n", __FUNCTION__
));
826 if (extents
->bounded
.width
== extents
->unbounded
.width
&&
827 extents
->bounded
.height
== extents
->unbounded
.height
)
829 return CAIRO_STATUS_SUCCESS
;
832 assert (extents
->clip
->path
== NULL
);
834 /* subtract the drawn boxes from the unbounded area */
835 _cairo_boxes_init (&clear
);
837 box
.p1
.x
= _cairo_fixed_from_int (extents
->unbounded
.x
+ extents
->unbounded
.width
);
838 box
.p1
.y
= _cairo_fixed_from_int (extents
->unbounded
.y
);
839 box
.p2
.x
= _cairo_fixed_from_int (extents
->unbounded
.x
);
840 box
.p2
.y
= _cairo_fixed_from_int (extents
->unbounded
.y
+ extents
->unbounded
.height
);
843 if (extents
->bounded
.width
== 0 || extents
->bounded
.height
== 0) {
847 if (extents
->bounded
.y
!= extents
->unbounded
.y
) {
849 extents
->unbounded
.x
, extents
->unbounded
.y
,
850 extents
->unbounded
.x
+ extents
->unbounded
.width
,
854 if (extents
->bounded
.x
!= extents
->unbounded
.x
) {
856 extents
->unbounded
.x
, extents
->bounded
.y
,
858 extents
->bounded
.y
+ extents
->bounded
.height
);
861 if (extents
->bounded
.x
+ extents
->bounded
.width
!= extents
->unbounded
.x
+ extents
->unbounded
.width
) {
863 extents
->bounded
.x
+ extents
->bounded
.width
,
865 extents
->unbounded
.x
+ extents
->unbounded
.width
,
866 extents
->bounded
.y
+ extents
->bounded
.height
);
869 if (extents
->bounded
.y
+ extents
->bounded
.height
!= extents
->unbounded
.y
+ extents
->unbounded
.height
) {
871 extents
->unbounded
.x
,
872 extents
->bounded
.y
+ extents
->bounded
.height
,
873 extents
->unbounded
.x
+ extents
->unbounded
.width
,
874 extents
->unbounded
.y
+ extents
->unbounded
.height
);
877 } else if (boxes
->num_boxes
) {
878 _cairo_boxes_init (&tmp
);
880 assert (boxes
->is_pixel_aligned
);
882 status
= _cairo_boxes_add (&tmp
, CAIRO_ANTIALIAS_DEFAULT
, &box
);
883 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
885 tmp
.chunks
.next
= &boxes
->chunks
;
886 tmp
.num_boxes
+= boxes
->num_boxes
;
888 status
= _cairo_bentley_ottmann_tessellate_boxes (&tmp
,
889 CAIRO_FILL_RULE_WINDING
,
891 tmp
.chunks
.next
= NULL
;
892 if (unlikely (status
))
896 box
.p1
.x
= _cairo_fixed_from_int (extents
->unbounded
.x
);
897 box
.p2
.x
= _cairo_fixed_from_int (extents
->unbounded
.x
+ extents
->unbounded
.width
);
899 status
= _cairo_boxes_add (&clear
, CAIRO_ANTIALIAS_DEFAULT
, &box
);
900 assert (status
== CAIRO_INT_STATUS_SUCCESS
);
903 /* Now intersect with the clip boxes */
904 if (extents
->clip
->num_boxes
) {
905 _cairo_boxes_init_for_array (&tmp
,
906 extents
->clip
->boxes
,
907 extents
->clip
->num_boxes
);
908 status
= _cairo_boxes_intersect (&clear
, &tmp
, &clear
);
909 if (unlikely (status
))
913 status
= compositor
->fill_boxes (dst
,
914 CAIRO_OPERATOR_CLEAR
,
915 CAIRO_COLOR_TRANSPARENT
,
919 _cairo_boxes_fini (&clear
);
924 NEED_CLIP_REGION
= 0x1,
925 NEED_CLIP_SURFACE
= 0x2,
926 FORCE_CLIP_REGION
= 0x4,
930 need_bounded_clip (cairo_composite_rectangles_t
*extents
)
932 unsigned int flags
= 0;
934 if (extents
->clip
->num_boxes
> 1 ||
935 extents
->mask
.width
> extents
->unbounded
.width
||
936 extents
->mask
.height
> extents
->unbounded
.height
)
938 flags
|= NEED_CLIP_REGION
;
941 if (extents
->clip
->num_boxes
> 1 ||
942 extents
->mask
.width
> extents
->bounded
.width
||
943 extents
->mask
.height
> extents
->bounded
.height
)
945 flags
|= FORCE_CLIP_REGION
;
948 if (! _cairo_clip_is_region (extents
->clip
))
949 flags
|= NEED_CLIP_SURFACE
;
955 need_unbounded_clip (cairo_composite_rectangles_t
*extents
)
957 unsigned int flags
= 0;
958 if (! extents
->is_bounded
) {
959 flags
|= NEED_CLIP_REGION
;
960 if (! _cairo_clip_is_region (extents
->clip
))
961 flags
|= NEED_CLIP_SURFACE
;
963 if (extents
->clip
->path
!= NULL
)
964 flags
|= NEED_CLIP_SURFACE
;
968 static cairo_status_t
969 clip_and_composite (const cairo_traps_compositor_t
*compositor
,
970 cairo_composite_rectangles_t
*extents
,
971 draw_func_t draw_func
,
972 draw_func_t mask_func
,
974 unsigned int need_clip
)
976 cairo_surface_t
*dst
= extents
->surface
;
977 cairo_operator_t op
= extents
->op
;
978 cairo_pattern_t
*source
= &extents
->source_pattern
.base
;
979 cairo_surface_t
*src
;
981 cairo_region_t
*clip_region
= NULL
;
982 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
984 TRACE ((stderr
, "%s\n", __FUNCTION__
));
986 if (reduce_alpha_op (extents
)) {
987 op
= CAIRO_OPERATOR_ADD
;
991 if (op
== CAIRO_OPERATOR_CLEAR
) {
992 op
= CAIRO_OPERATOR_DEST_OUT
;
996 compositor
->acquire (dst
);
998 if (need_clip
& NEED_CLIP_REGION
) {
999 const cairo_rectangle_int_t
*limit
;
1001 if ((need_clip
& FORCE_CLIP_REGION
) == 0)
1002 limit
= &extents
->unbounded
;
1004 limit
= &extents
->destination
;
1006 clip_region
= _cairo_clip_get_region (extents
->clip
);
1007 if (clip_region
!= NULL
&&
1008 cairo_region_contains_rectangle (clip_region
,
1009 limit
) == CAIRO_REGION_OVERLAP_IN
)
1012 if (clip_region
!= NULL
) {
1013 status
= compositor
->set_clip_region (dst
, clip_region
);
1014 if (unlikely (status
)) {
1015 compositor
->release (dst
);
1021 if (extents
->bounded
.width
== 0 || extents
->bounded
.height
== 0)
1024 src
= compositor
->pattern_to_surface (dst
, source
, FALSE
,
1026 &extents
->source_sample_area
,
1028 if (unlikely (status
= src
->status
))
1031 if (op
== CAIRO_OPERATOR_SOURCE
) {
1032 status
= clip_and_composite_source (compositor
, dst
,
1033 draw_func
, mask_func
, draw_closure
,
1037 if (need_clip
& NEED_CLIP_SURFACE
) {
1038 if (extents
->is_bounded
) {
1039 status
= clip_and_composite_with_mask (compositor
, extents
,
1040 draw_func
, mask_func
,
1042 op
, src
, src_x
, src_y
);
1044 status
= clip_and_composite_combine (compositor
, extents
,
1045 draw_func
, draw_closure
,
1046 op
, src
, src_x
, src_y
);
1049 status
= draw_func (compositor
,
1051 op
, src
, src_x
, src_y
,
1057 cairo_surface_destroy (src
);
1060 if (status
== CAIRO_STATUS_SUCCESS
&& ! extents
->is_bounded
) {
1061 if (need_clip
& NEED_CLIP_SURFACE
)
1062 status
= fixup_unbounded_with_mask (compositor
, extents
);
1064 status
= fixup_unbounded (compositor
, extents
, NULL
);
1069 compositor
->set_clip_region (dst
, NULL
);
1071 compositor
->release (dst
);
1079 cairo_traps_t traps
;
1080 cairo_antialias_t antialias
;
1081 } composite_traps_info_t
;
1083 static cairo_int_status_t
1084 composite_traps (const cairo_traps_compositor_t
*compositor
,
1085 cairo_surface_t
*dst
,
1087 cairo_operator_t op
,
1088 cairo_surface_t
*src
,
1089 int src_x
, int src_y
,
1090 int dst_x
, int dst_y
,
1091 const cairo_rectangle_int_t
*extents
,
1094 composite_traps_info_t
*info
= closure
;
1096 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1098 return compositor
->composite_traps (dst
, op
, src
,
1099 src_x
- dst_x
, src_y
- dst_y
,
1102 info
->antialias
, &info
->traps
);
1106 cairo_tristrip_t strip
;
1107 cairo_antialias_t antialias
;
1108 } composite_tristrip_info_t
;
1110 static cairo_int_status_t
1111 composite_tristrip (const cairo_traps_compositor_t
*compositor
,
1112 cairo_surface_t
*dst
,
1114 cairo_operator_t op
,
1115 cairo_surface_t
*src
,
1116 int src_x
, int src_y
,
1117 int dst_x
, int dst_y
,
1118 const cairo_rectangle_int_t
*extents
,
1121 composite_tristrip_info_t
*info
= closure
;
1123 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1125 return compositor
->composite_tristrip (dst
, op
, src
,
1126 src_x
- dst_x
, src_y
- dst_y
,
1129 info
->antialias
, &info
->strip
);
1133 is_recording_pattern (const cairo_pattern_t
*pattern
)
1135 cairo_surface_t
*surface
;
1137 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SURFACE
)
1140 surface
= ((const cairo_surface_pattern_t
*) pattern
)->surface
;
1141 surface
= _cairo_surface_get_source (surface
, NULL
);
1142 return _cairo_surface_is_recording (surface
);
1145 static cairo_surface_t
*
1146 recording_pattern_get_surface (const cairo_pattern_t
*pattern
)
1148 cairo_surface_t
*surface
;
1150 surface
= ((const cairo_surface_pattern_t
*) pattern
)->surface
;
1151 return _cairo_surface_get_source (surface
, NULL
);
1155 recording_pattern_contains_sample (const cairo_pattern_t
*pattern
,
1156 const cairo_rectangle_int_t
*sample
)
1158 cairo_recording_surface_t
*surface
;
1160 if (! is_recording_pattern (pattern
))
1163 if (pattern
->extend
== CAIRO_EXTEND_NONE
)
1166 surface
= (cairo_recording_surface_t
*) recording_pattern_get_surface (pattern
);
1167 if (surface
->unbounded
)
1170 return _cairo_rectangle_contains_rectangle (&surface
->extents
, sample
);
1174 op_reduces_to_source (cairo_composite_rectangles_t
*extents
)
1176 if (extents
->op
== CAIRO_OPERATOR_SOURCE
)
1179 if (extents
->surface
->is_clear
)
1180 return extents
->op
== CAIRO_OPERATOR_OVER
|| extents
->op
== CAIRO_OPERATOR_ADD
;
1185 static cairo_status_t
1186 composite_aligned_boxes (const cairo_traps_compositor_t
*compositor
,
1187 cairo_composite_rectangles_t
*extents
,
1188 cairo_boxes_t
*boxes
)
1190 cairo_surface_t
*dst
= extents
->surface
;
1191 cairo_operator_t op
= extents
->op
;
1192 cairo_bool_t need_clip_mask
= ! _cairo_clip_is_region (extents
->clip
);
1193 cairo_bool_t op_is_source
;
1194 cairo_status_t status
;
1196 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1198 if (need_clip_mask
&&
1199 (! extents
->is_bounded
|| extents
->op
== CAIRO_OPERATOR_SOURCE
))
1201 return CAIRO_INT_STATUS_UNSUPPORTED
;
1204 op_is_source
= op_reduces_to_source (extents
);
1206 /* Are we just copying a recording surface? */
1207 if (! need_clip_mask
&& op_is_source
&&
1208 recording_pattern_contains_sample (&extents
->source_pattern
.base
,
1209 &extents
->source_sample_area
))
1211 cairo_clip_t
*recording_clip
;
1212 const cairo_pattern_t
*source
= &extents
->source_pattern
.base
;
1213 const cairo_matrix_t
*m
;
1214 cairo_matrix_t matrix
;
1216 /* XXX could also do tiling repeat modes... */
1218 /* first clear the area about to be overwritten */
1219 if (! dst
->is_clear
) {
1220 status
= compositor
->acquire (dst
);
1221 if (unlikely (status
))
1224 status
= compositor
->fill_boxes (dst
,
1225 CAIRO_OPERATOR_CLEAR
,
1226 CAIRO_COLOR_TRANSPARENT
,
1228 compositor
->release (dst
);
1229 if (unlikely (status
))
1233 m
= &source
->matrix
;
1234 if (_cairo_surface_has_device_transform (dst
)) {
1235 cairo_matrix_multiply (&matrix
,
1237 &dst
->device_transform
);
1241 recording_clip
= _cairo_clip_from_boxes (boxes
);
1242 status
= _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (source
),
1243 m
, dst
, recording_clip
);
1244 _cairo_clip_destroy (recording_clip
);
1249 status
= compositor
->acquire (dst
);
1250 if (unlikely (status
))
1253 if (! need_clip_mask
&&
1254 (op
== CAIRO_OPERATOR_CLEAR
||
1255 extents
->source_pattern
.base
.type
== CAIRO_PATTERN_TYPE_SOLID
))
1257 const cairo_color_t
*color
;
1259 if (op
== CAIRO_OPERATOR_CLEAR
) {
1260 color
= CAIRO_COLOR_TRANSPARENT
;
1262 color
= &((cairo_solid_pattern_t
*) &extents
->source_pattern
)->color
;
1264 op
= CAIRO_OPERATOR_SOURCE
;
1267 status
= compositor
->fill_boxes (dst
, op
, color
, boxes
);
1271 cairo_surface_t
*src
, *mask
= NULL
;
1272 cairo_pattern_t
*source
= &extents
->source_pattern
.base
;
1274 int mask_x
= 0, mask_y
= 0;
1276 if (need_clip_mask
) {
1277 mask
= traps_get_clip_surface (compositor
,
1278 extents
, &extents
->bounded
);
1279 if (unlikely (mask
->status
))
1280 return mask
->status
;
1282 mask_x
= -extents
->bounded
.x
;
1283 mask_y
= -extents
->bounded
.y
;
1285 if (op
== CAIRO_OPERATOR_CLEAR
) {
1287 op
= CAIRO_OPERATOR_DEST_OUT
;
1289 } else if (op_is_source
)
1290 op
= CAIRO_OPERATOR_SOURCE
;
1292 src
= compositor
->pattern_to_surface (dst
, source
, FALSE
,
1294 &extents
->source_sample_area
,
1296 if (likely (src
->status
== CAIRO_STATUS_SUCCESS
)) {
1297 status
= compositor
->composite_boxes (dst
, op
, src
, mask
,
1301 boxes
, &extents
->bounded
);
1302 cairo_surface_destroy (src
);
1304 status
= src
->status
;
1306 cairo_surface_destroy (mask
);
1309 if (status
== CAIRO_STATUS_SUCCESS
&& ! extents
->is_bounded
)
1310 status
= fixup_unbounded (compositor
, extents
, boxes
);
1312 compositor
->release (dst
);
1317 static cairo_status_t
1318 upload_boxes (const cairo_traps_compositor_t
*compositor
,
1319 cairo_composite_rectangles_t
*extents
,
1320 cairo_boxes_t
*boxes
)
1322 cairo_surface_t
*dst
= extents
->surface
;
1323 const cairo_pattern_t
*source
= &extents
->source_pattern
.base
;
1324 cairo_surface_t
*src
;
1325 cairo_rectangle_int_t limit
;
1326 cairo_int_status_t status
;
1329 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1331 src
= _cairo_pattern_get_source((cairo_surface_pattern_t
*)source
,
1333 if (!(src
->type
== CAIRO_SURFACE_TYPE_IMAGE
|| src
->type
== dst
->type
))
1334 return CAIRO_INT_STATUS_UNSUPPORTED
;
1336 if (! _cairo_matrix_is_integer_translation (&source
->matrix
, &tx
, &ty
))
1337 return CAIRO_INT_STATUS_UNSUPPORTED
;
1339 /* Check that the data is entirely within the image */
1340 if (extents
->bounded
.x
+ tx
< limit
.x
|| extents
->bounded
.y
+ ty
< limit
.y
)
1341 return CAIRO_INT_STATUS_UNSUPPORTED
;
1343 if (extents
->bounded
.x
+ extents
->bounded
.width
+ tx
> limit
.x
+ limit
.width
||
1344 extents
->bounded
.y
+ extents
->bounded
.height
+ ty
> limit
.y
+ limit
.height
)
1345 return CAIRO_INT_STATUS_UNSUPPORTED
;
1350 if (src
->type
== CAIRO_SURFACE_TYPE_IMAGE
)
1351 status
= compositor
->draw_image_boxes (dst
,
1352 (cairo_image_surface_t
*)src
,
1355 status
= compositor
->copy_boxes (dst
, src
, boxes
, &extents
->bounded
,
1361 static cairo_int_status_t
1362 trim_extents_to_traps (cairo_composite_rectangles_t
*extents
,
1363 cairo_traps_t
*traps
)
1367 _cairo_traps_extents (traps
, &box
);
1368 return _cairo_composite_rectangles_intersect_mask_extents (extents
, &box
);
1371 static cairo_int_status_t
1372 trim_extents_to_tristrip (cairo_composite_rectangles_t
*extents
,
1373 cairo_tristrip_t
*strip
)
1377 _cairo_tristrip_extents (strip
, &box
);
1378 return _cairo_composite_rectangles_intersect_mask_extents (extents
, &box
);
1381 static cairo_int_status_t
1382 trim_extents_to_boxes (cairo_composite_rectangles_t
*extents
,
1383 cairo_boxes_t
*boxes
)
1387 _cairo_boxes_extents (boxes
, &box
);
1388 return _cairo_composite_rectangles_intersect_mask_extents (extents
, &box
);
1391 static cairo_int_status_t
1392 boxes_for_traps (cairo_boxes_t
*boxes
,
1393 cairo_traps_t
*traps
,
1394 cairo_antialias_t antialias
)
1398 /* first check that the traps are rectilinear */
1399 if (antialias
== CAIRO_ANTIALIAS_NONE
) {
1400 for (i
= 0; i
< traps
->num_traps
; i
++) {
1401 const cairo_trapezoid_t
*t
= &traps
->traps
[i
];
1402 if (_cairo_fixed_integer_round_down (t
->left
.p1
.x
) !=
1403 _cairo_fixed_integer_round_down (t
->left
.p2
.x
) ||
1404 _cairo_fixed_integer_round_down (t
->right
.p1
.x
) !=
1405 _cairo_fixed_integer_round_down (t
->right
.p2
.x
))
1407 return CAIRO_INT_STATUS_UNSUPPORTED
;
1411 for (i
= 0; i
< traps
->num_traps
; i
++) {
1412 const cairo_trapezoid_t
*t
= &traps
->traps
[i
];
1413 if (t
->left
.p1
.x
!= t
->left
.p2
.x
|| t
->right
.p1
.x
!= t
->right
.p2
.x
)
1414 return CAIRO_INT_STATUS_UNSUPPORTED
;
1418 _cairo_boxes_init (boxes
);
1420 boxes
->chunks
.base
= (cairo_box_t
*) traps
->traps
;
1421 boxes
->chunks
.size
= traps
->num_traps
;
1423 if (antialias
!= CAIRO_ANTIALIAS_NONE
) {
1424 for (i
= j
= 0; i
< traps
->num_traps
; i
++) {
1425 /* Note the traps and boxes alias so we need to take the local copies first. */
1426 cairo_fixed_t x1
= traps
->traps
[i
].left
.p1
.x
;
1427 cairo_fixed_t x2
= traps
->traps
[i
].right
.p1
.x
;
1428 cairo_fixed_t y1
= traps
->traps
[i
].top
;
1429 cairo_fixed_t y2
= traps
->traps
[i
].bottom
;
1431 if (x1
== x2
|| y1
== y2
)
1434 boxes
->chunks
.base
[j
].p1
.x
= x1
;
1435 boxes
->chunks
.base
[j
].p1
.y
= y1
;
1436 boxes
->chunks
.base
[j
].p2
.x
= x2
;
1437 boxes
->chunks
.base
[j
].p2
.y
= y2
;
1440 if (boxes
->is_pixel_aligned
) {
1441 boxes
->is_pixel_aligned
=
1442 _cairo_fixed_is_integer (x1
) && _cairo_fixed_is_integer (y1
) &&
1443 _cairo_fixed_is_integer (x2
) && _cairo_fixed_is_integer (y2
);
1447 boxes
->is_pixel_aligned
= TRUE
;
1449 for (i
= j
= 0; i
< traps
->num_traps
; i
++) {
1450 /* Note the traps and boxes alias so we need to take the local copies first. */
1451 cairo_fixed_t x1
= traps
->traps
[i
].left
.p1
.x
;
1452 cairo_fixed_t x2
= traps
->traps
[i
].right
.p1
.x
;
1453 cairo_fixed_t y1
= traps
->traps
[i
].top
;
1454 cairo_fixed_t y2
= traps
->traps
[i
].bottom
;
1456 /* round down here to match Pixman's behavior when using traps. */
1457 boxes
->chunks
.base
[j
].p1
.x
= _cairo_fixed_round_down (x1
);
1458 boxes
->chunks
.base
[j
].p1
.y
= _cairo_fixed_round_down (y1
);
1459 boxes
->chunks
.base
[j
].p2
.x
= _cairo_fixed_round_down (x2
);
1460 boxes
->chunks
.base
[j
].p2
.y
= _cairo_fixed_round_down (y2
);
1461 j
+= (boxes
->chunks
.base
[j
].p1
.x
!= boxes
->chunks
.base
[j
].p2
.x
&&
1462 boxes
->chunks
.base
[j
].p1
.y
!= boxes
->chunks
.base
[j
].p2
.y
);
1465 boxes
->chunks
.count
= j
;
1466 boxes
->num_boxes
= j
;
1468 return CAIRO_INT_STATUS_SUCCESS
;
1471 static cairo_status_t
1472 clip_and_composite_boxes (const cairo_traps_compositor_t
*compositor
,
1473 cairo_composite_rectangles_t
*extents
,
1474 cairo_boxes_t
*boxes
);
1476 static cairo_status_t
1477 clip_and_composite_polygon (const cairo_traps_compositor_t
*compositor
,
1478 cairo_composite_rectangles_t
*extents
,
1479 cairo_polygon_t
*polygon
,
1480 cairo_antialias_t antialias
,
1481 cairo_fill_rule_t fill_rule
,
1484 composite_traps_info_t traps
;
1485 cairo_surface_t
*dst
= extents
->surface
;
1486 cairo_bool_t clip_surface
= ! _cairo_clip_is_region (extents
->clip
);
1487 cairo_int_status_t status
;
1489 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1491 if (polygon
->num_edges
== 0) {
1492 status
= CAIRO_INT_STATUS_SUCCESS
;
1494 if (! extents
->is_bounded
) {
1495 cairo_region_t
*clip_region
= _cairo_clip_get_region (extents
->clip
);
1498 cairo_region_contains_rectangle (clip_region
,
1499 &extents
->unbounded
) == CAIRO_REGION_OVERLAP_IN
)
1502 if (clip_region
!= NULL
) {
1503 status
= compositor
->set_clip_region (dst
, clip_region
);
1504 if (unlikely (status
))
1509 status
= fixup_unbounded_with_mask (compositor
, extents
);
1511 status
= fixup_unbounded (compositor
, extents
, NULL
);
1513 if (clip_region
!= NULL
)
1514 compositor
->set_clip_region (dst
, NULL
);
1520 if (extents
->clip
->path
!= NULL
&& extents
->is_bounded
) {
1521 cairo_polygon_t clipper
;
1522 cairo_fill_rule_t clipper_fill_rule
;
1523 cairo_antialias_t clipper_antialias
;
1525 status
= _cairo_clip_get_polygon (extents
->clip
,
1528 &clipper_antialias
);
1529 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
1530 if (clipper_antialias
== antialias
) {
1531 status
= _cairo_polygon_intersect (polygon
, fill_rule
,
1532 &clipper
, clipper_fill_rule
);
1533 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
1534 cairo_clip_t
* clip
= _cairo_clip_copy_region (extents
->clip
);
1535 _cairo_clip_destroy (extents
->clip
);
1536 extents
->clip
= clip
;
1538 fill_rule
= CAIRO_FILL_RULE_WINDING
;
1540 _cairo_polygon_fini (&clipper
);
1545 if (antialias
== CAIRO_ANTIALIAS_NONE
&& curvy
) {
1546 cairo_boxes_t boxes
;
1548 _cairo_boxes_init (&boxes
);
1549 status
= _cairo_rasterise_polygon_to_boxes (polygon
, fill_rule
, &boxes
);
1550 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
1551 assert (boxes
.is_pixel_aligned
);
1552 status
= clip_and_composite_boxes (compositor
, extents
, &boxes
);
1554 _cairo_boxes_fini (&boxes
);
1555 if ((status
!= CAIRO_INT_STATUS_UNSUPPORTED
))
1559 _cairo_traps_init (&traps
.traps
);
1561 if (antialias
== CAIRO_ANTIALIAS_NONE
&& curvy
) {
1562 status
= _cairo_rasterise_polygon_to_traps (polygon
, fill_rule
, antialias
, &traps
.traps
);
1564 status
= _cairo_bentley_ottmann_tessellate_polygon (&traps
.traps
, polygon
, fill_rule
);
1566 if (unlikely (status
))
1569 status
= trim_extents_to_traps (extents
, &traps
.traps
);
1570 if (unlikely (status
))
1573 /* Use a fast path if the trapezoids consist of a set of boxes. */
1574 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1576 cairo_boxes_t boxes
;
1578 status
= boxes_for_traps (&boxes
, &traps
.traps
, antialias
);
1579 if (status
== CAIRO_INT_STATUS_SUCCESS
) {
1580 status
= clip_and_composite_boxes (compositor
, extents
, &boxes
);
1581 /* XXX need to reconstruct the traps! */
1582 assert (status
!= CAIRO_INT_STATUS_UNSUPPORTED
);
1585 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
1586 /* Otherwise render the trapezoids to a mask and composite in the usual
1589 unsigned int flags
= 0;
1591 /* For unbounded operations, the X11 server will estimate the
1592 * affected rectangle and apply the operation to that. However,
1593 * there are cases where this is an overestimate (e.g. the
1594 * clip-fill-{eo,nz}-unbounded test).
1596 * The clip will trim that overestimate to our expectations.
1598 if (! extents
->is_bounded
)
1599 flags
|= FORCE_CLIP_REGION
;
1601 traps
.antialias
= antialias
;
1602 status
= clip_and_composite (compositor
, extents
,
1603 composite_traps
, NULL
, &traps
,
1604 need_unbounded_clip (extents
) | flags
);
1608 _cairo_traps_fini (&traps
.traps
);
1613 struct composite_opacity_info
{
1614 const cairo_traps_compositor_t
*compositor
;
1616 cairo_surface_t
*dst
;
1617 cairo_surface_t
*src
;
1622 static void composite_opacity(void *closure
,
1623 int16_t x
, int16_t y
,
1624 int16_t w
, int16_t h
,
1627 struct composite_opacity_info
*info
= closure
;
1628 const cairo_traps_compositor_t
*compositor
= info
->compositor
;
1629 cairo_surface_t
*mask
;
1631 cairo_color_t color
;
1632 cairo_solid_pattern_t solid
;
1634 _cairo_color_init_rgba (&color
, 0, 0, 0, info
->opacity
* coverage
);
1635 _cairo_pattern_init_solid (&solid
, &color
);
1636 mask
= compositor
->pattern_to_surface (info
->dst
, &solid
.base
, TRUE
,
1637 &_cairo_unbounded_rectangle
,
1638 &_cairo_unbounded_rectangle
,
1640 if (likely (mask
->status
== CAIRO_STATUS_SUCCESS
)) {
1642 compositor
->composite (info
->dst
, info
->op
, info
->src
, mask
,
1643 x
+ info
->src_x
, y
+ info
->src_y
,
1648 compositor
->composite (info
->dst
, info
->op
, mask
, NULL
,
1656 cairo_surface_destroy (mask
);
1660 static cairo_int_status_t
1661 composite_opacity_boxes (const cairo_traps_compositor_t
*compositor
,
1662 cairo_surface_t
*dst
,
1664 cairo_operator_t op
,
1665 cairo_surface_t
*src
,
1670 const cairo_rectangle_int_t
*extents
,
1673 const cairo_solid_pattern_t
*mask
= closure
;
1674 struct composite_opacity_info info
;
1677 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1679 info
.compositor
= compositor
;
1687 info
.opacity
= mask
->color
.alpha
/ (double) 0xffff;
1689 /* XXX for lots of boxes create a clip region for the fully opaque areas */
1690 for (i
= 0; i
< clip
->num_boxes
; i
++)
1691 do_unaligned_box(composite_opacity
, &info
,
1692 &clip
->boxes
[i
], dst_x
, dst_y
);
1694 return CAIRO_STATUS_SUCCESS
;
1697 static cairo_int_status_t
1698 composite_boxes (const cairo_traps_compositor_t
*compositor
,
1699 cairo_surface_t
*dst
,
1701 cairo_operator_t op
,
1702 cairo_surface_t
*src
,
1707 const cairo_rectangle_int_t
*extents
,
1710 cairo_traps_t traps
;
1711 cairo_status_t status
;
1713 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1715 status
= _cairo_traps_init_boxes (&traps
, closure
);
1716 if (unlikely (status
))
1719 status
= compositor
->composite_traps (dst
, op
, src
,
1720 src_x
- dst_x
, src_y
- dst_y
,
1723 CAIRO_ANTIALIAS_DEFAULT
, &traps
);
1724 _cairo_traps_fini (&traps
);
1729 static cairo_status_t
1730 clip_and_composite_boxes (const cairo_traps_compositor_t
*compositor
,
1731 cairo_composite_rectangles_t
*extents
,
1732 cairo_boxes_t
*boxes
)
1734 cairo_int_status_t status
;
1736 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1738 if (boxes
->num_boxes
== 0 && extents
->is_bounded
)
1739 return CAIRO_STATUS_SUCCESS
;
1741 status
= trim_extents_to_boxes (extents
, boxes
);
1742 if (unlikely (status
))
1745 if (boxes
->is_pixel_aligned
&& extents
->clip
->path
== NULL
&&
1746 extents
->source_pattern
.base
.type
== CAIRO_PATTERN_TYPE_SURFACE
&&
1747 (op_reduces_to_source (extents
) ||
1748 (extents
->op
== CAIRO_OPERATOR_OVER
&&
1749 (extents
->source_pattern
.surface
.surface
->content
& CAIRO_CONTENT_ALPHA
) == 0)))
1751 status
= upload_boxes (compositor
, extents
, boxes
);
1752 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
1756 /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
1757 if (extents
->clip
->path
!= NULL
&& extents
->is_bounded
) {
1758 cairo_polygon_t polygon
;
1759 cairo_fill_rule_t fill_rule
;
1760 cairo_antialias_t antialias
;
1763 clip
= _cairo_clip_copy (extents
->clip
);
1764 clip
= _cairo_clip_intersect_boxes (clip
, boxes
);
1765 if (_cairo_clip_is_all_clipped (clip
))
1766 return CAIRO_INT_STATUS_NOTHING_TO_DO
;
1768 status
= _cairo_clip_get_polygon (clip
, &polygon
,
1769 &fill_rule
, &antialias
);
1770 _cairo_clip_path_destroy (clip
->path
);
1772 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
1773 cairo_clip_t
*saved_clip
= extents
->clip
;
1774 extents
->clip
= clip
;
1776 status
= clip_and_composite_polygon (compositor
, extents
, &polygon
,
1777 antialias
, fill_rule
, FALSE
);
1779 clip
= extents
->clip
;
1780 extents
->clip
= saved_clip
;
1782 _cairo_polygon_fini (&polygon
);
1784 _cairo_clip_destroy (clip
);
1786 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
1790 /* Use a fast path if the boxes are pixel aligned (or nearly aligned!) */
1791 if (boxes
->is_pixel_aligned
) {
1792 status
= composite_aligned_boxes (compositor
, extents
, boxes
);
1793 if (status
!= CAIRO_INT_STATUS_UNSUPPORTED
)
1797 return clip_and_composite (compositor
, extents
,
1798 composite_boxes
, NULL
, boxes
,
1799 need_unbounded_clip (extents
));
1802 static cairo_int_status_t
1803 composite_traps_as_boxes (const cairo_traps_compositor_t
*compositor
,
1804 cairo_composite_rectangles_t
*extents
,
1805 composite_traps_info_t
*info
)
1807 cairo_boxes_t boxes
;
1809 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1811 if (! _cairo_traps_to_boxes (&info
->traps
, info
->antialias
, &boxes
))
1812 return CAIRO_INT_STATUS_UNSUPPORTED
;
1814 return clip_and_composite_boxes (compositor
, extents
, &boxes
);
1817 static cairo_int_status_t
1818 clip_and_composite_traps (const cairo_traps_compositor_t
*compositor
,
1819 cairo_composite_rectangles_t
*extents
,
1820 composite_traps_info_t
*info
,
1823 cairo_int_status_t status
;
1825 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1827 status
= trim_extents_to_traps (extents
, &info
->traps
);
1828 if (unlikely (status
!= CAIRO_INT_STATUS_SUCCESS
))
1831 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1832 if ((flags
& FORCE_CLIP_REGION
) == 0)
1833 status
= composite_traps_as_boxes (compositor
, extents
, info
);
1834 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
1835 /* For unbounded operations, the X11 server will estimate the
1836 * affected rectangle and apply the operation to that. However,
1837 * there are cases where this is an overestimate (e.g. the
1838 * clip-fill-{eo,nz}-unbounded test).
1840 * The clip will trim that overestimate to our expectations.
1842 if (! extents
->is_bounded
)
1843 flags
|= FORCE_CLIP_REGION
;
1845 status
= clip_and_composite (compositor
, extents
,
1846 composite_traps
, NULL
, info
,
1847 need_unbounded_clip (extents
) | flags
);
1853 static cairo_int_status_t
1854 clip_and_composite_tristrip (const cairo_traps_compositor_t
*compositor
,
1855 cairo_composite_rectangles_t
*extents
,
1856 composite_tristrip_info_t
*info
)
1858 cairo_int_status_t status
;
1859 unsigned int flags
= 0;
1861 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1863 status
= trim_extents_to_tristrip (extents
, &info
->strip
);
1864 if (unlikely (status
!= CAIRO_INT_STATUS_SUCCESS
))
1867 if (! extents
->is_bounded
)
1868 flags
|= FORCE_CLIP_REGION
;
1870 status
= clip_and_composite (compositor
, extents
,
1871 composite_tristrip
, NULL
, info
,
1872 need_unbounded_clip (extents
) | flags
);
1877 struct composite_mask
{
1878 cairo_surface_t
*mask
;
1882 static cairo_int_status_t
1883 composite_mask (const cairo_traps_compositor_t
*compositor
,
1884 cairo_surface_t
*dst
,
1886 cairo_operator_t op
,
1887 cairo_surface_t
*src
,
1892 const cairo_rectangle_int_t
*extents
,
1895 struct composite_mask
*data
= closure
;
1897 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1900 compositor
->composite (dst
, op
, src
, data
->mask
,
1901 extents
->x
+ src_x
, extents
->y
+ src_y
,
1902 extents
->x
+ data
->mask_x
, extents
->y
+ data
->mask_y
,
1903 extents
->x
- dst_x
, extents
->y
- dst_y
,
1904 extents
->width
, extents
->height
);
1906 compositor
->composite (dst
, op
, data
->mask
, NULL
,
1907 extents
->x
+ data
->mask_x
, extents
->y
+ data
->mask_y
,
1909 extents
->x
- dst_x
, extents
->y
- dst_y
,
1910 extents
->width
, extents
->height
);
1913 return CAIRO_STATUS_SUCCESS
;
1916 struct composite_box_info
{
1917 const cairo_traps_compositor_t
*compositor
;
1918 cairo_surface_t
*dst
;
1919 cairo_surface_t
*src
;
1924 static void composite_box(void *closure
,
1925 int16_t x
, int16_t y
,
1926 int16_t w
, int16_t h
,
1929 struct composite_box_info
*info
= closure
;
1930 const cairo_traps_compositor_t
*compositor
= info
->compositor
;
1932 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1934 if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (coverage
)) {
1935 cairo_surface_t
*mask
;
1936 cairo_color_t color
;
1937 cairo_solid_pattern_t solid
;
1940 _cairo_color_init_rgba (&color
, 0, 0, 0, coverage
/ (double)0xffff);
1941 _cairo_pattern_init_solid (&solid
, &color
);
1943 mask
= compositor
->pattern_to_surface (info
->dst
, &solid
.base
, FALSE
,
1944 &_cairo_unbounded_rectangle
,
1945 &_cairo_unbounded_rectangle
,
1948 if (likely (mask
->status
== CAIRO_STATUS_SUCCESS
)) {
1949 compositor
->composite (info
->dst
, info
->op
, info
->src
, mask
,
1950 x
+ info
->src_x
, y
+ info
->src_y
,
1956 cairo_surface_destroy (mask
);
1958 compositor
->composite (info
->dst
, info
->op
, info
->src
, NULL
,
1959 x
+ info
->src_x
, y
+ info
->src_y
,
1966 static cairo_int_status_t
1967 composite_mask_clip_boxes (const cairo_traps_compositor_t
*compositor
,
1968 cairo_surface_t
*dst
,
1970 cairo_operator_t op
,
1971 cairo_surface_t
*src
,
1976 const cairo_rectangle_int_t
*extents
,
1979 struct composite_mask
*data
= closure
;
1980 struct composite_box_info info
;
1983 TRACE ((stderr
, "%s\n", __FUNCTION__
));
1985 info
.compositor
= compositor
;
1986 info
.op
= CAIRO_OPERATOR_SOURCE
;
1988 info
.src
= data
->mask
;
1989 info
.src_x
= data
->mask_x
;
1990 info
.src_y
= data
->mask_y
;
1992 info
.src_x
+= dst_x
;
1993 info
.src_y
+= dst_y
;
1995 for (i
= 0; i
< clip
->num_boxes
; i
++)
1996 do_unaligned_box(composite_box
, &info
, &clip
->boxes
[i
], dst_x
, dst_y
);
1998 return CAIRO_STATUS_SUCCESS
;
2001 static cairo_int_status_t
2002 composite_mask_clip (const cairo_traps_compositor_t
*compositor
,
2003 cairo_surface_t
*dst
,
2005 cairo_operator_t op
,
2006 cairo_surface_t
*src
,
2011 const cairo_rectangle_int_t
*extents
,
2014 struct composite_mask
*data
= closure
;
2015 cairo_polygon_t polygon
;
2016 cairo_fill_rule_t fill_rule
;
2017 composite_traps_info_t info
;
2018 cairo_status_t status
;
2020 TRACE ((stderr
, "%s\n", __FUNCTION__
));
2022 status
= _cairo_clip_get_polygon (clip
, &polygon
,
2023 &fill_rule
, &info
.antialias
);
2024 if (unlikely (status
))
2027 _cairo_traps_init (&info
.traps
);
2028 status
= _cairo_bentley_ottmann_tessellate_polygon (&info
.traps
,
2031 _cairo_polygon_fini (&polygon
);
2032 if (unlikely (status
))
2035 status
= composite_traps (compositor
, dst
, &info
,
2036 CAIRO_OPERATOR_SOURCE
,
2038 data
->mask_x
+ dst_x
, data
->mask_y
+ dst_y
,
2041 _cairo_traps_fini (&info
.traps
);
2046 /* high-level compositor interface */
2048 static cairo_int_status_t
2049 _cairo_traps_compositor_paint (const cairo_compositor_t
*_compositor
,
2050 cairo_composite_rectangles_t
*extents
)
2052 cairo_traps_compositor_t
*compositor
= (cairo_traps_compositor_t
*)_compositor
;
2053 cairo_boxes_t boxes
;
2054 cairo_int_status_t status
;
2056 TRACE ((stderr
, "%s\n", __FUNCTION__
));
2058 status
= compositor
->check_composite (extents
);
2059 if (unlikely (status
))
2062 _cairo_clip_steal_boxes (extents
->clip
, &boxes
);
2063 status
= clip_and_composite_boxes (compositor
, extents
, &boxes
);
2064 _cairo_clip_unsteal_boxes (extents
->clip
, &boxes
);
2069 static cairo_int_status_t
2070 _cairo_traps_compositor_mask (const cairo_compositor_t
*_compositor
,
2071 cairo_composite_rectangles_t
*extents
)
2073 const cairo_traps_compositor_t
*compositor
= (cairo_traps_compositor_t
*)_compositor
;
2074 cairo_int_status_t status
;
2076 TRACE ((stderr
, "%s\n", __FUNCTION__
));
2078 status
= compositor
->check_composite (extents
);
2079 if (unlikely (status
))
2082 if (extents
->mask_pattern
.base
.type
== CAIRO_PATTERN_TYPE_SOLID
&&
2083 extents
->clip
->path
== NULL
) {
2084 status
= clip_and_composite (compositor
, extents
,
2085 composite_opacity_boxes
,
2086 composite_opacity_boxes
,
2087 &extents
->mask_pattern
,
2088 need_unbounded_clip (extents
));
2090 struct composite_mask data
;
2092 data
.mask
= compositor
->pattern_to_surface (extents
->surface
,
2093 &extents
->mask_pattern
.base
,
2096 &extents
->mask_sample_area
,
2099 if (unlikely (data
.mask
->status
))
2100 return data
.mask
->status
;
2102 status
= clip_and_composite (compositor
, extents
,
2104 extents
->clip
->path
? composite_mask_clip
: composite_mask_clip_boxes
,
2105 &data
, need_bounded_clip (extents
));
2107 cairo_surface_destroy (data
.mask
);
2113 static cairo_int_status_t
2114 _cairo_traps_compositor_stroke (const cairo_compositor_t
*_compositor
,
2115 cairo_composite_rectangles_t
*extents
,
2116 const cairo_path_fixed_t
*path
,
2117 const cairo_stroke_style_t
*style
,
2118 const cairo_matrix_t
*ctm
,
2119 const cairo_matrix_t
*ctm_inverse
,
2121 cairo_antialias_t antialias
)
2123 const cairo_traps_compositor_t
*compositor
= (cairo_traps_compositor_t
*)_compositor
;
2124 cairo_int_status_t status
;
2126 TRACE ((stderr
, "%s\n", __FUNCTION__
));
2128 status
= compositor
->check_composite (extents
);
2129 if (unlikely (status
))
2132 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2133 if (_cairo_path_fixed_stroke_is_rectilinear (path
)) {
2134 cairo_boxes_t boxes
;
2136 _cairo_boxes_init_with_clip (&boxes
, extents
->clip
);
2137 status
= _cairo_path_fixed_stroke_rectilinear_to_boxes (path
,
2142 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
))
2143 status
= clip_and_composite_boxes (compositor
, extents
, &boxes
);
2144 _cairo_boxes_fini (&boxes
);
2147 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
&& 0 &&
2148 _cairo_clip_is_region (extents
->clip
)) /* XXX */
2150 composite_tristrip_info_t info
;
2152 info
.antialias
= antialias
;
2153 _cairo_tristrip_init_with_clip (&info
.strip
, extents
->clip
);
2154 status
= _cairo_path_fixed_stroke_to_tristrip (path
, style
,
2158 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
))
2159 status
= clip_and_composite_tristrip (compositor
, extents
, &info
);
2160 _cairo_tristrip_fini (&info
.strip
);
2163 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
&&
2164 path
->has_curve_to
&& antialias
== CAIRO_ANTIALIAS_NONE
) {
2165 cairo_polygon_t polygon
;
2167 _cairo_polygon_init_with_clip (&polygon
, extents
->clip
);
2168 status
= _cairo_path_fixed_stroke_to_polygon (path
, style
,
2172 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
))
2173 status
= clip_and_composite_polygon (compositor
,
2175 CAIRO_ANTIALIAS_NONE
,
2176 CAIRO_FILL_RULE_WINDING
,
2178 _cairo_polygon_fini (&polygon
);
2181 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
2182 cairo_int_status_t (*func
) (const cairo_path_fixed_t
*path
,
2183 const cairo_stroke_style_t
*stroke_style
,
2184 const cairo_matrix_t
*ctm
,
2185 const cairo_matrix_t
*ctm_inverse
,
2187 cairo_traps_t
*traps
);
2188 composite_traps_info_t info
;
2191 if (antialias
== CAIRO_ANTIALIAS_BEST
|| antialias
== CAIRO_ANTIALIAS_GOOD
) {
2192 func
= _cairo_path_fixed_stroke_polygon_to_traps
;
2195 func
= _cairo_path_fixed_stroke_to_traps
;
2196 flags
= need_bounded_clip (extents
) & ~NEED_CLIP_SURFACE
;
2199 info
.antialias
= antialias
;
2200 _cairo_traps_init_with_clip (&info
.traps
, extents
->clip
);
2201 status
= func (path
, style
, ctm
, ctm_inverse
, tolerance
, &info
.traps
);
2202 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
))
2203 status
= clip_and_composite_traps (compositor
, extents
, &info
, flags
);
2204 _cairo_traps_fini (&info
.traps
);
2210 static cairo_int_status_t
2211 _cairo_traps_compositor_fill (const cairo_compositor_t
*_compositor
,
2212 cairo_composite_rectangles_t
*extents
,
2213 const cairo_path_fixed_t
*path
,
2214 cairo_fill_rule_t fill_rule
,
2216 cairo_antialias_t antialias
)
2218 const cairo_traps_compositor_t
*compositor
= (cairo_traps_compositor_t
*)_compositor
;
2219 cairo_int_status_t status
;
2221 TRACE ((stderr
, "%s\n", __FUNCTION__
));
2223 status
= compositor
->check_composite (extents
);
2224 if (unlikely (status
))
2227 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2228 if (_cairo_path_fixed_fill_is_rectilinear (path
)) {
2229 cairo_boxes_t boxes
;
2231 _cairo_boxes_init_with_clip (&boxes
, extents
->clip
);
2232 status
= _cairo_path_fixed_fill_rectilinear_to_boxes (path
,
2236 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
))
2237 status
= clip_and_composite_boxes (compositor
, extents
, &boxes
);
2238 _cairo_boxes_fini (&boxes
);
2241 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
2242 cairo_polygon_t polygon
;
2245 if (extents
->mask
.width
> extents
->unbounded
.width
||
2246 extents
->mask
.height
> extents
->unbounded
.height
)
2249 _cairo_box_from_rectangle (&limits
, &extents
->unbounded
);
2250 _cairo_polygon_init (&polygon
, &limits
, 1);
2254 _cairo_polygon_init (&polygon
, NULL
, 0);
2257 status
= _cairo_path_fixed_fill_to_polygon (path
, tolerance
, &polygon
);
2258 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
2259 status
= _cairo_polygon_intersect_with_boxes (&polygon
, &fill_rule
,
2260 extents
->clip
->boxes
,
2261 extents
->clip
->num_boxes
);
2264 _cairo_polygon_init_with_clip (&polygon
, extents
->clip
);
2265 status
= _cairo_path_fixed_fill_to_polygon (path
, tolerance
, &polygon
);
2267 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
2268 status
= clip_and_composite_polygon (compositor
, extents
, &polygon
,
2269 antialias
, fill_rule
, path
->has_curve_to
);
2271 _cairo_polygon_fini (&polygon
);
2277 static cairo_int_status_t
2278 composite_glyphs (const cairo_traps_compositor_t
*compositor
,
2279 cairo_surface_t
*dst
,
2281 cairo_operator_t op
,
2282 cairo_surface_t
*src
,
2283 int src_x
, int src_y
,
2284 int dst_x
, int dst_y
,
2285 const cairo_rectangle_int_t
*extents
,
2288 cairo_composite_glyphs_info_t
*info
= closure
;
2290 TRACE ((stderr
, "%s\n", __FUNCTION__
));
2292 if (op
== CAIRO_OPERATOR_ADD
&& (dst
->content
& CAIRO_CONTENT_COLOR
) == 0)
2295 return compositor
->composite_glyphs (dst
, op
, src
,
2301 static cairo_int_status_t
2302 _cairo_traps_compositor_glyphs (const cairo_compositor_t
*_compositor
,
2303 cairo_composite_rectangles_t
*extents
,
2304 cairo_scaled_font_t
*scaled_font
,
2305 cairo_glyph_t
*glyphs
,
2307 cairo_bool_t overlap
)
2309 const cairo_traps_compositor_t
*compositor
= (cairo_traps_compositor_t
*)_compositor
;
2310 cairo_int_status_t status
;
2312 TRACE ((stderr
, "%s\n", __FUNCTION__
));
2314 status
= compositor
->check_composite (extents
);
2315 if (unlikely (status
))
2318 _cairo_scaled_font_freeze_cache (scaled_font
);
2319 status
= compositor
->check_composite_glyphs (extents
,
2320 scaled_font
, glyphs
,
2322 if (likely (status
== CAIRO_INT_STATUS_SUCCESS
)) {
2323 cairo_composite_glyphs_info_t info
;
2325 info
.font
= scaled_font
;
2326 info
.glyphs
= glyphs
;
2327 info
.num_glyphs
= num_glyphs
;
2328 info
.use_mask
= overlap
|| ! extents
->is_bounded
;
2329 info
.extents
= extents
->bounded
;
2331 status
= clip_and_composite (compositor
, extents
,
2332 composite_glyphs
, NULL
, &info
,
2333 need_bounded_clip (extents
) | FORCE_CLIP_REGION
);
2335 _cairo_scaled_font_thaw_cache (scaled_font
);
2341 _cairo_traps_compositor_init (cairo_traps_compositor_t
*compositor
,
2342 const cairo_compositor_t
*delegate
)
2344 compositor
->base
.delegate
= delegate
;
2346 compositor
->base
.paint
= _cairo_traps_compositor_paint
;
2347 compositor
->base
.mask
= _cairo_traps_compositor_mask
;
2348 compositor
->base
.fill
= _cairo_traps_compositor_fill
;
2349 compositor
->base
.stroke
= _cairo_traps_compositor_stroke
;
2350 compositor
->base
.glyphs
= _cairo_traps_compositor_glyphs
;