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,
177 const cairo_bool_t draw_color_glyph)
179 cairo_polygon_t polygon;
180 cairo_fill_rule_t fill_rule;
181 cairo_antialias_t antialias;
183 cairo_surface_t *src;
185 cairo_rectangle_int_t fixup;
187 cairo_int_status_t status;
189 TRACE ((stderr, "%s\n", __FUNCTION__));
191 status = _cairo_clip_get_polygon (clip, &polygon,
192 &fill_rule, &antialias);
196 _cairo_traps_init (&traps);
197 status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
200 _cairo_polygon_fini (&polygon);
201 if (unlikely (status))
204 src = compositor->pattern_to_surface (mask, NULL, FALSE,
207 if (unlikely (src->status)) {
208 _cairo_traps_fini (&traps);
212 if (draw_color_glyph)
213 status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, mask,
215 extents->x, extents->y,
219 status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, src,
221 extents->x, extents->y,
225 _cairo_traps_extents (&traps, &box);
226 _cairo_box_round_to_rectangle (&box, &fixup);
227 _cairo_traps_fini (&traps);
228 cairo_surface_destroy (src);
230 if (unlikely (status))
233 if (! _cairo_rectangle_intersect (&fixup, extents))
234 return CAIRO_STATUS_SUCCESS;
236 if (fixup.width < extents->width || fixup.height < extents->height) {
239 _cairo_boxes_init (&clear);
242 if (fixup.y != extents->y) {
243 add_rect_with_offset (&clear,
244 extents->x, extents->y,
245 extents->x + extents->width,
247 extents->x, extents->y);
250 if (fixup.x != extents->x) {
251 add_rect_with_offset (&clear,
254 fixup.y + fixup.height,
255 extents->x, extents->y);
258 if (fixup.x + fixup.width != extents->x + extents->width) {
259 add_rect_with_offset (&clear,
260 fixup.x + fixup.width,
262 extents->x + extents->width,
263 fixup.y + fixup.height,
264 extents->x, extents->y);
267 if (fixup.y + fixup.height != extents->y + extents->height) {
268 add_rect_with_offset (&clear,
270 fixup.y + fixup.height,
271 extents->x + extents->width,
272 extents->y + extents->height,
273 extents->x, extents->y);
276 status = compositor->fill_boxes (mask,
277 CAIRO_OPERATOR_CLEAR,
278 CAIRO_COLOR_TRANSPARENT,
281 _cairo_boxes_fini (&clear);
287 static cairo_status_t
288 __clip_to_surface (const cairo_traps_compositor_t *compositor,
289 const cairo_composite_rectangles_t *composite,
290 const cairo_rectangle_int_t *extents,
291 cairo_surface_t **surface)
293 cairo_surface_t *mask;
294 cairo_polygon_t polygon;
295 cairo_fill_rule_t fill_rule;
296 cairo_antialias_t antialias;
299 cairo_surface_t *src;
301 cairo_int_status_t status;
303 TRACE ((stderr, "%s\n", __FUNCTION__));
305 status = _cairo_clip_get_polygon (composite->clip, &polygon,
306 &fill_rule, &antialias);
310 _cairo_traps_init (&traps);
311 status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
314 _cairo_polygon_fini (&polygon);
315 if (unlikely (status))
318 mask = _cairo_surface_create_similar_scratch (composite->surface,
322 if (unlikely (mask->status)) {
323 _cairo_traps_fini (&traps);
327 src = compositor->pattern_to_surface (mask, NULL, FALSE,
330 if (unlikely (status = src->status))
333 status = compositor->acquire (mask);
334 if (unlikely (status))
337 _cairo_boxes_init_from_rectangle (&clear,
341 status = compositor->fill_boxes (mask,
342 CAIRO_OPERATOR_CLEAR,
343 CAIRO_COLOR_TRANSPARENT,
345 if (unlikely (status))
348 status = compositor->composite_traps (mask, CAIRO_OPERATOR_ADD, src,
350 extents->x, extents->y,
353 if (unlikely (status))
356 compositor->release (mask);
359 cairo_surface_destroy (src);
360 _cairo_traps_fini (&traps);
364 compositor->release (mask);
366 cairo_surface_destroy (mask);
370 static cairo_surface_t *
371 traps_get_clip_surface (const cairo_traps_compositor_t *compositor,
372 const cairo_composite_rectangles_t *composite,
373 const cairo_rectangle_int_t *extents)
375 cairo_surface_t *surface = NULL;
376 cairo_int_status_t status;
378 TRACE ((stderr, "%s\n", __FUNCTION__));
380 status = __clip_to_surface (compositor, composite, extents, &surface);
381 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
382 surface = _cairo_surface_create_similar_solid (composite->surface,
387 if (unlikely (surface->status))
390 status = _cairo_clip_combine_with_surface (composite->clip, surface,
391 extents->x, extents->y);
393 if (unlikely (status)) {
394 cairo_surface_destroy (surface);
395 surface = _cairo_surface_create_in_error (status);
401 static void blt_unaligned_boxes(const cairo_traps_compositor_t *compositor,
402 cairo_surface_t *surface,
410 info.compositor = compositor;
412 _cairo_boxes_init (&info.boxes);
413 info.boxes.num_boxes = 1;
414 for (i = 0; i < num_boxes; i++) {
415 cairo_box_t *b = &boxes[i];
417 if (! _cairo_fixed_is_integer (b->p1.x) ||
418 ! _cairo_fixed_is_integer (b->p1.y) ||
419 ! _cairo_fixed_is_integer (b->p2.x) ||
420 ! _cairo_fixed_is_integer (b->p2.y))
422 do_unaligned_box(blt_in, &info, b, dx, dy);
427 static cairo_surface_t *
428 create_composite_mask (const cairo_traps_compositor_t *compositor,
429 cairo_surface_t *dst,
431 draw_func_t draw_func,
432 draw_func_t mask_func,
433 const cairo_composite_rectangles_t *extents)
435 cairo_surface_t *surface, *src;
436 cairo_int_status_t status;
438 cairo_bool_t draw_color_glyph = FALSE;
440 TRACE ((stderr, "%s\n", __FUNCTION__));
442 surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_ALPHA,
443 extents->bounded.width,
444 extents->bounded.height);
445 if (unlikely (surface->status))
447 /* FIXME: This is more like an ugly hack and wasteful. Reason
448 for this code is that we don't know whether the mask surface
449 should alpha-only or argb32 before we render a glyph.
453 src = compositor->pattern_to_surface (surface,
454 &_cairo_pattern_white.base,
459 if (unlikely (src->status)) {
460 cairo_surface_destroy (surface);
464 status = compositor->acquire (surface);
465 if (unlikely (status)) {
466 cairo_surface_destroy (src);
467 cairo_surface_destroy (surface);
468 return _cairo_surface_create_in_error (status);
471 if (!surface->is_clear) {
474 _cairo_boxes_init_from_rectangle (&clear,
476 extents->bounded.width,
477 extents->bounded.height);
478 status = compositor->fill_boxes (surface,
479 CAIRO_OPERATOR_CLEAR,
480 CAIRO_COLOR_TRANSPARENT,
482 if (unlikely (status))
485 surface->is_clear = TRUE;
489 status = mask_func (compositor, surface, draw_closure,
490 CAIRO_OPERATOR_SOURCE, src, src_x, src_y,
491 extents->bounded.x, extents->bounded.y,
492 &extents->bounded, extents->clip);
493 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
494 surface->is_clear = FALSE;
497 if (unlikely (status != CAIRO_INT_STATUS_UNSUPPORTED))
501 /* Is it worth setting the clip region here? */
502 status = draw_func (compositor, surface, draw_closure,
503 CAIRO_OPERATOR_ADD, src, src_x, src_y,
504 extents->bounded.x, extents->bounded.y,
505 &extents->bounded, NULL);
506 if (unlikely (status)){
507 if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
510 compositor->release (surface);
511 cairo_surface_destroy (surface);
512 cairo_surface_destroy (src);
513 surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_COLOR_ALPHA,
514 extents->bounded.width,
515 extents->bounded.height);
516 if (unlikely (surface->status))
518 /* we are drawing color glyph */
519 draw_color_glyph = TRUE;
524 surface->is_clear = FALSE;
525 if (extents->clip->path != NULL) {
526 status = combine_clip_as_traps (compositor, surface,
527 extents->clip, &extents->bounded,
529 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
530 status = _cairo_clip_combine_with_surface (extents->clip, surface,
534 if (unlikely (status))
536 } else if (extents->clip->boxes) {
537 blt_unaligned_boxes(compositor, surface,
538 extents->bounded.x, extents->bounded.y,
539 extents->clip->boxes, extents->clip->num_boxes);
544 compositor->release (surface);
545 cairo_surface_destroy (src);
549 compositor->release (surface);
550 if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
551 cairo_surface_destroy (surface);
552 surface = _cairo_surface_create_in_error (status);
554 cairo_surface_destroy (src);
558 /* Handles compositing with a clip surface when the operator allows
559 * us to combine the clip with the mask
561 static cairo_status_t
562 clip_and_composite_with_mask (const cairo_traps_compositor_t *compositor,
563 const cairo_composite_rectangles_t*extents,
564 draw_func_t draw_func,
565 draw_func_t mask_func,
568 cairo_surface_t *src,
569 int src_x, int src_y)
571 cairo_surface_t *dst = extents->surface;
572 cairo_surface_t *mask;
574 TRACE ((stderr, "%s\n", __FUNCTION__));
576 mask = create_composite_mask (compositor, dst, draw_closure,
577 draw_func, mask_func,
579 if (unlikely (mask->status))
585 if (mask->content == CAIRO_CONTENT_ALPHA) {
586 /* This is real mask */
587 if (src != NULL || dst->content != CAIRO_CONTENT_ALPHA) {
588 compositor->composite (dst, op, src, mask,
589 extents->bounded.x + src_x,
590 extents->bounded.y + src_y,
592 extents->bounded.x, extents->bounded.y,
593 extents->bounded.width, extents->bounded.height);
595 compositor->composite (dst, op, mask, NULL,
598 extents->bounded.x, extents->bounded.y,
599 extents->bounded.width, extents->bounded.height);
602 compositor->composite (dst, op, mask, NULL,
604 extents->bounded.x + src_x,
605 extents->bounded.y + src_y,
606 extents->bounded.x, extents->bounded.y,
607 extents->bounded.width, extents->bounded.height);
610 cairo_surface_destroy (mask);
611 return CAIRO_STATUS_SUCCESS;
614 /* Handles compositing with a clip surface when we have to do the operation
615 * in two pieces and combine them together.
617 static cairo_status_t
618 clip_and_composite_combine (const cairo_traps_compositor_t *compositor,
619 const cairo_composite_rectangles_t*extents,
620 draw_func_t draw_func,
623 cairo_surface_t *src,
624 int src_x, int src_y)
626 cairo_surface_t *dst = extents->surface;
627 cairo_surface_t *tmp, *clip;
628 cairo_status_t status;
630 TRACE ((stderr, "%s\n", __FUNCTION__));
632 tmp = _cairo_surface_create_similar_scratch (dst, dst->content,
633 extents->bounded.width,
634 extents->bounded.height);
635 if (unlikely (tmp->status)) {
636 status = tmp->status;
637 cairo_surface_destroy (tmp);
641 status = compositor->acquire (tmp);
642 if (unlikely (status)) {
643 cairo_surface_destroy (tmp);
647 compositor->composite (tmp,
648 dst->is_clear ? CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
650 extents->bounded.x, extents->bounded.y,
653 extents->bounded.width, extents->bounded.height);
655 status = draw_func (compositor, tmp, draw_closure, op,
657 extents->bounded.x, extents->bounded.y,
658 &extents->bounded, NULL);
660 if (unlikely (status))
663 clip = traps_get_clip_surface (compositor, extents, &extents->bounded);
664 if (unlikely ((status = clip->status)))
668 compositor->composite (dst, CAIRO_OPERATOR_SOURCE, tmp, clip,
671 extents->bounded.x, extents->bounded.y,
672 extents->bounded.width, extents->bounded.height);
674 compositor->lerp (dst, tmp, clip,
677 extents->bounded.x, extents->bounded.y,
678 extents->bounded.width, extents->bounded.height);
680 cairo_surface_destroy (clip);
683 compositor->release (tmp);
684 cairo_surface_destroy (tmp);
689 /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
690 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
692 static cairo_status_t
693 clip_and_composite_source (const cairo_traps_compositor_t *compositor,
694 cairo_surface_t *dst,
695 draw_func_t draw_func,
696 draw_func_t mask_func,
698 cairo_surface_t *src,
701 const cairo_composite_rectangles_t *extents)
703 cairo_surface_t *mask = NULL;
704 /* create a white color pattern */
705 cairo_pattern_t *white_pattern = _cairo_pattern_create_solid (CAIRO_COLOR_WHITE);
706 cairo_surface_t *white_mask =
707 compositor->pattern_to_surface (dst, white_pattern, TRUE,
709 &extents->source_sample_area,
711 if (unlikely (white_mask->status))
714 TRACE ((stderr, "%s\n", __FUNCTION__));
716 /* Create a surface that is mask IN clip */
717 mask = create_composite_mask (compositor, dst, draw_closure,
718 draw_func, mask_func,
720 if (unlikely (mask->status))
727 compositor->composite (dst, CAIRO_OPERATOR_SOURCE, src, mask,
728 extents->bounded.x + src_x, extents->bounded.y + src_y,
730 extents->bounded.x, extents->bounded.y,
731 extents->bounded.width, extents->bounded.height);
733 if (mask->content == CAIRO_CONTENT_ALPHA)
734 compositor->lerp (dst, src, mask,
735 extents->bounded.x + src_x, extents->bounded.y + src_y,
737 extents->bounded.x, extents->bounded.y,
738 extents->bounded.width, extents->bounded.height);
740 compositor->lerp_color_glyph (dst, mask, white_mask,
742 extents->bounded.x + src_x, extents->bounded.y + src_y,
743 extents->bounded.x, extents->bounded.y,
744 extents->bounded.width, extents->bounded.height);
748 cairo_surface_destroy (mask);
749 cairo_surface_destroy (white_mask);
750 cairo_pattern_destroy (white_pattern);
752 return CAIRO_STATUS_SUCCESS;
756 can_reduce_alpha_op (cairo_operator_t op)
760 case CAIRO_OPERATOR_OVER:
761 case CAIRO_OPERATOR_SOURCE:
762 case CAIRO_OPERATOR_ADD:
770 reduce_alpha_op (cairo_composite_rectangles_t *extents)
772 cairo_surface_t *dst = extents->surface;
773 cairo_operator_t op = extents->op;
774 const cairo_pattern_t *pattern = &extents->source_pattern.base;
775 return dst->is_clear &&
776 dst->content == CAIRO_CONTENT_ALPHA &&
777 _cairo_pattern_is_opaque_solid (pattern) &&
778 can_reduce_alpha_op (op);
781 static cairo_status_t
782 fixup_unbounded_with_mask (const cairo_traps_compositor_t *compositor,
783 const cairo_composite_rectangles_t *extents)
785 cairo_surface_t *dst = extents->surface;
786 cairo_surface_t *mask;
788 TRACE ((stderr, "%s\n", __FUNCTION__));
790 /* XXX can we avoid querying the clip surface again? */
791 mask = traps_get_clip_surface (compositor, extents, &extents->unbounded);
792 if (unlikely (mask->status))
796 if (extents->bounded.y != extents->unbounded.y) {
797 int x = extents->unbounded.x;
798 int y = extents->unbounded.y;
799 int width = extents->unbounded.width;
800 int height = extents->bounded.y - y;
802 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
810 if (extents->bounded.x != extents->unbounded.x) {
811 int x = extents->unbounded.x;
812 int y = extents->bounded.y;
813 int width = extents->bounded.x - x;
814 int height = extents->bounded.height;
816 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
817 0, y - extents->unbounded.y,
824 if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
825 int x = extents->bounded.x + extents->bounded.width;
826 int y = extents->bounded.y;
827 int width = extents->unbounded.x + extents->unbounded.width - x;
828 int height = extents->bounded.height;
830 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
831 x - extents->unbounded.x, y - extents->unbounded.y,
838 if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
839 int x = extents->unbounded.x;
840 int y = extents->bounded.y + extents->bounded.height;
841 int width = extents->unbounded.width;
842 int height = extents->unbounded.y + extents->unbounded.height - y;
844 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL,
845 0, y - extents->unbounded.y,
851 cairo_surface_destroy (mask);
853 return CAIRO_STATUS_SUCCESS;
857 add_rect (cairo_boxes_t *boxes, int x1, int y1, int x2, int y2)
860 cairo_int_status_t status;
862 box.p1.x = _cairo_fixed_from_int (x1);
863 box.p1.y = _cairo_fixed_from_int (y1);
864 box.p2.x = _cairo_fixed_from_int (x2);
865 box.p2.y = _cairo_fixed_from_int (y2);
867 status = _cairo_boxes_add (boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
868 assert (status == CAIRO_INT_STATUS_SUCCESS);
871 static cairo_status_t
872 fixup_unbounded (const cairo_traps_compositor_t *compositor,
873 cairo_composite_rectangles_t *extents,
874 cairo_boxes_t *boxes)
876 cairo_surface_t *dst = extents->surface;
877 cairo_boxes_t clear, tmp;
879 cairo_int_status_t status;
881 TRACE ((stderr, "%s\n", __FUNCTION__));
883 if (extents->bounded.width == extents->unbounded.width &&
884 extents->bounded.height == extents->unbounded.height)
886 return CAIRO_STATUS_SUCCESS;
889 assert (extents->clip->path == NULL);
891 /* subtract the drawn boxes from the unbounded area */
892 _cairo_boxes_init (&clear);
894 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
895 box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
896 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
897 box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
900 if (extents->bounded.width == 0 || extents->bounded.height == 0) {
904 if (extents->bounded.y != extents->unbounded.y) {
906 extents->unbounded.x, extents->unbounded.y,
907 extents->unbounded.x + extents->unbounded.width,
911 if (extents->bounded.x != extents->unbounded.x) {
913 extents->unbounded.x, extents->bounded.y,
915 extents->bounded.y + extents->bounded.height);
918 if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
920 extents->bounded.x + extents->bounded.width,
922 extents->unbounded.x + extents->unbounded.width,
923 extents->bounded.y + extents->bounded.height);
926 if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
928 extents->unbounded.x,
929 extents->bounded.y + extents->bounded.height,
930 extents->unbounded.x + extents->unbounded.width,
931 extents->unbounded.y + extents->unbounded.height);
934 } else if (boxes->num_boxes) {
935 _cairo_boxes_init (&tmp);
937 assert (boxes->is_pixel_aligned);
939 status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
940 assert (status == CAIRO_INT_STATUS_SUCCESS);
942 tmp.chunks.next = &boxes->chunks;
943 tmp.num_boxes += boxes->num_boxes;
945 status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
946 CAIRO_FILL_RULE_WINDING,
948 tmp.chunks.next = NULL;
949 if (unlikely (status))
953 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x);
954 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
956 status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
957 assert (status == CAIRO_INT_STATUS_SUCCESS);
960 /* Now intersect with the clip boxes */
961 if (extents->clip->num_boxes) {
962 _cairo_boxes_init_for_array (&tmp,
963 extents->clip->boxes,
964 extents->clip->num_boxes);
965 status = _cairo_boxes_intersect (&clear, &tmp, &clear);
966 if (unlikely (status))
970 status = compositor->fill_boxes (dst,
971 CAIRO_OPERATOR_CLEAR,
972 CAIRO_COLOR_TRANSPARENT,
976 _cairo_boxes_fini (&clear);
981 NEED_CLIP_REGION = 0x1,
982 NEED_CLIP_SURFACE = 0x2,
983 FORCE_CLIP_REGION = 0x4,
987 need_bounded_clip (cairo_composite_rectangles_t *extents)
989 unsigned int flags = 0;
991 if (extents->unbounded.width < extents->destination.width ||
992 extents->unbounded.height < extents->destination.height)
994 flags |= NEED_CLIP_REGION;
997 if (! _cairo_clip_is_region (extents->clip))
998 flags |= NEED_CLIP_SURFACE;
1004 need_unbounded_clip (cairo_composite_rectangles_t *extents)
1006 unsigned int flags = 0;
1007 if (! extents->is_bounded) {
1008 flags |= NEED_CLIP_REGION;
1009 if (! _cairo_clip_is_region (extents->clip))
1010 flags |= NEED_CLIP_SURFACE;
1012 if (extents->clip->path != NULL)
1013 flags |= NEED_CLIP_SURFACE;
1017 static cairo_status_t
1018 clip_and_composite (const cairo_traps_compositor_t *compositor,
1019 cairo_composite_rectangles_t *extents,
1020 draw_func_t draw_func,
1021 draw_func_t mask_func,
1023 unsigned int need_clip)
1025 cairo_surface_t *dst = extents->surface;
1026 cairo_operator_t op = extents->op;
1027 cairo_pattern_t *source = &extents->source_pattern.base;
1028 cairo_surface_t *src;
1030 cairo_region_t *clip_region = NULL;
1031 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1033 TRACE ((stderr, "%s\n", __FUNCTION__));
1035 if (reduce_alpha_op (extents)) {
1036 op = CAIRO_OPERATOR_ADD;
1040 if (op == CAIRO_OPERATOR_CLEAR) {
1041 op = CAIRO_OPERATOR_DEST_OUT;
1045 compositor->acquire (dst);
1047 if (need_clip & NEED_CLIP_REGION) {
1048 const cairo_rectangle_int_t *limit;
1050 if ((need_clip & FORCE_CLIP_REGION) == 0)
1051 limit = &extents->unbounded;
1053 limit = &extents->destination;
1055 clip_region = _cairo_clip_get_region (extents->clip);
1056 if (clip_region != NULL &&
1057 cairo_region_contains_rectangle (clip_region,
1058 limit) == CAIRO_REGION_OVERLAP_IN)
1061 if (clip_region != NULL) {
1062 status = compositor->set_clip_region (dst, clip_region);
1063 if (unlikely (status)) {
1064 compositor->release (dst);
1070 if (extents->bounded.width == 0 || extents->bounded.height == 0)
1073 src = compositor->pattern_to_surface (dst, source, FALSE,
1075 &extents->source_sample_area,
1077 if (unlikely (status = src->status))
1080 if (op == CAIRO_OPERATOR_SOURCE) {
1081 status = clip_and_composite_source (compositor, dst,
1082 draw_func, mask_func, draw_closure,
1086 if (need_clip & NEED_CLIP_SURFACE) {
1087 if (extents->is_bounded) {
1088 status = clip_and_composite_with_mask (compositor, extents,
1089 draw_func, mask_func,
1091 op, src, src_x, src_y);
1093 status = clip_and_composite_combine (compositor, extents,
1094 draw_func, draw_closure,
1095 op, src, src_x, src_y);
1098 status = draw_func (compositor,
1100 op, src, src_x, src_y,
1106 cairo_surface_destroy (src);
1109 if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
1110 if (need_clip & NEED_CLIP_SURFACE)
1111 status = fixup_unbounded_with_mask (compositor, extents);
1113 status = fixup_unbounded (compositor, extents, NULL);
1118 compositor->set_clip_region (dst, NULL);
1120 compositor->release (dst);
1128 cairo_traps_t traps;
1129 cairo_antialias_t antialias;
1130 } composite_traps_info_t;
1132 static cairo_int_status_t
1133 composite_traps (const cairo_traps_compositor_t *compositor,
1134 cairo_surface_t *dst,
1136 cairo_operator_t op,
1137 cairo_surface_t *src,
1138 int src_x, int src_y,
1139 int dst_x, int dst_y,
1140 const cairo_rectangle_int_t *extents,
1143 composite_traps_info_t *info = closure;
1145 TRACE ((stderr, "%s\n", __FUNCTION__));
1147 return compositor->composite_traps (dst, op, src,
1148 src_x - dst_x, src_y - dst_y,
1151 info->antialias, &info->traps);
1155 cairo_tristrip_t strip;
1156 cairo_antialias_t antialias;
1157 } composite_tristrip_info_t;
1159 static cairo_int_status_t
1160 composite_tristrip (const cairo_traps_compositor_t *compositor,
1161 cairo_surface_t *dst,
1163 cairo_operator_t op,
1164 cairo_surface_t *src,
1165 int src_x, int src_y,
1166 int dst_x, int dst_y,
1167 const cairo_rectangle_int_t *extents,
1170 composite_tristrip_info_t *info = closure;
1172 TRACE ((stderr, "%s\n", __FUNCTION__));
1174 return compositor->composite_tristrip (dst, op, src,
1175 src_x - dst_x, src_y - dst_y,
1178 info->antialias, &info->strip);
1182 is_recording_pattern (const cairo_pattern_t *pattern)
1184 cairo_surface_t *surface;
1186 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
1189 surface = ((const cairo_surface_pattern_t *) pattern)->surface;
1190 surface = _cairo_surface_get_source (surface, NULL);
1191 return _cairo_surface_is_recording (surface);
1194 static cairo_surface_t *
1195 recording_pattern_get_surface (const cairo_pattern_t *pattern)
1197 cairo_surface_t *surface;
1199 surface = ((const cairo_surface_pattern_t *) pattern)->surface;
1200 return _cairo_surface_get_source (surface, NULL);
1204 recording_pattern_contains_sample (const cairo_pattern_t *pattern,
1205 const cairo_rectangle_int_t *sample)
1207 cairo_recording_surface_t *surface;
1209 if (! is_recording_pattern (pattern))
1212 if (pattern->extend == CAIRO_EXTEND_NONE)
1215 surface = (cairo_recording_surface_t *) recording_pattern_get_surface (pattern);
1216 if (surface->unbounded)
1219 return _cairo_rectangle_contains_rectangle (&surface->extents, sample);
1223 op_reduces_to_source (cairo_composite_rectangles_t *extents)
1225 if (extents->op == CAIRO_OPERATOR_SOURCE)
1228 if (extents->surface->is_clear)
1229 return extents->op == CAIRO_OPERATOR_OVER || extents->op == CAIRO_OPERATOR_ADD;
1234 static cairo_status_t
1235 composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
1236 cairo_composite_rectangles_t *extents,
1237 cairo_boxes_t *boxes)
1239 cairo_surface_t *dst = extents->surface;
1240 cairo_operator_t op = extents->op;
1241 cairo_bool_t need_clip_mask = ! _cairo_clip_is_region (extents->clip);
1242 cairo_bool_t op_is_source;
1243 cairo_status_t status;
1245 TRACE ((stderr, "%s\n", __FUNCTION__));
1247 if (need_clip_mask &&
1248 (! extents->is_bounded || extents->op == CAIRO_OPERATOR_SOURCE))
1250 return CAIRO_INT_STATUS_UNSUPPORTED;
1253 op_is_source = op_reduces_to_source (extents);
1255 /* Are we just copying a recording surface? */
1256 if (! need_clip_mask && op_is_source &&
1257 recording_pattern_contains_sample (&extents->source_pattern.base,
1258 &extents->source_sample_area))
1260 cairo_clip_t *recording_clip;
1261 cairo_pattern_t *source = &extents->source_pattern.base;
1263 /* XXX could also do tiling repeat modes... */
1265 /* first clear the area about to be overwritten */
1266 if (! dst->is_clear) {
1267 status = compositor->acquire (dst);
1268 if (unlikely (status))
1271 status = compositor->fill_boxes (dst,
1272 CAIRO_OPERATOR_CLEAR,
1273 CAIRO_COLOR_TRANSPARENT,
1275 compositor->release (dst);
1276 if (unlikely (status))
1280 recording_clip = _cairo_clip_from_boxes (boxes);
1281 status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (source),
1283 dst, recording_clip);
1284 _cairo_clip_destroy (recording_clip);
1289 status = compositor->acquire (dst);
1290 if (unlikely (status))
1293 if (! need_clip_mask &&
1294 (op == CAIRO_OPERATOR_CLEAR ||
1295 extents->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID))
1297 const cairo_color_t *color;
1299 if (op == CAIRO_OPERATOR_CLEAR) {
1300 color = CAIRO_COLOR_TRANSPARENT;
1302 color = &((cairo_solid_pattern_t *) &extents->source_pattern)->color;
1304 op = CAIRO_OPERATOR_SOURCE;
1307 status = compositor->fill_boxes (dst, op, color, boxes);
1311 cairo_surface_t *src, *mask = NULL;
1312 cairo_pattern_t *source = &extents->source_pattern.base;
1314 int mask_x = 0, mask_y = 0;
1316 if (need_clip_mask) {
1317 mask = traps_get_clip_surface (compositor,
1318 extents, &extents->bounded);
1319 if (unlikely (mask->status))
1320 return mask->status;
1322 mask_x = -extents->bounded.x;
1323 mask_y = -extents->bounded.y;
1325 if (op == CAIRO_OPERATOR_CLEAR) {
1327 op = CAIRO_OPERATOR_DEST_OUT;
1329 } else if (op_is_source)
1330 op = CAIRO_OPERATOR_SOURCE;
1332 src = compositor->pattern_to_surface (dst, source, FALSE,
1334 &extents->source_sample_area,
1336 if (likely (src->status == CAIRO_STATUS_SUCCESS)) {
1337 status = compositor->composite_boxes (dst, op, src, mask,
1341 boxes, &extents->bounded);
1342 cairo_surface_destroy (src);
1344 status = src->status;
1346 cairo_surface_destroy (mask);
1349 if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded)
1350 status = fixup_unbounded (compositor, extents, boxes);
1352 compositor->release (dst);
1357 static cairo_status_t
1358 upload_boxes (const cairo_traps_compositor_t *compositor,
1359 cairo_composite_rectangles_t *extents,
1360 cairo_boxes_t *boxes)
1362 cairo_surface_t *dst = extents->surface;
1363 const cairo_pattern_t *source = &extents->source_pattern.base;
1364 cairo_surface_t *src;
1365 cairo_rectangle_int_t limit;
1366 cairo_int_status_t status;
1369 TRACE ((stderr, "%s\n", __FUNCTION__));
1371 src = _cairo_pattern_get_source((cairo_surface_pattern_t *)source,
1373 if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
1374 return CAIRO_INT_STATUS_UNSUPPORTED;
1376 if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
1377 return CAIRO_INT_STATUS_UNSUPPORTED;
1379 /* Check that the data is entirely within the image */
1380 if (extents->bounded.x + tx < limit.x || extents->bounded.y + ty < limit.y)
1381 return CAIRO_INT_STATUS_UNSUPPORTED;
1383 if (extents->bounded.x + extents->bounded.width + tx > limit.x + limit.width ||
1384 extents->bounded.y + extents->bounded.height + ty > limit.y + limit.height)
1385 return CAIRO_INT_STATUS_UNSUPPORTED;
1390 if (src->type == CAIRO_SURFACE_TYPE_IMAGE)
1391 status = compositor->draw_image_boxes (dst,
1392 (cairo_image_surface_t *)src,
1395 status = compositor->copy_boxes (dst, src, boxes, &extents->bounded,
1401 static cairo_int_status_t
1402 trim_extents_to_traps (cairo_composite_rectangles_t *extents,
1403 cairo_traps_t *traps)
1407 _cairo_traps_extents (traps, &box);
1408 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1411 static cairo_int_status_t
1412 trim_extents_to_tristrip (cairo_composite_rectangles_t *extents,
1413 cairo_tristrip_t *strip)
1417 _cairo_tristrip_extents (strip, &box);
1418 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1421 static cairo_int_status_t
1422 trim_extents_to_boxes (cairo_composite_rectangles_t *extents,
1423 cairo_boxes_t *boxes)
1427 _cairo_boxes_extents (boxes, &box);
1428 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1431 static cairo_int_status_t
1432 boxes_for_traps (cairo_boxes_t *boxes,
1433 cairo_traps_t *traps,
1434 cairo_antialias_t antialias)
1438 /* first check that the traps are rectilinear */
1439 if (antialias == CAIRO_ANTIALIAS_NONE) {
1440 for (i = 0; i < traps->num_traps; i++) {
1441 const cairo_trapezoid_t *t = &traps->traps[i];
1442 if (_cairo_fixed_integer_round_down (t->left.p1.x) !=
1443 _cairo_fixed_integer_round_down (t->left.p2.x) ||
1444 _cairo_fixed_integer_round_down (t->right.p1.x) !=
1445 _cairo_fixed_integer_round_down (t->right.p2.x))
1447 return CAIRO_INT_STATUS_UNSUPPORTED;
1451 for (i = 0; i < traps->num_traps; i++) {
1452 const cairo_trapezoid_t *t = &traps->traps[i];
1453 if (t->left.p1.x != t->left.p2.x || t->right.p1.x != t->right.p2.x)
1454 return CAIRO_INT_STATUS_UNSUPPORTED;
1458 _cairo_boxes_init (boxes);
1460 boxes->num_boxes = traps->num_traps;
1461 boxes->chunks.base = (cairo_box_t *) traps->traps;
1462 boxes->chunks.count = traps->num_traps;
1463 boxes->chunks.size = traps->num_traps;
1465 if (antialias != CAIRO_ANTIALIAS_NONE) {
1466 for (i = 0; i < traps->num_traps; i++) {
1467 /* Note the traps and boxes alias so we need to take the local copies first. */
1468 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
1469 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
1470 cairo_fixed_t y1 = traps->traps[i].top;
1471 cairo_fixed_t y2 = traps->traps[i].bottom;
1473 boxes->chunks.base[i].p1.x = x1;
1474 boxes->chunks.base[i].p1.y = y1;
1475 boxes->chunks.base[i].p2.x = x2;
1476 boxes->chunks.base[i].p2.y = y2;
1478 if (boxes->is_pixel_aligned) {
1479 boxes->is_pixel_aligned =
1480 _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
1481 _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
1485 boxes->is_pixel_aligned = TRUE;
1487 for (i = 0; i < traps->num_traps; i++) {
1488 /* Note the traps and boxes alias so we need to take the local copies first. */
1489 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
1490 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
1491 cairo_fixed_t y1 = traps->traps[i].top;
1492 cairo_fixed_t y2 = traps->traps[i].bottom;
1494 /* round down here to match Pixman's behavior when using traps. */
1495 boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
1496 boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
1497 boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
1498 boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
1502 return CAIRO_INT_STATUS_SUCCESS;
1505 static cairo_status_t
1506 clip_and_composite_boxes (const cairo_traps_compositor_t *compositor,
1507 cairo_composite_rectangles_t *extents,
1508 cairo_boxes_t *boxes);
1510 static cairo_status_t
1511 clip_and_composite_polygon (const cairo_traps_compositor_t *compositor,
1512 cairo_composite_rectangles_t *extents,
1513 cairo_polygon_t *polygon,
1514 cairo_antialias_t antialias,
1515 cairo_fill_rule_t fill_rule,
1518 composite_traps_info_t traps;
1519 cairo_surface_t *dst = extents->surface;
1520 cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
1521 cairo_int_status_t status;
1523 TRACE ((stderr, "%s\n", __FUNCTION__));
1525 if (polygon->num_edges == 0) {
1526 status = CAIRO_INT_STATUS_SUCCESS;
1528 if (! extents->is_bounded) {
1529 cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
1532 cairo_region_contains_rectangle (clip_region,
1533 &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
1536 if (clip_region != NULL) {
1537 status = compositor->set_clip_region (dst, clip_region);
1538 if (unlikely (status))
1543 status = fixup_unbounded_with_mask (compositor, extents);
1545 status = fixup_unbounded (compositor, extents, NULL);
1547 if (clip_region != NULL)
1548 compositor->set_clip_region (dst, NULL);
1554 if (extents->clip->path != NULL && extents->is_bounded) {
1555 cairo_polygon_t clipper;
1556 cairo_fill_rule_t clipper_fill_rule;
1557 cairo_antialias_t clipper_antialias;
1559 status = _cairo_clip_get_polygon (extents->clip,
1562 &clipper_antialias);
1563 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1564 if (clipper_antialias == antialias) {
1565 status = _cairo_polygon_intersect (polygon, fill_rule,
1566 &clipper, clipper_fill_rule);
1567 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1568 cairo_clip_t * clip = _cairo_clip_copy_region (extents->clip);
1569 _cairo_clip_destroy (extents->clip);
1570 extents->clip = clip;
1572 fill_rule = CAIRO_FILL_RULE_WINDING;
1574 _cairo_polygon_fini (&clipper);
1579 if (antialias == CAIRO_ANTIALIAS_NONE && curvy) {
1580 cairo_boxes_t boxes;
1582 _cairo_boxes_init (&boxes);
1583 status = _cairo_rasterise_polygon_to_boxes (polygon, fill_rule, &boxes);
1584 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1585 assert (boxes.is_pixel_aligned);
1586 status = clip_and_composite_boxes (compositor, extents, &boxes);
1588 _cairo_boxes_fini (&boxes);
1589 if ((status != CAIRO_INT_STATUS_UNSUPPORTED))
1593 _cairo_traps_init (&traps.traps);
1595 if (antialias == CAIRO_ANTIALIAS_NONE && curvy) {
1596 status = _cairo_rasterise_polygon_to_traps (polygon, fill_rule, antialias, &traps.traps);
1598 status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
1600 if (unlikely (status))
1603 status = trim_extents_to_traps (extents, &traps.traps);
1604 if (unlikely (status))
1607 /* Use a fast path if the trapezoids consist of a set of boxes. */
1608 status = CAIRO_INT_STATUS_UNSUPPORTED;
1610 cairo_boxes_t boxes;
1612 status = boxes_for_traps (&boxes, &traps.traps, antialias);
1613 if (status == CAIRO_INT_STATUS_SUCCESS) {
1614 status = clip_and_composite_boxes (compositor, extents, &boxes);
1615 /* XXX need to reconstruct the traps! */
1616 assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
1619 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1620 /* Otherwise render the trapezoids to a mask and composite in the usual
1623 unsigned int flags = 0;
1625 /* For unbounded operations, the X11 server will estimate the
1626 * affected rectangle and apply the operation to that. However,
1627 * there are cases where this is an overestimate (e.g. the
1628 * clip-fill-{eo,nz}-unbounded test).
1630 * The clip will trim that overestimate to our expectations.
1632 if (! extents->is_bounded)
1633 flags |= FORCE_CLIP_REGION;
1635 traps.antialias = antialias;
1636 status = clip_and_composite (compositor, extents,
1637 composite_traps, NULL, &traps,
1638 need_unbounded_clip (extents) | flags);
1642 _cairo_traps_fini (&traps.traps);
1647 struct composite_opacity_info {
1648 const cairo_traps_compositor_t *compositor;
1650 cairo_surface_t *dst;
1651 cairo_surface_t *src;
1656 static void composite_opacity(void *closure,
1657 int16_t x, int16_t y,
1658 int16_t w, int16_t h,
1661 struct composite_opacity_info *info = closure;
1662 const cairo_traps_compositor_t *compositor = info->compositor;
1663 cairo_surface_t *mask;
1665 cairo_color_t color;
1666 cairo_solid_pattern_t solid;
1668 _cairo_color_init_rgba (&color, 0, 0, 0, info->opacity * coverage);
1669 _cairo_pattern_init_solid (&solid, &color);
1670 mask = compositor->pattern_to_surface (info->dst, &solid.base, TRUE,
1671 &_cairo_unbounded_rectangle,
1672 &_cairo_unbounded_rectangle,
1674 if (likely (mask->status == CAIRO_STATUS_SUCCESS)) {
1676 compositor->composite (info->dst, info->op, info->src, mask,
1677 x + info->src_x, y + info->src_y,
1682 compositor->composite (info->dst, info->op, mask, NULL,
1690 cairo_surface_destroy (mask);
1694 static cairo_int_status_t
1695 composite_opacity_boxes (const cairo_traps_compositor_t *compositor,
1696 cairo_surface_t *dst,
1698 cairo_operator_t op,
1699 cairo_surface_t *src,
1704 const cairo_rectangle_int_t *extents,
1707 const cairo_solid_pattern_t *mask = closure;
1708 struct composite_opacity_info info;
1711 TRACE ((stderr, "%s\n", __FUNCTION__));
1713 info.compositor = compositor;
1721 info.opacity = mask->color.alpha / (double) 0xffff;
1723 /* XXX for lots of boxes create a clip region for the fully opaque areas */
1724 for (i = 0; i < clip->num_boxes; i++)
1725 do_unaligned_box(composite_opacity, &info,
1726 &clip->boxes[i], dst_x, dst_y);
1728 return CAIRO_STATUS_SUCCESS;
1731 static cairo_int_status_t
1732 composite_boxes (const cairo_traps_compositor_t *compositor,
1733 cairo_surface_t *dst,
1735 cairo_operator_t op,
1736 cairo_surface_t *src,
1741 const cairo_rectangle_int_t *extents,
1744 cairo_traps_t traps;
1745 cairo_status_t status;
1747 TRACE ((stderr, "%s\n", __FUNCTION__));
1749 status = _cairo_traps_init_boxes (&traps, closure);
1750 if (unlikely (status))
1753 status = compositor->composite_traps (dst, op, src,
1754 src_x - dst_x, src_y - dst_y,
1757 CAIRO_ANTIALIAS_DEFAULT, &traps);
1758 _cairo_traps_fini (&traps);
1763 static cairo_status_t
1764 clip_and_composite_boxes (const cairo_traps_compositor_t *compositor,
1765 cairo_composite_rectangles_t *extents,
1766 cairo_boxes_t *boxes)
1768 cairo_int_status_t status;
1770 TRACE ((stderr, "%s\n", __FUNCTION__));
1772 if (boxes->num_boxes == 0 && extents->is_bounded)
1773 return CAIRO_STATUS_SUCCESS;
1775 status = trim_extents_to_boxes (extents, boxes);
1776 if (unlikely (status))
1779 if (boxes->is_pixel_aligned && extents->clip->path == NULL &&
1780 extents->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
1781 (op_reduces_to_source (extents) ||
1782 (extents->op == CAIRO_OPERATOR_OVER &&
1783 (extents->source_pattern.surface.surface->content & CAIRO_CONTENT_ALPHA) == 0)))
1785 status = upload_boxes (compositor, extents, boxes);
1786 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1790 /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
1791 if (extents->clip->path != NULL && extents->is_bounded) {
1792 cairo_polygon_t polygon;
1793 cairo_fill_rule_t fill_rule;
1794 cairo_antialias_t antialias;
1797 clip = _cairo_clip_copy (extents->clip);
1798 clip = _cairo_clip_intersect_boxes (clip, boxes);
1799 if (_cairo_clip_is_all_clipped (clip))
1800 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1802 status = _cairo_clip_get_polygon (clip, &polygon,
1803 &fill_rule, &antialias);
1804 _cairo_clip_path_destroy (clip->path);
1806 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1807 cairo_clip_t *saved_clip = extents->clip;
1808 extents->clip = clip;
1810 status = clip_and_composite_polygon (compositor, extents, &polygon,
1811 antialias, fill_rule, FALSE);
1813 clip = extents->clip;
1814 extents->clip = saved_clip;
1816 _cairo_polygon_fini (&polygon);
1818 _cairo_clip_destroy (clip);
1820 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1824 /* Use a fast path if the boxes are pixel aligned (or nearly aligned!) */
1825 if (boxes->is_pixel_aligned) {
1826 status = composite_aligned_boxes (compositor, extents, boxes);
1827 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1831 return clip_and_composite (compositor, extents,
1832 composite_boxes, NULL, boxes,
1833 need_unbounded_clip (extents));
1836 static cairo_int_status_t
1837 composite_traps_as_boxes (const cairo_traps_compositor_t *compositor,
1838 cairo_composite_rectangles_t *extents,
1839 composite_traps_info_t *info)
1841 cairo_boxes_t boxes;
1843 TRACE ((stderr, "%s\n", __FUNCTION__));
1845 if (! _cairo_traps_to_boxes (&info->traps, info->antialias, &boxes))
1846 return CAIRO_INT_STATUS_UNSUPPORTED;
1848 return clip_and_composite_boxes (compositor, extents, &boxes);
1851 static cairo_int_status_t
1852 clip_and_composite_traps (const cairo_traps_compositor_t *compositor,
1853 cairo_composite_rectangles_t *extents,
1854 composite_traps_info_t *info,
1857 cairo_int_status_t status;
1859 TRACE ((stderr, "%s\n", __FUNCTION__));
1861 status = trim_extents_to_traps (extents, &info->traps);
1862 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1865 status = CAIRO_INT_STATUS_UNSUPPORTED;
1866 if ((flags & FORCE_CLIP_REGION) == 0)
1867 status = composite_traps_as_boxes (compositor, extents, info);
1868 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1869 /* For unbounded operations, the X11 server will estimate the
1870 * affected rectangle and apply the operation to that. However,
1871 * there are cases where this is an overestimate (e.g. the
1872 * clip-fill-{eo,nz}-unbounded test).
1874 * The clip will trim that overestimate to our expectations.
1876 if (! extents->is_bounded)
1877 flags |= FORCE_CLIP_REGION;
1879 status = clip_and_composite (compositor, extents,
1880 composite_traps, NULL, info,
1881 need_unbounded_clip (extents) | flags);
1887 static cairo_int_status_t
1888 clip_and_composite_tristrip (const cairo_traps_compositor_t *compositor,
1889 cairo_composite_rectangles_t *extents,
1890 composite_tristrip_info_t *info)
1892 cairo_int_status_t status;
1893 unsigned int flags = 0;
1895 TRACE ((stderr, "%s\n", __FUNCTION__));
1897 status = trim_extents_to_tristrip (extents, &info->strip);
1898 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1901 if (! extents->is_bounded)
1902 flags |= FORCE_CLIP_REGION;
1904 status = clip_and_composite (compositor, extents,
1905 composite_tristrip, NULL, info,
1906 need_unbounded_clip (extents) | flags);
1911 struct composite_mask {
1912 cairo_surface_t *mask;
1916 static cairo_int_status_t
1917 composite_mask (const cairo_traps_compositor_t *compositor,
1918 cairo_surface_t *dst,
1920 cairo_operator_t op,
1921 cairo_surface_t *src,
1926 const cairo_rectangle_int_t *extents,
1929 struct composite_mask *data = closure;
1931 TRACE ((stderr, "%s\n", __FUNCTION__));
1934 compositor->composite (dst, op, src, data->mask,
1935 extents->x + src_x, extents->y + src_y,
1936 extents->x + data->mask_x, extents->y + data->mask_y,
1937 extents->x - dst_x, extents->y - dst_y,
1938 extents->width, extents->height);
1940 compositor->composite (dst, op, data->mask, NULL,
1941 extents->x + data->mask_x, extents->y + data->mask_y,
1943 extents->x - dst_x, extents->y - dst_y,
1944 extents->width, extents->height);
1947 return CAIRO_STATUS_SUCCESS;
1950 struct composite_box_info {
1951 const cairo_traps_compositor_t *compositor;
1952 cairo_surface_t *dst;
1953 cairo_surface_t *src;
1958 static void composite_box(void *closure,
1959 int16_t x, int16_t y,
1960 int16_t w, int16_t h,
1963 struct composite_box_info *info = closure;
1964 const cairo_traps_compositor_t *compositor = info->compositor;
1966 TRACE ((stderr, "%s\n", __FUNCTION__));
1968 if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (coverage)) {
1969 cairo_surface_t *mask;
1970 cairo_color_t color;
1971 cairo_solid_pattern_t solid;
1974 _cairo_color_init_rgba (&color, 0, 0, 0, coverage / (double)0xffff);
1975 _cairo_pattern_init_solid (&solid, &color);
1977 mask = compositor->pattern_to_surface (info->dst, &solid.base, FALSE,
1978 &_cairo_unbounded_rectangle,
1979 &_cairo_unbounded_rectangle,
1982 if (likely (mask->status == CAIRO_STATUS_SUCCESS)) {
1983 compositor->composite (info->dst, info->op, info->src, mask,
1984 x + info->src_x, y + info->src_y,
1990 cairo_surface_destroy (mask);
1992 compositor->composite (info->dst, info->op, info->src, NULL,
1993 x + info->src_x, y + info->src_y,
2000 static cairo_int_status_t
2001 composite_mask_clip_boxes (const cairo_traps_compositor_t *compositor,
2002 cairo_surface_t *dst,
2004 cairo_operator_t op,
2005 cairo_surface_t *src,
2010 const cairo_rectangle_int_t *extents,
2013 struct composite_mask *data = closure;
2014 struct composite_box_info info;
2017 TRACE ((stderr, "%s\n", __FUNCTION__));
2019 info.compositor = compositor;
2020 info.op = CAIRO_OPERATOR_SOURCE;
2022 info.src = data->mask;
2023 info.src_x = data->mask_x;
2024 info.src_y = data->mask_y;
2026 info.src_x += dst_x;
2027 info.src_y += dst_y;
2029 for (i = 0; i < clip->num_boxes; i++)
2030 do_unaligned_box(composite_box, &info, &clip->boxes[i], dst_x, dst_y);
2032 return CAIRO_STATUS_SUCCESS;
2035 static cairo_int_status_t
2036 composite_mask_clip (const cairo_traps_compositor_t *compositor,
2037 cairo_surface_t *dst,
2039 cairo_operator_t op,
2040 cairo_surface_t *src,
2045 const cairo_rectangle_int_t *extents,
2048 struct composite_mask *data = closure;
2049 cairo_polygon_t polygon;
2050 cairo_fill_rule_t fill_rule;
2051 composite_traps_info_t info;
2052 cairo_status_t status;
2054 TRACE ((stderr, "%s\n", __FUNCTION__));
2056 status = _cairo_clip_get_polygon (clip, &polygon,
2057 &fill_rule, &info.antialias);
2058 if (unlikely (status))
2061 _cairo_traps_init (&info.traps);
2062 status = _cairo_bentley_ottmann_tessellate_polygon (&info.traps,
2065 _cairo_polygon_fini (&polygon);
2066 if (unlikely (status))
2069 status = composite_traps (compositor, dst, &info,
2070 CAIRO_OPERATOR_SOURCE,
2072 data->mask_x + dst_x, data->mask_y + dst_y,
2075 _cairo_traps_fini (&info.traps);
2080 /* high-level compositor interface */
2082 static cairo_int_status_t
2083 _cairo_traps_compositor_paint (const cairo_compositor_t *_compositor,
2084 cairo_composite_rectangles_t *extents)
2086 cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
2087 cairo_boxes_t boxes;
2088 cairo_int_status_t status;
2090 TRACE ((stderr, "%s\n", __FUNCTION__));
2092 status = compositor->check_composite (extents);
2093 if (unlikely (status))
2096 _cairo_clip_steal_boxes (extents->clip, &boxes);
2097 status = clip_and_composite_boxes (compositor, extents, &boxes);
2098 _cairo_clip_unsteal_boxes (extents->clip, &boxes);
2103 static cairo_int_status_t
2104 _cairo_traps_compositor_mask (const cairo_compositor_t *_compositor,
2105 cairo_composite_rectangles_t *extents)
2107 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
2108 cairo_int_status_t status;
2110 TRACE ((stderr, "%s\n", __FUNCTION__));
2112 status = compositor->check_composite (extents);
2113 if (unlikely (status))
2116 if (extents->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
2117 extents->clip->path == NULL) {
2118 status = clip_and_composite (compositor, extents,
2119 composite_opacity_boxes,
2120 composite_opacity_boxes,
2121 &extents->mask_pattern,
2122 need_unbounded_clip (extents));
2124 struct composite_mask data;
2126 data.mask = compositor->pattern_to_surface (extents->surface,
2127 &extents->mask_pattern.base,
2130 &extents->mask_sample_area,
2133 if (unlikely (data.mask->status))
2134 return data.mask->status;
2136 status = clip_and_composite (compositor, extents,
2138 extents->clip->path ? composite_mask_clip : composite_mask_clip_boxes,
2139 &data, need_bounded_clip (extents));
2141 cairo_surface_destroy (data.mask);
2147 static cairo_int_status_t
2148 _cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
2149 cairo_composite_rectangles_t *extents,
2150 const cairo_path_fixed_t *path,
2151 const cairo_stroke_style_t *style,
2152 const cairo_matrix_t *ctm,
2153 const cairo_matrix_t *ctm_inverse,
2155 cairo_antialias_t antialias)
2157 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2158 cairo_int_status_t status;
2160 TRACE ((stderr, "%s\n", __FUNCTION__));
2162 status = compositor->check_composite (extents);
2163 if (unlikely (status))
2166 status = CAIRO_INT_STATUS_UNSUPPORTED;
2167 if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
2168 cairo_boxes_t boxes;
2170 _cairo_boxes_init_with_clip (&boxes, extents->clip);
2171 status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
2176 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2177 status = clip_and_composite_boxes (compositor, extents, &boxes);
2178 _cairo_boxes_fini (&boxes);
2181 if (status == CAIRO_INT_STATUS_UNSUPPORTED && 0 &&
2182 _cairo_clip_is_region (extents->clip)) /* XXX */
2184 composite_tristrip_info_t info;
2186 info.antialias = antialias;
2187 _cairo_tristrip_init_with_clip (&info.strip, extents->clip);
2188 status = _cairo_path_fixed_stroke_to_tristrip (path, style,
2192 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2193 status = clip_and_composite_tristrip (compositor, extents, &info);
2194 _cairo_tristrip_fini (&info.strip);
2197 if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
2198 path->has_curve_to && antialias == CAIRO_ANTIALIAS_NONE) {
2199 cairo_polygon_t polygon;
2201 _cairo_polygon_init_with_clip (&polygon, extents->clip);
2202 status = _cairo_path_fixed_stroke_to_polygon (path, style,
2206 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2207 status = clip_and_composite_polygon (compositor,
2209 CAIRO_ANTIALIAS_NONE,
2210 CAIRO_FILL_RULE_WINDING,
2212 _cairo_polygon_fini (&polygon);
2215 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2216 cairo_int_status_t (*func) (const cairo_path_fixed_t *path,
2217 const cairo_stroke_style_t *stroke_style,
2218 const cairo_matrix_t *ctm,
2219 const cairo_matrix_t *ctm_inverse,
2221 cairo_traps_t *traps);
2222 composite_traps_info_t info;
2225 if (antialias == CAIRO_ANTIALIAS_BEST || antialias == CAIRO_ANTIALIAS_GOOD) {
2226 func = _cairo_path_fixed_stroke_polygon_to_traps;
2228 func = _cairo_path_fixed_stroke_to_traps;
2229 if (extents->clip->num_boxes > 1 ||
2230 extents->mask.width > extents->unbounded.width ||
2231 extents->mask.height > extents->unbounded.height)
2233 flags = NEED_CLIP_REGION | FORCE_CLIP_REGION;
2237 info.antialias = antialias;
2238 _cairo_traps_init_with_clip (&info.traps, extents->clip);
2239 status = func (path, style, ctm, ctm_inverse, tolerance, &info.traps);
2240 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2241 status = clip_and_composite_traps (compositor, extents, &info, flags);
2242 _cairo_traps_fini (&info.traps);
2248 static cairo_int_status_t
2249 _cairo_traps_compositor_fill (const cairo_compositor_t *_compositor,
2250 cairo_composite_rectangles_t *extents,
2251 const cairo_path_fixed_t *path,
2252 cairo_fill_rule_t fill_rule,
2254 cairo_antialias_t antialias)
2256 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2257 cairo_int_status_t status;
2259 TRACE ((stderr, "%s\n", __FUNCTION__));
2261 status = compositor->check_composite (extents);
2262 if (unlikely (status))
2265 status = CAIRO_INT_STATUS_UNSUPPORTED;
2266 if (_cairo_path_fixed_fill_is_rectilinear (path)) {
2267 cairo_boxes_t boxes;
2269 _cairo_boxes_init_with_clip (&boxes, extents->clip);
2270 status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
2274 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
2275 status = clip_and_composite_boxes (compositor, extents, &boxes);
2276 _cairo_boxes_fini (&boxes);
2279 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2280 cairo_polygon_t polygon;
2283 if (extents->mask.width > extents->unbounded.width ||
2284 extents->mask.height > extents->unbounded.height)
2287 _cairo_box_from_rectangle (&limits, &extents->unbounded);
2288 _cairo_polygon_init (&polygon, &limits, 1);
2292 _cairo_polygon_init (&polygon, NULL, 0);
2295 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
2296 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
2297 status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
2298 extents->clip->boxes,
2299 extents->clip->num_boxes);
2302 _cairo_polygon_init_with_clip (&polygon, extents->clip);
2303 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
2305 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
2306 status = clip_and_composite_polygon (compositor, extents, &polygon,
2307 antialias, fill_rule, path->has_curve_to);
2309 _cairo_polygon_fini (&polygon);
2315 static cairo_int_status_t
2316 composite_glyphs (const cairo_traps_compositor_t *compositor,
2317 cairo_surface_t *dst,
2319 cairo_operator_t op,
2320 cairo_surface_t *src,
2321 int src_x, int src_y,
2322 int dst_x, int dst_y,
2323 const cairo_rectangle_int_t *extents,
2326 cairo_composite_glyphs_info_t *info = closure;
2328 TRACE ((stderr, "%s\n", __FUNCTION__));
2330 if (op == CAIRO_OPERATOR_ADD && (dst->content & CAIRO_CONTENT_COLOR) == 0)
2333 return compositor->composite_glyphs (dst, op, src,
2339 static cairo_int_status_t
2340 _cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
2341 cairo_composite_rectangles_t *extents,
2342 cairo_scaled_font_t *scaled_font,
2343 cairo_glyph_t *glyphs,
2345 cairo_bool_t overlap)
2347 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2348 cairo_int_status_t status;
2350 TRACE ((stderr, "%s\n", __FUNCTION__));
2352 status = compositor->check_composite (extents);
2353 if (unlikely (status))
2356 #if ! CAIRO_HAS_TG_SURFACE
2357 _cairo_scaled_font_freeze_cache (scaled_font);
2360 status = compositor->check_composite_glyphs (extents,
2361 scaled_font, glyphs,
2363 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
2364 cairo_composite_glyphs_info_t info;
2367 info.font = scaled_font;
2368 info.glyphs = glyphs;
2369 info.num_glyphs = num_glyphs;
2370 info.use_mask = overlap || ! extents->is_bounded;
2371 info.extents = extents->bounded;
2373 if (extents->mask.width > extents->bounded.width ||
2374 extents->mask.height > extents->bounded.height)
2376 flags |= FORCE_CLIP_REGION;
2379 status = clip_and_composite (compositor, extents,
2380 composite_glyphs, NULL, &info,
2381 need_bounded_clip (extents) |
2385 #if ! CAIRO_HAS_TG_SURFACE
2386 _cairo_scaled_font_thaw_cache (scaled_font);
2393 _cairo_traps_compositor_init (cairo_traps_compositor_t *compositor,
2394 const cairo_compositor_t *delegate)
2396 compositor->base.delegate = delegate;
2398 compositor->base.paint = _cairo_traps_compositor_paint;
2399 compositor->base.mask = _cairo_traps_compositor_mask;
2400 compositor->base.fill = _cairo_traps_compositor_fill;
2401 compositor->base.stroke = _cairo_traps_compositor_stroke;
2402 compositor->base.glyphs = _cairo_traps_compositor_glyphs;