summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2005-12-19 22:45:41 +0000
committerCarl Worth <cworth@cworth.org>2005-12-19 22:45:41 +0000
commitff486bec0fb1f991217ac9023c0559176ba19a0f (patch)
treeba6e2266f6cc0cf9d6b98e2c310ea251d7fbd2a1
parent75b2fe93f09324b509630d86e0b01de830d853cf (diff)
Begin moving fallback code out of cairo-surface.c and into cairo-surface-fallback.c.
-rw-r--r--ChangeLog22
-rw-r--r--src/Makefile.am2
-rw-r--r--src/cairo-surface-fallback-private.h119
-rw-r--r--src/cairo-surface-fallback.c625
-rw-r--r--src/cairo-surface.c644
5 files changed, 797 insertions, 615 deletions
diff --git a/ChangeLog b/ChangeLog
index 4bcd45e8..5c7e6132 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,27 @@
2005-12-19 Carl Worth <cworth@cworth.org>
+ * src/Makefile.am:
+ * src/cairo-surface-fallback-private.h:
+ * src/cairo-surface-fallback.c: (_fallback_init), (_fallback_fini),
+ (_cairo_surface_fallback_paint), (_cairo_surface_mask_draw_func),
+ (_cairo_surface_fallback_mask), (_cairo_surface_fallback_stroke),
+ (_cairo_surface_fallback_fill),
+ (_cairo_surface_old_show_glyphs_draw_func),
+ (_cairo_surface_fallback_show_glyphs),
+ (_cairo_surface_fallback_snapshot),
+ (_cairo_surface_fallback_composite),
+ (_cairo_surface_fallback_fill_rectangles),
+ (_cairo_surface_fallback_composite_trapezoids):
+ * src/cairo-surface.c: (_cairo_surface_snapshot),
+ (_cairo_surface_composite), (_cairo_surface_fill_rectangles),
+ (_cairo_surface_paint), (_cairo_surface_mask),
+ (_cairo_surface_stroke), (_cairo_surface_fill),
+ (_cairo_surface_composite_trapezoids),
+ (_cairo_surface_show_glyphs): Begin moving fallback code out of
+ cairo-surface.c and into cairo-surface-fallback.c.
+
+2005-12-19 Carl Worth <cworth@cworth.org>
+
* src/cairo-surface.c: (_cairo_surface_create_similar_solid):
Use _cairo_surface_paint rather than _cairo_surface_fill_rectangle
as only the former is guaranteed to work with all backends.
diff --git a/src/Makefile.am b/src/Makefile.am
index ce3cd43f..687d968d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -154,6 +154,8 @@ libcairo_la_SOURCES = \
cairo-spline.c \
cairo-stroke-style.c \
cairo-surface.c \
+ cairo-surface-fallback.c \
+ cairo-surface-fallback-private.h \
cairo-traps.c \
cairo-pattern.c \
cairo-unicode.c \
diff --git a/src/cairo-surface-fallback-private.h b/src/cairo-surface-fallback-private.h
new file mode 100644
index 00000000..8bd158a3
--- /dev/null
+++ b/src/cairo-surface-fallback-private.h
@@ -0,0 +1,119 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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@cworth.org>
+ */
+
+#ifndef CAIRO_SURFACE_FALLBACK_PRIVATE_H
+#define CAIRO_SURFACE_FALLBACK_PRIVATE_H
+
+#include "cairoint.h"
+
+cairo_private cairo_status_t
+_cairo_surface_fallback_paint (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source);
+cairo_private cairo_status_t
+_cairo_surface_fallback_mask (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_pattern_t *mask);
+
+cairo_private cairo_status_t
+_cairo_surface_fallback_stroke (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *stroke_style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias);
+
+cairo_private cairo_status_t
+_cairo_surface_fallback_fill (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias);
+
+cairo_private cairo_status_t
+_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font);
+
+cairo_private cairo_surface_t *
+_cairo_surface_fallback_snapshot (cairo_surface_t *surface);
+
+cairo_private cairo_status_t
+_cairo_surface_fallback_composite (cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_pattern_t *mask,
+ cairo_surface_t *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_private cairo_status_t
+_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_color_t *color,
+ cairo_rectangle_t *rects,
+ int num_rects);
+
+cairo_private cairo_status_t
+_cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *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);
+
+#endif
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
new file mode 100644
index 00000000..17684b19
--- /dev/null
+++ b/src/cairo-surface-fallback.c
@@ -0,0 +1,625 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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@cworth.org>
+ */
+
+#include "cairo-surface-fallback-private.h"
+#include "cairo-clip-private.h"
+
+typedef struct {
+ cairo_surface_t *dst;
+ cairo_rectangle_t extents;
+ cairo_image_surface_t *image;
+ cairo_rectangle_t image_rect;
+ void *image_extra;
+} fallback_state_t;
+
+/**
+ * _fallback_init:
+ *
+ * Acquire destination image surface needed for an image-based
+ * fallback.
+ *
+ * Return value: CAIRO_INT_STATUS_NOTHING_TO_DO if the extents are not
+ * visible, CAIRO_STATUS_SUCCESS if some portion is visible and all
+ * went well, or some error status otherwise.
+ **/
+static cairo_int_status_t
+_fallback_init (fallback_state_t *state,
+ cairo_surface_t *dst,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ cairo_status_t status;
+
+ state->extents.x = x;
+ state->extents.y = y;
+ state->extents.width = width;
+ state->extents.height = height;
+
+ state->dst = dst;
+
+ status = _cairo_surface_acquire_dest_image (dst, &state->extents,
+ &state->image, &state->image_rect,
+ &state->image_extra);
+ if (status)
+ return status;
+
+ /* XXX: This NULL value tucked away in state->image is a rather
+ * ugly interface. Cleaner would be to push the
+ * CAIRO_INT_STATUS_NOTHING_TO_DO value down into
+ * _cairo_surface_acquire_dest_image and its backend
+ * counterparts. */
+ if (state->image == NULL)
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_fallback_fini (fallback_state_t *state)
+{
+ _cairo_surface_release_dest_image (state->dst, &state->extents,
+ state->image, &state->image_rect,
+ state->image_extra);
+}
+
+cairo_status_t
+_cairo_surface_fallback_paint (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source)
+{
+ cairo_status_t status;
+ cairo_rectangle_t extents;
+ cairo_box_t box;
+ cairo_traps_t traps;
+
+ status = _cairo_surface_get_extents (surface, &extents);
+ if (status)
+ return status;
+
+ if (_cairo_operator_bounded_by_source (op)) {
+ cairo_rectangle_t source_extents;
+ status = _cairo_pattern_get_extents (source, &source_extents);
+ if (status)
+ return status;
+
+ _cairo_rectangle_intersect (&extents, &source_extents);
+ }
+
+ status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
+ if (status)
+ return status;
+
+ box.p1.x = _cairo_fixed_from_int (extents.x);
+ box.p1.y = _cairo_fixed_from_int (extents.y);
+ box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
+ box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
+
+ status = _cairo_traps_init_box (&traps, &box);
+ if (status)
+ return status;
+
+ _cairo_surface_clip_and_composite_trapezoids (source,
+ op,
+ surface,
+ &traps,
+ surface->clip,
+ CAIRO_ANTIALIAS_NONE);
+
+ _cairo_traps_fini (&traps);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_surface_mask_draw_func (void *closure,
+ cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents)
+{
+ cairo_pattern_t *mask = closure;
+
+ if (src)
+ return _cairo_surface_composite (op,
+ src, mask, dst,
+ extents->x, extents->y,
+ extents->x, extents->y,
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height);
+ else
+ return _cairo_surface_composite (op,
+ mask, NULL, dst,
+ extents->x, extents->y,
+ 0, 0, /* unused */
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height);
+}
+
+cairo_status_t
+_cairo_surface_fallback_mask (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_pattern_t *mask)
+{
+ cairo_status_t status;
+ cairo_rectangle_t extents, source_extents, mask_extents;
+
+ status = _cairo_surface_get_extents (surface, &extents);
+ if (status)
+ return status;
+
+ if (_cairo_operator_bounded_by_source (op)) {
+ status = _cairo_pattern_get_extents (source, &source_extents);
+ if (status)
+ return status;
+
+ _cairo_rectangle_intersect (&extents, &source_extents);
+ }
+
+ if (_cairo_operator_bounded_by_mask (op)) {
+ status = _cairo_pattern_get_extents (mask, &mask_extents);
+ if (status)
+ return status;
+
+ _cairo_rectangle_intersect (&extents, &mask_extents);
+ }
+
+ status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
+ if (status)
+ return status;
+
+ status = _cairo_gstate_clip_and_composite (surface->clip, op,
+ source,
+ _cairo_surface_mask_draw_func,
+ mask,
+ surface,
+ &extents);
+
+ return status;
+}
+
+cairo_status_t
+_cairo_surface_fallback_stroke (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *stroke_style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias)
+{
+ cairo_status_t status;
+ cairo_traps_t traps;
+
+ _cairo_traps_init (&traps);
+
+ status = _cairo_path_fixed_stroke_to_traps (path,
+ stroke_style,
+ ctm, ctm_inverse,
+ tolerance,
+ &traps);
+ if (status) {
+ _cairo_traps_fini (&traps);
+ return status;
+ }
+
+ _cairo_surface_clip_and_composite_trapezoids (source,
+ op,
+ surface,
+ &traps,
+ surface->clip,
+ antialias);
+
+ _cairo_traps_fini (&traps);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_surface_fallback_fill (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias)
+{
+ cairo_status_t status;
+ cairo_traps_t traps;
+
+ _cairo_traps_init (&traps);
+
+ status = _cairo_path_fixed_fill_to_traps (path,
+ fill_rule,
+ tolerance,
+ &traps);
+ if (status) {
+ _cairo_traps_fini (&traps);
+ return status;
+ }
+
+ status = _cairo_surface_clip_and_composite_trapezoids (source,
+ op,
+ surface,
+ &traps,
+ surface->clip,
+ antialias);
+
+ _cairo_traps_fini (&traps);
+
+ return status;
+}
+
+typedef struct {
+ cairo_scaled_font_t *font;
+ const cairo_glyph_t *glyphs;
+ int num_glyphs;
+} cairo_show_glyphs_info_t;
+
+static cairo_status_t
+_cairo_surface_old_show_glyphs_draw_func (void *closure,
+ cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents)
+{
+ cairo_show_glyphs_info_t *glyph_info = closure;
+ cairo_pattern_union_t pattern;
+ cairo_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
+ * glyphs in the wrapper.
+ */
+ if (dst_x != 0 || dst_y != 0) {
+ int i;
+
+ for (i = 0; i < glyph_info->num_glyphs; ++i)
+ {
+ ((cairo_glyph_t *) glyph_info->glyphs)[i].x -= dst_x;
+ ((cairo_glyph_t *) glyph_info->glyphs)[i].y -= dst_y;
+ }
+ }
+
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
+ if (!src)
+ src = &pattern.base;
+
+ status = _cairo_surface_old_show_glyphs (glyph_info->font, op, src,
+ dst,
+ extents->x, extents->y,
+ extents->x - dst_x,
+ extents->y - dst_y,
+ extents->width,
+ extents->height,
+ glyph_info->glyphs,
+ glyph_info->num_glyphs);
+
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ status = _cairo_scaled_font_show_glyphs (glyph_info->font,
+ op,
+ src, dst,
+ extents->x, extents->y,
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height,
+ glyph_info->glyphs,
+ glyph_info->num_glyphs);
+
+ if (src == &pattern.base)
+ _cairo_pattern_fini (&pattern.base);
+
+ return status;
+}
+
+cairo_status_t
+_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font)
+{
+ cairo_status_t status;
+ cairo_rectangle_t extents, glyph_extents;
+ cairo_show_glyphs_info_t glyph_info;
+
+ status = _cairo_surface_get_extents (surface, &extents);
+ if (status)
+ return status;
+
+ if (_cairo_operator_bounded_by_mask (op)) {
+ status = _cairo_scaled_font_glyph_device_extents (scaled_font,
+ glyphs,
+ num_glyphs,
+ &glyph_extents);
+ if (status)
+ return status;
+
+ _cairo_rectangle_intersect (&extents, &glyph_extents);
+ }
+
+ status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
+ if (status)
+ return status;
+
+ glyph_info.font = scaled_font;
+ glyph_info.glyphs = glyphs;
+ glyph_info.num_glyphs = num_glyphs;
+
+ status = _cairo_gstate_clip_and_composite (surface->clip,
+ op,
+ source,
+ _cairo_surface_old_show_glyphs_draw_func,
+ &glyph_info,
+ surface,
+ &extents);
+
+ return status;
+}
+
+cairo_surface_t *
+_cairo_surface_fallback_snapshot (cairo_surface_t *surface)
+{
+ cairo_surface_t *snapshot;
+ cairo_status_t status;
+ cairo_pattern_union_t pattern;
+ cairo_image_surface_t *image;
+ void *image_extra;
+
+ status = _cairo_surface_acquire_source_image (surface,
+ &image, &image_extra);
+ if (status != CAIRO_STATUS_SUCCESS)
+ return (cairo_surface_t *) &_cairo_surface_nil;
+
+ snapshot = cairo_image_surface_create (image->format,
+ image->width,
+ image->height);
+ if (cairo_surface_status (snapshot))
+ return snapshot;
+
+ _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
+
+ _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+ &pattern.base,
+ NULL,
+ snapshot,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ image->width,
+ image->height);
+
+ _cairo_pattern_fini (&pattern.base);
+
+ _cairo_surface_release_source_image (surface,
+ image, &image_extra);
+
+ snapshot->is_snapshot = TRUE;
+
+ return snapshot;
+}
+
+cairo_status_t
+_cairo_surface_fallback_composite (cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_pattern_t *mask,
+ cairo_surface_t *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)
+{
+ fallback_state_t state;
+ cairo_status_t status;
+
+ status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
+ if (status) {
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ return CAIRO_STATUS_SUCCESS;
+ return status;
+ }
+
+ status = state.image->base.backend->composite (op, src, mask,
+ &state.image->base,
+ src_x, src_y, mask_x, mask_y,
+ dst_x - state.image_rect.x,
+ dst_y - state.image_rect.y,
+ width, height);
+ _fallback_fini (&state);
+
+ return status;
+}
+
+cairo_status_t
+_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_color_t *color,
+ cairo_rectangle_t *rects,
+ int num_rects)
+{
+ fallback_state_t state;
+ cairo_rectangle_t *offset_rects = NULL;
+ cairo_status_t status;
+ int x1, y1, x2, y2;
+ int i;
+
+ assert (! surface->is_snapshot);
+
+ if (num_rects <= 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* Compute the bounds of the rectangles, so that we know what area of the
+ * destination surface to fetch
+ */
+ x1 = rects[0].x;
+ y1 = rects[0].y;
+ x2 = rects[0].x + rects[0].width;
+ y2 = rects[0].y + rects[0].height;
+
+ for (i = 1; i < num_rects; i++) {
+ if (rects[i].x < x1)
+ x1 = rects[i].x;
+ if (rects[i].y < y1)
+ y1 = rects[i].y;
+
+ if (rects[i].x + rects[i].width > x2)
+ x2 = rects[i].x + rects[i].width;
+ if (rects[i].y + rects[i].height > y2)
+ y2 = rects[i].y + rects[i].height;
+ }
+
+ status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
+ if (status) {
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ return CAIRO_STATUS_SUCCESS;
+ return status;
+ }
+
+ /* If the fetched image isn't at 0,0, we need to offset the rectangles */
+
+ if (state.image_rect.x != 0 || state.image_rect.y != 0) {
+ offset_rects = malloc (sizeof (cairo_rectangle_t) * num_rects);
+ if (offset_rects == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto DONE;
+ }
+
+ for (i = 0; i < num_rects; i++) {
+ offset_rects[i].x = rects[i].x - state.image_rect.x;
+ offset_rects[i].y = rects[i].y - state.image_rect.y;
+ offset_rects[i].width = rects[i].width;
+ offset_rects[i].height = rects[i].height;
+ }
+
+ rects = offset_rects;
+ }
+
+ status = state.image->base.backend->fill_rectangles (&state.image->base,
+ op, color,
+ rects, num_rects);
+
+ free (offset_rects);
+
+ DONE:
+ _fallback_fini (&state);
+
+ return status;
+}
+
+cairo_status_t
+_cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
+ cairo_pattern_t *pattern,
+ cairo_surface_t *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)
+{
+ fallback_state_t state;
+ cairo_trapezoid_t *offset_traps = NULL;
+ cairo_status_t status;
+ int i;
+
+ status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
+ if (status) {
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
+ return CAIRO_STATUS_SUCCESS;
+ return status;
+ }
+
+ /* If the destination image isn't at 0,0, we need to offset the trapezoids */
+
+ if (state.image_rect.x != 0 || state.image_rect.y != 0) {
+
+ cairo_fixed_t xoff = _cairo_fixed_from_int (state.image_rect.x);
+ cairo_fixed_t yoff = _cairo_fixed_from_int (state.image_rect.y);
+
+ offset_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
+ if (!offset_traps) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto DONE;
+ }
+
+ for (i = 0; i < num_traps; i++) {
+ offset_traps[i].top = traps[i].top - yoff;
+ offset_traps[i].bottom = traps[i].bottom - yoff;
+ offset_traps[i].left.p1.x = traps[i].left.p1.x - xoff;
+ offset_traps[i].left.p1.y = traps[i].left.p1.y - yoff;
+ offset_traps[i].left.p2.x = traps[i].left.p2.x - xoff;
+ offset_traps[i].left.p2.y = traps[i].left.p2.y - yoff;
+ offset_traps[i].right.p1.x = traps[i].right.p1.x - xoff;
+ offset_traps[i].right.p1.y = traps[i].right.p1.y - yoff;
+ offset_traps[i].right.p2.x = traps[i].right.p2.x - xoff;
+ offset_traps[i].right.p2.y = traps[i].right.p2.y - yoff;
+ }
+
+ traps = offset_traps;
+ }
+
+ state.image->base.backend->composite_trapezoids (op, pattern,
+ &state.image->base,
+ antialias,
+ src_x, src_y,
+ dst_x - state.image_rect.x,
+ dst_y - state.image_rect.y,
+ width, height, traps, num_traps);
+ if (offset_traps)
+ free (offset_traps);
+
+ DONE:
+ _fallback_fini (&state);
+
+ return status;
+}
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index e34cb6c1..4865fc71 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include "cairoint.h"
+#include "cairo-surface-fallback-private.h"
#include "cairo-clip-private.h"
const cairo_surface_t _cairo_surface_nil = {
@@ -735,48 +736,6 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
/* XXX: Shouldn't really need to do this here. */
#include "cairo-meta-surface-private.h"
-static cairo_surface_t *
-_fallback_snapshot (cairo_surface_t *surface)
-{
- cairo_surface_t *snapshot;
- cairo_status_t status;
- cairo_pattern_union_t pattern;
- cairo_image_surface_t *image;
- void *image_extra;
-
- status = _cairo_surface_acquire_source_image (surface,
- &image, &image_extra);
- if (status != CAIRO_STATUS_SUCCESS)
- return (cairo_surface_t *) &_cairo_surface_nil;
-
- snapshot = cairo_image_surface_create (image->format,
- image->width,
- image->height);
- if (cairo_surface_status (snapshot))
- return snapshot;
-
- _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
-
- _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
- &pattern.base,
- NULL,
- snapshot,
- 0, 0,
- 0, 0,
- 0, 0,
- image->width,
- image->height);
-
- _cairo_pattern_fini (&pattern.base);
-
- _cairo_surface_release_source_image (surface,
- image, &image_extra);
-
- snapshot->is_snapshot = TRUE;
-
- return snapshot;
-}
-
/**
* _cairo_surface_snapshot
* @surface: a #cairo_surface_t
@@ -800,102 +759,7 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
if (surface->backend->snapshot)
return surface->backend->snapshot (surface);
- return _fallback_snapshot (surface);
-}
-
-typedef struct {
- cairo_surface_t *dst;
- cairo_rectangle_t extents;
- cairo_image_surface_t *image;
- cairo_rectangle_t image_rect;
- void *image_extra;
-} fallback_state_t;
-
-/**
- * _fallback_init:
- *
- * Acquire destination image surface needed for an image-based
- * fallback.
- *
- * Return value: CAIRO_INT_STATUS_NOTHING_TO_DO if the extents are not
- * visible, CAIRO_STATUS_SUCCESS if some portion is visible and all
- * went well, or some error status otherwise.
- **/
-static cairo_int_status_t
-_fallback_init (fallback_state_t *state,
- cairo_surface_t *dst,
- int x,
- int y,
- int width,
- int height)
-{
- cairo_status_t status;
-
- state->extents.x = x;
- state->extents.y = y;
- state->extents.width = width;
- state->extents.height = height;
-
- state->dst = dst;
-
- status = _cairo_surface_acquire_dest_image (dst, &state->extents,
- &state->image, &state->image_rect,
- &state->image_extra);
- if (status)
- return status;
-
- /* XXX: This NULL value tucked away in state->image is a rather
- * ugly interface. Cleaner would be to push the
- * CAIRO_INT_STATUS_NOTHING_TO_DO value down into
- * _cairo_surface_acquire_dest_image and its backend
- * counterparts. */
- if (state->image == NULL)
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_fallback_fini (fallback_state_t *state)
-{
- _cairo_surface_release_dest_image (state->dst, &state->extents,
- state->image, &state->image_rect,
- state->image_extra);
-}
-
-static cairo_status_t
-_fallback_composite (cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_pattern_t *mask,
- cairo_surface_t *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)
-{
- fallback_state_t state;
- cairo_status_t status;
-
- status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (status) {
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
- return status;
- }
-
- status = state.image->base.backend->composite (op, src, mask,
- &state.image->base,
- src_x, src_y, mask_x, mask_y,
- dst_x - state.image_rect.x,
- dst_y - state.image_rect.y,
- width, height);
- _fallback_fini (&state);
-
- return status;
+ return _cairo_surface_fallback_snapshot (surface);
}
cairo_status_t
@@ -940,12 +804,12 @@ _cairo_surface_composite (cairo_operator_t op,
return status;
}
- return _fallback_composite (op,
- src, mask, dst,
- src_x, src_y,
- mask_x, mask_y,
- dst_x, dst_y,
- width, height);
+ return _cairo_surface_fallback_composite (op,
+ src, mask, dst,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y,
+ width, height);
}
/**
@@ -1039,82 +903,6 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
return status;
}
-static cairo_status_t
-_fallback_fill_rectangles (cairo_surface_t *surface,
- cairo_operator_t op,
- const cairo_color_t *color,
- cairo_rectangle_t *rects,
- int num_rects)
-{
- fallback_state_t state;
- cairo_rectangle_t *offset_rects = NULL;
- cairo_status_t status;
- int x1, y1, x2, y2;
- int i;
-
- assert (! surface->is_snapshot);
-
- if (num_rects <= 0)
- return CAIRO_STATUS_SUCCESS;
-
- /* Compute the bounds of the rectangles, so that we know what area of the
- * destination surface to fetch
- */
- x1 = rects[0].x;
- y1 = rects[0].y;
- x2 = rects[0].x + rects[0].width;
- y2 = rects[0].y + rects[0].height;
-
- for (i = 1; i < num_rects; i++) {
- if (rects[i].x < x1)
- x1 = rects[i].x;
- if (rects[i].y < y1)
- y1 = rects[i].y;
-
- if (rects[i].x + rects[i].width > x2)
- x2 = rects[i].x + rects[i].width;
- if (rects[i].y + rects[i].height > y2)
- y2 = rects[i].y + rects[i].height;
- }
-
- status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
- if (status) {
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
- return status;
- }
-
- /* If the fetched image isn't at 0,0, we need to offset the rectangles */
-
- if (state.image_rect.x != 0 || state.image_rect.y != 0) {
- offset_rects = malloc (sizeof (cairo_rectangle_t) * num_rects);
- if (offset_rects == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto DONE;
- }
-
- for (i = 0; i < num_rects; i++) {
- offset_rects[i].x = rects[i].x - state.image_rect.x;
- offset_rects[i].y = rects[i].y - state.image_rect.y;
- offset_rects[i].width = rects[i].width;
- offset_rects[i].height = rects[i].height;
- }
-
- rects = offset_rects;
- }
-
- status = state.image->base.backend->fill_rectangles (&state.image->base,
- op, color,
- rects, num_rects);
-
- free (offset_rects);
-
- DONE:
- _fallback_fini (&state);
-
- return status;
-}
-
/**
* _cairo_surface_fill_rectangles:
* @surface: a #cairo_surface_t
@@ -1152,63 +940,14 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
if (surface->backend->fill_rectangles) {
- status = surface->backend->fill_rectangles (surface,
- op,
- color,
+ status = surface->backend->fill_rectangles (surface, op, color,
rects, num_rects);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
- return _fallback_fill_rectangles (surface, op, color, rects, num_rects);
-}
-
-static cairo_status_t
-_fallback_paint (cairo_surface_t *surface,
- cairo_operator_t op,
- cairo_pattern_t *source)
-{
- cairo_status_t status;
- cairo_rectangle_t extents;
- cairo_box_t box;
- cairo_traps_t traps;
-
- status = _cairo_surface_get_extents (surface, &extents);
- if (status)
- return status;
-
- if (_cairo_operator_bounded_by_source (op)) {
- cairo_rectangle_t source_extents;
- status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
- return status;
-
- _cairo_rectangle_intersect (&extents, &source_extents);
- }
-
- status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
- return status;
-
- box.p1.x = _cairo_fixed_from_int (extents.x);
- box.p1.y = _cairo_fixed_from_int (extents.y);
- box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
- box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
-
- status = _cairo_traps_init_box (&traps, &box);
- if (status)
- return status;
-
- _cairo_surface_clip_and_composite_trapezoids (source,
- op,
- surface,
- &traps,
- surface->clip,
- CAIRO_ANTIALIAS_NONE);
-
- _cairo_traps_fini (&traps);
-
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_surface_fallback_fill_rectangles (surface, op, color,
+ rects, num_rects);
}
cairo_status_t
@@ -1226,77 +965,7 @@ _cairo_surface_paint (cairo_surface_t *surface,
return status;
}
- return _fallback_paint (surface, op, source);
-}
-
-static cairo_status_t
-_cairo_surface_mask_draw_func (void *closure,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_surface_t *dst,
- int dst_x,
- int dst_y,
- const cairo_rectangle_t *extents)
-{
- cairo_pattern_t *mask = closure;
-
- if (src)
- return _cairo_surface_composite (op,
- src, mask, dst,
- extents->x, extents->y,
- extents->x, extents->y,
- extents->x - dst_x, extents->y - dst_y,
- extents->width, extents->height);
- else
- return _cairo_surface_composite (op,
- mask, NULL, dst,
- extents->x, extents->y,
- 0, 0, /* unused */
- extents->x - dst_x, extents->y - dst_y,
- extents->width, extents->height);
-}
-
-static cairo_status_t
-_fallback_mask (cairo_surface_t *surface,
- cairo_operator_t op,
- cairo_pattern_t *source,
- cairo_pattern_t *mask)
-{
- cairo_status_t status;
- cairo_rectangle_t extents, source_extents, mask_extents;
-
- status = _cairo_surface_get_extents (surface, &extents);
- if (status)
- return status;
-
- if (_cairo_operator_bounded_by_source (op)) {
- status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
- return status;
-
- _cairo_rectangle_intersect (&extents, &source_extents);
- }
-
- if (_cairo_operator_bounded_by_mask (op)) {
- status = _cairo_pattern_get_extents (mask, &mask_extents);
- if (status)
- return status;
-
- _cairo_rectangle_intersect (&extents, &mask_extents);
- }
-
- status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
- return status;
-
- status = _cairo_gstate_clip_and_composite (surface->clip, op,
- source,
- _cairo_surface_mask_draw_func,
- mask,
- surface,
- &extents);
-
- return status;
+ return _cairo_surface_fallback_paint (surface, op, source);
}
cairo_status_t
@@ -1315,45 +984,7 @@ _cairo_surface_mask (cairo_surface_t *surface,
return status;
}
- return _fallback_mask (surface, op, source, mask);
-}
-
-static cairo_status_t
-_fallback_stroke (cairo_surface_t *surface,
- cairo_operator_t op,
- cairo_pattern_t *source,
- cairo_path_fixed_t *path,
- cairo_stroke_style_t *stroke_style,
- cairo_matrix_t *ctm,
- cairo_matrix_t *ctm_inverse,
- double tolerance,
- cairo_antialias_t antialias)
-{
- cairo_status_t status;
- cairo_traps_t traps;
-
- _cairo_traps_init (&traps);
-
- status = _cairo_path_fixed_stroke_to_traps (path,
- stroke_style,
- ctm, ctm_inverse,
- tolerance,
- &traps);
- if (status) {
- _cairo_traps_fini (&traps);
- return status;
- }
-
- _cairo_surface_clip_and_composite_trapezoids (source,
- op,
- surface,
- &traps,
- surface->clip,
- antialias);
-
- _cairo_traps_fini (&traps);
-
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_surface_fallback_mask (surface, op, source, mask);
}
cairo_status_t
@@ -1379,45 +1010,10 @@ _cairo_surface_stroke (cairo_surface_t *surface,
return status;
}
- return _fallback_stroke (surface, op, source,
- path, stroke_style,
- ctm, ctm_inverse,
- tolerance, antialias);
-}
-
-static cairo_status_t
-_fallback_fill (cairo_surface_t *surface,
- cairo_operator_t op,
- cairo_pattern_t *source,
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias)
-{
- cairo_status_t status;
- cairo_traps_t traps;
-
- _cairo_traps_init (&traps);
-
- status = _cairo_path_fixed_fill_to_traps (path,
- fill_rule,
- tolerance,
- &traps);
- if (status) {
- _cairo_traps_fini (&traps);
- return status;
- }
-
- status = _cairo_surface_clip_and_composite_trapezoids (source,
- op,
- surface,
- &traps,
- surface->clip,
- antialias);
-
- _cairo_traps_fini (&traps);
-
- return status;
+ return _cairo_surface_fallback_stroke (surface, op, source,
+ path, stroke_style,
+ ctm, ctm_inverse,
+ tolerance, antialias);
}
cairo_status_t
@@ -1441,82 +1037,11 @@ _cairo_surface_fill (cairo_surface_t *surface,
return status;
}
- return _fallback_fill (surface, op, source,
- path, fill_rule,
- tolerance, antialias);
+ return _cairo_surface_fallback_fill (surface, op, source,
+ path, fill_rule,
+ tolerance, antialias);
}
-static cairo_status_t
-_fallback_composite_trapezoids (cairo_operator_t op,
- cairo_pattern_t *pattern,
- cairo_surface_t *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)
-{
- fallback_state_t state;
- cairo_trapezoid_t *offset_traps = NULL;
- cairo_status_t status;
- int i;
-
- status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (status) {
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
- return CAIRO_STATUS_SUCCESS;
- return status;
- }
-
- /* If the destination image isn't at 0,0, we need to offset the trapezoids */
-
- if (state.image_rect.x != 0 || state.image_rect.y != 0) {
-
- cairo_fixed_t xoff = _cairo_fixed_from_int (state.image_rect.x);
- cairo_fixed_t yoff = _cairo_fixed_from_int (state.image_rect.y);
-
- offset_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
- if (!offset_traps) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto DONE;
- }
-
- for (i = 0; i < num_traps; i++) {
- offset_traps[i].top = traps[i].top - yoff;
- offset_traps[i].bottom = traps[i].bottom - yoff;
- offset_traps[i].left.p1.x = traps[i].left.p1.x - xoff;
- offset_traps[i].left.p1.y = traps[i].left.p1.y - yoff;
- offset_traps[i].left.p2.x = traps[i].left.p2.x - xoff;
- offset_traps[i].left.p2.y = traps[i].left.p2.y - yoff;
- offset_traps[i].right.p1.x = traps[i].right.p1.x - xoff;
- offset_traps[i].right.p1.y = traps[i].right.p1.y - yoff;
- offset_traps[i].right.p2.x = traps[i].right.p2.x - xoff;
- offset_traps[i].right.p2.y = traps[i].right.p2.y - yoff;
- }
-
- traps = offset_traps;
- }
-
- state.image->base.backend->composite_trapezoids (op, pattern,
- &state.image->base,
- antialias,
- src_x, src_y,
- dst_x - state.image_rect.x,
- dst_y - state.image_rect.y,
- width, height, traps, num_traps);
- if (offset_traps)
- free (offset_traps);
-
- DONE:
- _fallback_fini (&state);
-
- return status;
-}
-
cairo_status_t
_cairo_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
@@ -1558,12 +1083,12 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
return status;
}
- return _fallback_composite_trapezoids (op, pattern, dst,
- antialias,
- src_x, src_y,
- dst_x, dst_y,
- width, height,
- traps, num_traps);
+ return _cairo_surface_fallback_composite_trapezoids (op, pattern, dst,
+ antialias,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height,
+ traps, num_traps);
}
cairo_status_t
@@ -1854,117 +1379,6 @@ _cairo_surface_get_extents (cairo_surface_t *surface,
return surface->backend->get_extents (surface, rectangle);
}
-typedef struct {
- cairo_scaled_font_t *font;
- const cairo_glyph_t *glyphs;
- int num_glyphs;
-} cairo_show_glyphs_info_t;
-
-static cairo_status_t
-_cairo_surface_old_show_glyphs_draw_func (void *closure,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_surface_t *dst,
- int dst_x,
- int dst_y,
- const cairo_rectangle_t *extents)
-{
- cairo_show_glyphs_info_t *glyph_info = closure;
- cairo_pattern_union_t pattern;
- cairo_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
- * glyphs in the wrapper.
- */
- if (dst_x != 0 || dst_y != 0) {
- int i;
-
- for (i = 0; i < glyph_info->num_glyphs; ++i)
- {
- ((cairo_glyph_t *) glyph_info->glyphs)[i].x -= dst_x;
- ((cairo_glyph_t *) glyph_info->glyphs)[i].y -= dst_y;
- }
- }
-
- _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
- if (!src)
- src = &pattern.base;
-
- status = _cairo_surface_old_show_glyphs (glyph_info->font, op, src,
- dst,
- extents->x, extents->y,
- extents->x - dst_x,
- extents->y - dst_y,
- extents->width,
- extents->height,
- glyph_info->glyphs,
- glyph_info->num_glyphs);
-
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- status = _cairo_scaled_font_show_glyphs (glyph_info->font,
- op,
- src, dst,
- extents->x, extents->y,
- extents->x - dst_x, extents->y - dst_y,
- extents->width, extents->height,
- glyph_info->glyphs,
- glyph_info->num_glyphs);
-
- if (src == &pattern.base)
- _cairo_pattern_fini (&pattern.base);
-
- return status;
-}
-
-static cairo_status_t
-_fallback_show_glyphs (cairo_surface_t *surface,
- cairo_operator_t op,
- cairo_pattern_t *source,
- const cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font)
-{
- cairo_status_t status;
- cairo_rectangle_t extents, glyph_extents;
- cairo_show_glyphs_info_t glyph_info;
-
- status = _cairo_surface_get_extents (surface, &extents);
- if (status)
- return status;
-
- if (_cairo_operator_bounded_by_mask (op)) {
- status = _cairo_scaled_font_glyph_device_extents (scaled_font,
- glyphs,
- num_glyphs,
- &glyph_extents);
- if (status)
- return status;
-
- _cairo_rectangle_intersect (&extents, &glyph_extents);
- }
-
- status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
- return status;
-
- glyph_info.font = scaled_font;
- glyph_info.glyphs = glyphs;
- glyph_info.num_glyphs = num_glyphs;
-
- status = _cairo_gstate_clip_and_composite (surface->clip,
- op,
- source,
- _cairo_surface_old_show_glyphs_draw_func,
- &glyph_info,
- surface,
- &extents);
-
- return status;
-}
-
cairo_status_t
_cairo_surface_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
@@ -1985,9 +1399,9 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
return status;
}
- return _fallback_show_glyphs (surface, op, source,
- glyphs, num_glyphs,
- scaled_font);
+ return _cairo_surface_fallback_show_glyphs (surface, op, source,
+ glyphs, num_glyphs,
+ scaled_font);
}
/* XXX: Previously, we had a function named _cairo_surface_show_glyphs