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_similar_scratch (composite->surface,
314 if (unlikely (mask->status)) {
315 _cairo_traps_fini (&traps);
319 src = compositor->pattern_to_surface (mask, NULL, FALSE,
322 if (unlikely (status = src->status))
325 status = compositor->acquire (mask);
326 if (unlikely (status))
329 _cairo_boxes_init_from_rectangle (&clear,
333 status = compositor->fill_boxes (mask,
334 CAIRO_OPERATOR_CLEAR,
335 CAIRO_COLOR_TRANSPARENT,
337 if (unlikely (status))
340 status = compositor->composite_traps (mask, CAIRO_OPERATOR_ADD, src,
342 extents->x, extents->y,
345 if (unlikely (status))
348 compositor->release (mask);
351 cairo_surface_destroy (src);
352 _cairo_traps_fini (&traps);
356 compositor->release (mask);
358 cairo_surface_destroy (mask);
362 static cairo_surface_t *
363 traps_get_clip_surface (const cairo_traps_compositor_t *compositor,
364 const cairo_composite_rectangles_t *composite,
365 const cairo_rectangle_int_t *extents)
367 cairo_surface_t *surface = NULL;
368 cairo_int_status_t status;
370 TRACE ((stderr, "%s\n", __FUNCTION__));
372 status = __clip_to_surface (compositor, composite, extents, &surface);
373 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
374 surface = _cairo_surface_create_similar_solid (composite->surface,
379 if (unlikely (surface->status))
382 status = _cairo_clip_combine_with_surface (composite->clip, surface,
383 extents->x, extents->y);
385 if (unlikely (status)) {
386 cairo_surface_destroy (surface);
387 surface = _cairo_surface_create_in_error (status);
393 static void blt_unaligned_boxes(const cairo_traps_compositor_t *compositor,
394 cairo_surface_t *surface,
402 info.compositor = compositor;
404 _cairo_boxes_init (&info.boxes);
405 info.boxes.num_boxes = 1;
406 for (i = 0; i < num_boxes; i++) {
407 cairo_box_t *b = &boxes[i];
409 if (! _cairo_fixed_is_integer (b->p1.x) ||
410 ! _cairo_fixed_is_integer (b->p1.y) ||
411 ! _cairo_fixed_is_integer (b->p2.x) ||
412 ! _cairo_fixed_is_integer (b->p2.y))
414 do_unaligned_box(blt_in, &info, b, dx, dy);
419 static cairo_surface_t *
420 create_composite_mask (const cairo_traps_compositor_t *compositor,
421 cairo_surface_t *dst,
423 draw_func_t draw_func,
424 draw_func_t mask_func,
425 const cairo_composite_rectangles_t *extents)
427 cairo_surface_t *surface, *src;
428 cairo_int_status_t status;
431 TRACE ((stderr, "%s\n", __FUNCTION__));
433 surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_ALPHA,
434 extents->bounded.width,
435 extents->bounded.height);
436 if (unlikely (surface->status))
439 src = compositor->pattern_to_surface (surface,
440 &_cairo_pattern_white.base,
445 if (unlikely (src->status)) {
446 cairo_surface_destroy (surface);
450 status = compositor->acquire (surface);
451 if (unlikely (status)) {
452 cairo_surface_destroy (src);
453 cairo_surface_destroy (surface);
454 return _cairo_surface_create_in_error (status);
457 if (!surface->is_clear) {
460 _cairo_boxes_init_from_rectangle (&clear,
462 extents->bounded.width,
463 extents->bounded.height);
464 status = compositor->fill_boxes (surface,
465 CAIRO_OPERATOR_CLEAR,
466 CAIRO_COLOR_TRANSPARENT,
468 if (unlikely (status))
471 surface->is_clear = TRUE;
475 status = mask_func (compositor, surface, draw_closure,
476 CAIRO_OPERATOR_SOURCE, src, src_x, src_y,
477 extents->bounded.x, extents->bounded.y,
478 &extents->bounded, extents->clip);
479 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
480 surface->is_clear = FALSE;
483 if (unlikely (status != CAIRO_INT_STATUS_UNSUPPORTED))
487 /* Is it worth setting the clip region here? */
488 status = draw_func (compositor, surface, draw_closure,
489 CAIRO_OPERATOR_ADD, src, src_x, src_y,
490 extents->bounded.x, extents->bounded.y,
491 &extents->bounded, NULL);
492 if (unlikely (status))
495 surface->is_clear = FALSE;
496 if (extents->clip->path != NULL) {
497 status = combine_clip_as_traps (compositor, surface,
498 extents->clip, &extents->bounded);
499 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
500 status = _cairo_clip_combine_with_surface (extents->clip, surface,
504 if (unlikely (status))
506 } else if (extents->clip->boxes) {
507 blt_unaligned_boxes(compositor, surface,
508 extents->bounded.x, extents->bounded.y,
509 extents->clip->boxes, extents->clip->num_boxes);
514 compositor->release (surface);
515 cairo_surface_destroy (src);
519 compositor->release (surface);
520 if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
521 cairo_surface_destroy (surface);
522 surface = _cairo_surface_create_in_error (status);
524 cairo_surface_destroy (src);
528 /* Handles compositing with a clip surface when the operator allows
529 * us to combine the clip with the mask
531 static cairo_status_t
532 clip_and_composite_with_mask (const cairo_traps_compositor_t *compositor,
533 const cairo_composite_rectangles_t*extents,
534 draw_func_t draw_func,
535 draw_func_t mask_func,
538 cairo_surface_t *src,
539 int src_x, int src_y)
541 cairo_surface_t *dst = extents->surface;
542 cairo_surface_t *mask;
544 TRACE ((stderr, "%s\n", __FUNCTION__));
546 mask = create_composite_mask (compositor, dst, draw_closure,
547 draw_func, mask_func,
549 if (unlikely (mask->status))
555 if (src != NULL || dst->content != CAIRO_CONTENT_ALPHA) {
556 compositor->composite (dst, op, src, mask,
557 extents->bounded.x + src_x,
558 extents->bounded.y + src_y,
560 extents->bounded.x, extents->bounded.y,
561 extents->bounded.width, extents->bounded.height);
563 compositor->composite (dst, op, mask, NULL,
566 extents->bounded.x, extents->bounded.y,
567 extents->bounded.width, extents->bounded.height);
571 cairo_surface_destroy (mask);
572 return CAIRO_STATUS_SUCCESS;
575 /* Handles compositing with a clip surface when we have to do the operation
576 * in two pieces and combine them together.
578 static cairo_status_t
579 clip_and_composite_combine (const cairo_traps_compositor_t *compositor,
580 const cairo_composite_rectangles_t*extents,
581 draw_func_t draw_func,
584 cairo_surface_t *src,
585 int src_x, int src_y)
587 cairo_surface_t *dst = extents->surface;
588 cairo_surface_t *tmp, *clip;
589 cairo_status_t status;
591 TRACE ((stderr, "%s\n", __FUNCTION__));
593 tmp = _cairo_surface_create_similar_scratch (dst, dst->content,
594 extents->bounded.width,
595 extents->bounded.height);
596 if (unlikely (tmp->status))
599 status = compositor->acquire (tmp);
600 if (unlikely (status)) {
601 cairo_surface_destroy (tmp);
605 compositor->composite (tmp,
606 dst->is_clear ? CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
608 extents->bounded.x, extents->bounded.y,
611 extents->bounded.width, extents->bounded.height);
613 status = draw_func (compositor, tmp, draw_closure, op,
615 extents->bounded.x, extents->bounded.y,
616 &extents->bounded, NULL);
618 if (unlikely (status))
621 clip = traps_get_clip_surface (compositor, extents, &extents->bounded);
622 if (unlikely ((status = clip->status)))
626 compositor->composite (dst, CAIRO_OPERATOR_SOURCE, tmp, clip,
629 extents->bounded.x, extents->bounded.y,
630 extents->bounded.width, extents->bounded.height);
632 compositor->lerp (dst, tmp, clip,
635 extents->bounded.x, extents->bounded.y,
636 extents->bounded.width, extents->bounded.height);
638 cairo_surface_destroy (clip);
641 compositor->release (tmp);
642 cairo_surface_destroy (tmp);
647 /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
648 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
650 static cairo_status_t
651 clip_and_composite_source (const cairo_traps_compositor_t *compositor,
652 cairo_surface_t *dst,
653 draw_func_t draw_func,
654 draw_func_t mask_func,
656 cairo_surface_t *src,
659 const cairo_composite_rectangles_t *extents)
661 cairo_surface_t *mask;
663 TRACE ((stderr, "%s\n", __FUNCTION__));
665 /* Create a surface that is mask IN clip */
666 mask = create_composite_mask (compositor, dst, draw_closure,
667 draw_func, mask_func,
669 if (unlikely (mask->status))
676 compositor->composite (dst, CAIRO_OPERATOR_SOURCE, src, mask,
677 extents->bounded.x + src_x, extents->bounded.y + src_y,
679 extents->bounded.x, extents->bounded.y,
680 extents->bounded.width, extents->bounded.height);
682 compositor->lerp (dst, src, mask,
683 extents->bounded.x + src_x, extents->bounded.y + src_y,
685 extents->bounded.x, extents->bounded.y,
686 extents->bounded.width, extents->bounded.height);
690 cairo_surface_destroy (mask);
692 return CAIRO_STATUS_SUCCESS;
696 can_reduce_alpha_op (cairo_operator_t op)
700 case CAIRO_OPERATOR_OVER:
701 case CAIRO_OPERATOR_SOURCE:
702 case CAIRO_OPERATOR_ADD:
710 reduce_alpha_op (cairo_composite_rectangles_t *extents)
712 cairo_surface_t *dst = extents->surface;
713 cairo_operator_t op = extents->op;
714 const cairo_pattern_t *pattern = &extents->source_pattern.base;
715 return dst->is_clear &&
716 dst->content == CAIRO_CONTENT_ALPHA &&
717 _cairo_pattern_is_opaque_solid (pattern) &&
718 can_reduce_alpha_op (op);
721 static cairo_status_t
722 fixup_unbounded_with_mask (const cairo_traps_compositor_t *compositor,
723 const cairo_composite_rectangles_t *extents)
725 cairo_surface_t *dst = extents->surface;
726 cairo_surface_t *mask;
728 TRACE ((stderr, "%s\n", __FUNCTION__));
730 /* XXX can we avoid querying the clip surface again? */
731 mask = traps_get_clip_surface (compositor, extents, &extents->unbounded);
732 if (unlikely (mask->status))
736 if (extents->bounded.y != extents->unbounded.y) {
737 int x = extents->unbounded.x;
738 int y = extents->unbounded.y;
739 int width = extents->unbounded.width;
740 int height = extents->bounded.y - y;
742 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
750 if (extents->bounded.x != extents->unbounded.x) {
751 int x = extents->unbounded.x;
752 int y = extents->bounded.y;
753 int width = extents->bounded.x - x;
754 int height = extents->bounded.height;
756 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
757 0, y - extents->unbounded.y,
764 if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
765 int x = extents->bounded.x + extents->bounded.width;
766 int y = extents->bounded.y;
767 int width = extents->unbounded.x + extents->unbounded.width - x;
768 int height = extents->bounded.height;
770 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
771 x - extents->unbounded.x, y - extents->unbounded.y,
778 if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
779 int x = extents->unbounded.x;
780 int y = extents->bounded.y + extents->bounded.height;
781 int width = extents->unbounded.width;
782 int height = extents->unbounded.y + extents->unbounded.height - y;
784 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
785 0, y - extents->unbounded.y,
791 cairo_surface_destroy (mask);
793 return CAIRO_STATUS_SUCCESS;
797 add_rect (cairo_boxes_t *boxes, int x1, int y1, int x2, int y2)
800 cairo_int_status_t status;
802 box.p1.x = _cairo_fixed_from_int (x1);
803 box.p1.y = _cairo_fixed_from_int (y1);
804 box.p2.x = _cairo_fixed_from_int (x2);
805 box.p2.y = _cairo_fixed_from_int (y2);
807 status = _cairo_boxes_add (boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
808 assert (status == CAIRO_INT_STATUS_SUCCESS);
811 static cairo_status_t
812 fixup_unbounded (const cairo_traps_compositor_t *compositor,
813 cairo_composite_rectangles_t *extents,
814 cairo_boxes_t *boxes)
816 cairo_surface_t *dst = extents->surface;
817 cairo_boxes_t clear, tmp;
819 cairo_int_status_t status;
821 TRACE ((stderr, "%s\n", __FUNCTION__));
823 if (extents->bounded.width == extents->unbounded.width &&
824 extents->bounded.height == extents->unbounded.height)
826 return CAIRO_STATUS_SUCCESS;
829 assert (extents->clip->path == NULL);
831 /* subtract the drawn boxes from the unbounded area */
832 _cairo_boxes_init (&clear);
834 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
835 box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
836 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
837 box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
840 if (extents->bounded.width == 0 || extents->bounded.height == 0) {
844 if (extents->bounded.y != extents->unbounded.y) {
846 extents->unbounded.x, extents->unbounded.y,
847 extents->unbounded.x + extents->unbounded.width,
851 if (extents->bounded.x != extents->unbounded.x) {
853 extents->unbounded.x, extents->bounded.y,
855 extents->bounded.y + extents->bounded.height);
858 if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
860 extents->bounded.x + extents->bounded.width,
862 extents->unbounded.x + extents->unbounded.width,
863 extents->bounded.y + extents->bounded.height);
866 if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
868 extents->unbounded.x,
869 extents->bounded.y + extents->bounded.height,
870 extents->unbounded.x + extents->unbounded.width,
871 extents->unbounded.y + extents->unbounded.height);
874 } else if (boxes->num_boxes) {
875 _cairo_boxes_init (&tmp);
877 assert (boxes->is_pixel_aligned);
879 status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
880 assert (status == CAIRO_INT_STATUS_SUCCESS);
882 tmp.chunks.next = &boxes->chunks;
883 tmp.num_boxes += boxes->num_boxes;
885 status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
886 CAIRO_FILL_RULE_WINDING,
888 tmp.chunks.next = NULL;
889 if (unlikely (status))
893 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x);
894 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
896 status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
897 assert (status == CAIRO_INT_STATUS_SUCCESS);
900 /* Now intersect with the clip boxes */
901 if (extents->clip->num_boxes) {
902 _cairo_boxes_init_for_array (&tmp,
903 extents->clip->boxes,
904 extents->clip->num_boxes);
905 status = _cairo_boxes_intersect (&clear, &tmp, &clear);
906 if (unlikely (status))
910 status = compositor->fill_boxes (dst,
911 CAIRO_OPERATOR_CLEAR,
912 CAIRO_COLOR_TRANSPARENT,
916 _cairo_boxes_fini (&clear);
921 NEED_CLIP_REGION = 0x1,
922 NEED_CLIP_SURFACE = 0x2,
923 FORCE_CLIP_REGION = 0x4,
927 need_bounded_clip (cairo_composite_rectangles_t *extents)
929 unsigned int flags = 0;
931 if (extents->unbounded.width < extents->destination.width ||
932 extents->unbounded.height < extents->destination.height)
934 flags |= NEED_CLIP_REGION;
937 if (! _cairo_clip_is_region (extents->clip))
938 flags |= NEED_CLIP_SURFACE;
944 need_unbounded_clip (cairo_composite_rectangles_t *extents)
946 unsigned int flags = 0;
947 if (! extents->is_bounded) {
948 flags |= NEED_CLIP_REGION;
949 if (! _cairo_clip_is_region (extents->clip))
950 flags |= NEED_CLIP_SURFACE;
952 if (extents->clip->path != NULL)
953 flags |= NEED_CLIP_SURFACE;
957 static cairo_status_t
958 clip_and_composite (const cairo_traps_compositor_t *compositor,
959 cairo_composite_rectangles_t *extents,
960 draw_func_t draw_func,
961 draw_func_t mask_func,
963 unsigned int need_clip)
965 cairo_surface_t *dst = extents->surface;
966 cairo_operator_t op = extents->op;
967 cairo_pattern_t *source = &extents->source_pattern.base;
968 cairo_surface_t *src;
970 cairo_region_t *clip_region = NULL;
971 cairo_status_t status = CAIRO_STATUS_SUCCESS;
973 TRACE ((stderr, "%s\n", __FUNCTION__));
975 if (reduce_alpha_op (extents)) {
976 op = CAIRO_OPERATOR_ADD;
980 if (op == CAIRO_OPERATOR_CLEAR) {
981 op = CAIRO_OPERATOR_DEST_OUT;
985 compositor->acquire (dst);
987 if (need_clip & NEED_CLIP_REGION) {
988 const cairo_rectangle_int_t *limit;
990 if ((need_clip & FORCE_CLIP_REGION) == 0)
991 limit = &extents->unbounded;
993 limit = &extents->destination;
995 clip_region = _cairo_clip_get_region (extents->clip);
996 if (clip_region != NULL &&
997 cairo_region_contains_rectangle (clip_region,
998 limit) == CAIRO_REGION_OVERLAP_IN)
1001 if (clip_region != NULL) {
1002 status = compositor->set_clip_region (dst, clip_region);
1003 if (unlikely (status)) {
1004 compositor->release (dst);
1010 if (extents->bounded.width == 0 || extents->bounded.height == 0)
1013 src = compositor->pattern_to_surface (dst, source, FALSE,
1015 &extents->source_sample_area,
1017 if (unlikely (status = src->status))
1020 if (op == CAIRO_OPERATOR_SOURCE) {
1021 status = clip_and_composite_source (compositor, dst,
1022 draw_func, mask_func, draw_closure,
1026 if (need_clip & NEED_CLIP_SURFACE) {
1027 if (extents->is_bounded) {
1028 status = clip_and_composite_with_mask (compositor, extents,
1029 draw_func, mask_func,
1031 op, src, src_x, src_y);
1033 status = clip_and_composite_combine (compositor, extents,
1034 draw_func, draw_closure,
1035 op, src, src_x, src_y);
1038 status = draw_func (compositor,
1040 op, src, src_x, src_y,
1046 cairo_surface_destroy (src);
1049 if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
1050 if (need_clip & NEED_CLIP_SURFACE)
1051 status = fixup_unbounded_with_mask (compositor, extents);
1053 status = fixup_unbounded (compositor, extents, NULL);
1058 compositor->set_clip_region (dst, NULL);
1060 compositor->release (dst);
1068 cairo_traps_t traps;
1069 cairo_antialias_t antialias;
1070 } composite_traps_info_t;
1072 static cairo_int_status_t
1073 composite_traps (const cairo_traps_compositor_t *compositor,
1074 cairo_surface_t *dst,
1076 cairo_operator_t op,
1077 cairo_surface_t *src,
1078 int src_x, int src_y,
1079 int dst_x, int dst_y,
1080 const cairo_rectangle_int_t *extents,
1083 composite_traps_info_t *info = closure;
1085 TRACE ((stderr, "%s\n", __FUNCTION__));
1087 return compositor->composite_traps (dst, op, src,
1088 src_x - dst_x, src_y - dst_y,
1091 info->antialias, &info->traps);
1095 cairo_tristrip_t strip;
1096 cairo_antialias_t antialias;
1097 } composite_tristrip_info_t;
1099 static cairo_int_status_t
1100 composite_tristrip (const cairo_traps_compositor_t *compositor,
1101 cairo_surface_t *dst,
1103 cairo_operator_t op,
1104 cairo_surface_t *src,
1105 int src_x, int src_y,
1106 int dst_x, int dst_y,
1107 const cairo_rectangle_int_t *extents,
1110 composite_tristrip_info_t *info = closure;
1112 TRACE ((stderr, "%s\n", __FUNCTION__));
1114 return compositor->composite_tristrip (dst, op, src,
1115 src_x - dst_x, src_y - dst_y,
1118 info->antialias, &info->strip);
1122 is_recording_pattern (const cairo_pattern_t *pattern)
1124 cairo_surface_t *surface;
1126 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
1129 surface = ((const cairo_surface_pattern_t *) pattern)->surface;
1130 surface = _cairo_surface_get_source (surface, NULL);
1131 return _cairo_surface_is_recording (surface);
1134 static cairo_surface_t *
1135 recording_pattern_get_surface (const cairo_pattern_t *pattern)
1137 cairo_surface_t *surface;
1139 surface = ((const cairo_surface_pattern_t *) pattern)->surface;
1140 return _cairo_surface_get_source (surface, NULL);
1144 recording_pattern_contains_sample (const cairo_pattern_t *pattern,
1145 const cairo_rectangle_int_t *sample)
1147 cairo_recording_surface_t *surface;
1149 if (! is_recording_pattern (pattern))
1152 if (pattern->extend == CAIRO_EXTEND_NONE)
1155 surface = (cairo_recording_surface_t *) recording_pattern_get_surface (pattern);
1156 if (surface->unbounded)
1159 return _cairo_rectangle_contains_rectangle (&surface->extents, sample);
1163 op_reduces_to_source (cairo_composite_rectangles_t *extents)
1165 if (extents->op == CAIRO_OPERATOR_SOURCE)
1168 if (extents->surface->is_clear)
1169 return extents->op == CAIRO_OPERATOR_OVER || extents->op == CAIRO_OPERATOR_ADD;
1174 static cairo_status_t
1175 composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
1176 cairo_composite_rectangles_t *extents,
1177 cairo_boxes_t *boxes)
1179 cairo_surface_t *dst = extents->surface;
1180 cairo_operator_t op = extents->op;
1181 cairo_bool_t need_clip_mask = ! _cairo_clip_is_region (extents->clip);
1182 cairo_bool_t op_is_source;
1183 cairo_status_t status;
1185 TRACE ((stderr, "%s\n", __FUNCTION__));
1187 if (need_clip_mask &&
1188 (! extents->is_bounded || extents->op == CAIRO_OPERATOR_SOURCE))
1190 return CAIRO_INT_STATUS_UNSUPPORTED;
1193 op_is_source = op_reduces_to_source (extents);
1195 /* Are we just copying a recording surface? */
1196 if (! need_clip_mask && op_is_source &&
1197 recording_pattern_contains_sample (&extents->source_pattern.base,
1198 &extents->source_sample_area))
1200 cairo_clip_t *recording_clip;
1201 cairo_pattern_t *source = &extents->source_pattern.base;
1203 /* XXX could also do tiling repeat modes... */
1205 /* first clear the area about to be overwritten */
1206 if (! dst->is_clear) {
1207 status = compositor->acquire (dst);
1208 if (unlikely (status))
1211 status = compositor->fill_boxes (dst,
1212 CAIRO_OPERATOR_CLEAR,
1213 CAIRO_COLOR_TRANSPARENT,
1215 compositor->release (dst);
1216 if (unlikely (status))
1220 recording_clip = _cairo_clip_from_boxes (boxes);
1221 status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (source),
1223 dst, recording_clip);
1224 _cairo_clip_destroy (recording_clip);
1229 status = compositor->acquire (dst);
1230 if (unlikely (status))
1233 if (! need_clip_mask &&
1234 (op == CAIRO_OPERATOR_CLEAR ||
1235 extents->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID))
1237 const cairo_color_t *color;
1239 if (op == CAIRO_OPERATOR_CLEAR) {
1240 color = CAIRO_COLOR_TRANSPARENT;
1242 color = &((cairo_solid_pattern_t *) &extents->source_pattern)->color;
1244 op = CAIRO_OPERATOR_SOURCE;
1247 status = compositor->fill_boxes (dst, op, color, boxes);
1251 cairo_surface_t *src, *mask = NULL;
1252 cairo_pattern_t *source = &extents->source_pattern.base;
1254 int mask_x = 0, mask_y = 0;
1256 if (need_clip_mask) {
1257 mask = traps_get_clip_surface (compositor,
1258 extents, &extents->bounded);
1259 if (unlikely (mask->status))
1260 return mask->status;
1262 mask_x = -extents->bounded.x;
1263 mask_y = -extents->bounded.y;
1265 if (op == CAIRO_OPERATOR_CLEAR) {
1267 op = CAIRO_OPERATOR_DEST_OUT;
1269 } else if (op_is_source)
1270 op = CAIRO_OPERATOR_SOURCE;
1272 src = compositor->pattern_to_surface (dst, source, FALSE,
1274 &extents->source_sample_area,
1276 if (likely (src->status == CAIRO_STATUS_SUCCESS)) {
1277 status = compositor->composite_boxes (dst, op, src, mask,
1281 boxes, &extents->bounded);
1282 cairo_surface_destroy (src);
1284 status = src->status;
1286 cairo_surface_destroy (mask);
1289 if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded)
1290 status = fixup_unbounded (compositor, extents, boxes);
1292 compositor->release (dst);
1297 static cairo_status_t
1298 upload_boxes (const cairo_traps_compositor_t *compositor,
1299 cairo_composite_rectangles_t *extents,
1300 cairo_boxes_t *boxes)
1302 cairo_surface_t *dst = extents->surface;
1303 const cairo_pattern_t *source = &extents->source_pattern.base;
1304 cairo_surface_t *src;
1305 cairo_rectangle_int_t limit;
1306 cairo_int_status_t status;
1309 TRACE ((stderr, "%s\n", __FUNCTION__));
1311 src = _cairo_pattern_get_source((cairo_surface_pattern_t *)source,
1313 if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
1314 return CAIRO_INT_STATUS_UNSUPPORTED;
1316 if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
1317 return CAIRO_INT_STATUS_UNSUPPORTED;
1319 /* Check that the data is entirely within the image */
1320 if (extents->bounded.x + tx < limit.x || extents->bounded.y + ty < limit.y)
1321 return CAIRO_INT_STATUS_UNSUPPORTED;
1323 if (extents->bounded.x + extents->bounded.width + tx > limit.x + limit.width ||
1324 extents->bounded.y + extents->bounded.height + ty > limit.y + limit.height)
1325 return CAIRO_INT_STATUS_UNSUPPORTED;
1330 if (src->type == CAIRO_SURFACE_TYPE_IMAGE)
1331 status = compositor->draw_image_boxes (dst,
1332 (cairo_image_surface_t *)src,
1335 status = compositor->copy_boxes (dst, src, boxes, &extents->bounded,
1341 static cairo_int_status_t
1342 trim_extents_to_traps (cairo_composite_rectangles_t *extents,
1343 cairo_traps_t *traps)
1347 _cairo_traps_extents (traps, &box);
1348 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1351 static cairo_int_status_t
1352 trim_extents_to_tristrip (cairo_composite_rectangles_t *extents,
1353 cairo_tristrip_t *strip)
1357 _cairo_tristrip_extents (strip, &box);
1358 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1361 static cairo_int_status_t
1362 trim_extents_to_boxes (cairo_composite_rectangles_t *extents,
1363 cairo_boxes_t *boxes)
1367 _cairo_boxes_extents (boxes, &box);
1368 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1371 static cairo_int_status_t
1372 boxes_for_traps (cairo_boxes_t *boxes,
1373 cairo_traps_t *traps,
1374 cairo_antialias_t antialias)
1378 /* first check that the traps are rectilinear */
1379 if (antialias == CAIRO_ANTIALIAS_NONE) {
1380 for (i = 0; i < traps->num_traps; i++) {
1381 const cairo_trapezoid_t *t = &traps->traps[i];
1382 if (_cairo_fixed_integer_round_down (t->left.p1.x) !=
1383 _cairo_fixed_integer_round_down (t->left.p2.x) ||
1384 _cairo_fixed_integer_round_down (t->right.p1.x) !=
1385 _cairo_fixed_integer_round_down (t->right.p2.x))
1387 return CAIRO_INT_STATUS_UNSUPPORTED;
1391 for (i = 0; i < traps->num_traps; i++) {
1392 const cairo_trapezoid_t *t = &traps->traps[i];
1393 if (t->left.p1.x != t->left.p2.x || t->right.p1.x != t->right.p2.x)
1394 return CAIRO_INT_STATUS_UNSUPPORTED;
1398 _cairo_boxes_init (boxes);
1400 boxes->num_boxes = traps->num_traps;
1401 boxes->chunks.base = (cairo_box_t *) traps->traps;
1402 boxes->chunks.count = traps->num_traps;
1403 boxes->chunks.size = traps->num_traps;
1405 if (antialias != CAIRO_ANTIALIAS_NONE) {
1406 for (i = 0; i < traps->num_traps; i++) {
1407 /* Note the traps and boxes alias so we need to take the local copies first. */
1408 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
1409 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
1410 cairo_fixed_t y1 = traps->traps[i].top;
1411 cairo_fixed_t y2 = traps->traps[i].bottom;
1413 boxes->chunks.base[i].p1.x = x1;
1414 boxes->chunks.base[i].p1.y = y1;
1415 boxes->chunks.base[i].p2.x = x2;
1416 boxes->chunks.base[i].p2.y = y2;
1418 if (boxes->is_pixel_aligned) {
1419 boxes->is_pixel_aligned =
1420 _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
1421 _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
1425 boxes->is_pixel_aligned = TRUE;
1427 for (i = 0; i < traps->num_traps; i++) {
1428 /* Note the traps and boxes alias so we need to take the local copies first. */
1429 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
1430 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
1431 cairo_fixed_t y1 = traps->traps[i].top;
1432 cairo_fixed_t y2 = traps->traps[i].bottom;
1434 /* round down here to match Pixman's behavior when using traps. */
1435 boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
1436 boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
1437 boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
1438 boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
1442 return CAIRO_INT_STATUS_SUCCESS;
1445 static cairo_status_t
1446 clip_and_composite_boxes (const cairo_traps_compositor_t *compositor,
1447 cairo_composite_rectangles_t *extents,
1448 cairo_boxes_t *boxes);
1450 static cairo_status_t
1451 clip_and_composite_polygon (const cairo_traps_compositor_t *compositor,
1452 cairo_composite_rectangles_t *extents,
1453 cairo_polygon_t *polygon,
1454 cairo_antialias_t antialias,
1455 cairo_fill_rule_t fill_rule,
1458 composite_traps_info_t traps;
1459 cairo_surface_t *dst = extents->surface;
1460 cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
1461 cairo_int_status_t status;
1463 TRACE ((stderr, "%s\n", __FUNCTION__));
1465 if (polygon->num_edges == 0) {
1466 status = CAIRO_INT_STATUS_SUCCESS;
1468 if (! extents->is_bounded) {
1469 cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
1472 cairo_region_contains_rectangle (clip_region,
1473 &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
1476 if (clip_region != NULL) {
1477 status = compositor->set_clip_region (dst, clip_region);
1478 if (unlikely (status))
1483 status = fixup_unbounded_with_mask (compositor, extents);
1485 status = fixup_unbounded (compositor, extents, NULL);
1487 if (clip_region != NULL)
1488 compositor->set_clip_region (dst, NULL);
1494 if (extents->clip->path != NULL && extents->is_bounded) {
1495 cairo_polygon_t clipper;
1496 cairo_fill_rule_t clipper_fill_rule;
1497 cairo_antialias_t clipper_antialias;
1499 status = _cairo_clip_get_polygon (extents->clip,
1502 &clipper_antialias);
1503 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1504 if (clipper_antialias == antialias) {
1505 status = _cairo_polygon_intersect (polygon, fill_rule,
1506 &clipper, clipper_fill_rule);
1507 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1508 cairo_clip_t * clip = _cairo_clip_copy_region (extents->clip);
1509 _cairo_clip_destroy (extents->clip);
1510 extents->clip = clip;
1512 fill_rule = CAIRO_FILL_RULE_WINDING;
1514 _cairo_polygon_fini (&clipper);
1519 if (antialias == CAIRO_ANTIALIAS_NONE && curvy) {
1520 cairo_boxes_t boxes;
1522 _cairo_boxes_init (&boxes);
1523 status = _cairo_rasterise_polygon_to_boxes (polygon, fill_rule, &boxes);
1524 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1525 assert (boxes.is_pixel_aligned);
1526 status = clip_and_composite_boxes (compositor, extents, &boxes);
1528 _cairo_boxes_fini (&boxes);
1529 if ((status != CAIRO_INT_STATUS_UNSUPPORTED))
1533 _cairo_traps_init (&traps.traps);
1535 if (antialias == CAIRO_ANTIALIAS_NONE && curvy) {
1536 status = _cairo_rasterise_polygon_to_traps (polygon, fill_rule, antialias, &traps.traps);
1538 status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
1540 if (unlikely (status))
1543 status = trim_extents_to_traps (extents, &traps.traps);
1544 if (unlikely (status))
1547 /* Use a fast path if the trapezoids consist of a set of boxes. */
1548 status = CAIRO_INT_STATUS_UNSUPPORTED;
1550 cairo_boxes_t boxes;
1552 status = boxes_for_traps (&boxes, &traps.traps, antialias);
1553 if (status == CAIRO_INT_STATUS_SUCCESS) {
1554 status = clip_and_composite_boxes (compositor, extents, &boxes);
1555 /* XXX need to reconstruct the traps! */
1556 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
1559 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1560 /* Otherwise render the trapezoids to a mask and composite in the usual
1563 unsigned int flags = 0;
1565 /* For unbounded operations, the X11 server will estimate the
1566 * affected rectangle and apply the operation to that. However,
1567 * there are cases where this is an overestimate (e.g. the
1568 * clip-fill-{eo,nz}-unbounded test).
1570 * The clip will trim that overestimate to our expectations.
1572 if (! extents->is_bounded)
1573 flags |= FORCE_CLIP_REGION;
1575 traps.antialias = antialias;
1576 status = clip_and_composite (compositor, extents,
1577 composite_traps, NULL, &traps,
1578 need_unbounded_clip (extents) | flags);
1582 _cairo_traps_fini (&traps.traps);
1587 struct composite_opacity_info {
1588 const cairo_traps_compositor_t *compositor;
1590 cairo_surface_t *dst;
1591 cairo_surface_t *src;
1596 static void composite_opacity(void *closure,
1597 int16_t x, int16_t y,
1598 int16_t w, int16_t h,
1601 struct composite_opacity_info *info = closure;
1602 const cairo_traps_compositor_t *compositor = info->compositor;
1603 cairo_surface_t *mask;
1605 cairo_color_t color;
1606 cairo_solid_pattern_t solid;
1608 _cairo_color_init_rgba (&color, 0, 0, 0, info->opacity * coverage);
1609 _cairo_pattern_init_solid (&solid, &color);
1610 mask = compositor->pattern_to_surface (info->dst, &solid.base, TRUE,
1611 &_cairo_unbounded_rectangle,
1612 &_cairo_unbounded_rectangle,
1614 if (likely (mask->status == CAIRO_STATUS_SUCCESS)) {
1616 compositor->composite (info->dst, info->op, info->src, mask,
1617 x + info->src_x, y + info->src_y,
1622 compositor->composite (info->dst, info->op, mask, NULL,
1630 cairo_surface_destroy (mask);
1634 static cairo_int_status_t
1635 composite_opacity_boxes (const cairo_traps_compositor_t *compositor,
1636 cairo_surface_t *dst,
1638 cairo_operator_t op,
1639 cairo_surface_t *src,
1644 const cairo_rectangle_int_t *extents,
1647 const cairo_solid_pattern_t *mask = closure;
1648 struct composite_opacity_info info;
1651 TRACE ((stderr, "%s\n", __FUNCTION__));
1653 info.compositor = compositor;
1661 info.opacity = mask->color.alpha / (double) 0xffff;
1663 /* XXX for lots of boxes create a clip region for the fully opaque areas */
1664 for (i = 0; i < clip->num_boxes; i++)
1665 do_unaligned_box(composite_opacity, &info,
1666 &clip->boxes[i], dst_x, dst_y);
1668 return CAIRO_STATUS_SUCCESS;
1671 static cairo_int_status_t
1672 composite_boxes (const cairo_traps_compositor_t *compositor,
1673 cairo_surface_t *dst,
1675 cairo_operator_t op,
1676 cairo_surface_t *src,
1681 const cairo_rectangle_int_t *extents,
1684 cairo_traps_t traps;
1685 cairo_status_t status;
1687 TRACE ((stderr, "%s\n", __FUNCTION__));
1689 status = _cairo_traps_init_boxes (&traps, closure);
1690 if (unlikely (status))
1693 status = compositor->composite_traps (dst, op, src,
1694 src_x - dst_x, src_y - dst_y,
1697 CAIRO_ANTIALIAS_DEFAULT, &traps);
1698 _cairo_traps_fini (&traps);
1703 static cairo_status_t
1704 clip_and_composite_boxes (const cairo_traps_compositor_t *compositor,
1705 cairo_composite_rectangles_t *extents,
1706 cairo_boxes_t *boxes)
1708 cairo_int_status_t status;
1710 TRACE ((stderr, "%s\n", __FUNCTION__));
1712 if (boxes->num_boxes == 0 && extents->is_bounded)
1713 return CAIRO_STATUS_SUCCESS;
1715 status = trim_extents_to_boxes (extents, boxes);
1716 if (unlikely (status))
1719 if (boxes->is_pixel_aligned && extents->clip->path == NULL &&
1720 extents->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
1721 (op_reduces_to_source (extents) ||
1722 (extents->op == CAIRO_OPERATOR_OVER &&
1723 (extents->source_pattern.surface.surface->content & CAIRO_CONTENT_ALPHA) == 0)))
1725 status = upload_boxes (compositor, extents, boxes);
1726 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1730 /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
1731 if (extents->clip->path != NULL && extents->is_bounded) {
1732 cairo_polygon_t polygon;
1733 cairo_fill_rule_t fill_rule;
1734 cairo_antialias_t antialias;
1737 clip = _cairo_clip_copy (extents->clip);
1738 clip = _cairo_clip_intersect_boxes (clip, boxes);
1739 if (_cairo_clip_is_all_clipped (clip))
1740 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1742 status = _cairo_clip_get_polygon (clip, &polygon,
1743 &fill_rule, &antialias);
1744 _cairo_clip_path_destroy (clip->path);
1746 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1747 cairo_clip_t *saved_clip = extents->clip;
1748 extents->clip = clip;
1750 status = clip_and_composite_polygon (compositor, extents, &polygon,
1751 antialias, fill_rule, FALSE);
1753 clip = extents->clip;
1754 extents->clip = saved_clip;
1756 _cairo_polygon_fini (&polygon);
1758 _cairo_clip_destroy (clip);
1760 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1764 /* Use a fast path if the boxes are pixel aligned (or nearly aligned!) */
1765 if (boxes->is_pixel_aligned) {
1766 status = composite_aligned_boxes (compositor, extents, boxes);
1767 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1771 return clip_and_composite (compositor, extents,
1772 composite_boxes, NULL, boxes,
1773 need_unbounded_clip (extents));
1776 static cairo_int_status_t
1777 composite_traps_as_boxes (const cairo_traps_compositor_t *compositor,
1778 cairo_composite_rectangles_t *extents,
1779 composite_traps_info_t *info)
1781 cairo_boxes_t boxes;
1783 TRACE ((stderr, "%s\n", __FUNCTION__));
1785 if (! _cairo_traps_to_boxes (&info->traps, info->antialias, &boxes))
1786 return CAIRO_INT_STATUS_UNSUPPORTED;
1788 return clip_and_composite_boxes (compositor, extents, &boxes);
1791 static cairo_int_status_t
1792 clip_and_composite_traps (const cairo_traps_compositor_t *compositor,
1793 cairo_composite_rectangles_t *extents,
1794 composite_traps_info_t *info)
1796 cairo_int_status_t status;
1798 TRACE ((stderr, "%s\n", __FUNCTION__));
1800 status = trim_extents_to_traps (extents, &info->traps);
1801 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1804 status = composite_traps_as_boxes (compositor, extents, info);
1805 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1806 unsigned int flags = 0;
1808 /* For unbounded operations, the X11 server will estimate the
1809 * affected rectangle and apply the operation to that. However,
1810 * there are cases where this is an overestimate (e.g. the
1811 * clip-fill-{eo,nz}-unbounded test).
1813 * The clip will trim that overestimate to our expectations.
1815 if (! extents->is_bounded)
1816 flags |= FORCE_CLIP_REGION;
1818 status = clip_and_composite (compositor, extents,
1819 composite_traps, NULL, info,
1820 need_unbounded_clip (extents) | flags);
1826 static cairo_int_status_t
1827 clip_and_composite_tristrip (const cairo_traps_compositor_t *compositor,
1828 cairo_composite_rectangles_t *extents,
1829 composite_tristrip_info_t *info)
1831 cairo_int_status_t status;
1832 unsigned int flags = 0;
1834 TRACE ((stderr, "%s\n", __FUNCTION__));
1836 status = trim_extents_to_tristrip (extents, &info->strip);
1837 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1840 if (! extents->is_bounded)
1841 flags |= FORCE_CLIP_REGION;
1843 status = clip_and_composite (compositor, extents,
1844 composite_tristrip, NULL, info,
1845 need_unbounded_clip (extents) | flags);
1850 struct composite_mask {
1851 cairo_surface_t *mask;
1855 static cairo_int_status_t
1856 composite_mask (const cairo_traps_compositor_t *compositor,
1857 cairo_surface_t *dst,
1859 cairo_operator_t op,
1860 cairo_surface_t *src,
1865 const cairo_rectangle_int_t *extents,
1868 struct composite_mask *data = closure;
1870 TRACE ((stderr, "%s\n", __FUNCTION__));
1873 compositor->composite (dst, op, src, data->mask,
1874 extents->x + src_x, extents->y + src_y,
1875 extents->x + data->mask_x, extents->y + data->mask_y,
1876 extents->x - dst_x, extents->y - dst_y,
1877 extents->width, extents->height);
1879 compositor->composite (dst, op, data->mask, NULL,
1880 extents->x + data->mask_x, extents->y + data->mask_y,
1882 extents->x - dst_x, extents->y - dst_y,
1883 extents->width, extents->height);
1886 return CAIRO_STATUS_SUCCESS;
1889 struct composite_box_info {
1890 const cairo_traps_compositor_t *compositor;
1891 cairo_surface_t *dst;
1892 cairo_surface_t *src;
1897 static void composite_box(void *closure,
1898 int16_t x, int16_t y,
1899 int16_t w, int16_t h,
1902 struct composite_box_info *info = closure;
1903 const cairo_traps_compositor_t *compositor = info->compositor;
1905 TRACE ((stderr, "%s\n", __FUNCTION__));
1907 if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (coverage)) {
1908 cairo_surface_t *mask;
1909 cairo_color_t color;
1910 cairo_solid_pattern_t solid;
1913 _cairo_color_init_rgba (&color, 0, 0, 0, coverage / (double)0xffff);
1914 _cairo_pattern_init_solid (&solid, &color);
1916 mask = compositor->pattern_to_surface (info->dst, &solid.base, FALSE,
1917 &_cairo_unbounded_rectangle,
1918 &_cairo_unbounded_rectangle,
1921 if (likely (mask->status == CAIRO_STATUS_SUCCESS)) {
1922 compositor->composite (info->dst, info->op, info->src, mask,
1923 x + info->src_x, y + info->src_y,
1929 cairo_surface_destroy (mask);
1931 compositor->composite (info->dst, info->op, info->src, NULL,
1932 x + info->src_x, y + info->src_y,
1939 static cairo_int_status_t
1940 composite_mask_clip_boxes (const cairo_traps_compositor_t *compositor,
1941 cairo_surface_t *dst,
1943 cairo_operator_t op,
1944 cairo_surface_t *src,
1949 const cairo_rectangle_int_t *extents,
1952 struct composite_mask *data = closure;
1953 struct composite_box_info info;
1956 TRACE ((stderr, "%s\n", __FUNCTION__));
1958 info.compositor = compositor;
1959 info.op = CAIRO_OPERATOR_SOURCE;
1961 info.src = data->mask;
1962 info.src_x = data->mask_x;
1963 info.src_y = data->mask_y;
1965 info.src_x += dst_x;
1966 info.src_y += dst_y;
1968 for (i = 0; i < clip->num_boxes; i++)
1969 do_unaligned_box(composite_box, &info, &clip->boxes[i], dst_x, dst_y);
1971 return CAIRO_STATUS_SUCCESS;
1974 static cairo_int_status_t
1975 composite_mask_clip (const cairo_traps_compositor_t *compositor,
1976 cairo_surface_t *dst,
1978 cairo_operator_t op,
1979 cairo_surface_t *src,
1984 const cairo_rectangle_int_t *extents,
1987 struct composite_mask *data = closure;
1988 cairo_polygon_t polygon;
1989 cairo_fill_rule_t fill_rule;
1990 composite_traps_info_t info;
1991 cairo_status_t status;
1993 TRACE ((stderr, "%s\n", __FUNCTION__));
1995 status = _cairo_clip_get_polygon (clip, &polygon,
1996 &fill_rule, &info.antialias);
1997 if (unlikely (status))
2000 _cairo_traps_init (&info.traps);
2001 status = _cairo_bentley_ottmann_tessellate_polygon (&info.traps,
2004 _cairo_polygon_fini (&polygon);
2005 if (unlikely (status))
2008 status = composite_traps (compositor, dst, &info,
2009 CAIRO_OPERATOR_SOURCE,
2011 data->mask_x + dst_x, data->mask_y + dst_y,
2014 _cairo_traps_fini (&info.traps);
2019 /* high-level compositor interface */
2021 static cairo_int_status_t
2022 _cairo_traps_compositor_paint (const cairo_compositor_t *_compositor,
2023 cairo_composite_rectangles_t *extents)
2025 cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
2026 cairo_boxes_t boxes;
2027 cairo_int_status_t status;
2029 TRACE ((stderr, "%s\n", __FUNCTION__));
2031 status = compositor->check_composite (extents);
2032 if (unlikely (status))
2035 _cairo_clip_steal_boxes (extents->clip, &boxes);
2036 status = clip_and_composite_boxes (compositor, extents, &boxes);
2037 _cairo_clip_unsteal_boxes (extents->clip, &boxes);
2042 static cairo_int_status_t
2043 _cairo_traps_compositor_mask (const cairo_compositor_t *_compositor,
2044 cairo_composite_rectangles_t *extents)
2046 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
2047 cairo_int_status_t status;
2049 TRACE ((stderr, "%s\n", __FUNCTION__));
2051 status = compositor->check_composite (extents);
2052 if (unlikely (status))
2055 if (extents->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
2056 extents->clip->path == NULL) {
2057 status = clip_and_composite (compositor, extents,
2058 composite_opacity_boxes,
2059 composite_opacity_boxes,
2060 &extents->mask_pattern,
2061 need_unbounded_clip (extents));
2063 struct composite_mask data;
2065 data.mask = compositor->pattern_to_surface (extents->surface,
2066 &extents->mask_pattern.base,
2069 &extents->mask_sample_area,
2072 if (unlikely (data.mask->status))
2073 return data.mask->status;
2075 status = clip_and_composite (compositor, extents,
2077 extents->clip->path ? composite_mask_clip : composite_mask_clip_boxes,
2078 &data, need_bounded_clip (extents));
2080 cairo_surface_destroy (data.mask);
2086 static cairo_int_status_t
2087 _cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
2088 cairo_composite_rectangles_t *extents,
2089 const cairo_path_fixed_t *path,
2090 const cairo_stroke_style_t *style,
2091 const cairo_matrix_t *ctm,
2092 const cairo_matrix_t *ctm_inverse,
2094 cairo_antialias_t antialias)
2096 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2097 cairo_int_status_t status;
2099 TRACE ((stderr, "%s\n", __FUNCTION__));
2101 status = compositor->check_composite (extents);
2102 if (unlikely (status))
2105 status = CAIRO_INT_STATUS_UNSUPPORTED;
2106 if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
2107 cairo_boxes_t boxes;
2109 _cairo_boxes_init_with_clip (&boxes, extents->clip);
2110 status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
2115 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2116 status = clip_and_composite_boxes (compositor, extents, &boxes);
2117 _cairo_boxes_fini (&boxes);
2120 if (status == CAIRO_INT_STATUS_UNSUPPORTED && 0 &&
2121 _cairo_clip_is_region (extents->clip)) /* XXX */
2123 composite_tristrip_info_t info;
2125 info.antialias = antialias;
2126 _cairo_tristrip_init_with_clip (&info.strip, extents->clip);
2127 status = _cairo_path_fixed_stroke_to_tristrip (path, style,
2131 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2132 status = clip_and_composite_tristrip (compositor, extents, &info);
2133 _cairo_tristrip_fini (&info.strip);
2136 if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
2137 path->has_curve_to && antialias == CAIRO_ANTIALIAS_NONE) {
2138 cairo_polygon_t polygon;
2140 _cairo_polygon_init_with_clip (&polygon, extents->clip);
2141 status = _cairo_path_fixed_stroke_to_polygon (path, style,
2145 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2146 status = clip_and_composite_polygon (compositor,
2148 CAIRO_ANTIALIAS_NONE,
2149 CAIRO_FILL_RULE_WINDING,
2151 _cairo_polygon_fini (&polygon);
2154 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2155 composite_traps_info_t info;
2157 info.antialias = antialias;
2158 _cairo_traps_init_with_clip (&info.traps, extents->clip);
2159 status = _cairo_path_fixed_stroke_to_traps (path, style,
2163 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2164 status = clip_and_composite_traps (compositor, extents, &info);
2165 _cairo_traps_fini (&info.traps);
2171 static cairo_int_status_t
2172 _cairo_traps_compositor_fill (const cairo_compositor_t *_compositor,
2173 cairo_composite_rectangles_t *extents,
2174 const cairo_path_fixed_t *path,
2175 cairo_fill_rule_t fill_rule,
2177 cairo_antialias_t antialias)
2179 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2180 cairo_int_status_t status;
2182 TRACE ((stderr, "%s\n", __FUNCTION__));
2184 status = compositor->check_composite (extents);
2185 if (unlikely (status))
2188 status = CAIRO_INT_STATUS_UNSUPPORTED;
2189 if (_cairo_path_fixed_fill_is_rectilinear (path)) {
2190 cairo_boxes_t boxes;
2192 _cairo_boxes_init_with_clip (&boxes, extents->clip);
2193 status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
2197 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2198 status = clip_and_composite_boxes (compositor, extents, &boxes);
2199 _cairo_boxes_fini (&boxes);
2202 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2203 cairo_polygon_t polygon;
2206 if (extents->mask.width > extents->unbounded.width ||
2207 extents->mask.height > extents->unbounded.height)
2210 _cairo_box_from_rectangle (&limits, &extents->unbounded);
2211 _cairo_polygon_init (&polygon, &limits, 1);
2215 _cairo_polygon_init (&polygon, NULL, 0);
2218 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
2219 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
2220 status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
2221 extents->clip->boxes,
2222 extents->clip->num_boxes);
2225 _cairo_polygon_init_with_clip (&polygon, extents->clip);
2226 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
2228 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
2229 status = clip_and_composite_polygon (compositor, extents, &polygon,
2230 antialias, fill_rule, path->has_curve_to);
2232 _cairo_polygon_fini (&polygon);
2238 static cairo_int_status_t
2239 composite_glyphs (const cairo_traps_compositor_t *compositor,
2240 cairo_surface_t *dst,
2242 cairo_operator_t op,
2243 cairo_surface_t *src,
2244 int src_x, int src_y,
2245 int dst_x, int dst_y,
2246 const cairo_rectangle_int_t *extents,
2249 cairo_composite_glyphs_info_t *info = closure;
2251 TRACE ((stderr, "%s\n", __FUNCTION__));
2253 if (op == CAIRO_OPERATOR_ADD && (dst->content & CAIRO_CONTENT_COLOR) == 0)
2256 return compositor->composite_glyphs (dst, op, src,
2262 static cairo_int_status_t
2263 _cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
2264 cairo_composite_rectangles_t *extents,
2265 cairo_scaled_font_t *scaled_font,
2266 cairo_glyph_t *glyphs,
2268 cairo_bool_t overlap)
2270 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2271 cairo_int_status_t status;
2273 TRACE ((stderr, "%s\n", __FUNCTION__));
2275 status = compositor->check_composite (extents);
2276 if (unlikely (status))
2279 _cairo_scaled_font_freeze_cache (scaled_font);
2280 status = compositor->check_composite_glyphs (extents,
2281 scaled_font, glyphs,
2283 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
2284 cairo_composite_glyphs_info_t info;
2287 info.font = scaled_font;
2288 info.glyphs = glyphs;
2289 info.num_glyphs = num_glyphs;
2290 info.use_mask = overlap || ! extents->is_bounded;
2291 info.extents = extents->bounded;
2293 if (extents->mask.width > extents->bounded.width ||
2294 extents->mask.height > extents->bounded.height)
2296 flags |= FORCE_CLIP_REGION;
2299 status = clip_and_composite (compositor, extents,
2300 composite_glyphs, NULL, &info,
2301 need_bounded_clip (extents) |
2304 _cairo_scaled_font_thaw_cache (scaled_font);
2310 _cairo_traps_compositor_init (cairo_traps_compositor_t *compositor,
2311 const cairo_compositor_t *delegate)
2313 compositor->base.delegate = delegate;
2315 compositor->base.paint = _cairo_traps_compositor_paint;
2316 compositor->base.mask = _cairo_traps_compositor_mask;
2317 compositor->base.fill = _cairo_traps_compositor_fill;
2318 compositor->base.stroke = _cairo_traps_compositor_stroke;
2319 compositor->base.glyphs = _cairo_traps_compositor_glyphs;