[cairo-commit] 2 commits - src/cairo-analysis-surface.c src/cairo-bentley-ottmann-rectangular.c src/cairo-bentley-ottmann-rectilinear.c src/cairo-boxes.c src/cairo-boxes-intersect.c src/cairo-boxes-private.h src/cairo-cff-subset.c src/cairo-clip-boxes.c src/cairo-clip.c src/cairo-clip-polygon.c src/cairo-clip-private.h src/cairo-clip-region.c src/cairo-clip-surface.c src/cairo-composite-rectangles.c src/cairo-composite-rectangles-private.h src/cairo-debug.c src/cairo-default-context.c src/cairo-error.c src/cairo-error-private.h src/cairo-fixed-private.h src/cairo-font-face-twin.c src/cairo-ft-font.c src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-gl-surface.c src/cairo-gl-surface-legacy.c src/cairo-gstate.c src/cairo-gstate-private.h src/cairo-image-info.c src/cairo-image-surface.c src/cairoint.h src/cairo-misc.c src/cairo-paginated-surface.c src/cairo-path-bounds.c src/cairo-path-fill.c src/cairo-path-stroke.c src/cairo-pattern.c src/cairo-pdf-operators.c src/cairo-pdf-oper ators-private.h src/cairo-pdf-surface.c src/cairo-png.c src/cairo-polygon.c src/cairo-polygon-intersect.c src/cairo-polygon-reduce.c src/cairo-ps-surface.c src/cairo-quartz-surface.c src/cairo-recording-surface.c src/cairo-recording-surface-private.h src/cairo-scaled-font.c src/cairo-scaled-font-subsets.c src/cairo-scaled-font-subsets-private.h src/cairo-script-surface.c src/cairo-spans.c src/cairo-surface.c src/cairo-surface-clipper.c src/cairo-surface-clipper-private.h src/cairo-surface-fallback.c src/cairo-surface-fallback-private.h src/cairo-surface-offset.c src/cairo-surface-offset-private.h src/cairo-surface-subsurface.c src/cairo-surface-wrapper.c src/cairo-surface-wrapper-private.h src/cairo-svg-surface.c src/cairo-tee.h src/cairo-tee-surface.c src/cairo-tor-scan-converter.c src/cairo-traps.c src/cairo-truetype-subset.c src/cairo-type1-fallback.c src/cairo-type3-glyph-surface.c src/cairo-types-private.h src/cairo-user-font.c src/cairo-win32-printing-surface.c src/cai ro-win32-surface.c src/cairo-xcb-private.h src/cairo-xcb-surface.c src/cairo-xcb-surface-cairo.c src/cairo-xcb-surface-render.c src/cairo-xlib-surface.c src/cairo-xml-surface.c src/Makefile.sources src/test-null-surface.c src/test-paginated-surface.c src/test-wrapping-surface.c test/clip-group-shapes-circles.ref.png test/clip-shape.ref.png test/clip-stroke.ref.png
Chris Wilson
ickle at kemper.freedesktop.org
Tue Jul 19 13:15:50 PDT 2011
src/Makefile.sources | 7
src/cairo-analysis-surface.c | 98 --
src/cairo-bentley-ottmann-rectangular.c | 4
src/cairo-bentley-ottmann-rectilinear.c | 2
src/cairo-boxes-intersect.c | 666 +++++++++++++
src/cairo-boxes-private.h | 27
src/cairo-boxes.c | 78 +
src/cairo-cff-subset.c | 14
src/cairo-clip-boxes.c | 559 +++++++++++
src/cairo-clip-polygon.c | 127 ++
src/cairo-clip-private.h | 149 +--
src/cairo-clip-region.c | 117 ++
src/cairo-clip-surface.c | 142 ++
src/cairo-clip.c | 1414 +++--------------------------
src/cairo-composite-rectangles-private.h | 19
src/cairo-composite-rectangles.c | 54 -
src/cairo-debug.c | 37
src/cairo-default-context.c | 5
src/cairo-error-private.h | 54 +
src/cairo-error.c | 4
src/cairo-fixed-private.h | 6
src/cairo-font-face-twin.c | 31
src/cairo-ft-font.c | 52 -
src/cairo-gl-glyphs.c | 134 +-
src/cairo-gl-private.h | 2
src/cairo-gl-surface-legacy.c | 601 ++++++++++++
src/cairo-gl-surface.c | 126 --
src/cairo-gstate-private.h | 2
src/cairo-gstate.c | 206 +---
src/cairo-image-info.c | 2
src/cairo-image-surface.c | 507 +++-------
src/cairo-misc.c | 2
src/cairo-paginated-surface.c | 27
src/cairo-path-bounds.c | 1
src/cairo-path-fill.c | 112 ++
src/cairo-path-stroke.c | 34
src/cairo-pattern.c | 4
src/cairo-pdf-operators-private.h | 14
src/cairo-pdf-operators.c | 12
src/cairo-pdf-surface.c | 82 -
src/cairo-png.c | 2
src/cairo-polygon-intersect.c | 1466 ++++++++++++++++++++++++++++++
src/cairo-polygon-reduce.c | 1491 +++++++++++++++++++++++++++++++
src/cairo-polygon.c | 111 ++
src/cairo-ps-surface.c | 61 -
src/cairo-quartz-surface.c | 28
src/cairo-recording-surface-private.h | 5
src/cairo-recording-surface.c | 82 -
src/cairo-scaled-font-subsets-private.h | 4
src/cairo-scaled-font-subsets.c | 8
src/cairo-scaled-font.c | 14
src/cairo-script-surface.c | 73 -
src/cairo-spans.c | 29
src/cairo-surface-clipper-private.h | 5
src/cairo-surface-clipper.c | 122 +-
src/cairo-surface-fallback-private.h | 14
src/cairo-surface-fallback.c | 259 +----
src/cairo-surface-offset-private.h | 14
src/cairo-surface-offset.c | 102 --
src/cairo-surface-subsurface.c | 79 -
src/cairo-surface-wrapper-private.h | 16
src/cairo-surface-wrapper.c | 228 +---
src/cairo-surface.c | 82 -
src/cairo-svg-surface.c | 42
src/cairo-tee-surface.c | 30
src/cairo-tee.h | 2
src/cairo-tor-scan-converter.c | 22
src/cairo-traps.c | 95 +
src/cairo-truetype-subset.c | 11
src/cairo-type1-fallback.c | 2
src/cairo-type3-glyph-surface.c | 40
src/cairo-types-private.h | 11
src/cairo-user-font.c | 9
src/cairo-win32-printing-surface.c | 12
src/cairo-win32-surface.c | 8
src/cairo-xcb-private.h | 38
src/cairo-xcb-surface-cairo.c | 14
src/cairo-xcb-surface-render.c | 615 ++++--------
src/cairo-xcb-surface.c | 28
src/cairo-xlib-surface.c | 32
src/cairo-xml-surface.c | 27
src/cairoint.h | 79 +
src/test-null-surface.c | 16
src/test-paginated-surface.c | 14
src/test-wrapping-surface.c | 14
test/clip-group-shapes-circles.ref.png |binary
test/clip-shape.ref.png |binary
test/clip-stroke.ref.png |binary
88 files changed, 7489 insertions(+), 3501 deletions(-)
New commits:
commit b132fae5e843c329d1414d1a65b2e8d66b99852f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Jul 14 21:19:54 2011 +0100
clip: Rudimentary support for clip-polygon extraction
Step 1, fix the failings sighted recently by tracking clip-boxes as an
explicit property of the clipping and of composition.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 5371e81..97f452a 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -118,9 +118,14 @@ cairo_sources = \
cairo-bentley-ottmann-rectilinear.c \
cairo-botor-scan-converter.c \
cairo-boxes.c \
+ cairo-boxes-intersect.c \
cairo.c \
cairo-cache.c \
cairo-clip.c \
+ cairo-clip-boxes.c \
+ cairo-clip-polygon.c \
+ cairo-clip-region.c \
+ cairo-clip-surface.c \
cairo-color.c \
cairo-composite-rectangles.c \
cairo-debug.c \
@@ -156,6 +161,8 @@ cairo_sources = \
cairo-pattern.c \
cairo-pen.c \
cairo-polygon.c \
+ cairo-polygon-intersect.c \
+ cairo-polygon-reduce.c \
cairo-recording-surface.c \
cairo-rectangle.c \
cairo-rectangular-scan-converter.c \
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index affa556..aa0977e 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -67,8 +67,8 @@ _cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
cairo_int_status_t status_b)
{
/* fatal errors should be checked and propagated at source */
- assert (! _cairo_status_is_error (status_a));
- assert (! _cairo_status_is_error (status_b));
+ assert (! _cairo_int_status_is_error (status_a));
+ assert (! _cairo_int_status_is_error (status_b));
/* return the most important status */
if (status_a == CAIRO_INT_STATUS_UNSUPPORTED ||
@@ -88,10 +88,10 @@ _cairo_analysis_surface_merge_status (cairo_int_status_t status_a,
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
/* at this point we have checked all the valid internal codes, so... */
- assert (status_a == CAIRO_STATUS_SUCCESS &&
- status_b == CAIRO_STATUS_SUCCESS);
+ assert (status_a == CAIRO_INT_STATUS_SUCCESS &&
+ status_b == CAIRO_INT_STATUS_SUCCESS);
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -144,10 +144,10 @@ _add_operation (cairo_analysis_surface_t *surface,
/* Even though the operation is not visible we must be careful
* to not allow unsupported operations to be replayed to the
* backend during CAIRO_PAGINATED_MODE_RENDER */
- if (backend_status == CAIRO_STATUS_SUCCESS ||
+ if (backend_status == CAIRO_INT_STATUS_SUCCESS ||
backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
{
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
else
{
@@ -172,10 +172,10 @@ _add_operation (cairo_analysis_surface_t *surface,
* careful to not allow unsupported operations to be
* replayed to the backend during
* CAIRO_PAGINATED_MODE_RENDER */
- if (backend_status == CAIRO_STATUS_SUCCESS ||
+ if (backend_status == CAIRO_INT_STATUS_SUCCESS ||
backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
{
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
else
{
@@ -217,10 +217,10 @@ _add_operation (cairo_analysis_surface_t *surface,
* transparency into the white background.
*/
if (cairo_region_contains_rectangle (&surface->supported_region, rect) == CAIRO_REGION_OVERLAP_OUT)
- backend_status = CAIRO_STATUS_SUCCESS;
+ backend_status = CAIRO_INT_STATUS_SUCCESS;
}
- if (backend_status == CAIRO_STATUS_SUCCESS) {
+ if (backend_status == CAIRO_INT_STATUS_SUCCESS) {
/* Add the operation to the supported region. Operations in
* this region will be emitted as native operations.
*/
@@ -241,7 +241,7 @@ _add_operation (cairo_analysis_surface_t *surface,
* invoke the cairo-surface-fallback path then return
* CAIRO_STATUS_SUCCESS.
*/
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
else
return status;
@@ -270,23 +270,17 @@ _cairo_analysis_surface_get_extents (void *abstract_surface,
}
static void
-_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
+_rectangle_intersect_clip (cairo_rectangle_int_t *extents, const cairo_clip_t *clip)
{
- const cairo_rectangle_int_t *clip_extents;
-
- clip_extents = NULL;
if (clip != NULL)
- clip_extents = _cairo_clip_get_extents (clip);
-
- if (clip_extents != NULL)
- _cairo_rectangle_intersect (extents, clip_extents);
+ _cairo_rectangle_intersect (extents, _cairo_clip_get_extents (clip));
}
static void
_cairo_analysis_surface_operation_extents (cairo_analysis_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
cairo_rectangle_int_t *extents)
{
cairo_bool_t is_empty;
@@ -307,10 +301,10 @@ static cairo_int_status_t
_cairo_analysis_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_analysis_surface_t *surface = abstract_surface;
- cairo_status_t backend_status;
+ cairo_int_status_t backend_status;
cairo_rectangle_int_t extents;
if (surface->target->backend->paint == NULL) {
@@ -319,7 +313,7 @@ _cairo_analysis_surface_paint (void *abstract_surface,
backend_status =
surface->target->backend->paint (surface->target,
op, source, clip);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
}
@@ -338,7 +332,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_int_status_t backend_status;
@@ -350,7 +344,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
backend_status =
surface->target->backend->mask (surface->target,
op, source, mask, clip);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
}
@@ -363,7 +357,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
if (_cairo_surface_is_recording (surface_pattern->surface)) {
backend_source_status =
_analyze_recording_surface_pattern (surface, source);
- if (_cairo_status_is_error (backend_source_status))
+ if (_cairo_int_status_is_error (backend_source_status))
return backend_source_status;
}
}
@@ -373,7 +367,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
if (_cairo_surface_is_recording (surface_pattern->surface)) {
backend_mask_status =
_analyze_recording_surface_pattern (surface, mask);
- if (_cairo_status_is_error (backend_mask_status))
+ if (_cairo_int_status_is_error (backend_mask_status))
return backend_mask_status;
}
}
@@ -401,16 +395,16 @@ static cairo_int_status_t
_cairo_analysis_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_analysis_surface_t *surface = abstract_surface;
- cairo_status_t backend_status;
+ cairo_int_status_t backend_status;
cairo_rectangle_int_t extents;
if (surface->target->backend->stroke == NULL) {
@@ -422,7 +416,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
ctm, ctm_inverse,
tolerance, antialias,
clip);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
}
@@ -435,7 +429,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t mask_extents;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_path_fixed_stroke_extents (path, style,
ctm, ctm_inverse,
@@ -454,14 +448,14 @@ static cairo_int_status_t
_cairo_analysis_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_analysis_surface_t *surface = abstract_surface;
- cairo_status_t backend_status;
+ cairo_int_status_t backend_status;
cairo_rectangle_int_t extents;
if (surface->target->backend->fill == NULL) {
@@ -472,7 +466,7 @@ _cairo_analysis_surface_fill (void *abstract_surface,
source, path, fill_rule,
tolerance, antialias,
clip);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
}
@@ -502,11 +496,11 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_analysis_surface_t *surface = abstract_surface;
- cairo_status_t status, backend_status;
+ cairo_int_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
/* Adapted from _cairo_surface_show_glyphs */
@@ -518,7 +512,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
scaled_font,
clip,
remaining_glyphs);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
}
else if (surface->target->backend->show_text_glyphs != NULL)
@@ -532,7 +526,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
FALSE,
scaled_font,
clip);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
}
else
@@ -582,10 +576,10 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_analysis_surface_t *surface = abstract_surface;
- cairo_status_t status, backend_status;
+ cairo_int_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
/* Adapted from _cairo_surface_show_glyphs */
@@ -600,7 +594,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
cluster_flags,
scaled_font,
clip);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
}
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED &&
@@ -614,7 +608,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
scaled_font,
clip,
&remaining_glyphs);
- if (_cairo_status_is_error (backend_status))
+ if (_cairo_int_status_is_error (backend_status))
return backend_status;
glyphs += num_glyphs - remaining_glyphs;
@@ -803,36 +797,36 @@ typedef cairo_int_status_t
(*_paint_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_mask_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_stroke_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_fill_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_show_glyphs_func) (void *surface,
@@ -841,7 +835,7 @@ typedef cairo_int_status_t
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs);
static const cairo_surface_backend_t cairo_null_surface_backend = {
diff --git a/src/cairo-bentley-ottmann-rectangular.c b/src/cairo-bentley-ottmann-rectangular.c
index 9a4dcd9..ceeddd3 100644
--- a/src/cairo-bentley-ottmann-rectangular.c
+++ b/src/cairo-bentley-ottmann-rectangular.c
@@ -320,7 +320,7 @@ edge_end_box (sweep_line_t *sweep_line,
box.p2.x = left->right->x;
box.p2.y = bot;
- status = _cairo_boxes_add (container, &box);
+ status = _cairo_boxes_add (container, CAIRO_ANTIALIAS_DEFAULT, &box);
}
}
if (unlikely (status))
@@ -746,7 +746,7 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
box.p2.x = tmp;
}
- status = _cairo_boxes_add (out, &box);
+ status = _cairo_boxes_add (out, CAIRO_ANTIALIAS_DEFAULT, &box);
assert (status == CAIRO_STATUS_SUCCESS);
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-bentley-ottmann-rectilinear.c b/src/cairo-bentley-ottmann-rectilinear.c
index 1696d93..a3eb490 100644
--- a/src/cairo-bentley-ottmann-rectilinear.c
+++ b/src/cairo-bentley-ottmann-rectilinear.c
@@ -237,7 +237,7 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
box.p1.y = trap->top;
box.p2.x = trap->right->edge.line.p1.x;
box.p2.y = bot;
- status = _cairo_boxes_add (container, &box);
+ status = _cairo_boxes_add (container, CAIRO_ANTIALIAS_DEFAULT, &box);
}
}
diff --git a/src/cairo-boxes-intersect.c b/src/cairo-boxes-intersect.c
new file mode 100644
index 0000000..831abc1
--- /dev/null
+++ b/src/cairo-boxes-intersect.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright © 2004 Carl Worth
+ * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2009 Chris Wilson
+ * Copyright © 2011 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Carl Worth
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth at cworth.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+/* Provide definitions for standalone compilation */
+#include "cairoint.h"
+
+#include "cairo-boxes-private.h"
+#include "cairo-error-private.h"
+#include "cairo-combsort-private.h"
+#include "cairo-list-private.h"
+
+#include <setjmp.h>
+
+typedef struct _rectangle rectangle_t;
+typedef struct _edge edge_t;
+
+struct _edge {
+ edge_t *next, *prev;
+ edge_t *right;
+ cairo_fixed_t x, top;
+ int a_or_b;
+ int dir;
+};
+
+struct _rectangle {
+ edge_t left, right;
+ int32_t top, bottom;
+};
+
+#define UNROLL3(x) x x x
+
+/* the parent is always given by index/2 */
+#define PQ_PARENT_INDEX(i) ((i) >> 1)
+#define PQ_FIRST_ENTRY 1
+
+/* left and right children are index * 2 and (index * 2) +1 respectively */
+#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
+
+typedef struct _pqueue {
+ int size, max_size;
+
+ rectangle_t **elements;
+ rectangle_t *elements_embedded[1024];
+} pqueue_t;
+
+typedef struct _sweep_line {
+ rectangle_t **rectangles;
+ pqueue_t pq;
+ edge_t head, tail;
+ edge_t *insert_left, *insert_right;
+ int32_t current_y;
+ int32_t last_y;
+
+ jmp_buf unwind;
+} sweep_line_t;
+
+#define DEBUG_TRAPS 0
+
+#if DEBUG_TRAPS
+static void
+dump_traps (cairo_traps_t *traps, const char *filename)
+{
+ FILE *file;
+ int n;
+
+ if (getenv ("CAIRO_DEBUG_TRAPS") == NULL)
+ return;
+
+ file = fopen (filename, "a");
+ if (file != NULL) {
+ for (n = 0; n < traps->num_traps; n++) {
+ fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
+ traps->traps[n].top,
+ traps->traps[n].bottom,
+ traps->traps[n].left.p1.x,
+ traps->traps[n].left.p1.y,
+ traps->traps[n].left.p2.x,
+ traps->traps[n].left.p2.y,
+ traps->traps[n].right.p1.x,
+ traps->traps[n].right.p1.y,
+ traps->traps[n].right.p2.x,
+ traps->traps[n].right.p2.y);
+ }
+ fprintf (file, "\n");
+ fclose (file);
+ }
+}
+#else
+#define dump_traps(traps, filename)
+#endif
+
+static inline int
+rectangle_compare_start (const rectangle_t *a,
+ const rectangle_t *b)
+{
+ return a->top - b->top;
+}
+
+static inline int
+rectangle_compare_stop (const rectangle_t *a,
+ const rectangle_t *b)
+{
+ return a->bottom - b->bottom;
+}
+
+static inline void
+pqueue_init (pqueue_t *pq)
+{
+ pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
+ pq->size = 0;
+
+ pq->elements = pq->elements_embedded;
+ pq->elements[PQ_FIRST_ENTRY] = NULL;
+}
+
+static inline void
+pqueue_fini (pqueue_t *pq)
+{
+ if (pq->elements != pq->elements_embedded)
+ free (pq->elements);
+}
+
+static cairo_bool_t
+pqueue_grow (pqueue_t *pq)
+{
+ rectangle_t **new_elements;
+ pq->max_size *= 2;
+
+ if (pq->elements == pq->elements_embedded) {
+ new_elements = _cairo_malloc_ab (pq->max_size,
+ sizeof (rectangle_t *));
+ if (unlikely (new_elements == NULL))
+ return FALSE;
+
+ memcpy (new_elements, pq->elements_embedded,
+ sizeof (pq->elements_embedded));
+ } else {
+ new_elements = _cairo_realloc_ab (pq->elements,
+ pq->max_size,
+ sizeof (rectangle_t *));
+ if (unlikely (new_elements == NULL))
+ return FALSE;
+ }
+
+ pq->elements = new_elements;
+ return TRUE;
+}
+
+static inline void
+pqueue_push (sweep_line_t *sweep, rectangle_t *rectangle)
+{
+ rectangle_t **elements;
+ int i, parent;
+
+ if (unlikely (sweep->pq.size + 1 == sweep->pq.max_size)) {
+ if (unlikely (! pqueue_grow (&sweep->pq))) {
+ longjmp (sweep->unwind,
+ _cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+ }
+
+ elements = sweep->pq.elements;
+ for (i = ++sweep->pq.size;
+ i != PQ_FIRST_ENTRY &&
+ rectangle_compare_stop (rectangle,
+ elements[parent = PQ_PARENT_INDEX (i)]) < 0;
+ i = parent)
+ {
+ elements[i] = elements[parent];
+ }
+
+ elements[i] = rectangle;
+}
+
+static inline void
+pqueue_pop (pqueue_t *pq)
+{
+ rectangle_t **elements = pq->elements;
+ rectangle_t *tail;
+ int child, i;
+
+ tail = elements[pq->size--];
+ if (pq->size == 0) {
+ elements[PQ_FIRST_ENTRY] = NULL;
+ return;
+ }
+
+ for (i = PQ_FIRST_ENTRY;
+ (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
+ i = child)
+ {
+ if (child != pq->size &&
+ rectangle_compare_stop (elements[child+1],
+ elements[child]) < 0)
+ {
+ child++;
+ }
+
+ if (rectangle_compare_stop (elements[child], tail) >= 0)
+ break;
+
+ elements[i] = elements[child];
+ }
+ elements[i] = tail;
+}
+
+static inline rectangle_t *
+rectangle_pop_start (sweep_line_t *sweep_line)
+{
+ return *sweep_line->rectangles++;
+}
+
+static inline rectangle_t *
+rectangle_peek_stop (sweep_line_t *sweep_line)
+{
+ return sweep_line->pq.elements[PQ_FIRST_ENTRY];
+}
+
+CAIRO_COMBSORT_DECLARE (_rectangle_sort,
+ rectangle_t *,
+ rectangle_compare_start)
+
+static void
+sweep_line_init (sweep_line_t *sweep_line,
+ rectangle_t **rectangles,
+ int num_rectangles)
+{
+ _rectangle_sort (rectangles, num_rectangles);
+ rectangles[num_rectangles] = NULL;
+ sweep_line->rectangles = rectangles;
+
+ sweep_line->head.x = INT32_MIN;
+ sweep_line->head.right = NULL;
+ sweep_line->head.dir = 0;
+ sweep_line->head.next = &sweep_line->tail;
+ sweep_line->tail.x = INT32_MAX;
+ sweep_line->tail.right = NULL;
+ sweep_line->tail.dir = 0;
+ sweep_line->tail.prev = &sweep_line->head;
+
+ sweep_line->insert_left = &sweep_line->tail;
+ sweep_line->insert_right = &sweep_line->tail;
+
+ sweep_line->current_y = INT32_MIN;
+ sweep_line->last_y = INT32_MIN;
+
+ pqueue_init (&sweep_line->pq);
+}
+
+static void
+sweep_line_fini (sweep_line_t *sweep_line)
+{
+ pqueue_fini (&sweep_line->pq);
+}
+
+static void
+end_box (sweep_line_t *sweep_line, edge_t *left, int32_t bot, cairo_boxes_t *out)
+{
+ if (likely (left->top < bot)) {
+ cairo_status_t status;
+ cairo_box_t box;
+
+ box.p1.x = left->x;
+ box.p1.y = left->top;
+ box.p2.x = left->right->x;
+ box.p2.y = bot;
+
+ status = _cairo_boxes_add (out, CAIRO_ANTIALIAS_DEFAULT, &box);
+ if (unlikely (status))
+ longjmp (sweep_line->unwind, status);
+ }
+
+ left->right = NULL;
+}
+
+/* Start a new trapezoid at the given top y coordinate, whose edges
+ * are `edge' and `edge->next'. If `edge' already has a trapezoid,
+ * then either add it to the traps in `traps', if the trapezoid's
+ * right edge differs from `edge->next', or do nothing if the new
+ * trapezoid would be a continuation of the existing one. */
+static inline void
+start_or_continue_box (sweep_line_t *sweep_line,
+ edge_t *left,
+ edge_t *right,
+ int top,
+ cairo_boxes_t *out)
+{
+ if (left->right == right)
+ return;
+
+ if (left->right != NULL) {
+ if (right != NULL && left->right->x == right->x) {
+ /* continuation on right, so just swap edges */
+ left->right = right;
+ return;
+ }
+
+ end_box (sweep_line, left, top, out);
+ }
+
+ if (right != NULL && left->x != right->x) {
+ left->top = top;
+ left->right = right;
+ }
+}
+
+static inline int is_zero(const int *winding)
+{
+ return winding[0] == 0 || winding[1] == 0;
+}
+
+static inline void
+active_edges (sweep_line_t *sweep, cairo_boxes_t *out)
+{
+ int top = sweep->current_y;
+ int winding[2] = { 0 };
+ edge_t *pos;
+
+ if (sweep->last_y == sweep->current_y)
+ return;
+
+ pos = sweep->head.next;
+ if (pos == &sweep->tail)
+ return;
+
+ do {
+ edge_t *left, *right;
+
+ left = pos;
+ do {
+ winding[left->a_or_b] += left->dir;
+ if (!is_zero (winding))
+ break;
+ if (left->next == &sweep->tail)
+ goto out;
+
+ if (unlikely (left->right != NULL))
+ end_box (sweep, left, top, out);
+
+ left = left->next;
+ } while (1);
+
+ right = left->next;
+ do {
+ if (unlikely (right->right != NULL))
+ end_box (sweep, right, top, out);
+
+ winding[right->a_or_b] += right->dir;
+ if (is_zero (winding)) {
+ /* skip co-linear edges */
+ if (likely (right->x != right->next->x))
+ break;
+ }
+
+ right = right->next;
+ } while (TRUE);
+
+ start_or_continue_box (sweep, left, right, top, out);
+
+ pos = right->next;
+ } while (pos != &sweep->tail);
+
+out:
+ sweep->last_y = sweep->current_y;
+}
+
+static inline void
+sweep_line_delete_edge (sweep_line_t *sweep_line, edge_t *edge, cairo_boxes_t *out)
+{
+ if (edge->right != NULL) {
+ edge_t *next = edge->next;
+ if (next->x == edge->x) {
+ next->top = edge->top;
+ next->right = edge->right;
+ } else {
+ end_box (sweep_line, edge, sweep_line->current_y, out);
+ }
+ }
+
+ if (sweep_line->insert_left == edge)
+ sweep_line->insert_left = edge->next;
+ if (sweep_line->insert_right == edge)
+ sweep_line->insert_right = edge->next;
+
+ edge->prev->next = edge->next;
+ edge->next->prev = edge->prev;
+}
+
+static inline void
+sweep_line_delete (sweep_line_t *sweep,
+ rectangle_t *rectangle,
+ cairo_boxes_t *out)
+{
+ sweep_line_delete_edge (sweep, &rectangle->left, out);
+ sweep_line_delete_edge (sweep, &rectangle->right, out);
+
+ pqueue_pop (&sweep->pq);
+}
+
+static inline void
+insert_edge (edge_t *edge, edge_t *pos)
+{
+ if (pos->x != edge->x) {
+ if (pos->x > edge->x) {
+ do {
+ UNROLL3({
+ if (pos->prev->x <= edge->x)
+ break;
+ pos = pos->prev;
+ })
+ } while (TRUE);
+ } else {
+ do {
+ UNROLL3({
+ pos = pos->next;
+ if (pos->x >= edge->x)
+ break;
+ })
+ } while (TRUE);
+ }
+ }
+
+ pos->prev->next = edge;
+ edge->prev = pos->prev;
+ edge->next = pos;
+ pos->prev = edge;
+}
+
+static inline void
+sweep_line_insert (sweep_line_t *sweep, rectangle_t *rectangle)
+{
+ edge_t *pos;
+
+ /* right edge */
+ pos = sweep->insert_right;
+ insert_edge (&rectangle->right, pos);
+ sweep->insert_right = &rectangle->right;
+
+ /* left edge */
+ pos = sweep->insert_left;
+ if (pos->x > sweep->insert_right->x)
+ pos = sweep->insert_right->prev;
+ insert_edge (&rectangle->left, pos);
+ sweep->insert_left = &rectangle->left;
+
+ pqueue_push (sweep, rectangle);
+}
+
+static cairo_status_t
+intersect (rectangle_t **rectangles, int num_rectangles, cairo_boxes_t *out)
+{
+ sweep_line_t sweep_line;
+ rectangle_t *rectangle;
+ cairo_status_t status;
+
+ sweep_line_init (&sweep_line, rectangles, num_rectangles);
+ if ((status = setjmp (sweep_line.unwind)))
+ goto unwind;
+
+ rectangle = rectangle_pop_start (&sweep_line);
+ do {
+ if (rectangle->top != sweep_line.current_y) {
+ rectangle_t *stop;
+
+ stop = rectangle_peek_stop (&sweep_line);
+ while (stop != NULL && stop->bottom < rectangle->top) {
+ if (stop->bottom != sweep_line.current_y) {
+ active_edges (&sweep_line, out);
+ sweep_line.current_y = stop->bottom;
+ }
+
+ sweep_line_delete (&sweep_line, stop, out);
+
+ stop = rectangle_peek_stop (&sweep_line);
+ }
+
+ active_edges (&sweep_line, out);
+ sweep_line.current_y = rectangle->top;
+ }
+
+ sweep_line_insert (&sweep_line, rectangle);
+ } while ((rectangle = rectangle_pop_start (&sweep_line)) != NULL);
+
+ while ((rectangle = rectangle_peek_stop (&sweep_line)) != NULL) {
+ if (rectangle->bottom != sweep_line.current_y) {
+ active_edges (&sweep_line, out);
+ sweep_line.current_y = rectangle->bottom;
+ }
+
+ sweep_line_delete (&sweep_line, rectangle, out);
+ }
+
+unwind:
+ sweep_line_fini (&sweep_line);
+ return status;
+}
+
+static cairo_status_t
+_cairo_boxes_intersect_with_box (const cairo_boxes_t *boxes,
+ const cairo_box_t *box,
+ cairo_boxes_t *out)
+{
+ const struct _cairo_boxes_chunk *chunk;
+ cairo_status_t status;
+ int i;
+
+ _cairo_boxes_clear (out);
+ _cairo_boxes_limit (out, box, 1);
+ for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+ for (i = 0; i < chunk->count; i++) {
+ status = _cairo_boxes_add (out,
+ CAIRO_ANTIALIAS_DEFAULT,
+ &chunk->base[i]);
+ if (unlikely (status))
+ return status;
+ }
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_boxes_intersect (const cairo_boxes_t *a,
+ const cairo_boxes_t *b,
+ cairo_boxes_t *out)
+{
+ rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)];
+ rectangle_t *rectangles;
+ rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 1];
+ rectangle_t **rectangles_ptrs;
+ const struct _cairo_boxes_chunk *chunk;
+ cairo_status_t status;
+ int i, j, count;
+
+ if (unlikely (a->num_boxes == 0 || b->num_boxes == 0)) {
+ _cairo_boxes_clear (out);
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (unlikely (a->num_boxes == 1)) {
+ cairo_box_t box = a->chunks.base[0];
+ return _cairo_boxes_intersect_with_box (b, &box, out);
+ }
+ if (unlikely (b->num_boxes == 1)) {
+ cairo_box_t box = b->chunks.base[0];
+ return _cairo_boxes_intersect_with_box (a, &box, out);
+ /* XXX */
+ }
+
+ rectangles = stack_rectangles;
+ rectangles_ptrs = stack_rectangles_ptrs;
+ count = a->num_boxes + b->num_boxes;
+ if (count > ARRAY_LENGTH (stack_rectangles)) {
+ rectangles = _cairo_malloc_ab_plus_c (count,
+ sizeof (rectangle_t) +
+ sizeof (rectangle_t *),
+ sizeof (rectangle_t *));
+ if (unlikely (rectangles == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ rectangles_ptrs = (rectangle_t **) (rectangles + count);
+ }
+
+ j = 0;
+ for (chunk = &a->chunks; chunk != NULL; chunk = chunk->next) {
+ const cairo_box_t *box = chunk->base;
+ for (i = 0; i < chunk->count; i++) {
+ if (box[i].p1.x < box[i].p2.x) {
+ rectangles[j].left.x = box[i].p1.x;
+ rectangles[j].left.dir = 1;
+
+ rectangles[j].right.x = box[i].p2.x;
+ rectangles[j].right.dir = -1;
+ } else {
+ rectangles[j].right.x = box[i].p1.x;
+ rectangles[j].right.dir = 1;
+
+ rectangles[j].left.x = box[i].p2.x;
+ rectangles[j].left.dir = -1;
+ }
+
+ rectangles[j].left.a_or_b = 0;
+ rectangles[j].left.right = NULL;
+ rectangles[j].right.a_or_b = 0;
+ rectangles[j].right.right = NULL;
+
+ rectangles[j].top = box[i].p1.y;
+ rectangles[j].bottom = box[i].p2.y;
+
+ rectangles_ptrs[j] = &rectangles[j];
+ j++;
+ }
+ }
+ for (chunk = &b->chunks; chunk != NULL; chunk = chunk->next) {
+ const cairo_box_t *box = chunk->base;
+ for (i = 0; i < chunk->count; i++) {
+ if (box[i].p1.x < box[i].p2.x) {
+ rectangles[j].left.x = box[i].p1.x;
+ rectangles[j].left.dir = 1;
+
+ rectangles[j].right.x = box[i].p2.x;
+ rectangles[j].right.dir = -1;
+ } else {
+ rectangles[j].right.x = box[i].p1.x;
+ rectangles[j].right.dir = 1;
+
+ rectangles[j].left.x = box[i].p2.x;
+ rectangles[j].left.dir = -1;
+ }
+
+ rectangles[j].left.a_or_b = 1;
+ rectangles[j].left.right = NULL;
+ rectangles[j].right.a_or_b = 1;
+ rectangles[j].right.right = NULL;
+
+ rectangles[j].top = box[i].p1.y;
+ rectangles[j].bottom = box[i].p2.y;
+
+ rectangles_ptrs[j] = &rectangles[j];
+ j++;
+ }
+ }
+ assert (j == count);
+
+ _cairo_boxes_clear (out);
+ status = intersect (rectangles_ptrs, j, out);
+ if (rectangles != stack_rectangles)
+ free (rectangles);
+
+ return status;
+}
diff --git a/src/cairo-boxes-private.h b/src/cairo-boxes-private.h
index 3af0fbd..619545f 100644
--- a/src/cairo-boxes-private.h
+++ b/src/cairo-boxes-private.h
@@ -58,6 +58,10 @@ cairo_private void
_cairo_boxes_init (cairo_boxes_t *boxes);
cairo_private void
+_cairo_boxes_init_with_clip (cairo_boxes_t *boxes,
+ cairo_clip_t *clip);
+
+cairo_private void
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
cairo_box_t *array,
int num_boxes);
@@ -69,16 +73,39 @@ _cairo_boxes_limit (cairo_boxes_t *boxes,
cairo_private cairo_status_t
_cairo_boxes_add (cairo_boxes_t *boxes,
+ cairo_antialias_t antialias,
const cairo_box_t *box);
cairo_private void
_cairo_boxes_extents (const cairo_boxes_t *boxes,
cairo_rectangle_int_t *extents);
+cairo_private cairo_box_t *
+_cairo_boxes_to_array (const cairo_boxes_t *boxes,
+ int *num_boxes,
+ cairo_bool_t force_allocation);
+
+static inline void
+_cairo_boxes_free_array (const cairo_boxes_t *boxes,
+ cairo_box_t *box)
+{
+ if (box != boxes->chunks.base)
+ free(box);
+}
+
+cairo_private cairo_status_t
+_cairo_boxes_intersect (const cairo_boxes_t *a,
+ const cairo_boxes_t *b,
+ cairo_boxes_t *out);
+
cairo_private void
_cairo_boxes_clear (cairo_boxes_t *boxes);
cairo_private void
_cairo_boxes_fini (cairo_boxes_t *boxes);
+cairo_private void
+_cairo_debug_print_boxes (FILE *stream,
+ const cairo_boxes_t *boxes);
+
#endif /* CAIRO_BOXES_H */
diff --git a/src/cairo-boxes.c b/src/cairo-boxes.c
index 31bfc0e..130a44c 100644
--- a/src/cairo-boxes.c
+++ b/src/cairo-boxes.c
@@ -53,6 +53,15 @@ _cairo_boxes_init (cairo_boxes_t *boxes)
}
void
+_cairo_boxes_init_with_clip (cairo_boxes_t *boxes,
+ cairo_clip_t *clip)
+{
+ _cairo_boxes_init (boxes);
+ if (clip)
+ _cairo_boxes_limit (boxes, clip->boxes, clip->num_boxes);
+}
+
+void
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
cairo_box_t *array,
int num_boxes)
@@ -156,8 +165,19 @@ _cairo_boxes_add_internal (cairo_boxes_t *boxes,
cairo_status_t
_cairo_boxes_add (cairo_boxes_t *boxes,
+ cairo_antialias_t antialias,
const cairo_box_t *box)
{
+ cairo_box_t b;
+
+ if (antialias == CAIRO_ANTIALIAS_NONE) {
+ b.p1.x = _cairo_fixed_round_down (box->p1.x);
+ b.p1.y = _cairo_fixed_round_down (box->p1.y);
+ b.p2.x = _cairo_fixed_round_down (box->p2.x);
+ b.p2.y = _cairo_fixed_round_down (box->p2.y);
+ box = &b;
+ }
+
if (box->p1.y == box->p2.y)
return CAIRO_STATUS_SUCCESS;
@@ -247,6 +267,11 @@ _cairo_boxes_extents (const cairo_boxes_t *boxes,
cairo_box_t box;
int i;
+ if (boxes->num_boxes == 0) {
+ extents->x = extents->y = extents->width = extents->height = 0;
+ return;
+ }
+
box.p1.y = box.p1.x = INT_MAX;
box.p2.y = box.p2.x = INT_MIN;
@@ -283,11 +308,41 @@ _cairo_boxes_clear (cairo_boxes_t *boxes)
boxes->tail = &boxes->chunks;
boxes->chunks.next = 0;
boxes->chunks.count = 0;
+ boxes->chunks.base = boxes->boxes_embedded;
+ boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded);
boxes->num_boxes = 0;
boxes->is_pixel_aligned = TRUE;
}
+cairo_box_t *
+_cairo_boxes_to_array (const cairo_boxes_t *boxes,
+ int *num_boxes,
+ cairo_bool_t force_allocation)
+{
+ const struct _cairo_boxes_chunk *chunk;
+ cairo_box_t *box;
+ int i, j;
+
+ *num_boxes = boxes->num_boxes;
+ if (boxes->chunks.next == NULL && ! force_allocation)
+ return boxes->chunks.base;
+
+ box = _cairo_malloc_ab (boxes->num_boxes, sizeof (cairo_box_t));
+ if (box == NULL) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return NULL;
+ }
+
+ j = 0;
+ for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+ for (i = 0; i < chunk->count; i++)
+ box[j++] = chunk->base[i];
+ }
+
+ return box;
+}
+
void
_cairo_boxes_fini (cairo_boxes_t *boxes)
{
@@ -298,3 +353,26 @@ _cairo_boxes_fini (cairo_boxes_t *boxes)
free (chunk);
}
}
+
+void
+_cairo_debug_print_boxes (FILE *stream, const cairo_boxes_t *boxes)
+{
+ cairo_rectangle_int_t extents;
+ const struct _cairo_boxes_chunk *chunk;
+ int i;
+
+ _cairo_boxes_extents (boxes, &extents);
+ fprintf (stream, "boxes x %d: (%d, %d) x (%d, %d)\n",
+ boxes->num_boxes,
+ extents.x, extents.y, extents.width, extents.height);
+
+ for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+ for (i = 0; i < chunk->count; i++) {
+ fprintf (stderr, " box[%d]: (%f, %f), (%f, %f)\n", i,
+ _cairo_fixed_to_double (chunk->base[i].p1.x),
+ _cairo_fixed_to_double (chunk->base[i].p1.y),
+ _cairo_fixed_to_double (chunk->base[i].p2.x),
+ _cairo_fixed_to_double (chunk->base[i].p2.y));
+ }
+ }
+}
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 1a52ca2..02f2cba 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -1373,12 +1373,12 @@ cairo_cff_find_subroutines_used (cairo_cff_font_t *font,
return cairo_cff_parse_charstring (font, charstring, length, glyph_id);
}
-static cairo_status_t
+static cairo_int_status_t
cairo_cff_font_subset_charstrings_and_subroutines (cairo_cff_font_t *font)
{
cff_index_element_t *element;
unsigned int i;
- cairo_status_t status;
+ cairo_int_status_t status;
unsigned long glyph;
font->subset_subroutines = TRUE;
@@ -1758,23 +1758,23 @@ cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
byte = 3;
status = _cairo_array_append (&font->output, &byte);
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
word = cpu_to_be16 (1);
status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
word = cpu_to_be16 (0);
status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
byte = 0;
status = _cairo_array_append (&font->output, &byte);
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
}
return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-clip-boxes.c b/src/cairo-clip-boxes.c
new file mode 100644
index 0000000..aa560ce
--- /dev/null
+++ b/src/cairo-clip-boxes.c
@@ -0,0 +1,559 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2009 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth at cworth.org>
+ * Kristian Høgsberg <krh at redhat.com>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+#include "cairo-clip-private.h"
+#include "cairo-error-private.h"
+#include "cairo-freed-pool-private.h"
+#include "cairo-gstate-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-region-private.h"
+
+static inline int
+pot (int v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return v;
+}
+
+
+static cairo_bool_t
+_cairo_clip_contains_rectangle_box (const cairo_clip_t *clip,
+ const cairo_rectangle_int_t *rect,
+ const cairo_box_t *box)
+{
+ int i;
+
+ /* clip == NULL means no clip, so the clip contains everything */
+ if (clip == NULL)
+ return TRUE;
+
+ if (_cairo_clip_is_all_clipped (clip))
+ return FALSE;
+
+ /* If we have a non-trivial path, just say no */
+ if (clip->path)
+ return FALSE;
+
+ if (clip->extents.x > rect->x ||
+ clip->extents.y > rect->y ||
+ clip->extents.x + clip->extents.width < rect->x + rect->width ||
+ clip->extents.y + clip->extents.height < rect->y + rect->height)
+ {
+ return FALSE;
+ }
+
+ /* Check for a clip-box that wholly contains the rectangle */
+ assert (clip->num_boxes);
+ for (i = 0; i < clip->num_boxes; i++) {
+ if (box->p1.x >= clip->boxes[i].p1.x &&
+ box->p1.y >= clip->boxes[i].p1.y &&
+ box->p2.x <= clip->boxes[i].p2.x &&
+ box->p2.y <= clip->boxes[i].p2.y)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+cairo_bool_t
+_cairo_clip_contains_box (const cairo_clip_t *clip,
+ const cairo_box_t *box)
+{
+ cairo_rectangle_int_t rect;
+
+ _cairo_box_round_to_rectangle (box, &rect);
+ return _cairo_clip_contains_rectangle_box(clip, &rect, box);
+}
+
+cairo_bool_t
+_cairo_clip_contains_rectangle (const cairo_clip_t *clip,
+ const cairo_rectangle_int_t *rect)
+{
+ cairo_box_t box;
+
+ box.p1.x = _cairo_fixed_from_int (rect->x);
+ box.p1.y = _cairo_fixed_from_int (rect->y);
+ box.p2.x = _cairo_fixed_from_int (rect->x + rect->width);
+ box.p2.y = _cairo_fixed_from_int (rect->y + rect->height);
+
+ return _cairo_clip_contains_rectangle_box (clip, rect, &box);
+}
+
+cairo_clip_t *
+_cairo_clip_intersect_rectilinear_path (cairo_clip_t *clip,
+ const cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias)
+{
+ cairo_status_t status;
+ cairo_boxes_t boxes;
+
+ _cairo_boxes_init (&boxes);
+ status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
+ fill_rule,
+ antialias,
+ &boxes);
+ if (likely (status == CAIRO_STATUS_SUCCESS))
+ clip = _cairo_clip_intersect_boxes (clip, &boxes);
+ else
+ clip = _cairo_clip_set_all_clipped (clip);
+ _cairo_boxes_fini (&boxes);
+
+ return clip;
+}
+
+static cairo_clip_t *
+_cairo_clip_intersect_rectangle_box (cairo_clip_t *clip,
+ const cairo_rectangle_int_t *r,
+ const cairo_box_t *box)
+{
+ cairo_box_t extents_box;
+ int i, j;
+
+ if (clip == NULL) {
+ clip = _cairo_clip_create ();
+ if (clip == NULL)
+ return _cairo_clip_set_all_clipped (clip);
+
+ clip->boxes = _cairo_malloc (sizeof (cairo_box_t));
+ if (clip->boxes == NULL)
+ return _cairo_clip_set_all_clipped (clip);
+
+ clip->extents = *r;
+ clip->num_boxes = 1;
+ clip->boxes[0] = *box;
+
+ return clip;
+ }
+
+ if (clip->num_boxes == 0) {
+ clip->boxes = _cairo_malloc (sizeof (cairo_box_t));
+ if (clip->boxes == NULL)
+ return _cairo_clip_set_all_clipped (clip);
+
+ j = 1;
+ clip->boxes[0] = *box;
+ } else for (i = j = 0; i < clip->num_boxes; i++) {
+ cairo_box_t *b = &clip->boxes[j];
+
+ if (j != i)
+ *b = clip->boxes[i];
+
+ if (box->p1.x > b->p1.x)
+ b->p1.x = box->p1.x;
+ if (box->p2.x < b->p2.x)
+ b->p2.x = box->p2.x;
+
+ if (box->p1.y > b->p1.y)
+ b->p1.y = box->p1.y;
+ if (box->p2.y < b->p2.y)
+ b->p2.y = box->p2.y;
+
+ j += b->p2.x > b->p1.x && b->p2.y > b->p1.y;
+ }
+ clip->num_boxes = j;
+
+ if (clip->num_boxes == 0)
+ return _cairo_clip_set_all_clipped (clip);
+
+ extents_box = clip->boxes[0];
+ for (i = 1; i < clip->num_boxes; i++) {
+ if (clip->boxes[i].p1.x < extents_box.p1.x)
+ extents_box.p1.x = clip->boxes[i].p1.x;
+
+ if (clip->boxes[i].p1.y < extents_box.p1.y)
+ extents_box.p1.y = clip->boxes[i].p1.y;
+
+ if (clip->boxes[i].p2.x > extents_box.p2.x)
+ extents_box.p2.x = clip->boxes[i].p2.x;
+
+ if (clip->boxes[i].p2.y > extents_box.p2.y)
+ extents_box.p2.y = clip->boxes[i].p2.y;
+ }
+
+ if (clip->path == NULL) {
+ _cairo_box_round_to_rectangle (&extents_box, &clip->extents);
+ } else {
+ cairo_rectangle_int_t extents_rect;
+
+ _cairo_box_round_to_rectangle (&extents_box, &extents_rect);
+ if (! _cairo_rectangle_intersect (&clip->extents, &extents_rect))
+ return _cairo_clip_set_all_clipped (clip);
+ }
+
+ if (clip->region) {
+ cairo_region_destroy (clip->region);
+ clip->region = NULL;
+ }
+
+ clip->is_region = FALSE;
+ return clip;
+}
+
+cairo_clip_t *
+_cairo_clip_intersect_box (cairo_clip_t *clip,
+ const cairo_box_t *box)
+{
+ cairo_rectangle_int_t r;
+
+ _cairo_box_round_to_rectangle (box, &r);
+ if (r.width == 0 || r.height == 0)
+ return _cairo_clip_set_all_clipped (clip);
+
+ return _cairo_clip_intersect_rectangle_box (clip, &r, box);
+}
+
+cairo_clip_t *
+_cairo_clip_intersect_boxes (cairo_clip_t *clip,
+ const cairo_boxes_t *boxes)
+{
+ cairo_boxes_t clip_boxes;
+ cairo_rectangle_int_t extents;
+
+ if (boxes->num_boxes == 0)
+ return clip;
+
+ if (clip == NULL)
+ clip = _cairo_clip_create ();
+
+ if (clip->num_boxes == 0) {
+ clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE);
+ _cairo_boxes_extents (boxes, &extents);
+ } else {
+ _cairo_boxes_init_for_array (&clip_boxes, clip->boxes, clip->num_boxes);
+ if (unlikely (_cairo_boxes_intersect (&clip_boxes, boxes, &clip_boxes)))
+ return _cairo_clip_set_all_clipped (clip);
+
+ free (clip->boxes);
+ clip->boxes = _cairo_boxes_to_array (&clip_boxes, &clip->num_boxes, TRUE);
+ _cairo_boxes_extents (&clip_boxes, &extents);
+ }
+
+ if (clip->path == NULL)
+ clip->extents = extents;
+ else if (! _cairo_rectangle_intersect (&clip->extents, &extents))
+ clip = _cairo_clip_set_all_clipped (clip);
+
+ if (clip->region) {
+ cairo_region_destroy (clip->region);
+ clip->region = NULL;
+ }
+ clip->is_region = FALSE;
+
+ return clip;
+}
+
+cairo_clip_t *
+_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
+ const cairo_rectangle_int_t *r)
+{
+ cairo_box_t box;
+
+ if (_cairo_clip_is_all_clipped (clip))
+ return clip;
+
+ if (r->width == 0 || r->height == 0)
+ return _cairo_clip_set_all_clipped (clip);
+
+ box.p1.x = _cairo_fixed_from_int (r->x);
+ box.p1.y = _cairo_fixed_from_int (r->y);
+ box.p2.x = _cairo_fixed_from_int (r->x + r->width);
+ box.p2.y = _cairo_fixed_from_int (r->y + r->height);
+
+ return _cairo_clip_intersect_rectangle_box (clip, r, &box);
+}
+
+struct reduce {
+ cairo_clip_t *clip;
+ cairo_box_t limit;
+ cairo_box_t extents;
+ cairo_bool_t inside;
+
+ cairo_point_t current_point;
+ cairo_point_t last_move_to;
+};
+
+static void
+_add_clipped_edge (struct reduce *r,
+ const cairo_point_t *p1,
+ const cairo_point_t *p2,
+ int y1, int y2)
+{
+ cairo_fixed_t x;
+
+ x = _cairo_edge_compute_intersection_x_for_y (p1, p2, y1);
+ if (x < r->extents.p1.x)
+ r->extents.p1.x = x;
+
+ x = _cairo_edge_compute_intersection_x_for_y (p1, p2, y2);
+ if (x > r->extents.p2.x)
+ r->extents.p2.x = x;
+
+ if (y1 < r->extents.p1.y)
+ r->extents.p1.y = y1;
+
+ if (y2 > r->extents.p2.y)
+ r->extents.p2.y = y2;
+
+ r->inside = TRUE;
+}
+
+static void
+_add_edge (struct reduce *r,
+ const cairo_point_t *p1,
+ const cairo_point_t *p2)
+{
+ int top, bottom;
+ int top_y, bot_y;
+ int n;
+
+ if (p1->y < p2->y) {
+ top = p1->y;
+ bottom = p2->y;
+ } else {
+ top = p2->y;
+ bottom = p1->y;
+ }
+
+ if (bottom < r->limit.p1.y || top > r->limit.p2.y)
+ return;
+
+ if (p1->x > p2->x) {
+ const cairo_point_t *t = p1;
+ p1 = p2;
+ p2 = t;
+ }
+
+ if (p2->x <= r->limit.p1.x || p1->x >= r->limit.p2.x)
+ return;
+
+ for (n = 0; n < r->clip->num_boxes; n++) {
+ const cairo_box_t *limits = &r->clip->boxes[n];
+
+ if (bottom < limits->p1.y || top > limits->p2.y)
+ continue;
+
+ if (p2->x <= limits->p1.x || p1->x >= limits->p2.x)
+ continue;
+
+ if (p1->x >= limits->p1.x && p2->x <= limits->p1.x) {
+ top_y = top;
+ bot_y = bottom;
+ } else {
+ int p1_y, p2_y;
+
+ p1_y = _cairo_edge_compute_intersection_y_for_x (p1, p2,
+ limits->p1.x);
+ p2_y = _cairo_edge_compute_intersection_y_for_x (p1, p2,
+ limits->p2.x);
+ if (p1_y < p2_y) {
+ top_y = p1_y;
+ bot_y = p2_y;
+ } else {
+ top_y = p2_y;
+ bot_y = p1_y;
+ }
+
+ if (top_y < top)
+ top_y = top;
+ if (bot_y > bottom)
+ bot_y = bottom;
+ }
+
+ if (top_y < limits->p1.y)
+ top_y = limits->p1.y;
+
+ if (bot_y > limits->p2.y)
+ bot_y = limits->p2.y;
+ if (bot_y > top_y)
+ _add_clipped_edge (r, p1, p2, top_y, bot_y);
+ }
+}
+
+static cairo_status_t
+_reduce_line_to (void *closure,
+ const cairo_point_t *point)
+{
+ struct reduce *r = closure;
+
+ _add_edge (r, &r->current_point, point);
+ r->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_reduce_close (void *closure)
+{
+ struct reduce *r = closure;
+
+ return _reduce_line_to (r, &r->last_move_to);
+}
+
+static cairo_status_t
+_reduce_move_to (void *closure,
+ const cairo_point_t *point)
+{
+ struct reduce *r = closure;
+ cairo_status_t status;
+
+ /* close current subpath */
+ status = _reduce_close (closure);
+
+ /* make sure that the closure represents a degenerate path */
+ r->current_point = *point;
+ r->last_move_to = *point;
+
+ return status;
+}
+
+static cairo_clip_t *
+_cairo_clip_reduce_to_boxes (cairo_clip_t *clip)
+{
+ struct reduce r;
+ cairo_clip_path_t *clip_path;
+ cairo_status_t status;
+
+ return clip;
+ if (clip->path == NULL)
+ return clip;
+
+ r.clip = clip;
+ r.extents.p1.x = r.extents.p1.y = INT_MAX;
+ r.extents.p2.x = r.extents.p2.y = INT_MIN;
+ r.inside = FALSE;
+
+ r.limit.p1.x = _cairo_fixed_from_int (clip->extents.x);
+ r.limit.p1.y = _cairo_fixed_from_int (clip->extents.y);
+ r.limit.p2.x = _cairo_fixed_from_int (clip->extents.x + clip->extents.width);
+ r.limit.p2.y = _cairo_fixed_from_int (clip->extents.y + clip->extents.height);
+
+ clip_path = clip->path;
+ do {
+ r.current_point.x = 0;
+ r.current_point.y = 0;
+ r.last_move_to = r.current_point;
+
+ status = _cairo_path_fixed_interpret_flat (&clip_path->path,
+ _reduce_move_to,
+ _reduce_line_to,
+ _reduce_close,
+ &r,
+ clip_path->tolerance);
+ assert (status == CAIRO_STATUS_SUCCESS);
+ _reduce_close (&r);
+ } while ((clip_path = clip_path->prev));
+
+ if (! r.inside) {
+ _cairo_clip_path_destroy (clip->path);
+ clip->path = NULL;
+ }
+
+ return _cairo_clip_intersect_box (clip, &r.extents);
+}
+
+cairo_clip_t *
+_cairo_clip_reduce_to_rectangle (const cairo_clip_t *clip,
+ const cairo_rectangle_int_t *r)
+{
+ cairo_clip_t *copy;
+
+ if (_cairo_clip_is_all_clipped (clip))
+ return (cairo_clip_t *) clip;
+
+ if (_cairo_clip_contains_rectangle (clip, r))
+ return _cairo_clip_intersect_rectangle (NULL, r);
+
+ copy = _cairo_clip_copy_intersect_rectangle (clip, r);
+ if (_cairo_clip_is_all_clipped (copy))
+ return copy;
+
+ return _cairo_clip_reduce_to_boxes (copy);
+}
+
+cairo_clip_t *
+_cairo_clip_reduce_for_composite (const cairo_clip_t *clip,
+ cairo_composite_rectangles_t *extents)
+{
+ const cairo_rectangle_int_t *r;
+
+ r = extents->is_bounded ? &extents->bounded : &extents->unbounded;
+ return _cairo_clip_reduce_to_rectangle (clip, r);
+}
+
+cairo_status_t
+_cairo_clip_to_boxes (cairo_clip_t *clip,
+ cairo_boxes_t *boxes)
+{
+ _cairo_boxes_init_for_array (boxes, clip->boxes, clip->num_boxes);
+
+ if (clip->path == NULL) {
+ cairo_box_t *src = clip->boxes;
+ int i;
+
+ clip->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+ if (clip->boxes == NULL) {
+ clip->boxes = src;
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ for (i = 0; i < clip->num_boxes; i++) {
+ clip->boxes[i].p1.x = _cairo_fixed_floor (src[i].p1.x);
+ clip->boxes[i].p1.y = _cairo_fixed_floor (src[i].p1.y);
+ clip->boxes[i].p2.x = _cairo_fixed_ceil (src[i].p2.x);
+ clip->boxes[i].p2.y = _cairo_fixed_ceil (src[i].p2.y);
+ }
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+
+}
diff --git a/src/cairo-clip-polygon.c b/src/cairo-clip-polygon.c
new file mode 100644
index 0000000..19da15d
--- /dev/null
+++ b/src/cairo-clip-polygon.c
@@ -0,0 +1,127 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2011 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+#include "cairo-clip-private.h"
+#include "cairo-error-private.h"
+#include "cairo-freed-pool-private.h"
+#include "cairo-gstate-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-region-private.h"
+
+static cairo_bool_t
+can_convert_to_polygon (const cairo_clip_t *clip)
+{
+ cairo_clip_path_t *clip_path = clip->path;
+ cairo_antialias_t antialias = clip_path->antialias;
+
+ while ((clip_path = clip_path->prev) != NULL) {
+ if (clip_path->antialias != antialias)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+cairo_int_status_t
+_cairo_clip_get_polygon (const cairo_clip_t *clip,
+ cairo_polygon_t *polygon,
+ cairo_fill_rule_t *fill_rule,
+ cairo_antialias_t *antialias)
+{
+ cairo_status_t status;
+ cairo_clip_path_t *clip_path;
+
+ if (_cairo_clip_is_all_clipped (clip)) {
+ _cairo_polygon_init (polygon, NULL, 0);
+ return CAIRO_INT_STATUS_SUCCESS;
+ }
+
+ /* If there is no clip, we need an infinite polygon */
+ assert (clip && (clip->path || clip->num_boxes));
+
+ if (clip->path == NULL) {
+ *fill_rule = CAIRO_FILL_RULE_WINDING;
+ *antialias = CAIRO_ANTIALIAS_DEFAULT;
+ return _cairo_polygon_init_box_array (polygon,
+ clip->boxes,
+ clip->num_boxes);
+ }
+
+ /* check that residual is all of the same type/tolerance */
+ if (! can_convert_to_polygon (clip))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ _cairo_polygon_init_with_clip (polygon, clip);
+
+ clip_path = clip->path;
+ status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
+ clip_path->tolerance,
+ polygon);
+ if (unlikely (status)) {
+ _cairo_polygon_fini (polygon);
+ return status;
+ }
+
+ polygon->limits = NULL;
+ polygon->num_limits = 0;
+
+ *fill_rule = clip_path->fill_rule;
+ *antialias = clip_path->antialias;
+ while ((clip_path = clip_path->prev) != NULL) {
+ cairo_polygon_t next;
+
+ _cairo_polygon_init (&next, NULL, 0);
+ status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
+ clip_path->tolerance,
+ &next);
+ if (likely (status == CAIRO_STATUS_SUCCESS))
+ status = _cairo_polygon_intersect (polygon, *fill_rule,
+ &next, clip_path->fill_rule);
+ _cairo_polygon_fini (&next);
+ if (unlikely (status)) {
+ _cairo_polygon_fini (polygon);
+ return status;
+ }
+
+ *fill_rule = CAIRO_FILL_RULE_WINDING;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index bfbb539..861be63 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -31,24 +31,21 @@
*
* Contributor(s):
* Kristian Høgsberg <krh at redhat.com>
+ * Chris Wilson <chris at chris-wilson.co.uk>
*/
#ifndef CAIRO_CLIP_PRIVATE_H
#define CAIRO_CLIP_PRIVATE_H
#include "cairo-types-private.h"
+
+#include "cairo-boxes-private.h"
#include "cairo-compiler-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-reference-count-private.h"
extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
-enum {
- CAIRO_CLIP_PATH_HAS_REGION = 0x1,
- CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED = 0x2,
- CAIRO_CLIP_PATH_IS_BOX = 0x4
-};
-
struct _cairo_clip_path {
cairo_reference_count_t ref_count;
cairo_path_fixed_t path;
@@ -58,92 +55,124 @@ struct _cairo_clip_path {
cairo_clip_path_t *prev;
cairo_rectangle_int_t extents;
-
- /* partial caches */
- unsigned int flags;
- cairo_region_t *region;
- cairo_surface_t *surface;
};
struct _cairo_clip {
- /* can be used as a cairo_hash_entry_t for live clips */
+ cairo_rectangle_int_t extents;
cairo_clip_path_t *path;
- cairo_bool_t all_clipped;
+ cairo_box_t *boxes;
+ int num_boxes;
+ cairo_region_t *region;
+ cairo_bool_t is_region;
};
+cairo_private cairo_clip_t *
+_cairo_clip_create (void);
+
cairo_private void
-_cairo_clip_init (cairo_clip_t *clip);
+_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
-cairo_private_no_warn cairo_clip_t *
-_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
+cairo_private void
+_cairo_clip_destroy (cairo_clip_t *clip);
-cairo_private cairo_status_t
-_cairo_clip_init_copy_transformed (cairo_clip_t *clip,
- cairo_clip_t *other,
- const cairo_matrix_t *matrix);
+extern const cairo_clip_t __cairo_clip_all;
-cairo_private void
-_cairo_clip_reset (cairo_clip_t *clip);
+static inline cairo_bool_t _cairo_clip_is_all_clipped(const cairo_clip_t *clip)
+{
+ return clip == &__cairo_clip_all;
+}
-cairo_private cairo_bool_t
-_cairo_clip_equal (const cairo_clip_t *clip_a,
- const cairo_clip_t *clip_b);
+static inline cairo_clip_t *
+_cairo_clip_set_all_clipped (cairo_clip_t *clip)
+{
+ _cairo_clip_destroy (clip);
+ return (cairo_clip_t *) &__cairo_clip_all;
+}
-#define _cairo_clip_fini(clip) _cairo_clip_reset (clip)
+cairo_private cairo_clip_t *
+_cairo_clip_copy (const cairo_clip_t *clip);
-cairo_private cairo_status_t
-_cairo_clip_rectangle (cairo_clip_t *clip,
- const cairo_rectangle_int_t *rectangle);
+cairo_private cairo_clip_t *
+_cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty);
-cairo_private cairo_status_t
-_cairo_clip_clip (cairo_clip_t *clip,
- const cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias);
+cairo_private cairo_bool_t
+_cairo_clip_equal (const cairo_clip_t *clip_a,
+ const cairo_clip_t *clip_b);
-cairo_private cairo_status_t
-_cairo_clip_apply_clip (cairo_clip_t *clip,
- const cairo_clip_t *other);
+cairo_private cairo_clip_t *
+_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
+ const cairo_rectangle_int_t *rectangle);
+
+static inline cairo_clip_t *
+_cairo_clip_copy_intersect_rectangle (const cairo_clip_t *clip,
+ const cairo_rectangle_int_t *r)
+{
+ return _cairo_clip_intersect_rectangle (_cairo_clip_copy (clip), r);
+}
+
+cairo_private cairo_clip_t *
+_cairo_clip_intersect_box (cairo_clip_t *clip,
+ const cairo_box_t *box);
+
+cairo_private cairo_clip_t *
+_cairo_clip_intersect_boxes (cairo_clip_t *clip,
+ const cairo_boxes_t *boxes);
+
+cairo_private cairo_clip_t *
+_cairo_clip_intersect_rectilinear_path (cairo_clip_t *clip,
+ const cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias);
+
+cairo_private cairo_clip_t *
+_cairo_clip_intersect_path (cairo_clip_t *clip,
+ const cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias);
cairo_private const cairo_rectangle_int_t *
_cairo_clip_get_extents (const cairo_clip_t *clip);
cairo_private cairo_surface_t *
-_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
+_cairo_clip_get_surface (const cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
cairo_private cairo_status_t
-_cairo_clip_combine_with_surface (cairo_clip_t *clip,
+_cairo_clip_combine_with_surface (const cairo_clip_t *clip,
cairo_surface_t *dst,
int dst_x, int dst_y);
-cairo_private cairo_int_status_t
-_cairo_clip_get_region (cairo_clip_t *clip,
- cairo_region_t **region);
+cairo_private cairo_status_t
+_cairo_clip_to_boxes (cairo_clip_t *clip,
+ cairo_boxes_t *boxes);
-cairo_private cairo_int_status_t
-_cairo_clip_get_boxes (cairo_clip_t *clip,
- cairo_box_t **boxes,
- int *count);
+cairo_private cairo_region_t *
+_cairo_clip_get_region (const cairo_clip_t *clip);
-cairo_private cairo_status_t
-_cairo_clip_to_boxes (cairo_clip_t **clip,
- cairo_composite_rectangles_t *extents,
- cairo_box_t **boxes,
- int *num_boxes);
+cairo_private cairo_bool_t
+_cairo_clip_is_region (const cairo_clip_t *clip);
+
+cairo_private cairo_clip_t *
+_cairo_clip_reduce_to_rectangle (const cairo_clip_t *clip,
+ const cairo_rectangle_int_t *r);
+
+cairo_private cairo_clip_t *
+_cairo_clip_reduce_for_composite (const cairo_clip_t *clip,
+ cairo_composite_rectangles_t *extents);
cairo_private cairo_bool_t
-_cairo_clip_contains_rectangle (cairo_clip_t *clip,
+_cairo_clip_contains_rectangle (const cairo_clip_t *clip,
const cairo_rectangle_int_t *rect);
cairo_private cairo_bool_t
-_cairo_clip_contains_extents (cairo_clip_t *clip,
- const cairo_composite_rectangles_t *extents);
+_cairo_clip_contains_box (const cairo_clip_t *clip,
+ const cairo_box_t *box);
-cairo_private void
-_cairo_clip_drop_cache (cairo_clip_t *clip);
+cairo_private cairo_bool_t
+_cairo_clip_contains_extents (const cairo_clip_t *clip,
+ const cairo_composite_rectangles_t *extents);
cairo_private cairo_rectangle_list_t*
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate);
@@ -151,4 +180,10 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate);
cairo_private cairo_rectangle_list_t *
_cairo_rectangle_list_create_in_error (cairo_status_t status);
+cairo_private cairo_int_status_t
+_cairo_clip_get_polygon (const cairo_clip_t *clip,
+ cairo_polygon_t *polygon,
+ cairo_fill_rule_t *fill_rule,
+ cairo_antialias_t *antialias);
+
#endif /* CAIRO_CLIP_PRIVATE_H */
diff --git a/src/cairo-clip-region.c b/src/cairo-clip-region.c
new file mode 100644
index 0000000..28a0d4b
--- /dev/null
+++ b/src/cairo-clip-region.c
@@ -0,0 +1,117 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2009 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth at cworth.org>
+ * Kristian Høgsberg <krh at redhat.com>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+#include "cairo-clip-private.h"
+#include "cairo-error-private.h"
+#include "cairo-freed-pool-private.h"
+#include "cairo-gstate-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-region-private.h"
+
+static void
+_cairo_clip_extract_region (cairo_clip_t *clip)
+{
+ cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
+ cairo_rectangle_int_t *r = stack_rects;
+ cairo_bool_t is_region;
+ int i;
+
+ if (clip->num_boxes == 0)
+ return;
+
+ if (clip->num_boxes > ARRAY_LENGTH (stack_rects)) {
+ r = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_rectangle_int_t));
+ if (r == NULL){
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return;
+ }
+ }
+
+ is_region = clip->path == NULL;
+ for (i = 0; i < clip->num_boxes; i++) {
+ cairo_box_t *b = &clip->boxes[i];
+ if (is_region)
+ is_region =
+ _cairo_fixed_is_integer (b->p1.x | b->p1.y | b->p2.x | b->p2.y);
+ r[i].x = _cairo_fixed_integer_floor (b->p1.x);
+ r[i].y = _cairo_fixed_integer_floor (b->p1.y);
+ r[i].width = _cairo_fixed_integer_ceil (b->p2.x) - r[i].x;
+ r[i].height = _cairo_fixed_integer_ceil (b->p2.y) - r[i].y;
+ }
+ clip->is_region = is_region;
+
+ clip->region = cairo_region_create_rectangles (r, i);
+
+ if (r != stack_rects)
+ free (r);
+}
+
+cairo_region_t *
+_cairo_clip_get_region (const cairo_clip_t *clip)
+{
+ if (clip == NULL)
+ return NULL;
+
+ if (clip->region == NULL)
+ _cairo_clip_extract_region ((cairo_clip_t *) clip);
+
+ return clip->region;
+}
+
+cairo_bool_t
+_cairo_clip_is_region (const cairo_clip_t *clip)
+{
+ if (clip == NULL)
+ return TRUE;
+
+ /* XXX Geometric reduction? */
+
+ if (clip->path)
+ return FALSE;
+
+ if (clip->region == NULL)
+ _cairo_clip_extract_region ((cairo_clip_t *) clip);
+
+ return clip->is_region;
+}
diff --git a/src/cairo-clip-surface.c b/src/cairo-clip-surface.c
new file mode 100644
index 0000000..79e6a62
--- /dev/null
+++ b/src/cairo-clip-surface.c
@@ -0,0 +1,142 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 Red Hat, Inc.
+ * Copyright © 2009 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth at cworth.org>
+ * Kristian Høgsberg <krh at redhat.com>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+#include "cairo-clip-private.h"
+#include "cairo-error-private.h"
+#include "cairo-freed-pool-private.h"
+#include "cairo-gstate-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-pattern-private.h"
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-region-private.h"
+
+cairo_status_t
+_cairo_clip_combine_with_surface (const cairo_clip_t *clip,
+ cairo_surface_t *dst,
+ int dst_x, int dst_y)
+{
+ cairo_clip_path_t *clip_path;
+ cairo_clip_path_t *copy_path;
+ cairo_clip_t *copy;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ copy = _cairo_clip_copy_with_translation (clip, -dst_x, -dst_y);
+ copy_path = copy->path;
+ copy->path = NULL;
+
+ if (copy_path == NULL) {
+ assert (copy->num_boxes);
+ status = _cairo_surface_paint (dst,
+ CAIRO_OPERATOR_IN,
+ &_cairo_pattern_white.base,
+ copy);
+ }
+
+ clip_path = copy_path;
+ while (status == CAIRO_STATUS_SUCCESS && clip_path) {
+ status = _cairo_surface_fill (dst,
+ CAIRO_OPERATOR_IN,
+ &_cairo_pattern_white.base,
+ &clip_path->path,
+ clip_path->fill_rule,
+ clip_path->tolerance,
+ clip_path->antialias,
+ copy);
+ clip_path = clip_path->prev;
+ }
+
+ copy->path = copy_path;
+ _cairo_clip_destroy (copy);
+ return status;
+}
+
+cairo_surface_t *
+_cairo_clip_get_surface (const cairo_clip_t *clip,
+ cairo_surface_t *target,
+ int *tx, int *ty)
+{
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ cairo_clip_t *copy;
+ cairo_clip_path_t *copy_path, *clip_path;
+
+ surface = _cairo_surface_create_similar_solid (target,
+ CAIRO_CONTENT_ALPHA,
+ clip->extents.width,
+ clip->extents.height,
+ CAIRO_COLOR_TRANSPARENT,
+ TRUE);
+ if (unlikely (surface->status))
+ return surface;
+
+ copy = _cairo_clip_copy_with_translation (clip,
+ -clip->extents.x,
+ -clip->extents.y);
+ copy_path = copy->path;
+ copy->path = NULL;
+
+ assert (copy->num_boxes);
+ status = _cairo_surface_paint (surface,
+ CAIRO_OPERATOR_ADD,
+ &_cairo_pattern_white.base,
+ copy);
+
+ clip_path = copy_path;
+ while (status == CAIRO_STATUS_SUCCESS && clip_path) {
+ status = _cairo_surface_fill (surface,
+ CAIRO_OPERATOR_IN,
+ &_cairo_pattern_white.base,
+ &clip_path->path,
+ clip_path->fill_rule,
+ clip_path->tolerance,
+ clip_path->antialias,
+ copy);
+ clip_path = clip_path->prev;
+ }
+
+ copy->path = copy_path;
+ _cairo_clip_destroy (copy);
+
+ *tx = clip->extents.x;
+ *ty = clip->extents.y;
+ return surface;
+}
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 9054b4e..99d7cd4 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -50,6 +50,16 @@
#include "cairo-region-private.h"
static freed_pool_t clip_path_pool;
+static freed_pool_t clip_pool;
+
+const cairo_clip_t __cairo_clip_all;
+
+static const cairo_rectangle_int_t _cairo_empty_rectangle = { 0, 0, 0, 0 };
+static const cairo_rectangle_int_t _cairo_unbounded_rectangle = {
+ CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN,
+ CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
+ CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
+};
static cairo_clip_path_t *
_cairo_clip_path_create (cairo_clip_t *clip)
@@ -65,10 +75,6 @@ _cairo_clip_path_create (cairo_clip_t *clip)
CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
- clip_path->flags = 0;
- clip_path->region = NULL;
- clip_path->surface = NULL;
-
clip_path->prev = clip->path;
clip->path = clip_path;
@@ -85,7 +91,7 @@ _cairo_clip_path_reference (cairo_clip_path_t *clip_path)
return clip_path;
}
-static void
+void
_cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
{
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
@@ -94,10 +100,6 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
return;
_cairo_path_fixed_fini (&clip_path->path);
- if (clip_path->region != NULL)
- cairo_region_destroy (clip_path->region);
- if (clip_path->surface != NULL)
- cairo_surface_destroy (clip_path->surface);
if (clip_path->prev != NULL)
_cairo_clip_path_destroy (clip_path->prev);
@@ -105,115 +107,75 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
_freed_pool_put (&clip_path_pool, clip_path);
}
-void
-_cairo_clip_init (cairo_clip_t *clip)
+cairo_clip_t *
+_cairo_clip_create (void)
{
- clip->all_clipped = FALSE;
+ cairo_clip_t *clip;
+
+ clip = _freed_pool_get (&clip_pool);
+ if (unlikely (clip == NULL)) {
+ clip = malloc (sizeof (cairo_clip_t));
+ if (unlikely (clip == NULL))
+ return NULL;
+ }
+
+ clip->extents = _cairo_unbounded_rectangle;
+
clip->path = NULL;
+ clip->boxes = NULL;
+ clip->num_boxes = 0;
+ clip->region = NULL;
+ clip->is_region = FALSE;
+
+ return clip;
}
-static void
-_cairo_clip_set_all_clipped (cairo_clip_t *clip)
+void
+_cairo_clip_destroy (cairo_clip_t *clip)
{
- clip->all_clipped = TRUE;
- if (clip->path != NULL) {
+ if (clip == NULL || _cairo_clip_is_all_clipped (clip))
+ return;
+
+ if (clip->path != NULL)
_cairo_clip_path_destroy (clip->path);
- clip->path = NULL;
- }
+
+ free (clip->boxes);
+ cairo_region_destroy (clip->region);
+
+ _freed_pool_put (&clip_pool, clip);
}
-static cairo_status_t
-_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
- const cairo_rectangle_int_t *rect)
+cairo_clip_t *
+_cairo_clip_copy (const cairo_clip_t *clip)
{
- cairo_clip_path_t *clip_path;
- cairo_status_t status;
+ cairo_clip_t *copy;
- if (clip->path != NULL) {
- if (rect->x <= clip->path->extents.x &&
- rect->y <= clip->path->extents.y &&
- rect->x + rect->width >= clip->path->extents.x + clip->path->extents.width &&
- rect->y + rect->height >= clip->path->extents.y + clip->path->extents.height)
- {
- return CAIRO_STATUS_SUCCESS;
- }
- }
+ if (clip == NULL || _cairo_clip_is_all_clipped (clip))
+ return (cairo_clip_t *) clip;
- clip_path = _cairo_clip_path_create (clip);
- if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_path_fixed_init (&clip_path->path);
-
- status = _cairo_path_fixed_move_to (&clip_path->path,
- _cairo_fixed_from_int (rect->x),
- _cairo_fixed_from_int (rect->y));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_rel_line_to (&clip_path->path,
- _cairo_fixed_from_int (rect->width),
- _cairo_fixed_from_int (0));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_rel_line_to (&clip_path->path,
- _cairo_fixed_from_int (0),
- _cairo_fixed_from_int (rect->height));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_rel_line_to (&clip_path->path,
- _cairo_fixed_from_int (-rect->width),
- _cairo_fixed_from_int (0));
- assert (status == CAIRO_STATUS_SUCCESS);
- status = _cairo_path_fixed_close_path (&clip_path->path);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- clip_path->fill_rule = CAIRO_FILL_RULE_WINDING;
- clip_path->tolerance = 1;
- clip_path->antialias = CAIRO_ANTIALIAS_DEFAULT;
- clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
-
- clip_path->extents = *rect;
- if (clip_path->prev != NULL) {
- if (! _cairo_rectangle_intersect (&clip_path->extents,
- &clip_path->prev->extents))
- {
- _cairo_clip_set_all_clipped (clip);
- }
- }
+ copy = _cairo_clip_create ();
- /* could preallocate the region if it proves worthwhile */
+ if (clip->path)
+ copy->path = _cairo_clip_path_reference (clip->path);
- return CAIRO_STATUS_SUCCESS;
-}
+ if (clip->num_boxes) {
+ copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+ if (unlikely (copy->boxes == NULL))
+ return _cairo_clip_set_all_clipped (copy);
-cairo_clip_t *
-_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
-{
- if (other != NULL) {
- clip->all_clipped = other->all_clipped;
- if (other->path == NULL) {
- clip->path = NULL;
- if (! clip->all_clipped)
- clip = NULL;
- } else {
- clip->path = _cairo_clip_path_reference (other->path);
- }
- } else {
- _cairo_clip_init (clip);
- clip = NULL;
+ memcpy (copy->boxes, clip->boxes,
+ clip->num_boxes * sizeof (cairo_box_t));
+ copy->num_boxes = clip->num_boxes;
}
- return clip;
-}
+ copy->extents = clip->extents;
+ copy->region = cairo_region_reference (clip->region);
+ copy->is_region = clip->is_region;
-void
-_cairo_clip_reset (cairo_clip_t *clip)
-{
- clip->all_clipped = FALSE;
- if (clip->path != NULL) {
- _cairo_clip_path_destroy (clip->path);
- clip->path = NULL;
- }
+ return copy;
}
-static cairo_status_t
+cairo_clip_t *
_cairo_clip_intersect_path (cairo_clip_t *clip,
const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
@@ -224,928 +186,147 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
cairo_status_t status;
cairo_rectangle_int_t extents;
cairo_box_t box;
- cairo_bool_t is_box = FALSE;
-
- if (clip->path != NULL) {
- if (clip->path->fill_rule == fill_rule &&
- (_cairo_path_fixed_fill_is_rectilinear (path) || tolerance == clip->path->tolerance) &&
- antialias == clip->path->antialias &&
- _cairo_path_fixed_equal (&clip->path->path, path))
- {
- return CAIRO_STATUS_SUCCESS;
+
+ if (_cairo_clip_is_all_clipped (clip))
+ return clip;
+
+ /* catch the empty clip path */
+ if (_cairo_path_fixed_fill_is_empty (path))
+ return _cairo_clip_set_all_clipped (clip);
+
+ if (_cairo_path_fixed_is_box (path, &box)) {
+ if (antialias == CAIRO_ANTIALIAS_NONE) {
+ box.p1.x = _cairo_fixed_round_down (box.p1.x);
+ box.p1.y = _cairo_fixed_round_down (box.p1.y);
+ box.p2.x = _cairo_fixed_round_down (box.p2.x);
+ box.p2.y = _cairo_fixed_round_down (box.p2.y);
}
+
+ return _cairo_clip_intersect_box (clip, &box);
}
+ if (_cairo_path_fixed_fill_is_rectilinear (path))
+ return _cairo_clip_intersect_rectilinear_path (clip, path,
+ fill_rule, antialias);
_cairo_path_fixed_approximate_clip_extents (path, &extents);
- if (extents.width == 0 || extents.height == 0) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
+ if (extents.width == 0 || extents.height == 0)
+ return _cairo_clip_set_all_clipped (clip);
- is_box = _cairo_path_fixed_is_box (path, &box);
- if (clip->path != NULL) {
- if (! _cairo_rectangle_intersect (&extents, &clip->path->extents)) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
+ if (clip && ! _cairo_rectangle_intersect (&clip->extents, &extents))
+ return _cairo_clip_set_all_clipped (clip);
- /* does this clip wholly subsume the others? */
- if (is_box &&
- box.p1.x <= _cairo_fixed_from_int (clip->path->extents.x) &&
- box.p2.x >= _cairo_fixed_from_int (clip->path->extents.x + clip->path->extents.width) &&
- box.p1.y <= _cairo_fixed_from_int (clip->path->extents.y) &&
- box.p2.y >= _cairo_fixed_from_int (clip->path->extents.y + clip->path->extents.height))
- {
- return CAIRO_STATUS_SUCCESS;
- }
+ if (clip == NULL) {
+ clip = _cairo_clip_create ();
+ if (unlikely (clip == NULL))
+ return _cairo_clip_set_all_clipped (clip);
+
+ clip->extents = extents;
}
clip_path = _cairo_clip_path_create (clip);
if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return _cairo_clip_set_all_clipped (clip);
status = _cairo_path_fixed_init_copy (&clip_path->path, path);
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
+ if (unlikely (status))
+ return _cairo_clip_set_all_clipped (clip);
- clip_path->extents = extents;
clip_path->fill_rule = fill_rule;
clip_path->tolerance = tolerance;
clip_path->antialias = antialias;
- if (is_box)
- clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
- return CAIRO_STATUS_SUCCESS;
+ clip->is_region = FALSE;
+ return clip;
}
cairo_bool_t
_cairo_clip_equal (const cairo_clip_t *clip_a,
const cairo_clip_t *clip_b)
{
- const cairo_clip_path_t *clip_path_a, *clip_path_b;
-
- clip_path_a = clip_a->path;
- clip_path_b = clip_b->path;
-
- while (clip_path_a && clip_path_b) {
- if (clip_path_a == clip_path_b)
- return TRUE;
-
- if (clip_path_a->fill_rule != clip_path_b->fill_rule)
- return FALSE;
-
- if (clip_path_a->tolerance != clip_path_b->tolerance)
- return FALSE;
-
- if (clip_path_a->antialias != clip_path_b->antialias)
- return FALSE;
-
- if (! _cairo_path_fixed_equal (&clip_path_a->path, &clip_path_b->path))
- return FALSE;
-
- clip_path_a = clip_path_a->prev;
- clip_path_b = clip_path_b->prev;
- }
-
- return clip_path_a == clip_path_b; /* ie both NULL */
-}
-
-cairo_status_t
-_cairo_clip_clip (cairo_clip_t *clip,
- const cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias)
-{
- if (clip->all_clipped)
- return CAIRO_STATUS_SUCCESS;
-
- /* catch the empty clip path */
- if (_cairo_path_fixed_fill_is_empty (path)) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- return _cairo_clip_intersect_path (clip,
- path, fill_rule, tolerance,
- antialias);
-}
-
-cairo_status_t
-_cairo_clip_rectangle (cairo_clip_t *clip,
- const cairo_rectangle_int_t *rectangle)
-{
- if (clip->all_clipped)
- return CAIRO_STATUS_SUCCESS;
-
- if (rectangle->width == 0 || rectangle->height == 0) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- /* if a smaller clip has already been set, ignore the new path */
- if (clip->path != NULL) {
- if (rectangle->x <= clip->path->extents.x &&
- rectangle->y <= clip->path->extents.y &&
- rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
- rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
- {
- return CAIRO_STATUS_SUCCESS;
- }
- }
-
- return _cairo_clip_intersect_rectangle (clip, rectangle);
-}
-
-static cairo_status_t
-_cairo_clip_path_reapply_clip_path_transform (cairo_clip_t *clip,
- cairo_clip_path_t *other_path,
- const cairo_matrix_t *matrix)
-{
- cairo_status_t status;
- cairo_clip_path_t *clip_path;
-
- if (other_path->prev != NULL) {
- status = _cairo_clip_path_reapply_clip_path_transform (clip,
- other_path->prev,
- matrix);
- if (unlikely (status))
- return status;
- }
-
- clip_path = _cairo_clip_path_create (clip);
- if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- status = _cairo_path_fixed_init_copy (&clip_path->path,
- &other_path->path);
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
-
- _cairo_path_fixed_transform (&clip_path->path, matrix);
- _cairo_path_fixed_approximate_clip_extents (&clip_path->path,
- &clip_path->extents);
- if (clip_path->prev != NULL) {
- _cairo_rectangle_intersect (&clip_path->extents,
- &clip_path->prev->extents);
- }
-
- clip_path->fill_rule = other_path->fill_rule;
- clip_path->tolerance = other_path->tolerance;
- clip_path->antialias = other_path->antialias;
+ /* are both all-clipped or no-clip? */
+ if (clip_a == clip_b)
+ return TRUE;
- return CAIRO_STATUS_SUCCESS;
+ return FALSE;
}
-static cairo_status_t
-_cairo_clip_path_reapply_clip_path_translate (cairo_clip_t *clip,
- cairo_clip_path_t *other_path,
- int tx, int ty)
+static cairo_clip_t *
+_cairo_clip_path_copy_with_translation (cairo_clip_t *clip,
+ cairo_clip_path_t *other_path,
+ int fx, int fy)
{
cairo_status_t status;
cairo_clip_path_t *clip_path;
- if (other_path->prev != NULL) {
- status = _cairo_clip_path_reapply_clip_path_translate (clip,
- other_path->prev,
- tx, ty);
- if (unlikely (status))
- return status;
- }
+ if (other_path->prev != NULL)
+ clip = _cairo_clip_path_copy_with_translation (clip, other_path->prev,
+ fx, fy);
+ if (_cairo_clip_is_all_clipped (clip))
+ return clip;
clip_path = _cairo_clip_path_create (clip);
if (unlikely (clip_path == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return _cairo_clip_set_all_clipped (clip);
status = _cairo_path_fixed_init_copy (&clip_path->path,
&other_path->path);
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
+ if (unlikely (status))
+ return _cairo_clip_set_all_clipped (clip);
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (tx),
- _cairo_fixed_from_int (ty));
+ _cairo_path_fixed_translate (&clip_path->path, fx, fy);
clip_path->fill_rule = other_path->fill_rule;
clip_path->tolerance = other_path->tolerance;
clip_path->antialias = other_path->antialias;
- clip_path->flags = other_path->flags;
- if (other_path->region != NULL) {
- clip_path->region = cairo_region_copy (other_path->region);
- status = clip_path->region->status;
- if (unlikely (status)) {
- clip->path = clip->path->prev;
- _cairo_clip_path_destroy (clip_path);
- return status;
- }
-
- cairo_region_translate (clip_path->region, tx, ty);
- }
- clip_path->surface = cairo_surface_reference (other_path->surface);
-
- clip_path->extents = other_path->extents;
- clip_path->extents.x += tx;
- clip_path->extents.y += ty;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_clip_init_copy_transformed (cairo_clip_t *clip,
- cairo_clip_t *other,
- const cairo_matrix_t *matrix)
-{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- int tx, ty;
-
- if (other == NULL) {
- _cairo_clip_init (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (other->all_clipped) {
- _cairo_clip_init (clip);
- clip->all_clipped = TRUE;
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (_cairo_matrix_is_identity (matrix)) {
- _cairo_clip_init_copy (clip, other);
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (other->path != NULL) {
- _cairo_clip_init (clip);
-
- /* if we only need to translate, so we can reuse the caches... */
- /* XXX we still loose the benefit of constructs when the copy is
- * deleted though. Indirect clip_paths?
- */
- if (_cairo_matrix_is_integer_translation (matrix, &tx, &ty)) {
- status = _cairo_clip_path_reapply_clip_path_translate (clip,
- other->path,
- tx, ty);
- } else {
- status = _cairo_clip_path_reapply_clip_path_transform (clip,
- other->path,
- matrix);
- if (clip->path->extents.width == 0 &&
- clip->path->extents.height == 0)
- {
- _cairo_clip_set_all_clipped (clip);
- }
- }
- }
-
- return status;
-}
-
-static cairo_status_t
-_cairo_clip_apply_clip_path (cairo_clip_t *clip,
- const cairo_clip_path_t *path)
-{
- if (path->prev != NULL) {
- cairo_status_t status;
-
- status = _cairo_clip_apply_clip_path (clip, path->prev);
- if (unlikely (status))
- return status;
- }
-
- return _cairo_clip_intersect_path (clip,
- &path->path,
- path->fill_rule,
- path->tolerance,
- path->antialias);
-}
-
-cairo_status_t
-_cairo_clip_apply_clip (cairo_clip_t *clip,
- const cairo_clip_t *other)
-{
- cairo_status_t status;
-
- if (clip->all_clipped)
- return CAIRO_STATUS_SUCCESS;
-
- if (other->all_clipped) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- status = CAIRO_STATUS_SUCCESS;
- if (other->path != NULL)
- status = _cairo_clip_apply_clip_path (clip, other->path);
-
- return status;
-}
-
-static inline cairo_bool_t
-_clip_paths_are_rectilinear (cairo_clip_path_t *clip_path)
-{
- while (clip_path != NULL) {
- if (! _cairo_path_fixed_fill_is_rectilinear (&clip_path->path))
- return FALSE;
-
- clip_path = clip_path->prev;
- }
-
- return TRUE;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_region_geometric (cairo_clip_path_t *clip_path)
-{
- cairo_traps_t traps;
- cairo_box_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_t)];
- cairo_box_t *boxes = stack_boxes;
- cairo_status_t status;
- int n;
-
- /* If we have nothing to intersect with this path, then it cannot
- * magically be reduced into a region.
- */
- if (clip_path->prev == NULL)
- goto UNSUPPORTED;
-
- /* Start simple... Intersect some boxes with an arbitrary path. */
- if (! _cairo_path_fixed_fill_is_rectilinear (&clip_path->path))
- goto UNSUPPORTED;
- if (clip_path->prev->prev != NULL)
- goto UNSUPPORTED;
-
- _cairo_traps_init (&traps);
- _cairo_box_from_rectangle (&boxes[0], &clip_path->extents);
- _cairo_traps_limit (&traps, boxes, 1);
-
- status = _cairo_path_fixed_fill_rectilinear_to_traps (&clip_path->path,
- clip_path->fill_rule,
- &traps);
- if (unlikely (_cairo_status_is_error (status)))
- return status;
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- goto UNSUPPORTED;
-
- if (traps.num_traps > ARRAY_LENGTH (stack_boxes)) {
- boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
- if (unlikely (boxes == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- for (n = 0; n < traps.num_traps; n++) {
- boxes[n].p1.x = traps.traps[n].left.p1.x;
- boxes[n].p1.y = traps.traps[n].top;
- boxes[n].p2.x = traps.traps[n].right.p1.x;
- boxes[n].p2.y = traps.traps[n].bottom;
- }
-
- _cairo_traps_clear (&traps);
- _cairo_traps_limit (&traps, boxes, n);
- status = _cairo_path_fixed_fill_to_traps (&clip_path->prev->path,
- clip_path->prev->fill_rule,
- clip_path->prev->tolerance,
- &traps);
- if (boxes != stack_boxes)
- free (boxes);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_traps_extract_region (&traps, &clip_path->region);
- _cairo_traps_fini (&traps);
-
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- goto UNSUPPORTED;
- if (unlikely (status))
- return status;
-
- clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
- return CAIRO_STATUS_SUCCESS;
-
-UNSUPPORTED:
- clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_region (cairo_clip_path_t *clip_path)
-{
- cairo_int_status_t status;
- cairo_region_t *prev = NULL;
-
- if (clip_path->flags &
- (CAIRO_CLIP_PATH_HAS_REGION |
- CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED))
- {
- return clip_path->flags & CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED ?
- CAIRO_INT_STATUS_UNSUPPORTED :
- CAIRO_STATUS_SUCCESS;
- }
-
- if (! _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- return _cairo_clip_path_to_region_geometric (clip_path);
-
- /* first retrieve the region for our antecedents */
- if (clip_path->prev != NULL) {
- status = _cairo_clip_path_to_region (clip_path->prev);
- if (status) {
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- return _cairo_clip_path_to_region_geometric (clip_path);
-
- return status;
- }
-
- prev = clip_path->prev->region;
- }
-
- /* now extract the region for ourselves */
- clip_path->region =
- _cairo_path_fixed_fill_rectilinear_to_region (&clip_path->path,
- clip_path->fill_rule,
- &clip_path->extents);
- assert (clip_path->region != NULL);
-
- status = clip_path->region->status;
- if (unlikely (status))
- return status;
-
- if (prev != NULL) {
- status = cairo_region_intersect (clip_path->region, prev);
- if (unlikely (status))
- return status;
- }
-
- clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static inline int
-pot (int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
- return v;
-}
-
-/* XXX there is likely a faster method! ;-) */
-static cairo_status_t
-_region_clip_to_boxes (const cairo_region_t *region,
- cairo_box_t **boxes,
- int *num_boxes,
- int *size_boxes)
-{
- cairo_traps_t traps;
- cairo_status_t status;
- int n, num_rects;
-
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, *boxes, *num_boxes);
- traps.is_rectilinear = TRUE;
- traps.is_rectangular = TRUE;
-
- num_rects = cairo_region_num_rectangles (region);
- for (n = 0; n < num_rects; n++) {
- cairo_rectangle_int_t rect;
- cairo_point_t p1, p2;
-
- cairo_region_get_rectangle (region, n, &rect);
-
- p1.x = _cairo_fixed_from_int (rect.x);
- p1.y = _cairo_fixed_from_int (rect.y);
- p2.x = _cairo_fixed_from_int (rect.x + rect.width);
- p2.y = _cairo_fixed_from_int (rect.y + rect.height);
-
- status = _cairo_traps_tessellate_rectangle (&traps, &p1, &p2);
- if (unlikely (status))
- goto CLEANUP;
- }
-
- status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps, CAIRO_FILL_RULE_WINDING);
- if (unlikely (status))
- goto CLEANUP;
-
- n = *size_boxes;
- if (n < 0)
- n = -n;
-
- if (traps.num_traps > n) {
- cairo_box_t *new_boxes;
-
- new_boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
- if (unlikely (new_boxes == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP;
- }
-
- if (*size_boxes > 0)
- free (*boxes);
-
- *boxes = new_boxes;
- *size_boxes = traps.num_traps;
- }
-
- for (n = 0; n < traps.num_traps; n++) {
- (*boxes)[n].p1.x = traps.traps[n].left.p1.x;
- (*boxes)[n].p1.y = traps.traps[n].top;
- (*boxes)[n].p2.x = traps.traps[n].right.p1.x;
- (*boxes)[n].p2.y = traps.traps[n].bottom;
- }
- *num_boxes = n;
-
- CLEANUP:
- _cairo_traps_fini (&traps);
-
- return status;
-}
-
-static cairo_status_t
-_rectilinear_clip_to_boxes (const cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- cairo_box_t **boxes,
- int *num_boxes,
- int *size_boxes)
-{
- cairo_polygon_t polygon;
- cairo_traps_t traps;
- cairo_status_t status;
-
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, *boxes, *num_boxes);
-
- _cairo_polygon_init (&polygon, *boxes, *num_boxes);
-
- status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
- fill_rule,
- &traps);
- if (unlikely (_cairo_status_is_error (status)))
- goto CLEANUP;
- if (status == CAIRO_STATUS_SUCCESS)
- goto BOXES;
-
- /* tolerance will be ignored as the path is rectilinear */
- status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
- if (unlikely (status))
- goto CLEANUP;
-
- if (polygon.num_edges == 0) {
- *num_boxes = 0;
- } else {
- status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
- &polygon,
- fill_rule);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
- int i;
-
- BOXES:
- i = *size_boxes;
- if (i < 0)
- i = -i;
-
- if (traps.num_traps > i) {
- cairo_box_t *new_boxes;
- int new_size;
-
- new_size = pot (traps.num_traps);
- new_boxes = _cairo_malloc_ab (new_size, sizeof (cairo_box_t));
- if (unlikely (new_boxes == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP;
- }
-
- if (*size_boxes > 0)
- free (*boxes);
-
- *boxes = new_boxes;
- *size_boxes = new_size;
- }
-
- for (i = 0; i < traps.num_traps; i++) {
- (*boxes)[i].p1.x = traps.traps[i].left.p1.x;
- (*boxes)[i].p1.y = traps.traps[i].top;
- (*boxes)[i].p2.x = traps.traps[i].right.p1.x;
- (*boxes)[i].p2.y = traps.traps[i].bottom;
- }
- *num_boxes = i;
- }
- }
-
- CLEANUP:
- _cairo_polygon_fini (&polygon);
- _cairo_traps_fini (&traps);
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
- cairo_box_t **boxes,
- int *count)
-{
- int size = -*count;
- int num_boxes = 0;
- cairo_status_t status;
-
- if (clip_path->region != NULL) {
- int num_rects, n;
-
- num_rects = cairo_region_num_rectangles (clip_path->region);
- if (num_rects > -size) {
- cairo_box_t *new_boxes;
-
- new_boxes = _cairo_malloc_ab (num_rects, sizeof (cairo_box_t));
- if (unlikely (new_boxes == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- *boxes = new_boxes;
- }
-
- for (n = 0; n < num_rects; n++) {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (clip_path->region, n, &rect);
- (*boxes)[n].p1.x = _cairo_fixed_from_int (rect.x);
- (*boxes)[n].p1.y = _cairo_fixed_from_int (rect.y);
- (*boxes)[n].p2.x = _cairo_fixed_from_int (rect.x + rect.width);
- (*boxes)[n].p2.y = _cairo_fixed_from_int (rect.y + rect.height);
- }
-
- *count = num_rects;
- return CAIRO_STATUS_SUCCESS;
- }
-
- /* keep it simple at first */
- if (! _clip_paths_are_rectilinear (clip_path))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- assert (-size >= 1);
- if (_cairo_path_fixed_is_box (&clip_path->path, *boxes)) {
- num_boxes = 1;
- } else {
- status = _rectilinear_clip_to_boxes (&clip_path->path,
- clip_path->fill_rule,
- boxes, &num_boxes, &size);
- if (unlikely (status))
- return status;
- }
-
- while (num_boxes > 0 && (clip_path = clip_path->prev) != NULL) {
- cairo_box_t box;
-
- if (clip_path->region != NULL) {
- status = _region_clip_to_boxes (clip_path->region,
- boxes, &num_boxes, &size);
- if (unlikely (status))
- return status;
-
- break;
- } else if (_cairo_path_fixed_is_box (&clip_path->path, &box)) {
- int i, j;
-
- for (i = j = 0; i < num_boxes; i++) {
- if (j != i)
- (*boxes)[j] = (*boxes)[i];
-
- if (box.p1.x > (*boxes)[j].p1.x)
- (*boxes)[j].p1.x = box.p1.x;
- if (box.p2.x < (*boxes)[j].p2.x)
- (*boxes)[j].p2.x = box.p2.x;
-
- if (box.p1.y > (*boxes)[j].p1.y)
- (*boxes)[j].p1.y = box.p1.y;
- if (box.p2.y < (*boxes)[j].p2.y)
- (*boxes)[j].p2.y = box.p2.y;
-
- j += (*boxes)[j].p2.x > (*boxes)[j].p1.x &&
- (*boxes)[j].p2.y > (*boxes)[j].p1.y;
- }
-
- num_boxes = j;
- } else {
- status = _rectilinear_clip_to_boxes (&clip_path->path,
- clip_path->fill_rule,
- boxes, &num_boxes, &size);
- if (unlikely (status))
- return status;
- }
- }
-
- *count = num_boxes;
- return CAIRO_STATUS_SUCCESS;
+ return clip;
}
-static cairo_surface_t *
-_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
- cairo_surface_t *target,
- int *tx, int *ty)
+cairo_clip_t *
+_cairo_clip_copy_with_translation (const cairo_clip_t *clip, int tx, int ty)
{
- const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
- cairo_bool_t need_translate;
- cairo_surface_t *surface;
- cairo_clip_path_t *prev;
- cairo_status_t status;
+ cairo_clip_t *copy;
+ int fx, fy, i;
- while (clip_path->prev != NULL &&
- clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- {
- clip_path = clip_path->prev;
- }
+ if (clip == NULL || _cairo_clip_is_all_clipped (clip))
+ return (cairo_clip_t *)clip;
- clip_extents = &clip_path->extents;
- if (clip_path->surface != NULL &&
- clip_path->surface->backend == target->backend)
- {
- *tx = clip_extents->x;
- *ty = clip_extents->y;
- return clip_path->surface;
- }
+ if (tx == 0 && ty == 0)
+ return _cairo_clip_copy (clip);
- surface = _cairo_surface_create_similar_scratch (target,
- CAIRO_CONTENT_ALPHA,
- clip_extents->width,
- clip_extents->height);
- if (surface == NULL) {
- surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
- clip_extents->width,
- clip_extents->height);
- }
- if (unlikely (surface->status))
- return surface;
-
- need_translate = clip_extents->x | clip_extents->y;
- if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- {
- status = _cairo_surface_paint (surface,
- CAIRO_OPERATOR_SOURCE,
- &_cairo_pattern_white.base,
- NULL);
- if (unlikely (status))
- goto BAIL;
- }
- else
- {
- status = _cairo_surface_paint (surface,
- CAIRO_OPERATOR_CLEAR,
- &_cairo_pattern_clear.base,
- NULL);
- if (unlikely (status))
- goto BAIL;
-
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (-clip_extents->x),
- _cairo_fixed_from_int (-clip_extents->y));
- }
- status = _cairo_surface_fill (surface,
- CAIRO_OPERATOR_ADD,
- &_cairo_pattern_white.base,
- &clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- clip_path->antialias,
- NULL);
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (clip_extents->x),
- _cairo_fixed_from_int (clip_extents->y));
- }
+ copy = _cairo_clip_create ();
+ if (copy == NULL)
+ return _cairo_clip_set_all_clipped (copy);
- if (unlikely (status))
- goto BAIL;
- }
+ fx = _cairo_fixed_from_int (tx);
+ fy = _cairo_fixed_from_int (ty);
- prev = clip_path->prev;
- while (prev != NULL) {
- if (prev->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&prev->path))
- {
- /* a simple box only affects the extents */
- }
- else if (_cairo_path_fixed_fill_is_rectilinear (&prev->path) ||
- prev->surface == NULL ||
- prev->surface->backend != target->backend)
- {
- if (need_translate) {
- _cairo_path_fixed_translate (&prev->path,
- _cairo_fixed_from_int (-clip_extents->x),
- _cairo_fixed_from_int (-clip_extents->y));
- }
- status = _cairo_surface_fill (surface,
- CAIRO_OPERATOR_IN,
- &_cairo_pattern_white.base,
- &prev->path,
- prev->fill_rule,
- prev->tolerance,
- prev->antialias,
- NULL);
- if (need_translate) {
- _cairo_path_fixed_translate (&prev->path,
- _cairo_fixed_from_int (clip_extents->x),
- _cairo_fixed_from_int (clip_extents->y));
- }
+ if (clip->num_boxes) {
+ copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
+ if (unlikely (copy->boxes == NULL))
+ return _cairo_clip_set_all_clipped (copy);
- if (unlikely (status))
- goto BAIL;
- }
- else
- {
- cairo_surface_pattern_t pattern;
- cairo_surface_t *prev_surface;
- int prev_tx, prev_ty;
-
- prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty);
- status = prev_surface->status;
- if (unlikely (status))
- goto BAIL;
-
- _cairo_pattern_init_for_surface (&pattern, prev_surface);
- pattern.base.filter = CAIRO_FILTER_NEAREST;
- cairo_matrix_init_translate (&pattern.base.matrix,
- clip_extents->x - prev_tx,
- clip_extents->y - prev_ty);
- status = _cairo_surface_paint (surface,
- CAIRO_OPERATOR_IN,
- &pattern.base,
- NULL);
- _cairo_pattern_fini (&pattern.base);
-
- if (unlikely (status))
- goto BAIL;
-
- break;
+ for (i = 0; i < clip->num_boxes; i++) {
+ copy->boxes[i].p1.x = clip->boxes[i].p1.x + fx;
+ copy->boxes[i].p2.x = clip->boxes[i].p2.x + fx;
+ copy->boxes[i].p1.y = clip->boxes[i].p1.y + fy;
+ copy->boxes[i].p2.y = clip->boxes[i].p2.y + fy;
}
-
- prev = prev->prev;
+ copy->num_boxes = clip->num_boxes;
}
- *tx = clip_extents->x;
- *ty = clip_extents->y;
- cairo_surface_destroy (clip_path->surface);
- return clip_path->surface = surface;
-
- BAIL:
- cairo_surface_destroy (surface);
- return _cairo_surface_create_in_error (status);
-}
-
-cairo_bool_t
-_cairo_clip_contains_rectangle (cairo_clip_t *clip,
- const cairo_rectangle_int_t *rect)
-{
- cairo_clip_path_t *clip_path;
-
- /* clip == NULL means no clip, so the clip contains everything */
- if (clip == NULL)
- return TRUE;
-
- clip_path = clip->path;
- if (clip_path->extents.x > rect->x ||
- clip_path->extents.y > rect->y ||
- clip_path->extents.x + clip_path->extents.width < rect->x + rect->width ||
- clip_path->extents.y + clip_path->extents.height < rect->y + rect->height)
- {
- return FALSE;
- }
+ copy->extents = clip->extents;
+ copy->extents.x += tx;
+ copy->extents.y += ty;
- do {
- cairo_box_t box;
-
- if ((clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) == 0)
- return FALSE;
-
- if (! _cairo_path_fixed_is_box (&clip_path->path, &box))
- return FALSE;
-
- if (box.p1.x > _cairo_fixed_from_int (rect->x) ||
- box.p1.y > _cairo_fixed_from_int (rect->y) ||
- box.p2.x < _cairo_fixed_from_int (rect->x + rect->width) ||
- box.p2.y < _cairo_fixed_from_int (rect->y + rect->height))
- {
- return FALSE;
- }
- } while ((clip_path = clip_path->prev) != NULL);
+ if (clip->path == NULL)
+ return copy;
- return TRUE;
+ return _cairo_clip_path_copy_with_translation (copy, clip->path, fx, fy);
}
cairo_bool_t
-_cairo_clip_contains_extents (cairo_clip_t *clip,
+_cairo_clip_contains_extents (const cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents)
{
const cairo_rectangle_int_t *rect;
@@ -1155,149 +336,57 @@ _cairo_clip_contains_extents (cairo_clip_t *clip,
}
void
-_cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
+_cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip)
{
- cairo_clip_path_t *clip_path;
+ int i;
if (clip == NULL) {
fprintf (stream, "no clip\n");
return;
}
- if (clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (clip)) {
fprintf (stream, "clip: all-clipped\n");
return;
}
- if (clip->path == NULL) {
- fprintf (stream, "clip: empty\n");
- return;
- }
-
fprintf (stream, "clip:\n");
+ fprintf (stream, " extents: (%d, %d) x (%d, %d)",
+ clip->extents.x, clip->extents.y,
+ clip->extents.width, clip->extents.height);
- clip_path = clip->path;
- do {
- fprintf (stream, "path: has region? %s, has surface? %s, aa=%d, tolerance=%f, rule=%d: ",
- clip_path->region == NULL ? "no" : "yes",
- clip_path->surface == NULL ? "no" : "yes",
- clip_path->antialias,
- clip_path->tolerance,
- clip_path->fill_rule);
- _cairo_debug_print_path (stream, &clip_path->path);
- fprintf (stream, "\n");
- } while ((clip_path = clip_path->prev) != NULL);
-}
-
-cairo_surface_t *
-_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target, int *tx, int *ty)
-{
- /* XXX is_clear -> all_clipped */
- assert (clip->path != NULL);
- return _cairo_clip_path_get_surface (clip->path, target, tx, ty);
-}
-
-cairo_status_t
-_cairo_clip_combine_with_surface (cairo_clip_t *clip,
- cairo_surface_t *dst,
- int dst_x, int dst_y)
-{
- cairo_clip_path_t *clip_path = clip->path;
- cairo_bool_t need_translate;
- cairo_status_t status;
-
- assert (clip_path != NULL);
-
- need_translate = dst_x | dst_y;
- do {
- if (clip_path->surface != NULL &&
- clip_path->surface->backend == dst->backend)
- {
- cairo_surface_pattern_t pattern;
-
- _cairo_pattern_init_for_surface (&pattern, clip_path->surface);
- cairo_matrix_init_translate (&pattern.base.matrix,
- dst_x - clip_path->extents.x,
- dst_y - clip_path->extents.y);
- pattern.base.filter = CAIRO_FILTER_NEAREST;
- status = _cairo_surface_paint (dst,
- CAIRO_OPERATOR_IN,
- &pattern.base,
- NULL);
-
- _cairo_pattern_fini (&pattern.base);
-
- return status;
- }
-
- if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
- _cairo_path_fixed_fill_maybe_region (&clip_path->path))
- {
- continue;
- }
-
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (-dst_x),
- _cairo_fixed_from_int (-dst_y));
- }
- status = _cairo_surface_fill (dst,
- CAIRO_OPERATOR_IN,
- &_cairo_pattern_white.base,
- &clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- clip_path->antialias,
- NULL);
- if (need_translate) {
- _cairo_path_fixed_translate (&clip_path->path,
- _cairo_fixed_from_int (dst_x),
- _cairo_fixed_from_int (dst_y));
- }
-
- if (unlikely (status))
- return status;
- } while ((clip_path = clip_path->prev) != NULL);
+ fprintf (stream, " num_boxes = %d\n", clip->num_boxes);
+ for (i = 0; i < clip->num_boxes; i++) {
+ fprintf (stream, " [%d] = (%f, %f), (%f, %f)\n", i,
+ _cairo_fixed_to_double (clip->boxes[i].p1.x),
+ _cairo_fixed_to_double (clip->boxes[i].p1.y),
+ _cairo_fixed_to_double (clip->boxes[i].p2.x),
+ _cairo_fixed_to_double (clip->boxes[i].p2.y));
+ }
- return CAIRO_STATUS_SUCCESS;
+ if (clip->path) {
+ cairo_clip_path_t *clip_path = clip->path;
+ do {
+ fprintf (stream, "path: aa=%d, tolerance=%f, rule=%d: ",
+ clip_path->antialias,
+ clip_path->tolerance,
+ clip_path->fill_rule);
+ _cairo_debug_print_path (stream, &clip_path->path);
+ fprintf (stream, "\n");
+ } while ((clip_path = clip_path->prev) != NULL);
+ }
}
-static const cairo_rectangle_int_t _cairo_empty_rectangle_int = { 0, 0, 0, 0 };
-
const cairo_rectangle_int_t *
_cairo_clip_get_extents (const cairo_clip_t *clip)
{
- if (clip->all_clipped)
- return &_cairo_empty_rectangle_int;
-
- if (clip->path == NULL)
- return NULL;
-
- return &clip->path->extents;
-}
-
-void
-_cairo_clip_drop_cache (cairo_clip_t *clip)
-{
- cairo_clip_path_t *clip_path;
-
- if (clip->path == NULL)
- return;
+ if (clip == NULL)
+ return &_cairo_unbounded_rectangle;
- clip_path = clip->path;
- do {
- if (clip_path->region != NULL) {
- cairo_region_destroy (clip_path->region);
- clip_path->region = NULL;
- }
+ if (_cairo_clip_is_all_clipped (clip))
+ return &_cairo_empty_rectangle;
- if (clip_path->surface != NULL) {
- cairo_surface_destroy (clip_path->surface);
- clip_path->surface = NULL;
- }
-
- clip_path->flags &= ~CAIRO_CLIP_PATH_HAS_REGION;
- } while ((clip_path = clip_path->prev) != NULL);
+ return &clip->extents;
}
const cairo_rectangle_list_t _cairo_rectangles_nil =
@@ -1329,145 +418,6 @@ _cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
return is_tight;
}
-cairo_int_status_t
-_cairo_clip_get_region (cairo_clip_t *clip,
- cairo_region_t **region)
-{
- cairo_int_status_t status;
-
- if (clip->all_clipped)
- goto CLIPPED;
-
- assert (clip->path != NULL);
-
- status = _cairo_clip_path_to_region (clip->path);
- if (status)
- return status;
-
- if (cairo_region_is_empty (clip->path->region)) {
- _cairo_clip_set_all_clipped (clip);
- goto CLIPPED;
- }
-
- if (region)
- *region = clip->path->region;
- return CAIRO_STATUS_SUCCESS;
-
- CLIPPED:
- if (region)
- *region = NULL;
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
-}
-
-cairo_int_status_t
-_cairo_clip_get_boxes (cairo_clip_t *clip,
- cairo_box_t **boxes,
- int *count)
-{
- cairo_int_status_t status;
-
- if (clip->all_clipped)
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
- assert (clip->path != NULL);
-
- status = _cairo_clip_path_to_boxes (clip->path, boxes, count);
- if (status)
- return status;
-
- if (*count == 0) {
- _cairo_clip_set_all_clipped (clip);
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-box_is_aligned (const cairo_box_t *box)
-{
- return
- _cairo_fixed_is_integer (box->p1.x) &&
- _cairo_fixed_is_integer (box->p1.y) &&
- _cairo_fixed_is_integer (box->p2.x) &&
- _cairo_fixed_is_integer (box->p2.y);
-}
-
-static void
-intersect_with_boxes (cairo_composite_rectangles_t *extents,
- cairo_box_t *boxes,
- int num_boxes)
-{
- cairo_rectangle_int_t rect;
- cairo_box_t box;
- int i;
-
- assert (num_boxes > 0);
-
- /* Find the extents over all the clip boxes */
- box = boxes[0];
- for (i = 1; i < num_boxes; i++) {
- if (boxes[i].p1.x < box.p1.x)
- box.p1.x = boxes[i].p1.x;
- if (boxes[i].p1.y < box.p1.y)
- box.p1.y = boxes[i].p1.y;
-
- if (boxes[i].p2.x > box.p2.x)
- box.p2.x = boxes[i].p2.x;
- if (boxes[i].p2.y > box.p2.y)
- box.p2.y = boxes[i].p2.y;
- }
-
- _cairo_box_round_to_rectangle (&box, &rect);
- _cairo_rectangle_intersect (&extents->bounded, &rect);
- _cairo_rectangle_intersect (&extents->unbounded, &rect);
-}
-
-cairo_status_t
-_cairo_clip_to_boxes (cairo_clip_t **clip,
- cairo_composite_rectangles_t *extents,
- cairo_box_t **boxes,
- int *num_boxes)
-{
- cairo_status_t status;
- const cairo_rectangle_int_t *rect;
-
- rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
-
- if (*clip == NULL)
- goto EXTENTS;
-
- status = _cairo_clip_rectangle (*clip, rect);
- if (unlikely (status))
- return status;
-
- status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
- switch ((int) status) {
- case CAIRO_STATUS_SUCCESS:
- intersect_with_boxes (extents, *boxes, *num_boxes);
- if (rect->width == 0 || rect->height == 0 ||
- extents->is_bounded ||
- (*num_boxes == 1 && box_is_aligned (*boxes)))
- {
- *clip = NULL;
- }
- goto DONE;
-
- case CAIRO_INT_STATUS_UNSUPPORTED:
- goto EXTENTS;
-
- default:
- return status;
- }
-
- EXTENTS:
- status = CAIRO_STATUS_SUCCESS;
- _cairo_box_from_rectangle (&(*boxes)[0], rect);
- *num_boxes = 1;
- DONE:
- return status;
-}
-
cairo_rectangle_list_t *
_cairo_rectangle_list_create_in_error (cairo_status_t status)
{
@@ -1499,24 +449,18 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles = NULL;
cairo_region_t *region = NULL;
- cairo_int_status_t status;
int n_rects = 0;
int i;
- if (clip->all_clipped)
- goto DONE;
-
- if (!clip->path)
+ if (clip == NULL)
return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- status = _cairo_clip_get_region (clip, ®ion);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
+ if (_cairo_clip_is_all_clipped (clip))
goto DONE;
- } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- } else if (unlikely (status)) {
- return ERROR_LIST (status);
- }
+
+ region = _cairo_clip_get_region (clip);
+ if (region == NULL)
+ return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
n_rects = cairo_region_num_rectangles (region);
if (n_rects) {
diff --git a/src/cairo-composite-rectangles-private.h b/src/cairo-composite-rectangles-private.h
index a0f7c1a..2b4bdba 100644
--- a/src/cairo-composite-rectangles-private.h
+++ b/src/cairo-composite-rectangles-private.h
@@ -56,6 +56,8 @@ struct _cairo_composite_rectangles {
cairo_rectangle_int_t bounded; /* dst */
cairo_rectangle_int_t unbounded; /* clip */
uint32_t is_bounded;
+
+ cairo_clip_t *clip;
};
cairo_private cairo_int_status_t
@@ -63,7 +65,7 @@ _cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extent
int surface_width, int surface_height,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
@@ -71,25 +73,25 @@ _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
int surface_width, int surface_height,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
int surface_width, int surface_height,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
- cairo_clip_t *clip);
+ const cairo_path_fixed_t *path,
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
@@ -99,7 +101,10 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
cairo_bool_t *overlap);
+cairo_private void
+_cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents);
+
#endif /* CAIRO_COMPOSITE_RECTANGLES_PRIVATE_H */
diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c
index 4240de3..cab7c0c 100644
--- a/src/cairo-composite-rectangles.c
+++ b/src/cairo-composite-rectangles.c
@@ -41,25 +41,29 @@
/* A collection of routines to facilitate writing compositors. */
+void _cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents)
+{
+ _cairo_clip_destroy (extents->clip);
+}
+
static inline cairo_bool_t
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
int width, int height,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
extents->unbounded.x = extents->unbounded.y = 0;
extents->unbounded.width = width;
extents->unbounded.height = height;
+ extents->clip = NULL;
- if (clip != NULL) {
- const cairo_rectangle_int_t *clip_extents;
-
- clip_extents = _cairo_clip_get_extents (clip);
- if (clip_extents == NULL)
- return FALSE;
+ if (_cairo_clip_is_all_clipped (clip))
+ return FALSE;
- if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents))
+ if (clip != NULL) {
+ if (! _cairo_rectangle_intersect (&extents->unbounded,
+ _cairo_clip_get_extents (clip)))
return FALSE;
}
@@ -80,7 +84,7 @@ _cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extent
int surface_width, int surface_height,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_width, surface_height,
@@ -90,11 +94,17 @@ _cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extent
}
extents->mask = extents->bounded;
+
+ extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
+ if (_cairo_clip_is_all_clipped (extents->clip))
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
-_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
+_cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents,
+ const cairo_clip_t *clip)
{
cairo_bool_t ret;
@@ -102,6 +112,10 @@ _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents)
if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
+ extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
+ if (_cairo_clip_is_all_clipped (extents->clip))
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -111,7 +125,7 @@ _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_width, surface_height,
@@ -122,7 +136,7 @@ _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents
_cairo_pattern_get_extents (mask, &extents->mask);
- return _cairo_composite_rectangles_intersect (extents);
+ return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
@@ -130,10 +144,10 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten
int surface_width, int surface_height,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_width, surface_height,
@@ -144,7 +158,7 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten
_cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask);
- return _cairo_composite_rectangles_intersect (extents);
+ return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
@@ -152,8 +166,8 @@ _cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents
int surface_width, int surface_height,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
- cairo_clip_t *clip)
+ const cairo_path_fixed_t *path,
+ const cairo_clip_t *clip)
{
if (! _cairo_composite_rectangles_init (extents,
surface_width, surface_height,
@@ -164,7 +178,7 @@ _cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents
_cairo_path_fixed_approximate_fill_extents (path, &extents->mask);
- return _cairo_composite_rectangles_intersect (extents);
+ return _cairo_composite_rectangles_intersect (extents, clip);
}
cairo_int_status_t
@@ -175,7 +189,7 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
cairo_bool_t *overlap)
{
cairo_status_t status;
@@ -194,5 +208,5 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
if (unlikely (status))
return status;
- return _cairo_composite_rectangles_intersect (extents);
+ return _cairo_composite_rectangles_intersect (extents, clip);
}
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 9b16de8..99289e3 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -35,7 +35,6 @@
#include "cairoint.h"
-
/**
* cairo_debug_reset_static_data:
*
@@ -234,8 +233,10 @@ void
_cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
{
cairo_status_t status;
+ cairo_box_t box;
- printf ("path: extents=(%f, %f), (%f, %f)\n",
+ fprintf (stream,
+ "path: extents=(%f, %f), (%f, %f)\n",
_cairo_fixed_to_double (path->extents.p1.x),
_cairo_fixed_to_double (path->extents.p1.y),
_cairo_fixed_to_double (path->extents.p2.x),
@@ -249,5 +250,37 @@ _cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path)
stream);
assert (status == CAIRO_STATUS_SUCCESS);
+ if (_cairo_path_fixed_is_box (path, &box)) {
+ fprintf (stream, "[box (%d, %d), (%d, %d)]",
+ box.p1.x, box.p1.y, box.p2.x, box.p2.y);
+ }
+
printf ("\n");
}
+
+void
+_cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon)
+{
+ int n;
+
+ fprintf (stream,
+ "polygon: extents=(%f, %f), (%f, %f)\n",
+ _cairo_fixed_to_double (polygon->extents.p1.x),
+ _cairo_fixed_to_double (polygon->extents.p1.y),
+ _cairo_fixed_to_double (polygon->extents.p2.x),
+ _cairo_fixed_to_double (polygon->extents.p2.y));
+ for (n = 0; n < polygon->num_edges; n++) {
+ cairo_edge_t *edge = &polygon->edges[n];
+
+ fprintf (stream,
+ " (%f, %f) -> (%f, %f), top=%f, bottom=%f, dir=%d\n",
+ _cairo_fixed_to_double (edge->line.p1.x),
+ _cairo_fixed_to_double (edge->line.p1.y),
+ _cairo_fixed_to_double (edge->line.p2.x),
+ _cairo_fixed_to_double (edge->line.p2.y),
+ _cairo_fixed_to_double (edge->top),
+ _cairo_fixed_to_double (edge->bottom),
+ edge->dir);
+
+ }
+}
diff --git a/src/cairo-default-context.c b/src/cairo-default-context.c
index cec8016..1798e5c 100644
--- a/src/cairo-default-context.c
+++ b/src/cairo-default-context.c
@@ -131,7 +131,7 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
cairo_status_t status;
clip = _cairo_gstate_get_clip (cr->gstate);
- if (clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (clip)) {
group_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
status = group_surface->status;
if (unlikely (status))
@@ -276,7 +276,8 @@ _cairo_default_context_set_source_rgba (void *abstract_cr, double red, double gr
cairo_pattern_t *pattern;
cairo_status_t status;
- if (_current_source_matches_solid (cr->gstate->source, red, green, blue, 1.))
+ if (_current_source_matches_solid (cr->gstate->source,
+ red, green, blue, alpha))
return CAIRO_STATUS_SUCCESS;
/* push the current pattern to the freed lists */
diff --git a/src/cairo-error-private.h b/src/cairo-error-private.h
index fc0c564..953e8af 100644
--- a/src/cairo-error-private.h
+++ b/src/cairo-error-private.h
@@ -43,9 +43,63 @@
CAIRO_BEGIN_DECLS
+enum _cairo_int_status {
+ CAIRO_INT_STATUS_SUCCESS = 0,
+
+ CAIRO_INT_STATUS_NO_MEMORY,
+ CAIRO_INT_STATUS_INVALID_RESTORE,
+ CAIRO_INT_STATUS_INVALID_POP_GROUP,
+ CAIRO_INT_STATUS_NO_CURRENT_POINT,
+ CAIRO_INT_STATUS_INVALID_MATRIX,
+ CAIRO_INT_STATUS_INVALID_STATUS,
+ CAIRO_INT_STATUS_NULL_POINTER,
+ CAIRO_INT_STATUS_INVALID_STRING,
+ CAIRO_INT_STATUS_INVALID_PATH_DATA,
+ CAIRO_INT_STATUS_READ_ERROR,
+ CAIRO_INT_STATUS_WRITE_ERROR,
+ CAIRO_INT_STATUS_SURFACE_FINISHED,
+ CAIRO_INT_STATUS_SURFACE_TYPE_MISMATCH,
+ CAIRO_INT_STATUS_PATTERN_TYPE_MISMATCH,
+ CAIRO_INT_STATUS_INVALID_CONTENT,
+ CAIRO_INT_STATUS_INVALID_FORMAT,
+ CAIRO_INT_STATUS_INVALID_VISUAL,
+ CAIRO_INT_STATUS_FILE_NOT_FOUND,
+ CAIRO_INT_STATUS_INVALID_DASH,
+ CAIRO_INT_STATUS_INVALID_DSC_COMMENT,
+ CAIRO_INT_STATUS_INVALID_INDEX,
+ CAIRO_INT_STATUS_CLIP_NOT_REPRESENTABLE,
+ CAIRO_INT_STATUS_TEMP_FILE_ERROR,
+ CAIRO_INT_STATUS_INVALID_STRIDE,
+ CAIRO_INT_STATUS_FONT_TYPE_MISMATCH,
+ CAIRO_INT_STATUS_USER_FONT_IMMUTABLE,
+ CAIRO_INT_STATUS_USER_FONT_ERROR,
+ CAIRO_INT_STATUS_NEGATIVE_COUNT,
+ CAIRO_INT_STATUS_INVALID_CLUSTERS,
+ CAIRO_INT_STATUS_INVALID_SLANT,
+ CAIRO_INT_STATUS_INVALID_WEIGHT,
+ CAIRO_INT_STATUS_INVALID_SIZE,
+ CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED,
+ CAIRO_INT_STATUS_DEVICE_TYPE_MISMATCH,
+ CAIRO_INT_STATUS_DEVICE_ERROR,
+ CAIRO_INT_STATUS_INVALID_MESH_CONSTRUCTION,
+ CAIRO_INT_STATUS_DEVICE_FINISHED,
+
+ CAIRO_INT_STATUS_LAST_STATUS,
+
+ CAIRO_INT_STATUS_UNSUPPORTED = 100,
+ CAIRO_INT_STATUS_DEGENERATE,
+ CAIRO_INT_STATUS_NOTHING_TO_DO,
+ CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY,
+ CAIRO_INT_STATUS_IMAGE_FALLBACK,
+ CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN,
+};
+
#define _cairo_status_is_error(status) \
(status != CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS)
+#define _cairo_int_status_is_error(status) \
+ (status != CAIRO_INT_STATUS_SUCCESS && status <= CAIRO_INT_STATUS_LAST_STATUS)
+
cairo_private cairo_status_t
_cairo_error (cairo_status_t status);
diff --git a/src/cairo-error.c b/src/cairo-error.c
index a3fc197..1b9bd76 100644
--- a/src/cairo-error.c
+++ b/src/cairo-error.c
@@ -39,7 +39,9 @@
#include "cairoint.h"
#include "cairo-private.h"
+#include "cairo-compiler-private.h"
#include "cairo-error-private.h"
+
#include <assert.h>
/**
@@ -67,3 +69,5 @@ _cairo_error (cairo_status_t status)
return status;
}
+
+COMPILE_TIME_ASSERT ((int)CAIRO_INT_STATUS_LAST_STATUS == (int)CAIRO_STATUS_LAST_STATUS);
diff --git a/src/cairo-fixed-private.h b/src/cairo-fixed-private.h
index 6cecc8d..9a16a03 100644
--- a/src/cairo-fixed-private.h
+++ b/src/cairo-fixed-private.h
@@ -164,6 +164,12 @@ _cairo_fixed_floor (cairo_fixed_t f)
}
static inline cairo_fixed_t
+_cairo_fixed_ceil (cairo_fixed_t f)
+{
+ return _cairo_fixed_floor (f + CAIRO_FIXED_FRAC_MASK);
+}
+
+static inline cairo_fixed_t
_cairo_fixed_round (cairo_fixed_t f)
{
return _cairo_fixed_floor (f + (CAIRO_FIXED_FRAC_MASK+1)/2);
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 98c6dd8..2ad2630 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -283,16 +283,14 @@ face_props_parse (twin_face_properties_t *props,
parse_field (props, start, end - start);
}
-static cairo_status_t
-twin_font_face_create_properties (cairo_font_face_t *twin_face,
- twin_face_properties_t **props_out)
+static twin_face_properties_t *
+twin_font_face_create_properties (cairo_font_face_t *twin_face)
{
twin_face_properties_t *props;
- cairo_status_t status;
props = malloc (sizeof (twin_face_properties_t));
if (unlikely (props == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return NULL;
props->stretch = TWIN_STRETCH_NORMAL;
props->slant = CAIRO_FONT_SLANT_NORMAL;
@@ -300,30 +298,25 @@ twin_font_face_create_properties (cairo_font_face_t *twin_face,
props->monospace = FALSE;
props->smallcaps = FALSE;
- status = cairo_font_face_set_user_data (twin_face,
+ if (unlikely (cairo_font_face_set_user_data (twin_face,
&twin_properties_key,
- props, free);
- if (unlikely (status)) {
+ props, free))) {
free (props);
- return status;
+ return NULL;
}
- if (props_out)
- *props_out = props;
-
- return CAIRO_STATUS_SUCCESS;
+ return props;
}
static cairo_status_t
twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
cairo_toy_font_face_t *toy_face)
{
- cairo_status_t status;
twin_face_properties_t *props;
- status = twin_font_face_create_properties (twin_face, &props);
- if (unlikely (status))
- return status;
+ props = twin_font_face_create_properties (twin_face);
+ if (unlikely (props == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
props->slant = toy_face->slant;
props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
@@ -729,11 +722,9 @@ cairo_font_face_t *
_cairo_font_face_twin_create_fallback (void)
{
cairo_font_face_t *twin_font_face;
- cairo_status_t status;
twin_font_face = _cairo_font_face_twin_create_internal ();
- status = twin_font_face_create_properties (twin_font_face, NULL);
- if (status) {
+ if (! twin_font_face_create_properties (twin_font_face)) {
cairo_font_face_destroy (twin_font_face);
return (cairo_font_face_t *) &_cairo_font_face_nil;
}
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 6389200..ff737a3 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2573,27 +2573,28 @@ static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
/* #cairo_ft_font_face_t */
#if CAIRO_HAS_FC_FONT
-static cairo_status_t
-_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
- cairo_font_face_t **out);
+static cairo_font_face_t *
+_cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
static cairo_status_t
-_cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
- cairo_font_face_t **font_face)
+_cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
+ cairo_font_face_t **font_face_out)
{
+ cairo_font_face_t *font_face = (cairo_font_face_t *) &_cairo_font_face_nil;
FcPattern *pattern;
int fcslant;
int fcweight;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
pattern = FcPatternCreate ();
- if (!pattern)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (!pattern) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return font_face->status;
+ }
if (!FcPatternAddString (pattern,
FC_FAMILY, (unsigned char *) toy_face->family))
{
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
goto FREE_PATTERN;
}
@@ -2612,7 +2613,7 @@ _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
}
if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
goto FREE_PATTERN;
}
@@ -2628,16 +2629,17 @@ _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
}
if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
goto FREE_PATTERN;
}
- status = _cairo_ft_font_face_create_for_pattern (pattern, font_face);
+ font_face = _cairo_ft_font_face_create_for_pattern (pattern);
FREE_PATTERN:
FcPatternDestroy (pattern);
- return status;
+ *font_face_out = font_face;
+ return font_face->status;
}
#endif
@@ -2776,15 +2778,16 @@ const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
};
#if CAIRO_HAS_FC_FONT
-static cairo_status_t
-_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
- cairo_font_face_t **out)
+static cairo_font_face_t *
+_cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
{
cairo_ft_font_face_t *font_face;
font_face = malloc (sizeof (cairo_ft_font_face_t));
- if (unlikely (font_face == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (unlikely (font_face == NULL)) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *) &_cairo_font_face_nil;
+ }
font_face->unscaled = NULL;
font_face->next = NULL;
@@ -2792,7 +2795,8 @@ _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
font_face->pattern = FcPatternDuplicate (pattern);
if (unlikely (font_face->pattern == NULL)) {
free (font_face);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *) &_cairo_font_face_nil;
}
font_face->resolved_font_face = NULL;
@@ -2800,8 +2804,7 @@ _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
_cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
- *out = &font_face->base;
- return CAIRO_STATUS_SUCCESS;
+ return &font_face->base;
}
#endif
@@ -3156,12 +3159,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
if (unlikely (unscaled == NULL)) {
/* Store the pattern. We will resolve it and create unscaled
* font when creating scaled fonts */
- status = _cairo_ft_font_face_create_for_pattern (pattern,
- &font_face);
- if (unlikely (status))
- return (cairo_font_face_t *) &_cairo_font_face_nil;
-
- return font_face;
+ return _cairo_ft_font_face_create_for_pattern (pattern);
}
_get_pattern_ft_options (pattern, &ft_options);
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index f09cf41..81efbbb 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -40,6 +40,7 @@
#include "cairo-gl-private.h"
+#include "cairo-composite-rectangles-private.h"
#include "cairo-error-private.h"
#include "cairo-rtree-private.h"
@@ -54,7 +55,7 @@ typedef struct _cairo_gl_glyph_private {
struct { float x, y; } p1, p2;
} cairo_gl_glyph_private_t;
-static cairo_status_t
+static cairo_int_status_t
_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
cairo_gl_glyph_cache_t *cache,
cairo_scaled_glyph_t *scaled_glyph)
@@ -63,7 +64,7 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
cairo_gl_surface_t *cache_surface;
cairo_gl_glyph_private_t *glyph_private;
cairo_rtree_node_t *node = NULL;
- cairo_status_t status;
+ cairo_int_status_t status;
int width, height;
width = glyph_surface->width;
@@ -79,7 +80,7 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_rtree_evict_random (&cache->rtree,
width, height, &node);
- if (status == CAIRO_STATUS_SUCCESS) {
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
status = _cairo_rtree_node_insert (&cache->rtree,
node, width, height, &node);
}
@@ -148,6 +149,7 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
cache = &ctx->glyph_cache[1];
content = CAIRO_CONTENT_ALPHA;
break;
+ default:
case CAIRO_FORMAT_INVALID:
ASSERT_NOT_REACHED;
return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
@@ -227,10 +229,9 @@ _render_glyphs (cairo_gl_surface_t *dst,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
- const cairo_rectangle_int_t *glyph_extents,
cairo_scaled_font_t *scaled_font,
+ const cairo_composite_rectangles_t *extents,
cairo_bool_t *has_component_alpha,
- cairo_region_t *clip_region,
int *remaining_glyphs)
{
cairo_format_t last_format = CAIRO_FORMAT_INVALID;
@@ -249,7 +250,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
_cairo_scaled_font_freeze_cache (scaled_font);
status = _cairo_gl_composite_init (&setup, op, dst,
- TRUE, glyph_extents);
+ TRUE, &extents->bounded);
if (unlikely (status))
goto FINISH;
@@ -260,10 +261,11 @@ _render_glyphs (cairo_gl_surface_t *dst,
}
status = _cairo_gl_composite_set_source (&setup, source,
- glyph_extents->x, glyph_extents->y,
+ extents->bounded.x,
+ extents->bounded.y,
dst_x, dst_y,
- glyph_extents->width,
- glyph_extents->height);
+ extents->bounded.width,
+ extents->bounded.height);
if (unlikely (status))
goto FINISH;
@@ -273,7 +275,8 @@ _render_glyphs (cairo_gl_surface_t *dst,
cairo_list_add (&scaled_font->link, &ctx->fonts);
}
- _cairo_gl_composite_set_clip_region (&setup, clip_region);
+ _cairo_gl_composite_set_clip_region (&setup,
+ _cairo_clip_get_region (extents->clip));
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
@@ -374,35 +377,41 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
- const cairo_rectangle_int_t *glyph_extents,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ cairo_composite_rectangles_t *extents,
int *remaining_glyphs)
{
cairo_surface_t *mask;
cairo_status_t status;
cairo_bool_t has_component_alpha;
+ cairo_clip_t *saved_clip;
int i;
/* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
mask = cairo_gl_surface_create (dst->base.device,
CAIRO_CONTENT_COLOR_ALPHA,
- glyph_extents->width,
- glyph_extents->height);
+ extents->bounded.width,
+ extents->bounded.height);
if (unlikely (mask->status))
return mask->status;
for (i = 0; i < num_glyphs; i++) {
- glyphs[i].x -= glyph_extents->x;
- glyphs[i].y -= glyph_extents->y;
+ glyphs[i].x -= extents->bounded.x;
+ glyphs[i].y -= extents->bounded.y;
}
+
+ saved_clip = extents->clip;
+ extents->clip = NULL;
status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
CAIRO_OPERATOR_ADD,
&_cairo_pattern_white.base,
- glyphs, num_glyphs, glyph_extents,
- scaled_font, &has_component_alpha,
- NULL, remaining_glyphs);
+ glyphs, num_glyphs, scaled_font,
+ extents,
+ &has_component_alpha,
+ remaining_glyphs);
+ extents->clip = saved_clip;
+
if (likely (status == CAIRO_STATUS_SUCCESS)) {
cairo_surface_pattern_t mask_pattern;
@@ -410,14 +419,15 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
_cairo_pattern_init_for_surface (&mask_pattern, mask);
mask_pattern.base.has_component_alpha = has_component_alpha;
cairo_matrix_init_translate (&mask_pattern.base.matrix,
- -glyph_extents->x, -glyph_extents->y);
+ -extents->bounded.x, -extents->bounded.y);
status = _cairo_surface_mask (&dst->base, op,
- source, &mask_pattern.base, clip);
+ source, &mask_pattern.base,
+ extents->clip);
_cairo_pattern_fini (&mask_pattern.base);
} else {
for (i = 0; i < num_glyphs; i++) {
- glyphs[i].x += glyph_extents->x;
- glyphs[i].y += glyph_extents->y;
+ glyphs[i].x += extents->bounded.x;
+ glyphs[i].y += extents->bounded.y;
}
*remaining_glyphs = num_glyphs;
}
@@ -434,13 +444,11 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_gl_surface_t *dst = abstract_dst;
- cairo_rectangle_int_t surface_extents;
- cairo_rectangle_int_t extents;
- cairo_region_t *clip_region = NULL;
+ cairo_composite_rectangles_t extents;
cairo_bool_t overlap, use_mask = FALSE;
cairo_bool_t has_component_alpha;
cairo_status_t status;
@@ -526,60 +534,40 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
if (! _cairo_gl_surface_owns_font (dst, scaled_font))
return UNSUPPORTED ("do not control font");
- /* If the glyphs overlap, we need to build an intermediate mask rather
- * then perform the compositing directly.
- */
- status = _cairo_scaled_font_glyph_device_extents (scaled_font,
- glyphs, num_glyphs,
- &extents,
- &overlap);
+ status = _cairo_composite_rectangles_init_for_glyphs (&extents,
+ dst->width,
+ dst->height,
+ op, source,
+ scaled_font,
+ glyphs, num_glyphs,
+ clip, &overlap);
if (unlikely (status))
return status;
+ /* If the glyphs overlap, we need to build an intermediate mask rather
+ * then perform the compositing directly.
+ */
use_mask |= overlap;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- /* the empty clip should never be propagated this far */
- assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
- if (unlikely (_cairo_status_is_error (status)))
- return status;
-
- use_mask |= status == CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (! _cairo_rectangle_intersect (&extents,
- _cairo_clip_get_extents (clip)))
- goto EMPTY;
- }
-
- surface_extents.x = surface_extents.y = 0;
- surface_extents.width = dst->width;
- surface_extents.height = dst->height;
- if (! _cairo_rectangle_intersect (&extents, &surface_extents))
- goto EMPTY;
+ use_mask |= ! _cairo_clip_is_region (extents.clip);
if (use_mask) {
- return _cairo_gl_surface_show_glyphs_via_mask (dst, op,
- source,
- glyphs, num_glyphs,
- &extents,
- scaled_font,
- clip,
- remaining_glyphs);
+ status = _cairo_gl_surface_show_glyphs_via_mask (dst, op,
+ source,
+ glyphs, num_glyphs,
+ scaled_font,
+ &extents,
+ remaining_glyphs);
+ } else {
+ status = _render_glyphs (dst, extents.bounded.x, extents.bounded.y,
+ op, source,
+ glyphs, num_glyphs, scaled_font,
+ &extents,
+ &has_component_alpha,
+ remaining_glyphs);
}
- return _render_glyphs (dst, extents.x, extents.y,
- op, source,
- glyphs, num_glyphs, &extents,
- scaled_font, &has_component_alpha,
- clip_region, remaining_glyphs);
-
-EMPTY:
- *remaining_glyphs = 0;
- if (! _cairo_operator_bounded_by_mask (op))
- return _cairo_surface_paint (&dst->base, op, source, clip);
- else
- return CAIRO_STATUS_SUCCESS;
+ _cairo_composite_rectangles_fini (&extents);
+ return status;
}
void
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index edd1355..c83d78f 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -501,7 +501,7 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs);
static inline int
diff --git a/src/cairo-gl-surface-legacy.c b/src/cairo-gl-surface-legacy.c
new file mode 100644
index 0000000..0ba356e
--- /dev/null
+++ b/src/cairo-gl-surface-legacy.c
@@ -0,0 +1,601 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Eric Anholt
+ * Copyright © 2009 Chris Wilson
+ * Copyright © 2005,2010 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Benjamin Otte <otte at gnome.org>
+ * Carl Worth <cworth at cworth.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ * Eric Anholt <eric at anholt.net>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
+#include "cairo-error-private.h"
+#include "cairo-gl-private.h"
+
+cairo_status_t
+_cairo_gl_surface_acquire_dest_image (void *abstract_surface,
+ cairo_rectangle_int_t *interest_rect,
+ cairo_image_surface_t **image_out,
+ cairo_rectangle_int_t *image_rect_out,
+ void **image_extra)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+ cairo_int_status_t status;
+
+ status = _cairo_gl_surface_deferred_clear (surface);
+ if (unlikely (status))
+ return status;
+
+ *image_extra = NULL;
+ return _cairo_gl_surface_get_image (surface, interest_rect, image_out,
+ image_rect_out);
+}
+
+void
+_cairo_gl_surface_release_dest_image (void *abstract_surface,
+ cairo_rectangle_int_t *interest_rect,
+ cairo_image_surface_t *image,
+ cairo_rectangle_int_t *image_rect,
+ void *image_extra)
+{
+ cairo_status_t status;
+
+ status = _cairo_gl_surface_draw_image (abstract_surface, image,
+ 0, 0,
+ image->width, image->height,
+ image_rect->x, image_rect->y);
+ /* as we created the image, its format should be directly applicable */
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ cairo_surface_destroy (&image->base);
+}
+
+cairo_status_t
+_cairo_gl_surface_clone_similar (void *abstract_surface,
+ cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ int *clone_offset_x,
+ int *clone_offset_y,
+ cairo_surface_t **clone_out)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+ cairo_int_status_t status;
+
+ /* XXX: Use GLCopyTexImage2D to clone non-texture-surfaces */
+ if (src->device == surface->base.device &&
+ _cairo_gl_surface_is_texture ((cairo_gl_surface_t *) src)) {
+ status = _cairo_gl_surface_deferred_clear ((cairo_gl_surface_t *)src);
+ if (unlikely (status))
+ return status;
+
+ *clone_offset_x = 0;
+ *clone_offset_y = 0;
+ *clone_out = cairo_surface_reference (src);
+
+ return CAIRO_STATUS_SUCCESS;
+ } else if (_cairo_surface_is_image (src)) {
+ cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
+ cairo_gl_surface_t *clone;
+
+ clone = (cairo_gl_surface_t *)
+ _cairo_gl_surface_create_similar (&surface->base,
+ src->content,
+ width, height);
+ if (clone == NULL)
+ return UNSUPPORTED ("create_similar failed");
+ if (clone->base.status)
+ return clone->base.status;
+
+ status = _cairo_gl_surface_draw_image (clone, image_src,
+ src_x, src_y,
+ width, height,
+ 0, 0);
+ if (status) {
+ cairo_surface_destroy (&clone->base);
+ return status;
+ }
+
+ *clone_out = &clone->base;
+ *clone_offset_x = src_x;
+ *clone_offset_y = src_y;
+
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ return UNSUPPORTED ("unknown src surface type in clone_similar");
+}
+
+/** Creates a cairo-gl pattern surface for the given trapezoids */
+static cairo_status_t
+_cairo_gl_get_traps_pattern (cairo_gl_surface_t *dst,
+ int dst_x, int dst_y,
+ int width, int height,
+ cairo_trapezoid_t *traps,
+ int num_traps,
+ cairo_antialias_t antialias,
+ cairo_surface_pattern_t *pattern)
+{
+ pixman_format_code_t pixman_format;
+ pixman_image_t *image;
+ cairo_surface_t *surface;
+ int i;
+
+ pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1,
+ image = pixman_image_create_bits (pixman_format, width, height, NULL, 0);
+ if (unlikely (image == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ for (i = 0; i < num_traps; i++) {
+ pixman_trapezoid_t trap;
+
+ trap.top = _cairo_fixed_to_16_16 (traps[i].top);
+ trap.bottom = _cairo_fixed_to_16_16 (traps[i].bottom);
+
+ trap.left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
+ trap.left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
+ trap.left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
+ trap.left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
+
+ trap.right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
+ trap.right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
+ trap.right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
+ trap.right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
+
+ pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y);
+ }
+
+ surface = _cairo_image_surface_create_for_pixman_image (image,
+ pixman_format);
+ if (unlikely (surface->status)) {
+ pixman_image_unref (image);
+ return surface->status;
+ }
+
+ _cairo_pattern_init_for_surface (pattern, surface);
+ cairo_surface_destroy (surface);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_int_status_t
+_cairo_gl_surface_composite (cairo_operator_t op,
+ const cairo_pattern_t *src,
+ const cairo_pattern_t *mask,
+ void *abstract_dst,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height,
+ cairo_region_t *clip_region)
+{
+ cairo_gl_surface_t *dst = abstract_dst;
+ cairo_gl_context_t *ctx;
+ cairo_status_t status;
+ cairo_gl_composite_t setup;
+ cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
+ int dx, dy;
+
+ status = _cairo_gl_surface_deferred_clear (dst);
+ if (unlikely (status))
+ return status;
+
+ if (op == CAIRO_OPERATOR_SOURCE &&
+ mask == NULL &&
+ src->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ _cairo_surface_is_image (((cairo_surface_pattern_t *) src)->surface) &&
+ _cairo_matrix_is_integer_translation (&src->matrix, &dx, &dy)) {
+ cairo_image_surface_t *image = (cairo_image_surface_t *)
+ ((cairo_surface_pattern_t *) src)->surface;
+ dx += src_x;
+ dy += src_y;
+ if (dx >= 0 &&
+ dy >= 0 &&
+ dx + width <= (unsigned int) image->width &&
+ dy + height <= (unsigned int) image->height) {
+ status = _cairo_gl_surface_draw_image (dst, image,
+ dx, dy,
+ width, height,
+ dst_x, dst_y);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+ }
+ }
+
+ status = _cairo_gl_composite_init (&setup, op, dst,
+ mask && mask->has_component_alpha,
+ &rect);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ status = _cairo_gl_composite_set_source (&setup, src,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ status = _cairo_gl_composite_set_mask (&setup, mask,
+ mask_x, mask_y,
+ dst_x, dst_y,
+ width, height);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ status = _cairo_gl_composite_begin (&setup, &ctx);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ if (clip_region != NULL) {
+ int i, num_rectangles;
+
+ num_rectangles = cairo_region_num_rectangles (clip_region);
+
+ for (i = 0; i < num_rectangles; i++) {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (clip_region, i, &rect);
+ _cairo_gl_composite_emit_rect (ctx,
+ rect.x, rect.y,
+ rect.x + rect.width, rect.y + rect.height,
+ 0);
+ }
+ } else {
+ _cairo_gl_composite_emit_rect (ctx,
+ dst_x, dst_y,
+ dst_x + width, dst_y + height,
+ 0);
+ }
+
+ status = _cairo_gl_context_release (ctx, status);
+
+ CLEANUP:
+ _cairo_gl_composite_fini (&setup);
+
+ return status;
+}
+
+cairo_int_status_t
+_cairo_gl_surface_composite_trapezoids (cairo_operator_t op,
+ const cairo_pattern_t *pattern,
+ void *abstract_dst,
+ cairo_antialias_t antialias,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ unsigned int width,
+ unsigned int height,
+ cairo_trapezoid_t *traps,
+ int num_traps,
+ cairo_region_t *clip_region)
+{
+ cairo_gl_surface_t *dst = abstract_dst;
+ cairo_surface_pattern_t traps_pattern;
+ cairo_int_status_t status;
+
+ if (! _cairo_gl_operator_is_supported (op))
+ return UNSUPPORTED ("unsupported operator");
+
+ status = _cairo_gl_surface_deferred_clear (dst);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_gl_get_traps_pattern (dst,
+ dst_x, dst_y, width, height,
+ traps, num_traps, antialias,
+ &traps_pattern);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_gl_surface_composite (op,
+ pattern, &traps_pattern.base, dst,
+ src_x, src_y,
+ 0, 0,
+ dst_x, dst_y,
+ width, height,
+ clip_region);
+
+ _cairo_pattern_fini (&traps_pattern.base);
+
+ assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
+ return status;
+}
+
+cairo_int_status_t
+_cairo_gl_surface_fill_rectangles (void *abstract_dst,
+ cairo_operator_t op,
+ const cairo_color_t *color,
+ cairo_rectangle_int_t *rects,
+ int num_rects)
+{
+ cairo_gl_surface_t *dst = abstract_dst;
+ cairo_solid_pattern_t solid;
+ cairo_gl_context_t *ctx;
+ cairo_status_t status;
+ cairo_gl_composite_t setup;
+ int i;
+
+ status = _cairo_gl_surface_deferred_clear (dst);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_gl_composite_init (&setup, op, dst,
+ FALSE,
+ /* XXX */ NULL);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ _cairo_pattern_init_solid (&solid, color);
+ status = _cairo_gl_composite_set_source (&setup, &solid.base,
+ 0, 0,
+ 0, 0,
+ 0, 0);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ status = _cairo_gl_composite_set_mask (&setup, NULL,
+ 0, 0,
+ 0, 0,
+ 0, 0);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ status = _cairo_gl_composite_begin (&setup, &ctx);
+ if (unlikely (status))
+ goto CLEANUP;
+
+ for (i = 0; i < num_rects; i++) {
+ _cairo_gl_composite_emit_rect (ctx,
+ rects[i].x,
+ rects[i].y,
+ rects[i].x + rects[i].width,
+ rects[i].y + rects[i].height,
+ 0);
+ }
+
+ status = _cairo_gl_context_release (ctx, status);
+
+ CLEANUP:
+ _cairo_gl_composite_fini (&setup);
+
+ return status;
+}
+
+typedef struct _cairo_gl_surface_span_renderer {
+ cairo_span_renderer_t base;
+
+ cairo_gl_composite_t setup;
+
+ int xmin, xmax;
+ int ymin, ymax;
+
+ cairo_gl_context_t *ctx;
+} cairo_gl_surface_span_renderer_t;
+
+static cairo_status_t
+_cairo_gl_render_bounded_spans (void *abstract_renderer,
+ int y, int height,
+ const cairo_half_open_span_t *spans,
+ unsigned num_spans)
+{
+ cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
+
+ if (num_spans == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ do {
+ if (spans[0].coverage) {
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ spans[0].x, y,
+ spans[1].x, y + height,
+ spans[0].coverage);
+ }
+
+ spans++;
+ } while (--num_spans > 1);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_gl_render_unbounded_spans (void *abstract_renderer,
+ int y, int height,
+ const cairo_half_open_span_t *spans,
+ unsigned num_spans)
+{
+ cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
+
+ if (y > renderer->ymin) {
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ renderer->xmin, renderer->ymin,
+ renderer->xmax, y,
+ 0);
+ }
+
+ if (num_spans == 0) {
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ renderer->xmin, y,
+ renderer->xmax, y + height,
+ 0);
+ } else {
+ if (spans[0].x != renderer->xmin) {
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ renderer->xmin, y,
+ spans[0].x, y + height,
+ 0);
+ }
+
+ do {
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ spans[0].x, y,
+ spans[1].x, y + height,
+ spans[0].coverage);
+ spans++;
+ } while (--num_spans > 1);
+
+ if (spans[0].x != renderer->xmax) {
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ spans[0].x, y,
+ renderer->xmax, y + height,
+ 0);
+ }
+ }
+
+ renderer->ymin = y + height;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_gl_finish_unbounded_spans (void *abstract_renderer)
+{
+ cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
+
+ if (renderer->ymax > renderer->ymin) {
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ renderer->xmin, renderer->ymin,
+ renderer->xmax, renderer->ymax,
+ 0);
+ }
+
+ return _cairo_gl_context_release (renderer->ctx, CAIRO_STATUS_SUCCESS);
+}
+
+static cairo_status_t
+_cairo_gl_finish_bounded_spans (void *abstract_renderer)
+{
+ cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
+
+ return _cairo_gl_context_release (renderer->ctx, CAIRO_STATUS_SUCCESS);
+}
+
+static void
+_cairo_gl_surface_span_renderer_destroy (void *abstract_renderer)
+{
+ cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
+
+ if (!renderer)
+ return;
+
+ _cairo_gl_composite_fini (&renderer->setup);
+
+ free (renderer);
+}
+
+cairo_bool_t
+_cairo_gl_surface_check_span_renderer (cairo_operator_t op,
+ const cairo_pattern_t *pattern,
+ void *abstract_dst,
+ cairo_antialias_t antialias)
+{
+ if (! _cairo_gl_operator_is_supported (op))
+ return FALSE;
+
+ return TRUE;
+
+ (void) pattern;
+ (void) abstract_dst;
+ (void) antialias;
+}
+
+cairo_span_renderer_t *
+_cairo_gl_surface_create_span_renderer (cairo_operator_t op,
+ const cairo_pattern_t *src,
+ void *abstract_dst,
+ cairo_antialias_t antialias,
+ const cairo_composite_rectangles_t *rects)
+{
+ cairo_gl_surface_t *dst = abstract_dst;
+ cairo_gl_surface_span_renderer_t *renderer;
+ cairo_status_t status;
+ const cairo_rectangle_int_t *extents;
+
+ status = _cairo_gl_surface_deferred_clear (dst);
+ if (unlikely (status))
+ return _cairo_span_renderer_create_in_error (status);
+
+ renderer = calloc (1, sizeof (*renderer));
+ if (unlikely (renderer == NULL))
+ return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
+
+ renderer->base.destroy = _cairo_gl_surface_span_renderer_destroy;
+ if (rects->is_bounded) {
+ renderer->base.render_rows = _cairo_gl_render_bounded_spans;
+ renderer->base.finish = _cairo_gl_finish_bounded_spans;
+ extents = &rects->bounded;
+ } else {
+ renderer->base.render_rows = _cairo_gl_render_unbounded_spans;
+ renderer->base.finish = _cairo_gl_finish_unbounded_spans;
+ extents = &rects->unbounded;
+ }
+ renderer->xmin = extents->x;
+ renderer->xmax = extents->x + extents->width;
+ renderer->ymin = extents->y;
+ renderer->ymax = extents->y + extents->height;
+
+ status = _cairo_gl_composite_init (&renderer->setup,
+ op, dst,
+ FALSE, extents);
+ if (unlikely (status))
+ goto FAIL;
+
+ status = _cairo_gl_composite_set_source (&renderer->setup, src,
+ extents->x, extents->y,
+ extents->x, extents->y,
+ extents->width, extents->height);
+ if (unlikely (status))
+ goto FAIL;
+
+ _cairo_gl_composite_set_spans (&renderer->setup);
+ _cairo_gl_composite_set_clip_region (&renderer->setup,
+ _cairo_clip_get_region (rects->clip));
+
+ status = _cairo_gl_composite_begin (&renderer->setup, &renderer->ctx);
+ if (unlikely (status))
+ goto FAIL;
+
+ return &renderer->base;
+
+FAIL:
+ _cairo_gl_composite_fini (&renderer->setup);
+ free (renderer);
+ return _cairo_span_renderer_create_in_error (status);
+}
+
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index eb317f0..1b001b6 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -745,7 +745,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
cairo_image_surface_t *clone = NULL;
cairo_gl_context_t *ctx;
int cpp;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
@@ -851,7 +851,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
}
} else {
cairo_surface_t *tmp;
-
+
tmp = _cairo_gl_surface_create_scratch (ctx,
dst->base.content,
width, height);
@@ -864,7 +864,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
src_x, src_y,
width, height,
0, 0);
- if (status == CAIRO_STATUS_SUCCESS) {
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
cairo_surface_pattern_t tmp_pattern;
_cairo_pattern_init_for_surface (&tmp_pattern, tmp);
@@ -1212,7 +1212,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
{
cairo_gl_surface_t *dst = abstract_dst;
cairo_gl_context_t *ctx;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_gl_composite_t setup;
cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
int dx, dy;
@@ -1634,7 +1634,7 @@ static cairo_int_status_t
_cairo_gl_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
/* simplify the common case of clearing the surface */
if (clip == NULL) {
@@ -1658,22 +1658,12 @@ _cairo_gl_surface_polygon (cairo_gl_surface_t *dst,
cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule,
cairo_antialias_t antialias,
- const cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
+ const cairo_composite_rectangles_t *extents)
{
- cairo_status_t status;
- cairo_region_t *clip_region = NULL;
+ cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
- if (unlikely (_cairo_status_is_error (status)))
- return status;
-
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- return UNSUPPORTED ("a clip surface would be required");
- }
+ if (! _cairo_clip_is_region (extents->clip))
+ return UNSUPPORTED ("a clip surface would be required");
if (! _cairo_surface_check_span_renderer (op, src, &dst->base, antialias))
return UNSUPPORTED ("no span renderer");
@@ -1685,35 +1675,30 @@ _cairo_gl_surface_polygon (cairo_gl_surface_t *dst,
src = &_cairo_pattern_white.base;
}
- status = _cairo_surface_composite_polygon (&dst->base,
- op,
- src,
- fill_rule,
- antialias,
- extents,
- polygon,
- clip_region);
- return status;
+ return _cairo_surface_composite_polygon (&dst->base,
+ op,
+ src,
+ fill_rule,
+ antialias,
+ extents,
+ polygon,
+ clip_region);
}
static cairo_int_status_t
_cairo_gl_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_gl_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
cairo_polygon_t polygon;
cairo_status_t status;
@@ -1726,24 +1711,7 @@ _cairo_gl_surface_stroke (void *abstract_surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
-
+ _cairo_polygon_init_with_clip (&polygon, extents.clip);
status = _cairo_path_fixed_stroke_to_polygon (path,
style,
ctm, ctm_inverse,
@@ -1752,13 +1720,11 @@ _cairo_gl_surface_stroke (void *abstract_surface,
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _cairo_gl_surface_polygon (surface, op, source, &polygon,
CAIRO_FILL_RULE_WINDING, antialias,
- &extents, clip);
+ &extents);
}
-
_cairo_polygon_fini (&polygon);
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -1767,18 +1733,14 @@ static cairo_int_status_t
_cairo_gl_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_gl_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
cairo_polygon_t polygon;
cairo_status_t status;
@@ -1790,50 +1752,16 @@ _cairo_gl_surface_fill (void *abstract_surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
-#if 0
- if (extents.is_bounded && clip != NULL) {
- cairo_clip_path_t *clip_path;
-
- if (((clip_path = _clip_get_single_path (clip)) != NULL) &&
- _cairo_path_fixed_equal (&clip_path->path, path))
- {
- clip = NULL;
- }
- }
-#endif
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
-
+ _cairo_polygon_init_with_clip (&polygon, extents.clip);
status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _cairo_gl_surface_polygon (surface, op, source, &polygon,
fill_rule, antialias,
- &extents, clip);
+ &extents);
}
-
_cairo_polygon_fini (&polygon);
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
index 9e823fa..38f11c7 100644
--- a/src/cairo-gstate-private.h
+++ b/src/cairo-gstate-private.h
@@ -55,7 +55,7 @@ struct _cairo_gstate {
cairo_matrix_t font_matrix;
cairo_font_options_t font_options;
- cairo_clip_t clip;
+ cairo_clip_t *clip;
cairo_surface_t *target; /* The target to which all rendering is directed */
cairo_surface_t *parent_target; /* The previous target which was receiving rendering */
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index a7eced6..b6252de 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -111,7 +111,7 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
_cairo_font_options_init_default (&gstate->font_options);
- _cairo_clip_init (&gstate->clip);
+ gstate->clip = NULL;
gstate->target = cairo_surface_reference (target);
gstate->parent_target = NULL;
@@ -169,7 +169,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
_cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
- _cairo_clip_init_copy (&gstate->clip, &other->clip);
+ gstate->clip = _cairo_clip_copy (other->clip);
gstate->target = cairo_surface_reference (other->target);
/* parent_target is always set to NULL; it's only ever set by redirect_target */
@@ -206,7 +206,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
- _cairo_clip_reset (&gstate->clip);
+ _cairo_clip_destroy (gstate->clip);
cairo_list_del (&gstate->device_transform_observer.link);
@@ -300,8 +300,6 @@ _cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
cairo_status_t
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
{
- cairo_matrix_t matrix;
-
/* If this gstate is already redirected, this is an error; we need a
* new gstate to be able to redirect */
assert (gstate->parent_target == NULL);
@@ -320,13 +318,11 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
/* The clip is in surface backend coordinates for the previous target;
* translate it into the child's backend coordinates. */
- cairo_matrix_init_translate (&matrix,
- child->device_transform.x0 - gstate->parent_target->device_transform.x0,
- child->device_transform.y0 - gstate->parent_target->device_transform.y0);
- _cairo_clip_reset (&gstate->clip);
- return _cairo_clip_init_copy_transformed (&gstate->clip,
- &gstate->next->clip,
- &matrix);
+ gstate->clip = _cairo_clip_copy_with_translation (gstate->next->clip,
+ child->device_transform.x0 - gstate->parent_target->device_transform.x0,
+ child->device_transform.y0 - gstate->parent_target->device_transform.y0);
+
+ return CAIRO_STATUS_SUCCESS;
}
/**
@@ -388,7 +384,7 @@ _cairo_gstate_get_original_target (cairo_gstate_t *gstate)
cairo_clip_t *
_cairo_gstate_get_clip (cairo_gstate_t *gstate)
{
- return &gstate->clip;
+ return gstate->clip;
}
cairo_status_t
@@ -938,39 +934,6 @@ _cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
&gstate->ctm_inverse);
}
-/* We need to take a copy of the clip so that the lower layers may modify it
- * by, perhaps, intersecting it with the operation extents and other paths.
- */
-#define _gstate_get_clip(G, C) _cairo_clip_init_copy ((C), &(G)->clip)
-
-static cairo_bool_t
-_clipped (cairo_gstate_t *gstate)
-{
- cairo_rectangle_int_t extents;
-
- if (gstate->clip.all_clipped)
- return TRUE;
-
- /* XXX consider applying a surface clip? */
-
- if (gstate->clip.path == NULL)
- return FALSE;
-
- if (_cairo_surface_get_extents (gstate->target, &extents)) {
- if (extents.width == 0 || extents.height == 0)
- return TRUE;
-
- if (! _cairo_rectangle_intersect (&extents,
- &gstate->clip.path->extents))
- {
- return TRUE;
- }
- }
-
- /* perform a simple query to exclude trivial all-clipped cases */
- return _cairo_clip_get_region (&gstate->clip, NULL) == CAIRO_INT_STATUS_NOTHING_TO_DO;
-}
-
static cairo_operator_t
_reduce_op (cairo_gstate_t *gstate)
{
@@ -1029,7 +992,6 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
{
cairo_pattern_union_t source_pattern;
const cairo_pattern_t *pattern;
- cairo_clip_t clip;
cairo_status_t status;
cairo_operator_t op;
@@ -1040,7 +1002,7 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
if (gstate->op == CAIRO_OPERATOR_DEST)
return CAIRO_STATUS_SUCCESS;
- if (_clipped (gstate))
+ if (_cairo_clip_is_all_clipped (gstate->clip))
return CAIRO_STATUS_SUCCESS;
op = _reduce_op (gstate);
@@ -1051,12 +1013,9 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
pattern = &source_pattern.base;
}
- status = _cairo_surface_paint (gstate->target,
- op, pattern,
- _gstate_get_clip (gstate, &clip));
- _cairo_clip_fini (&clip);
-
- return status;
+ return _cairo_surface_paint (gstate->target,
+ op, pattern,
+ gstate->clip);
}
cairo_status_t
@@ -1066,7 +1025,6 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
cairo_pattern_union_t source_pattern, mask_pattern;
const cairo_pattern_t *source;
cairo_operator_t op;
- cairo_clip_t clip;
cairo_status_t status;
status = _cairo_gstate_get_pattern_status (mask);
@@ -1080,7 +1038,7 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
if (gstate->op == CAIRO_OPERATOR_DEST)
return CAIRO_STATUS_SUCCESS;
- if (_clipped (gstate))
+ if (_cairo_clip_is_all_clipped (gstate->clip))
return CAIRO_STATUS_SUCCESS;
assert (gstate->opacity == 1.0);
@@ -1126,16 +1084,15 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
status = _cairo_surface_paint (gstate->target, op,
&source_pattern.base,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
}
else
{
status = _cairo_surface_mask (gstate->target, op,
source,
&mask_pattern.base,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
}
- _cairo_clip_fini (&clip);
return status;
}
@@ -1146,7 +1103,6 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
cairo_pattern_union_t source_pattern;
cairo_stroke_style_t style;
double dash[2];
- cairo_clip_t clip;
cairo_status_t status;
status = _cairo_gstate_get_pattern_status (gstate->source);
@@ -1159,7 +1115,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (gstate->stroke_style.line_width <= 0.0)
return CAIRO_STATUS_SUCCESS;
- if (_clipped (gstate))
+ if (_cairo_clip_is_all_clipped (gstate->clip))
return CAIRO_STATUS_SUCCESS;
assert (gstate->opacity == 1.0);
@@ -1175,19 +1131,16 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
- status = _cairo_surface_stroke (gstate->target,
- gstate->op,
- &source_pattern.base,
- path,
- &style,
- &gstate->ctm,
- &gstate->ctm_inverse,
- gstate->tolerance,
- gstate->antialias,
- _gstate_get_clip (gstate, &clip));
- _cairo_clip_fini (&clip);
-
- return status;
+ return _cairo_surface_stroke (gstate->target,
+ gstate->op,
+ &source_pattern.base,
+ path,
+ &style,
+ &gstate->ctm,
+ &gstate->ctm_inverse,
+ gstate->tolerance,
+ gstate->antialias,
+ gstate->clip);
}
cairo_status_t
@@ -1251,7 +1204,6 @@ BAIL:
cairo_status_t
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
- cairo_clip_t clip;
cairo_status_t status;
status = _cairo_gstate_get_pattern_status (gstate->source);
@@ -1261,7 +1213,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (gstate->op == CAIRO_OPERATOR_DEST)
return CAIRO_STATUS_SUCCESS;
- if (_clipped (gstate))
+ if (_cairo_clip_is_all_clipped (gstate->clip))
return CAIRO_STATUS_SUCCESS;
assert (gstate->opacity == 1.0);
@@ -1273,7 +1225,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
status = _cairo_surface_paint (gstate->target,
CAIRO_OPERATOR_CLEAR,
&_cairo_pattern_clear.base,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
} else {
cairo_pattern_union_t source_pattern;
const cairo_pattern_t *pattern;
@@ -1298,7 +1250,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height))
{
status = _cairo_surface_paint (gstate->target, op, pattern,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
}
else
{
@@ -1307,12 +1259,10 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
gstate->fill_rule,
gstate->tolerance,
gstate->antialias,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
}
}
- _cairo_clip_fini (&clip);
-
return status;
}
@@ -1335,32 +1285,46 @@ _cairo_gstate_in_clip (cairo_gstate_t *gstate,
double x,
double y)
{
- cairo_clip_path_t *clip_path;
+ cairo_clip_t *clip = gstate->clip;
+ int i;
- if (gstate->clip.all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return FALSE;
- clip_path = gstate->clip.path;
- if (clip_path == NULL)
- return TRUE;
-
_cairo_gstate_user_to_backend (gstate, &x, &y);
- if (x < clip_path->extents.x ||
- x >= clip_path->extents.x + clip_path->extents.width ||
- y < clip_path->extents.y ||
- y >= clip_path->extents.y + clip_path->extents.height)
+ if (x < clip->extents.x ||
+ x >= clip->extents.x + clip->extents.width ||
+ y < clip->extents.y ||
+ y >= clip->extents.y + clip->extents.height)
{
return FALSE;
}
- do {
- if (! _cairo_path_fixed_in_fill (&clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- x, y))
+ if (clip->num_boxes) {
+ int fx, fy;
+
+ fx = _cairo_fixed_from_double (x);
+ fy = _cairo_fixed_from_double (y);
+ for (i = 0; i < clip->num_boxes; i++) {
+ if (fx >= clip->boxes[i].p1.x && fx <= clip->boxes[i].p2.x &&
+ fy >= clip->boxes[i].p1.y && fy <= clip->boxes[i].p2.y)
+ break;
+ }
+ if (i == clip->num_boxes)
return FALSE;
- } while ((clip_path = clip_path->prev) != NULL);
+ }
+
+ if (clip->path) {
+ cairo_clip_path_t *clip_path = clip->path;
+ do {
+ if (! _cairo_path_fixed_in_fill (&clip_path->path,
+ clip_path->fill_rule,
+ clip_path->tolerance,
+ x, y))
+ return FALSE;
+ } while ((clip_path = clip_path->prev) != NULL);
+ }
return TRUE;
}
@@ -1500,7 +1464,8 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
{
- _cairo_clip_reset (&gstate->clip);
+ _cairo_clip_destroy (gstate->clip);
+ gstate->clip = NULL;
return CAIRO_STATUS_SUCCESS;
}
@@ -1508,23 +1473,27 @@ _cairo_gstate_reset_clip (cairo_gstate_t *gstate)
cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
- return _cairo_clip_clip (&gstate->clip,
- path, gstate->fill_rule,
- gstate->tolerance, gstate->antialias);
+ gstate->clip =
+ _cairo_clip_intersect_path (gstate->clip,
+ path,
+ gstate->fill_rule,
+ gstate->tolerance,
+ gstate->antialias);
+ /* XXX */
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
_cairo_gstate_int_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_int_t *extents)
{
- const cairo_rectangle_int_t *clip_extents;
cairo_bool_t is_bounded;
is_bounded = _cairo_surface_get_extents (gstate->target, extents);
- clip_extents = _cairo_clip_get_extents (&gstate->clip);
- if (clip_extents != NULL) {
- _cairo_rectangle_intersect (extents, clip_extents);
+ if (gstate->clip) {
+ _cairo_rectangle_intersect (extents,
+ _cairo_clip_get_extents (gstate->clip));
is_bounded = TRUE;
}
@@ -1568,23 +1537,19 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
{
- cairo_clip_t clip;
cairo_rectangle_int_t extents;
cairo_rectangle_list_t *list;
- cairo_status_t status;
-
- _cairo_clip_init_copy (&clip, &gstate->clip);
+ cairo_clip_t *clip;
if (_cairo_surface_get_extents (gstate->target, &extents))
- status = _cairo_clip_rectangle (&clip, &extents);
+ clip = _cairo_clip_copy_intersect_rectangle (gstate->clip, &extents);
else
- status = CAIRO_STATUS_SUCCESS;
+ clip = gstate->clip;
- if (unlikely (status))
- return _cairo_rectangle_list_create_in_error (status);
+ list = _cairo_clip_copy_rectangle_list (clip, gstate);
- list = _cairo_clip_copy_rectangle_list (&clip, gstate);
- _cairo_clip_fini (&clip);
+ if (clip != gstate->clip)
+ _cairo_clip_destroy (clip);
return list;
}
@@ -1875,7 +1840,6 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
cairo_text_cluster_t *transformed_clusters = NULL;
cairo_operator_t op;
cairo_status_t status;
- cairo_clip_t clip;
status = _cairo_gstate_get_pattern_status (gstate->source);
if (unlikely (status))
@@ -1884,7 +1848,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
if (gstate->op == CAIRO_OPERATOR_DEST)
return CAIRO_STATUS_SUCCESS;
- if (_clipped (gstate))
+ if (_cairo_clip_is_all_clipped (gstate->clip))
return CAIRO_STATUS_SUCCESS;
status = _cairo_gstate_ensure_scaled_font (gstate);
@@ -1958,14 +1922,14 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
transformed_clusters, info->num_clusters,
info->cluster_flags,
gstate->scaled_font,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
} else {
status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
NULL, 0,
transformed_glyphs, num_glyphs,
NULL, 0, 0,
gstate->scaled_font,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
}
}
else
@@ -1984,14 +1948,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
CAIRO_FILL_RULE_WINDING,
gstate->tolerance,
gstate->scaled_font->options.antialias,
- _gstate_get_clip (gstate, &clip));
+ gstate->clip);
}
_cairo_path_fixed_fini (&path);
}
- _cairo_clip_fini (&clip);
-
CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs)
cairo_glyph_free (transformed_glyphs);
diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
index 63201e6..4489698 100644
--- a/src/cairo-image-info.c
+++ b/src/cairo-image-info.c
@@ -34,6 +34,8 @@
*/
#include "cairoint.h"
+
+#include "cairo-error-private.h"
#include "cairo-image-info-private.h"
static uint32_t
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index be42724..d7e8b82 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -77,16 +77,6 @@
* @Since: 1.8
*/
-static cairo_int_status_t
-_cairo_image_surface_fill (void *dst,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias,
- cairo_clip_t *clip);
-
static pixman_image_t *
_pixman_image_for_solid (const cairo_solid_pattern_t *pattern);
@@ -113,6 +103,7 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
return CAIRO_FORMAT_A1;
case PIXMAN_r5g6b5:
return CAIRO_FORMAT_RGB16_565;
+ case PIXMAN_r8g8b8a8: case PIXMAN_r8g8b8x8:
case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
case PIXMAN_b8g8r8: case PIXMAN_b5g6r5:
case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
@@ -181,6 +172,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
surface->stride = pixman_image_get_stride (pixman_image);
surface->depth = pixman_image_get_depth (pixman_image);
+ surface->base.is_clear = width == 0 || height == 0;
+
return &surface->base;
}
@@ -1099,7 +1092,7 @@ _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
cairo_circle_double_t extremes[2];
pixman_point_fixed_t p1, p2;
unsigned int i;
- cairo_status_t status;
+ cairo_int_status_t status;
if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
pixman_stops = _cairo_malloc_ab (pattern->n_stops,
@@ -1150,7 +1143,7 @@ _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
extents->y + extents->height/2.,
&pixman_transform, ix, iy);
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
- if (unlikely (status != CAIRO_STATUS_SUCCESS) ||
+ if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
! pixman_image_set_transform (pixman_image, &pixman_transform))
{
pixman_image_unref (pixman_image);
@@ -1328,7 +1321,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
cairo_rectangle_int_t sample;
cairo_extend_t extend;
cairo_filter_t filter;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_bool_t undo_src_transform = FALSE;
extend = pattern->base.extend;
@@ -1529,7 +1522,7 @@ _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
* and we can use any filtering, so choose the fastest one. */
pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
}
- else if (unlikely (status != CAIRO_STATUS_SUCCESS ||
+ else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
! pixman_image_set_transform (pixman_image,
&pixman_transform)))
{
@@ -1795,7 +1788,7 @@ _cairo_image_surface_fixup_unbounded_boxes (cairo_image_surface_t *dst,
_cairo_boxes_init (&tmp);
- status = _cairo_boxes_add (&tmp, &box);
+ status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
assert (status == CAIRO_STATUS_SUCCESS);
tmp.chunks.next = &boxes->chunks;
@@ -1812,12 +1805,14 @@ _cairo_image_surface_fixup_unbounded_boxes (cairo_image_surface_t *dst,
pbox = pixman_region32_rectangles (&clip_region->rgn, &i);
_cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i);
- status = _cairo_boxes_add (&clear, &box);
+ status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
assert (status == CAIRO_STATUS_SUCCESS);
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
- status = _cairo_boxes_add (&clear, &chunk->base[i]);
+ status = _cairo_boxes_add (&clear,
+ CAIRO_ANTIALIAS_DEFAULT,
+ &chunk->base[i]);
if (unlikely (status)) {
_cairo_boxes_fini (&clear);
return status;
@@ -1885,7 +1880,7 @@ typedef cairo_status_t
const cairo_pattern_t *src,
int dst_x,
int dst_y,
- cairo_matrix_t *dst_device_transform,
+ cairo_matrix_t *dst_device_transform,
const cairo_rectangle_int_t *extents,
cairo_region_t *clip_region);
@@ -1896,23 +1891,13 @@ _create_composite_mask_pattern (cairo_clip_t *clip,
cairo_image_surface_t *dst,
const cairo_rectangle_int_t *extents)
{
- cairo_region_t *clip_region = NULL;
+ cairo_region_t *clip_region = _cairo_clip_get_region (clip);
+ cairo_bool_t need_clip_surface = ! _cairo_clip_is_region (clip);
pixman_image_t *mask;
cairo_status_t status;
- cairo_bool_t need_clip_surface = FALSE;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (! _cairo_status_is_error (status));
-
- /* The all-clipped state should never propagate this far. */
- assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
-
- need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
- clip_region = NULL;
- }
+ if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
+ clip_region = NULL;
mask = pixman_image_create_bits (PIXMAN_a8, extents->width, extents->height,
NULL, 0);
@@ -1955,7 +1940,8 @@ _create_composite_mask_pattern (cairo_clip_t *clip,
pixman_image_ref (mask);
- status = _cairo_clip_combine_with_surface (clip, tmp, extents->x, extents->y);
+ status = _cairo_clip_combine_with_surface (clip, tmp,
+ extents->x, extents->y);
cairo_surface_destroy (tmp);
if (unlikely (status)) {
pixman_image_unref (mask);
@@ -2014,7 +2000,9 @@ _clip_and_composite_with_mask (cairo_clip_t *clip,
pixman_image_t *src;
int src_x, src_y;
- src = _pixman_image_for_pattern (pattern, FALSE, extents, &dst->base.device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, extents,
+ &dst->base.device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL)) {
pixman_image_unref (mask);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2085,7 +2073,6 @@ _clip_and_composite_combine (cairo_clip_t *clip,
if (unlikely (status))
goto CLEANUP_SURFACE;
- assert (clip->path != NULL);
clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
if (unlikely (clip_surface->status))
goto CLEANUP_SURFACE;
@@ -2156,7 +2143,6 @@ _clip_and_composite_source (cairo_clip_t *clip,
int src_x, src_y;
if (pattern == NULL) {
- cairo_region_t *clip_region;
cairo_status_t status;
status = draw_func (draw_closure,
@@ -2168,7 +2154,7 @@ _clip_and_composite_source (cairo_clip_t *clip,
if (unlikely (status))
return status;
- if (_cairo_clip_get_region (clip, &clip_region) == CAIRO_INT_STATUS_UNSUPPORTED)
+ if (! _cairo_clip_is_region (clip))
status = _cairo_clip_combine_with_surface (clip, &dst->base, 0, 0);
return status;
@@ -2179,7 +2165,9 @@ _clip_and_composite_source (cairo_clip_t *clip,
if (unlikely (mask == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- src = _pixman_image_for_pattern (pattern, FALSE, extents, &dst->base.device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, extents,
+ &dst->base.device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL)) {
pixman_image_unref (mask);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2230,39 +2218,14 @@ _clip_and_composite (cairo_image_surface_t *dst,
const cairo_pattern_t *src,
image_draw_func_t draw_func,
void *draw_closure,
- cairo_composite_rectangles_t*extents,
- cairo_clip_t *clip)
+ cairo_composite_rectangles_t*extents)
{
+ cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
+ cairo_bool_t need_clip_surface = ! _cairo_clip_is_region (extents->clip);
cairo_status_t status;
- cairo_region_t *clip_region = NULL;
- cairo_bool_t need_clip_surface = FALSE;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
- if (unlikely (_cairo_status_is_error (status)))
- return status;
-
- need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (clip_region != NULL) {
- cairo_rectangle_int_t rect;
- cairo_bool_t is_empty;
-
- cairo_region_get_extents (clip_region, &rect);
- is_empty = ! _cairo_rectangle_intersect (&extents->unbounded, &rect);
- if (unlikely (is_empty))
- return CAIRO_STATUS_SUCCESS;
- is_empty = ! _cairo_rectangle_intersect (&extents->bounded, &rect);
- if (unlikely (is_empty && extents->is_bounded))
- return CAIRO_STATUS_SUCCESS;
-
- if (cairo_region_num_rectangles (clip_region) == 1)
- clip_region = NULL;
- }
- }
+ if (cairo_region_num_rectangles (clip_region) == 1)
+ clip_region = NULL;
if (clip_region != NULL) {
status = _cairo_image_surface_set_clip_region (dst, clip_region);
@@ -2276,7 +2239,7 @@ _clip_and_composite (cairo_image_surface_t *dst,
}
if (op == CAIRO_OPERATOR_SOURCE) {
- status = _clip_and_composite_source (clip, src,
+ status = _clip_and_composite_source (extents->clip, src,
draw_func, draw_closure,
dst, &extents->bounded);
} else {
@@ -2287,11 +2250,11 @@ _clip_and_composite (cairo_image_surface_t *dst,
if (need_clip_surface) {
if (extents->is_bounded) {
- status = _clip_and_composite_with_mask (clip, op, src,
+ status = _clip_and_composite_with_mask (extents->clip, op, src,
draw_func, draw_closure,
dst, &extents->bounded);
} else {
- status = _clip_and_composite_combine (clip, op, src,
+ status = _clip_and_composite_combine (extents->clip, op, src,
draw_func, draw_closure,
dst, &extents->bounded);
}
@@ -2308,7 +2271,7 @@ _clip_and_composite (cairo_image_surface_t *dst,
if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
status = _cairo_image_surface_fixup_unbounded (dst, extents,
- need_clip_surface ? clip : NULL);
+ need_clip_surface ? extents->clip : NULL);
}
if (clip_region != NULL)
@@ -2444,7 +2407,9 @@ _composite_traps (void *closure,
return CAIRO_STATUS_SUCCESS;
}
- src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, extents,
+ dst_device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -2856,7 +2821,9 @@ _composite_unaligned_boxes (cairo_image_surface_t *dst,
if (unlikely (status))
goto CLEANUP;
- src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &dst->base.device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded,
+ &dst->base.device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP;
@@ -2882,44 +2849,36 @@ _composite_boxes (cairo_image_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *pattern,
cairo_boxes_t *boxes,
- cairo_antialias_t antialias,
- cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents)
{
- cairo_region_t *clip_region = NULL;
- cairo_bool_t need_clip_mask = FALSE;
+ cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
+ cairo_bool_t need_clip_mask = extents->clip->path != NULL;
cairo_status_t status;
struct _cairo_boxes_chunk *chunk;
uint32_t pixel;
int i;
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- need_clip_mask = status == CAIRO_INT_STATUS_UNSUPPORTED;
- if (need_clip_mask &&
- (op == CAIRO_OPERATOR_SOURCE || ! extents->is_bounded))
- {
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
- clip_region = NULL;
+ if (need_clip_mask &&
+ (op == CAIRO_OPERATOR_SOURCE || ! extents->is_bounded))
+ {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
}
- if (antialias != CAIRO_ANTIALIAS_NONE) {
- if (! boxes->is_pixel_aligned) {
- if (need_clip_mask)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
+ clip_region = NULL;
- if (pattern_to_pixel ((cairo_solid_pattern_t *) pattern, op,
- dst->pixman_format, &pixel))
- {
- return _fill_unaligned_boxes (dst, pattern, pixel, boxes, extents);
- }
- else
- {
- return _composite_unaligned_boxes (dst, op, pattern, boxes, extents);
- }
+ if (! boxes->is_pixel_aligned) {
+ if (need_clip_mask)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (pattern_to_pixel ((cairo_solid_pattern_t *) pattern, op,
+ dst->pixman_format, &pixel))
+ {
+ return _fill_unaligned_boxes (dst, pattern, pixel, boxes, extents);
+ }
+ else
+ {
+ return _composite_unaligned_boxes (dst, op, pattern, boxes, extents);
}
}
@@ -2957,7 +2916,9 @@ _composite_boxes (cairo_image_surface_t *dst,
cairo_surface_t *clip_surface;
int clip_x, clip_y;
- clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
+ clip_surface = _cairo_clip_get_surface (extents->clip,
+ &dst->base,
+ &clip_x, &clip_y);
if (unlikely (clip_surface->status))
return clip_surface->status;
@@ -2970,10 +2931,14 @@ _composite_boxes (cairo_image_surface_t *dst,
}
mask = ((cairo_image_surface_t *) clip_surface)->pixman_image;
+ pixman_image_ref (mask);
+ cairo_surface_destroy (clip_surface);
}
if (pattern != NULL) {
- src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &dst->base.device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded,
+ &dst->base.device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else {
@@ -3022,19 +2987,17 @@ _clip_and_composite_boxes (cairo_image_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *src,
cairo_boxes_t *boxes,
- cairo_antialias_t antialias,
- cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
+ cairo_composite_rectangles_t *extents)
{
cairo_traps_t traps;
- cairo_status_t status;
+ cairo_int_status_t status;
composite_traps_info_t info;
if (boxes->num_boxes == 0 && extents->is_bounded)
return CAIRO_STATUS_SUCCESS;
/* Use a fast path if the boxes are pixel aligned */
- status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
+ status = _composite_boxes (dst, op, src, boxes, extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -3045,10 +3008,10 @@ _clip_and_composite_boxes (cairo_image_surface_t *dst,
info.num_traps = traps.num_traps;
info.traps = traps.traps;
- info.antialias = antialias;
+ info.antialias = CAIRO_ANTIALIAS_DEFAULT;
status = _clip_and_composite (dst, op, src,
_composite_traps, &info,
- extents, clip);
+ extents);
_cairo_traps_fini (&traps);
return status;
@@ -3151,8 +3114,7 @@ _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
const cairo_pattern_t *src,
cairo_traps_t *traps,
cairo_antialias_t antialias,
- cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
+ cairo_composite_rectangles_t *extents)
{
composite_traps_info_t info;
cairo_bool_t need_clip_surface = FALSE;
@@ -3161,12 +3123,7 @@ _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
if (traps->num_traps == 0 && extents->is_bounded)
return CAIRO_STATUS_SUCCESS;
- if (clip != NULL) {
- cairo_region_t *clip_region;
-
- status = _cairo_clip_get_region (clip, &clip_region);
- need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ need_clip_surface = ! _cairo_clip_is_region (extents->clip);
if (traps->has_intersections) {
if (traps->is_rectangular)
@@ -3191,8 +3148,7 @@ _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
_boxes_for_traps (&boxes, traps, antialias);
return _clip_and_composite_boxes (dst, op, src,
- &boxes, antialias,
- extents, clip);
+ &boxes, extents);
}
/* No fast path, exclude self-intersections and clip trapezoids. */
@@ -3204,27 +3160,7 @@ _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
info.antialias = antialias;
return _clip_and_composite (dst, op, src,
_composite_traps, &info,
- extents, clip);
-}
-
-static cairo_clip_path_t *
-_clip_get_single_path (cairo_clip_t *clip)
-{
- cairo_clip_path_t *iter = clip->path;
- cairo_clip_path_t *path = NULL;
-
- /* Boxes only effect the extents, so discard any outer boxes. */
- do {
- if (path != NULL)
- return FALSE;
-
- if ((iter->flags & CAIRO_CLIP_PATH_IS_BOX) == 0)
- path = iter;
-
- iter = iter->prev;
- } while (iter != NULL);
-
- return path;
+ extents);
}
/* high level image interface */
@@ -3233,16 +3169,12 @@ static cairo_int_status_t
_cairo_image_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
- cairo_clip_path_t *clip_path;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
cairo_status_t status;
+ cairo_boxes_t boxes;
status = _cairo_composite_rectangles_init_for_paint (&extents,
surface->width,
@@ -3252,53 +3184,20 @@ _cairo_image_surface_paint (void *abstract_surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
/* If the clip cannot be reduced to a set of boxes, we will need to
* use a clipmask. Paint is special as it is the only operation that
* does not implicitly use a mask, so we may be able to reduce this
* operation to a fill...
*/
- if (clip != NULL &&
- extents.is_bounded &&
- (clip_path = _clip_get_single_path (clip)) != NULL)
- {
- status = _cairo_image_surface_fill (surface, op, source,
- &clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- clip_path->antialias,
- NULL);
- }
- else
- {
- cairo_boxes_t boxes;
- _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
+ status = _cairo_clip_to_boxes (extents.clip, &boxes);
+ if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, CAIRO_ANTIALIAS_DEFAULT,
- &extents, clip);
+ &boxes, &extents);
+ _cairo_boxes_fini (&boxes);
}
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -3311,7 +3210,7 @@ _composite_mask (void *closure,
const cairo_pattern_t *src_pattern,
int dst_x,
int dst_y,
- cairo_matrix_t *dst_device_transform,
+ cairo_matrix_t *dst_device_transform,
const cairo_rectangle_int_t *extents,
cairo_region_t *clip_region)
{
@@ -3321,11 +3220,15 @@ _composite_mask (void *closure,
int mask_x = 0, mask_y = 0;
if (src_pattern != NULL) {
- src = _pixman_image_for_pattern (src_pattern, FALSE, extents, dst_device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (src_pattern, FALSE, extents,
+ dst_device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- mask = _pixman_image_for_pattern (mask_pattern, TRUE, extents, dst_device_transform, &mask_x, &mask_y);
+ mask = _pixman_image_for_pattern (mask_pattern, TRUE, extents,
+ dst_device_transform,
+ &mask_x, &mask_y);
if (unlikely (mask == NULL)) {
pixman_image_unref (src);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -3334,7 +3237,9 @@ _composite_mask (void *closure,
if (mask_pattern->has_component_alpha)
pixman_image_set_component_alpha (mask, TRUE);
} else {
- src = _pixman_image_for_pattern (mask_pattern, FALSE, extents, dst_device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (mask_pattern, FALSE, extents,
+ dst_device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
@@ -3357,12 +3262,10 @@ _cairo_image_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
cairo_status_t status;
status = _cairo_composite_rectangles_init_for_mask (&extents,
@@ -3371,26 +3274,11 @@ _cairo_image_surface_mask (void *abstract_surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL && extents.is_bounded) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- status = _cairo_clip_rectangle (clip, &extents.bounded);
- if (unlikely (status)) {
- _cairo_clip_fini (&local_clip);
- return status;
- }
-
- have_clip = TRUE;
- }
-
status = _clip_and_composite (surface, op, source,
_composite_mask, (void *) mask,
- &extents, clip);
+ &extents);
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -3410,7 +3298,7 @@ _composite_spans (void *closure,
const cairo_pattern_t *pattern,
int dst_x,
int dst_y,
- cairo_matrix_t *dst_device_transform,
+ cairo_matrix_t *dst_device_transform,
const cairo_rectangle_int_t *extents,
cairo_region_t *clip_region)
{
@@ -3494,7 +3382,9 @@ _composite_spans (void *closure,
pixman_image_t *src;
int src_x, src_y;
- src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, extents,
+ dst_device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_RENDERER;
@@ -3527,8 +3417,7 @@ _clip_and_composite_polygon (cairo_image_surface_t *dst,
cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule,
cairo_antialias_t antialias,
- cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
+ cairo_composite_rectangles_t *extents)
{
cairo_status_t status;
@@ -3541,7 +3430,7 @@ _clip_and_composite_polygon (cairo_image_surface_t *dst,
_cairo_traps_init (&traps);
status = _clip_and_composite_trapezoids (dst, op, src,
&traps, antialias,
- extents, clip);
+ extents);
_cairo_traps_fini (&traps);
return status;
@@ -3560,7 +3449,7 @@ _clip_and_composite_polygon (cairo_image_surface_t *dst,
status = _clip_and_composite (dst, op, src,
_composite_spans, &info,
- extents, clip);
+ extents);
} else {
cairo_traps_t traps;
@@ -3573,7 +3462,7 @@ _clip_and_composite_polygon (cairo_image_surface_t *dst,
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _clip_and_composite_trapezoids (dst, op, src,
&traps, antialias,
- extents, clip);
+ extents);
}
_cairo_traps_fini (&traps);
@@ -3586,21 +3475,17 @@ static cairo_int_status_t
_cairo_image_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_composite_rectangles_init_for_stroke (&extents,
surface->width,
@@ -3611,80 +3496,42 @@ _cairo_image_surface_stroke (void *abstract_surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
cairo_boxes_t boxes;
- _cairo_boxes_init (&boxes);
- if (num_boxes == 0) {
- /* When compositing with the span renderer, we limit the mask
- * to the bounded area, and so we must also constrain the path
- * appropriately. (Unlike the other compositing paths
- * where the operation itself is limited to extents.)
- */
- boxes_stack[0].p1.x = extents.bounded.x;
- boxes_stack[0].p1.y = extents.bounded.y;
- boxes_stack[0].p2.x = extents.bounded.x + extents.bounded.width;
- boxes_stack[0].p2.y = extents.bounded.y + extents.bounded.height;
-
- clip_boxes = boxes_stack;
- num_boxes = 1;
- }
- _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
-
+ _cairo_boxes_init_with_clip (&boxes, extents.clip);
status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
style,
ctm,
+ antialias,
&boxes);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, antialias,
- &extents, clip);
+ &boxes, &extents);
}
-
_cairo_boxes_fini (&boxes);
}
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
cairo_polygon_t polygon;
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
-
+ _cairo_polygon_init_with_clip (&polygon, extents.clip);
status = _cairo_path_fixed_stroke_to_polygon (path,
style,
ctm, ctm_inverse,
tolerance,
&polygon);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
status = _clip_and_composite_polygon (surface, op, source, &polygon,
- CAIRO_FILL_RULE_WINDING, antialias,
- &extents, clip);
+ CAIRO_FILL_RULE_WINDING,
+ antialias,
+ &extents);
}
-
_cairo_polygon_fini (&polygon);
}
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -3693,18 +3540,14 @@ static cairo_int_status_t
_cairo_image_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
cairo_status_t status;
status = _cairo_composite_rectangles_init_for_fill (&extents,
@@ -3715,84 +3558,35 @@ _cairo_image_surface_fill (void *abstract_surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (extents.is_bounded && clip != NULL) {
- cairo_clip_path_t *clip_path;
-
- if (((clip_path = _clip_get_single_path (clip)) != NULL) &&
- _cairo_path_fixed_equal (&clip_path->path, path))
- {
- clip = NULL;
- }
- }
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
if (_cairo_path_fixed_fill_is_rectilinear (path)) {
cairo_boxes_t boxes;
- _cairo_boxes_init (&boxes);
- if (num_boxes == 0) {
- /* When compositing with the span renderer, we limit the mask
- * to the bounded area, and so we must also constrain the path
- * appropriately. (Unlike the other compositing paths
- * where the operation itself is limited to extents.)
- */
- boxes_stack[0].p1.x = extents.bounded.x;
- boxes_stack[0].p1.y = extents.bounded.y;
- boxes_stack[0].p2.x = extents.bounded.x + extents.bounded.width;
- boxes_stack[0].p2.y = extents.bounded.y + extents.bounded.height;
-
- clip_boxes = boxes_stack;
- num_boxes = 1;
- }
- _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
-
+ _cairo_boxes_init_with_clip (&boxes, extents.clip);
status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
fill_rule,
+ antialias,
&boxes);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, antialias,
- &extents, clip);
+ &boxes, &extents);
}
-
_cairo_boxes_fini (&boxes);
} else {
cairo_polygon_t polygon;
assert (! _cairo_path_fixed_fill_is_empty (path));
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
-
+ _cairo_polygon_init_with_clip (&polygon, extents.clip);
status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _clip_and_composite_polygon (surface, op, source, &polygon,
fill_rule, antialias,
- &extents, clip);
+ &extents);
}
-
_cairo_polygon_fini (&polygon);
}
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -3811,7 +3605,7 @@ _composite_glyphs_via_mask (void *closure,
const cairo_pattern_t *pattern,
int dst_x,
int dst_y,
- cairo_matrix_t *dst_device_transform,
+ cairo_matrix_t *dst_device_transform,
const cairo_rectangle_int_t *extents,
cairo_region_t *clip_region)
{
@@ -3827,7 +3621,9 @@ _composite_glyphs_via_mask (void *closure,
int src_x, src_y;
int i;
- src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, extents,
+ dst_device_transform,
+ &src_x, &src_y);
if (unlikely (src == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -3961,7 +3757,9 @@ _composite_glyphs (void *closure,
int i;
if (pattern != NULL) {
- src = _pixman_image_for_pattern (pattern, FALSE, extents, dst_device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (pattern, FALSE, extents,
+ dst_device_transform,
+ &src_x, &src_y);
src_x -= dst_x;
src_y -= dst_y;
} else {
@@ -4042,16 +3840,14 @@ _cairo_image_surface_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *num_remaining)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
composite_glyphs_info_t glyph_info;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- cairo_bool_t overlap;
cairo_status_t status;
+ cairo_bool_t overlap;
status = _cairo_composite_rectangles_init_for_glyphs (&extents,
surface->width,
@@ -4064,20 +3860,6 @@ _cairo_image_surface_glyphs (void *abstract_surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_rectangle (clip, &extents.mask))
- clip = NULL;
-
- if (clip != NULL && extents.is_bounded) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- status = _cairo_clip_rectangle (clip, &extents.bounded);
- if (unlikely (status)) {
- _cairo_clip_fini (&local_clip);
- return status;
- }
-
- have_clip = TRUE;
- }
-
glyph_info.font = scaled_font;
glyph_info.glyphs = glyphs;
glyph_info.num_glyphs = num_glyphs;
@@ -4085,10 +3867,9 @@ _cairo_image_surface_glyphs (void *abstract_surface,
status = _clip_and_composite (surface, op, source,
overlap || extents.is_bounded == 0 ? _composite_glyphs_via_mask : _composite_glyphs,
&glyph_info,
- &extents, clip);
+ &extents);
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
*num_remaining = 0;
return status;
@@ -4228,7 +4009,9 @@ _cairo_image_surface_composite (cairo_operator_t op,
extents.is_bounded = _cairo_operator_bounded_by_either (op);
- src = _pixman_image_for_pattern (src_pattern, FALSE, &extents.source, &dst->base.device_transform, &src_offset_x, &src_offset_y);
+ src = _pixman_image_for_pattern (src_pattern, FALSE, &extents.source,
+ &dst->base.device_transform,
+ &src_offset_x, &src_offset_y);
if (unlikely (src == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -4237,7 +4020,9 @@ _cairo_image_surface_composite (cairo_operator_t op,
pixman_image_t *mask;
int mask_offset_x, mask_offset_y;
- mask = _pixman_image_for_pattern (mask_pattern, TRUE, &extents.mask, &dst->base.device_transform, &mask_offset_x, &mask_offset_y);
+ mask = _pixman_image_for_pattern (mask_pattern, TRUE, &extents.mask,
+ &dst->base.device_transform,
+ &mask_offset_x, &mask_offset_y);
if (unlikely (mask == NULL)) {
pixman_image_unref (src);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -4507,7 +4292,9 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer)
return status;
}
- src = _pixman_image_for_pattern (renderer->pattern, FALSE, &rects->bounded, &renderer->dst->base.device_transform, &src_x, &src_y);
+ src = _pixman_image_for_pattern (renderer->pattern, FALSE, &rects->bounded,
+ &renderer->dst->base.device_transform,
+ &src_x, &src_y);
if (src == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index 926d3aa..c04fe11 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -41,7 +41,7 @@
#include "cairoint.h"
#include "cairo-error-private.h"
-COMPILE_TIME_ASSERT (CAIRO_STATUS_LAST_STATUS < CAIRO_INT_STATUS_UNSUPPORTED);
+COMPILE_TIME_ASSERT ((int)CAIRO_STATUS_LAST_STATUS < (int)CAIRO_INT_STATUS_UNSUPPORTED);
COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
/**
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 74c8468..e876127 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -279,7 +279,7 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
cairo_status_t status;
cairo_surface_t *image;
cairo_surface_pattern_t pattern;
- cairo_clip_t clip;
+ cairo_clip_t *clip;
x = rect->x;
y = rect->y;
@@ -304,15 +304,14 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
* filtering (if possible) to avoid introducing potential artifacts. */
pattern.base.filter = CAIRO_FILTER_NEAREST;
- _cairo_clip_init (&clip);
- status = _cairo_clip_rectangle (&clip, rect);
+ clip = _cairo_clip_intersect_rectangle (NULL, rect);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _cairo_surface_paint (surface->target,
CAIRO_OPERATOR_SOURCE,
- &pattern.base, &clip);
+ &pattern.base, clip);
}
- _cairo_clip_fini (&clip);
+ _cairo_clip_destroy (clip);
_cairo_pattern_fini (&pattern.base);
CLEANUP_IMAGE:
@@ -325,7 +324,7 @@ static cairo_int_status_t
_paint_page (cairo_paginated_surface_t *surface)
{
cairo_surface_t *analysis;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback;
if (unlikely (surface->target->status))
@@ -340,7 +339,7 @@ _paint_page (cairo_paginated_surface_t *surface)
status = _cairo_recording_surface_replay_and_create_regions (surface->recording_surface,
analysis);
if (status || analysis->status) {
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = analysis->status;
goto FAIL;
}
@@ -542,7 +541,7 @@ static cairo_int_status_t
_cairo_paginated_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_paginated_surface_t *surface = abstract_surface;
@@ -554,7 +553,7 @@ _cairo_paginated_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_paginated_surface_t *surface = abstract_surface;
@@ -565,13 +564,13 @@ static cairo_int_status_t
_cairo_paginated_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_paginated_surface_t *surface = abstract_surface;
@@ -586,11 +585,11 @@ static cairo_int_status_t
_cairo_paginated_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_paginated_surface_t *surface = abstract_surface;
@@ -620,7 +619,7 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_paginated_surface_t *surface = abstract_surface;
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 204b982..1fc9a06 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -37,6 +37,7 @@
#include "cairoint.h"
#include "cairo-box-private.h"
+#include "cairo-error-private.h"
#include "cairo-path-fixed-private.h"
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index 6074a52..b15b1a4 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -120,6 +120,86 @@ _cairo_path_fixed_fill_to_polygon (const cairo_path_fixed_t *path,
return _cairo_filler_close (&filler);
}
+typedef struct cairo_filler_rectilinear_aligned {
+ cairo_polygon_t *polygon;
+
+ cairo_point_t current_point;
+ cairo_point_t last_move_to;
+} cairo_filler_ra_t;
+
+static cairo_status_t
+_cairo_filler_ra_line_to (void *closure,
+ const cairo_point_t *point)
+{
+ cairo_filler_ra_t *filler = closure;
+ cairo_status_t status;
+ cairo_point_t p;
+
+ p.x = _cairo_fixed_round_down (point->x);
+ p.y = _cairo_fixed_round_down (point->y);
+
+ status = _cairo_polygon_add_external_edge (filler->polygon,
+ &filler->current_point,
+ &p);
+
+ filler->current_point = p;
+
+ return status;
+}
+
+static cairo_status_t
+_cairo_filler_ra_move_to (void *closure,
+ const cairo_point_t *point)
+{
+ cairo_filler_t *filler = closure;
+ cairo_status_t status;
+ cairo_point_t p;
+
+ /* close current subpath */
+ status = _cairo_filler_close (closure);
+ if (unlikely (status))
+ return status;
+
+ p.x = _cairo_fixed_round_down (point->x);
+ p.y = _cairo_fixed_round_down (point->y);
+
+ /* make sure that the closure represents a degenerate path */
+ filler->current_point = p;
+ filler->last_move_to = p;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_path_fixed_fill_rectilinear_to_polygon (const cairo_path_fixed_t *path,
+ cairo_antialias_t antialias,
+ cairo_polygon_t *polygon)
+{
+ cairo_filler_ra_t filler;
+ cairo_status_t status;
+
+ if (antialias != CAIRO_ANTIALIAS_NONE)
+ return _cairo_path_fixed_fill_to_polygon (path, 0., polygon);
+
+ filler.polygon = polygon;
+
+ /* make sure that the closure represents a degenerate path */
+ filler.current_point.x = 0;
+ filler.current_point.y = 0;
+ filler.last_move_to = filler.current_point;
+
+ status = _cairo_path_fixed_interpret_flat (path,
+ _cairo_filler_ra_move_to,
+ _cairo_filler_ra_line_to,
+ _cairo_filler_close,
+ &filler,
+ 0.);
+ if (unlikely (status))
+ return status;
+
+ return _cairo_filler_close (&filler);
+}
+
cairo_status_t
_cairo_path_fixed_fill_to_traps (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
@@ -170,12 +250,15 @@ _cairo_path_fixed_fill_rectilinear_tessellate_to_region (const cairo_path_fixed_
_cairo_traps_init (&traps);
status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
fill_rule,
+ CAIRO_ANTIALIAS_NONE,
&traps);
if (_cairo_status_is_error (status))
goto CLEANUP_TRAPS;
if (status == CAIRO_STATUS_SUCCESS) {
- status = _cairo_traps_extract_region (&traps, ®ion);
+ status = _cairo_traps_extract_region (&traps,
+ CAIRO_ANTIALIAS_NONE,
+ ®ion);
goto CLEANUP_TRAPS;
}
@@ -200,7 +283,9 @@ _cairo_path_fixed_fill_rectilinear_tessellate_to_region (const cairo_path_fixed_
&polygon,
fill_rule);
if (likely (status == CAIRO_STATUS_SUCCESS))
- status = _cairo_traps_extract_region (&traps, ®ion);
+ status = _cairo_traps_extract_region (&traps,
+ CAIRO_ANTIALIAS_NONE,
+ ®ion);
}
CLEANUP_POLYGON:
@@ -338,6 +423,7 @@ TESSELLATE:
cairo_int_status_t
_cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias,
cairo_traps_t *traps)
{
cairo_box_t box;
@@ -347,6 +433,12 @@ _cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path,
traps->is_rectangular = TRUE;
if (_cairo_path_fixed_is_box (path, &box)) {
+ if (antialias == CAIRO_ANTIALIAS_NONE) {
+ box.p1.x = _cairo_fixed_round_down (box.p1.x);
+ box.p1.y = _cairo_fixed_round_down (box.p1.y);
+ box.p2.x = _cairo_fixed_round_down (box.p2.x);
+ box.p2.y = _cairo_fixed_round_down (box.p2.y);
+ }
return _cairo_traps_tessellate_rectangle (traps, &box.p1, &box.p2);
} else {
cairo_path_fixed_iter_t iter;
@@ -365,6 +457,13 @@ _cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path,
box.p2.x = t;
}
+ if (antialias == CAIRO_ANTIALIAS_NONE) {
+ box.p1.x = _cairo_fixed_round_down (box.p1.x);
+ box.p1.y = _cairo_fixed_round_down (box.p1.y);
+ box.p2.x = _cairo_fixed_round_down (box.p2.x);
+ box.p2.y = _cairo_fixed_round_down (box.p2.y);
+ }
+
status = _cairo_traps_tessellate_rectangle (traps,
&box.p1, &box.p2);
if (unlikely (status)) {
@@ -384,6 +483,7 @@ _cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path,
static cairo_status_t
_cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias,
cairo_boxes_t *boxes)
{
cairo_polygon_t polygon;
@@ -393,7 +493,7 @@ _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (const cairo_path_fixed_t
boxes->num_limits = 0;
/* tolerance will be ignored as the path is rectilinear */
- status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
+ status = _cairo_path_fixed_fill_rectilinear_to_polygon (path, antialias, &polygon);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status =
_cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (&polygon,
@@ -409,6 +509,7 @@ _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (const cairo_path_fixed_t
cairo_status_t
_cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias,
cairo_boxes_t *boxes)
{
cairo_path_fixed_iter_t iter;
@@ -416,7 +517,7 @@ _cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
cairo_box_t box;
if (_cairo_path_fixed_is_box (path, &box))
- return _cairo_boxes_add (boxes, &box);
+ return _cairo_boxes_add (boxes, antialias, &box);
_cairo_path_fixed_iter_init (&iter, path);
while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) {
@@ -435,7 +536,7 @@ _cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
box.p2.x = t;
}
- status = _cairo_boxes_add (boxes, &box);
+ status = _cairo_boxes_add (boxes, antialias, &box);
if (unlikely (status))
return status;
}
@@ -447,5 +548,6 @@ _cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
_cairo_boxes_clear (boxes);
return _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (path,
fill_rule,
+ antialias,
boxes);
}
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 6b0df9c..31ce1ac 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -1402,6 +1402,7 @@ _cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
status = _cairo_path_fixed_stroke_rectilinear_to_traps (path,
stroke_style,
ctm,
+ CAIRO_ANTIALIAS_DEFAULT,
traps);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -1440,6 +1441,7 @@ typedef struct _segment_t {
typedef struct _cairo_rectilinear_stroker {
const cairo_stroke_style_t *stroke_style;
const cairo_matrix_t *ctm;
+ cairo_antialias_t antialias;
cairo_fixed_t half_line_width;
cairo_bool_t do_traps;
@@ -1478,6 +1480,7 @@ static cairo_bool_t
_cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t *stroker,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
+ cairo_antialias_t antialias,
cairo_bool_t do_traps,
void *container)
{
@@ -1512,6 +1515,7 @@ _cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t *stroker,
stroker->stroke_style = stroke_style;
stroker->ctm = ctm;
+ stroker->antialias = antialias;
stroker->half_line_width =
_cairo_fixed_from_double (stroke_style->line_width / 2.0);
@@ -1687,6 +1691,12 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
}
if (stroker->do_traps) {
+ if (stroker->antialias == CAIRO_ANTIALIAS_NONE) {
+ a->x = _cairo_fixed_round_down (a->x);
+ a->y = _cairo_fixed_round_down (a->y);
+ b->x = _cairo_fixed_round_down (b->x);
+ b->y = _cairo_fixed_round_down (b->y);
+ }
status = _cairo_traps_tessellate_rectangle (stroker->container, a, b);
} else {
cairo_box_t box;
@@ -1694,7 +1704,7 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
box.p1 = *a;
box.p2 = *b;
- status = _cairo_boxes_add (stroker->container, &box);
+ status = _cairo_boxes_add (stroker->container, stroker->antialias, &box);
}
if (unlikely (status))
return status;
@@ -1762,6 +1772,12 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
}
if (stroker->do_traps) {
+ if (stroker->antialias == CAIRO_ANTIALIAS_NONE) {
+ p1.x = _cairo_fixed_round_down (p1.x);
+ p1.y = _cairo_fixed_round_down (p1.y);
+ p2.x = _cairo_fixed_round_down (p2.x);
+ p2.y = _cairo_fixed_round_down (p2.y);
+ }
status = _cairo_traps_tessellate_rectangle (stroker->container, &p1, &p2);
} else {
cairo_box_t box;
@@ -1769,7 +1785,7 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
box.p1 = p1;
box.p2 = p2;
- status = _cairo_boxes_add (stroker->container, &box);
+ status = _cairo_boxes_add (stroker->container, stroker->antialias, &box);
}
if (unlikely (status))
return status;
@@ -1824,6 +1840,12 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
continue;
if (stroker->do_traps) {
+ if (stroker->antialias == CAIRO_ANTIALIAS_NONE) {
+ a->x = _cairo_fixed_round_down (a->x);
+ a->y = _cairo_fixed_round_down (a->y);
+ b->x = _cairo_fixed_round_down (b->x);
+ b->y = _cairo_fixed_round_down (b->y);
+ }
status = _cairo_traps_tessellate_rectangle (stroker->container, a, b);
} else {
cairo_box_t box;
@@ -1831,7 +1853,7 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
box.p1 = *a;
box.p2 = *b;
- status = _cairo_boxes_add (stroker->container, &box);
+ status = _cairo_boxes_add (stroker->container, stroker->antialias, &box);
}
if (unlikely (status))
return status;
@@ -2029,6 +2051,7 @@ cairo_int_status_t
_cairo_path_fixed_stroke_rectilinear_to_traps (const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
+ cairo_antialias_t antialias,
cairo_traps_t *traps)
{
cairo_rectilinear_stroker_t rectilinear_stroker;
@@ -2037,7 +2060,7 @@ _cairo_path_fixed_stroke_rectilinear_to_traps (const cairo_path_fixed_t *path,
assert (_cairo_path_fixed_stroke_is_rectilinear (path));
if (! _cairo_rectilinear_stroker_init (&rectilinear_stroker,
- stroke_style, ctm,
+ stroke_style, ctm, antialias,
TRUE, traps))
{
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -2082,6 +2105,7 @@ cairo_int_status_t
_cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
+ cairo_antialias_t antialias,
cairo_boxes_t *boxes)
{
cairo_rectilinear_stroker_t rectilinear_stroker;
@@ -2090,7 +2114,7 @@ _cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t *path,
assert (_cairo_path_fixed_stroke_is_rectilinear (path));
if (! _cairo_rectilinear_stroker_init (&rectilinear_stroker,
- stroke_style, ctm,
+ stroke_style, ctm, antialias,
FALSE, boxes))
{
return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index b14a5f8..bb4c643 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -2118,7 +2118,7 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
pixman_transform_t pixman_transform;
cairo_circle_double_t extremes[2];
pixman_point_fixed_t p1, p2;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_bool_t repeat = FALSE;
int ix, iy;
pixman_gradient_stop_t pixman_stops_static[2];
@@ -2241,7 +2241,7 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat
&pixman_transform,
&ix, &iy);
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
- if (unlikely (status != CAIRO_STATUS_SUCCESS) ||
+ if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
! pixman_image_set_transform (pixman_image, &pixman_transform))
{
cairo_surface_destroy (&image->base);
diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
index 14d60b6..48ae6b5 100644
--- a/src/cairo-pdf-operators-private.h
+++ b/src/cairo-pdf-operators-private.h
@@ -129,8 +129,8 @@ cairo_private void
_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators);
cairo_private cairo_int_status_t
-_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule);
cairo_private cairo_int_status_t
@@ -140,19 +140,19 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
cairo_private cairo_int_status_t
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse);
cairo_private cairo_int_status_t
-_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule);
+_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
+ const cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule);
cairo_private cairo_int_status_t
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 0f2500e..58c6472 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -493,7 +493,7 @@ _cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
*/
static cairo_status_t
_cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_matrix_t *path_transform,
cairo_line_cap_t line_cap)
{
@@ -530,7 +530,7 @@ _cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators,
cairo_int_status_t
_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule)
{
const char *pdf_operator;
@@ -763,7 +763,7 @@ _cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
static cairo_int_status_t
_cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
@@ -854,7 +854,7 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_int_status_t
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse)
@@ -869,7 +869,7 @@ _cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_int_status_t
_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule)
{
const char *pdf_operator;
@@ -908,7 +908,7 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
cairo_int_status_t
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index dbb7228..8bfa556 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1089,12 +1089,12 @@ _get_jpeg_image_info (cairo_surface_t *source,
return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length);
}
-static cairo_status_t
+static cairo_int_status_t
_get_source_surface_size (cairo_surface_t *source,
int *width,
int *height)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_rectangle_int_t extents;
cairo_image_info_t info;
const unsigned char *mime_data;
@@ -2184,12 +2184,12 @@ static cairo_status_t
_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
cairo_surface_t *source,
cairo_pdf_resource_t resource,
- cairo_bool_t interpolate,
+ cairo_bool_t interpolate,
cairo_bool_t mask)
{
cairo_image_surface_t *image;
void *image_extra;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_pdf_surface_emit_jpx_image (surface, source, resource);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
@@ -2226,7 +2226,7 @@ _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
cairo_image_surface_t *image;
cairo_surface_t *pad_image;
void *image_extra;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
int x = 0;
int y = 0;
@@ -2276,6 +2276,7 @@ _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
}
switch (pdf_pattern->pattern->filter) {
+ default:
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
@@ -2323,7 +2324,7 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
cairo_paginated_mode_t old_paginated_mode;
cairo_rectangle_int_t recording_extents;
cairo_bool_t is_bounded;
- cairo_status_t status;
+ cairo_int_status_t status;
int alpha = 0;
is_bounded = _cairo_surface_get_extents (recording_surface, &recording_extents);
@@ -2384,7 +2385,7 @@ _cairo_pdf_surface_emit_recording_subsurface (cairo_pdf_surface_t *surface,
{
double old_width, old_height;
cairo_paginated_mode_t old_paginated_mode;
- cairo_status_t status;
+ cairo_int_status_t status;
int alpha = 0;
old_width = surface->width;
@@ -4351,6 +4352,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
if (_cairo_status_is_error (status))
return status;
+ last_glyph = font_subset->num_glyphs - 1;
if (font_subset->is_latin) {
/* find last glyph used */
for (i = 255; i >= 32; i--)
@@ -4404,7 +4406,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
tag,
subset->base_font,
font_subset->is_latin ? 32 : 0,
- font_subset->is_latin ? last_glyph : font_subset->num_glyphs - 1,
+ last_glyph,
descriptor.id);
if (font_subset->is_latin)
@@ -4741,7 +4743,7 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
return _cairo_output_stream_get_status (stream);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
@@ -4781,7 +4783,7 @@ _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_su
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
@@ -4966,12 +4968,12 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
return _cairo_array_append (&surface->fonts, &font);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_pdf_surface_t *surface = closure;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
@@ -4994,22 +4996,22 @@ _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_s
return status;
ASSERT_NOT_REACHED;
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_pdf_surface_t *surface = closure;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
ASSERT_NOT_REACHED;
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_status_t
@@ -5742,20 +5744,20 @@ static cairo_int_status_t
_cairo_pdf_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_status_t status;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_composite_rectangles_t extents;
+ cairo_int_status_t status;
status = _cairo_composite_rectangles_init_for_paint (&extents,
surface->width, surface->height,
op, source, clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
return status;
}
@@ -5859,12 +5861,12 @@ _cairo_pdf_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_smask_group_t *group;
- cairo_status_t status;
cairo_composite_rectangles_t extents;
+ cairo_int_status_t status;
status = _cairo_composite_rectangles_init_for_mask (&extents,
surface->width, surface->height,
@@ -5966,19 +5968,19 @@ static cairo_int_status_t
_cairo_pdf_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_composite_rectangles_t extents;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_composite_rectangles_init_for_stroke (&extents,
surface->width,
@@ -5988,7 +5990,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
return status;
}
@@ -6003,7 +6005,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
return status;
if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@@ -6021,7 +6023,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
if (unlikely (status))
return status;
@@ -6097,14 +6099,14 @@ static cairo_int_status_t
_cairo_pdf_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_composite_rectangles_t extents;
@@ -6116,7 +6118,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
clip);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
return status;
}
@@ -6129,7 +6131,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
&extents.mask);
if (! _cairo_rectangle_intersect (&extents.bounded, &extents.mask))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
@@ -6180,7 +6182,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
if (unlikely (status))
return status;
@@ -6251,7 +6253,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
cairo_fill_rule_t fill_rule,
double fill_tolerance,
cairo_antialias_t fill_antialias,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_operator_t stroke_op,
const cairo_pattern_t *stroke_source,
const cairo_stroke_style_t *stroke_style,
@@ -6259,10 +6261,10 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
const cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
cairo_composite_rectangles_t extents;
@@ -6408,14 +6410,14 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_pdf_smask_group_t *group;
cairo_pdf_resource_t pattern_res, gstate_res;
cairo_composite_rectangles_t extents;
cairo_bool_t overlap;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_composite_rectangles_init_for_glyphs (&extents,
surface->width,
@@ -6427,7 +6429,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
&overlap);
if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
return status;
}
@@ -6447,7 +6449,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
if (unlikely (status))
return status;
diff --git a/src/cairo-png.c b/src/cairo-png.c
index 5cb132e..5468096 100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -169,7 +169,7 @@ write_png (cairo_surface_t *surface,
void *closure)
{
int i;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_image_surface_t *image;
cairo_image_surface_t * volatile clone;
void *image_extra;
diff --git a/src/cairo-polygon-intersect.c b/src/cairo-polygon-intersect.c
new file mode 100644
index 0000000..e2ed6e9
--- /dev/null
+++ b/src/cairo-polygon-intersect.c
@@ -0,0 +1,1466 @@
+/*
+ * Copyright © 2004 Carl Worth
+ * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2008 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Carl Worth
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth at cworth.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+/* Provide definitions for standalone compilation */
+#include "cairoint.h"
+
+#include "cairo-error-private.h"
+#include "cairo-freelist-private.h"
+#include "cairo-combsort-private.h"
+
+typedef cairo_point_t cairo_bo_point32_t;
+
+typedef struct _cairo_bo_intersect_ordinate {
+ int32_t ordinate;
+ enum { EXACT, INEXACT } exactness;
+} cairo_bo_intersect_ordinate_t;
+
+typedef struct _cairo_bo_intersect_point {
+ cairo_bo_intersect_ordinate_t x;
+ cairo_bo_intersect_ordinate_t y;
+} cairo_bo_intersect_point_t;
+
+typedef struct _cairo_bo_edge cairo_bo_edge_t;
+
+typedef struct _cairo_bo_deferred {
+ cairo_bo_edge_t *other;
+ int32_t top;
+ int dir;
+} cairo_bo_deferred_t;
+
+struct _cairo_bo_edge {
+ int a_or_b;
+ cairo_edge_t edge;
+ cairo_bo_edge_t *prev;
+ cairo_bo_edge_t *next;
+ cairo_bo_deferred_t deferred;
+};
+
+/* the parent is always given by index/2 */
+#define PQ_PARENT_INDEX(i) ((i) >> 1)
+#define PQ_FIRST_ENTRY 1
+
+/* left and right children are index * 2 and (index * 2) +1 respectively */
+#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
+
+typedef enum {
+ CAIRO_BO_EVENT_TYPE_STOP,
+ CAIRO_BO_EVENT_TYPE_INTERSECTION,
+ CAIRO_BO_EVENT_TYPE_START
+} cairo_bo_event_type_t;
+
+typedef struct _cairo_bo_event {
+ cairo_bo_event_type_t type;
+ cairo_point_t point;
+} cairo_bo_event_t;
+
+typedef struct _cairo_bo_start_event {
+ cairo_bo_event_type_t type;
+ cairo_point_t point;
+ cairo_bo_edge_t edge;
+} cairo_bo_start_event_t;
+
+typedef struct _cairo_bo_queue_event {
+ cairo_bo_event_type_t type;
+ cairo_point_t point;
+ cairo_bo_edge_t *e1;
+ cairo_bo_edge_t *e2;
+} cairo_bo_queue_event_t;
+
+typedef struct _pqueue {
+ int size, max_size;
+
+ cairo_bo_event_t **elements;
+ cairo_bo_event_t *elements_embedded[1024];
+} pqueue_t;
+
+typedef struct _cairo_bo_event_queue {
+ cairo_freepool_t pool;
+ pqueue_t pqueue;
+ cairo_bo_event_t **start_events;
+} cairo_bo_event_queue_t;
+
+typedef struct _cairo_bo_sweep_line {
+ cairo_bo_edge_t *head;
+ int32_t current_y;
+ cairo_bo_edge_t *current_edge;
+} cairo_bo_sweep_line_t;
+
+static cairo_fixed_t
+_line_compute_intersection_x_for_y (const cairo_line_t *line,
+ cairo_fixed_t y)
+{
+ cairo_fixed_t x, dy;
+
+ if (y == line->p1.y)
+ return line->p1.x;
+ if (y == line->p2.y)
+ return line->p2.x;
+
+ x = line->p1.x;
+ dy = line->p2.y - line->p1.y;
+ if (dy != 0) {
+ x += _cairo_fixed_mul_div_floor (y - line->p1.y,
+ line->p2.x - line->p1.x,
+ dy);
+ }
+
+ return x;
+}
+
+static inline int
+_cairo_bo_point32_compare (cairo_bo_point32_t const *a,
+ cairo_bo_point32_t const *b)
+{
+ int cmp;
+
+ cmp = a->y - b->y;
+ if (cmp)
+ return cmp;
+
+ return a->x - b->x;
+}
+
+/* Compare the slope of a to the slope of b, returning 1, 0, -1 if the
+ * slope a is respectively greater than, equal to, or less than the
+ * slope of b.
+ *
+ * For each edge, consider the direction vector formed from:
+ *
+ * top -> bottom
+ *
+ * which is:
+ *
+ * (dx, dy) = (line.p2.x - line.p1.x, line.p2.y - line.p1.y)
+ *
+ * We then define the slope of each edge as dx/dy, (which is the
+ * inverse of the slope typically used in math instruction). We never
+ * compute a slope directly as the value approaches infinity, but we
+ * can derive a slope comparison without division as follows, (where
+ * the ? represents our compare operator).
+ *
+ * 1. slope(a) ? slope(b)
+ * 2. adx/ady ? bdx/bdy
+ * 3. (adx * bdy) ? (bdx * ady)
+ *
+ * Note that from step 2 to step 3 there is no change needed in the
+ * sign of the result since both ady and bdy are guaranteed to be
+ * greater than or equal to 0.
+ *
+ * When using this slope comparison to sort edges, some care is needed
+ * when interpreting the results. Since the slope compare operates on
+ * distance vectors from top to bottom it gives a correct left to
+ * right sort for edges that have a common top point, (such as two
+ * edges with start events at the same location). On the other hand,
+ * the sense of the result will be exactly reversed for two edges that
+ * have a common stop point.
+ */
+static inline int
+_slope_compare (const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b)
+{
+ /* XXX: We're assuming here that dx and dy will still fit in 32
+ * bits. That's not true in general as there could be overflow. We
+ * should prevent that before the tessellation algorithm
+ * begins.
+ */
+ int32_t adx = a->edge.line.p2.x - a->edge.line.p1.x;
+ int32_t bdx = b->edge.line.p2.x - b->edge.line.p1.x;
+
+ /* Since the dy's are all positive by construction we can fast
+ * path several common cases.
+ */
+
+ /* First check for vertical lines. */
+ if (adx == 0)
+ return -bdx;
+ if (bdx == 0)
+ return adx;
+
+ /* Then where the two edges point in different directions wrt x. */
+ if ((adx ^ bdx) < 0)
+ return adx;
+
+ /* Finally we actually need to do the general comparison. */
+ {
+ int32_t ady = a->edge.line.p2.y - a->edge.line.p1.y;
+ int32_t bdy = b->edge.line.p2.y - b->edge.line.p1.y;
+ cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+ cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
+
+ return _cairo_int64_cmp (adx_bdy, bdx_ady);
+ }
+}
+
+/*
+ * We need to compare the x-coordinates of a pair of lines for a particular y,
+ * without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ * X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ * A_x + (Y - A_y) * A_dx / A_dy â B_x + (Y - B_y) * B_dx / B_dy,
+ * where â is our inequality operator.
+ *
+ * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ * A_dy * B_dy * (A_x - B_x) â (Y - B_y) * B_dx * A_dy
+ * - (Y - A_y) * A_dx * B_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 128 bit arithmetic. For certain, but common,
+ * input we can reduce this down to a single 32 bit compare by inspecting the
+ * deltas.
+ *
+ * (And put the burden of the work on developing fast 128 bit ops, which are
+ * required throughout the tessellator.)
+ *
+ * See the similar discussion for _slope_compare().
+ */
+static int
+edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b,
+ int32_t y)
+{
+ /* XXX: We're assuming here that dx and dy will still fit in 32
+ * bits. That's not true in general as there could be overflow. We
+ * should prevent that before the tessellation algorithm
+ * begins.
+ */
+ int32_t dx;
+ int32_t adx, ady;
+ int32_t bdx, bdy;
+ enum {
+ HAVE_NONE = 0x0,
+ HAVE_DX = 0x1,
+ HAVE_ADX = 0x2,
+ HAVE_DX_ADX = HAVE_DX | HAVE_ADX,
+ HAVE_BDX = 0x4,
+ HAVE_DX_BDX = HAVE_DX | HAVE_BDX,
+ HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
+ HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX
+ } have_dx_adx_bdx = HAVE_ALL;
+
+ /* don't bother solving for abscissa if the edges' bounding boxes
+ * can be used to order them. */
+ {
+ int32_t amin, amax;
+ int32_t bmin, bmax;
+ if (a->edge.line.p1.x < a->edge.line.p2.x) {
+ amin = a->edge.line.p1.x;
+ amax = a->edge.line.p2.x;
+ } else {
+ amin = a->edge.line.p2.x;
+ amax = a->edge.line.p1.x;
+ }
+ if (b->edge.line.p1.x < b->edge.line.p2.x) {
+ bmin = b->edge.line.p1.x;
+ bmax = b->edge.line.p2.x;
+ } else {
+ bmin = b->edge.line.p2.x;
+ bmax = b->edge.line.p1.x;
+ }
+ if (amax < bmin) return -1;
+ if (amin > bmax) return +1;
+ }
+
+ ady = a->edge.line.p2.y - a->edge.line.p1.y;
+ adx = a->edge.line.p2.x - a->edge.line.p1.x;
+ if (adx == 0)
+ have_dx_adx_bdx &= ~HAVE_ADX;
+
+ bdy = b->edge.line.p2.y - b->edge.line.p1.y;
+ bdx = b->edge.line.p2.x - b->edge.line.p1.x;
+ if (bdx == 0)
+ have_dx_adx_bdx &= ~HAVE_BDX;
+
+ dx = a->edge.line.p1.x - b->edge.line.p1.x;
+ if (dx == 0)
+ have_dx_adx_bdx &= ~HAVE_DX;
+
+#define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
+#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->edge.line.p1.y)
+#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->edge.line.p1.y)
+ switch (have_dx_adx_bdx) {
+ default:
+ case HAVE_NONE:
+ return 0;
+ case HAVE_DX:
+ /* A_dy * B_dy * (A_x - B_x) â 0 */
+ return dx; /* ady * bdy is positive definite */
+ case HAVE_ADX:
+ /* 0 â - (Y - A_y) * A_dx * B_dy */
+ return adx; /* bdy * (y - a->top.y) is positive definite */
+ case HAVE_BDX:
+ /* 0 â (Y - B_y) * B_dx * A_dy */
+ return -bdx; /* ady * (y - b->top.y) is positive definite */
+ case HAVE_ADX_BDX:
+ /* 0 â (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
+ if ((adx ^ bdx) < 0) {
+ return adx;
+ } else if (a->edge.line.p1.y == b->edge.line.p1.y) { /* common origin */
+ cairo_int64_t adx_bdy, bdx_ady;
+
+ /* â´ A_dx * B_dy â B_dx * A_dy */
+
+ adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+ bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
+
+ return _cairo_int64_cmp (adx_bdy, bdx_ady);
+ } else
+ return _cairo_int128_cmp (A, B);
+ case HAVE_DX_ADX:
+ /* A_dy * (A_x - B_x) â - (Y - A_y) * A_dx */
+ if ((-adx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t ady_dx, dy_adx;
+
+ ady_dx = _cairo_int32x32_64_mul (ady, dx);
+ dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx);
+
+ return _cairo_int64_cmp (ady_dx, dy_adx);
+ }
+ case HAVE_DX_BDX:
+ /* B_dy * (A_x - B_x) â (Y - B_y) * B_dx */
+ if ((bdx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t bdy_dx, dy_bdx;
+
+ bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
+ dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.y, bdx);
+
+ return _cairo_int64_cmp (bdy_dx, dy_bdx);
+ }
+ case HAVE_ALL:
+ /* XXX try comparing (a->edge.line.p2.x - b->edge.line.p2.x) et al */
+ return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
+ }
+#undef B
+#undef A
+#undef L
+}
+
+/*
+ * We need to compare the x-coordinate of a line for a particular y wrt to a
+ * given x, without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ * X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ * A_x + (Y - A_y) * A_dx / A_dy â X
+ * where â is our inequality operator.
+ *
+ * By construction, we know that A_dy (and (Y - A_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ * (Y - A_y) * A_dx â (X - A_x) * A_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 64 bit arithmetic.
+ *
+ * See the similar discussion for _slope_compare() and
+ * edges_compare_x_for_y_general().
+ */
+static int
+edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
+ int32_t y,
+ int32_t x)
+{
+ int32_t adx, ady;
+ int32_t dx, dy;
+ cairo_int64_t L, R;
+
+ if (x < a->edge.line.p1.x && x < a->edge.line.p2.x)
+ return 1;
+ if (x > a->edge.line.p1.x && x > a->edge.line.p2.x)
+ return -1;
+
+ adx = a->edge.line.p2.x - a->edge.line.p1.x;
+ dx = x - a->edge.line.p1.x;
+
+ if (adx == 0)
+ return -dx;
+ if (dx == 0 || (adx ^ dx) < 0)
+ return adx;
+
+ dy = y - a->edge.line.p1.y;
+ ady = a->edge.line.p2.y - a->edge.line.p1.y;
+
+ L = _cairo_int32x32_64_mul (dy, adx);
+ R = _cairo_int32x32_64_mul (dx, ady);
+
+ return _cairo_int64_cmp (L, R);
+}
+
+static int
+edges_compare_x_for_y (const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b,
+ int32_t y)
+{
+ /* If the sweep-line is currently on an end-point of a line,
+ * then we know its precise x value (and considering that we often need to
+ * compare events at end-points, this happens frequently enough to warrant
+ * special casing).
+ */
+ enum {
+ HAVE_NEITHER = 0x0,
+ HAVE_AX = 0x1,
+ HAVE_BX = 0x2,
+ HAVE_BOTH = HAVE_AX | HAVE_BX
+ } have_ax_bx = HAVE_BOTH;
+ int32_t ax, bx;
+
+ if (y == a->edge.line.p1.y)
+ ax = a->edge.line.p1.x;
+ else if (y == a->edge.line.p2.y)
+ ax = a->edge.line.p2.x;
+ else
+ have_ax_bx &= ~HAVE_AX;
+
+ if (y == b->edge.line.p1.y)
+ bx = b->edge.line.p1.x;
+ else if (y == b->edge.line.p2.y)
+ bx = b->edge.line.p2.x;
+ else
+ have_ax_bx &= ~HAVE_BX;
+
+ switch (have_ax_bx) {
+ default:
+ case HAVE_NEITHER:
+ return edges_compare_x_for_y_general (a, b, y);
+ case HAVE_AX:
+ return -edge_compare_for_y_against_x (b, y, ax);
+ case HAVE_BX:
+ return edge_compare_for_y_against_x (a, y, bx);
+ case HAVE_BOTH:
+ return ax - bx;
+ }
+}
+
+static inline int
+_line_equal (const cairo_line_t *a, const cairo_line_t *b)
+{
+ return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
+ a->p2.x == b->p2.x && a->p2.y == b->p2.y;
+}
+
+static int
+_cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
+ const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b)
+{
+ int cmp;
+
+ /* compare the edges if not identical */
+ if (! _line_equal (&a->edge.line, &b->edge.line)) {
+ cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
+ if (cmp)
+ return cmp;
+
+ /* The two edges intersect exactly at y, so fall back on slope
+ * comparison. We know that this compare_edges function will be
+ * called only when starting a new edge, (not when stopping an
+ * edge), so we don't have to worry about conditionally inverting
+ * the sense of _slope_compare. */
+ cmp = _slope_compare (a, b);
+ if (cmp)
+ return cmp;
+ }
+
+ /* We've got two collinear edges now. */
+ return b->edge.bottom - a->edge.bottom;
+}
+
+static inline cairo_int64_t
+det32_64 (int32_t a, int32_t b,
+ int32_t c, int32_t d)
+{
+ /* det = a * d - b * c */
+ return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d),
+ _cairo_int32x32_64_mul (b, c));
+}
+
+static inline cairo_int128_t
+det64x32_128 (cairo_int64_t a, int32_t b,
+ cairo_int64_t c, int32_t d)
+{
+ /* det = a * d - b * c */
+ return _cairo_int128_sub (_cairo_int64x32_128_mul (a, d),
+ _cairo_int64x32_128_mul (c, b));
+}
+
+/* Compute the intersection of two lines as defined by two edges. The
+ * result is provided as a coordinate pair of 128-bit integers.
+ *
+ * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
+ * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
+ */
+static cairo_bool_t
+intersect_lines (cairo_bo_edge_t *a,
+ cairo_bo_edge_t *b,
+ cairo_bo_intersect_point_t *intersection)
+{
+ cairo_int64_t a_det, b_det;
+
+ /* XXX: We're assuming here that dx and dy will still fit in 32
+ * bits. That's not true in general as there could be overflow. We
+ * should prevent that before the tessellation algorithm begins.
+ * What we're doing to mitigate this is to perform clamping in
+ * cairo_bo_tessellate_polygon().
+ */
+ int32_t dx1 = a->edge.line.p1.x - a->edge.line.p2.x;
+ int32_t dy1 = a->edge.line.p1.y - a->edge.line.p2.y;
+
+ int32_t dx2 = b->edge.line.p1.x - b->edge.line.p2.x;
+ int32_t dy2 = b->edge.line.p1.y - b->edge.line.p2.y;
+
+ cairo_int64_t den_det;
+ cairo_int64_t R;
+ cairo_quorem64_t qr;
+
+ den_det = det32_64 (dx1, dy1, dx2, dy2);
+
+ /* Q: Can we determine that the lines do not intersect (within range)
+ * much more cheaply than computing the intersection point i.e. by
+ * avoiding the division?
+ *
+ * X = ax + t * adx = bx + s * bdx;
+ * Y = ay + t * ady = by + s * bdy;
+ * â´ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
+ * => t * L = R
+ *
+ * Therefore we can reject any intersection (under the criteria for
+ * valid intersection events) if:
+ * L^R < 0 => t < 0, or
+ * L<R => t > 1
+ *
+ * (where top/bottom must at least extend to the line endpoints).
+ *
+ * A similar substitution can be performed for s, yielding:
+ * s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
+ */
+ R = det32_64 (dx2, dy2,
+ b->edge.line.p1.x - a->edge.line.p1.x,
+ b->edge.line.p1.y - a->edge.line.p1.y);
+ if (_cairo_int64_negative (den_det)) {
+ if (_cairo_int64_ge (den_det, R))
+ return FALSE;
+ } else {
+ if (_cairo_int64_le (den_det, R))
+ return FALSE;
+ }
+
+ R = det32_64 (dy1, dx1,
+ a->edge.line.p1.y - b->edge.line.p1.y,
+ a->edge.line.p1.x - b->edge.line.p1.x);
+ if (_cairo_int64_negative (den_det)) {
+ if (_cairo_int64_ge (den_det, R))
+ return FALSE;
+ } else {
+ if (_cairo_int64_le (den_det, R))
+ return FALSE;
+ }
+
+ /* We now know that the two lines should intersect within range. */
+
+ a_det = det32_64 (a->edge.line.p1.x, a->edge.line.p1.y,
+ a->edge.line.p2.x, a->edge.line.p2.y);
+ b_det = det32_64 (b->edge.line.p1.x, b->edge.line.p1.y,
+ b->edge.line.p2.x, b->edge.line.p2.y);
+
+ /* x = det (a_det, dx1, b_det, dx2) / den_det */
+ qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
+ b_det, dx2),
+ den_det);
+ if (_cairo_int64_eq (qr.rem, den_det))
+ return FALSE;
+#if 0
+ intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
+#else
+ intersection->x.exactness = EXACT;
+ if (! _cairo_int64_is_zero (qr.rem)) {
+ if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
+ qr.rem = _cairo_int64_negate (qr.rem);
+ qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
+ if (_cairo_int64_ge (qr.rem, den_det)) {
+ qr.quo = _cairo_int64_add (qr.quo,
+ _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
+ } else
+ intersection->x.exactness = INEXACT;
+ }
+#endif
+ intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
+
+ /* y = det (a_det, dy1, b_det, dy2) / den_det */
+ qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
+ b_det, dy2),
+ den_det);
+ if (_cairo_int64_eq (qr.rem, den_det))
+ return FALSE;
+#if 0
+ intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
+#else
+ intersection->y.exactness = EXACT;
+ if (! _cairo_int64_is_zero (qr.rem)) {
+ if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
+ qr.rem = _cairo_int64_negate (qr.rem);
+ qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
+ if (_cairo_int64_ge (qr.rem, den_det)) {
+ qr.quo = _cairo_int64_add (qr.quo,
+ _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
+ } else
+ intersection->y.exactness = INEXACT;
+ }
+#endif
+ intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
+
+ return TRUE;
+}
+
+static int
+_cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t a,
+ int32_t b)
+{
+ /* First compare the quotient */
+ if (a.ordinate > b)
+ return +1;
+ if (a.ordinate < b)
+ return -1;
+ /* With quotient identical, if remainder is 0 then compare equal */
+ /* Otherwise, the non-zero remainder makes a > b */
+ return INEXACT == a.exactness;
+}
+
+/* Does the given edge contain the given point. The point must already
+ * be known to be contained within the line determined by the edge,
+ * (most likely the point results from an intersection of this edge
+ * with another).
+ *
+ * If we had exact arithmetic, then this function would simply be a
+ * matter of examining whether the y value of the point lies within
+ * the range of y values of the edge. But since intersection points
+ * are not exact due to being rounded to the nearest integer within
+ * the available precision, we must also examine the x value of the
+ * point.
+ *
+ * The definition of "contains" here is that the given intersection
+ * point will be seen by the sweep line after the start event for the
+ * given edge and before the stop event for the edge. See the comments
+ * in the implementation for more details.
+ */
+static cairo_bool_t
+_cairo_bo_edge_contains_intersect_point (cairo_bo_edge_t *edge,
+ cairo_bo_intersect_point_t *point)
+{
+ int cmp_top, cmp_bottom;
+
+ /* XXX: When running the actual algorithm, we don't actually need to
+ * compare against edge->top at all here, since any intersection above
+ * top is eliminated early via a slope comparison. We're leaving these
+ * here for now only for the sake of the quadratic-time intersection
+ * finder which needs them.
+ */
+
+ cmp_top = _cairo_bo_intersect_ordinate_32_compare (point->y,
+ edge->edge.top);
+ cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y,
+ edge->edge.bottom);
+
+ if (cmp_top < 0 || cmp_bottom > 0)
+ {
+ return FALSE;
+ }
+
+ if (cmp_top > 0 && cmp_bottom < 0)
+ {
+ return TRUE;
+ }
+
+ /* At this stage, the point lies on the same y value as either
+ * edge->top or edge->bottom, so we have to examine the x value in
+ * order to properly determine containment. */
+
+ /* If the y value of the point is the same as the y value of the
+ * top of the edge, then the x value of the point must be greater
+ * to be considered as inside the edge. Similarly, if the y value
+ * of the point is the same as the y value of the bottom of the
+ * edge, then the x value of the point must be less to be
+ * considered as inside. */
+
+ if (cmp_top == 0) {
+ cairo_fixed_t top_x;
+
+ top_x = _line_compute_intersection_x_for_y (&edge->edge.line,
+ edge->edge.top);
+ return _cairo_bo_intersect_ordinate_32_compare (point->x, top_x) > 0;
+ } else { /* cmp_bottom == 0 */
+ cairo_fixed_t bot_x;
+
+ bot_x = _line_compute_intersection_x_for_y (&edge->edge.line,
+ edge->edge.bottom);
+ return _cairo_bo_intersect_ordinate_32_compare (point->x, bot_x) < 0;
+ }
+}
+
+/* Compute the intersection of two edges. The result is provided as a
+ * coordinate pair of 128-bit integers.
+ *
+ * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection
+ * that is within both edges, %CAIRO_BO_STATUS_NO_INTERSECTION if the
+ * intersection of the lines defined by the edges occurs outside of
+ * one or both edges, and %CAIRO_BO_STATUS_PARALLEL if the two edges
+ * are exactly parallel.
+ *
+ * Note that when determining if a candidate intersection is "inside"
+ * an edge, we consider both the infinitesimal shortening and the
+ * infinitesimal tilt rules described by John Hobby. Specifically, if
+ * the intersection is exactly the same as an edge point, it is
+ * effectively outside (no intersection is returned). Also, if the
+ * intersection point has the same
+ */
+static cairo_bool_t
+_cairo_bo_edge_intersect (cairo_bo_edge_t *a,
+ cairo_bo_edge_t *b,
+ cairo_bo_point32_t *intersection)
+{
+ cairo_bo_intersect_point_t quorem;
+
+ if (! intersect_lines (a, b, &quorem))
+ return FALSE;
+
+ if (! _cairo_bo_edge_contains_intersect_point (a, &quorem))
+ return FALSE;
+
+ if (! _cairo_bo_edge_contains_intersect_point (b, &quorem))
+ return FALSE;
+
+ /* Now that we've correctly compared the intersection point and
+ * determined that it lies within the edge, then we know that we
+ * no longer need any more bits of storage for the intersection
+ * than we do for our edge coordinates. We also no longer need the
+ * remainder from the division. */
+ intersection->x = quorem.x.ordinate;
+ intersection->y = quorem.y.ordinate;
+
+ return TRUE;
+}
+
+static inline int
+cairo_bo_event_compare (const cairo_bo_event_t *a,
+ const cairo_bo_event_t *b)
+{
+ int cmp;
+
+ cmp = _cairo_bo_point32_compare (&a->point, &b->point);
+ if (cmp)
+ return cmp;
+
+ cmp = a->type - b->type;
+ if (cmp)
+ return cmp;
+
+ return a - b;
+}
+
+static inline void
+_pqueue_init (pqueue_t *pq)
+{
+ pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
+ pq->size = 0;
+
+ pq->elements = pq->elements_embedded;
+}
+
+static inline void
+_pqueue_fini (pqueue_t *pq)
+{
+ if (pq->elements != pq->elements_embedded)
+ free (pq->elements);
+}
+
+static cairo_status_t
+_pqueue_grow (pqueue_t *pq)
+{
+ cairo_bo_event_t **new_elements;
+ pq->max_size *= 2;
+
+ if (pq->elements == pq->elements_embedded) {
+ new_elements = _cairo_malloc_ab (pq->max_size,
+ sizeof (cairo_bo_event_t *));
+ if (unlikely (new_elements == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ memcpy (new_elements, pq->elements_embedded,
+ sizeof (pq->elements_embedded));
+ } else {
+ new_elements = _cairo_realloc_ab (pq->elements,
+ pq->max_size,
+ sizeof (cairo_bo_event_t *));
+ if (unlikely (new_elements == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ pq->elements = new_elements;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static inline cairo_status_t
+_pqueue_push (pqueue_t *pq, cairo_bo_event_t *event)
+{
+ cairo_bo_event_t **elements;
+ int i, parent;
+
+ if (unlikely (pq->size + 1 == pq->max_size)) {
+ cairo_status_t status;
+
+ status = _pqueue_grow (pq);
+ if (unlikely (status))
+ return status;
+ }
+
+ elements = pq->elements;
+
+ for (i = ++pq->size;
+ i != PQ_FIRST_ENTRY &&
+ cairo_bo_event_compare (event,
+ elements[parent = PQ_PARENT_INDEX (i)]) < 0;
+ i = parent)
+ {
+ elements[i] = elements[parent];
+ }
+
+ elements[i] = event;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static inline void
+_pqueue_pop (pqueue_t *pq)
+{
+ cairo_bo_event_t **elements = pq->elements;
+ cairo_bo_event_t *tail;
+ int child, i;
+
+ tail = elements[pq->size--];
+ if (pq->size == 0) {
+ elements[PQ_FIRST_ENTRY] = NULL;
+ return;
+ }
+
+ for (i = PQ_FIRST_ENTRY;
+ (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
+ i = child)
+ {
+ if (child != pq->size &&
+ cairo_bo_event_compare (elements[child+1],
+ elements[child]) < 0)
+ {
+ child++;
+ }
+
+ if (cairo_bo_event_compare (elements[child], tail) >= 0)
+ break;
+
+ elements[i] = elements[child];
+ }
+ elements[i] = tail;
+}
+
+static inline cairo_status_t
+_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
+ cairo_bo_event_type_t type,
+ cairo_bo_edge_t *e1,
+ cairo_bo_edge_t *e2,
+ const cairo_point_t *point)
+{
+ cairo_bo_queue_event_t *event;
+
+ event = _cairo_freepool_alloc (&queue->pool);
+ if (unlikely (event == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ event->type = type;
+ event->e1 = e1;
+ event->e2 = e2;
+ event->point = *point;
+
+ return _pqueue_push (&queue->pqueue, (cairo_bo_event_t *) event);
+}
+
+static void
+_cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
+ cairo_bo_event_t *event)
+{
+ _cairo_freepool_free (&queue->pool, event);
+}
+
+static cairo_bo_event_t *
+_cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
+{
+ cairo_bo_event_t *event, *cmp;
+
+ event = event_queue->pqueue.elements[PQ_FIRST_ENTRY];
+ cmp = *event_queue->start_events;
+ if (event == NULL ||
+ (cmp != NULL && cairo_bo_event_compare (cmp, event) < 0))
+ {
+ event = cmp;
+ event_queue->start_events++;
+ }
+ else
+ {
+ _pqueue_pop (&event_queue->pqueue);
+ }
+
+ return event;
+}
+
+CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
+ cairo_bo_event_t *,
+ cairo_bo_event_compare)
+
+static void
+_cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
+ cairo_bo_event_t **start_events,
+ int num_events)
+{
+ _cairo_bo_event_queue_sort (start_events, num_events);
+ start_events[num_events] = NULL;
+
+ event_queue->start_events = start_events;
+
+ _cairo_freepool_init (&event_queue->pool,
+ sizeof (cairo_bo_queue_event_t));
+ _pqueue_init (&event_queue->pqueue);
+ event_queue->pqueue.elements[PQ_FIRST_ENTRY] = NULL;
+}
+
+static cairo_status_t
+event_queue_insert_stop (cairo_bo_event_queue_t *event_queue,
+ cairo_bo_edge_t *edge)
+{
+ cairo_bo_point32_t point;
+
+ point.y = edge->edge.bottom;
+ point.x = _line_compute_intersection_x_for_y (&edge->edge.line,
+ point.y);
+ return _cairo_bo_event_queue_insert (event_queue,
+ CAIRO_BO_EVENT_TYPE_STOP,
+ edge, NULL,
+ &point);
+}
+
+static void
+_cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
+{
+ _pqueue_fini (&event_queue->pqueue);
+ _cairo_freepool_fini (&event_queue->pool);
+}
+
+static inline cairo_status_t
+event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue,
+ cairo_bo_edge_t *left,
+ cairo_bo_edge_t *right)
+{
+ cairo_bo_point32_t intersection;
+
+ if (_line_equal (&left->edge.line, &right->edge.line))
+ return CAIRO_STATUS_SUCCESS;
+
+ /* The names "left" and "right" here are correct descriptions of
+ * the order of the two edges within the active edge list. So if a
+ * slope comparison also puts left less than right, then we know
+ * that the intersection of these two segments has already
+ * occurred before the current sweep line position. */
+ if (_slope_compare (left, right) <= 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (! _cairo_bo_edge_intersect (left, right, &intersection))
+ return CAIRO_STATUS_SUCCESS;
+
+ return _cairo_bo_event_queue_insert (event_queue,
+ CAIRO_BO_EVENT_TYPE_INTERSECTION,
+ left, right,
+ &intersection);
+}
+
+static void
+_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
+{
+ sweep_line->head = NULL;
+ sweep_line->current_y = INT32_MIN;
+ sweep_line->current_edge = NULL;
+}
+
+static cairo_status_t
+sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
+ cairo_bo_edge_t *edge)
+{
+ if (sweep_line->current_edge != NULL) {
+ cairo_bo_edge_t *prev, *next;
+ int cmp;
+
+ cmp = _cairo_bo_sweep_line_compare_edges (sweep_line,
+ sweep_line->current_edge,
+ edge);
+ if (cmp < 0) {
+ prev = sweep_line->current_edge;
+ next = prev->next;
+ while (next != NULL &&
+ _cairo_bo_sweep_line_compare_edges (sweep_line,
+ next, edge) < 0)
+ {
+ prev = next, next = prev->next;
+ }
+
+ prev->next = edge;
+ edge->prev = prev;
+ edge->next = next;
+ if (next != NULL)
+ next->prev = edge;
+ } else if (cmp > 0) {
+ next = sweep_line->current_edge;
+ prev = next->prev;
+ while (prev != NULL &&
+ _cairo_bo_sweep_line_compare_edges (sweep_line,
+ prev, edge) > 0)
+ {
+ next = prev, prev = next->prev;
+ }
+
+ next->prev = edge;
+ edge->next = next;
+ edge->prev = prev;
+ if (prev != NULL)
+ prev->next = edge;
+ else
+ sweep_line->head = edge;
+ } else {
+ prev = sweep_line->current_edge;
+ edge->prev = prev;
+ edge->next = prev->next;
+ if (prev->next != NULL)
+ prev->next->prev = edge;
+ prev->next = edge;
+ }
+ } else {
+ sweep_line->head = edge;
+ }
+
+ sweep_line->current_edge = edge;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line,
+ cairo_bo_edge_t *edge)
+{
+ if (edge->prev != NULL)
+ edge->prev->next = edge->next;
+ else
+ sweep_line->head = edge->next;
+
+ if (edge->next != NULL)
+ edge->next->prev = edge->prev;
+
+ if (sweep_line->current_edge == edge)
+ sweep_line->current_edge = edge->prev ? edge->prev : edge->next;
+}
+
+static void
+_cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line,
+ cairo_bo_edge_t *left,
+ cairo_bo_edge_t *right)
+{
+ if (left->prev != NULL)
+ left->prev->next = right;
+ else
+ sweep_line->head = right;
+
+ if (right->next != NULL)
+ right->next->prev = left;
+
+ left->next = right->next;
+ right->next = left;
+
+ right->prev = left->prev;
+ left->prev = right;
+}
+
+static inline cairo_bool_t
+edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
+{
+ if (_line_equal (&a->edge.line, &b->edge.line))
+ return TRUE;
+
+ if (_slope_compare (a, b))
+ return FALSE;
+
+ /* The choice of y is not truly arbitrary since we must guarantee that it
+ * is greater than the start of either line.
+ */
+ if (a->edge.line.p1.y == b->edge.line.p1.y) {
+ return a->edge.line.p1.x == b->edge.line.p1.x;
+ } else if (a->edge.line.p1.y < b->edge.line.p1.y) {
+ return edge_compare_for_y_against_x (b,
+ a->edge.line.p1.y,
+ a->edge.line.p1.x) == 0;
+ } else {
+ return edge_compare_for_y_against_x (a,
+ b->edge.line.p1.y,
+ b->edge.line.p1.x) == 0;
+ }
+}
+
+static void
+edges_end (cairo_bo_edge_t *left,
+ int32_t bot,
+ cairo_polygon_t *polygon)
+{
+ cairo_bo_deferred_t *l = &left->deferred;
+ cairo_bo_edge_t *right = l->other;
+ cairo_bo_deferred_t *r = &right->deferred;
+
+ if (likely (l->top < bot)) {
+ _cairo_polygon_add_line (polygon, &left->edge.line,
+ l->top, bot, l->dir);
+ _cairo_polygon_add_line (polygon, &right->edge.line,
+ l->top, bot, r->dir);
+ }
+
+ l->other = NULL;
+ r->other = NULL;
+}
+
+
+static inline void
+edges_start_or_continue (cairo_bo_edge_t *left,
+ cairo_bo_edge_t *right,
+ int top,
+ cairo_polygon_t *polygon)
+{
+ if (left->deferred.other == right) {
+ assert (right->deferred.other == left);
+ assert (left->deferred.dir == 1);
+ assert (right->deferred.dir == -1);
+ return;
+ }
+
+ if (left->deferred.other != NULL) {
+ assert (left->deferred.dir == 1);
+ if (right != NULL && edges_colinear (left->deferred.other, right)) {
+ /* continuation on right, so just swap edges */
+ left->deferred.other->deferred.other = NULL;
+ left->deferred.other = right;
+ right->deferred.other = left;
+ right->deferred.dir = -1;
+ return;
+ }
+
+ edges_end (left, top, polygon);
+ }
+
+ if (right != NULL && ! edges_colinear (left, right)) {
+ left->deferred.top = top;
+ left->deferred.dir = 1;
+ left->deferred.other = right;
+
+ right->deferred.top = top;
+ right->deferred.dir = -1;
+ right->deferred.other = left;
+ }
+}
+
+#define is_zero(w) ((w)[0] == 0 || (w)[1] == 0)
+
+static inline void
+active_edges (cairo_bo_edge_t *left,
+ int32_t top,
+ cairo_polygon_t *polygon)
+{
+ cairo_bo_edge_t *right;
+ int winding[2] = {0, 0};
+
+ /* Yes, this is naive. Consider this a placeholder. */
+
+ while (left != NULL) {
+ assert (is_zero (winding));
+
+ do {
+ winding[left->a_or_b] += left->edge.dir;
+ if (! is_zero (winding))
+ break;
+
+ if unlikely ((left->deferred.other))
+ edges_end (left, top, polygon);
+
+ left = left->next;
+ if (! left)
+ return;
+ } while (1);
+
+ right = left->next;
+ do {
+ if unlikely ((right->deferred.other))
+ edges_end (right, top, polygon);
+
+ winding[right->a_or_b] += right->edge.dir;
+ if (is_zero (winding)) {
+ if (right->next == NULL ||
+ ! edges_colinear (right, right->next))
+ break;
+ }
+
+ right = right->next;
+ } while (right);
+
+ edges_start_or_continue (left, right, top, polygon);
+
+ left = right;
+ if (left != NULL)
+ left = left->next;
+ }
+}
+
+
+static cairo_status_t
+intersection_sweep (cairo_bo_event_t **start_events,
+ int num_events,
+ cairo_polygon_t *polygon)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */
+ cairo_bo_event_queue_t event_queue;
+ cairo_bo_sweep_line_t sweep_line;
+ cairo_bo_event_t *event;
+ cairo_bo_edge_t *left, *right;
+ cairo_bo_edge_t *e1, *e2;
+
+ _cairo_bo_event_queue_init (&event_queue, start_events, num_events);
+ _cairo_bo_sweep_line_init (&sweep_line);
+
+ while ((event = _cairo_bo_event_dequeue (&event_queue))) {
+ if (event->point.y != sweep_line.current_y) {
+ active_edges (sweep_line.head,
+ sweep_line.current_y,
+ polygon);
+ sweep_line.current_y = event->point.y;
+ }
+
+ switch (event->type) {
+ case CAIRO_BO_EVENT_TYPE_START:
+ e1 = &((cairo_bo_start_event_t *) event)->edge;
+
+ status = sweep_line_insert (&sweep_line, e1);
+ if (unlikely (status))
+ goto unwind;
+
+ status = event_queue_insert_stop (&event_queue, e1);
+ if (unlikely (status))
+ goto unwind;
+
+ left = e1->prev;
+ right = e1->next;
+
+ if (left != NULL) {
+ status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, e1);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ if (right != NULL) {
+ status = event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ break;
+
+ case CAIRO_BO_EVENT_TYPE_STOP:
+ e1 = ((cairo_bo_queue_event_t *) event)->e1;
+ _cairo_bo_event_queue_delete (&event_queue, event);
+
+ if (e1->deferred.other)
+ edges_end (e1, sweep_line.current_y, polygon);
+
+ left = e1->prev;
+ right = e1->next;
+
+ _cairo_bo_sweep_line_delete (&sweep_line, e1);
+
+ if (left != NULL && right != NULL) {
+ status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ break;
+
+ case CAIRO_BO_EVENT_TYPE_INTERSECTION:
+ e1 = ((cairo_bo_queue_event_t *) event)->e1;
+ e2 = ((cairo_bo_queue_event_t *) event)->e2;
+ _cairo_bo_event_queue_delete (&event_queue, event);
+
+ /* skip this intersection if its edges are not adjacent */
+ if (e2 != e1->next)
+ break;
+
+ left = e1->prev;
+ right = e2->next;
+
+ _cairo_bo_sweep_line_swap (&sweep_line, e1, e2);
+
+ /* after the swap e2 is left of e1 */
+
+ if (left != NULL) {
+ status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, e2);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ if (right != NULL) {
+ status = event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ break;
+ }
+ }
+
+ unwind:
+ _cairo_bo_event_queue_fini (&event_queue);
+
+ return status;
+}
+
+cairo_status_t
+_cairo_polygon_intersect (cairo_polygon_t *a, int winding_a,
+ cairo_polygon_t *b, int winding_b)
+{
+ cairo_status_t status;
+ cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)];
+ cairo_bo_start_event_t *events;
+ cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
+ cairo_bo_event_t **event_ptrs;
+ int num_events;
+ int i, j;
+
+ /* XXX lazy */
+ if (winding_a != CAIRO_FILL_RULE_WINDING) {
+ status = _cairo_polygon_reduce (a, winding_a);
+ if (unlikely (status))
+ return status;
+ }
+
+ if (winding_b != CAIRO_FILL_RULE_WINDING) {
+ status = _cairo_polygon_reduce (b, winding_b);
+ if (unlikely (status))
+ return status;
+ }
+
+ if (unlikely (0 == a->num_edges))
+ return CAIRO_STATUS_SUCCESS;
+
+ if (unlikely (b->num_edges == 0)) {
+ a->num_edges = 0;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ events = stack_events;
+ event_ptrs = stack_event_ptrs;
+ num_events = a->num_edges + b->num_edges;
+ if (num_events > ARRAY_LENGTH (stack_events)) {
+ events = _cairo_malloc_ab_plus_c (num_events,
+ sizeof (cairo_bo_start_event_t) +
+ sizeof (cairo_bo_event_t *),
+ sizeof (cairo_bo_event_t *));
+ if (unlikely (events == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ event_ptrs = (cairo_bo_event_t **) (events + num_events);
+ }
+
+ j = 0;
+ for (i = 0; i < a->num_edges; i++) {
+ event_ptrs[j] = (cairo_bo_event_t *) &events[j];
+
+ events[j].type = CAIRO_BO_EVENT_TYPE_START;
+ events[j].point.y = a->edges[i].top;
+ events[j].point.x =
+ _line_compute_intersection_x_for_y (&a->edges[i].line,
+ events[j].point.y);
+
+ events[j].edge.a_or_b = 0;
+ events[j].edge.edge = a->edges[i];
+ events[j].edge.deferred.other = NULL;
+ events[j].edge.prev = NULL;
+ events[j].edge.next = NULL;
+ j++;
+ }
+
+ for (i = 0; i < b->num_edges; i++) {
+ event_ptrs[j] = (cairo_bo_event_t *) &events[j];
+
+ events[j].type = CAIRO_BO_EVENT_TYPE_START;
+ events[j].point.y = b->edges[i].top;
+ events[j].point.x =
+ _line_compute_intersection_x_for_y (&b->edges[i].line,
+ events[j].point.y);
+
+ events[j].edge.a_or_b = 1;
+ events[j].edge.edge = b->edges[i];
+ events[j].edge.deferred.other = NULL;
+ events[j].edge.prev = NULL;
+ events[j].edge.next = NULL;
+ j++;
+ }
+ assert (j == num_events);
+
+ //fprintf(stderr, "a "); _cairo_debug_print_polygon(stderr,a);
+ //fprintf(stderr, "b "); _cairo_debug_print_polygon(stderr,b);
+
+ a->num_edges = 0;
+ status = intersection_sweep (event_ptrs, num_events, a);
+ if (events != stack_events)
+ free (events);
+
+ return status;
+}
diff --git a/src/cairo-polygon-reduce.c b/src/cairo-polygon-reduce.c
new file mode 100644
index 0000000..f18e234
--- /dev/null
+++ b/src/cairo-polygon-reduce.c
@@ -0,0 +1,1491 @@
+/*
+ * Copyright © 2004 Carl Worth
+ * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2008 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Carl Worth
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth at cworth.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+/* Provide definitions for standalone compilation */
+#include "cairoint.h"
+
+#include "cairo-error-private.h"
+#include "cairo-freelist-private.h"
+#include "cairo-combsort-private.h"
+
+typedef cairo_point_t cairo_bo_point32_t;
+
+typedef struct _cairo_bo_intersect_ordinate {
+ int32_t ordinate;
+ enum { EXACT, INEXACT } exactness;
+} cairo_bo_intersect_ordinate_t;
+
+typedef struct _cairo_bo_intersect_point {
+ cairo_bo_intersect_ordinate_t x;
+ cairo_bo_intersect_ordinate_t y;
+} cairo_bo_intersect_point_t;
+
+typedef struct _cairo_bo_edge cairo_bo_edge_t;
+
+typedef struct _cairo_bo_deferred {
+ cairo_bo_edge_t *right;
+ int32_t top;
+} cairo_bo_deferred_t;
+
+struct _cairo_bo_edge {
+ cairo_edge_t edge;
+ cairo_bo_edge_t *prev;
+ cairo_bo_edge_t *next;
+ cairo_bo_deferred_t deferred;
+};
+
+/* the parent is always given by index/2 */
+#define PQ_PARENT_INDEX(i) ((i) >> 1)
+#define PQ_FIRST_ENTRY 1
+
+/* left and right children are index * 2 and (index * 2) +1 respectively */
+#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
+
+typedef enum {
+ CAIRO_BO_EVENT_TYPE_STOP,
+ CAIRO_BO_EVENT_TYPE_INTERSECTION,
+ CAIRO_BO_EVENT_TYPE_START
+} cairo_bo_event_type_t;
+
+typedef struct _cairo_bo_event {
+ cairo_bo_event_type_t type;
+ cairo_point_t point;
+} cairo_bo_event_t;
+
+typedef struct _cairo_bo_start_event {
+ cairo_bo_event_type_t type;
+ cairo_point_t point;
+ cairo_bo_edge_t edge;
+} cairo_bo_start_event_t;
+
+typedef struct _cairo_bo_queue_event {
+ cairo_bo_event_type_t type;
+ cairo_point_t point;
+ cairo_bo_edge_t *e1;
+ cairo_bo_edge_t *e2;
+} cairo_bo_queue_event_t;
+
+typedef struct _pqueue {
+ int size, max_size;
+
+ cairo_bo_event_t **elements;
+ cairo_bo_event_t *elements_embedded[1024];
+} pqueue_t;
+
+typedef struct _cairo_bo_event_queue {
+ cairo_freepool_t pool;
+ pqueue_t pqueue;
+ cairo_bo_event_t **start_events;
+} cairo_bo_event_queue_t;
+
+typedef struct _cairo_bo_sweep_line {
+ cairo_bo_edge_t *head;
+ cairo_bo_edge_t *stopped;
+ int32_t current_y;
+ cairo_bo_edge_t *current_edge;
+} cairo_bo_sweep_line_t;
+
+static cairo_fixed_t
+_line_compute_intersection_x_for_y (const cairo_line_t *line,
+ cairo_fixed_t y)
+{
+ cairo_fixed_t x, dy;
+
+ if (y == line->p1.y)
+ return line->p1.x;
+ if (y == line->p2.y)
+ return line->p2.x;
+
+ x = line->p1.x;
+ dy = line->p2.y - line->p1.y;
+ if (dy != 0) {
+ x += _cairo_fixed_mul_div_floor (y - line->p1.y,
+ line->p2.x - line->p1.x,
+ dy);
+ }
+
+ return x;
+}
+
+static inline int
+_cairo_bo_point32_compare (cairo_bo_point32_t const *a,
+ cairo_bo_point32_t const *b)
+{
+ int cmp;
+
+ cmp = a->y - b->y;
+ if (cmp)
+ return cmp;
+
+ return a->x - b->x;
+}
+
+/* Compare the slope of a to the slope of b, returning 1, 0, -1 if the
+ * slope a is respectively greater than, equal to, or less than the
+ * slope of b.
+ *
+ * For each edge, consider the direction vector formed from:
+ *
+ * top -> bottom
+ *
+ * which is:
+ *
+ * (dx, dy) = (line.p2.x - line.p1.x, line.p2.y - line.p1.y)
+ *
+ * We then define the slope of each edge as dx/dy, (which is the
+ * inverse of the slope typically used in math instruction). We never
+ * compute a slope directly as the value approaches infinity, but we
+ * can derive a slope comparison without division as follows, (where
+ * the ? represents our compare operator).
+ *
+ * 1. slope(a) ? slope(b)
+ * 2. adx/ady ? bdx/bdy
+ * 3. (adx * bdy) ? (bdx * ady)
+ *
+ * Note that from step 2 to step 3 there is no change needed in the
+ * sign of the result since both ady and bdy are guaranteed to be
+ * greater than or equal to 0.
+ *
+ * When using this slope comparison to sort edges, some care is needed
+ * when interpreting the results. Since the slope compare operates on
+ * distance vectors from top to bottom it gives a correct left to
+ * right sort for edges that have a common top point, (such as two
+ * edges with start events at the same location). On the other hand,
+ * the sense of the result will be exactly reversed for two edges that
+ * have a common stop point.
+ */
+static inline int
+_slope_compare (const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b)
+{
+ /* XXX: We're assuming here that dx and dy will still fit in 32
+ * bits. That's not true in general as there could be overflow. We
+ * should prevent that before the tessellation algorithm
+ * begins.
+ */
+ int32_t adx = a->edge.line.p2.x - a->edge.line.p1.x;
+ int32_t bdx = b->edge.line.p2.x - b->edge.line.p1.x;
+
+ /* Since the dy's are all positive by construction we can fast
+ * path several common cases.
+ */
+
+ /* First check for vertical lines. */
+ if (adx == 0)
+ return -bdx;
+ if (bdx == 0)
+ return adx;
+
+ /* Then where the two edges point in different directions wrt x. */
+ if ((adx ^ bdx) < 0)
+ return adx;
+
+ /* Finally we actually need to do the general comparison. */
+ {
+ int32_t ady = a->edge.line.p2.y - a->edge.line.p1.y;
+ int32_t bdy = b->edge.line.p2.y - b->edge.line.p1.y;
+ cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+ cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
+
+ return _cairo_int64_cmp (adx_bdy, bdx_ady);
+ }
+}
+
+/*
+ * We need to compare the x-coordinates of a pair of lines for a particular y,
+ * without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ * X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ * A_x + (Y - A_y) * A_dx / A_dy â B_x + (Y - B_y) * B_dx / B_dy,
+ * where â is our inequality operator.
+ *
+ * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ * A_dy * B_dy * (A_x - B_x) â (Y - B_y) * B_dx * A_dy
+ * - (Y - A_y) * A_dx * B_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 128 bit arithmetic. For certain, but common,
+ * input we can reduce this down to a single 32 bit compare by inspecting the
+ * deltas.
+ *
+ * (And put the burden of the work on developing fast 128 bit ops, which are
+ * required throughout the tessellator.)
+ *
+ * See the similar discussion for _slope_compare().
+ */
+static int
+edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b,
+ int32_t y)
+{
+ /* XXX: We're assuming here that dx and dy will still fit in 32
+ * bits. That's not true in general as there could be overflow. We
+ * should prevent that before the tessellation algorithm
+ * begins.
+ */
+ int32_t dx;
+ int32_t adx, ady;
+ int32_t bdx, bdy;
+ enum {
+ HAVE_NONE = 0x0,
+ HAVE_DX = 0x1,
+ HAVE_ADX = 0x2,
+ HAVE_DX_ADX = HAVE_DX | HAVE_ADX,
+ HAVE_BDX = 0x4,
+ HAVE_DX_BDX = HAVE_DX | HAVE_BDX,
+ HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
+ HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX
+ } have_dx_adx_bdx = HAVE_ALL;
+
+ /* don't bother solving for abscissa if the edges' bounding boxes
+ * can be used to order them. */
+ {
+ int32_t amin, amax;
+ int32_t bmin, bmax;
+ if (a->edge.line.p1.x < a->edge.line.p2.x) {
+ amin = a->edge.line.p1.x;
+ amax = a->edge.line.p2.x;
+ } else {
+ amin = a->edge.line.p2.x;
+ amax = a->edge.line.p1.x;
+ }
+ if (b->edge.line.p1.x < b->edge.line.p2.x) {
+ bmin = b->edge.line.p1.x;
+ bmax = b->edge.line.p2.x;
+ } else {
+ bmin = b->edge.line.p2.x;
+ bmax = b->edge.line.p1.x;
+ }
+ if (amax < bmin) return -1;
+ if (amin > bmax) return +1;
+ }
+
+ ady = a->edge.line.p2.y - a->edge.line.p1.y;
+ adx = a->edge.line.p2.x - a->edge.line.p1.x;
+ if (adx == 0)
+ have_dx_adx_bdx &= ~HAVE_ADX;
+
+ bdy = b->edge.line.p2.y - b->edge.line.p1.y;
+ bdx = b->edge.line.p2.x - b->edge.line.p1.x;
+ if (bdx == 0)
+ have_dx_adx_bdx &= ~HAVE_BDX;
+
+ dx = a->edge.line.p1.x - b->edge.line.p1.x;
+ if (dx == 0)
+ have_dx_adx_bdx &= ~HAVE_DX;
+
+#define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
+#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->edge.line.p1.y)
+#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->edge.line.p1.y)
+ switch (have_dx_adx_bdx) {
+ default:
+ case HAVE_NONE:
+ return 0;
+ case HAVE_DX:
+ /* A_dy * B_dy * (A_x - B_x) â 0 */
+ return dx; /* ady * bdy is positive definite */
+ case HAVE_ADX:
+ /* 0 â - (Y - A_y) * A_dx * B_dy */
+ return adx; /* bdy * (y - a->top.y) is positive definite */
+ case HAVE_BDX:
+ /* 0 â (Y - B_y) * B_dx * A_dy */
+ return -bdx; /* ady * (y - b->top.y) is positive definite */
+ case HAVE_ADX_BDX:
+ /* 0 â (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
+ if ((adx ^ bdx) < 0) {
+ return adx;
+ } else if (a->edge.line.p1.y == b->edge.line.p1.y) { /* common origin */
+ cairo_int64_t adx_bdy, bdx_ady;
+
+ /* â´ A_dx * B_dy â B_dx * A_dy */
+
+ adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+ bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
+
+ return _cairo_int64_cmp (adx_bdy, bdx_ady);
+ } else
+ return _cairo_int128_cmp (A, B);
+ case HAVE_DX_ADX:
+ /* A_dy * (A_x - B_x) â - (Y - A_y) * A_dx */
+ if ((-adx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t ady_dx, dy_adx;
+
+ ady_dx = _cairo_int32x32_64_mul (ady, dx);
+ dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx);
+
+ return _cairo_int64_cmp (ady_dx, dy_adx);
+ }
+ case HAVE_DX_BDX:
+ /* B_dy * (A_x - B_x) â (Y - B_y) * B_dx */
+ if ((bdx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t bdy_dx, dy_bdx;
+
+ bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
+ dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.y, bdx);
+
+ return _cairo_int64_cmp (bdy_dx, dy_bdx);
+ }
+ case HAVE_ALL:
+ /* XXX try comparing (a->edge.line.p2.x - b->edge.line.p2.x) et al */
+ return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
+ }
+#undef B
+#undef A
+#undef L
+}
+
+/*
+ * We need to compare the x-coordinate of a line for a particular y wrt to a
+ * given x, without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ * X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ * A_x + (Y - A_y) * A_dx / A_dy â X
+ * where â is our inequality operator.
+ *
+ * By construction, we know that A_dy (and (Y - A_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ * (Y - A_y) * A_dx â (X - A_x) * A_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 64 bit arithmetic.
+ *
+ * See the similar discussion for _slope_compare() and
+ * edges_compare_x_for_y_general().
+ */
+static int
+edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
+ int32_t y,
+ int32_t x)
+{
+ int32_t adx, ady;
+ int32_t dx, dy;
+ cairo_int64_t L, R;
+
+ if (x < a->edge.line.p1.x && x < a->edge.line.p2.x)
+ return 1;
+ if (x > a->edge.line.p1.x && x > a->edge.line.p2.x)
+ return -1;
+
+ adx = a->edge.line.p2.x - a->edge.line.p1.x;
+ dx = x - a->edge.line.p1.x;
+
+ if (adx == 0)
+ return -dx;
+ if (dx == 0 || (adx ^ dx) < 0)
+ return adx;
+
+ dy = y - a->edge.line.p1.y;
+ ady = a->edge.line.p2.y - a->edge.line.p1.y;
+
+ L = _cairo_int32x32_64_mul (dy, adx);
+ R = _cairo_int32x32_64_mul (dx, ady);
+
+ return _cairo_int64_cmp (L, R);
+}
+
+static int
+edges_compare_x_for_y (const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b,
+ int32_t y)
+{
+ /* If the sweep-line is currently on an end-point of a line,
+ * then we know its precise x value (and considering that we often need to
+ * compare events at end-points, this happens frequently enough to warrant
+ * special casing).
+ */
+ enum {
+ HAVE_NEITHER = 0x0,
+ HAVE_AX = 0x1,
+ HAVE_BX = 0x2,
+ HAVE_BOTH = HAVE_AX | HAVE_BX
+ } have_ax_bx = HAVE_BOTH;
+ int32_t ax, bx;
+
+ if (y == a->edge.line.p1.y)
+ ax = a->edge.line.p1.x;
+ else if (y == a->edge.line.p2.y)
+ ax = a->edge.line.p2.x;
+ else
+ have_ax_bx &= ~HAVE_AX;
+
+ if (y == b->edge.line.p1.y)
+ bx = b->edge.line.p1.x;
+ else if (y == b->edge.line.p2.y)
+ bx = b->edge.line.p2.x;
+ else
+ have_ax_bx &= ~HAVE_BX;
+
+ switch (have_ax_bx) {
+ default:
+ case HAVE_NEITHER:
+ return edges_compare_x_for_y_general (a, b, y);
+ case HAVE_AX:
+ return -edge_compare_for_y_against_x (b, y, ax);
+ case HAVE_BX:
+ return edge_compare_for_y_against_x (a, y, bx);
+ case HAVE_BOTH:
+ return ax - bx;
+ }
+}
+
+static inline int
+_line_equal (const cairo_line_t *a, const cairo_line_t *b)
+{
+ return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
+ a->p2.x == b->p2.x && a->p2.y == b->p2.y;
+}
+
+static int
+_cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line,
+ const cairo_bo_edge_t *a,
+ const cairo_bo_edge_t *b)
+{
+ int cmp;
+
+ /* compare the edges if not identical */
+ if (! _line_equal (&a->edge.line, &b->edge.line)) {
+ cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
+ if (cmp)
+ return cmp;
+
+ /* The two edges intersect exactly at y, so fall back on slope
+ * comparison. We know that this compare_edges function will be
+ * called only when starting a new edge, (not when stopping an
+ * edge), so we don't have to worry about conditionally inverting
+ * the sense of _slope_compare. */
+ cmp = _slope_compare (a, b);
+ if (cmp)
+ return cmp;
+ }
+
+ /* We've got two collinear edges now. */
+ return b->edge.bottom - a->edge.bottom;
+}
+
+static inline cairo_int64_t
+det32_64 (int32_t a, int32_t b,
+ int32_t c, int32_t d)
+{
+ /* det = a * d - b * c */
+ return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d),
+ _cairo_int32x32_64_mul (b, c));
+}
+
+static inline cairo_int128_t
+det64x32_128 (cairo_int64_t a, int32_t b,
+ cairo_int64_t c, int32_t d)
+{
+ /* det = a * d - b * c */
+ return _cairo_int128_sub (_cairo_int64x32_128_mul (a, d),
+ _cairo_int64x32_128_mul (c, b));
+}
+
+/* Compute the intersection of two lines as defined by two edges. The
+ * result is provided as a coordinate pair of 128-bit integers.
+ *
+ * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
+ * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
+ */
+static cairo_bool_t
+intersect_lines (cairo_bo_edge_t *a,
+ cairo_bo_edge_t *b,
+ cairo_bo_intersect_point_t *intersection)
+{
+ cairo_int64_t a_det, b_det;
+
+ /* XXX: We're assuming here that dx and dy will still fit in 32
+ * bits. That's not true in general as there could be overflow. We
+ * should prevent that before the tessellation algorithm begins.
+ * What we're doing to mitigate this is to perform clamping in
+ * cairo_bo_tessellate_polygon().
+ */
+ int32_t dx1 = a->edge.line.p1.x - a->edge.line.p2.x;
+ int32_t dy1 = a->edge.line.p1.y - a->edge.line.p2.y;
+
+ int32_t dx2 = b->edge.line.p1.x - b->edge.line.p2.x;
+ int32_t dy2 = b->edge.line.p1.y - b->edge.line.p2.y;
+
+ cairo_int64_t den_det;
+ cairo_int64_t R;
+ cairo_quorem64_t qr;
+
+ den_det = det32_64 (dx1, dy1, dx2, dy2);
+
+ /* Q: Can we determine that the lines do not intersect (within range)
+ * much more cheaply than computing the intersection point i.e. by
+ * avoiding the division?
+ *
+ * X = ax + t * adx = bx + s * bdx;
+ * Y = ay + t * ady = by + s * bdy;
+ * â´ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
+ * => t * L = R
+ *
+ * Therefore we can reject any intersection (under the criteria for
+ * valid intersection events) if:
+ * L^R < 0 => t < 0, or
+ * L<R => t > 1
+ *
+ * (where top/bottom must at least extend to the line endpoints).
+ *
+ * A similar substitution can be performed for s, yielding:
+ * s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
+ */
+ R = det32_64 (dx2, dy2,
+ b->edge.line.p1.x - a->edge.line.p1.x,
+ b->edge.line.p1.y - a->edge.line.p1.y);
+ if (_cairo_int64_negative (den_det)) {
+ if (_cairo_int64_ge (den_det, R))
+ return FALSE;
+ } else {
+ if (_cairo_int64_le (den_det, R))
+ return FALSE;
+ }
+
+ R = det32_64 (dy1, dx1,
+ a->edge.line.p1.y - b->edge.line.p1.y,
+ a->edge.line.p1.x - b->edge.line.p1.x);
+ if (_cairo_int64_negative (den_det)) {
+ if (_cairo_int64_ge (den_det, R))
+ return FALSE;
+ } else {
+ if (_cairo_int64_le (den_det, R))
+ return FALSE;
+ }
+
+ /* We now know that the two lines should intersect within range. */
+
+ a_det = det32_64 (a->edge.line.p1.x, a->edge.line.p1.y,
+ a->edge.line.p2.x, a->edge.line.p2.y);
+ b_det = det32_64 (b->edge.line.p1.x, b->edge.line.p1.y,
+ b->edge.line.p2.x, b->edge.line.p2.y);
+
+ /* x = det (a_det, dx1, b_det, dx2) / den_det */
+ qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
+ b_det, dx2),
+ den_det);
+ if (_cairo_int64_eq (qr.rem, den_det))
+ return FALSE;
+#if 0
+ intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
+#else
+ intersection->x.exactness = EXACT;
+ if (! _cairo_int64_is_zero (qr.rem)) {
+ if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
+ qr.rem = _cairo_int64_negate (qr.rem);
+ qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
+ if (_cairo_int64_ge (qr.rem, den_det)) {
+ qr.quo = _cairo_int64_add (qr.quo,
+ _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
+ } else
+ intersection->x.exactness = INEXACT;
+ }
+#endif
+ intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
+
+ /* y = det (a_det, dy1, b_det, dy2) / den_det */
+ qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
+ b_det, dy2),
+ den_det);
+ if (_cairo_int64_eq (qr.rem, den_det))
+ return FALSE;
+#if 0
+ intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
+#else
+ intersection->y.exactness = EXACT;
+ if (! _cairo_int64_is_zero (qr.rem)) {
+ if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
+ qr.rem = _cairo_int64_negate (qr.rem);
+ qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
+ if (_cairo_int64_ge (qr.rem, den_det)) {
+ qr.quo = _cairo_int64_add (qr.quo,
+ _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
+ } else
+ intersection->y.exactness = INEXACT;
+ }
+#endif
+ intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
+
+ return TRUE;
+}
+
+static int
+_cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t a,
+ int32_t b)
+{
+ /* First compare the quotient */
+ if (a.ordinate > b)
+ return +1;
+ if (a.ordinate < b)
+ return -1;
+ /* With quotient identical, if remainder is 0 then compare equal */
+ /* Otherwise, the non-zero remainder makes a > b */
+ return INEXACT == a.exactness;
+}
+
+/* Does the given edge contain the given point. The point must already
+ * be known to be contained within the line determined by the edge,
+ * (most likely the point results from an intersection of this edge
+ * with another).
+ *
+ * If we had exact arithmetic, then this function would simply be a
+ * matter of examining whether the y value of the point lies within
+ * the range of y values of the edge. But since intersection points
+ * are not exact due to being rounded to the nearest integer within
+ * the available precision, we must also examine the x value of the
+ * point.
+ *
+ * The definition of "contains" here is that the given intersection
+ * point will be seen by the sweep line after the start event for the
+ * given edge and before the stop event for the edge. See the comments
+ * in the implementation for more details.
+ */
+static cairo_bool_t
+_cairo_bo_edge_contains_intersect_point (cairo_bo_edge_t *edge,
+ cairo_bo_intersect_point_t *point)
+{
+ int cmp_top, cmp_bottom;
+
+ /* XXX: When running the actual algorithm, we don't actually need to
+ * compare against edge->top at all here, since any intersection above
+ * top is eliminated early via a slope comparison. We're leaving these
+ * here for now only for the sake of the quadratic-time intersection
+ * finder which needs them.
+ */
+
+ cmp_top = _cairo_bo_intersect_ordinate_32_compare (point->y,
+ edge->edge.top);
+ cmp_bottom = _cairo_bo_intersect_ordinate_32_compare (point->y,
+ edge->edge.bottom);
+
+ if (cmp_top < 0 || cmp_bottom > 0)
+ {
+ return FALSE;
+ }
+
+ if (cmp_top > 0 && cmp_bottom < 0)
+ {
+ return TRUE;
+ }
+
+ /* At this stage, the point lies on the same y value as either
+ * edge->top or edge->bottom, so we have to examine the x value in
+ * order to properly determine containment. */
+
+ /* If the y value of the point is the same as the y value of the
+ * top of the edge, then the x value of the point must be greater
+ * to be considered as inside the edge. Similarly, if the y value
+ * of the point is the same as the y value of the bottom of the
+ * edge, then the x value of the point must be less to be
+ * considered as inside. */
+
+ if (cmp_top == 0) {
+ cairo_fixed_t top_x;
+
+ top_x = _line_compute_intersection_x_for_y (&edge->edge.line,
+ edge->edge.top);
+ return _cairo_bo_intersect_ordinate_32_compare (point->x, top_x) > 0;
+ } else { /* cmp_bottom == 0 */
+ cairo_fixed_t bot_x;
+
+ bot_x = _line_compute_intersection_x_for_y (&edge->edge.line,
+ edge->edge.bottom);
+ return _cairo_bo_intersect_ordinate_32_compare (point->x, bot_x) < 0;
+ }
+}
+
+/* Compute the intersection of two edges. The result is provided as a
+ * coordinate pair of 128-bit integers.
+ *
+ * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection
+ * that is within both edges, %CAIRO_BO_STATUS_NO_INTERSECTION if the
+ * intersection of the lines defined by the edges occurs outside of
+ * one or both edges, and %CAIRO_BO_STATUS_PARALLEL if the two edges
+ * are exactly parallel.
+ *
+ * Note that when determining if a candidate intersection is "inside"
+ * an edge, we consider both the infinitesimal shortening and the
+ * infinitesimal tilt rules described by John Hobby. Specifically, if
+ * the intersection is exactly the same as an edge point, it is
+ * effectively outside (no intersection is returned). Also, if the
+ * intersection point has the same
+ */
+static cairo_bool_t
+_cairo_bo_edge_intersect (cairo_bo_edge_t *a,
+ cairo_bo_edge_t *b,
+ cairo_bo_point32_t *intersection)
+{
+ cairo_bo_intersect_point_t quorem;
+
+ if (! intersect_lines (a, b, &quorem))
+ return FALSE;
+
+ if (! _cairo_bo_edge_contains_intersect_point (a, &quorem))
+ return FALSE;
+
+ if (! _cairo_bo_edge_contains_intersect_point (b, &quorem))
+ return FALSE;
+
+ /* Now that we've correctly compared the intersection point and
+ * determined that it lies within the edge, then we know that we
+ * no longer need any more bits of storage for the intersection
+ * than we do for our edge coordinates. We also no longer need the
+ * remainder from the division. */
+ intersection->x = quorem.x.ordinate;
+ intersection->y = quorem.y.ordinate;
+
+ return TRUE;
+}
+
+static inline int
+cairo_bo_event_compare (const cairo_bo_event_t *a,
+ const cairo_bo_event_t *b)
+{
+ int cmp;
+
+ cmp = _cairo_bo_point32_compare (&a->point, &b->point);
+ if (cmp)
+ return cmp;
+
+ cmp = a->type - b->type;
+ if (cmp)
+ return cmp;
+
+ return a - b;
+}
+
+static inline void
+_pqueue_init (pqueue_t *pq)
+{
+ pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
+ pq->size = 0;
+
+ pq->elements = pq->elements_embedded;
+}
+
+static inline void
+_pqueue_fini (pqueue_t *pq)
+{
+ if (pq->elements != pq->elements_embedded)
+ free (pq->elements);
+}
+
+static cairo_status_t
+_pqueue_grow (pqueue_t *pq)
+{
+ cairo_bo_event_t **new_elements;
+ pq->max_size *= 2;
+
+ if (pq->elements == pq->elements_embedded) {
+ new_elements = _cairo_malloc_ab (pq->max_size,
+ sizeof (cairo_bo_event_t *));
+ if (unlikely (new_elements == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ memcpy (new_elements, pq->elements_embedded,
+ sizeof (pq->elements_embedded));
+ } else {
+ new_elements = _cairo_realloc_ab (pq->elements,
+ pq->max_size,
+ sizeof (cairo_bo_event_t *));
+ if (unlikely (new_elements == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ pq->elements = new_elements;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static inline cairo_status_t
+_pqueue_push (pqueue_t *pq, cairo_bo_event_t *event)
+{
+ cairo_bo_event_t **elements;
+ int i, parent;
+
+ if (unlikely (pq->size + 1 == pq->max_size)) {
+ cairo_status_t status;
+
+ status = _pqueue_grow (pq);
+ if (unlikely (status))
+ return status;
+ }
+
+ elements = pq->elements;
+
+ for (i = ++pq->size;
+ i != PQ_FIRST_ENTRY &&
+ cairo_bo_event_compare (event,
+ elements[parent = PQ_PARENT_INDEX (i)]) < 0;
+ i = parent)
+ {
+ elements[i] = elements[parent];
+ }
+
+ elements[i] = event;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static inline void
+_pqueue_pop (pqueue_t *pq)
+{
+ cairo_bo_event_t **elements = pq->elements;
+ cairo_bo_event_t *tail;
+ int child, i;
+
+ tail = elements[pq->size--];
+ if (pq->size == 0) {
+ elements[PQ_FIRST_ENTRY] = NULL;
+ return;
+ }
+
+ for (i = PQ_FIRST_ENTRY;
+ (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
+ i = child)
+ {
+ if (child != pq->size &&
+ cairo_bo_event_compare (elements[child+1],
+ elements[child]) < 0)
+ {
+ child++;
+ }
+
+ if (cairo_bo_event_compare (elements[child], tail) >= 0)
+ break;
+
+ elements[i] = elements[child];
+ }
+ elements[i] = tail;
+}
+
+static inline cairo_status_t
+_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
+ cairo_bo_event_type_t type,
+ cairo_bo_edge_t *e1,
+ cairo_bo_edge_t *e2,
+ const cairo_point_t *point)
+{
+ cairo_bo_queue_event_t *event;
+
+ event = _cairo_freepool_alloc (&queue->pool);
+ if (unlikely (event == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ event->type = type;
+ event->e1 = e1;
+ event->e2 = e2;
+ event->point = *point;
+
+ return _pqueue_push (&queue->pqueue, (cairo_bo_event_t *) event);
+}
+
+static void
+_cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
+ cairo_bo_event_t *event)
+{
+ _cairo_freepool_free (&queue->pool, event);
+}
+
+static cairo_bo_event_t *
+_cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
+{
+ cairo_bo_event_t *event, *cmp;
+
+ event = event_queue->pqueue.elements[PQ_FIRST_ENTRY];
+ cmp = *event_queue->start_events;
+ if (event == NULL ||
+ (cmp != NULL && cairo_bo_event_compare (cmp, event) < 0))
+ {
+ event = cmp;
+ event_queue->start_events++;
+ }
+ else
+ {
+ _pqueue_pop (&event_queue->pqueue);
+ }
+
+ return event;
+}
+
+CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
+ cairo_bo_event_t *,
+ cairo_bo_event_compare)
+
+static void
+_cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
+ cairo_bo_event_t **start_events,
+ int num_events)
+{
+ _cairo_bo_event_queue_sort (start_events, num_events);
+ start_events[num_events] = NULL;
+
+ event_queue->start_events = start_events;
+
+ _cairo_freepool_init (&event_queue->pool,
+ sizeof (cairo_bo_queue_event_t));
+ _pqueue_init (&event_queue->pqueue);
+ event_queue->pqueue.elements[PQ_FIRST_ENTRY] = NULL;
+}
+
+static cairo_status_t
+_cairo_bo_event_queue_insert_stop (cairo_bo_event_queue_t *event_queue,
+ cairo_bo_edge_t *edge)
+{
+ cairo_bo_point32_t point;
+
+ point.y = edge->edge.bottom;
+ point.x = _line_compute_intersection_x_for_y (&edge->edge.line,
+ point.y);
+ return _cairo_bo_event_queue_insert (event_queue,
+ CAIRO_BO_EVENT_TYPE_STOP,
+ edge, NULL,
+ &point);
+}
+
+static void
+_cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
+{
+ _pqueue_fini (&event_queue->pqueue);
+ _cairo_freepool_fini (&event_queue->pool);
+}
+
+static inline cairo_status_t
+_cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue,
+ cairo_bo_edge_t *left,
+ cairo_bo_edge_t *right)
+{
+ cairo_bo_point32_t intersection;
+
+ if (_line_equal (&left->edge.line, &right->edge.line))
+ return CAIRO_STATUS_SUCCESS;
+
+ /* The names "left" and "right" here are correct descriptions of
+ * the order of the two edges within the active edge list. So if a
+ * slope comparison also puts left less than right, then we know
+ * that the intersection of these two segments has already
+ * occurred before the current sweep line position. */
+ if (_slope_compare (left, right) <= 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (! _cairo_bo_edge_intersect (left, right, &intersection))
+ return CAIRO_STATUS_SUCCESS;
+
+ return _cairo_bo_event_queue_insert (event_queue,
+ CAIRO_BO_EVENT_TYPE_INTERSECTION,
+ left, right,
+ &intersection);
+}
+
+static void
+_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
+{
+ sweep_line->head = NULL;
+ sweep_line->stopped = NULL;
+ sweep_line->current_y = INT32_MIN;
+ sweep_line->current_edge = NULL;
+}
+
+static cairo_status_t
+_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
+ cairo_bo_edge_t *edge)
+{
+ if (sweep_line->current_edge != NULL) {
+ cairo_bo_edge_t *prev, *next;
+ int cmp;
+
+ cmp = _cairo_bo_sweep_line_compare_edges (sweep_line,
+ sweep_line->current_edge,
+ edge);
+ if (cmp < 0) {
+ prev = sweep_line->current_edge;
+ next = prev->next;
+ while (next != NULL &&
+ _cairo_bo_sweep_line_compare_edges (sweep_line,
+ next, edge) < 0)
+ {
+ prev = next, next = prev->next;
+ }
+
+ prev->next = edge;
+ edge->prev = prev;
+ edge->next = next;
+ if (next != NULL)
+ next->prev = edge;
+ } else if (cmp > 0) {
+ next = sweep_line->current_edge;
+ prev = next->prev;
+ while (prev != NULL &&
+ _cairo_bo_sweep_line_compare_edges (sweep_line,
+ prev, edge) > 0)
+ {
+ next = prev, prev = next->prev;
+ }
+
+ next->prev = edge;
+ edge->next = next;
+ edge->prev = prev;
+ if (prev != NULL)
+ prev->next = edge;
+ else
+ sweep_line->head = edge;
+ } else {
+ prev = sweep_line->current_edge;
+ edge->prev = prev;
+ edge->next = prev->next;
+ if (prev->next != NULL)
+ prev->next->prev = edge;
+ prev->next = edge;
+ }
+ } else {
+ sweep_line->head = edge;
+ }
+
+ sweep_line->current_edge = edge;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line,
+ cairo_bo_edge_t *edge)
+{
+ if (edge->prev != NULL)
+ edge->prev->next = edge->next;
+ else
+ sweep_line->head = edge->next;
+
+ if (edge->next != NULL)
+ edge->next->prev = edge->prev;
+
+ if (sweep_line->current_edge == edge)
+ sweep_line->current_edge = edge->prev ? edge->prev : edge->next;
+}
+
+static void
+_cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line,
+ cairo_bo_edge_t *left,
+ cairo_bo_edge_t *right)
+{
+ if (left->prev != NULL)
+ left->prev->next = right;
+ else
+ sweep_line->head = right;
+
+ if (right->next != NULL)
+ right->next->prev = left;
+
+ left->next = right->next;
+ right->next = left;
+
+ right->prev = left->prev;
+ left->prev = right;
+}
+
+static inline cairo_bool_t
+edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
+{
+ if (_line_equal (&a->edge.line, &b->edge.line))
+ return TRUE;
+
+ if (_slope_compare (a, b))
+ return FALSE;
+
+ /* The choice of y is not truly arbitrary since we must guarantee that it
+ * is greater than the start of either line.
+ */
+ if (a->edge.line.p1.y == b->edge.line.p1.y) {
+ return a->edge.line.p1.x == b->edge.line.p1.x;
+ } else if (a->edge.line.p1.y < b->edge.line.p1.y) {
+ return edge_compare_for_y_against_x (b,
+ a->edge.line.p1.y,
+ a->edge.line.p1.x) == 0;
+ } else {
+ return edge_compare_for_y_against_x (a,
+ b->edge.line.p1.y,
+ b->edge.line.p1.x) == 0;
+ }
+}
+
+static void
+_cairo_bo_edge_end (cairo_bo_edge_t *left,
+ int32_t bot,
+ cairo_polygon_t *polygon)
+{
+ cairo_bo_deferred_t *d = &left->deferred;
+
+ if (likely (d->top < bot)) {
+ _cairo_polygon_add_line (polygon,
+ &left->edge.line,
+ d->top, bot,
+ 1);
+ _cairo_polygon_add_line (polygon,
+ &d->right->edge.line,
+ d->top, bot,
+ -1);
+ }
+
+ d->right = NULL;
+}
+
+
+static inline void
+_cairo_bo_edge_start_or_continue (cairo_bo_edge_t *left,
+ cairo_bo_edge_t *right,
+ int top,
+ cairo_polygon_t *polygon)
+{
+ if (left->deferred.right == right)
+ return;
+
+ if (left->deferred.right != NULL) {
+ if (right != NULL && edges_colinear (left->deferred.right, right))
+ {
+ /* continuation on right, so just swap edges */
+ left->deferred.right = right;
+ return;
+ }
+
+ _cairo_bo_edge_end (left, top, polygon);
+ }
+
+ if (right != NULL && ! edges_colinear (left, right)) {
+ left->deferred.top = top;
+ left->deferred.right = right;
+ }
+}
+
+static inline void
+_active_edges_to_polygon (cairo_bo_edge_t *left,
+ int32_t top,
+ cairo_fill_rule_t fill_rule,
+ cairo_polygon_t *polygon)
+{
+ cairo_bo_edge_t *right;
+
+ if (fill_rule == CAIRO_FILL_RULE_WINDING) {
+ while (left != NULL) {
+ int in_out = left->edge.dir;
+
+ right = left->next;
+ if (left->deferred.right == NULL) {
+ while (right != NULL && right->deferred.right == NULL)
+ right = right->next;
+
+ if (right != NULL && edges_colinear (left, right)) {
+ /* continuation on left */
+ left->deferred = right->deferred;
+ right->deferred.right = NULL;
+ }
+ }
+
+ right = left->next;
+ while (right != NULL) {
+ if (right->deferred.right != NULL)
+ _cairo_bo_edge_end (right, top, polygon);
+
+ in_out += right->edge.dir;
+ if (in_out == 0) {
+ cairo_bo_edge_t *next;
+ cairo_bool_t skip = FALSE;
+
+ /* skip co-linear edges */
+ next = right->next;
+ if (next != NULL)
+ skip = edges_colinear (right, next);
+
+ if (! skip)
+ break;
+ }
+
+ right = right->next;
+ }
+
+ _cairo_bo_edge_start_or_continue (left, right, top, polygon);
+
+ left = right;
+ if (left != NULL)
+ left = left->next;
+ }
+ } else {
+ while (left != NULL) {
+ int in_out = 0;
+
+ right = left->next;
+ while (right != NULL) {
+ if (right->deferred.right != NULL)
+ _cairo_bo_edge_end (right, top, polygon);
+
+ if ((in_out++ & 1) == 0) {
+ cairo_bo_edge_t *next;
+ cairo_bool_t skip = FALSE;
+
+ /* skip co-linear edges */
+ next = right->next;
+ if (next != NULL)
+ skip = edges_colinear (right, next);
+
+ if (! skip)
+ break;
+ }
+
+ right = right->next;
+ }
+
+ _cairo_bo_edge_start_or_continue (left, right, top, polygon);
+
+ left = right;
+ if (left != NULL)
+ left = left->next;
+ }
+ }
+}
+
+
+static cairo_status_t
+_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
+ int num_events,
+ cairo_fill_rule_t fill_rule,
+ cairo_polygon_t *polygon)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */
+ cairo_bo_event_queue_t event_queue;
+ cairo_bo_sweep_line_t sweep_line;
+ cairo_bo_event_t *event;
+ cairo_bo_edge_t *left, *right;
+ cairo_bo_edge_t *e1, *e2;
+
+ _cairo_bo_event_queue_init (&event_queue, start_events, num_events);
+ _cairo_bo_sweep_line_init (&sweep_line);
+
+ while ((event = _cairo_bo_event_dequeue (&event_queue))) {
+ if (event->point.y != sweep_line.current_y) {
+ for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
+ if (e1->deferred.right != NULL)
+ _cairo_bo_edge_end (e1, e1->edge.bottom, polygon);
+ }
+ sweep_line.stopped = NULL;
+
+ _active_edges_to_polygon (sweep_line.head,
+ sweep_line.current_y,
+ fill_rule, polygon);
+
+ sweep_line.current_y = event->point.y;
+ }
+
+ switch (event->type) {
+ case CAIRO_BO_EVENT_TYPE_START:
+ e1 = &((cairo_bo_start_event_t *) event)->edge;
+
+ status = _cairo_bo_sweep_line_insert (&sweep_line, e1);
+ if (unlikely (status))
+ goto unwind;
+
+ status = _cairo_bo_event_queue_insert_stop (&event_queue, e1);
+ if (unlikely (status))
+ goto unwind;
+
+ /* check to see if this is a continuation of a stopped edge */
+ /* XXX change to an infinitesimal lengthening rule */
+ for (left = sweep_line.stopped; left; left = left->next) {
+ if (e1->edge.top <= left->edge.bottom &&
+ edges_colinear (e1, left))
+ {
+ e1->deferred = left->deferred;
+ if (left->prev != NULL)
+ left->prev = left->next;
+ else
+ sweep_line.stopped = left->next;
+ if (left->next != NULL)
+ left->next->prev = left->prev;
+ break;
+ }
+ }
+
+ left = e1->prev;
+ right = e1->next;
+
+ if (left != NULL) {
+ status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, e1);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ if (right != NULL) {
+ status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ break;
+
+ case CAIRO_BO_EVENT_TYPE_STOP:
+ e1 = ((cairo_bo_queue_event_t *) event)->e1;
+ _cairo_bo_event_queue_delete (&event_queue, event);
+
+ left = e1->prev;
+ right = e1->next;
+
+ _cairo_bo_sweep_line_delete (&sweep_line, e1);
+
+ /* first, check to see if we have a continuation via a fresh edge */
+ if (e1->deferred.right != NULL) {
+ e1->next = sweep_line.stopped;
+ if (sweep_line.stopped != NULL)
+ sweep_line.stopped->prev = e1;
+ sweep_line.stopped = e1;
+ e1->prev = NULL;
+ }
+
+ if (left != NULL && right != NULL) {
+ status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ break;
+
+ case CAIRO_BO_EVENT_TYPE_INTERSECTION:
+ e1 = ((cairo_bo_queue_event_t *) event)->e1;
+ e2 = ((cairo_bo_queue_event_t *) event)->e2;
+ _cairo_bo_event_queue_delete (&event_queue, event);
+
+ /* skip this intersection if its edges are not adjacent */
+ if (e2 != e1->next)
+ break;
+
+ left = e1->prev;
+ right = e2->next;
+
+ _cairo_bo_sweep_line_swap (&sweep_line, e1, e2);
+
+ /* after the swap e2 is left of e1 */
+
+ if (left != NULL) {
+ status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, e2);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ if (right != NULL) {
+ status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right);
+ if (unlikely (status))
+ goto unwind;
+ }
+
+ break;
+ }
+ }
+
+ for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
+ if (e1->deferred.right != NULL)
+ _cairo_bo_edge_end (e1, e1->edge.bottom, polygon);
+ }
+ unwind:
+ _cairo_bo_event_queue_fini (&event_queue);
+
+ return status;
+}
+
+cairo_status_t
+_cairo_polygon_reduce (cairo_polygon_t *polygon,
+ cairo_fill_rule_t fill_rule)
+{
+ cairo_status_t status;
+ cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)];
+ cairo_bo_start_event_t *events;
+ cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
+ cairo_bo_event_t **event_ptrs;
+ int num_limits;
+ int num_events;
+ int i;
+
+ num_events = polygon->num_edges;
+ if (unlikely (0 == num_events))
+ return CAIRO_STATUS_SUCCESS;
+
+ events = stack_events;
+ event_ptrs = stack_event_ptrs;
+ if (num_events > ARRAY_LENGTH (stack_events)) {
+ events = _cairo_malloc_ab_plus_c (num_events,
+ sizeof (cairo_bo_start_event_t) +
+ sizeof (cairo_bo_event_t *),
+ sizeof (cairo_bo_event_t *));
+ if (unlikely (events == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ event_ptrs = (cairo_bo_event_t **) (events + num_events);
+ }
+
+ for (i = 0; i < num_events; i++) {
+ event_ptrs[i] = (cairo_bo_event_t *) &events[i];
+
+ events[i].type = CAIRO_BO_EVENT_TYPE_START;
+ events[i].point.y = polygon->edges[i].top;
+ events[i].point.x =
+ _line_compute_intersection_x_for_y (&polygon->edges[i].line,
+ events[i].point.y);
+
+ events[i].edge.edge = polygon->edges[i];
+ events[i].edge.deferred.right = NULL;
+ events[i].edge.prev = NULL;
+ events[i].edge.next = NULL;
+ }
+
+ num_limits = polygon->num_limits; polygon->num_limits = 0;
+ polygon->num_edges = 0;
+
+ status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs,
+ num_events,
+ fill_rule,
+ polygon);
+ polygon->num_limits = num_limits;
+
+ if (events != stack_events)
+ free (events);
+
+ return status;
+}
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index c3f3631..cc9faae 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -37,8 +37,14 @@
#include "cairoint.h"
+#include "cairo-boxes-private.h"
#include "cairo-error-private.h"
+static void
+_cairo_polygon_add_edge (cairo_polygon_t *polygon,
+ const cairo_point_t *p1,
+ const cairo_point_t *p2);
+
void
_cairo_polygon_init (cairo_polygon_t *polygon,
const cairo_box_t *limits,
@@ -80,6 +86,111 @@ _cairo_polygon_init (cairo_polygon_t *polygon,
}
void
+_cairo_polygon_init_with_clip (cairo_polygon_t *polygon,
+ const cairo_clip_t *clip)
+{
+ if (clip)
+ _cairo_polygon_init (polygon, clip->boxes, clip->num_boxes);
+ else
+ _cairo_polygon_init (polygon, 0, 0);
+}
+
+cairo_status_t
+_cairo_polygon_init_boxes (cairo_polygon_t *polygon,
+ const cairo_boxes_t *boxes)
+{
+ const struct _cairo_boxes_chunk *chunk;
+ int i;
+
+ VG (VALGRIND_MAKE_MEM_UNDEFINED (polygon, sizeof (cairo_polygon_t)));
+
+ polygon->status = CAIRO_STATUS_SUCCESS;
+
+ polygon->num_edges = 0;
+
+ polygon->edges = polygon->edges_embedded;
+ polygon->edges_size = ARRAY_LENGTH (polygon->edges_embedded);
+ if (boxes->num_boxes > ARRAY_LENGTH (polygon->edges_embedded)/2) {
+ polygon->edges_size = 2 * boxes->num_boxes;
+ polygon->edges = _cairo_malloc_ab (polygon->edges_size,
+ 2*sizeof(cairo_edge_t));
+ if (unlikely (polygon->edges == NULL))
+ return polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ polygon->extents.p1.x = polygon->extents.p1.y = INT32_MAX;
+ polygon->extents.p2.x = polygon->extents.p2.y = INT32_MIN;
+
+ polygon->limits = NULL;
+ polygon->num_limits = 0;
+
+ for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+ for (i = 0; i < chunk->count; i++) {
+ cairo_point_t p1, p2;
+
+ p1 = chunk->base[i].p1;
+ p2.x = p1.x;
+ p2.y = chunk->base[i].p2.y;
+ _cairo_polygon_add_edge (polygon, &p1, &p2);
+
+ p1 = chunk->base[i].p2;
+ p2.x = p1.x;
+ p2.y = chunk->base[i].p1.y;
+ _cairo_polygon_add_edge (polygon, &p1, &p2);
+ }
+ }
+
+ return polygon->status;
+}
+
+cairo_status_t
+_cairo_polygon_init_box_array (cairo_polygon_t *polygon,
+ cairo_box_t *boxes,
+ int num_boxes)
+{
+ int i;
+
+ VG (VALGRIND_MAKE_MEM_UNDEFINED (polygon, sizeof (cairo_polygon_t)));
+
+ polygon->status = CAIRO_STATUS_SUCCESS;
+
+ polygon->num_edges = 0;
+
+ polygon->edges = polygon->edges_embedded;
+ polygon->edges_size = ARRAY_LENGTH (polygon->edges_embedded);
+ if (num_boxes > ARRAY_LENGTH (polygon->edges_embedded)/2) {
+ polygon->edges_size = 2 * num_boxes;
+ polygon->edges = _cairo_malloc_ab (polygon->edges_size,
+ 2*sizeof(cairo_edge_t));
+ if (unlikely (polygon->edges == NULL))
+ return polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ polygon->extents.p1.x = polygon->extents.p1.y = INT32_MAX;
+ polygon->extents.p2.x = polygon->extents.p2.y = INT32_MIN;
+
+ polygon->limits = NULL;
+ polygon->num_limits = 0;
+
+ for (i = 0; i < num_boxes; i++) {
+ cairo_point_t p1, p2;
+
+ p1 = boxes[i].p1;
+ p2.x = p1.x;
+ p2.y = boxes[i].p2.y;
+ _cairo_polygon_add_edge (polygon, &p1, &p2);
+
+ p1 = boxes[i].p2;
+ p2.x = p1.x;
+ p2.y = boxes[i].p1.y;
+ _cairo_polygon_add_edge (polygon, &p1, &p2);
+ }
+
+ return polygon->status;
+}
+
+
+void
_cairo_polygon_fini (cairo_polygon_t *polygon)
{
if (polygon->edges != polygon->edges_embedded)
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 0b5f8e9..80ad474 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -572,7 +572,7 @@ _cairo_ps_emit_imagemask (cairo_image_surface_t *image,
return _cairo_output_stream_get_status (stream);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
@@ -704,16 +704,15 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_ps_surface_t *surface = closure;
- cairo_status_t status;
-
+ cairo_int_status_t status;
status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
- if (_cairo_status_is_error (status))
+ if (_cairo_int_status_is_error (status))
return status;
status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset);
@@ -732,15 +731,15 @@ _cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_su
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_ps_surface_t *surface = closure;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_scaled_font_subset_create_glyph_names (font_subset);
- if (_cairo_status_is_error (status))
+ if (_cairo_int_status_is_error (status))
return status;
status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
@@ -748,7 +747,7 @@ _cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subs
return status;
ASSERT_NOT_REACHED;
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_status_t
@@ -1640,7 +1639,7 @@ _cairo_ps_surface_end_page (cairo_ps_surface_t *surface)
if (unlikely (status))
return status;
- if (surface->clipper.clip.path != NULL) {
+ if (surface->clipper.clip != NULL) {
_cairo_output_stream_printf (surface->stream, "Q Q\n");
_cairo_surface_clipper_reset (&surface->clipper);
} else
@@ -2444,7 +2443,7 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
cairo_content_t old_content;
cairo_rectangle_int_t old_page_bbox;
cairo_box_t bbox;
- cairo_status_t status;
+ cairo_int_status_t status;
old_content = surface->content;
old_width = surface->width;
@@ -2516,7 +2515,7 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
cairo_surface_t *recording_surface,
const cairo_rectangle_int_t *extents)
@@ -2525,7 +2524,7 @@ _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
cairo_matrix_t old_cairo_to_ps;
cairo_content_t old_content;
cairo_rectangle_int_t old_page_bbox;
- cairo_status_t status;
+ cairo_int_status_t status;
old_content = surface->content;
old_width = surface->width;
@@ -2733,7 +2732,7 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface,
int width,
int height)
{
- cairo_status_t status;
+ cairo_int_status_t status;
if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
cairo_surface_t *source = pattern->surface;
@@ -3576,7 +3575,7 @@ static cairo_int_status_t
_cairo_ps_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
@@ -3635,13 +3634,13 @@ static cairo_int_status_t
_cairo_ps_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
@@ -3699,11 +3698,11 @@ static cairo_int_status_t
_cairo_ps_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
@@ -3786,7 +3785,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_ps_surface_t *surface = abstract_surface;
@@ -3840,7 +3839,7 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface,
surface->paginated_mode = paginated_mode;
- if (surface->clipper.clip.path != NULL) {
+ if (surface->clipper.clip != NULL) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
_cairo_output_stream_printf (surface->stream, "Q q\n");
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 9628c87..5b99680 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1725,7 +1725,7 @@ static cairo_int_status_t
_cairo_quartz_surface_paint_cg (cairo_quartz_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_quartz_drawing_state_t state;
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
@@ -1752,7 +1752,7 @@ static cairo_int_status_t
_cairo_quartz_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv;
@@ -1779,11 +1779,11 @@ static cairo_int_status_t
_cairo_quartz_surface_fill_cg (cairo_quartz_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_quartz_drawing_state_t state;
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
@@ -1827,11 +1827,11 @@ static cairo_int_status_t
_cairo_quartz_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv;
@@ -1864,13 +1864,13 @@ static cairo_int_status_t
_cairo_quartz_surface_stroke_cg (cairo_quartz_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_quartz_drawing_state_t state;
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
@@ -1947,13 +1947,13 @@ static cairo_int_status_t
_cairo_quartz_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv;
@@ -1987,7 +1987,7 @@ _cairo_quartz_surface_show_glyphs_cg (cairo_quartz_surface_t *surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
CGAffineTransform textTransform, invTextTransform;
@@ -2131,7 +2131,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
@@ -2248,7 +2248,7 @@ _cairo_quartz_surface_mask_cg (cairo_quartz_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_surface_t *mask_surf;
cairo_matrix_t matrix;
@@ -2350,7 +2350,7 @@ _cairo_quartz_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv;
diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h
index 3d8cba3..a901e7b 100644
--- a/src/cairo-recording-surface-private.h
+++ b/src/cairo-recording-surface-private.h
@@ -40,7 +40,6 @@
#include "cairoint.h"
#include "cairo-path-fixed-private.h"
#include "cairo-pattern-private.h"
-#include "cairo-clip-private.h"
typedef enum {
/* The 5 basic drawing operations. */
@@ -61,7 +60,7 @@ typedef struct _cairo_command_header {
cairo_command_type_t type;
cairo_recording_region_type_t region;
cairo_operator_t op;
- cairo_clip_t clip;
+ cairo_clip_t *clip;
} cairo_command_header_t;
typedef struct _cairo_command_paint {
@@ -130,8 +129,6 @@ typedef struct _cairo_recording_surface {
cairo_rectangle_int_t extents;
cairo_bool_t unbounded;
- cairo_clip_t clip;
-
cairo_array_t commands;
int replay_start_idx;
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 84ae347..ea5ee01 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -136,7 +136,6 @@ cairo_recording_surface_create (cairo_content_t content,
const cairo_rectangle_t *extents)
{
cairo_recording_surface_t *recording_surface;
- cairo_status_t status;
recording_surface = malloc (sizeof (cairo_recording_surface_t));
if (unlikely (recording_surface == NULL))
@@ -150,7 +149,6 @@ cairo_recording_surface_create (cairo_content_t content,
recording_surface->content = content;
recording_surface->unbounded = TRUE;
- _cairo_clip_init (&recording_surface->clip);
/* unbounded -> 'infinite' extents */
if (extents != NULL) {
@@ -162,13 +160,6 @@ cairo_recording_surface_create (cairo_content_t content,
recording_surface->extents.width = ceil (extents->x + extents->width) - recording_surface->extents.x;
recording_surface->extents.height = ceil (extents->y + extents->height) - recording_surface->extents.y;
- status = _cairo_clip_rectangle (&recording_surface->clip,
- &recording_surface->extents);
- if (unlikely (status)) {
- free (recording_surface);
- return _cairo_surface_create_in_error (status);
- }
-
recording_surface->unbounded = FALSE;
}
@@ -239,12 +230,11 @@ _cairo_recording_surface_finish (void *abstract_surface)
ASSERT_NOT_REACHED;
}
- _cairo_clip_fini (&command->header.clip);
+ _cairo_clip_destroy (command->header.clip);
free (command);
}
_cairo_array_fini (&recording_surface->commands);
- _cairo_clip_fini (&recording_surface->clip);
return CAIRO_STATUS_SUCCESS;
}
@@ -321,16 +311,14 @@ _command_init (cairo_recording_surface_t *recording_surface,
cairo_command_header_t *command,
cairo_command_type_t type,
cairo_operator_t op,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
command->type = type;
command->op = op;
command->region = CAIRO_RECORDING_REGION_ALL;
- _cairo_clip_init_copy (&command->clip, clip);
- if (recording_surface->clip.path != NULL)
- status = _cairo_clip_apply_clip (&command->clip, &recording_surface->clip);
+ command->clip = _cairo_clip_copy (clip);
return status;
}
@@ -339,7 +327,7 @@ static cairo_int_status_t
_cairo_recording_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_recording_surface_t *recording_surface = abstract_surface;
@@ -373,7 +361,7 @@ _cairo_recording_surface_paint (void *abstract_surface,
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
- _cairo_clip_fini (&command->header.clip);
+ _cairo_clip_destroy (command->header.clip);
free (command);
return status;
}
@@ -383,7 +371,7 @@ _cairo_recording_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_recording_surface_t *recording_surface = abstract_surface;
@@ -417,7 +405,7 @@ _cairo_recording_surface_mask (void *abstract_surface,
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
- _cairo_clip_fini (&command->header.clip);
+ _cairo_clip_destroy (command->header.clip);
free (command);
return status;
}
@@ -426,13 +414,13 @@ static cairo_int_status_t
_cairo_recording_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_recording_surface_t *recording_surface = abstract_surface;
@@ -477,7 +465,7 @@ _cairo_recording_surface_stroke (void *abstract_surface,
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
- _cairo_clip_fini (&command->header.clip);
+ _cairo_clip_destroy (command->header.clip);
free (command);
return status;
}
@@ -486,11 +474,11 @@ static cairo_int_status_t
_cairo_recording_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_recording_surface_t *recording_surface = abstract_surface;
@@ -528,7 +516,7 @@ _cairo_recording_surface_fill (void *abstract_surface,
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
- _cairo_clip_fini (&command->header.clip);
+ _cairo_clip_destroy (command->header.clip);
free (command);
return status;
}
@@ -551,7 +539,7 @@ _cairo_recording_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_recording_surface_t *recording_surface = abstract_surface;
@@ -622,7 +610,7 @@ _cairo_recording_surface_show_text_glyphs (void *abstract_surface,
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
- _cairo_clip_fini (&command->header.clip);
+ _cairo_clip_destroy (command->header.clip);
free (command);
return status;
}
@@ -661,8 +649,6 @@ _cairo_recording_surface_snapshot (void *abstract_other)
recording_surface->unbounded = other->unbounded;
recording_surface->content = other->content;
- _cairo_clip_init_copy (&recording_surface->clip, &other->clip);
-
/* XXX We should in theory be able to reuse the original array, but we
* need to handle reference cycles during subsurface and self-copy.
*/
@@ -795,7 +781,7 @@ _cairo_recording_surface_get_path (cairo_surface_t *surface,
command->stroke.tolerance,
&traps);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = _cairo_traps_path (&traps, path);
_cairo_traps_fini (&traps);
@@ -828,7 +814,6 @@ _cairo_recording_surface_get_path (cairo_surface_t *surface,
return _cairo_surface_set_error (surface, status);
}
-#define _clip(c) ((c)->header.clip.path ? &(c)->header.clip : NULL)
static cairo_status_t
_cairo_recording_surface_replay_internal (cairo_surface_t *surface,
const cairo_rectangle_int_t *surface_extents,
@@ -867,18 +852,24 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
cairo_command_t *command = elements[i];
+ cairo_clip_t *clip = command->header.clip;
if (type == CAIRO_RECORDING_REPLAY && region != CAIRO_RECORDING_REGION_ALL) {
if (command->header.region != region)
continue;
}
+ if (! recording_surface->unbounded)
+ clip = _cairo_clip_copy_intersect_rectangle (clip, &recording_surface->extents);
+ if (_cairo_clip_is_all_clipped (clip))
+ continue;
+
switch (command->header.type) {
case CAIRO_COMMAND_PAINT:
status = _cairo_surface_wrapper_paint (&wrapper,
command->header.op,
&command->paint.source.base,
- _clip (command));
+ clip);
break;
case CAIRO_COMMAND_MASK:
@@ -886,7 +877,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
command->header.op,
&command->mask.source.base,
&command->mask.mask.base,
- _clip (command));
+ clip);
break;
case CAIRO_COMMAND_STROKE:
@@ -900,7 +891,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
&command->stroke.ctm_inverse,
command->stroke.tolerance,
command->stroke.antialias,
- _clip (command));
+ clip);
break;
}
case CAIRO_COMMAND_FILL:
@@ -938,7 +929,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
&stroke_command->stroke.ctm_inverse,
stroke_command->stroke.tolerance,
stroke_command->stroke.antialias,
- _clip (command));
+ clip);
i++;
}
else
@@ -950,7 +941,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
command->fill.fill_rule,
command->fill.tolerance,
command->fill.antialias,
- _clip (command));
+ clip);
}
break;
}
@@ -980,7 +971,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
command->show_text_glyphs.cluster_flags,
command->show_text_glyphs.scaled_font,
- _clip (command));
+ clip);
free (glyphs_copy);
break;
}
@@ -989,29 +980,24 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
}
if (type == CAIRO_RECORDING_CREATE_REGIONS) {
- if (status == CAIRO_STATUS_SUCCESS) {
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
command->header.region = CAIRO_RECORDING_REGION_NATIVE;
} else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
command->header.region = CAIRO_RECORDING_REGION_IMAGE_FALLBACK;
- status = CAIRO_STATUS_SUCCESS;
+ status = CAIRO_INT_STATUS_SUCCESS;
} else {
- assert (_cairo_status_is_error (status));
+ assert (_cairo_int_status_is_error (status));
}
}
+ if (clip != command->header.clip)
+ _cairo_clip_destroy (clip);
+
if (unlikely (status))
break;
}
- /* free up any caches */
- for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
- cairo_command_t *command = elements[i];
-
- _cairo_clip_drop_cache (&command->header.clip);
- }
-
_cairo_surface_wrapper_fini (&wrapper);
-
return _cairo_surface_set_error (surface, status);
}
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 1f952c4..1504eaa 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -216,11 +216,11 @@ cairo_private cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
- const char * utf8,
+ const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
-typedef cairo_status_t
+typedef cairo_int_status_t
(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset,
void *closure);
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 433ca3f..dd6b824 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -511,7 +511,7 @@ _cairo_sub_font_add_glyph (cairo_sub_font_t *sub_font,
int *num_glyphs_in_subset_ptr;
double x_advance;
double y_advance;
- cairo_status_t status;
+ cairo_int_status_t status;
_cairo_scaled_font_freeze_cache (sub_font->scaled_font);
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
@@ -828,7 +828,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
cairo_matrix_t identity;
cairo_font_options_t font_options;
cairo_scaled_font_t *unscaled_font;
- cairo_status_t status;
+ cairo_int_status_t status;
int max_glyphs;
cairo_bool_t type1_font;
@@ -881,10 +881,10 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
&scaled_glyph);
_cairo_scaled_font_thaw_cache (scaled_font);
}
- if (_cairo_status_is_error (status))
+ if (_cairo_int_status_is_error (status))
return status;
- if (status == CAIRO_STATUS_SUCCESS &&
+ if (status == CAIRO_INT_STATUS_SUCCESS &&
subsets->type != CAIRO_SUBSETS_SCALED &&
! _cairo_font_face_is_user (scaled_font->font_face))
{
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index c6c599b..6cca4ac 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1858,7 +1858,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
cairo_text_cluster_flags_t *cluster_flags)
{
int num_chars = 0;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_glyph_t *orig_glyphs;
cairo_text_cluster_t *orig_clusters;
@@ -1941,7 +1941,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
clusters, num_clusters,
cluster_flags);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
- if (status == CAIRO_STATUS_SUCCESS) {
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
/* The checks here are crude; we only should do them in
* user-font backend, but they don't hurt here. This stuff
* can be hard to get right. */
@@ -2193,7 +2193,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_region_t *clip_region)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_surface_t *mask = NULL;
cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */
cairo_surface_pattern_t mask_pattern;
@@ -2224,7 +2224,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (remaining_glyphs == 0)
- status = CAIRO_STATUS_SUCCESS;
+ status = CAIRO_INT_STATUS_SUCCESS;
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_scaled_font_set_error (scaled_font, status);
}
@@ -2480,7 +2480,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_path_fixed_t *path)
{
- cairo_status_t status;
+ cairo_int_status_t status;
int i;
status = scaled_font->status;
@@ -2495,7 +2495,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
- if (status == CAIRO_STATUS_SUCCESS) {
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
status = _cairo_path_fixed_append (path,
scaled_glyph->path,
_cairo_fixed_from_double (glyphs[i].x),
@@ -2787,7 +2787,7 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_info_t info,
cairo_scaled_glyph_t **scaled_glyph_ret)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
cairo_scaled_glyph_t *scaled_glyph;
cairo_scaled_glyph_info_t need_info;
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 4ca0faf..6f46320 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -839,6 +839,7 @@ _format_to_string (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_ARGB32: return "ARGB32";
+ case CAIRO_FORMAT_RGB30: return "RGB30";
case CAIRO_FORMAT_RGB24: return "RGB24";
case CAIRO_FORMAT_RGB16_565: return "RGB16_565";
case CAIRO_FORMAT_A8: return "A8";
@@ -1204,6 +1205,7 @@ _write_image_surface (cairo_output_stream_t *output,
data += stride;
}
break;
+ case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32:
for (row = image->height; row--; ) {
uint32_t *src = (uint32_t *) data;
@@ -1279,14 +1281,14 @@ _undef (void *data)
free (def);
}
-static cairo_status_t
+static cairo_int_status_t
_emit_image_surface (cairo_script_surface_t *surface,
cairo_image_surface_t *image)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_output_stream_t *base85_stream;
cairo_output_stream_t *zlib_stream;
- cairo_status_t status, status2;
+ cairo_int_status_t status, status2;
const uint8_t *mime_data;
unsigned long mime_data_length;
struct def *tag;
@@ -1297,11 +1299,11 @@ _emit_image_surface (cairo_script_surface_t *surface,
_cairo_output_stream_printf (ctx->stream,
"s%u ",
image->base.unique_id);
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
status = _emit_png_surface (surface, image);
- if (_cairo_status_is_error (status)) {
+ if (_cairo_int_status_is_error (status)) {
return status;
} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
cairo_image_surface_t *clone;
@@ -1336,6 +1338,7 @@ _emit_image_surface (cairo_script_surface_t *surface,
case CAIRO_FORMAT_RGB24:
len = clone->width * 3;
break;
+ case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32:
len = clone->width * 4;
break;
@@ -1357,10 +1360,10 @@ _emit_image_surface (cairo_script_surface_t *surface,
status = _write_image_surface (zlib_stream, clone);
status2 = _cairo_output_stream_destroy (zlib_stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
status2 = _cairo_output_stream_destroy (base85_stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
if (unlikely (status))
return status;
@@ -1370,7 +1373,7 @@ _emit_image_surface (cairo_script_surface_t *surface,
base85_stream = _cairo_base85_stream_create (ctx->stream);
status = _write_image_surface (base85_stream, clone);
status2 = _cairo_output_stream_destroy (base85_stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
if (unlikely (status))
return status;
@@ -1432,10 +1435,10 @@ _emit_image_surface (cairo_script_surface_t *surface,
_cairo_output_stream_puts (ctx->stream, "~> set-mime-data\n");
}
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_emit_image_surface_pattern (cairo_script_surface_t *surface,
cairo_surface_t *source)
{
@@ -1458,12 +1461,12 @@ _emit_image_surface_pattern (cairo_script_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_emit_subsurface_pattern (cairo_script_surface_t *surface,
cairo_surface_subsurface_t *sub)
{
cairo_surface_t *source = sub->target;
- cairo_status_t status;
+ cairo_int_status_t status;
switch ((int) source->backend->type) {
case CAIRO_SURFACE_TYPE_RECORDING:
@@ -1485,16 +1488,16 @@ _emit_subsurface_pattern (cairo_script_surface_t *surface,
sub->extents.y,
sub->extents.width,
sub->extents.height);
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_emit_surface_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_surface_pattern_t *surface_pattern;
cairo_surface_t *source;
- cairo_status_t status;
+ cairo_int_status_t status;
surface_pattern = (cairo_surface_pattern_t *) pattern;
source = surface_pattern->surface;
@@ -1520,15 +1523,15 @@ _emit_surface_pattern (cairo_script_surface_t *surface,
return status;
_cairo_output_stream_puts (to_context (surface)->stream, "pattern");
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_emit_pattern (cairo_script_surface_t *surface,
const cairo_pattern_t *pattern)
{
cairo_script_context_t *ctx = to_context (surface);
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_bool_t is_default_extend;
cairo_bool_t need_newline = TRUE;
@@ -1599,17 +1602,17 @@ _emit_pattern (cairo_script_surface_t *surface,
if (need_newline)
_cairo_output_stream_puts (ctx->stream, "\n ");
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_emit_identity (cairo_script_surface_t *surface,
cairo_bool_t *matrix_updated)
{
assert (target_is_active (surface));
if (_cairo_matrix_is_identity (&surface->cr.current_ctm))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
_cairo_output_stream_puts (to_context (surface)->stream,
"identity set-matrix\n");
@@ -1617,26 +1620,26 @@ _emit_identity (cairo_script_surface_t *surface,
*matrix_updated = TRUE;
cairo_matrix_init_identity (&surface->cr.current_ctm);
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_emit_source (cairo_script_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source)
{
cairo_bool_t matrix_updated = FALSE;
- cairo_status_t status;
+ cairo_int_status_t status;
assert (target_is_active (surface));
if (op == CAIRO_OPERATOR_CLEAR) {
/* the source is ignored, so don't change it */
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
if (_cairo_pattern_equal (&surface->cr.current_source.base, source))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
_cairo_pattern_fini (&surface->cr.current_source.base);
status = _cairo_pattern_init_copy (&surface->cr.current_source.base,
@@ -1655,7 +1658,7 @@ _emit_source (cairo_script_surface_t *surface,
assert (target_is_active (surface));
_cairo_output_stream_puts (to_context (surface)->stream,
" set-source\n");
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_status_t
@@ -1711,7 +1714,7 @@ _path_close (void *closure)
static cairo_status_t
_emit_path (cairo_script_surface_t *surface,
- cairo_path_fixed_t *path)
+ const cairo_path_fixed_t *path)
{
cairo_script_context_t *ctx = to_context (surface);
cairo_box_t box;
@@ -2263,7 +2266,7 @@ static cairo_int_status_t
_cairo_script_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_status_t status;
@@ -2310,7 +2313,7 @@ _cairo_script_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_status_t status;
@@ -2366,13 +2369,13 @@ static cairo_int_status_t
_cairo_script_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_bool_t matrix_updated = FALSE;
@@ -2457,11 +2460,11 @@ static cairo_int_status_t
_cairo_script_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_bool_t matrix_updated = FALSE;
@@ -2743,7 +2746,7 @@ _emit_scaled_font_init (cairo_script_surface_t *surface,
{
cairo_script_context_t *ctx = to_context (surface);
cairo_script_surface_font_private_t *font_private;
- cairo_status_t status;
+ cairo_int_status_t status;
font_private = malloc (sizeof (cairo_script_surface_font_private_t));
if (unlikely (font_private == NULL))
@@ -3135,7 +3138,7 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t backward,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_script_surface_t *surface = abstract_surface;
cairo_script_context_t *ctx = to_context (surface);
diff --git a/src/cairo-spans.c b/src/cairo-spans.c
index 09af57a..f658650 100644
--- a/src/cairo-spans.c
+++ b/src/cairo-spans.c
@@ -27,7 +27,10 @@
#include "cairoint.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-clip-private.h"
+#include "cairo-error-private.h"
#include "cairo-fixed-private.h"
+#include "cairo-types-private.h"
static cairo_scan_converter_t *
_create_scan_converter (cairo_fill_rule_t fill_rule,
@@ -62,6 +65,31 @@ _cairo_surface_composite_polygon (cairo_surface_t *surface,
cairo_span_renderer_t *renderer;
cairo_scan_converter_t *converter;
cairo_status_t status;
+ cairo_clip_path_t *clip_path = rects->clip->path;
+
+ if (rects->is_bounded) {
+ if (polygon->num_edges == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (clip_path) { /* XXX */
+ cairo_polygon_t clipper;
+ cairo_fill_rule_t clipper_fill_rule;
+ cairo_antialias_t clipper_antialias;
+
+ if (_cairo_clip_get_polygon (rects->clip, &clipper,
+ &clipper_fill_rule,
+ &clipper_antialias) == CAIRO_INT_STATUS_SUCCESS) {
+ if (clipper_antialias != CAIRO_ANTIALIAS_NONE &&
+ _cairo_polygon_intersect (polygon, fill_rule,
+ &clipper, clipper_fill_rule) == CAIRO_STATUS_SUCCESS)
+ {
+ rects->clip->path = NULL;
+ }
+
+ _cairo_polygon_fini (&clipper);
+ }
+ }
+ }
converter = _create_scan_converter (fill_rule, antialias, rects);
status = converter->add_polygon (converter, polygon);
@@ -81,6 +109,7 @@ _cairo_surface_composite_polygon (cairo_surface_t *surface,
renderer->destroy (renderer);
CLEANUP_CONVERTER:
converter->destroy (converter);
+ rects->clip->path = clip_path;
return status;
}
diff --git a/src/cairo-surface-clipper-private.h b/src/cairo-surface-clipper-private.h
index b9ca3cb..e5b00af 100644
--- a/src/cairo-surface-clipper-private.h
+++ b/src/cairo-surface-clipper-private.h
@@ -51,14 +51,13 @@ typedef cairo_status_t
double,
cairo_antialias_t);
struct _cairo_surface_clipper {
- cairo_clip_t clip;
- cairo_bool_t is_clipped;
+ cairo_clip_t *clip;
cairo_surface_clipper_intersect_clip_path_func_t intersect_clip_path;
};
cairo_private cairo_status_t
_cairo_surface_clipper_set_clip (cairo_surface_clipper_t *clipper,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private void
_cairo_surface_clipper_init (cairo_surface_clipper_t *clipper,
diff --git a/src/cairo-surface-clipper.c b/src/cairo-surface-clipper.c
index 9487300..c1644b4 100644
--- a/src/cairo-surface-clipper.c
+++ b/src/cairo-surface-clipper.c
@@ -39,6 +39,63 @@
/* A collection of routines to facilitate vector surface clipping */
+/* XXX Eliminate repeated paths and nested clips */
+
+static cairo_status_t
+_cairo_path_fixed_add_box (cairo_path_fixed_t *path,
+ const cairo_box_t *box)
+{
+ cairo_status_t status;
+
+ status = _cairo_path_fixed_move_to (path, box->p1.x, box->p1.y);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_path_fixed_line_to (path, box->p2.x, box->p1.y);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_path_fixed_line_to (path, box->p2.x, box->p2.y);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_path_fixed_line_to (path, box->p1.x, box->p2.y);
+ if (unlikely (status))
+ return status;
+
+ return _cairo_path_fixed_close_path (path);
+}
+
+static cairo_status_t
+_cairo_surface_clipper_intersect_clip_boxes (cairo_surface_clipper_t *clipper,
+ const cairo_clip_t *clip)
+{
+ cairo_path_fixed_t path;
+ cairo_status_t status;
+ int i;
+
+ /* Reconstruct the path for the clip boxes.
+ * XXX maybe a new clipper callback?
+ */
+
+ _cairo_path_fixed_init (&path);
+ for (i = 0; i < clip->num_boxes; i++) {
+ status = _cairo_path_fixed_add_box (&path, &clip->boxes[i]);
+ if (unlikely (status)) {
+ _cairo_path_fixed_fini (&path);
+ return status;
+ }
+ }
+
+ status = clipper->intersect_clip_path (clipper, &path,
+ CAIRO_FILL_RULE_WINDING,
+ 0.,
+ CAIRO_ANTIALIAS_DEFAULT);
+ _cairo_path_fixed_init (&path);
+
+ return status;
+}
+
static cairo_status_t
_cairo_surface_clipper_intersect_clip_path_recursive (cairo_surface_clipper_t *clipper,
cairo_clip_path_t *clip_path)
@@ -62,57 +119,33 @@ _cairo_surface_clipper_intersect_clip_path_recursive (cairo_surface_clipper_t *c
cairo_status_t
_cairo_surface_clipper_set_clip (cairo_surface_clipper_t *clipper,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_bool_t clear;
-
- /* XXX as we cache a reference to the path, and compare every time,
- * we may in future need to install a notification if the clip->path
- * is every modified (e.g. cairo_clip_translate).
- */
- if (clip == NULL && clipper->clip.path == NULL)
+ if (_cairo_clip_equal (clip, clipper->clip))
return CAIRO_STATUS_SUCCESS;
- if (clip != NULL && clipper->clip.path != NULL &&
- _cairo_clip_equal (clip, &clipper->clip))
- {
- return CAIRO_STATUS_SUCCESS;
- }
-
/* all clipped out state should never propagate this far */
- assert (clip == NULL || clip->path != NULL);
+ assert (!_cairo_clip_is_all_clipped (clip));
- /* Check whether this clip is a continuation of the previous.
- * If not, we have to remove the current clip and rebuild.
- */
- clear = clip == NULL || clip->path->prev != clipper->clip.path;
+ _cairo_clip_destroy (clipper->clip);
+ clipper->clip = _cairo_clip_copy (clip);
- _cairo_clip_reset (&clipper->clip);
- _cairo_clip_init_copy (&clipper->clip, clip);
+ status = clipper->intersect_clip_path (clipper, NULL, 0, 0, 0);
+ if (unlikely (status))
+ return status;
- if (clear) {
- clipper->is_clipped = FALSE;
- status = clipper->intersect_clip_path (clipper, NULL, 0, 0, 0);
- if (unlikely (status))
- return status;
+ if (clip == NULL)
+ return CAIRO_STATUS_SUCCESS;
- if (clip != NULL && clip->path != NULL) {
- status =
- _cairo_surface_clipper_intersect_clip_path_recursive (clipper,
- clip->path);
- clipper->is_clipped = TRUE;
- }
- } else {
- cairo_clip_path_t *path = clip->path;
-
- clipper->is_clipped = TRUE;
- status = clipper->intersect_clip_path (clipper,
- &path->path,
- path->fill_rule,
- path->tolerance,
- path->antialias);
+ status = _cairo_surface_clipper_intersect_clip_boxes (clipper, clip);
+ if (unlikely (status))
+ return status;
+
+ if (clip->path != NULL) {
+ status = _cairo_surface_clipper_intersect_clip_path_recursive (clipper,
+ clip->path);
}
return status;
@@ -122,14 +155,13 @@ void
_cairo_surface_clipper_init (cairo_surface_clipper_t *clipper,
cairo_surface_clipper_intersect_clip_path_func_t func)
{
- _cairo_clip_init (&clipper->clip);
- clipper->is_clipped = FALSE;
+ clipper->clip = NULL;
clipper->intersect_clip_path = func;
}
void
_cairo_surface_clipper_reset (cairo_surface_clipper_t *clipper)
{
- _cairo_clip_reset (&clipper->clip);
- clipper->is_clipped = FALSE;
+ _cairo_clip_destroy (clipper->clip);
+ clipper->clip = NULL;
}
diff --git a/src/cairo-surface-fallback-private.h b/src/cairo-surface-fallback-private.h
index e993de6..ffb6f91 100644
--- a/src/cairo-surface-fallback-private.h
+++ b/src/cairo-surface-fallback-private.h
@@ -45,36 +45,36 @@ cairo_private cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_fallback_mask (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_fallback_fill (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
@@ -83,7 +83,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_surface_t *
_cairo_surface_fallback_snapshot (cairo_surface_t *surface);
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 5a30d4f..21966fe 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -128,20 +128,10 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
const cairo_rectangle_int_t *extents)
{
cairo_surface_t *mask;
- cairo_region_t *clip_region = NULL, *fallback_region = NULL;
cairo_status_t status;
- cairo_bool_t clip_surface = FALSE;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- if (unlikely (_cairo_status_is_error (status) ||
- status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- {
- return status;
- }
-
- clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ cairo_region_t *clip_region = _cairo_clip_get_region (clip);
+ cairo_bool_t clip_surface = ! _cairo_clip_is_region (clip);
+ cairo_region_t *fallback_region = NULL;
/* We need to use solid here, because to use CAIRO_OPERATOR_SOURCE with
* a mask (as called via _cairo_surface_mask) triggers assertion failures.
@@ -282,7 +272,6 @@ _clip_and_composite_combine (cairo_clip_t *clip,
if (unlikely (status))
goto CLEANUP_SURFACE;
- assert (clip->path != NULL);
clip_surface = _cairo_clip_get_surface (clip, dst, &clip_x, &clip_y);
if (unlikely (clip_surface->status))
goto CLEANUP_SURFACE;
@@ -344,18 +333,9 @@ _clip_and_composite_source (cairo_clip_t *clip,
const cairo_rectangle_int_t *extents)
{
cairo_surface_pattern_t mask_pattern;
- cairo_region_t *clip_region = NULL;
+ cairo_region_t *clip_region = _cairo_clip_get_region (clip);
cairo_status_t status;
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- if (unlikely (_cairo_status_is_error (status) ||
- status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- {
- return status;
- }
- }
-
/* Create a surface that is mask IN clip */
status = _create_composite_mask_pattern (&mask_pattern,
clip,
@@ -390,12 +370,6 @@ _clip_and_composite_source (cairo_clip_t *clip,
return status;
}
-static int
-_cairo_rectangle_empty (const cairo_rectangle_int_t *rect)
-{
- return rect->width == 0 || rect->height == 0;
-}
-
/**
* _clip_and_composite:
* @clip: a #cairo_clip_t
@@ -428,10 +402,6 @@ _clip_and_composite (cairo_clip_t *clip,
{
cairo_status_t status;
- if (_cairo_rectangle_empty (extents))
- /* Nothing to do */
- return CAIRO_STATUS_SUCCESS;
-
if (op == CAIRO_OPERATOR_CLEAR) {
src = &_cairo_pattern_white.base;
op = CAIRO_OPERATOR_DEST_OUT;
@@ -443,21 +413,7 @@ _clip_and_composite (cairo_clip_t *clip,
draw_func, draw_closure,
dst, extents);
} else {
- cairo_bool_t clip_surface = FALSE;
- cairo_region_t *clip_region = NULL;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- if (unlikely (_cairo_status_is_error (status) ||
- status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- {
- return status;
- }
-
- clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- if (clip_surface) {
+ if (! _cairo_clip_is_region (clip)) {
if (_cairo_operator_bounded_by_mask (op)) {
status = _clip_and_composite_with_mask (clip, op,
src,
@@ -474,7 +430,7 @@ _clip_and_composite (cairo_clip_t *clip,
src, dst,
0, 0,
extents,
- clip_region);
+ _cairo_clip_get_region (clip));
}
}
@@ -779,23 +735,12 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
cairo_rectangle_int_t *extents)
{
cairo_composite_traps_info_t traps_info;
- cairo_region_t *clip_region = NULL;
- cairo_bool_t clip_surface = FALSE;
- cairo_status_t status;
+ cairo_bool_t clip_surface = ! _cairo_clip_is_region (clip);
+ cairo_int_status_t status;
if (traps->num_traps == 0 && _cairo_operator_bounded_by_mask (op))
return CAIRO_STATUS_SUCCESS;
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- if (unlikely (_cairo_status_is_error (status)))
- return status;
- if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
-
- clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
/* Use a fast path if the trapezoids consist of a simple region,
* but we can only do this if we do not have a clip surface, or can
* substitute the mask with the clip.
@@ -815,8 +760,8 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
return status;
}
- status = _cairo_traps_extract_region (traps, &trap_region);
- if (unlikely (_cairo_status_is_error (status)))
+ status = _cairo_traps_extract_region (traps, antialias, &trap_region);
+ if (unlikely (_cairo_int_status_is_error (status)))
return status;
if (trap_region != NULL) {
@@ -826,21 +771,13 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
return status;
}
- if (clip_region != NULL) {
- status = cairo_region_intersect (trap_region, clip_region);
- if (unlikely (status)) {
- cairo_region_destroy (trap_region);
- return status;
- }
- }
-
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t trap_extents;
cairo_region_get_extents (trap_region, &trap_extents);
if (! _cairo_rectangle_intersect (extents, &trap_extents)) {
cairo_region_destroy (trap_region);
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
}
@@ -882,16 +819,12 @@ cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_rectangle_int_t rect;
- cairo_clip_path_t *clip_path = clip ? clip->path : NULL;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
cairo_boxes_t boxes;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
- cairo_status_t status;
- cairo_traps_t traps;
+ cairo_int_status_t status;
if (!_cairo_surface_get_extents (surface, &rect))
ASSERT_NOT_REACHED;
@@ -904,44 +837,22 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status))
- return status;
-
- /* If the clip cannot be reduced to a set of boxes, we will need to
- * use a clipmask. Paint is special as it is the only operation that
- * does not implicitly use a mask, so we may be able to reduce this
- * operation to a fill...
- */
- if (clip != NULL && clip_path->prev == NULL &&
- _cairo_operator_bounded_by_mask (op))
- {
- return _cairo_surface_fill (surface, op, source,
- &clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- clip_path->antialias,
- NULL);
+ status = _cairo_clip_to_boxes (extents.clip, &boxes);
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
+ cairo_traps_t traps;
+
+ /* meh, surface-fallback is dying anyway... */
+ status = _cairo_traps_init_boxes (&traps, &boxes);
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
+ status = _clip_and_composite_trapezoids (source, op, surface,
+ &traps, CAIRO_ANTIALIAS_DEFAULT,
+ extents.clip,
+ extents.is_bounded ? &extents.bounded : &extents.unbounded);
+ _cairo_traps_fini (&traps);
+ }
}
- /* meh, surface-fallback is dying anyway... */
- _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
- status = _cairo_traps_init_boxes (&traps, &boxes);
- if (unlikely (status))
- goto CLEANUP_BOXES;
-
- status = _clip_and_composite_trapezoids (source, op, surface,
- &traps, CAIRO_ANTIALIAS_DEFAULT,
- clip,
- extents.is_bounded ? &extents.bounded : &extents.unbounded);
- _cairo_traps_fini (&traps);
-
-CLEANUP_BOXES:
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -957,7 +868,7 @@ _cairo_surface_mask_draw_func (void *closure,
cairo_region_t *clip_region)
{
cairo_pattern_t *mask = closure;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_region_t *extents_region = NULL;
if (clip_region == NULL &&
@@ -998,7 +909,7 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_rectangle_int_t rect;
@@ -1013,38 +924,31 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
+ status = _clip_and_composite (extents.clip, op, source,
+ _cairo_surface_mask_draw_func,
+ (void *) mask,
+ surface,
+ extents.is_bounded ? &extents.bounded : &extents.unbounded);
- if (clip != NULL && extents.is_bounded) {
- status = _cairo_clip_rectangle (clip, &extents.bounded);
- if (unlikely (status))
- return status;
- }
+ _cairo_composite_rectangles_fini (&extents);
- return _clip_and_composite (clip, op, source,
- _cairo_surface_mask_draw_func,
- (void *) mask,
- surface,
- extents.is_bounded ? &extents.bounded : &extents.unbounded);
+ return status;
}
cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_polygon_t polygon;
cairo_traps_t traps;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
cairo_composite_rectangles_t extents;
cairo_rectangle_int_t rect;
cairo_status_t status;
@@ -1061,22 +965,14 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status))
- return status;
-
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
-
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, clip_boxes, num_boxes);
+ _cairo_polygon_init_with_clip (&polygon, extents.clip);
+ _cairo_traps_init_with_clip (&traps, extents.clip);
if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
status = _cairo_path_fixed_stroke_rectilinear_to_traps (path,
stroke_style,
ctm,
+ antialias,
&traps);
if (likely (status == CAIRO_STATUS_SUCCESS))
goto DO_TRAPS;
@@ -1112,13 +1008,13 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
DO_TRAPS:
status = _clip_and_composite_trapezoids (source, op, surface,
&traps, antialias,
- clip,
+ extents.clip,
extents.is_bounded ? &extents.bounded : &extents.unbounded);
CLEANUP:
_cairo_traps_fini (&traps);
_cairo_polygon_fini (&polygon);
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
+
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -1127,16 +1023,14 @@ cairo_status_t
_cairo_surface_fallback_fill (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_polygon_t polygon;
cairo_traps_t traps;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
cairo_bool_t is_rectilinear;
cairo_composite_rectangles_t extents;
cairo_rectangle_int_t rect;
@@ -1153,17 +1047,8 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status))
- return status;
-
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, clip_boxes, num_boxes);
-
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
+ _cairo_traps_init_with_clip (&traps, extents.clip);
+ _cairo_polygon_init_with_clip (&polygon, extents.clip);
if (_cairo_path_fixed_fill_is_empty (path))
goto DO_TRAPS;
@@ -1172,6 +1057,7 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
if (is_rectilinear) {
status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
fill_rule,
+ antialias,
&traps);
if (likely (status == CAIRO_STATUS_SUCCESS))
goto DO_TRAPS;
@@ -1214,13 +1100,13 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
DO_TRAPS:
status = _clip_and_composite_trapezoids (source, op, surface,
&traps, antialias,
- clip,
+ extents.clip,
extents.is_bounded ? &extents.bounded : &extents.unbounded);
CLEANUP:
_cairo_traps_fini (&traps);
_cairo_polygon_fini (&polygon);
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
+
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -1242,17 +1128,7 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
cairo_region_t *clip_region)
{
cairo_show_glyphs_info_t *glyph_info = closure;
- cairo_status_t status;
- cairo_region_t *extents_region = NULL;
-
- if (clip_region == NULL &&
- !_cairo_operator_bounded_by_source (op)) {
- extents_region = cairo_region_create_rectangle (extents);
- if (unlikely (extents_region->status))
- return extents_region->status;
- cairo_region_translate (extents_region, -dst_x, -dst_y);
- clip_region = extents_region;
- }
+ cairo_int_status_t status;
/* Modifying the glyph array is fine because we know that this function
* will be called only once, and we've already made a copy of the
@@ -1291,9 +1167,6 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
clip_region);
}
- if (extents_region)
- cairo_region_destroy (extents_region);
-
return status;
}
@@ -1304,12 +1177,12 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_show_glyphs_info_t glyph_info;
cairo_composite_rectangles_t extents;
cairo_rectangle_int_t rect;
- cairo_status_t status;
+ cairo_int_status_t status;
if (!_cairo_surface_get_extents (surface, &rect))
ASSERT_NOT_REACHED;
@@ -1325,24 +1198,18 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_rectangle (clip, &extents.mask))
- clip = NULL;
-
- if (clip != NULL && extents.is_bounded) {
- status = _cairo_clip_rectangle (clip, &extents.bounded);
- if (unlikely (status))
- return status;
- }
-
glyph_info.font = scaled_font;
glyph_info.glyphs = glyphs;
glyph_info.num_glyphs = num_glyphs;
- return _clip_and_composite (clip, op, source,
- _cairo_surface_old_show_glyphs_draw_func,
- &glyph_info,
- surface,
- extents.is_bounded ? &extents.bounded : &extents.unbounded);
+ status = _clip_and_composite (extents.clip, op, source,
+ _cairo_surface_old_show_glyphs_draw_func,
+ &glyph_info, surface,
+ extents.is_bounded ? &extents.bounded : &extents.unbounded);
+
+ _cairo_composite_rectangles_fini (&extents);
+
+ return status;
}
cairo_surface_t *
diff --git a/src/cairo-surface-offset-private.h b/src/cairo-surface-offset-private.h
index b7877b3..310ba56 100644
--- a/src/cairo-surface-offset-private.h
+++ b/src/cairo-surface-offset-private.h
@@ -48,7 +48,7 @@ _cairo_surface_offset_paint (cairo_surface_t *target,
int x, int y,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_offset_mask (cairo_surface_t *target,
@@ -56,31 +56,31 @@ _cairo_surface_offset_mask (cairo_surface_t *target,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_offset_stroke (cairo_surface_t *surface,
int x, int y,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_offset_fill (cairo_surface_t *surface,
int x, int y,
cairo_operator_t op,
const cairo_pattern_t*source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_offset_glyphs (cairo_surface_t *surface,
@@ -90,6 +90,6 @@ _cairo_surface_offset_glyphs (cairo_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
#endif /* CAIRO_SURFACE_OFFSET_PRIVATE_H */
diff --git a/src/cairo-surface-offset.c b/src/cairo-surface-offset.c
index c36196e..d2cc030 100644
--- a/src/cairo-surface-offset.c
+++ b/src/cairo-surface-offset.c
@@ -59,29 +59,22 @@ _cairo_surface_offset_paint (cairo_surface_t *target,
int x, int y,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_pattern_union_t source_copy;
if (unlikely (target->status))
return target->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (x | y) {
cairo_matrix_t m;
- if (clip != NULL) {
- cairo_matrix_init_translate (&m, -x, -y);
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
cairo_matrix_init_translate (&m, x, y);
_copy_transformed_pattern (&source_copy.base, source, &m);
@@ -90,9 +83,8 @@ _cairo_surface_offset_paint (cairo_surface_t *target,
status = _cairo_surface_paint (target, op, source, dev_clip);
- FINISH:
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -103,30 +95,23 @@ _cairo_surface_offset_mask (cairo_surface_t *target,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_pattern_union_t source_copy;
cairo_pattern_union_t mask_copy;
if (unlikely (target->status))
return target->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (x | y) {
cairo_matrix_t m;
- if (clip != NULL) {
- cairo_matrix_init_translate (&m, -x, -y);
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
cairo_matrix_init_translate (&m, x, y);
_copy_transformed_pattern (&source_copy.base, source, &m);
@@ -139,9 +124,8 @@ _cairo_surface_offset_mask (cairo_surface_t *target,
source, mask,
dev_clip);
- FINISH:
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -151,16 +135,16 @@ _cairo_surface_offset_stroke (cairo_surface_t *surface,
int x, int y,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t*stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
- cairo_path_fixed_t path_copy, *dev_path = path;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_matrix_t dev_ctm = *ctm;
cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
cairo_pattern_union_t source_copy;
@@ -169,12 +153,14 @@ _cairo_surface_offset_stroke (cairo_surface_t *surface,
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (x | y) {
cairo_matrix_t m;
+ dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
+
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (unlikely (status))
goto FINISH;
@@ -186,13 +172,6 @@ _cairo_surface_offset_stroke (cairo_surface_t *surface,
cairo_matrix_init_translate (&m, -x, -y);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
- if (clip != NULL) {
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
cairo_matrix_init_translate (&m, x, y);
_copy_transformed_pattern (&source_copy.base, source, &m);
@@ -206,11 +185,11 @@ _cairo_surface_offset_stroke (cairo_surface_t *surface,
tolerance, antialias,
dev_clip);
- FINISH:
+FINISH:
if (dev_path != path)
_cairo_path_fixed_fini (dev_path);
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -220,26 +199,28 @@ _cairo_surface_offset_fill (cairo_surface_t *surface,
int x, int y,
cairo_operator_t op,
const cairo_pattern_t*source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_path_fixed_t path_copy, *dev_path = path;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_pattern_union_t source_copy;
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (x | y) {
cairo_matrix_t m;
+ dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
+
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (unlikely (status))
goto FINISH;
@@ -249,15 +230,6 @@ _cairo_surface_offset_fill (cairo_surface_t *surface,
_cairo_fixed_from_int (-y));
dev_path = &path_copy;
- if (clip != NULL) {
- cairo_matrix_init_translate (&m, -x, -y);
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
-
cairo_matrix_init_translate (&m, x, y);
_copy_transformed_pattern (&source_copy.base, source, &m);
source = &source_copy.base;
@@ -268,11 +240,11 @@ _cairo_surface_offset_fill (cairo_surface_t *surface,
tolerance, antialias,
dev_clip);
- FINISH:
+FINISH:
if (dev_path != path)
_cairo_path_fixed_fini (dev_path);
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -285,10 +257,10 @@ _cairo_surface_offset_glyphs (cairo_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_pattern_union_t source_copy;
cairo_glyph_t *dev_glyphs;
int i;
@@ -296,7 +268,7 @@ _cairo_surface_offset_glyphs (cairo_surface_t *surface,
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
@@ -308,14 +280,7 @@ _cairo_surface_offset_glyphs (cairo_surface_t *surface,
if (x | y) {
cairo_matrix_t m;
- if (clip != NULL) {
- cairo_matrix_init_translate (&m, -x, -y);
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ dev_clip = _cairo_clip_copy_with_translation (clip, -x, -y);
cairo_matrix_init_translate (&m, x, y);
_copy_transformed_pattern (&source_copy.base, source, &m);
@@ -334,9 +299,8 @@ _cairo_surface_offset_glyphs (cairo_surface_t *surface,
scaled_font,
dev_clip);
- FINISH:
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
free (dev_glyphs);
return status;
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index ff1df83..2a4a4fb 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -65,23 +65,18 @@ static cairo_int_status_t
_cairo_surface_subsurface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_surface_subsurface_t *surface = abstract_surface;
cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
cairo_status_t status;
- cairo_clip_t target_clip;
-
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &rect);
- if (unlikely (status))
- goto CLEANUP;
+ cairo_clip_t *target_clip;
+ target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
status = _cairo_surface_offset_paint (surface->target,
-surface->extents.x, -surface->extents.y,
- op, source, &target_clip);
- CLEANUP:
- _cairo_clip_fini (&target_clip);
+ op, source, target_clip);
+ _cairo_clip_destroy (target_clip);
return status;
}
@@ -90,23 +85,18 @@ _cairo_surface_subsurface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_surface_subsurface_t *surface = abstract_surface;
cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
cairo_status_t status;
- cairo_clip_t target_clip;
-
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &rect);
- if (unlikely (status))
- goto CLEANUP;
+ cairo_clip_t *target_clip;
+ target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
status = _cairo_surface_offset_mask (surface->target,
-surface->extents.x, -surface->extents.y,
- op, source, mask, &target_clip);
- CLEANUP:
- _cairo_clip_fini (&target_clip);
+ op, source, mask, target_clip);
+ _cairo_clip_destroy (target_clip);
return status;
}
@@ -114,28 +104,23 @@ static cairo_int_status_t
_cairo_surface_subsurface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_surface_subsurface_t *surface = abstract_surface;
cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
cairo_status_t status;
- cairo_clip_t target_clip;
-
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &rect);
- if (unlikely (status))
- goto CLEANUP;
+ cairo_clip_t *target_clip;
+ target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
status = _cairo_surface_offset_fill (surface->target,
-surface->extents.x, -surface->extents.y,
op, source, path, fill_rule, tolerance, antialias,
- &target_clip);
- CLEANUP:
- _cairo_clip_fini (&target_clip);
+ target_clip);
+ _cairo_clip_destroy (target_clip);
return status;
}
@@ -143,31 +128,26 @@ static cairo_int_status_t
_cairo_surface_subsurface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_surface_subsurface_t *surface = abstract_surface;
cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
cairo_status_t status;
- cairo_clip_t target_clip;
-
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &rect);
- if (unlikely (status))
- goto CLEANUP;
+ cairo_clip_t *target_clip;
+ target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
status = _cairo_surface_offset_stroke (surface->target,
-surface->extents.x, -surface->extents.y,
op, source, path, stroke_style, ctm, ctm_inverse,
tolerance, antialias,
- &target_clip);
- CLEANUP:
- _cairo_clip_fini (&target_clip);
+ target_clip);
+ _cairo_clip_destroy (target_clip);
return status;
}
@@ -178,27 +158,22 @@ _cairo_surface_subsurface_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_surface_subsurface_t *surface = abstract_surface;
cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
cairo_status_t status;
- cairo_clip_t target_clip;
-
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &rect);
- if (unlikely (status))
- goto CLEANUP;
+ cairo_clip_t *target_clip;
+ target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect);
status = _cairo_surface_offset_glyphs (surface->target,
-surface->extents.x, -surface->extents.y,
op, source,
scaled_font, glyphs, num_glyphs,
- &target_clip);
+ target_clip);
*remaining_glyphs = 0;
- CLEANUP:
- _cairo_clip_fini (&target_clip);
+ _cairo_clip_destroy (target_clip);
return status;
}
diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h
index 39dad2b..b3d3a55 100644
--- a/src/cairo-surface-wrapper-private.h
+++ b/src/cairo-surface-wrapper-private.h
@@ -76,26 +76,26 @@ cairo_private cairo_status_t
_cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
@@ -112,17 +112,17 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
const cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
@@ -136,7 +136,7 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_surface_t *
_cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper,
diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index a76003b..9e746f9 100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -90,26 +90,20 @@ cairo_status_t
_cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
+ cairo_clip_t *target_clip = NULL;
cairo_pattern_union_t source_copy;
- cairo_clip_t target_clip;
if (unlikely (wrapper->target->status))
return wrapper->target->status;
- if (wrapper->has_extents) {
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = clip = &target_clip;
- }
+ if (wrapper->has_extents)
+ dev_clip = target_clip = _cairo_clip_copy_intersect_rectangle (clip, &wrapper->extents);
- if (clip && clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (dev_clip)) {
status = CAIRO_STATUS_SUCCESS;
goto FINISH;
}
@@ -127,13 +121,8 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
- if (clip != NULL) {
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ /* XXX */
+ dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
status = cairo_matrix_invert (&m);
assert (status == CAIRO_STATUS_SUCCESS);
@@ -145,10 +134,9 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
status = _cairo_surface_paint (wrapper->target, op, source, dev_clip);
FINISH:
- if (wrapper->has_extents)
- _cairo_clip_reset (&target_clip);
+ _cairo_clip_destroy (target_clip);
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -157,27 +145,21 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_pattern_union_t source_copy;
cairo_pattern_union_t mask_copy;
- cairo_clip_t target_clip;
+ cairo_clip_t *target_clip = NULL;
if (unlikely (wrapper->target->status))
return wrapper->target->status;
- if (wrapper->has_extents) {
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = clip = &target_clip;
- }
+ if (wrapper->has_extents)
+ dev_clip = target_clip = _cairo_clip_copy_intersect_rectangle (clip, &wrapper->extents);
- if (clip && clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (dev_clip)) {
status = CAIRO_STATUS_SUCCESS;
goto FINISH;
}
@@ -195,13 +177,8 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
- if (clip != NULL) {
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ /* XXX */
+ dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
status = cairo_matrix_invert (&m);
assert (status == CAIRO_STATUS_SUCCESS);
@@ -216,10 +193,9 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);
FINISH:
- if (wrapper->has_extents)
- _cairo_clip_reset (&target_clip);
+ _cairo_clip_destroy (target_clip);
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -227,35 +203,29 @@ cairo_status_t
_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_path_fixed_t path_copy, *dev_path = path;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_matrix_t dev_ctm = *ctm;
cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
cairo_pattern_union_t source_copy;
- cairo_clip_t target_clip;
+ cairo_clip_t *target_clip = NULL;
if (unlikely (wrapper->target->status))
return wrapper->target->status;
- if (wrapper->has_extents) {
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = clip = &target_clip;
- }
+ if (wrapper->has_extents)
+ dev_clip = target_clip = _cairo_clip_copy_intersect_rectangle (clip, &wrapper->extents);
- if (clip && clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (dev_clip)) {
status = CAIRO_STATUS_SUCCESS;
goto FINISH;
}
@@ -280,13 +250,8 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
_cairo_path_fixed_transform (&path_copy, &m);
dev_path = &path_copy;
- if (clip != NULL) {
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ /* XXX */
+ dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
@@ -298,13 +263,6 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
_copy_transformed_pattern (&source_copy.base, source, &m);
source = &source_copy.base;
}
- else
- {
- if (clip != NULL) {
- dev_clip = &clip_copy;
- _cairo_clip_init_copy (&clip_copy, clip);
- }
- }
status = _cairo_surface_stroke (wrapper->target, op, source,
dev_path, stroke_style,
@@ -315,10 +273,9 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
FINISH:
if (dev_path != path)
_cairo_path_fixed_fini (dev_path);
- if (wrapper->has_extents)
- _cairo_clip_reset (&target_clip);
+ _cairo_clip_destroy (target_clip);
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -337,30 +294,24 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
const cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_path_fixed_t path_copy, *dev_path = path;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_matrix_t dev_ctm = *stroke_ctm;
cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
cairo_pattern_union_t stroke_source_copy;
cairo_pattern_union_t fill_source_copy;
- cairo_clip_t target_clip;
+ cairo_clip_t *target_clip = NULL;
if (unlikely (wrapper->target->status))
return wrapper->target->status;
- if (wrapper->has_extents) {
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = clip = &target_clip;
- }
+ if (wrapper->has_extents)
+ dev_clip = target_clip = _cairo_clip_copy_intersect_rectangle (clip, &wrapper->extents);
- if (clip && clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (dev_clip)) {
status = CAIRO_STATUS_SUCCESS;
goto FINISH;
}
@@ -385,13 +336,8 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
_cairo_path_fixed_transform (&path_copy, &m);
dev_path = &path_copy;
- if (clip != NULL) {
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ /* XXX */
+ dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
@@ -406,13 +352,6 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
_copy_transformed_pattern (&fill_source_copy.base, fill_source, &m);
fill_source = &fill_source_copy.base;
}
- else
- {
- if (clip != NULL) {
- dev_clip = &clip_copy;
- _cairo_clip_init_copy (&clip_copy, clip);
- }
- }
status = _cairo_surface_fill_stroke (wrapper->target,
fill_op, fill_source, fill_rule,
@@ -427,10 +366,9 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
FINISH:
if (dev_path != path)
_cairo_path_fixed_fini (dev_path);
- if (wrapper->has_extents)
- _cairo_clip_reset (&target_clip);
+ _cairo_clip_destroy (target_clip);
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -438,31 +376,25 @@ cairo_status_t
_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_path_fixed_t path_copy, *dev_path = path;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path;
+ cairo_clip_t *dev_clip = (cairo_clip_t *) clip;
cairo_pattern_union_t source_copy;
- cairo_clip_t target_clip;
+ cairo_clip_t *target_clip = NULL;
if (unlikely (wrapper->target->status))
return wrapper->target->status;
- if (wrapper->has_extents) {
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = clip = &target_clip;
- }
+ if (wrapper->has_extents)
+ dev_clip = target_clip = _cairo_clip_copy_intersect_rectangle (clip, &wrapper->extents);
- if (clip && clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (dev_clip)) {
status = CAIRO_STATUS_SUCCESS;
goto FINISH;
}
@@ -487,13 +419,8 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
_cairo_path_fixed_transform (&path_copy, &m);
dev_path = &path_copy;
- if (clip != NULL) {
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ /* XXX */
+ dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
status = cairo_matrix_invert (&m);
assert (status == CAIRO_STATUS_SUCCESS);
@@ -501,13 +428,6 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
_copy_transformed_pattern (&source_copy.base, source, &m);
source = &source_copy.base;
}
- else
- {
- if (clip != NULL) {
- dev_clip = &clip_copy;
- _cairo_clip_init_copy (&clip_copy, clip);
- }
- }
status = _cairo_surface_fill (wrapper->target, op, source,
dev_path, fill_rule,
@@ -517,10 +437,9 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
FINISH:
if (dev_path != path)
_cairo_path_fixed_fini (dev_path);
- if (wrapper->has_extents)
- _cairo_clip_reset (&target_clip);
+ _cairo_clip_destroy (target_clip);
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
+ _cairo_clip_destroy (dev_clip);
return status;
}
@@ -536,13 +455,13 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
- cairo_clip_t clip_copy, *dev_clip = clip;
+ cairo_clip_t *dev_clip = (cairo_clip_t *)clip;
cairo_glyph_t *dev_glyphs = glyphs;
cairo_pattern_union_t source_copy;
- cairo_clip_t target_clip;
+ cairo_clip_t *target_clip = NULL;
if (unlikely (wrapper->target->status))
return wrapper->target->status;
@@ -550,16 +469,10 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
if (glyphs == NULL || num_glyphs == 0)
return CAIRO_STATUS_SUCCESS;
- if (wrapper->has_extents) {
- _cairo_clip_init_copy (&target_clip, clip);
- status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = clip = &target_clip;
- }
+ if (wrapper->has_extents)
+ dev_clip = target_clip = _cairo_clip_copy_intersect_rectangle (clip, &wrapper->extents);
- if (clip && clip->all_clipped) {
+ if (_cairo_clip_is_all_clipped (dev_clip)) {
status = CAIRO_STATUS_SUCCESS;
goto FINISH;
}
@@ -578,13 +491,8 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
- if (clip != NULL) {
- status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
- if (unlikely (status))
- goto FINISH;
-
- dev_clip = &clip_copy;
- }
+ /* XXX */
+ dev_clip = _cairo_clip_copy_with_translation (clip, wrapper->extents.x, wrapper->extents.y);
dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (dev_glyphs == NULL) {
@@ -603,13 +511,6 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
_copy_transformed_pattern (&source_copy.base, source, &m);
source = &source_copy.base;
}
- else
- {
- if (clip != NULL) {
- dev_clip = &clip_copy;
- _cairo_clip_init_copy (&clip_copy, clip);
- }
- }
status = _cairo_surface_show_text_glyphs (wrapper->target, op, source,
utf8, utf8_len,
@@ -621,9 +522,8 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
FINISH:
if (dev_clip != clip)
- _cairo_clip_reset (dev_clip);
- if (wrapper->has_extents)
- _cairo_clip_reset (&target_clip);
+ _cairo_clip_destroy (dev_clip);
+ _cairo_clip_destroy (target_clip);
if (dev_glyphs != glyphs)
free (dev_glyphs);
return status;
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 98903dc..1f9028d 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -170,7 +170,7 @@ _cairo_surface_set_error (cairo_surface_t *surface,
cairo_status_t status)
{
if (status == CAIRO_STATUS_SUCCESS ||
- status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ status == (int)CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
/* Don't overwrite an existing error. This preserves the first
@@ -498,6 +498,8 @@ cairo_surface_create_similar (cairo_surface_t *other,
int width,
int height)
{
+ cairo_surface_t *surface;
+
if (unlikely (other->status))
return _cairo_surface_create_in_error (other->status);
if (unlikely (other->finished))
@@ -508,10 +510,13 @@ cairo_surface_create_similar (cairo_surface_t *other,
if (unlikely (! CAIRO_CONTENT_VALID (content)))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
- return _cairo_surface_create_similar_solid (other,
- content, width, height,
- CAIRO_COLOR_TRANSPARENT,
- TRUE);
+ surface = _cairo_surface_create_similar_solid (other,
+ content, width, height,
+ CAIRO_COLOR_TRANSPARENT,
+ TRUE);
+ assert (surface->is_clear);
+
+ return surface;
}
cairo_surface_t *
@@ -1699,7 +1704,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
int *clone_offset_y,
cairo_surface_t **clone_out)
{
- cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+ cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
cairo_image_surface_t *image;
void *image_extra;
@@ -1746,7 +1751,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
/* If we failed, try again with an image surface */
status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
- if (status == CAIRO_STATUS_SUCCESS) {
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
status =
surface->backend->clone_similar (surface, &image->base,
src_x, src_y,
@@ -1995,27 +2000,27 @@ _pattern_has_error (const cairo_pattern_t *pattern)
}
cairo_status_t
-_cairo_surface_paint (cairo_surface_t *surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_clip_t *clip)
+_cairo_surface_paint (cairo_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_clip_t *clip)
{
- cairo_status_t status;
+ cairo_int_status_t status;
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
+ if (op == CAIRO_OPERATOR_SOURCE && _cairo_pattern_is_clear (source))
+ op = CAIRO_OPERATOR_CLEAR;
+
if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
return CAIRO_STATUS_SUCCESS;
- if (op == CAIRO_OPERATOR_OVER &&
- _cairo_pattern_is_clear (source))
- {
+ if (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_clear (source))
return CAIRO_STATUS_SUCCESS;
- }
status = _pattern_has_error (source);
if (unlikely (status))
@@ -2043,14 +2048,14 @@ _cairo_surface_mask (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
- cairo_status_t status;
+ cairo_int_status_t status;
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
@@ -2109,14 +2114,14 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
const cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
- cairo_status_t status;
+ cairo_int_status_t status;
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (surface->is_clear &&
@@ -2178,20 +2183,20 @@ cairo_status_t
_cairo_surface_stroke (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
- cairo_status_t status;
+ cairo_int_status_t status;
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
@@ -2237,18 +2242,18 @@ cairo_status_t
_cairo_surface_fill (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
- cairo_status_t status;
+ cairo_int_status_t status;
if (unlikely (surface->status))
return surface->status;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
@@ -2355,11 +2360,8 @@ _cairo_surface_create_span_renderer (cairo_operator_t op,
return _cairo_span_renderer_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
if (dst->backend->create_span_renderer) {
- return dst->backend->create_span_renderer (op,
- pattern, dst,
- antialias,
- rects,
- clip_region);
+ return dst->backend->create_span_renderer (op, pattern, dst, antialias,
+ rects, clip_region);
}
ASSERT_NOT_REACHED;
return _cairo_span_renderer_create_in_error (CAIRO_INT_STATUS_UNSUPPORTED);
@@ -2570,9 +2572,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_scaled_font_t *dev_scaled_font = scaled_font;
if (unlikely (surface->status))
@@ -2581,7 +2583,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
if (num_glyphs == 0 && utf8_len == 0)
return CAIRO_STATUS_SUCCESS;
- if (clip && clip->all_clipped)
+ if (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
@@ -2641,7 +2643,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
- status = CAIRO_STATUS_SUCCESS;
+ status = CAIRO_INT_STATUS_SUCCESS;
}
} else {
/* A mere show_glyphs call. Try show_glyphs backend method first */
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 7adcfb7..e5ddb7e 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -85,7 +85,7 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
static void
_cairo_svg_surface_emit_path (cairo_output_stream_t *output,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_matrix_t *ctm_inverse);
static cairo_bool_t
@@ -562,10 +562,10 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream,
static cairo_svg_page_t *
_cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
{
- unsigned int i;
cairo_svg_page_t page;
cairo_output_stream_t *stream;
- cairo_status_t status;
+ cairo_int_status_t status;
+ unsigned int i;
stream = _cairo_memory_stream_create ();
if (_cairo_output_stream_get_status (stream)) {
@@ -715,7 +715,7 @@ _cairo_svg_path_close_path (void *closure)
static void
_cairo_svg_surface_emit_path (cairo_output_stream_t *output,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_matrix_t *ctm_inverse)
{
cairo_status_t status;
@@ -814,14 +814,14 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
unsigned int font_id,
unsigned int subset_glyph_index)
{
- cairo_status_t status;
+ cairo_int_status_t status;
_cairo_output_stream_printf (document->xml_node_glyphs,
"<symbol overflow=\"visible\" id=\"glyph%d-%d\">\n",
@@ -840,16 +840,16 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
_cairo_output_stream_printf (document->xml_node_glyphs, "</symbol>\n");
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_svg_document_t *document = closure;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
unsigned int i;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
_cairo_scaled_font_freeze_cache (font_subset->scaled_font);
for (i = 0; i < font_subset->num_glyphs; i++) {
@@ -1163,7 +1163,7 @@ static cairo_int_status_t
_cairo_surface_base64_encode (cairo_surface_t *surface,
cairo_output_stream_t *output)
{
- cairo_status_t status;
+ cairo_int_status_t status;
base64_write_closure_t info;
status = _cairo_surface_base64_encode_jpeg (surface, output);
@@ -2137,7 +2137,7 @@ _cairo_svg_surface_fill_stroke (void *abstract_surface,
cairo_fill_rule_t fill_rule,
double fill_tolerance,
cairo_antialias_t fill_antialias,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_operator_t stroke_op,
const cairo_pattern_t *stroke_source,
const cairo_stroke_style_t *stroke_style,
@@ -2145,7 +2145,7 @@ _cairo_svg_surface_fill_stroke (void *abstract_surface,
const cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_svg_surface_t *surface = abstract_surface;
cairo_status_t status;
@@ -2179,11 +2179,11 @@ static cairo_int_status_t
_cairo_svg_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_svg_surface_t *surface = abstract_surface;
cairo_status_t status;
@@ -2274,7 +2274,7 @@ static cairo_int_status_t
_cairo_svg_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_svg_surface_t *surface = abstract_surface;
@@ -2340,7 +2340,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_status_t status;
cairo_svg_surface_t *surface = abstract_surface;
@@ -2430,13 +2430,13 @@ static cairo_int_status_t
_cairo_svg_surface_stroke (void *abstract_dst,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_svg_surface_t *surface = abstract_dst;
cairo_status_t status;
@@ -2473,13 +2473,13 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_document_t *document = surface->document;
cairo_path_fixed_t path;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_scaled_font_subsets_glyph_t subset_glyph;
int i;
@@ -2834,7 +2834,7 @@ _cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface)
CAIRO_OPERATOR_SOURCE);
}
- return status == CAIRO_STATUS_SUCCESS;
+ return status == CAIRO_INT_STATUS_SUCCESS;
}
static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = {
diff --git a/src/cairo-tee-surface.c b/src/cairo-tee-surface.c
index df0ae99..40f8aa3 100644
--- a/src/cairo-tee-surface.c
+++ b/src/cairo-tee-surface.c
@@ -199,12 +199,12 @@ static cairo_int_status_t
_cairo_tee_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_tee_surface_t *surface = abstract_surface;
cairo_surface_wrapper_t *slaves;
int n, num_slaves;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_surface_wrapper_paint (&surface->master, op, source, clip);
if (unlikely (status))
@@ -226,12 +226,12 @@ _cairo_tee_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_tee_surface_t *surface = abstract_surface;
cairo_surface_wrapper_t *slaves;
+ cairo_int_status_t status;
int n, num_slaves;
- cairo_status_t status;
status = _cairo_surface_wrapper_mask (&surface->master,
op, source, mask, clip);
@@ -254,18 +254,18 @@ static cairo_int_status_t
_cairo_tee_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_tee_surface_t *surface = abstract_surface;
cairo_surface_wrapper_t *slaves;
+ cairo_int_status_t status;
int n, num_slaves;
- cairo_status_t status;
status = _cairo_surface_wrapper_stroke (&surface->master,
op, source,
@@ -296,16 +296,16 @@ static cairo_int_status_t
_cairo_tee_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_tee_surface_t *surface = abstract_surface;
cairo_surface_wrapper_t *slaves;
+ cairo_int_status_t status;
int n, num_slaves;
- cairo_status_t status;
status = _cairo_surface_wrapper_fill (&surface->master,
op, source,
@@ -327,7 +327,7 @@ _cairo_tee_surface_fill (void *abstract_surface,
return status;
}
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
static cairo_bool_t
@@ -348,12 +348,12 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_tee_surface_t *surface = abstract_surface;
cairo_surface_wrapper_t *slaves;
+ cairo_int_status_t status;
int n, num_slaves;
- cairo_status_t status;
cairo_glyph_t *glyphs_copy;
/* XXX: This copying is ugly. */
@@ -504,8 +504,8 @@ cairo_tee_surface_remove (cairo_surface_t *abstract_surface,
{
cairo_tee_surface_t *surface;
cairo_surface_wrapper_t *slaves;
+ cairo_int_status_t status;
int n, num_slaves;
- cairo_status_t status;
if (unlikely (abstract_surface->status))
return;
@@ -549,7 +549,7 @@ cairo_tee_surface_remove (cairo_surface_t *abstract_surface,
cairo_surface_t *
cairo_tee_surface_index (cairo_surface_t *abstract_surface,
- int index)
+ unsigned int index)
{
cairo_tee_surface_t *surface;
diff --git a/src/cairo-tee.h b/src/cairo-tee.h
index 9c048c6..9125a3a 100644
--- a/src/cairo-tee.h
+++ b/src/cairo-tee.h
@@ -55,7 +55,7 @@ cairo_tee_surface_remove (cairo_surface_t *surface,
cairo_public cairo_surface_t *
cairo_tee_surface_index (cairo_surface_t *surface,
- int index);
+ unsigned int index);
CAIRO_END_DECLS
diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c
index 888a395..4c0d8dc 100644
--- a/src/cairo-tor-scan-converter.c
+++ b/src/cairo-tor-scan-converter.c
@@ -1960,8 +1960,8 @@ blit_with_span_renderer (struct cell_list *cells,
int xmin, int xmax)
{
struct cell *cell = cells->head;
- int prev_x = xmin;
- int cover = 0;
+ int prev_x = xmin, last_x = -1;
+ int cover = 0, last_cover = -1;
cairo_half_open_span_t *spans;
unsigned num_spans;
@@ -2005,26 +2005,34 @@ blit_with_span_renderer (struct cell_list *cells,
if (x > prev_x) {
spans[num_spans].x = prev_x;
spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
+ last_cover = cover;
+ last_x = prev_x;
++num_spans;
}
cover += cell->covered_height*GRID_X*2;
area = cover - cell->uncovered_area;
- spans[num_spans].x = x;
- spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
- ++num_spans;
+ if (area != last_cover) {
+ spans[num_spans].x = x;
+ spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
+ last_cover = area;
+ last_x = x;
+ ++num_spans;
+ }
prev_x = x+1;
}
- if (prev_x <= xmax) {
+ if (prev_x <= xmax && cover != last_cover) {
spans[num_spans].x = prev_x;
spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
+ last_cover = cover;
+ last_x = prev_x;
++num_spans;
}
- if (prev_x < xmax && cover) {
+ if (last_x < xmax && last_cover) {
spans[num_spans].x = xmax;
spans[num_spans].coverage = 0;
++num_spans;
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 2fe6684..42e2eb5 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -76,6 +76,15 @@ _cairo_traps_limit (cairo_traps_t *traps,
}
void
+_cairo_traps_init_with_clip (cairo_traps_t *traps,
+ const cairo_clip_t *clip)
+{
+ _cairo_traps_init (traps);
+ if (clip)
+ _cairo_traps_limit (traps, clip->boxes, clip->num_boxes);
+}
+
+void
_cairo_traps_clear (cairo_traps_t *traps)
{
traps->status = CAIRO_STATUS_SUCCESS;
@@ -485,6 +494,44 @@ _cairo_traps_extents (const cairo_traps_t *traps,
}
}
+static cairo_bool_t
+_mono_edge_is_vertical (const cairo_line_t *line)
+{
+ return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
+}
+
+static cairo_bool_t
+_traps_are_pixel_aligned (cairo_traps_t *traps,
+ cairo_antialias_t antialias)
+{
+ int i;
+
+ if (antialias == CAIRO_ANTIALIAS_NONE) {
+ for (i = 0; i < traps->num_traps; i++) {
+ if (! _mono_edge_is_vertical (&traps->traps[i].left) ||
+ ! _mono_edge_is_vertical (&traps->traps[i].right))
+ {
+ traps->maybe_region = FALSE;
+ return FALSE;
+ }
+ }
+ } else {
+ for (i = 0; i < traps->num_traps; i++) {
+ if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
+ traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
+ ! _cairo_fixed_is_integer (traps->traps[i].top) ||
+ ! _cairo_fixed_is_integer (traps->traps[i].bottom) ||
+ ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) ||
+ ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
+ {
+ traps->maybe_region = FALSE;
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
/**
* _cairo_traps_extract_region:
@@ -502,6 +549,7 @@ _cairo_traps_extents (const cairo_traps_t *traps,
**/
cairo_int_status_t
_cairo_traps_extract_region (cairo_traps_t *traps,
+ cairo_antialias_t antialias,
cairo_region_t **region)
{
cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
@@ -510,20 +558,12 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
int i, rect_count;
/* we only treat this a hint... */
- if (! traps->maybe_region)
+ if (antialias != CAIRO_ANTIALIAS_NONE && ! traps->maybe_region)
return CAIRO_INT_STATUS_UNSUPPORTED;
- for (i = 0; i < traps->num_traps; i++) {
- if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
- traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
- ! _cairo_fixed_is_integer (traps->traps[i].top) ||
- ! _cairo_fixed_is_integer (traps->traps[i].bottom) ||
- ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) ||
- ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
- {
- traps->maybe_region = FALSE;
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ if (! _traps_are_pixel_aligned (traps, antialias)) {
+ traps->maybe_region = FALSE;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
@@ -535,19 +575,30 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
rect_count = 0;
for (i = 0; i < traps->num_traps; i++) {
- int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
- int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
- int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
- int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
-
- rects[rect_count].x = x1;
- rects[rect_count].y = y1;
- rects[rect_count].width = x2 - x1;
- rects[rect_count].height = y2 - y1;
+ int x1, y1, x2, y2;
+
+ if (antialias == CAIRO_ANTIALIAS_NONE) {
+ x1 = _cairo_fixed_integer_round_down (traps->traps[i].left.p1.x);
+ y1 = _cairo_fixed_integer_round_down (traps->traps[i].top);
+ x2 = _cairo_fixed_integer_round_down (traps->traps[i].right.p1.x);
+ y2 = _cairo_fixed_integer_round_down (traps->traps[i].bottom);
+ } else {
+ x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
+ y1 = _cairo_fixed_integer_part (traps->traps[i].top);
+ x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
+ y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
+ }
- rect_count++;
+ if (x2 > x1 && y2 > y1) {
+ rects[rect_count].x = x1;
+ rects[rect_count].y = y1;
+ rects[rect_count].width = x2 - x1;
+ rects[rect_count].height = y2 - y1;
+ rect_count++;
+ }
}
+
*region = cairo_region_create_rectangles (rects, rect_count);
status = (*region)->status;
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 176f163..844e521 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -122,7 +122,8 @@ static cairo_status_t
_cairo_truetype_font_set_error (cairo_truetype_font_t *font,
cairo_status_t status)
{
- if (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED)
+ if (status == CAIRO_STATUS_SUCCESS ||
+ status == (int)CAIRO_INT_STATUS_UNSUPPORTED)
return status;
_cairo_status_set_error (&font->status, status);
@@ -1056,19 +1057,19 @@ cairo_truetype_font_create_truetype_table_list (cairo_truetype_font_t *font)
size = 0;
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_cvt, 0, NULL,
- &size) == CAIRO_STATUS_SUCCESS)
+ &size) == CAIRO_INT_STATUS_SUCCESS)
has_cvt = TRUE;
size = 0;
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_fpgm, 0, NULL,
- &size) == CAIRO_STATUS_SUCCESS)
+ &size) == CAIRO_INT_STATUS_SUCCESS)
has_fpgm = TRUE;
size = 0;
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_prep, 0, NULL,
- &size) == CAIRO_STATUS_SUCCESS)
+ &size) == CAIRO_INT_STATUS_SUCCESS)
has_prep = TRUE;
font->num_tables = 0;
@@ -1344,7 +1345,7 @@ _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
unsigned long index,
uint32_t *ucs4)
{
- cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+ cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
const cairo_scaled_font_backend_t *backend;
tt_cmap_t *cmap;
char buf[4];
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index 39bc53f..5284cfe 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -626,7 +626,7 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
fail:
status2 = _cairo_output_stream_destroy (encrypted_output);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
return status;
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index e9e8311..bad0d3b 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -188,7 +188,7 @@ static cairo_int_status_t
_cairo_type3_glyph_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
const cairo_surface_pattern_t *pattern;
@@ -224,7 +224,7 @@ _cairo_type3_glyph_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
return _cairo_type3_glyph_surface_paint (abstract_surface,
op, mask,
@@ -235,13 +235,13 @@ static cairo_int_status_t
_cairo_type3_glyph_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_int_status_t status;
@@ -261,11 +261,11 @@ static cairo_int_status_t
_cairo_type3_glyph_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_int_status_t status;
@@ -286,7 +286,7 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
@@ -418,7 +418,7 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_scaled_glyph_t *scaled_glyph;
- cairo_status_t status, status2;
+ cairo_int_status_t status, status2;
cairo_output_stream_t *null_stream;
if (unlikely (surface->base.status))
@@ -436,11 +436,11 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
&scaled_glyph);
- if (_cairo_status_is_error (status))
+ if (_cairo_int_status_is_error (status))
goto cleanup;
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- status = CAIRO_STATUS_SUCCESS;
+ status = CAIRO_INT_STATUS_SUCCESS;
goto cleanup;
}
@@ -451,13 +451,13 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
- status = CAIRO_STATUS_SUCCESS;
+ status = CAIRO_INT_STATUS_SUCCESS;
cleanup:
_cairo_scaled_font_thaw_cache (surface->scaled_font);
status2 = _cairo_output_stream_destroy (null_stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
return status;
@@ -472,7 +472,7 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_scaled_glyph_t *scaled_glyph;
- cairo_status_t status, status2;
+ cairo_int_status_t status, status2;
double x_advance, y_advance;
cairo_matrix_t font_matrix_inverse;
@@ -492,10 +492,10 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
}
- if (_cairo_status_is_error (status)) {
+ if (_cairo_int_status_is_error (status)) {
_cairo_scaled_font_thaw_cache (surface->scaled_font);
return status;
}
@@ -508,7 +508,7 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
/* The invertability of font_matrix is tested in
* pdf_operators_show_glyphs before any glyphs are mapped to the
* subset. */
- assert (status2 == CAIRO_STATUS_SUCCESS);
+ assert (status2 == CAIRO_INT_STATUS_SUCCESS);
cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
*width = x_advance;
@@ -525,7 +525,7 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
_cairo_fixed_to_double (bbox->p2.x),
- _cairo_fixed_to_double (bbox->p1.y));
- if (status == CAIRO_STATUS_SUCCESS) {
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
cairo_output_stream_t *mem_stream;
mem_stream = _cairo_memory_stream_create ();
@@ -540,17 +540,17 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
&surface->base);
status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
_cairo_output_stream_printf (surface->stream, "Q\n");
_cairo_type3_glyph_surface_set_stream (surface, stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
_cairo_memory_stream_copy (mem_stream, stream);
status2 = _cairo_output_stream_destroy (mem_stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
}
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 8881055..bed6412 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -228,16 +228,7 @@ typedef enum _cairo_paginated_mode {
* from #cairo_status_t. Oh well, without that, I'll use this bogus 100
* offset. We want to keep it fit in int8_t as the compiler may choose
* that for #cairo_status_t */
-typedef enum _cairo_int_status {
- CAIRO_INT_STATUS_UNSUPPORTED = 100,
- CAIRO_INT_STATUS_DEGENERATE,
- CAIRO_INT_STATUS_NOTHING_TO_DO,
- CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY,
- CAIRO_INT_STATUS_IMAGE_FALLBACK,
- CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN,
-
- CAIRO_INT_STATUS_LAST_STATUS
-} cairo_int_status_t;
+typedef enum _cairo_int_status cairo_int_status_t;
typedef enum _cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT = 0x1000,
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index a524d58..522711d 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -158,7 +158,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
_cairo_scaled_glyph_index(scaled_glyph),
cr, &extents);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = cairo_status (cr);
cairo_destroy (cr);
@@ -328,11 +328,12 @@ _cairo_user_text_to_glyphs (void *abstract_font,
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags);
- if (status != CAIRO_STATUS_SUCCESS &&
- status != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
+ if (status != CAIRO_INT_STATUS_SUCCESS &&
+ status != CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED)
return status;
- if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED || *num_glyphs < 0) {
+ if (status == CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED ||
+ *num_glyphs < 0) {
if (orig_glyphs != *glyphs) {
cairo_glyph_free (*glyphs);
*glyphs = orig_glyphs;
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 58d404a..a5d2787 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1167,7 +1167,7 @@ static cairo_int_status_t
_cairo_win32_printing_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_solid_pattern_t clear;
@@ -1244,13 +1244,13 @@ static cairo_int_status_t
_cairo_win32_printing_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *stroke_ctm,
const cairo_matrix_t *stroke_ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_int_status_t status;
@@ -1373,11 +1373,11 @@ static cairo_int_status_t
_cairo_win32_printing_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_int_status_t status;
@@ -1528,7 +1528,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_win32_surface_t *surface = abstract_surface;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 0f0bffc..f309b4b 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1522,7 +1522,7 @@ _cairo_win32_surface_show_glyphs_internal (void *surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs,
cairo_bool_t glyph_indexing)
{
@@ -1674,11 +1674,11 @@ cairo_int_status_t
_cairo_win32_surface_show_glyphs (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
+ cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
- int *remaining_glyphs)
+ const cairo_clip_t *clip,
+ int *remaining_glyphs)
{
return _cairo_win32_surface_show_glyphs_internal (surface,
op,
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index 92898b8..d52306e 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -360,36 +360,36 @@ cairo_private cairo_int_status_t
_cairo_xcb_surface_cairo_paint (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_cairo_mask (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_cairo_stroke (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_cairo_fill (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_cairo_glyphs (cairo_xcb_surface_t *surface,
@@ -398,42 +398,42 @@ _cairo_xcb_surface_cairo_glyphs (cairo_xcb_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_paint (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_mask (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
-_cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+_cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
- cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ cairo_antialias_t antialias,
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
- cairo_operator_t op,
+ cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_int_status_t
_cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
@@ -442,7 +442,7 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private void
_cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font);
diff --git a/src/cairo-xcb-surface-cairo.c b/src/cairo-xcb-surface-cairo.c
index 79c4d6c..338a616 100644
--- a/src/cairo-xcb-surface-cairo.c
+++ b/src/cairo-xcb-surface-cairo.c
@@ -38,7 +38,7 @@ cairo_int_status_t
_cairo_xcb_surface_cairo_paint (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -48,7 +48,7 @@ _cairo_xcb_surface_cairo_mask (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -57,13 +57,13 @@ cairo_int_status_t
_cairo_xcb_surface_cairo_stroke (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -72,11 +72,11 @@ cairo_int_status_t
_cairo_xcb_surface_cairo_fill (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -88,7 +88,7 @@ _cairo_xcb_surface_cairo_glyphs (cairo_xcb_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index fc349a3..000f00f 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -425,7 +425,7 @@ _cairo_xcb_picture_set_matrix (cairo_xcb_picture_t *picture,
{
xcb_render_transform_t transform;
pixman_transform_t *pixman_transform;
- cairo_status_t ignored;
+ cairo_int_status_t ignored;
/* Casting between pixman_transform_t and xcb_render_transform_t is safe
* because they happen to be the exact same type.
@@ -1572,13 +1572,7 @@ _create_composite_mask (cairo_clip_t *clip,
cairo_bool_t clip_surface = FALSE;
cairo_status_t status;
- if (clip != NULL) {
- cairo_region_t *clip_region;
-
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (! _cairo_status_is_error (status));
- clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ clip_surface = ! _cairo_clip_is_region (clip);
surface = (cairo_xcb_surface_t *)
_cairo_xcb_surface_create_similar (dst, CAIRO_CONTENT_ALPHA,
@@ -1794,6 +1788,7 @@ _clip_and_composite_combine (cairo_clip_t *clip,
extents->x, extents->y,
extents->width, extents->height);
}
+ cairo_surface_destroy (clip_surface);
CLEANUP_SURFACE:
cairo_surface_destroy (&tmp->base);
@@ -2056,6 +2051,8 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst,
width, height);
}
+ cairo_surface_destroy (&mask->base);
+
return CAIRO_STATUS_SUCCESS;
}
@@ -2086,7 +2083,7 @@ _cairo_xcb_surface_fixup_unbounded_boxes (cairo_xcb_surface_t *dst,
_cairo_boxes_init (&tmp);
- status = _cairo_boxes_add (&tmp, &box);
+ status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
assert (status == CAIRO_STATUS_SUCCESS);
tmp.chunks.next = &boxes->chunks;
@@ -2103,12 +2100,14 @@ _cairo_xcb_surface_fixup_unbounded_boxes (cairo_xcb_surface_t *dst,
pbox = pixman_region32_rectangles (&clip_region->rgn, &i);
_cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i);
- status = _cairo_boxes_add (&clear, &box);
+ status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
assert (status == CAIRO_STATUS_SUCCESS);
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
- status = _cairo_boxes_add (&clear, &chunk->base[i]);
+ status = _cairo_boxes_add (&clear,
+ CAIRO_ANTIALIAS_DEFAULT,
+ &chunk->base[i]);
if (unlikely (status)) {
_cairo_boxes_fini (&clear);
return status;
@@ -2173,6 +2172,22 @@ _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst)
return CAIRO_STATUS_SUCCESS;
}
+static cairo_bool_t
+need_bounded_clip (cairo_composite_rectangles_t *extents)
+{
+ return ! _cairo_clip_is_region (extents->clip);
+}
+
+static cairo_bool_t
+need_unbounded_clip (cairo_composite_rectangles_t *extents)
+{
+ if (! extents->is_bounded)
+ return need_bounded_clip (extents);
+
+ return extents->clip->path != NULL;
+}
+
+
static cairo_status_t
_clip_and_composite (cairo_xcb_surface_t *dst,
cairo_operator_t op,
@@ -2180,43 +2195,10 @@ _clip_and_composite (cairo_xcb_surface_t *dst,
xcb_draw_func_t draw_func,
void *draw_closure,
cairo_composite_rectangles_t*extents,
- cairo_clip_t *clip)
+ cairo_bool_t need_clip_surface)
{
cairo_status_t status;
- cairo_region_t *clip_region = NULL;
- cairo_region_t extents_region;
- cairo_bool_t need_clip_surface = FALSE;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
-
- assert (! _cairo_status_is_error (status));
- need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (clip_region != NULL) {
- cairo_rectangle_int_t rect;
- cairo_bool_t is_empty;
-
- cairo_region_get_extents (clip_region, &rect);
- is_empty = ! _cairo_rectangle_intersect (&extents->unbounded, &rect);
- if (unlikely (is_empty))
- return CAIRO_STATUS_SUCCESS;
-
- is_empty = ! _cairo_rectangle_intersect (&extents->bounded, &rect);
- if (unlikely (is_empty && extents->is_bounded))
- return CAIRO_STATUS_SUCCESS;
- }
- } else if (!extents->is_bounded) {
- /* The X server will estimate the affected region of the unbounded
- * operation and will apply the operation to that rectangle.
- * However, there are cases where this estimate is too high (e.g.
- * the test suite's clip-fill-{eo,nz}-unbounded tests).
- */
- _cairo_region_init_rectangle (&extents_region, &extents->unbounded);
- clip_region = &extents_region;
- }
+ cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
status = _cairo_xcb_connection_acquire (dst->connection);
if (unlikely (status))
@@ -2241,7 +2223,7 @@ _clip_and_composite (cairo_xcb_surface_t *dst,
}
if (op == CAIRO_OPERATOR_SOURCE) {
- status = _clip_and_composite_source (clip, src,
+ status = _clip_and_composite_source (extents->clip, src,
draw_func, draw_closure,
dst, &extents->bounded);
} else {
@@ -2252,11 +2234,11 @@ _clip_and_composite (cairo_xcb_surface_t *dst,
if (need_clip_surface) {
if (extents->is_bounded) {
- status = _clip_and_composite_with_mask (clip, op, src,
+ status = _clip_and_composite_with_mask (extents->clip, op, src,
draw_func, draw_closure,
dst, &extents->bounded);
} else {
- status = _clip_and_composite_combine (clip, op, src,
+ status = _clip_and_composite_combine (extents->clip, op, src,
draw_func, draw_closure,
dst, &extents->bounded);
}
@@ -2271,15 +2253,13 @@ _clip_and_composite (cairo_xcb_surface_t *dst,
if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
if (need_clip_surface)
- status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst, extents, clip);
+ status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst, extents, extents->clip);
else
status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
}
if (clip_region != NULL)
_cairo_xcb_surface_clear_clip_region (dst);
- if (clip_region == &extents_region)
- _cairo_region_fini (&extents_region);
_cairo_xcb_connection_release (dst->connection);
@@ -2291,26 +2271,13 @@ _core_boxes (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *src,
cairo_boxes_t *boxes,
- cairo_antialias_t antialias,
- cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents)
{
- if (antialias != CAIRO_ANTIALIAS_NONE) {
- if (! boxes->is_pixel_aligned)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- if (clip != NULL) {
- cairo_region_t *clip_region;
- cairo_status_t status;
-
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (status == CAIRO_STATUS_SUCCESS ||
- status == CAIRO_INT_STATUS_UNSUPPORTED);
+ if (! boxes->is_pixel_aligned)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ if (! _cairo_clip_is_region (extents->clip))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
if (op == CAIRO_OPERATOR_CLEAR)
return _cairo_xcb_surface_core_fill_boxes (dst, CAIRO_COLOR_TRANSPARENT, boxes);
@@ -2336,36 +2303,25 @@ _composite_boxes (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *src,
cairo_boxes_t *boxes,
- cairo_antialias_t antialias,
- cairo_clip_t *clip,
const cairo_composite_rectangles_t *extents)
{
- cairo_bool_t need_clip_mask = FALSE;
- cairo_region_t *clip_region = NULL;
+ cairo_bool_t need_clip_mask = extents->clip->path != NULL;
+ cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
cairo_status_t status;
/* If the boxes are not pixel-aligned, we will need to compute a real mask */
- if (antialias != CAIRO_ANTIALIAS_NONE) {
- if (! boxes->is_pixel_aligned)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (status == CAIRO_STATUS_SUCCESS ||
- status == CAIRO_INT_STATUS_UNSUPPORTED);
-
- need_clip_mask = status == CAIRO_INT_STATUS_UNSUPPORTED;
- if (need_clip_mask &&
- (! extents->is_bounded || op == CAIRO_OPERATOR_SOURCE))
- {
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ if (! boxes->is_pixel_aligned)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
- clip_region = NULL;
+ if (need_clip_mask &&
+ (! extents->is_bounded || op == CAIRO_OPERATOR_SOURCE))
+ {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
}
+ if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
+ clip_region = NULL;
+
status = _cairo_xcb_connection_acquire (dst->connection);
if (unlikely (status))
return status;
@@ -2391,7 +2347,9 @@ _composite_boxes (cairo_xcb_surface_t *dst,
cairo_surface_t *clip_surface;
int clip_x, clip_y;
- clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
+ clip_surface = _cairo_clip_get_surface (extents->clip,
+ &dst->base,
+ &clip_x, &clip_y);
if (unlikely (clip_surface->status))
return clip_surface->status;
@@ -2400,6 +2358,7 @@ _composite_boxes (cairo_xcb_surface_t *dst,
cairo_matrix_init_translate (&mask.base.matrix,
-clip_x,
-clip_y);
+ cairo_surface_destroy (clip_surface);
if (op == CAIRO_OPERATOR_CLEAR) {
src = NULL;
@@ -2426,17 +2385,96 @@ _composite_boxes (cairo_xcb_surface_t *dst,
return status;
}
+static cairo_bool_t
+cairo_boxes_for_each_box (cairo_boxes_t *boxes,
+ cairo_bool_t (*func) (cairo_box_t *box,
+ void *data),
+ void *data)
+{
+ struct _cairo_boxes_chunk *chunk;
+ int i;
+
+ for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
+ for (i = 0; i < chunk->count; i++)
+ if (! func (&chunk->base[i], data))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+struct image_contains_box {
+ int width, height;
+ int tx, ty;
+};
+
+static cairo_bool_t image_contains_box (cairo_box_t *box, void *closure)
+{
+ struct image_contains_box *data = closure;
+
+ return
+ box->p1.x + data->tx >= 0 &&
+ box->p1.y + data->ty >= 0 &&
+ box->p2.x + data->tx <= data->width &&
+ box->p2.y + data->ty <= data->height;
+}
+
+struct image_upload_box {
+ cairo_xcb_surface_t *surface;
+ cairo_image_surface_t *image;
+ xcb_gcontext_t gc;
+ int tx, ty;
+};
+
+static cairo_bool_t image_upload_box (cairo_box_t *box, void *closure)
+{
+ const struct image_upload_box *iub = closure;
+ int width = box->p2.x - box->p1.x;
+ int height = box->p2.y - box->p1.y;
+ int bpp = PIXMAN_FORMAT_BPP (iub->image->pixman_format);
+ int len = CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp);
+ if (len == iub->image->stride) {
+ _cairo_xcb_connection_put_image (iub->surface->connection,
+ iub->surface->drawable,
+ iub->gc,
+ width, height,
+ box->p1.x, box->p2.y,
+ iub->image->depth,
+ iub->image->stride,
+ iub->image->data +
+ (box->p1.y + iub->ty) * iub->image->stride +
+ (box->p1.x + iub->tx) * bpp/8);
+ } else {
+ _cairo_xcb_connection_put_subimage (iub->surface->connection,
+ iub->surface->drawable,
+ iub->gc,
+ box->p1.x + iub->tx,
+ box->p1.y + iub->ty,
+ width, height,
+ bpp / 8,
+ iub->image->stride,
+ box->p1.x, box->p2.y,
+ iub->image->depth,
+ iub->image->data);
+ }
+
+ return TRUE;
+}
+
static cairo_status_t
_upload_image_inplace (cairo_xcb_surface_t *surface,
const cairo_pattern_t *source,
- const cairo_rectangle_int_t *extents)
+ cairo_boxes_t *boxes)
{
const cairo_surface_pattern_t *pattern;
+ struct image_contains_box icb;
+ struct image_upload_box iub;
cairo_image_surface_t *image;
- xcb_gcontext_t gc;
cairo_status_t status;
int tx, ty;
- int len, bpp;
+
+ if (! boxes->is_pixel_aligned)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -2445,6 +2483,7 @@ _upload_image_inplace (cairo_xcb_surface_t *surface,
if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ /* Have we already upload this image to a pixmap? */
{
cairo_xcb_picture_t *snapshot;
@@ -2466,79 +2505,73 @@ _upload_image_inplace (cairo_xcb_surface_t *surface,
if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
return CAIRO_INT_STATUS_UNSUPPORTED;
- image = (cairo_image_surface_t *) pattern->surface;
- if (source->extend != CAIRO_EXTEND_NONE &&
- (extents->x + tx < 0 ||
- extents->y + ty < 0 ||
- extents->x + tx + extents->width > image->width ||
- extents->y + ty + extents->height > image->height))
- {
+ /* Check that the data is entirely within the image */
+ icb.width = image->width;
+ icb.height = image->height;
+ icb.tx = tx;
+ icb.ty = ty;
+ if (! cairo_boxes_for_each_box (boxes, image_contains_box, &icb))
return CAIRO_INT_STATUS_UNSUPPORTED;
- }
status = _cairo_xcb_connection_acquire (surface->connection);
if (unlikely (status))
return status;
- gc = _cairo_xcb_screen_get_gc (surface->screen, surface->drawable, image->depth);
-
- /* Do we need to trim the image? */
- bpp = PIXMAN_FORMAT_BPP (image->pixman_format);
- len = CAIRO_STRIDE_FOR_WIDTH_BPP (extents->width, bpp);
- if (len == image->stride) {
- _cairo_xcb_connection_put_image (surface->connection,
- surface->drawable, gc,
- extents->width, extents->height,
- extents->x, extents->y,
- image->depth,
- image->stride,
- image->data +
- (extents->y + ty) * image->stride +
- (extents->x + tx) * bpp/8);
- } else {
- _cairo_xcb_connection_put_subimage (surface->connection,
- surface->drawable, gc,
- extents->x + tx, extents->y + ty,
- extents->width, extents->height,
- bpp / 8,
- image->stride,
- extents->x, extents->y,
- image->depth,
- image->data);
- }
+ iub.surface = surface;
+ iub.image = image;
+ iub.gc = _cairo_xcb_screen_get_gc (surface->screen,
+ surface->drawable,
+ image->depth);
+ iub.tx = tx;
+ iub.ty = ty;
+ cairo_boxes_for_each_box (boxes, image_upload_box, &iub);
- _cairo_xcb_screen_put_gc (surface->screen, image->depth, gc);
+ _cairo_xcb_screen_put_gc (surface->screen, image->depth, iub.gc);
_cairo_xcb_connection_release (surface->connection);
return CAIRO_STATUS_SUCCESS;
}
+static void
+trim_extents_to_traps (cairo_composite_rectangles_t *extents,
+ cairo_traps_t *traps)
+{
+ cairo_box_t box;
+
+ /* X trims the affected area to the extents of the trapezoids, so
+ * we need to compensate when fixing up the unbounded area.
+ */
+ _cairo_traps_extents (traps, &box);
+ _cairo_box_round_to_rectangle (&box, &extents->mask);
+ _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
+}
+
static cairo_status_t
_clip_and_composite_boxes (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *src,
cairo_boxes_t *boxes,
- cairo_antialias_t antialias,
- cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
+ cairo_composite_rectangles_t *extents)
{
composite_traps_info_t info;
- cairo_status_t status;
+ cairo_int_status_t status;
if (boxes->num_boxes == 0 && extents->is_bounded)
return CAIRO_STATUS_SUCCESS;
- if (clip == NULL &&
- (op == CAIRO_OPERATOR_SOURCE || (op == CAIRO_OPERATOR_OVER && dst->base.is_clear)) &&
- boxes->num_boxes == 1 &&
- extents->bounded.width == dst->width &&
- extents->bounded.height == dst->height)
+ if (boxes->is_pixel_aligned && _cairo_clip_is_region (extents->clip) &&
+ (op == CAIRO_OPERATOR_SOURCE || (op == CAIRO_OPERATOR_OVER && dst->base.is_clear)))
{
- op = CAIRO_OPERATOR_SOURCE;
- dst->deferred_clear = FALSE;
+ if (boxes->num_boxes == 1 &&
+ extents->bounded.width == dst->width &&
+ extents->bounded.height == dst->height)
+ {
+ op = CAIRO_OPERATOR_SOURCE;
+ dst->deferred_clear = FALSE;
+ }
- status = _upload_image_inplace (dst, src, &extents->bounded);
+ status = _upload_image_inplace (dst, src, boxes);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
@@ -2553,14 +2586,16 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
op = CAIRO_OPERATOR_SOURCE;
}
- if (clip == NULL && op == CAIRO_OPERATOR_SOURCE && boxes->num_boxes == 1) {
- status = _upload_image_inplace (dst, src, &extents->bounded);
+ if (boxes->is_pixel_aligned &&
+ _cairo_clip_is_region (extents->clip) &&
+ op == CAIRO_OPERATOR_SOURCE) {
+ status = _upload_image_inplace (dst, src, boxes);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
if ((dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
- return _core_boxes (dst, op, src, boxes, antialias, clip, extents);
+ return _core_boxes (dst, op, src, boxes, extents);
if (dst->deferred_clear) {
status = _cairo_xcb_surface_clear (dst);
@@ -2569,7 +2604,7 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
}
/* Use a fast path if the boxes are pixel aligned */
- status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
+ status = _composite_boxes (dst, op, src, boxes, extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
@@ -2581,10 +2616,11 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
if (unlikely (status))
return status;
- info.antialias = antialias;
+ trim_extents_to_traps (extents, &info.traps);
+ info.antialias = CAIRO_ANTIALIAS_DEFAULT;
status = _clip_and_composite (dst, op, src,
_composite_traps, &info,
- extents, clip);
+ extents, need_unbounded_clip (extents));
_cairo_traps_fini (&info.traps);
return status;
@@ -2738,38 +2774,14 @@ _composite_mask (void *closure,
/* high level rasteriser -> compositor */
-static cairo_clip_path_t *
-_clip_get_single_path (cairo_clip_t *clip)
-{
- cairo_clip_path_t *iter = clip->path;
- cairo_clip_path_t *path = NULL;
-
- do {
- if ((iter->flags & CAIRO_CLIP_PATH_IS_BOX) == 0) {
- if (path != NULL)
- return FALSE;
-
- path = iter;
- }
- iter = iter->prev;
- } while (iter != NULL);
-
- return path;
-}
-
cairo_int_status_t
_cairo_xcb_surface_render_paint (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
cairo_boxes_t boxes;
- cairo_box_t *clip_boxes = boxes.boxes_embedded;
- cairo_clip_t local_clip;
- cairo_clip_path_t *clip_path;
- cairo_bool_t have_clip = FALSE;
- int num_boxes = ARRAY_LENGTH (boxes.boxes_embedded);
cairo_status_t status;
if (unlikely (! _operator_is_supported (surface->flags, op)))
@@ -2794,45 +2806,13 @@ _cairo_xcb_surface_render_paint (cairo_xcb_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
- if (clip != NULL &&
- extents.is_bounded &&
- (clip_path = _clip_get_single_path (clip)) != NULL)
- {
- status = _cairo_xcb_surface_render_fill (surface, op, source,
- &clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- clip_path->antialias,
- NULL);
- }
- else
- {
- _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
+ status = _cairo_clip_to_boxes(extents.clip, &boxes);
+ if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, CAIRO_ANTIALIAS_DEFAULT,
- &extents, clip);
- if (clip_boxes != boxes.boxes_embedded)
- free (clip_boxes);
+ &boxes, &extents);
}
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -2842,11 +2822,9 @@ _cairo_xcb_surface_render_mask (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
cairo_status_t status;
if (unlikely (! _operator_is_supported (surface->flags, op)))
@@ -2861,25 +2839,11 @@ _cairo_xcb_surface_render_mask (cairo_xcb_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL && extents.is_bounded) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- status = _cairo_clip_rectangle (clip, &extents.bounded);
- if (unlikely (status)) {
- _cairo_clip_fini (&local_clip);
- return status;
- }
- have_clip = TRUE;
- }
-
status = _clip_and_composite (surface, op, source,
_composite_mask, (void *) mask,
- &extents, clip);
+ &extents, need_bounded_clip (&extents));
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -2891,27 +2855,19 @@ _cairo_xcb_surface_render_composite_polygon (cairo_xcb_surface_t *dst,
cairo_polygon_t *polygon,
cairo_antialias_t antialias,
cairo_fill_rule_t fill_rule,
- cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
+ cairo_composite_rectangles_t *extents)
{
composite_traps_info_t traps;
- cairo_bool_t clip_surface = FALSE;
+ cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
+ cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
cairo_status_t status;
- cairo_bool_t is_not_empty;
if (polygon->num_edges == 0) {
status = CAIRO_STATUS_SUCCESS;
if (! extents->is_bounded) {
- cairo_region_t *clip_region = NULL;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
-
if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
clip_region = NULL;
- }
if (clip_surface == FALSE) {
if (clip_region != NULL)
@@ -2924,31 +2880,19 @@ _cairo_xcb_surface_render_composite_polygon (cairo_xcb_surface_t *dst,
} else {
status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst,
extents,
- clip);
+ extents->clip);
}
}
return status;
}
- _cairo_box_round_to_rectangle (&polygon->extents, &extents->mask);
- is_not_empty = _cairo_rectangle_intersect (&extents->bounded, &extents->mask);
- if (extents->is_bounded && ! is_not_empty)
- return CAIRO_STATUS_SUCCESS;
-
_cairo_traps_init (&traps.traps);
status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
if (unlikely (status))
goto CLEANUP_TRAPS;
- if (clip != NULL) {
- cairo_region_t *clip_region;
-
- status = _cairo_clip_get_region (clip, &clip_region);
- clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
if (traps.traps.has_intersections) {
if (traps.traps.is_rectangular)
status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
@@ -2973,18 +2917,18 @@ _cairo_xcb_surface_render_composite_polygon (cairo_xcb_surface_t *dst,
_boxes_for_traps (&boxes, &traps.traps, antialias);
status = _clip_and_composite_boxes (dst, op, source,
- &boxes, antialias,
- extents, clip);
+ &boxes, extents);
}
else
{
/* Otherwise render the trapezoids to a mask and composite in the usual
* fashion.
*/
+ trim_extents_to_traps (extents, &traps.traps);
traps.antialias = antialias;
status = _clip_and_composite (dst, op, source,
_composite_traps, &traps,
- extents, clip);
+ extents, need_unbounded_clip (extents));
}
CLEANUP_TRAPS:
@@ -2997,22 +2941,18 @@ static cairo_int_status_t
_cairo_xcb_surface_render_stroke_as_polygon (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip,
- const cairo_box_t *clip_boxes,
- int num_boxes,
cairo_composite_rectangles_t *extents)
{
cairo_polygon_t polygon;
cairo_status_t status;
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
-
+ _cairo_polygon_init_with_clip (&polygon, extents->clip);
status = _cairo_path_fixed_stroke_to_polygon (path,
stroke_style,
ctm, ctm_inverse,
@@ -3022,9 +2962,8 @@ _cairo_xcb_surface_render_stroke_as_polygon (cairo_xcb_surface_t *dst,
status = _cairo_xcb_surface_render_composite_polygon (dst, op, source,
&polygon, antialias,
CAIRO_FILL_RULE_WINDING,
- extents, clip);
+ extents);
}
-
_cairo_polygon_fini (&polygon);
return status;
@@ -3042,13 +2981,12 @@ static cairo_status_t
_cairo_xcb_surface_render_stroke_via_mask (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip,
cairo_composite_rectangles_t *extents)
{
cairo_surface_t *image;
@@ -3081,7 +3019,7 @@ _cairo_xcb_surface_render_stroke_via_mask (cairo_xcb_surface_t *dst,
cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
status = _clip_and_composite (dst, op, source,
_composite_mask, (void *) &mask.base,
- extents, clip);
+ extents, need_bounded_clip (extents));
_cairo_pattern_fini (&mask.base);
}
@@ -3095,20 +3033,16 @@ cairo_int_status_t
_cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- cairo_status_t status;
+ cairo_int_status_t status;
if (unlikely (! _operator_is_supported (surface->flags, op)))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -3128,39 +3062,21 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
cairo_boxes_t boxes;
- _cairo_boxes_init (&boxes);
- _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
-
+ _cairo_boxes_init_with_clip (&boxes, extents.clip);
status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
style,
ctm,
+ antialias,
&boxes);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, antialias,
- &extents, clip);
+ &boxes, &extents);
}
-
_cairo_boxes_fini (&boxes);
}
@@ -3170,25 +3086,19 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t *surface,
path, style,
ctm, ctm_inverse,
tolerance, antialias,
- clip, clip_boxes, num_boxes,
&extents);
} else if (surface->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
status = _cairo_xcb_surface_render_stroke_via_mask (surface, op, source,
path, style,
ctm, ctm_inverse,
tolerance, antialias,
- have_clip ? &local_clip : NULL,
&extents);
} else {
ASSERT_NOT_REACHED;
}
}
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -3197,28 +3107,24 @@ static cairo_status_t
_cairo_xcb_surface_render_fill_as_polygon (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t*source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip,
- cairo_box_t *clip_boxes,
- int num_boxes,
cairo_composite_rectangles_t *extents)
{
cairo_polygon_t polygon;
cairo_status_t status;
- _cairo_polygon_init (&polygon, clip_boxes, num_boxes);
-
+ _cairo_polygon_init_with_clip (&polygon, extents->clip);
status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
status = _cairo_xcb_surface_render_composite_polygon (dst, op, source,
- &polygon, antialias,
+ &polygon,
+ antialias,
fill_rule,
- extents, clip);
+ extents);
}
-
_cairo_polygon_fini (&polygon);
return status;
@@ -3228,11 +3134,10 @@ static cairo_status_t
_cairo_xcb_surface_render_fill_via_mask (cairo_xcb_surface_t *dst,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip,
cairo_composite_rectangles_t *extents)
{
cairo_surface_t *image;
@@ -3264,7 +3169,7 @@ _cairo_xcb_surface_render_fill_via_mask (cairo_xcb_surface_t *dst,
cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
status = _clip_and_composite (dst, op, source,
_composite_mask, (void *) &mask.base,
- extents, clip);
+ extents, need_bounded_clip (extents));
_cairo_pattern_fini (&mask.base);
}
@@ -3279,18 +3184,14 @@ cairo_int_status_t
_cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- cairo_status_t status;
+ cairo_int_status_t status;
if (unlikely (! _operator_is_supported (surface->flags, op)))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -3309,38 +3210,19 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_path_fixed_fill_is_rectilinear (path)) {
cairo_boxes_t boxes;
- _cairo_boxes_init (&boxes);
- _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
-
+ _cairo_boxes_init_with_clip (&boxes, extents.clip);
status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
fill_rule,
+ antialias,
&boxes);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
status = _clip_and_composite_boxes (surface, op, source,
- &boxes, antialias,
- &extents, clip);
+ &boxes, &extents);
}
-
_cairo_boxes_fini (&boxes);
}
@@ -3348,23 +3230,17 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t *surface,
if (surface->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) {
status = _cairo_xcb_surface_render_fill_as_polygon (surface, op, source, path,
fill_rule, tolerance, antialias,
- clip, clip_boxes, num_boxes,
&extents);
} else if (surface->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
status = _cairo_xcb_surface_render_fill_via_mask (surface, op, source, path,
fill_rule, tolerance, antialias,
- have_clip ? &local_clip : NULL,
&extents);
} else {
ASSERT_NOT_REACHED;
}
}
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
@@ -3376,7 +3252,6 @@ _cairo_xcb_surface_render_glyphs_via_mask (cairo_xcb_surface_t *dst,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip,
cairo_composite_rectangles_t *extents)
{
cairo_surface_t *image;
@@ -3414,7 +3289,7 @@ _cairo_xcb_surface_render_glyphs_via_mask (cairo_xcb_surface_t *dst,
cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
status = _clip_and_composite (dst, op, source,
_composite_mask, (void *) &mask.base,
- extents, clip);
+ extents, need_bounded_clip (extents));
_cairo_pattern_fini (&mask.base);
}
@@ -4290,12 +4165,10 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
cairo_scaled_font_t *scaled_font,
cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_composite_rectangles_t extents;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_bool_t overlap;
if (unlikely (! _operator_is_supported (surface->flags, op)))
@@ -4314,20 +4187,6 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_clip_contains_rectangle (clip, &extents.mask))
- clip = NULL;
-
- if (clip != NULL && extents.is_bounded) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- status = _cairo_clip_rectangle (clip, &extents.bounded);
- if (unlikely (status)) {
- _cairo_clip_fini (&local_clip);
- return status;
- }
-
- have_clip = TRUE;
- }
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS) {
_cairo_scaled_font_freeze_cache (scaled_font);
@@ -4335,17 +4194,20 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
if (_surface_owns_font (surface, scaled_font)) {
status = _can_composite_glyphs (surface, &extents.bounded,
scaled_font, glyphs, &num_glyphs);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
composite_glyphs_info_t info;
info.font = scaled_font;
info.glyphs = (cairo_xcb_glyph_t *) glyphs;
info.num_glyphs = num_glyphs;
- info.use_mask = overlap || clip != NULL || ! extents.is_bounded;
+ info.use_mask =
+ overlap ||
+ ! extents.is_bounded ||
+ ! _cairo_clip_is_region(extents.clip);
status = _clip_and_composite (surface, op, source,
_composite_glyphs, &info,
- &extents, clip);
+ &extents, need_bounded_clip (&extents));
}
}
@@ -4357,11 +4219,10 @@ _cairo_xcb_surface_render_glyphs (cairo_xcb_surface_t *surface,
status =
_cairo_xcb_surface_render_glyphs_via_mask (surface, op, source,
scaled_font, glyphs, num_glyphs,
- clip, &extents);
+ &extents);
}
- if (have_clip)
- _cairo_clip_fini (&local_clip);
+ _cairo_composite_rectangles_fini (&extents);
return status;
}
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 157c8fb..6738cdd 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -379,7 +379,7 @@ _get_image (cairo_xcb_surface_t *surface,
cairo_image_surface_t *image;
cairo_xcb_connection_t *connection;
xcb_get_image_reply_t *reply;
- cairo_status_t status;
+ cairo_int_status_t status;
if (surface->base.is_clear || surface->deferred_clear) {
image = (cairo_image_surface_t *)
@@ -594,7 +594,7 @@ static cairo_status_t
_put_image (cairo_xcb_surface_t *surface,
cairo_image_surface_t *image)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
/* XXX track damaged region? */
@@ -688,10 +688,10 @@ static cairo_int_status_t
_cairo_xcb_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_int_status_t status;
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_paint (surface, op, source, clip);
@@ -713,10 +713,10 @@ _cairo_xcb_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_int_status_t status;
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_mask (surface,
@@ -741,16 +741,16 @@ static cairo_int_status_t
_cairo_xcb_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_int_status_t status;
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_stroke (surface, op, source,
@@ -786,14 +786,14 @@ static cairo_int_status_t
_cairo_xcb_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_xcb_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_int_status_t status;
if (surface->fallback == NULL) {
status = _cairo_xcb_surface_cairo_fill (surface, op, source,
@@ -827,11 +827,11 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *num_remaining)
{
cairo_xcb_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_int_status_t status;
*num_remaining = 0;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 25cfc68..46ca63f 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -175,7 +175,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs);
/*
@@ -369,6 +369,9 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
return NULL;
+ if (width == 0 || height == 0)
+ return NULL;
+
if (! CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (src))
return NULL;
@@ -1695,7 +1698,7 @@ _cairo_xlib_surface_can_repaint_solid_pattern_surface (void *abstract_surface,
return CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_xlib_surface_set_matrix (cairo_xlib_display_t *display,
cairo_xlib_surface_t *surface,
const cairo_matrix_t *matrix,
@@ -1707,7 +1710,7 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_display_t *display,
{
XTransform xtransform;
pixman_transform_t *pixman_transform;
- cairo_status_t status;
+ cairo_int_status_t status;
/* Casting between pixman_transform_t and XTransform is safe because
* they happen to be the exact same type.
@@ -1718,8 +1721,8 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_display_t *display,
pixman_transform,
x_offset, y_offset);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- status = CAIRO_STATUS_SUCCESS;
- if (unlikely (status != CAIRO_STATUS_SUCCESS))
+ status = CAIRO_INT_STATUS_SUCCESS;
+ if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
return status;
if (memcmp (&xtransform, &surface->xtransform, sizeof (XTransform)) == 0)
@@ -4573,7 +4576,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_display_t *display,
int *remaining_glyphs)
{
int i;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
cairo_scaled_glyph_t *scaled_glyph;
cairo_fixed_t x = 0, y = 0;
cairo_xlib_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info;
@@ -4725,7 +4728,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_display_t *display,
}
*remaining_glyphs = num_glyphs - i;
- if (*remaining_glyphs != 0 && status == CAIRO_STATUS_SUCCESS)
+ if (*remaining_glyphs != 0 && status == CAIRO_INT_STATUS_SUCCESS)
status = CAIRO_INT_STATUS_UNSUPPORTED;
return status;
@@ -4755,7 +4758,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
@@ -4779,23 +4782,16 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
* then the entire thing is copied to the destination surface,
* including the fully transparent "background" of the rectangular
* glyph surface. */
- if (op == CAIRO_OPERATOR_SOURCE &&
- ! CAIRO_SURFACE_RENDER_AT_LEAST(dst, 0, 11))
- {
+ if (op == CAIRO_OPERATOR_SOURCE)
return UNSUPPORTED ("known bug in Render");
- }
/* We can only use our code if we either have no clip or
* have a real native clip region set. If we're using
* fallback clip masking, we have to go through the full
* fallback path.
*/
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
- if (status)
- return status;
- }
+ if (!_cairo_clip_is_region (clip))
+ return UNSUPPORTED ("clip mask required");
operation = _categorize_composite_operation (dst, op, src_pattern, TRUE);
if (operation == DO_UNSUPPORTED)
diff --git a/src/cairo-xml-surface.c b/src/cairo-xml-surface.c
index cf99ee6..1a6b01d 100644
--- a/src/cairo-xml-surface.c
+++ b/src/cairo-xml-surface.c
@@ -206,6 +206,7 @@ _format_to_string (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_ARGB32: return "ARGB32";
+ case CAIRO_FORMAT_RGB30: return "RGB30";
case CAIRO_FORMAT_RGB24: return "RGB24";
case CAIRO_FORMAT_RGB16_565: return "RGB16_565";
case CAIRO_FORMAT_A8: return "A8";
@@ -416,7 +417,7 @@ _cairo_xml_close_path (void *closure)
static void
_cairo_xml_emit_path (cairo_xml_t *xml,
- cairo_path_fixed_t *path)
+ const cairo_path_fixed_t *path)
{
cairo_status_t status;
@@ -500,7 +501,7 @@ _cairo_xml_surface_emit_clip_path (cairo_xml_surface_t *surface,
static cairo_status_t
_cairo_xml_surface_emit_clip (cairo_xml_surface_t *surface,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
if (clip == NULL)
return CAIRO_STATUS_SUCCESS;
@@ -686,7 +687,7 @@ static cairo_int_status_t
_cairo_xml_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_xml_surface_t *surface = abstract_surface;
cairo_xml_t *xml = to_xml (surface);
@@ -713,10 +714,10 @@ _cairo_xml_surface_paint (void *abstract_surface,
static cairo_int_status_t
_cairo_xml_surface_mask (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_pattern_t *mask,
+ const cairo_clip_t *clip)
{
cairo_xml_surface_t *surface = abstract_surface;
cairo_xml_t *xml = to_xml (surface);
@@ -749,13 +750,13 @@ static cairo_int_status_t
_cairo_xml_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_xml_surface_t *surface = abstract_surface;
cairo_xml_t *xml = to_xml (surface);
@@ -805,11 +806,11 @@ static cairo_int_status_t
_cairo_xml_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
cairo_xml_surface_t *surface = abstract_surface;
cairo_xml_t *xml = to_xml (surface);
@@ -924,7 +925,7 @@ _cairo_xml_emit_scaled_font (cairo_xml_t *xml,
cairo_glyph_t *glyphs,
int num_glyphs)
{
- cairo_status_t status;
+ cairo_int_status_t status;
_cairo_xml_printf (xml, "<scaled-font>");
_cairo_xml_indent (xml, 2);
@@ -948,7 +949,7 @@ _cairo_xml_surface_glyphs (void *abstract_surface,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs)
{
cairo_xml_surface_t *surface = abstract_surface;
diff --git a/src/cairoint.h b/src/cairoint.h
index 0ae2051..5503a07 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -744,7 +744,8 @@ struct _cairo_surface_backend {
void *dst,
cairo_antialias_t antialias,
const cairo_composite_rectangles_t *rects,
- cairo_region_t *clip_region);
+ cairo_region_t *clip_region);
+
cairo_warn cairo_bool_t
(*check_span_renderer) (cairo_operator_t op,
@@ -818,36 +819,36 @@ struct _cairo_surface_backend {
(*paint) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_warn cairo_int_status_t
(*mask) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_warn cairo_int_status_t
(*stroke) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_warn cairo_int_status_t
(*fill) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_warn cairo_int_status_t
(*show_glyphs) (void *surface,
@@ -856,7 +857,7 @@ struct _cairo_surface_backend {
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs);
cairo_surface_t *
@@ -873,7 +874,7 @@ struct _cairo_surface_backend {
cairo_fill_rule_t fill_rule,
double fill_tolerance,
cairo_antialias_t fill_antialias,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_operator_t stroke_op,
const cairo_pattern_t *stroke_source,
const cairo_stroke_style_t *stroke_style,
@@ -881,7 +882,7 @@ struct _cairo_surface_backend {
const cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_surface_t *
(*create_solid_pattern_surface)
@@ -908,7 +909,7 @@ struct _cairo_surface_backend {
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_warn cairo_status_t
(*acquire_source_image_transformed) (void *abstract_surface,
@@ -1357,14 +1358,21 @@ _cairo_path_fixed_fill_to_polygon (const cairo_path_fixed_t *path,
double tolerance,
cairo_polygon_t *polygon);
+cairo_private cairo_status_t
+_cairo_path_fixed_fill_rectilinear_to_polygon (const cairo_path_fixed_t *path,
+ cairo_antialias_t antialias,
+ cairo_polygon_t *polygon);
+
cairo_private cairo_int_status_t
_cairo_path_fixed_fill_rectilinear_to_traps (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias,
cairo_traps_t *traps);
cairo_private cairo_status_t
_cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
+ cairo_antialias_t antialias,
cairo_boxes_t *boxes);
cairo_private cairo_region_t *
@@ -1391,12 +1399,14 @@ cairo_private cairo_int_status_t
_cairo_path_fixed_stroke_rectilinear_to_traps (const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
+ cairo_antialias_t antialias,
cairo_traps_t *traps);
cairo_private cairo_int_status_t
_cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
+ cairo_antialias_t antialias,
cairo_boxes_t *boxes);
cairo_private cairo_int_status_t
@@ -1656,14 +1666,14 @@ cairo_private cairo_status_t
_cairo_surface_paint (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_mask (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_fill_stroke (cairo_surface_t *surface,
@@ -1680,29 +1690,29 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
const cairo_matrix_t *stroke_ctm_inverse,
double stroke_tolerance,
cairo_antialias_t stroke_antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_stroke (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_fill (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_show_text_glyphs (cairo_surface_t *surface,
@@ -1716,7 +1726,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t op,
@@ -2026,6 +2036,19 @@ _cairo_polygon_init (cairo_polygon_t *polygon,
int num_boxes);
cairo_private void
+_cairo_polygon_init_with_clip (cairo_polygon_t *polygon,
+ const cairo_clip_t *clip);
+
+cairo_private cairo_status_t
+_cairo_polygon_init_boxes (cairo_polygon_t *polygon,
+ const cairo_boxes_t *boxes);
+
+cairo_private cairo_status_t
+_cairo_polygon_init_box_array (cairo_polygon_t *polygon,
+ cairo_box_t *boxes,
+ int num_boxes);
+
+cairo_private void
_cairo_polygon_fini (cairo_polygon_t *polygon);
cairo_private cairo_status_t
@@ -2039,6 +2062,14 @@ _cairo_polygon_add_external_edge (void *polygon,
const cairo_point_t *p1,
const cairo_point_t *p2);
+cairo_private cairo_status_t
+_cairo_polygon_reduce (cairo_polygon_t *polygon,
+ cairo_fill_rule_t fill_rule);
+
+cairo_private cairo_status_t
+_cairo_polygon_intersect (cairo_polygon_t *a, int winding_a,
+ cairo_polygon_t *b, int winding_b);
+
#define _cairo_polygon_status(P) ((cairo_polygon_t *) (P))->status
/* cairo-spline.c */
@@ -2129,6 +2160,10 @@ cairo_private void
_cairo_traps_init (cairo_traps_t *traps);
cairo_private void
+_cairo_traps_init_with_clip (cairo_traps_t *traps,
+ const cairo_clip_t *clip);
+
+cairo_private void
_cairo_traps_limit (cairo_traps_t *traps,
const cairo_box_t *boxes,
int num_boxes);
@@ -2200,6 +2235,7 @@ _cairo_traps_extents (const cairo_traps_t *traps,
cairo_private cairo_int_status_t
_cairo_traps_extract_region (cairo_traps_t *traps,
+ cairo_antialias_t antialias,
cairo_region_t **region);
cairo_private cairo_status_t
@@ -2454,6 +2490,9 @@ cairo_private void
_cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path);
cairo_private void
-_cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip);
+_cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon);
+
+cairo_private void
+_cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip);
#endif
diff --git a/src/test-null-surface.c b/src/test-null-surface.c
index 620dd2f..a71ce8b 100644
--- a/src/test-null-surface.c
+++ b/src/test-null-surface.c
@@ -56,36 +56,36 @@ typedef cairo_int_status_t
(*_paint_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_mask_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_stroke_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_fill_func) (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t*path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
typedef cairo_int_status_t
(*_show_glyphs_func) (void *surface,
@@ -94,7 +94,7 @@ typedef cairo_int_status_t
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
+ const cairo_clip_t *clip,
int *remaining_glyphs);
typedef cairo_int_status_t
@@ -109,7 +109,7 @@ typedef cairo_int_status_t
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip);
+ const cairo_clip_t *clip);
static cairo_surface_t *
_cairo_null_surface_create_similar (void *other,
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index 241f1bd..7736282 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -122,7 +122,7 @@ static cairo_int_status_t
_test_paginated_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_paginated_surface_t *surface = abstract_surface;
@@ -137,7 +137,7 @@ _test_paginated_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_paginated_surface_t *surface = abstract_surface;
@@ -152,13 +152,13 @@ static cairo_int_status_t
_test_paginated_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_paginated_surface_t *surface = abstract_surface;
@@ -176,11 +176,11 @@ static cairo_int_status_t
_test_paginated_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_paginated_surface_t *surface = abstract_surface;
@@ -213,7 +213,7 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_paginated_surface_t *surface = abstract_surface;
diff --git a/src/test-wrapping-surface.c b/src/test-wrapping-surface.c
index 4dd6c4c..cef7055 100644
--- a/src/test-wrapping-surface.c
+++ b/src/test-wrapping-surface.c
@@ -138,7 +138,7 @@ static cairo_int_status_t
_test_wrapping_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_wrapping_surface_t *surface = abstract_surface;
@@ -150,7 +150,7 @@ _test_wrapping_surface_mask (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_wrapping_surface_t *surface = abstract_surface;
@@ -162,13 +162,13 @@ static cairo_int_status_t
_test_wrapping_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
const cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_wrapping_surface_t *surface = abstract_surface;
@@ -184,11 +184,11 @@ static cairo_int_status_t
_test_wrapping_surface_fill (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
+ const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_wrapping_surface_t *surface = abstract_surface;
@@ -219,7 +219,7 @@ _test_wrapping_surface_show_text_glyphs (void *abstract_surface,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip)
+ const cairo_clip_t *clip)
{
test_wrapping_surface_t *surface = abstract_surface;
diff --git a/test/clip-group-shapes-circles.ref.png b/test/clip-group-shapes-circles.ref.png
index 064cc58..7dd6a83 100644
Binary files a/test/clip-group-shapes-circles.ref.png and b/test/clip-group-shapes-circles.ref.png differ
diff --git a/test/clip-shape.ref.png b/test/clip-shape.ref.png
index e80f666..313e245 100644
Binary files a/test/clip-shape.ref.png and b/test/clip-shape.ref.png differ
diff --git a/test/clip-stroke.ref.png b/test/clip-stroke.ref.png
index e66cc43..0b316e6 100644
Binary files a/test/clip-stroke.ref.png and b/test/clip-stroke.ref.png differ
commit f58ade7bace8c82d0ea6740f56d227696181d616
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue Jul 19 21:14:08 2011 +0100
ps: Add HAS_FT_FONT guards for type1
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 72a82f3..0b5f8e9 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -339,6 +339,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
}
}
+#if CAIRO_HAS_FT_FONT
+
static cairo_status_t
_cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@@ -371,6 +373,7 @@ _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+
static cairo_status_t
_cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@@ -400,6 +403,23 @@ _cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+#else
+
+static cairo_status_t
+_cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface,
+ cairo_scaled_font_subset_t *font_subset)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_status_t
+_cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface,
+ cairo_scaled_font_subset_t *font_subset)
+{
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+#endif
static cairo_status_t
_cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
More information about the cairo-commit
mailing list