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-compositor-private.h"
45 #include "cairo-clip-inline.h"
46 #include "cairo-clip-private.h"
47 #include "cairo-image-surface-private.h"
48 #include "cairo-paginated-private.h"
49 #include "cairo-pattern-inline.h"
50 #include "cairo-region-private.h"
51 #include "cairo-recording-surface-inline.h"
52 #include "cairo-spans-compositor-private.h"
53 #include "cairo-surface-subsurface-private.h"
54 #include "cairo-surface-snapshot-private.h"
55 #include "cairo-surface-observer-private.h"
58 cairo_polygon_t *polygon;
59 cairo_fill_rule_t fill_rule;
60 cairo_antialias_t antialias;
61 } composite_spans_info_t;
63 static cairo_int_status_t
64 composite_polygon (const cairo_spans_compositor_t *compositor,
65 cairo_composite_rectangles_t *extents,
66 cairo_polygon_t *polygon,
67 cairo_fill_rule_t fill_rule,
68 cairo_antialias_t antialias);
70 static cairo_int_status_t
71 composite_boxes (const cairo_spans_compositor_t *compositor,
72 cairo_composite_rectangles_t *extents,
73 cairo_boxes_t *boxes);
75 static cairo_int_status_t
76 clip_and_composite_polygon (const cairo_spans_compositor_t *compositor,
77 cairo_composite_rectangles_t *extents,
78 cairo_polygon_t *polygon,
79 cairo_fill_rule_t fill_rule,
80 cairo_antialias_t antialias);
81 static cairo_surface_t *
82 get_clip_surface (const cairo_spans_compositor_t *compositor,
84 const cairo_clip_t *clip,
85 const cairo_rectangle_int_t *extents)
87 cairo_composite_rectangles_t composite;
88 cairo_surface_t *surface;
90 cairo_polygon_t polygon;
91 const cairo_clip_path_t *clip_path;
92 cairo_antialias_t antialias;
93 cairo_fill_rule_t fill_rule;
94 cairo_int_status_t status;
98 surface = _cairo_surface_create_similar_solid (dst,
102 CAIRO_COLOR_TRANSPARENT);
104 _cairo_box_from_rectangle (&box, extents);
105 _cairo_polygon_init (&polygon, &box, 1);
107 clip_path = clip->path;
108 status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
109 clip_path->tolerance,
111 if (unlikely (status))
112 goto cleanup_polygon;
114 polygon.num_limits = 0;
116 antialias = clip_path->antialias;
117 fill_rule = clip_path->fill_rule;
120 cairo_polygon_t intersect;
123 _cairo_boxes_init_for_array (&tmp, clip->boxes, clip->num_boxes);
124 status= _cairo_polygon_init_boxes (&intersect, &tmp);
125 if (unlikely (status))
126 goto cleanup_polygon;
128 status = _cairo_polygon_intersect (&polygon, fill_rule,
129 &intersect, CAIRO_FILL_RULE_WINDING);
130 _cairo_polygon_fini (&intersect);
132 if (unlikely (status))
133 goto cleanup_polygon;
135 fill_rule = CAIRO_FILL_RULE_WINDING;
138 polygon.limits = NULL;
139 polygon.num_limits = 0;
141 clip_path = clip_path->prev;
143 if (clip_path->antialias == antialias) {
144 cairo_polygon_t next;
146 _cairo_polygon_init (&next, NULL, 0);
147 status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
148 clip_path->tolerance,
150 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
151 status = _cairo_polygon_intersect (&polygon, fill_rule,
152 &next, clip_path->fill_rule);
153 _cairo_polygon_fini (&next);
154 if (unlikely (status))
155 goto cleanup_polygon;
157 fill_rule = CAIRO_FILL_RULE_WINDING;
160 clip_path = clip_path->prev;
163 _cairo_polygon_translate (&polygon, -extents->x, -extents->y);
164 status = _cairo_composite_rectangles_init_for_polygon (&composite, surface,
166 &_cairo_pattern_white.base,
169 if (unlikely (status))
170 goto cleanup_polygon;
172 status = composite_polygon (compositor, &composite,
173 &polygon, fill_rule, antialias);
174 _cairo_composite_rectangles_fini (&composite);
175 _cairo_polygon_fini (&polygon);
176 if (unlikely (status))
179 _cairo_polygon_init (&polygon, &box, 1);
181 clip_path = clip->path;
182 antialias = clip_path->antialias == CAIRO_ANTIALIAS_DEFAULT ? CAIRO_ANTIALIAS_NONE : CAIRO_ANTIALIAS_DEFAULT;
183 clip_path = clip_path->prev;
185 if (clip_path->antialias == antialias) {
186 if (polygon.num_edges == 0) {
187 status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
188 clip_path->tolerance,
191 fill_rule = clip_path->fill_rule;
192 polygon.limits = NULL;
193 polygon.num_limits = 0;
195 cairo_polygon_t next;
197 _cairo_polygon_init (&next, NULL, 0);
198 status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
199 clip_path->tolerance,
201 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
202 status = _cairo_polygon_intersect (&polygon, fill_rule,
203 &next, clip_path->fill_rule);
204 _cairo_polygon_fini (&next);
205 fill_rule = CAIRO_FILL_RULE_WINDING;
207 if (unlikely (status))
211 clip_path = clip_path->prev;
214 if (polygon.num_edges) {
215 _cairo_polygon_translate (&polygon, -extents->x, -extents->y);
216 status = _cairo_composite_rectangles_init_for_polygon (&composite, surface,
218 &_cairo_pattern_white.base,
221 if (unlikely (status))
222 goto cleanup_polygon;
224 status = composite_polygon (compositor, &composite,
225 &polygon, fill_rule, antialias);
226 _cairo_composite_rectangles_fini (&composite);
227 _cairo_polygon_fini (&polygon);
228 if (unlikely (status))
235 _cairo_polygon_fini (&polygon);
237 cairo_surface_destroy (surface);
238 return _cairo_int_surface_create_in_error (status);
241 static cairo_int_status_t
242 fixup_unbounded_mask (const cairo_spans_compositor_t *compositor,
243 const cairo_composite_rectangles_t *extents,
244 cairo_boxes_t *boxes)
246 cairo_composite_rectangles_t composite;
247 cairo_surface_t *clip;
248 cairo_int_status_t status;
250 TRACE((stderr, "%s\n", __FUNCTION__));
252 clip = get_clip_surface (compositor, extents->surface, extents->clip,
253 &extents->unbounded);
254 if (unlikely (clip->status)) {
255 if ((cairo_int_status_t)clip->status == CAIRO_INT_STATUS_NOTHING_TO_DO)
256 return CAIRO_STATUS_SUCCESS;
261 status = _cairo_composite_rectangles_init_for_boxes (&composite,
263 CAIRO_OPERATOR_CLEAR,
264 &_cairo_pattern_clear.base,
267 if (unlikely (status))
270 _cairo_pattern_init_for_surface (&composite.mask_pattern.surface, clip);
271 composite.mask_pattern.base.filter = CAIRO_FILTER_NEAREST;
272 composite.mask_pattern.base.extend = CAIRO_EXTEND_NONE;
274 status = composite_boxes (compositor, &composite, boxes);
276 _cairo_pattern_fini (&composite.mask_pattern.base);
277 _cairo_composite_rectangles_fini (&composite);
280 cairo_surface_destroy (clip);
284 static cairo_int_status_t
285 fixup_unbounded_polygon (const cairo_spans_compositor_t *compositor,
286 const cairo_composite_rectangles_t *extents,
287 cairo_boxes_t *boxes)
289 cairo_polygon_t polygon, intersect;
290 cairo_composite_rectangles_t composite;
291 cairo_fill_rule_t fill_rule;
292 cairo_antialias_t antialias;
293 cairo_int_status_t status;
295 TRACE((stderr, "%s\n", __FUNCTION__));
297 /* Can we treat the clip as a regular clear-polygon and use it to fill? */
298 status = _cairo_clip_get_polygon (extents->clip, &polygon,
299 &fill_rule, &antialias);
300 if (status == CAIRO_INT_STATUS_UNSUPPORTED)
303 status= _cairo_polygon_init_boxes (&intersect, boxes);
304 if (unlikely (status))
305 goto cleanup_polygon;
307 status = _cairo_polygon_intersect (&polygon, fill_rule,
308 &intersect, CAIRO_FILL_RULE_WINDING);
309 _cairo_polygon_fini (&intersect);
311 if (unlikely (status))
312 goto cleanup_polygon;
314 status = _cairo_composite_rectangles_init_for_polygon (&composite,
316 CAIRO_OPERATOR_CLEAR,
317 &_cairo_pattern_clear.base,
320 if (unlikely (status))
321 goto cleanup_polygon;
323 status = composite_polygon (compositor, &composite,
324 &polygon, fill_rule, antialias);
326 _cairo_composite_rectangles_fini (&composite);
328 _cairo_polygon_fini (&polygon);
333 static cairo_int_status_t
334 fixup_unbounded_boxes (const cairo_spans_compositor_t *compositor,
335 const cairo_composite_rectangles_t *extents,
336 cairo_boxes_t *boxes)
338 cairo_boxes_t tmp, clear;
340 cairo_int_status_t status;
342 assert (boxes->is_pixel_aligned);
344 TRACE ((stderr, "%s\n", __FUNCTION__));
345 if (extents->bounded.width == extents->unbounded.width &&
346 extents->bounded.height == extents->unbounded.height)
348 return CAIRO_STATUS_SUCCESS;
351 /* subtract the drawn boxes from the unbounded area */
352 _cairo_boxes_init (&clear);
354 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
355 box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
356 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
357 box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
359 if (boxes->num_boxes) {
360 _cairo_boxes_init (&tmp);
362 status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
363 assert (status == CAIRO_INT_STATUS_SUCCESS);
365 tmp.chunks.next = &boxes->chunks;
366 tmp.num_boxes += boxes->num_boxes;
368 status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
369 CAIRO_FILL_RULE_WINDING,
371 tmp.chunks.next = NULL;
372 if (unlikely (status))
375 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x);
376 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
378 status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
379 assert (status == CAIRO_INT_STATUS_SUCCESS);
382 /* If we have a clip polygon, we need to intersect with that as well */
383 if (extents->clip->path) {
384 status = fixup_unbounded_polygon (compositor, extents, &clear);
385 if (status == CAIRO_INT_STATUS_UNSUPPORTED)
386 status = fixup_unbounded_mask (compositor, extents, &clear);
388 /* Otherwise just intersect with the clip boxes */
389 if (extents->clip->num_boxes) {
390 _cairo_boxes_init_for_array (&tmp,
391 extents->clip->boxes,
392 extents->clip->num_boxes);
393 status = _cairo_boxes_intersect (&clear, &tmp, &clear);
394 if (unlikely (status))
398 if (clear.is_pixel_aligned) {
399 status = compositor->fill_boxes (extents->surface,
400 CAIRO_OPERATOR_CLEAR,
401 CAIRO_COLOR_TRANSPARENT,
404 cairo_composite_rectangles_t composite;
406 status = _cairo_composite_rectangles_init_for_boxes (&composite,
408 CAIRO_OPERATOR_CLEAR,
409 &_cairo_pattern_clear.base,
412 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
413 status = composite_boxes (compositor, &composite, &clear);
414 _cairo_composite_rectangles_fini (&composite);
420 _cairo_boxes_fini (&clear);
424 static cairo_surface_t *
425 unwrap_source (const cairo_pattern_t *pattern)
427 cairo_rectangle_int_t limit;
429 return _cairo_pattern_get_source ((cairo_surface_pattern_t *)pattern,
434 is_recording_pattern (const cairo_pattern_t *pattern)
436 cairo_surface_t *surface;
438 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
441 surface = ((const cairo_surface_pattern_t *) pattern)->surface;
442 return _cairo_surface_is_recording (surface);
446 recording_pattern_contains_sample (const cairo_pattern_t *pattern,
447 const cairo_rectangle_int_t *sample)
449 cairo_recording_surface_t *surface;
451 if (! is_recording_pattern (pattern))
454 if (pattern->extend == CAIRO_EXTEND_NONE)
457 surface = (cairo_recording_surface_t *) unwrap_source (pattern);
458 if (surface->unbounded)
461 return _cairo_rectangle_contains_rectangle (&surface->extents, sample);
465 op_reduces_to_source (const cairo_composite_rectangles_t *extents,
466 cairo_bool_t no_mask)
468 if (extents->op == CAIRO_OPERATOR_SOURCE)
471 if (extents->surface->is_clear)
472 return extents->op == CAIRO_OPERATOR_OVER || extents->op == CAIRO_OPERATOR_ADD;
474 if (no_mask && extents->op == CAIRO_OPERATOR_OVER)
475 return _cairo_pattern_is_opaque (&extents->source_pattern.base,
476 &extents->source_sample_area);
481 static cairo_status_t
482 upload_boxes (const cairo_spans_compositor_t *compositor,
483 const cairo_composite_rectangles_t *extents,
484 cairo_boxes_t *boxes)
486 cairo_surface_t *dst = extents->surface;
487 const cairo_surface_pattern_t *source = &extents->source_pattern.surface;
488 cairo_surface_t *src;
489 cairo_rectangle_int_t limit;
490 cairo_int_status_t status;
493 TRACE ((stderr, "%s\n", __FUNCTION__));
495 if (source->base.filter == CAIRO_FILTER_GAUSSIAN)
496 return CAIRO_INT_STATUS_UNSUPPORTED;
498 src = _cairo_pattern_get_source(source, &limit);
499 if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
500 return CAIRO_INT_STATUS_UNSUPPORTED;
502 if (! _cairo_matrix_is_integer_translation (&source->base.matrix, &tx, &ty))
503 return CAIRO_INT_STATUS_UNSUPPORTED;
505 /* Check that the data is entirely within the image */
506 if (extents->bounded.x + tx < limit.x || extents->bounded.y + ty < limit.y)
507 return CAIRO_INT_STATUS_UNSUPPORTED;
509 if (extents->bounded.x + extents->bounded.width + tx > limit.x + limit.width ||
510 extents->bounded.y + extents->bounded.height + ty > limit.y + limit.height)
511 return CAIRO_INT_STATUS_UNSUPPORTED;
516 if (src->type == CAIRO_SURFACE_TYPE_IMAGE)
517 status = compositor->draw_image_boxes (dst,
518 (cairo_image_surface_t *)src,
521 status = compositor->copy_boxes (dst, src, boxes, &extents->bounded,
528 _clip_is_region (const cairo_clip_t *clip)
538 for (i = 0; i < clip->num_boxes; i++) {
539 const cairo_box_t *b = &clip->boxes[i];
540 if (!_cairo_fixed_is_integer (b->p1.x | b->p1.y | b->p2.x | b->p2.y))
547 static cairo_int_status_t
548 composite_aligned_boxes (const cairo_spans_compositor_t *compositor,
549 const cairo_composite_rectangles_t *extents,
550 cairo_boxes_t *boxes)
552 cairo_surface_t *dst = extents->surface;
553 cairo_operator_t op = extents->op;
554 const cairo_pattern_t *source = &extents->source_pattern.base;
555 cairo_int_status_t status;
556 cairo_bool_t need_clip_mask = ! _clip_is_region (extents->clip);
557 cairo_bool_t op_is_source;
558 cairo_bool_t no_mask;
559 cairo_bool_t inplace;
561 TRACE ((stderr, "%s: need_clip_mask=%d, is-bounded=%d\n",
562 __FUNCTION__, need_clip_mask, extents->is_bounded));
563 if (need_clip_mask && ! extents->is_bounded) {
564 TRACE ((stderr, "%s: unsupported clip\n", __FUNCTION__));
565 return CAIRO_INT_STATUS_UNSUPPORTED;
568 no_mask = extents->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
569 CAIRO_COLOR_IS_OPAQUE (&extents->mask_pattern.solid.color);
570 op_is_source = op_reduces_to_source (extents, no_mask);
571 inplace = ! need_clip_mask && op_is_source && no_mask;
573 TRACE ((stderr, "%s: op-is-source=%d [op=%d], no-mask=%d, inplace=%d\n",
574 __FUNCTION__, op_is_source, op, no_mask, inplace));
576 if (op == CAIRO_OPERATOR_SOURCE && (need_clip_mask || ! no_mask)) {
577 /* SOURCE with a mask is actually a LERP in cairo semantics */
578 if ((compositor->flags & CAIRO_SPANS_COMPOSITOR_HAS_LERP) == 0) {
579 TRACE ((stderr, "%s: unsupported lerp\n", __FUNCTION__));
580 return CAIRO_INT_STATUS_UNSUPPORTED;
584 /* Are we just copying a recording surface? */
586 recording_pattern_contains_sample (&extents->source_pattern.base,
587 &extents->source_sample_area))
589 cairo_clip_t *recording_clip;
590 const cairo_pattern_t *source = &extents->source_pattern.base;
592 /* XXX could also do tiling repeat modes... */
594 /* first clear the area about to be overwritten */
596 status = compositor->fill_boxes (dst,
597 CAIRO_OPERATOR_CLEAR,
598 CAIRO_COLOR_TRANSPARENT,
601 recording_clip = _cairo_clip_from_boxes (boxes);
602 status = _cairo_recording_surface_replay_with_clip (unwrap_source (source),
604 dst, recording_clip);
605 _cairo_clip_destroy (recording_clip);
610 status = CAIRO_INT_STATUS_UNSUPPORTED;
611 if (! need_clip_mask && no_mask && source->type == CAIRO_PATTERN_TYPE_SOLID) {
612 const cairo_color_t *color;
614 color = &((cairo_solid_pattern_t *) source)->color;
616 op = CAIRO_OPERATOR_SOURCE;
617 status = compositor->fill_boxes (dst, op, color, boxes);
618 } else if (inplace && source->type == CAIRO_PATTERN_TYPE_SURFACE) {
619 status = upload_boxes (compositor, extents, boxes);
621 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
622 cairo_surface_t *src;
623 cairo_surface_t *mask = NULL;
625 int mask_x = 0, mask_y = 0;
627 /* All typical cases will have been resolved before now... */
628 if (need_clip_mask) {
629 mask = get_clip_surface (compositor, dst, extents->clip,
631 if (unlikely (mask->status))
634 mask_x = -extents->bounded.x;
635 mask_y = -extents->bounded.y;
638 /* XXX but this is still ugly */
640 src = compositor->pattern_to_surface (dst,
641 &extents->mask_pattern.base,
644 &extents->mask_sample_area,
646 if (unlikely (src->status)) {
647 cairo_surface_destroy (mask);
652 status = compositor->composite_boxes (mask, CAIRO_OPERATOR_IN,
657 boxes, &extents->bounded);
659 cairo_surface_destroy (src);
667 src = compositor->pattern_to_surface (dst, source, FALSE,
669 &extents->source_sample_area,
671 if (likely (src->status == CAIRO_STATUS_SUCCESS)) {
672 status = compositor->composite_boxes (dst, op, src, mask,
676 boxes, &extents->bounded);
677 cairo_surface_destroy (src);
679 status = src->status;
681 cairo_surface_destroy (mask);
684 if (status == CAIRO_INT_STATUS_SUCCESS && ! extents->is_bounded)
685 status = fixup_unbounded_boxes (compositor, extents, boxes);
691 composite_needs_clip (const cairo_composite_rectangles_t *composite,
692 const cairo_box_t *extents)
694 return !_cairo_clip_contains_box (composite->clip, extents);
697 static cairo_int_status_t
698 composite_boxes (const cairo_spans_compositor_t *compositor,
699 cairo_composite_rectangles_t *extents,
700 cairo_boxes_t *boxes)
702 cairo_abstract_span_renderer_t renderer;
703 cairo_rectangular_scan_converter_t converter;
704 const struct _cairo_boxes_chunk *chunk;
705 cairo_int_status_t status;
708 TRACE ((stderr, "%s\n", __FUNCTION__));
709 _cairo_box_from_rectangle (&box, &extents->unbounded);
710 if (composite_needs_clip (extents, &box)) {
711 TRACE ((stderr, "%s: unsupported clip\n", __FUNCTION__));
712 return CAIRO_INT_STATUS_UNSUPPORTED;
715 _cairo_rectangular_scan_converter_init (&converter, &extents->unbounded);
716 for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
717 const cairo_box_t *box = chunk->base;
720 for (i = 0; i < chunk->count; i++) {
721 status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
722 if (unlikely (status))
723 goto cleanup_converter;
727 status = compositor->renderer_init (&renderer, extents,
728 CAIRO_ANTIALIAS_DEFAULT, FALSE);
729 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
730 status = converter.base.generate (&converter.base, &renderer.base);
731 compositor->renderer_fini (&renderer, status);
734 converter.base.destroy (&converter.base);
738 static cairo_int_status_t
739 composite_polygon (const cairo_spans_compositor_t *compositor,
740 cairo_composite_rectangles_t *extents,
741 cairo_polygon_t *polygon,
742 cairo_fill_rule_t fill_rule,
743 cairo_antialias_t antialias)
745 cairo_abstract_span_renderer_t renderer;
746 cairo_scan_converter_t *converter;
747 cairo_bool_t needs_clip;
748 cairo_int_status_t status;
750 if (extents->is_bounded)
751 needs_clip = extents->clip->path != NULL;
753 needs_clip = !_clip_is_region (extents->clip) || extents->clip->num_boxes > 1;
754 TRACE ((stderr, "%s - needs_clip=%d\n", __FUNCTION__, needs_clip));
756 TRACE ((stderr, "%s: unsupported clip\n", __FUNCTION__));
757 return CAIRO_INT_STATUS_UNSUPPORTED;
759 const cairo_rectangle_int_t *r = &extents->unbounded;
761 if (antialias == CAIRO_ANTIALIAS_FAST) {
762 converter = _cairo_tor22_scan_converter_create (r->x, r->y,
765 fill_rule, antialias);
766 status = _cairo_tor22_scan_converter_add_polygon (converter, polygon);
767 } else if (antialias == CAIRO_ANTIALIAS_NONE) {
768 converter = _cairo_mono_scan_converter_create (r->x, r->y,
772 status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
774 converter = _cairo_tor_scan_converter_create (r->x, r->y,
777 fill_rule, antialias);
778 status = _cairo_tor_scan_converter_add_polygon (converter, polygon);
781 if (unlikely (status))
782 goto cleanup_converter;
784 status = compositor->renderer_init (&renderer, extents,
785 antialias, needs_clip);
786 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
787 status = converter->generate (converter, &renderer.base);
788 compositor->renderer_fini (&renderer, status);
791 converter->destroy (converter);
795 static cairo_int_status_t
796 trim_extents_to_boxes (cairo_composite_rectangles_t *extents,
797 cairo_boxes_t *boxes)
801 _cairo_boxes_extents (boxes, &box);
802 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
805 static cairo_int_status_t
806 trim_extents_to_polygon (cairo_composite_rectangles_t *extents,
807 cairo_polygon_t *polygon)
809 return _cairo_composite_rectangles_intersect_mask_extents (extents,
813 static cairo_int_status_t
814 clip_and_composite_boxes (const cairo_spans_compositor_t *compositor,
815 cairo_composite_rectangles_t *extents,
816 cairo_boxes_t *boxes)
818 cairo_int_status_t status;
819 cairo_polygon_t polygon;
821 TRACE ((stderr, "%s\n", __FUNCTION__));
822 status = trim_extents_to_boxes (extents, boxes);
823 if (unlikely (status))
826 if (boxes->num_boxes == 0) {
827 if (extents->is_bounded)
828 return CAIRO_STATUS_SUCCESS;
830 return fixup_unbounded_boxes (compositor, extents, boxes);
833 /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
834 if (extents->clip->path != NULL && extents->is_bounded) {
835 cairo_polygon_t polygon;
836 cairo_fill_rule_t fill_rule;
837 cairo_antialias_t antialias;
840 clip = _cairo_clip_copy (extents->clip);
841 clip = _cairo_clip_intersect_boxes (clip, boxes);
842 if (_cairo_clip_is_all_clipped (clip))
843 return CAIRO_INT_STATUS_NOTHING_TO_DO;
845 status = _cairo_clip_get_polygon (clip, &polygon,
846 &fill_rule, &antialias);
847 _cairo_clip_path_destroy (clip->path);
849 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
850 cairo_clip_t *saved_clip = extents->clip;
851 extents->clip = clip;
853 status = clip_and_composite_polygon (compositor, extents, &polygon,
854 fill_rule, antialias);
856 clip = extents->clip;
857 extents->clip = saved_clip;
859 _cairo_polygon_fini (&polygon);
861 _cairo_clip_destroy (clip);
863 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
867 if (boxes->is_pixel_aligned) {
868 status = composite_aligned_boxes (compositor, extents, boxes);
869 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
873 status = composite_boxes (compositor, extents, boxes);
874 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
877 status = _cairo_polygon_init_boxes (&polygon, boxes);
878 if (unlikely (status))
881 status = composite_polygon (compositor, extents, &polygon,
882 CAIRO_FILL_RULE_WINDING,
883 CAIRO_ANTIALIAS_DEFAULT);
884 _cairo_polygon_fini (&polygon);
889 static cairo_int_status_t
890 clip_and_composite_polygon (const cairo_spans_compositor_t *compositor,
891 cairo_composite_rectangles_t *extents,
892 cairo_polygon_t *polygon,
893 cairo_fill_rule_t fill_rule,
894 cairo_antialias_t antialias)
896 cairo_int_status_t status;
898 TRACE ((stderr, "%s\n", __FUNCTION__));
900 /* XXX simply uses polygon limits.point extemities, tessellation? */
901 status = trim_extents_to_polygon (extents, polygon);
902 if (unlikely (status))
905 if (_cairo_polygon_is_empty (polygon)) {
908 if (extents->is_bounded)
909 return CAIRO_STATUS_SUCCESS;
911 _cairo_boxes_init (&boxes);
912 extents->bounded.width = extents->bounded.height = 0;
913 return fixup_unbounded_boxes (compositor, extents, &boxes);
916 if (extents->is_bounded && extents->clip->path) {
917 cairo_polygon_t clipper;
918 cairo_antialias_t clip_antialias;
919 cairo_fill_rule_t clip_fill_rule;
921 TRACE((stderr, "%s - combining shape with clip polygon\n",
924 status = _cairo_clip_get_polygon (extents->clip,
928 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
929 cairo_clip_t *old_clip;
931 if (clip_antialias == antialias) {
932 status = _cairo_polygon_intersect (polygon, fill_rule,
933 &clipper, clip_fill_rule);
934 _cairo_polygon_fini (&clipper);
935 if (unlikely (status))
938 old_clip = extents->clip;
939 extents->clip = _cairo_clip_copy_region (extents->clip);
940 _cairo_clip_destroy (old_clip);
942 status = trim_extents_to_polygon (extents, polygon);
943 if (unlikely (status))
946 fill_rule = CAIRO_FILL_RULE_WINDING;
948 _cairo_polygon_fini (&clipper);
953 return composite_polygon (compositor, extents,
954 polygon, fill_rule, antialias);
957 /* high-level compositor interface */
959 static cairo_int_status_t
960 _cairo_spans_compositor_paint (const cairo_compositor_t *_compositor,
961 cairo_composite_rectangles_t *extents)
963 const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
965 cairo_int_status_t status;
967 TRACE ((stderr, "%s\n", __FUNCTION__));
968 _cairo_clip_steal_boxes (extents->clip, &boxes);
969 status = clip_and_composite_boxes (compositor, extents, &boxes);
970 _cairo_clip_unsteal_boxes (extents->clip, &boxes);
975 static cairo_int_status_t
976 _cairo_spans_compositor_mask (const cairo_compositor_t *_compositor,
977 cairo_composite_rectangles_t *extents)
979 const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
980 cairo_int_status_t status;
983 TRACE ((stderr, "%s\n", __FUNCTION__));
984 _cairo_clip_steal_boxes (extents->clip, &boxes);
985 status = clip_and_composite_boxes (compositor, extents, &boxes);
986 _cairo_clip_unsteal_boxes (extents->clip, &boxes);
991 static cairo_int_status_t
992 _cairo_spans_compositor_stroke (const cairo_compositor_t *_compositor,
993 cairo_composite_rectangles_t *extents,
994 const cairo_path_fixed_t *path,
995 const cairo_stroke_style_t *style,
996 const cairo_matrix_t *ctm,
997 const cairo_matrix_t *ctm_inverse,
999 cairo_antialias_t antialias)
1001 const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
1002 cairo_int_status_t status;
1004 TRACE ((stderr, "%s\n", __FUNCTION__));
1005 TRACE_ (_cairo_debug_print_path (stderr, path));
1006 TRACE_ (_cairo_debug_print_clip (stderr, extents->clip));
1008 status = CAIRO_INT_STATUS_UNSUPPORTED;
1009 if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
1010 cairo_boxes_t boxes;
1012 _cairo_boxes_init (&boxes);
1013 if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
1014 _cairo_boxes_limit (&boxes,
1015 extents->clip->boxes,
1016 extents->clip->num_boxes);
1018 status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
1023 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
1024 status = clip_and_composite_boxes (compositor, extents, &boxes);
1025 _cairo_boxes_fini (&boxes);
1028 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1029 cairo_polygon_t polygon;
1030 cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING;
1032 if (! _cairo_rectangle_contains_rectangle (&extents->unbounded,
1035 if (extents->clip->num_boxes == 1) {
1036 _cairo_polygon_init (&polygon, extents->clip->boxes, 1);
1039 _cairo_box_from_rectangle (&limits, &extents->unbounded);
1040 _cairo_polygon_init (&polygon, &limits, 1);
1045 _cairo_polygon_init (&polygon, NULL, 0);
1047 status = _cairo_path_fixed_stroke_to_polygon (path,
1052 TRACE_ (_cairo_debug_print_polygon (stderr, &polygon));
1053 polygon.num_limits = 0;
1055 if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) {
1056 status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
1057 extents->clip->boxes,
1058 extents->clip->num_boxes);
1060 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1061 cairo_clip_t *saved_clip = extents->clip;
1063 if (extents->is_bounded) {
1064 extents->clip = _cairo_clip_copy_path (extents->clip);
1065 extents->clip = _cairo_clip_intersect_box(extents->clip,
1069 status = clip_and_composite_polygon (compositor, extents, &polygon,
1070 fill_rule, antialias);
1072 if (extents->is_bounded) {
1073 _cairo_clip_destroy (extents->clip);
1074 extents->clip = saved_clip;
1077 _cairo_polygon_fini (&polygon);
1083 static cairo_int_status_t
1084 _cairo_spans_compositor_fill (const cairo_compositor_t *_compositor,
1085 cairo_composite_rectangles_t *extents,
1086 const cairo_path_fixed_t *path,
1087 cairo_fill_rule_t fill_rule,
1089 cairo_antialias_t antialias)
1091 const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
1092 cairo_int_status_t status;
1094 TRACE((stderr, "%s op=%d, antialias=%d\n", __FUNCTION__, extents->op, antialias));
1096 status = CAIRO_INT_STATUS_UNSUPPORTED;
1097 if (_cairo_path_fixed_fill_is_rectilinear (path)) {
1098 cairo_boxes_t boxes;
1100 TRACE((stderr, "%s - rectilinear\n", __FUNCTION__));
1102 _cairo_boxes_init (&boxes);
1103 if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
1104 _cairo_boxes_limit (&boxes,
1105 extents->clip->boxes,
1106 extents->clip->num_boxes);
1107 status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
1111 if (likely (status == CAIRO_INT_STATUS_SUCCESS))
1112 status = clip_and_composite_boxes (compositor, extents, &boxes);
1113 _cairo_boxes_fini (&boxes);
1115 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1116 cairo_polygon_t polygon;
1118 TRACE((stderr, "%s - polygon\n", __FUNCTION__));
1120 if (! _cairo_rectangle_contains_rectangle (&extents->unbounded,
1123 TRACE((stderr, "%s - clipping to bounds\n", __FUNCTION__));
1124 if (extents->clip->num_boxes == 1) {
1125 _cairo_polygon_init (&polygon, extents->clip->boxes, 1);
1128 _cairo_box_from_rectangle (&limits, &extents->unbounded);
1129 _cairo_polygon_init (&polygon, &limits, 1);
1134 _cairo_polygon_init (&polygon, NULL, 0);
1137 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
1138 TRACE_ (_cairo_debug_print_polygon (stderr, &polygon));
1139 polygon.num_limits = 0;
1141 if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) {
1142 TRACE((stderr, "%s - polygon intersect with %d clip boxes\n",
1143 __FUNCTION__, extents->clip->num_boxes));
1144 status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
1145 extents->clip->boxes,
1146 extents->clip->num_boxes);
1148 TRACE_ (_cairo_debug_print_polygon (stderr, &polygon));
1149 if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1150 cairo_clip_t *saved_clip = extents->clip;
1152 if (extents->is_bounded) {
1153 TRACE((stderr, "%s - polygon discard clip boxes\n",
1155 extents->clip = _cairo_clip_copy_path (extents->clip);
1156 extents->clip = _cairo_clip_intersect_box(extents->clip,
1160 status = clip_and_composite_polygon (compositor, extents, &polygon,
1161 fill_rule, antialias);
1163 if (extents->is_bounded) {
1164 _cairo_clip_destroy (extents->clip);
1165 extents->clip = saved_clip;
1168 _cairo_polygon_fini (&polygon);
1170 TRACE((stderr, "%s - polygon status=%d\n", __FUNCTION__, status));
1177 _cairo_spans_compositor_init (cairo_spans_compositor_t *compositor,
1178 const cairo_compositor_t *delegate)
1180 compositor->base.delegate = delegate;
1182 compositor->base.paint = _cairo_spans_compositor_paint;
1183 compositor->base.mask = _cairo_spans_compositor_mask;
1184 compositor->base.fill = _cairo_spans_compositor_fill;
1185 compositor->base.stroke = _cairo_spans_compositor_stroke;
1186 compositor->base.glyphs = NULL;