summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-04-23 19:45:26 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-07-15 11:05:19 +0100
commit83bfd85a1378e61b8bdc3f554f5e07900311f61f (patch)
tree380f96e0021d420799db02f4abe3e364745ec476
parent2055732ffcd6316c3feb05ac330fbaf8698df5c4 (diff)
Implement cairo_backend_t
Allow a backend to completely reimplement the Cairo API as it wants. The goal is to pass operations to the native backends such as Quartz, Direct2D, Qt, Skia, OpenVG with no overhead. And to permit complete logging contexts, and whatever else the imagination holds. Perhaps to experiment with double-paths? Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/Makefile.sources2
-rw-r--r--src/cairo-analysis-surface.c4
-rw-r--r--src/cairo-backend-private.h170
-rw-r--r--src/cairo-clip.c7
-rw-r--r--src/cairo-debug.c2
-rw-r--r--src/cairo-default-context-private.h58
-rw-r--r--src/cairo-default-context.c1406
-rw-r--r--src/cairo-directfb-surface.c3
-rw-r--r--src/cairo-gl-surface.c3
-rw-r--r--src/cairo-gstate-private.h39
-rw-r--r--src/cairo-gstate.c142
-rw-r--r--src/cairo-image-surface.c3
-rw-r--r--src/cairo-os2-surface.c3
-rw-r--r--src/cairo-paginated-surface.c9
-rw-r--r--src/cairo-path-private.h4
-rw-r--r--src/cairo-path-stroke.c4
-rw-r--r--src/cairo-path.c98
-rw-r--r--src/cairo-pdf-surface.c3
-rw-r--r--src/cairo-private.h25
-rw-r--r--src/cairo-ps-surface.c3
-rw-r--r--src/cairo-qt-surface.cpp3
-rw-r--r--src/cairo-quartz-image-surface.c2
-rw-r--r--src/cairo-recording-surface.c3
-rw-r--r--src/cairo-scaled-font-subsets.c1
-rw-r--r--src/cairo-script-surface.c2
-rw-r--r--src/cairo-surface-snapshot.c1
-rw-r--r--src/cairo-surface-subsurface.c9
-rw-r--r--src/cairo-svg-surface.c3
-rw-r--r--src/cairo-tee-surface.c3
-rw-r--r--src/cairo-type3-glyph-surface.c3
-rw-r--r--src/cairo-types-private.h14
-rw-r--r--src/cairo-vg-surface.c3
-rw-r--r--src/cairo-win32-printing-surface.c3
-rw-r--r--src/cairo-win32-surface.c3
-rw-r--r--src/cairo-xcb-surface-core.c1
-rw-r--r--src/cairo-xcb-surface-render.c1
-rw-r--r--src/cairo-xcb-surface.c3
-rw-r--r--src/cairo-xlib-surface.c3
-rw-r--r--src/cairo-xlib-xcb-surface.c6
-rw-r--r--src/cairo-xml-surface.c3
-rw-r--r--src/cairo.c1039
-rw-r--r--src/cairoint.h9
-rw-r--r--src/drm/cairo-drm-gallium-surface.c3
-rw-r--r--src/drm/cairo-drm-i915-surface.c2
-rw-r--r--src/drm/cairo-drm-i965-surface.c2
-rw-r--r--src/drm/cairo-drm-intel-surface.c2
-rw-r--r--src/drm/cairo-drm-radeon-surface.c2
-rw-r--r--src/test-fallback-surface.c3
-rw-r--r--src/test-fallback16-surface.c3
-rw-r--r--src/test-null-surface.c2
-rw-r--r--src/test-paginated-surface.c2
-rw-r--r--src/test-wrapping-surface.c3
52 files changed, 2321 insertions, 809 deletions
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 966e03d9..03b20301 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -62,6 +62,7 @@ cairo_private = \
cairo-combsort-private.h \
cairo-compiler-private.h \
cairo-composite-rectangles-private.h \
+ cairo-default-context-private.h \
cairo-device-private.h \
cairo-error-private.h \
cairo-fixed-private.h \
@@ -122,6 +123,7 @@ cairo_sources = \
cairo-color.c \
cairo-composite-rectangles.c \
cairo-debug.c \
+ cairo-default-context.c \
cairo-device.c \
cairo-error.c \
cairo-fixed.c \
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 5468eac0..affa5563 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -37,6 +37,7 @@
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-paginated-private.h"
#include "cairo-recording-surface-private.h"
@@ -646,6 +647,8 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
+ NULL,
+
NULL, /* create_similar */
_cairo_analysis_surface_finish,
NULL, /* acquire_source_image */
@@ -843,6 +846,7 @@ typedef cairo_int_status_t
static const cairo_surface_backend_t cairo_null_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
+ _cairo_default_context_create, /* XXX */
NULL, /* create_similar */
NULL, /* finish */
diff --git a/src/cairo-backend-private.h b/src/cairo-backend-private.h
new file mode 100644
index 00000000..720b28c3
--- /dev/null
+++ b/src/cairo-backend-private.h
@@ -0,0 +1,170 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2010 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., 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 Intel Corporation
+ *
+ * Contributor(s):
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#ifndef CAIRO_BACKEND_PRIVATE_H
+#define CAIRO_BACKEND_PRIVATE_H
+
+#include "cairo-types-private.h"
+
+typedef enum _cairo_backend_type {
+ CAIRO_TYPE_DEFAULT,
+} cairo_backend_type_t;
+
+struct _cairo_backend {
+ cairo_backend_type_t type;
+ void (*destroy) (void *cr);
+
+ cairo_surface_t *(*get_original_target) (void *cr);
+ cairo_surface_t *(*get_current_target) (void *cr);
+
+ cairo_status_t (*save) (void *cr);
+ cairo_status_t (*restore) (void *cr);
+
+ cairo_status_t (*push_group) (void *cr, cairo_content_t content);
+ cairo_pattern_t *(*pop_group) (void *cr);
+
+ cairo_status_t (*set_source_rgba) (void *cr, double red, double green, double blue, double alpha);
+ cairo_status_t (*set_source_surface) (void *cr, cairo_surface_t *surface, double x, double y);
+ cairo_status_t (*set_source) (void *cr, cairo_pattern_t *source);
+ cairo_pattern_t *(*get_source) (void *cr);
+
+ cairo_status_t (*set_antialias) (void *cr, cairo_antialias_t antialias);
+ cairo_status_t (*set_dash) (void *cr, const double *dashes, int num_dashes, double offset);
+ cairo_status_t (*set_fill_rule) (void *cr, cairo_fill_rule_t fill_rule);
+ cairo_status_t (*set_line_cap) (void *cr, cairo_line_cap_t line_cap);
+ cairo_status_t (*set_line_join) (void *cr, cairo_line_join_t line_join);
+ cairo_status_t (*set_line_width) (void *cr, double line_width);
+ cairo_status_t (*set_miter_limit) (void *cr, double limit);
+ cairo_status_t (*set_opacity) (void *cr, double opacity);
+ cairo_status_t (*set_operator) (void *cr, cairo_operator_t op);
+ cairo_status_t (*set_tolerance) (void *cr, double tolerance);
+
+ cairo_antialias_t (*get_antialias) (void *cr);
+ void (*get_dash) (void *cr, double *dashes, int *num_dashes, double *offset);
+ cairo_fill_rule_t (*get_fill_rule) (void *cr);
+ cairo_line_cap_t (*get_line_cap) (void *cr);
+ cairo_line_join_t (*get_line_join) (void *cr);
+ double (*get_line_width) (void *cr);
+ double (*get_miter_limit) (void *cr);
+ double (*get_opacity) (void *cr);
+ cairo_operator_t (*get_operator) (void *cr);
+ double (*get_tolerance) (void *cr);
+
+ cairo_status_t (*translate) (void *cr, double tx, double ty);
+ cairo_status_t (*scale) (void *cr, double sx, double sy);
+ cairo_status_t (*rotate) (void *cr, double theta);
+ cairo_status_t (*transform) (void *cr, const cairo_matrix_t *matrix);
+ cairo_status_t (*set_matrix) (void *cr, const cairo_matrix_t *matrix);
+ cairo_status_t (*set_identity_matrix) (void *cr);
+ void (*get_matrix) (void *cr, cairo_matrix_t *matrix);
+
+ void (*user_to_device) (void *cr, double *x, double *y);
+ void (*user_to_device_distance) (void *cr, double *x, double *y);
+ void (*device_to_user) (void *cr, double *x, double *y);
+ void (*device_to_user_distance) (void *cr, double *x, double *y);
+
+ cairo_status_t (*new_path) (void *cr);
+ cairo_status_t (*new_sub_path) (void *cr);
+ cairo_status_t (*move_to) (void *cr, double x, double y);
+ cairo_status_t (*rel_move_to) (void *cr, double dx, double dy);
+ cairo_status_t (*line_to) (void *cr, double x, double y);
+ cairo_status_t (*rel_line_to) (void *cr, double dx, double dy);
+ cairo_status_t (*curve_to) (void *cr, double x1, double y1, double x2, double y2, double x3, double y3);
+ cairo_status_t (*rel_curve_to) (void *cr, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3);
+ cairo_status_t (*arc_to) (void *cr, double x1, double y1, double x2, double y2, double radius);
+ cairo_status_t (*rel_arc_to) (void *cr, double dx1, double dy1, double dx2, double dy2, double radius);
+ cairo_status_t (*close_path) (void *cr);
+
+ cairo_status_t (*arc) (void *cr, double xc, double yc, double radius, double angle1, double angle2, cairo_bool_t forward);
+ cairo_status_t (*rectangle) (void *cr, double x, double y, double width, double height);
+
+ void (*path_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
+ cairo_bool_t (*has_current_point) (void *cr);
+ cairo_bool_t (*get_current_point) (void *cr, double *x, double *y);
+
+ cairo_path_t *(*copy_path) (void *cr);
+ cairo_path_t *(*copy_path_flat) (void *cr);
+ cairo_status_t (*append_path) (void *cr, const cairo_path_t *path);
+
+ cairo_status_t (*stroke_to_path) (void *cr);
+
+ cairo_status_t (*clip) (void *cr);
+ cairo_status_t (*clip_preserve) (void *cr);
+ cairo_status_t (*in_clip) (void *cr, double x, double y, cairo_bool_t *inside);
+ cairo_status_t (*clip_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
+ cairo_status_t (*reset_clip) (void *cr);
+ cairo_rectangle_list_t *(*clip_copy_rectangle_list) (void *cr);
+
+ cairo_status_t (*paint) (void *cr);
+ cairo_status_t (*paint_with_alpha) (void *cr, double opacity);
+ cairo_status_t (*mask) (void *cr, cairo_pattern_t *pattern);
+
+ cairo_status_t (*stroke) (void *cr);
+ cairo_status_t (*stroke_preserve) (void *cr);
+ cairo_status_t (*in_stroke) (void *cr, double x, double y, cairo_bool_t *inside);
+ cairo_status_t (*stroke_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
+
+ cairo_status_t (*fill) (void *cr);
+ cairo_status_t (*fill_preserve) (void *cr);
+ cairo_status_t (*in_fill) (void *cr, double x, double y, cairo_bool_t *inside);
+ cairo_status_t (*fill_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
+
+ cairo_status_t (*set_font_face) (void *cr, cairo_font_face_t *font_face);
+ cairo_font_face_t *(*get_font_face) (void *cr);
+ cairo_status_t (*set_font_size) (void *cr, double size);
+ cairo_status_t (*set_font_matrix) (void *cr, const cairo_matrix_t *matrix);
+ void (*get_font_matrix) (void *cr, cairo_matrix_t *matrix);
+ cairo_status_t (*set_font_options) (void *cr, const cairo_font_options_t *options);
+ void (*get_font_options) (void *cr, cairo_font_options_t *options);
+ cairo_status_t (*set_scaled_font) (void *cr, cairo_scaled_font_t *scaled_font);
+ cairo_scaled_font_t *(*get_scaled_font) (void *cr);
+ cairo_status_t (*font_extents) (void *cr, cairo_font_extents_t *extents);
+
+ cairo_status_t (*glyphs) (void *cr,
+ const cairo_glyph_t *glyphs, int num_glyphs,
+ cairo_glyph_text_info_t *info);
+ cairo_status_t (*glyph_path) (void *cr,
+ const cairo_glyph_t *glyphs, int num_glyphs);
+
+ cairo_status_t (*glyph_extents) (void *cr,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents);
+
+ cairo_status_t (*copy_page) (void *cr);
+ cairo_status_t (*show_page) (void *cr);
+};
+
+#endif /* CAIRO_BACKEND_PRIVATE_H */
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index d78a17c2..929c1073 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -513,10 +513,13 @@ static cairo_status_t
_cairo_clip_apply_clip_path (cairo_clip_t *clip,
const cairo_clip_path_t *path)
{
- cairo_status_t status;
+ if (path->prev != NULL) {
+ cairo_status_t status;
- if (path->prev != NULL)
status = _cairo_clip_apply_clip_path (clip, path->prev);
+ if (unlikely (status))
+ return status;
+ }
return _cairo_clip_intersect_path (clip,
&path->path,
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 1aa57791..f8ef717e 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -87,7 +87,7 @@ cairo_debug_reset_static_data (void)
_cairo_drm_device_reset_static_data ();
#endif
- _cairo_reset_static_data ();
+ _cairo_default_context_reset_static_data ();
CAIRO_MUTEX_FINALIZE ();
}
diff --git a/src/cairo-default-context-private.h b/src/cairo-default-context-private.h
new file mode 100644
index 00000000..e2d780d2
--- /dev/null
+++ b/src/cairo-default-context-private.h
@@ -0,0 +1,58 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * 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 Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@redhat.com>
+ */
+
+#ifndef CAIRO_DEFAULT_CONTEXT_PRIVATE_H
+#define CAIRO_DEFAULT_CONTEXT_PRIVATE_H
+
+#include "cairo-private.h"
+#include "cairo-gstate-private.h"
+#include "cairo-path-fixed-private.h"
+
+typedef struct _cairo_default_context cairo_default_context_t;
+
+struct _cairo_default_context {
+ cairo_t base;
+
+ cairo_gstate_t *gstate;
+ cairo_gstate_t gstate_tail[2];
+ cairo_gstate_t *gstate_freelist;
+
+ cairo_path_fixed_t path[1];
+};
+
+cairo_private cairo_t *
+_cairo_default_context_create (void *target);
+
+#endif /* CAIRO_DEFAULT_CONTEXT_PRIVATE_H */
diff --git a/src/cairo-default-context.c b/src/cairo-default-context.c
new file mode 100644
index 00000000..dbd014a6
--- /dev/null
+++ b/src/cairo-default-context.c
@@ -0,0 +1,1406 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005 Red Hat, Inc.
+ * 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):
+ * Carl D. Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-private.h"
+#include "cairo-arc-private.h"
+#include "cairo-backend-private.h"
+#include "cairo-default-context-private.h"
+#include "cairo-error-private.h"
+#include "cairo-freed-pool-private.h"
+#include "cairo-path-private.h"
+
+#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1)
+
+#if !defined(INFINITY)
+#define INFINITY HUGE_VAL
+#endif
+
+static freed_pool_t context_pool;
+
+void
+_cairo_default_context_reset_static_data (void)
+{
+ _freed_pool_reset (&context_pool);
+}
+
+static void
+_cairo_default_context_destroy (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ while (cr->gstate != &cr->gstate_tail[0]) {
+ if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist))
+ break;
+ }
+
+ _cairo_gstate_fini (cr->gstate);
+ cr->gstate_freelist = cr->gstate_freelist->next; /* skip over tail[1] */
+ while (cr->gstate_freelist != NULL) {
+ cairo_gstate_t *gstate = cr->gstate_freelist;
+ cr->gstate_freelist = gstate->next;
+ free (gstate);
+ }
+
+ _cairo_path_fixed_fini (cr->path);
+
+ _cairo_fini (&cr->base);
+
+ /* mark the context as invalid to protect against misuse */
+ cr->base.status = CAIRO_STATUS_NULL_POINTER;
+ _freed_pool_put (&context_pool, cr);
+}
+
+static cairo_surface_t *
+_cairo_default_context_get_original_target (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_original_target (cr->gstate);
+}
+
+static cairo_surface_t *
+_cairo_default_context_get_current_target (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_target (cr->gstate);
+}
+
+static cairo_status_t
+_cairo_default_context_save (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
+}
+
+static cairo_status_t
+_cairo_default_context_restore (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
+}
+
+static cairo_status_t
+_cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_surface_t *group_surface;
+ cairo_clip_t *clip;
+ cairo_status_t status;
+
+ clip = _cairo_gstate_get_clip (cr->gstate);
+ if (clip->all_clipped) {
+ group_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
+ status = group_surface->status;
+ if (unlikely (status))
+ goto bail;
+ } else {
+ cairo_surface_t *parent_surface;
+ const cairo_rectangle_int_t *clip_extents;
+ cairo_rectangle_int_t extents;
+ cairo_matrix_t matrix;
+ cairo_bool_t is_empty;
+
+ parent_surface = _cairo_gstate_get_target (cr->gstate);
+
+ /* Get the extents that we'll use in creating our new group surface */
+ is_empty = _cairo_surface_get_extents (parent_surface, &extents);
+ clip_extents = _cairo_clip_get_extents (_cairo_gstate_get_clip (cr->gstate));
+ if (clip_extents != NULL)
+ is_empty = _cairo_rectangle_intersect (&extents, clip_extents);
+
+ group_surface = _cairo_surface_create_similar_solid (parent_surface,
+ content,
+ extents.width,
+ extents.height,
+ CAIRO_COLOR_TRANSPARENT,
+ TRUE);
+ status = group_surface->status;
+ if (unlikely (status))
+ goto bail;
+
+ /* Set device offsets on the new surface so that logically it appears at
+ * the same location on the parent surface -- when we pop_group this,
+ * the source pattern will get fixed up for the appropriate target surface
+ * device offsets, so we want to set our own surface offsets from /that/,
+ * and not from the device origin. */
+ cairo_surface_set_device_offset (group_surface,
+ parent_surface->device_transform.x0 - extents.x,
+ parent_surface->device_transform.y0 - extents.y);
+
+ /* If we have a current path, we need to adjust it to compensate for
+ * the device offset just applied. */
+ cairo_matrix_init_translate (&matrix, -extents.x, -extents.y);
+ _cairo_path_fixed_transform (cr->path, &matrix);
+ }
+
+ /* create a new gstate for the redirect */
+ status = _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
+ if (unlikely (status))
+ goto bail;
+
+ status = _cairo_gstate_redirect_target (cr->gstate, group_surface);
+
+bail:
+ cairo_surface_destroy (group_surface);
+ return status;
+}
+
+static cairo_pattern_t *
+_cairo_default_context_pop_group (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_surface_t *group_surface;
+ cairo_pattern_t *group_pattern;
+ cairo_matrix_t group_matrix, device_transform_matrix;
+ cairo_status_t status;
+
+ /* Verify that we are at the right nesting level */
+ if (unlikely (! _cairo_gstate_is_group (cr->gstate)))
+ return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_POP_GROUP);
+
+ /* Get a reference to the active surface before restoring */
+ group_surface = _cairo_gstate_get_target (cr->gstate);
+ group_surface = cairo_surface_reference (group_surface);
+
+ status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ group_pattern = cairo_pattern_create_for_surface (group_surface);
+ status = group_pattern->status;
+ if (unlikely (status))
+ goto done;
+
+ _cairo_gstate_get_matrix (cr->gstate, &group_matrix);
+ /* Transform by group_matrix centered around device_transform so that when
+ * we call _cairo_gstate_copy_transformed_pattern the result is a pattern
+ * with a matrix equivalent to the device_transform of group_surface. */
+ if (_cairo_surface_has_device_transform (group_surface)) {
+ cairo_pattern_set_matrix (group_pattern, &group_surface->device_transform);
+ _cairo_pattern_transform (group_pattern, &group_matrix);
+ _cairo_pattern_transform (group_pattern, &group_surface->device_transform_inverse);
+ } else {
+ cairo_pattern_set_matrix (group_pattern, &group_matrix);
+ }
+
+ /* If we have a current path, we need to adjust it to compensate for
+ * the device offset just removed. */
+ cairo_matrix_multiply (&device_transform_matrix,
+ &_cairo_gstate_get_target (cr->gstate)->device_transform,
+ &group_surface->device_transform_inverse);
+ _cairo_path_fixed_transform (cr->path, &device_transform_matrix);
+
+done:
+ cairo_surface_destroy (group_surface);
+
+ return group_pattern;
+}
+
+static cairo_status_t
+_cairo_default_context_set_source (void *abstract_cr,
+ cairo_pattern_t *source)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_source (cr->gstate, source);
+}
+
+static cairo_bool_t
+_current_source_matches_solid (const cairo_pattern_t *pattern,
+ double red,
+ double green,
+ double blue,
+ double alpha)
+{
+ cairo_color_t color;
+
+ if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
+ return FALSE;
+
+ red = _cairo_restrict_value (red, 0.0, 1.0);
+ green = _cairo_restrict_value (green, 0.0, 1.0);
+ blue = _cairo_restrict_value (blue, 0.0, 1.0);
+ alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
+
+ _cairo_color_init_rgba (&color, red, green, blue, alpha);
+ return _cairo_color_equal (&color,
+ &((cairo_solid_pattern_t *) pattern)->color);
+}
+
+static cairo_status_t
+_cairo_default_context_set_source_rgba (void *abstract_cr, double red, double green, double blue, double alpha)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_pattern_t *pattern;
+ cairo_status_t status;
+
+ if (_current_source_matches_solid (cr->gstate->source, red, green, blue, 1.))
+ return CAIRO_STATUS_SUCCESS;
+
+ /* push the current pattern to the freed lists */
+ _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
+
+ pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
+ if (unlikely (pattern->status))
+ return pattern->status;
+
+ status = _cairo_default_context_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+
+ return status;
+}
+
+static cairo_status_t
+_cairo_default_context_set_source_surface (void *abstract_cr,
+ cairo_surface_t *surface,
+ double x,
+ double y)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_pattern_t *pattern;
+ cairo_matrix_t matrix;
+ cairo_status_t status;
+
+ /* push the current pattern to the freed lists */
+ _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
+
+ pattern = cairo_pattern_create_for_surface (surface);
+ if (unlikely (pattern->status))
+ return pattern->status;
+
+ cairo_matrix_init_translate (&matrix, -x, -y);
+ cairo_pattern_set_matrix (pattern, &matrix);
+
+ status = _cairo_default_context_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+
+ return status;
+}
+
+static cairo_pattern_t *
+_cairo_default_context_get_source (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_source (cr->gstate);
+}
+
+static cairo_status_t
+_cairo_default_context_set_tolerance (void *abstract_cr,
+ double tolerance)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ if (tolerance < CAIRO_TOLERANCE_MINIMUM)
+ tolerance = CAIRO_TOLERANCE_MINIMUM;
+
+ return _cairo_gstate_set_tolerance (cr->gstate, tolerance);
+}
+
+static cairo_status_t
+_cairo_default_context_set_operator (void *abstract_cr, cairo_operator_t op)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_operator (cr->gstate, op);
+}
+
+static cairo_status_t
+_cairo_default_context_set_opacity (void *abstract_cr, double opacity)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_opacity (cr->gstate, opacity);
+}
+
+static cairo_status_t
+_cairo_default_context_set_antialias (void *abstract_cr,
+ cairo_antialias_t antialias)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_antialias (cr->gstate, antialias);
+}
+
+static cairo_status_t
+_cairo_default_context_set_fill_rule (void *abstract_cr,
+ cairo_fill_rule_t fill_rule)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
+}
+
+static cairo_status_t
+_cairo_default_context_set_line_width (void *abstract_cr,
+ double line_width)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_line_width (cr->gstate, line_width);
+}
+
+static cairo_status_t
+_cairo_default_context_set_line_cap (void *abstract_cr,
+ cairo_line_cap_t line_cap)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_line_cap (cr->gstate, line_cap);
+}
+
+static cairo_status_t
+_cairo_default_context_set_line_join (void *abstract_cr,
+ cairo_line_join_t line_join)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_line_join (cr->gstate, line_join);
+}
+
+static cairo_status_t
+_cairo_default_context_set_dash (void *abstract_cr,
+ const double *dashes,
+ int num_dashes,
+ double offset)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_dash (cr->gstate,
+ dashes, num_dashes, offset);
+}
+
+static cairo_status_t
+_cairo_default_context_set_miter_limit (void *abstract_cr,
+ double limit)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_miter_limit (cr->gstate, limit);
+}
+
+static cairo_antialias_t
+_cairo_default_context_get_antialias (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_antialias (cr->gstate);
+}
+
+static void
+_cairo_default_context_get_dash (void *abstract_cr,
+ double *dashes,
+ int *num_dashes,
+ double *offset)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_get_dash (cr->gstate, dashes, num_dashes, offset);
+}
+
+static cairo_fill_rule_t
+_cairo_default_context_get_fill_rule (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_fill_rule (cr->gstate);
+}
+
+static double
+_cairo_default_context_get_line_width (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_line_width (cr->gstate);
+}
+
+static cairo_line_cap_t
+_cairo_default_context_get_line_cap (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_line_cap (cr->gstate);
+}
+
+static cairo_line_join_t
+_cairo_default_context_get_line_join (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_line_join (cr->gstate);
+}
+
+static double
+_cairo_default_context_get_miter_limit (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_miter_limit (cr->gstate);
+}
+
+static cairo_operator_t
+_cairo_default_context_get_operator (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_operator (cr->gstate);
+}
+
+static double
+_cairo_default_context_get_opacity (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_opacity (cr->gstate);
+}
+
+static double
+_cairo_default_context_get_tolerance (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_tolerance (cr->gstate);
+}
+
+
+/* Current tranformation matrix */
+
+static cairo_status_t
+_cairo_default_context_translate (void *abstract_cr,
+ double tx,
+ double ty)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_translate (cr->gstate, tx, ty);
+}
+
+static cairo_status_t
+_cairo_default_context_scale (void *abstract_cr,
+ double sx,
+ double sy)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_scale (cr->gstate, sx, sy);
+}
+
+static cairo_status_t
+_cairo_default_context_rotate (void *abstract_cr,
+ double theta)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_rotate (cr->gstate, theta);
+}
+
+static cairo_status_t
+_cairo_default_context_transform (void *abstract_cr,
+ const cairo_matrix_t *matrix)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_transform (cr->gstate, matrix);
+}
+
+static cairo_status_t
+_cairo_default_context_set_matrix (void *abstract_cr,
+ const cairo_matrix_t *matrix)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_matrix (cr->gstate, matrix);
+}
+
+static cairo_status_t
+_cairo_default_context_set_identity_matrix (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_identity_matrix (cr->gstate);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_default_context_get_matrix (void *abstract_cr,
+ cairo_matrix_t *matrix)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_get_matrix (cr->gstate, matrix);
+}
+
+static void
+_cairo_default_context_user_to_device (void *abstract_cr,
+ double *x,
+ double *y)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_user_to_device (cr->gstate, x, y);
+}
+
+static void
+_cairo_default_context_user_to_device_distance (void *abstract_cr, double *dx, double *dy)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
+}
+
+static void
+_cairo_default_context_device_to_user (void *abstract_cr,
+ double *x,
+ double *y)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_device_to_user (cr->gstate, x, y);
+}
+
+static void
+_cairo_default_context_device_to_user_distance (void *abstract_cr,
+ double *dx,
+ double *dy)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
+}
+
+/* Path constructor */
+
+static cairo_status_t
+_cairo_default_context_new_path (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_path_fixed_fini (cr->path);
+ _cairo_path_fixed_init (cr->path);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_default_context_new_sub_path (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_path_fixed_new_sub_path (cr->path);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_default_context_move_to (void *abstract_cr, double x, double y)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_fixed_t x_fixed, y_fixed;
+
+ _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
+ x_fixed = _cairo_fixed_from_double (x);
+ y_fixed = _cairo_fixed_from_double (y);
+
+ return _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed);
+}
+
+static cairo_status_t
+_cairo_default_context_line_to (void *abstract_cr, double x, double y)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_fixed_t x_fixed, y_fixed;
+
+ _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
+ x_fixed = _cairo_fixed_from_double (x);
+ y_fixed = _cairo_fixed_from_double (y);
+
+ return _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
+}
+
+static cairo_status_t
+_cairo_default_context_curve_to (void *abstract_cr,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_fixed_t x1_fixed, y1_fixed;
+ cairo_fixed_t x2_fixed, y2_fixed;
+ cairo_fixed_t x3_fixed, y3_fixed;
+
+ _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
+ _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
+ _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
+
+ x1_fixed = _cairo_fixed_from_double (x1);
+ y1_fixed = _cairo_fixed_from_double (y1);
+
+ x2_fixed = _cairo_fixed_from_double (x2);
+ y2_fixed = _cairo_fixed_from_double (y2);
+
+ x3_fixed = _cairo_fixed_from_double (x3);
+ y3_fixed = _cairo_fixed_from_double (y3);
+
+ return _cairo_path_fixed_curve_to (cr->path,
+ x1_fixed, y1_fixed,
+ x2_fixed, y2_fixed,
+ x3_fixed, y3_fixed);
+}
+
+static cairo_status_t
+_cairo_default_context_arc (void *abstract_cr,
+ double xc, double yc, double radius,
+ double angle1, double angle2,
+ cairo_bool_t forward)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_status_t status;
+
+ /* Do nothing, successfully, if radius is <= 0 */
+ if (radius <= 0.0) {
+ cairo_fixed_t x_fixed, y_fixed;
+
+ _cairo_gstate_user_to_backend (cr->gstate, &xc, &yc);
+ x_fixed = _cairo_fixed_from_double (xc);
+ y_fixed = _cairo_fixed_from_double (yc);
+ status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
+ if (unlikely (status))
+ return status;
+
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ status = _cairo_default_context_line_to (cr,
+ xc + radius * cos (angle1),
+ yc + radius * sin (angle1));
+
+ if (unlikely (status))
+ return status;
+
+ if (forward)
+ _cairo_arc_path (&cr->base, xc, yc, radius, angle1, angle2);
+ else
+ _cairo_arc_path_negative (&cr->base, xc, yc, radius, angle1, angle2);
+
+ return CAIRO_STATUS_SUCCESS; /* any error will have already been set on cr */
+}
+
+static cairo_status_t
+_cairo_default_context_rel_move_to (void *abstract_cr, double dx, double dy)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_fixed_t dx_fixed, dy_fixed;
+
+ _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
+
+ dx_fixed = _cairo_fixed_from_double (dx);
+ dy_fixed = _cairo_fixed_from_double (dy);
+
+ return _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed);
+}
+
+static cairo_status_t
+_cairo_default_context_rel_line_to (void *abstract_cr, double dx, double dy)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_fixed_t dx_fixed, dy_fixed;
+
+ _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
+
+ dx_fixed = _cairo_fixed_from_double (dx);
+ dy_fixed = _cairo_fixed_from_double (dy);
+
+ return _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed);
+}
+
+
+static cairo_status_t
+_cairo_default_context_rel_curve_to (void *abstract_cr,
+ double dx1, double dy1,
+ double dx2, double dy2,
+ double dx3, double dy3)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_fixed_t dx1_fixed, dy1_fixed;
+ cairo_fixed_t dx2_fixed, dy2_fixed;
+ cairo_fixed_t dx3_fixed, dy3_fixed;
+
+ _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1);
+ _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2);
+ _cairo_gstate_user_to_device_distance (cr->gstate, &dx3, &dy3);
+
+ dx1_fixed = _cairo_fixed_from_double (dx1);
+ dy1_fixed = _cairo_fixed_from_double (dy1);
+
+ dx2_fixed = _cairo_fixed_from_double (dx2);
+ dy2_fixed = _cairo_fixed_from_double (dy2);
+
+ dx3_fixed = _cairo_fixed_from_double (dx3);
+ dy3_fixed = _cairo_fixed_from_double (dy3);
+
+ return _cairo_path_fixed_rel_curve_to (cr->path,
+ dx1_fixed, dy1_fixed,
+ dx2_fixed, dy2_fixed,
+ dx3_fixed, dy3_fixed);
+}
+
+static cairo_status_t
+_cairo_default_context_close_path (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_path_fixed_close_path (cr->path);
+}
+
+static cairo_status_t
+_cairo_default_context_rectangle (void *abstract_cr,
+ double x, double y,
+ double width, double height)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_status_t status;
+
+ status = _cairo_default_context_move_to (cr, x, y);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rel_line_to (cr, width, 0);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rel_line_to (cr, 0, height);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rel_line_to (cr, -width, 0);
+ if (unlikely (status))
+ return status;
+
+ return _cairo_default_context_close_path (cr);
+}
+
+static void
+_cairo_default_context_path_extents (void *abstract_cr,
+ double *x1,
+ double *y1,
+ double *x2,
+ double *y2)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_path_extents (cr->gstate,
+ cr->path,
+ x1, y1, x2, y2);
+}
+
+static cairo_bool_t
+_cairo_default_context_has_current_point (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return cr->path->has_current_point;
+}
+
+static cairo_bool_t
+_cairo_default_context_get_current_point (void *abstract_cr,
+ double *x,
+ double *y)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_fixed_t x_fixed, y_fixed;
+
+ if (_cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed))
+ {
+ *x = _cairo_fixed_to_double (x_fixed);
+ *y = _cairo_fixed_to_double (y_fixed);
+ _cairo_gstate_backend_to_user (cr->gstate, x, y);
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static cairo_path_t *
+_cairo_default_context_copy_path (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_path_create (cr->path, &cr->base);
+}
+
+static cairo_path_t *
+_cairo_default_context_copy_path_flat (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_path_create_flat (cr->path, &cr->base);
+}
+
+static cairo_status_t
+_cairo_default_context_append_path (void *abstract_cr,
+ const cairo_path_t *path)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_path_append_to_context (path, &cr->base);
+}
+
+static cairo_status_t
+_cairo_default_context_paint (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_paint (cr->gstate);
+}
+
+static cairo_status_t
+_cairo_default_context_paint_with_alpha (void *abstract_cr,
+ double alpha)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_solid_pattern_t pattern;
+ cairo_status_t status;
+ cairo_color_t color;
+
+ if (CAIRO_ALPHA_IS_OPAQUE (alpha))
+ return _cairo_gstate_paint (cr->gstate);
+
+ if (CAIRO_ALPHA_IS_ZERO (alpha) &&
+ _cairo_operator_bounded_by_mask (cr->gstate->op)) {
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ _cairo_color_init_rgba (&color, 0., 0., 0., alpha);
+ _cairo_pattern_init_solid (&pattern, &color);
+
+ status = _cairo_gstate_mask (cr->gstate, &pattern.base);
+ _cairo_pattern_fini (&pattern.base);
+
+ return status;
+}
+
+static cairo_status_t
+_cairo_default_context_mask (void *abstract_cr,
+ cairo_pattern_t *mask)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_mask (cr->gstate, mask);
+}
+
+static cairo_status_t
+_cairo_default_context_stroke_preserve (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_stroke (cr->gstate, cr->path);
+}
+
+static cairo_status_t
+_cairo_default_context_stroke (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_status_t status;
+
+ status = _cairo_gstate_stroke (cr->gstate, cr->path);
+ if (unlikely (status))
+ return status;
+
+ return _cairo_default_context_new_path (cr);
+}
+
+static cairo_status_t
+_cairo_default_context_in_stroke (void *abstract_cr,
+ double x, double y,
+ cairo_bool_t *inside)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_in_stroke (cr->gstate,
+ cr->path,
+ x, y,
+ inside);
+}
+
+static cairo_status_t
+_cairo_default_context_stroke_extents (void *abstract_cr,
+ double *x1, double *y1, double *x2, double *y2)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_stroke_extents (cr->gstate,
+ cr->path,
+ x1, y1, x2, y2);
+}
+
+static cairo_status_t
+_cairo_default_context_fill_preserve (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_fill (cr->gstate, cr->path);
+}
+
+static cairo_status_t
+_cairo_default_context_fill (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_status_t status;
+
+ status = _cairo_gstate_fill (cr->gstate, cr->path);
+ if (unlikely (status))
+ return status;
+
+ return _cairo_default_context_new_path (cr);
+}
+
+static cairo_status_t
+_cairo_default_context_in_fill (void *abstract_cr,
+ double x, double y,
+ cairo_bool_t *inside)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ *inside = _cairo_gstate_in_fill (cr->gstate,
+ cr->path,
+ x, y);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_default_context_fill_extents (void *abstract_cr,
+ double *x1, double *y1, double *x2, double *y2)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_fill_extents (cr->gstate,
+ cr->path,
+ x1, y1, x2, y2);
+}
+
+static cairo_status_t
+_cairo_default_context_clip_preserve (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_clip (cr->gstate, cr->path);
+}
+
+static cairo_status_t
+_cairo_default_context_clip (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_status_t status;
+
+ status = _cairo_gstate_clip (cr->gstate, cr->path);
+ if (unlikely (status))
+ return status;
+
+ return _cairo_default_context_new_path (cr);
+}
+
+static cairo_status_t
+_cairo_default_context_in_clip (void *abstract_cr,
+ double x, double y,
+ cairo_bool_t *inside)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ *inside = _cairo_gstate_in_clip (cr->gstate, x, y);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_default_context_reset_clip (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_reset_clip (cr->gstate);
+}
+
+static cairo_status_t
+_cairo_default_context_clip_extents (void *abstract_cr,
+ double *x1, double *y1, double *x2, double *y2)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ if (! _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2)) {
+ *x1 = -INFINITY;
+ *y1 = -INFINITY;
+ *x2 = +INFINITY;
+ *y2 = +INFINITY;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_rectangle_list_t *
+_cairo_default_context_copy_clip_rectangle_list (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_copy_clip_rectangle_list (cr->gstate);
+}
+
+static cairo_status_t
+_cairo_default_context_copy_page (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_copy_page (cr->gstate);
+}
+
+static cairo_status_t
+_cairo_default_context_show_page (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_show_page (cr->gstate);
+}
+
+static cairo_status_t
+_cairo_default_context_set_font_face (void *abstract_cr,
+ cairo_font_face_t *font_face)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_font_face (cr->gstate, font_face);
+}
+
+static cairo_font_face_t *
+_cairo_default_context_get_font_face (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_font_face_t *font_face;
+ cairo_status_t status;
+
+ status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
+ if (unlikely (status)) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *) &_cairo_font_face_nil;
+ }
+
+ return font_face;
+}
+
+static cairo_status_t
+_cairo_default_context_font_extents (void *abstract_cr,
+ cairo_font_extents_t *extents)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_get_font_extents (cr->gstate, extents);
+}
+
+static cairo_status_t
+_cairo_default_context_set_font_size (void *abstract_cr,
+ double size)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_font_size (cr->gstate, size);
+}
+
+static cairo_status_t
+_cairo_default_context_set_font_matrix (void *abstract_cr,
+ const cairo_matrix_t *matrix)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_set_font_matrix (cr->gstate, matrix);
+}
+
+static void
+_cairo_default_context_get_font_matrix (void *abstract_cr,
+ cairo_matrix_t *matrix)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_get_font_matrix (cr->gstate, matrix);
+}
+
+static cairo_status_t
+_cairo_default_context_set_font_options (void *abstract_cr,
+ const cairo_font_options_t *options)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_set_font_options (cr->gstate, options);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_default_context_get_font_options (void *abstract_cr,
+ cairo_font_options_t *options)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ _cairo_gstate_get_font_options (cr->gstate, options);
+}
+
+static cairo_status_t
+_cairo_default_context_set_scaled_font (void *abstract_cr,
+ cairo_scaled_font_t *scaled_font)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_bool_t was_previous;
+ cairo_status_t status;
+
+ if (scaled_font == cr->gstate->scaled_font)
+ return CAIRO_STATUS_SUCCESS;
+
+ was_previous = scaled_font == cr->gstate->previous_scaled_font;
+
+ status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix);
+ if (unlikely (status))
+ return status;
+
+ _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options);
+
+ if (was_previous)
+ cr->gstate->scaled_font = cairo_scaled_font_reference (scaled_font);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_scaled_font_t *
+_cairo_default_context_get_scaled_font (void *abstract_cr)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_scaled_font_t *scaled_font;
+ cairo_status_t status;
+
+ status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
+ if (unlikely (status))
+ return _cairo_scaled_font_create_in_error (status);
+
+ return scaled_font;
+}
+
+static cairo_status_t
+_cairo_default_context_glyphs (void *abstract_cr,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_glyph_text_info_t *info)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_show_text_glyphs (cr->gstate, glyphs, num_glyphs, info);
+}
+
+static cairo_status_t
+_cairo_default_context_glyph_path (void *abstract_cr,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_glyph_path (cr->gstate,
+ glyphs, num_glyphs,
+ cr->path);
+}
+
+static cairo_status_t
+_cairo_default_context_glyph_extents (void *abstract_cr,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents)
+{
+ cairo_default_context_t *cr = abstract_cr;
+
+ return _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents);
+}
+
+static const cairo_backend_t _cairo_default_context_backend = {
+ CAIRO_TYPE_DEFAULT,
+ _cairo_default_context_destroy,
+
+ _cairo_default_context_get_original_target,
+ _cairo_default_context_get_current_target,
+
+ _cairo_default_context_save,
+ _cairo_default_context_restore,
+
+ _cairo_default_context_push_group,
+ _cairo_default_context_pop_group,
+
+ _cairo_default_context_set_source_rgba,
+ _cairo_default_context_set_source_surface,
+ _cairo_default_context_set_source,
+ _cairo_default_context_get_source,
+
+ _cairo_default_context_set_antialias,
+ _cairo_default_context_set_dash,
+ _cairo_default_context_set_fill_rule,
+ _cairo_default_context_set_line_cap,
+ _cairo_default_context_set_line_join,
+ _cairo_default_context_set_line_width,
+ _cairo_default_context_set_miter_limit,
+ _cairo_default_context_set_opacity,
+ _cairo_default_context_set_operator,
+ _cairo_default_context_set_tolerance,
+ _cairo_default_context_get_antialias,
+ _cairo_default_context_get_dash,
+ _cairo_default_context_get_fill_rule,
+ _cairo_default_context_get_line_cap,
+ _cairo_default_context_get_line_join,
+ _cairo_default_context_get_line_width,
+ _cairo_default_context_get_miter_limit,
+ _cairo_default_context_get_opacity,
+ _cairo_default_context_get_operator,
+ _cairo_default_context_get_tolerance,
+
+ _cairo_default_context_translate,
+ _cairo_default_context_scale,
+ _cairo_default_context_rotate,
+ _cairo_default_context_transform,
+ _cairo_default_context_set_matrix,
+ _cairo_default_context_set_identity_matrix,
+ _cairo_default_context_get_matrix,
+ _cairo_default_context_user_to_device,
+ _cairo_default_context_user_to_device_distance,
+ _cairo_default_context_device_to_user,
+ _cairo_default_context_device_to_user_distance,
+
+ _cairo_default_context_new_path,
+ _cairo_default_context_new_sub_path,
+ _cairo_default_context_move_to,
+ _cairo_default_context_rel_move_to,
+ _cairo_default_context_line_to,
+ _cairo_default_context_rel_line_to,
+ _cairo_default_context_curve_to,
+ _cairo_default_context_rel_curve_to,
+ NULL, /* arc-to */
+ NULL, /* rel-arc-to */
+ _cairo_default_context_close_path,
+ _cairo_default_context_arc,
+ _cairo_default_context_rectangle,
+ _cairo_default_context_path_extents,
+ _cairo_default_context_has_current_point,
+ _cairo_default_context_get_current_point,
+ _cairo_default_context_copy_path,
+ _cairo_default_context_copy_path_flat,
+ _cairo_default_context_append_path,
+
+ NULL, /* stroke-to-path */
+
+ _cairo_default_context_clip,
+ _cairo_default_context_clip_preserve,
+ _cairo_default_context_in_clip,
+ _cairo_default_context_clip_extents,
+ _cairo_default_context_reset_clip,
+ _cairo_default_context_copy_clip_rectangle_list,
+
+ _cairo_default_context_paint,
+ _cairo_default_context_paint_with_alpha,
+ _cairo_default_context_mask,
+
+ _cairo_default_context_stroke,
+ _cairo_default_context_stroke_preserve,
+ _cairo_default_context_in_stroke,
+ _cairo_default_context_stroke_extents,
+
+ _cairo_default_context_fill,
+ _cairo_default_context_fill_preserve,
+ _cairo_default_context_in_fill,
+ _cairo_default_context_fill_extents,
+
+ _cairo_default_context_set_font_face,
+ _cairo_default_context_get_font_face,
+ _cairo_default_context_set_font_size,
+ _cairo_default_context_set_font_matrix,
+ _cairo_default_context_get_font_matrix,
+ _cairo_default_context_set_font_options,
+ _cairo_default_context_get_font_options,
+ _cairo_default_context_set_scaled_font,
+ _cairo_default_context_get_scaled_font,
+ _cairo_default_context_font_extents,
+
+ _cairo_default_context_glyphs,
+ _cairo_default_context_glyph_path,
+ _cairo_default_context_glyph_extents,
+
+ _cairo_default_context_copy_page,
+ _cairo_default_context_show_page,
+};
+
+cairo_t *
+_cairo_default_context_create (void *target)
+{
+ cairo_default_context_t *cr;
+ cairo_status_t status;
+
+ cr = _freed_pool_get (&context_pool);
+ if (unlikely (cr == NULL)) {
+ cr = malloc (sizeof (cairo_default_context_t));
+ if (unlikely (cr == NULL))
+ return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+
+ _cairo_init (&cr->base, &_cairo_default_context_backend);
+ _cairo_path_fixed_init (cr->path);
+
+ cr->gstate = &cr->gstate_tail[0];
+ cr->gstate_freelist = &cr->gstate_tail[1];
+ cr->gstate_tail[1].next = NULL;
+
+ status = _cairo_gstate_init (cr->gstate, target);
+ if (unlikely (status)) {
+ _freed_pool_put (&context_pool, cr);
+ return _cairo_create_in_error (status);
+ }
+
+ return &cr->base;
+}
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index fc7509c1..3de01683 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -39,6 +39,7 @@
#include "cairo-directfb.h"
#include "cairo-clip-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include <pixman.h>
@@ -1827,6 +1828,8 @@ _cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
static cairo_surface_backend_t
_cairo_directfb_surface_backend = {
CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
+ _cairo_default_context_create,
+
_cairo_directfb_surface_create_similar,/*create_similar*/
_cairo_directfb_surface_finish, /*finish*/
_cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 813e3542..eb317f0b 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -41,6 +41,7 @@
#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"
@@ -1839,6 +1840,8 @@ _cairo_gl_surface_fill (void *abstract_surface,
const cairo_surface_backend_t _cairo_gl_surface_backend = {
CAIRO_SURFACE_TYPE_GL,
+ _cairo_default_context_create,
+
_cairo_gl_surface_create_similar,
_cairo_gl_surface_finish,
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
index f1e03b37..9e823fa0 100644
--- a/src/cairo-gstate-private.h
+++ b/src/cairo-gstate-private.h
@@ -41,6 +41,7 @@
struct _cairo_gstate {
cairo_operator_t op;
+ double opacity;
double tolerance;
cairo_antialias_t antialias;
@@ -115,6 +116,12 @@ cairo_private cairo_operator_t
_cairo_gstate_get_operator (cairo_gstate_t *gstate);
cairo_private cairo_status_t
+_cairo_gstate_set_opacity (cairo_gstate_t *gstate, double opacity);
+
+cairo_private double
+_cairo_gstate_get_opacity (cairo_gstate_t *gstate);
+
+cairo_private cairo_status_t
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance);
cairo_private double
@@ -289,10 +296,16 @@ cairo_private cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate);
cairo_private cairo_status_t
-_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
- const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight);
+_cairo_gstate_show_surface (cairo_gstate_t *gstate,
+ cairo_surface_t *surface,
+ double x,
+ double y,
+ double width,
+ double height);
+
+cairo_private cairo_status_t
+_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
+ double size);
cairo_private void
_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
@@ -327,18 +340,6 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_font_face_t *font_face);
cairo_private cairo_status_t
-_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
- double x,
- double y,
- const char *utf8,
- int utf8_len,
- cairo_glyph_t **glyphs,
- int *num_glyphs,
- cairo_text_cluster_t **clusters,
- int *num_clusters,
- cairo_text_cluster_flags_t *cluster_flags);
-
-cairo_private cairo_status_t
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
@@ -346,13 +347,9 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
cairo_private cairo_status_t
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
- const char *utf8,
- int utf8_len,
const cairo_glyph_t *glyphs,
int num_glyphs,
- const cairo_text_cluster_t *clusters,
- int num_clusters,
- cairo_text_cluster_flags_t cluster_flags);
+ cairo_glyph_text_info_t *info);
cairo_private cairo_status_t
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index d9672c22..7aea6c1d 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -91,6 +91,7 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
gstate->next = NULL;
gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
+ gstate->opacity = 1.;
gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
gstate->antialias = CAIRO_ANTIALIAS_DEFAULT;
@@ -147,6 +148,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t)));
gstate->op = other->op;
+ gstate->opacity = other->opacity;
gstate->tolerance = other->tolerance;
gstate->antialias = other->antialias;
@@ -429,6 +431,20 @@ _cairo_gstate_get_operator (cairo_gstate_t *gstate)
}
cairo_status_t
+_cairo_gstate_set_opacity (cairo_gstate_t *gstate, double op)
+{
+ gstate->opacity = op;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+double
+_cairo_gstate_get_opacity (cairo_gstate_t *gstate)
+{
+ return gstate->opacity;
+}
+
+cairo_status_t
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance)
{
gstate->tolerance = tolerance;
@@ -1066,6 +1082,8 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
if (_clipped (gstate))
return CAIRO_STATUS_SUCCESS;
+ assert (gstate->opacity == 1.0);
+
if (_cairo_pattern_is_opaque (mask, NULL))
return _cairo_gstate_paint (gstate);
@@ -1143,6 +1161,8 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (_clipped (gstate))
return CAIRO_STATUS_SUCCESS;
+ assert (gstate->opacity == 1.0);
+
memcpy (&style, &gstate->stroke_style, sizeof (gstate->stroke_style));
if (_cairo_stroke_style_dash_can_approximate (&gstate->stroke_style, &gstate->ctm, gstate->tolerance)) {
style.dash = dash;
@@ -1243,6 +1263,8 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (_clipped (gstate))
return CAIRO_STATUS_SUCCESS;
+ assert (gstate->opacity == 1.0);
+
if (_cairo_path_fixed_fill_is_empty (path)) {
if (_cairo_operator_bounded_by_mask (gstate->op))
return CAIRO_STATUS_SUCCESS;
@@ -1580,22 +1602,14 @@ _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate)
}
cairo_status_t
-_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
- const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight)
+_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
+ double size)
{
- cairo_font_face_t *font_face;
- cairo_status_t status;
-
- font_face = cairo_toy_font_face_create (family, slant, weight);
- if (font_face->status)
- return font_face->status;
+ _cairo_gstate_unset_scaled_font (gstate);
- status = _cairo_gstate_set_font_face (gstate, font_face);
- cairo_font_face_destroy (font_face);
+ cairo_matrix_init_scale (&gstate->font_matrix, size, size);
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@@ -1810,31 +1824,6 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
}
cairo_status_t
-_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
- double x,
- double y,
- const char *utf8,
- int utf8_len,
- cairo_glyph_t **glyphs,
- int *num_glyphs,
- cairo_text_cluster_t **clusters,
- int *num_clusters,
- cairo_text_cluster_flags_t *cluster_flags)
-{
- cairo_status_t status;
-
- status = _cairo_gstate_ensure_scaled_font (gstate);
- if (unlikely (status))
- return status;
-
- return cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
- utf8, utf8_len,
- glyphs, num_glyphs,
- clusters, num_clusters,
- cluster_flags);
-}
-
-cairo_status_t
_cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_font_face_t *font_face)
{
@@ -1873,20 +1862,16 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
- const char *utf8,
- int utf8_len,
const cairo_glyph_t *glyphs,
int num_glyphs,
- const cairo_text_cluster_t *clusters,
- int num_clusters,
- cairo_text_cluster_flags_t cluster_flags)
+ cairo_glyph_text_info_t *info)
{
cairo_pattern_union_t source_pattern;
const cairo_pattern_t *pattern;
cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
cairo_glyph_t *transformed_glyphs;
cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
- cairo_text_cluster_t *transformed_clusters;
+ cairo_text_cluster_t *transformed_clusters = NULL;
cairo_operator_t op;
cairo_status_t status;
cairo_clip_t clip;
@@ -1906,8 +1891,6 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
return status;
transformed_glyphs = stack_transformed_glyphs;
- transformed_clusters = stack_transformed_clusters;
-
if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) {
transformed_glyphs = cairo_glyph_allocate (num_glyphs);
if (unlikely (transformed_glyphs == NULL)) {
@@ -1916,26 +1899,32 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
}
}
- /* Just in case */
- if (!clusters)
- num_clusters = 0;
-
- if (num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
- transformed_clusters = cairo_text_cluster_allocate (num_clusters);
- if (unlikely (transformed_clusters == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP_GLYPHS;
+ if (info != NULL) {
+ transformed_clusters = stack_transformed_clusters;
+ if (info->num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
+ transformed_clusters = cairo_text_cluster_allocate (info->num_clusters);
+ if (unlikely (transformed_clusters == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto CLEANUP_GLYPHS;
+ }
}
- }
- status = _cairo_gstate_transform_glyphs_to_backend (gstate,
- glyphs, num_glyphs,
- clusters,
- num_clusters,
- cluster_flags,
- transformed_glyphs,
- &num_glyphs,
- transformed_clusters);
+ status = _cairo_gstate_transform_glyphs_to_backend (gstate,
+ glyphs, num_glyphs,
+ info->clusters,
+ info->num_clusters,
+ info->cluster_flags,
+ transformed_glyphs,
+ &num_glyphs,
+ transformed_clusters);
+ } else {
+ status = _cairo_gstate_transform_glyphs_to_backend (gstate,
+ glyphs, num_glyphs,
+ NULL, 0, 0,
+ transformed_glyphs,
+ &num_glyphs,
+ NULL);
+ }
if (status || num_glyphs == 0)
goto CLEANUP_GLYPHS;
@@ -1961,13 +1950,22 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
if (cairo_surface_has_show_text_glyphs (gstate->target) ||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240)
{
- status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
- utf8, utf8_len,
- transformed_glyphs, num_glyphs,
- transformed_clusters, num_clusters,
- cluster_flags,
- gstate->scaled_font,
- _gstate_get_clip (gstate, &clip));
+ if (info != NULL) {
+ status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
+ info->utf8, info->utf8_len,
+ transformed_glyphs, num_glyphs,
+ transformed_clusters, info->num_clusters,
+ info->cluster_flags,
+ gstate->scaled_font,
+ _gstate_get_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));
+ }
}
else
{
@@ -2028,7 +2026,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
glyphs, num_glyphs,
NULL, 0, 0,
transformed_glyphs,
- NULL, NULL);
+ &num_glyphs, NULL);
if (unlikely (status))
goto CLEANUP_GLYPHS;
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 2c538d5f..71d8d884 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -42,6 +42,7 @@
#include "cairo-boxes-private.h"
#include "cairo-clip-private.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-region-private.h"
#include "cairo-scaled-font-private.h"
@@ -4601,6 +4602,8 @@ _cairo_surface_is_image (const cairo_surface_t *surface)
const cairo_surface_backend_t _cairo_image_surface_backend = {
CAIRO_SURFACE_TYPE_IMAGE,
+ _cairo_default_context_create,
+
_cairo_image_surface_create_similar,
_cairo_image_surface_finish,
_cairo_image_surface_acquire_source_image,
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index b9758281..c8a54583 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -39,6 +39,7 @@
#include "cairoint.h"
#include "cairo-os2-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#if CAIRO_HAS_FC_FONT
@@ -1438,6 +1439,8 @@ _cairo_os2_surface_mark_dirty_rectangle (void *surface,
static const cairo_surface_backend_t cairo_os2_surface_backend = {
CAIRO_SURFACE_TYPE_OS2,
+ _cairo_default_context_create,
+
NULL, /* create_similar */
_cairo_os2_surface_finish,
_cairo_os2_surface_acquire_source_image,
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 9e65f7ba..74c8468e 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -641,8 +641,17 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
return _cairo_surface_snapshot (other->recording_surface);
}
+static cairo_t *
+_cairo_paginated_context_create (void *target)
+{
+ cairo_paginated_surface_t *surface = target;
+ return cairo_create (surface->recording_surface);
+}
+
static const cairo_surface_backend_t cairo_paginated_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
+ _cairo_paginated_context_create,
+
_cairo_paginated_surface_create_similar,
_cairo_paginated_surface_finish,
_cairo_paginated_surface_acquire_source_image,
diff --git a/src/cairo-path-private.h b/src/cairo-path-private.h
index 61b4060f..7b54317e 100644
--- a/src/cairo-path-private.h
+++ b/src/cairo-path-private.h
@@ -41,11 +41,11 @@
cairo_private cairo_path_t *
_cairo_path_create (cairo_path_fixed_t *path,
- cairo_gstate_t *gstate);
+ cairo_t *cr);
cairo_private cairo_path_t *
_cairo_path_create_flat (cairo_path_fixed_t *path,
- cairo_gstate_t *gstate);
+ cairo_t *cr);
cairo_private cairo_path_t *
_cairo_path_create_in_error (cairo_status_t status);
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 522f1ab2..6b0df9cc 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -1382,7 +1382,7 @@ BAIL:
return status;
}
-cairo_status_t
+cairo_int_status_t
_cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
@@ -1390,7 +1390,7 @@ _cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
double tolerance,
cairo_traps_t *traps)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_polygon_t polygon;
/* Before we do anything else, we attempt the rectilinear
diff --git a/src/cairo-path.c b/src/cairo-path.c
index bc5b731b..16447a4d 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -138,7 +138,7 @@ _cairo_path_count (cairo_path_t *path,
/* Closure for path interpretation. */
typedef struct cairo_path_populate {
cairo_path_data_t *data;
- cairo_gstate_t *gstate;
+ cairo_t *cr;
} cpp_t;
static cairo_status_t
@@ -152,7 +152,7 @@ _cpp_move_to (void *closure,
x = _cairo_fixed_to_double (point->x);
y = _cairo_fixed_to_double (point->y);
- _cairo_gstate_backend_to_user (cpp->gstate, &x, &y);
+ cairo_device_to_user (cpp->cr, &x, &y);
data->header.type = CAIRO_PATH_MOVE_TO;
data->header.length = 2;
@@ -177,7 +177,7 @@ _cpp_line_to (void *closure,
x = _cairo_fixed_to_double (point->x);
y = _cairo_fixed_to_double (point->y);
- _cairo_gstate_backend_to_user (cpp->gstate, &x, &y);
+ cairo_device_to_user (cpp->cr, &x, &y);
data->header.type = CAIRO_PATH_LINE_TO;
data->header.length = 2;
@@ -205,15 +205,15 @@ _cpp_curve_to (void *closure,
x1 = _cairo_fixed_to_double (p1->x);
y1 = _cairo_fixed_to_double (p1->y);
- _cairo_gstate_backend_to_user (cpp->gstate, &x1, &y1);
+ cairo_device_to_user (cpp->cr, &x1, &y1);
x2 = _cairo_fixed_to_double (p2->x);
y2 = _cairo_fixed_to_double (p2->y);
- _cairo_gstate_backend_to_user (cpp->gstate, &x2, &y2);
+ cairo_device_to_user (cpp->cr, &x2, &y2);
x3 = _cairo_fixed_to_double (p3->x);
y3 = _cairo_fixed_to_double (p3->y);
- _cairo_gstate_backend_to_user (cpp->gstate, &x3, &y3);
+ cairo_device_to_user (cpp->cr, &x3, &y3);
data->header.type = CAIRO_PATH_CURVE_TO;
data->header.length = 4;
@@ -250,23 +250,22 @@ _cpp_close_path (void *closure)
static cairo_status_t
_cairo_path_populate (cairo_path_t *path,
cairo_path_fixed_t *path_fixed,
- cairo_gstate_t *gstate,
+ cairo_t *cr,
cairo_bool_t flatten)
{
cairo_status_t status;
cpp_t cpp;
cpp.data = path->data;
- cpp.gstate = gstate;
+ cpp.cr = cr;
if (flatten) {
- double tolerance = _cairo_gstate_get_tolerance (gstate);
status = _cairo_path_fixed_interpret_flat (path_fixed,
_cpp_move_to,
_cpp_line_to,
_cpp_close_path,
&cpp,
- tolerance);
+ cairo_get_tolerance (cr));
} else {
status = _cairo_path_fixed_interpret (path_fixed,
_cpp_move_to,
@@ -309,7 +308,7 @@ _cairo_path_create_in_error (cairo_status_t status)
static cairo_path_t *
_cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
- cairo_gstate_t *gstate,
+ cairo_t *cr,
cairo_bool_t flatten)
{
cairo_path_t *path;
@@ -321,7 +320,7 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
}
path->num_data = _cairo_path_count (path, path_fixed,
- _cairo_gstate_get_tolerance (gstate),
+ cairo_get_tolerance (cr),
flatten);
if (path->num_data < 0) {
free (path);
@@ -337,8 +336,7 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
return (cairo_path_t*) &_cairo_path_nil;
}
- path->status = _cairo_path_populate (path, path_fixed,
- gstate, flatten);
+ path->status = _cairo_path_populate (path, path_fixed, cr, flatten);
} else {
path->data = NULL;
path->status = CAIRO_STATUS_SUCCESS;
@@ -377,10 +375,10 @@ slim_hidden_def (cairo_path_destroy);
/**
* _cairo_path_create:
* @path: a fixed-point, device-space path to be converted and copied
- * @gstate: the current graphics state
+ * @cr: the current graphics context
*
* Creates a user-space #cairo_path_t copy of the given device-space
- * @path. The @gstate parameter provides the inverse CTM for the
+ * @path. The @cr parameter provides the inverse CTM for the
* conversion.
*
* Return value: the new copy of the path. If there is insufficient
@@ -389,19 +387,19 @@ slim_hidden_def (cairo_path_destroy);
* data==%NULL.
**/
cairo_path_t *
-_cairo_path_create (cairo_path_fixed_t *path,
- cairo_gstate_t *gstate)
+_cairo_path_create (cairo_path_fixed_t *path,
+ cairo_t *cr)
{
- return _cairo_path_create_internal (path, gstate, FALSE);
+ return _cairo_path_create_internal (path, cr, FALSE);
}
/**
* _cairo_path_create_flat:
* @path: a fixed-point, device-space path to be flattened, converted and copied
- * @gstate: the current graphics state
+ * @cr: the current graphics context
*
* Creates a flattened, user-space #cairo_path_t copy of the given
- * device-space @path. The @gstate parameter provide the inverse CTM
+ * device-space @path. The @cr parameter provide the inverse CTM
* for the conversion, as well as the tolerance value to control the
* accuracy of the flattening.
*
@@ -412,9 +410,9 @@ _cairo_path_create (cairo_path_fixed_t *path,
**/
cairo_path_t *
_cairo_path_create_flat (cairo_path_fixed_t *path,
- cairo_gstate_t *gstate)
+ cairo_t *cr)
{
- return _cairo_path_create_internal (path, gstate, TRUE);
+ return _cairo_path_create_internal (path, cr, TRUE);
}
/**
@@ -432,17 +430,6 @@ _cairo_path_append_to_context (const cairo_path_t *path,
cairo_t *cr)
{
const cairo_path_data_t *p, *end;
- cairo_fixed_t x1_fixed, y1_fixed;
- cairo_fixed_t x2_fixed, y2_fixed;
- cairo_fixed_t x3_fixed, y3_fixed;
- cairo_matrix_t user_to_backend;
- cairo_status_t status;
- double x, y;
-
- user_to_backend = cr->gstate->ctm;
- cairo_matrix_multiply (&user_to_backend,
- &user_to_backend,
- &cr->gstate->target->device_transform);
end = &path->data[path->num_data];
for (p = &path->data[0]; p < end; p += p->header.length) {
@@ -451,64 +438,39 @@ _cairo_path_append_to_context (const cairo_path_t *path,
if (unlikely (p->header.length < 2))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- x = p[1].point.x, y = p[1].point.y;
- cairo_matrix_transform_point (&user_to_backend, &x, &y);
- x1_fixed = _cairo_fixed_from_double (x);
- y1_fixed = _cairo_fixed_from_double (y);
-
- status = _cairo_path_fixed_move_to (cr->path, x1_fixed, y1_fixed);
+ cairo_move_to (cr, p[1].point.x, p[1].point.y);
break;
case CAIRO_PATH_LINE_TO:
if (unlikely (p->header.length < 2))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- x = p[1].point.x, y = p[1].point.y;
- cairo_matrix_transform_point (&user_to_backend, &x, &y);
- x1_fixed = _cairo_fixed_from_double (x);
- y1_fixed = _cairo_fixed_from_double (y);
-
- status = _cairo_path_fixed_line_to (cr->path, x1_fixed, y1_fixed);
+ cairo_line_to (cr, p[1].point.x, p[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
if (unlikely (p->header.length < 4))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- x = p[1].point.x, y = p[1].point.y;
- cairo_matrix_transform_point (&user_to_backend, &x, &y);
- x1_fixed = _cairo_fixed_from_double (x);
- y1_fixed = _cairo_fixed_from_double (y);
-
- x = p[2].point.x, y = p[2].point.y;
- cairo_matrix_transform_point (&user_to_backend, &x, &y);
- x2_fixed = _cairo_fixed_from_double (x);
- y2_fixed = _cairo_fixed_from_double (y);
-
- x = p[3].point.x, y = p[3].point.y;
- cairo_matrix_transform_point (&user_to_backend, &x, &y);
- x3_fixed = _cairo_fixed_from_double (x);
- y3_fixed = _cairo_fixed_from_double (y);
-
- status = _cairo_path_fixed_curve_to (cr->path,
- x1_fixed, y1_fixed,
- x2_fixed, y2_fixed,
- x3_fixed, y3_fixed);
+ cairo_curve_to (cr,
+ p[1].point.x, p[1].point.y,
+ p[2].point.x, p[2].point.y,
+ p[3].point.x, p[3].point.y);
break;
case CAIRO_PATH_CLOSE_PATH:
if (unlikely (p->header.length < 1))
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
- status = _cairo_path_fixed_close_path (cr->path);
+ cairo_close_path (cr);
break;
default:
return _cairo_error (CAIRO_STATUS_INVALID_PATH_DATA);
}
- if (unlikely (status))
- return status;
+ if (unlikely (cr->status))
+ return cr->status;
}
return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index b4b2981e..9447c362 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -47,6 +47,7 @@
#include "cairo-pdf-shading-private.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-image-info-private.h"
#include "cairo-recording-surface-private.h"
@@ -6566,6 +6567,8 @@ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
CAIRO_SURFACE_TYPE_PDF,
+ _cairo_default_context_create,
+
NULL, /* create similar: handled by wrapper */
_cairo_pdf_surface_finish,
NULL, /* acquire_source_image */
diff --git a/src/cairo-private.h b/src/cairo-private.h
index 901a69a3..9f4f55b7 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -36,22 +36,29 @@
#ifndef CAIRO_PRIVATE_H
#define CAIRO_PRIVATE_H
+#include "cairo-types-private.h"
#include "cairo-reference-count-private.h"
-#include "cairo-gstate-private.h"
-#include "cairo-path-fixed-private.h"
+
+CAIRO_BEGIN_DECLS
struct _cairo {
cairo_reference_count_t ref_count;
-
cairo_status_t status;
-
cairo_user_data_array_t user_data;
- cairo_gstate_t *gstate;
- cairo_gstate_t gstate_tail[2];
- cairo_gstate_t *gstate_freelist;
-
- cairo_path_fixed_t path[1];
+ const cairo_backend_t *backend;
};
+cairo_private cairo_t *
+_cairo_create_in_error (cairo_status_t status);
+
+cairo_private void
+_cairo_init (cairo_t *cr,
+ const cairo_backend_t *backend);
+
+cairo_private void
+_cairo_fini (cairo_t *cr);
+
+CAIRO_END_DECLS
+
#endif /* CAIRO_PRIVATE_H */
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 5c83453d..cf6908fa 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -60,6 +60,7 @@
#include "cairo-pdf-operators-private.h"
#include "cairo-pdf-shading-private.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-paginated-private.h"
@@ -3931,6 +3932,8 @@ _cairo_ps_surface_supports_fine_grained_fallbacks (void *abstract_surface)
static const cairo_surface_backend_t cairo_ps_surface_backend = {
CAIRO_SURFACE_TYPE_PS,
+ _cairo_default_context_create,
+
NULL, /* create similar: handled by wrapper */
_cairo_ps_surface_finish,
NULL, /* acquire_source_image */
diff --git a/src/cairo-qt-surface.cpp b/src/cairo-qt-surface.cpp
index 25ee9e9f..772d610c 100644
--- a/src/cairo-qt-surface.cpp
+++ b/src/cairo-qt-surface.cpp
@@ -40,6 +40,7 @@
#include "cairoint.h"
#include "cairo-clip-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-region-private.h"
#include "cairo-surface-clipper-private.h"
@@ -1551,6 +1552,8 @@ _cairo_qt_surface_mark_dirty (void *abstract_surface,
static const cairo_surface_backend_t cairo_qt_surface_backend = {
CAIRO_SURFACE_TYPE_QT,
+ _cairo_default_context_create,
+
_cairo_qt_surface_create_similar,
_cairo_qt_surface_finish,
_cairo_qt_surface_acquire_source_image,
diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index 81ed5fe2..cd675a15 100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -159,6 +159,8 @@ _cairo_quartz_image_surface_flush (void *asurface)
static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
+ _cairo_default_context_create,
+
_cairo_quartz_image_surface_create_similar,
_cairo_quartz_image_surface_finish,
_cairo_quartz_image_surface_acquire_source_image,
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index ce8a95ab..84ae347a 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -79,6 +79,7 @@
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-clip-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-recording-surface-private.h"
#include "cairo-surface-wrapper-private.h"
@@ -707,6 +708,8 @@ _cairo_surface_is_recording (const cairo_surface_t *surface)
static const cairo_surface_backend_t cairo_recording_surface_backend = {
CAIRO_SURFACE_TYPE_RECORDING,
+ _cairo_default_context_create,
+
_cairo_recording_surface_create_similar,
_cairo_recording_surface_finish,
_cairo_recording_surface_acquire_source_image,
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index f5e6dec2..ec228ca3 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -630,6 +630,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
* create a separate subset just for the .notdef glyph.
*/
is_latin = FALSE;
+ latin_character = -1;
if (sub_font->use_latin_subset &&
(! _cairo_font_face_is_user (sub_font->scaled_font->font_face)))
{
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 89311a00..6b59464b 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -3405,6 +3405,8 @@ _cairo_script_surface_get_extents (void *abstract_surface,
static const cairo_surface_backend_t
_cairo_script_surface_backend = {
CAIRO_SURFACE_TYPE_SCRIPT,
+ _cairo_default_context_create,
+
_cairo_script_surface_create_similar,
_cairo_script_surface_finish,
_cairo_script_surface_acquire_source_image,
diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c
index 20cc6b9a..757ec1e6 100644
--- a/src/cairo-surface-snapshot.c
+++ b/src/cairo-surface-snapshot.c
@@ -89,6 +89,7 @@ _cairo_surface_snapshot_get_extents (void *abstract_surface,
static const cairo_surface_backend_t _cairo_surface_snapshot_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT,
+ NULL,
NULL, /* create similar */
_cairo_surface_snapshot_finish,
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 3cf83302..ff1df839 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -442,8 +442,17 @@ _cairo_surface_subsurface_snapshot (void *abstract_surface)
return &snapshot->base;
}
+static cairo_t *
+_cairo_surface_subsurface_create_context(void *target)
+{
+ cairo_surface_subsurface_t *surface = target;
+ return cairo_create (surface->target);
+}
+
static const cairo_surface_backend_t _cairo_surface_subsurface_backend = {
CAIRO_SURFACE_TYPE_SUBSURFACE,
+ _cairo_surface_subsurface_create_context,
+
_cairo_surface_subsurface_create_similar,
_cairo_surface_subsurface_finish,
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index bb5bccff..7adcfb72 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -43,6 +43,7 @@
#include "cairoint.h"
#include "cairo-svg.h"
#include "cairo-analysis-surface-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-image-info-private.h"
#include "cairo-recording-surface-private.h"
@@ -2574,6 +2575,8 @@ _cairo_svg_surface_get_font_options (void *abstract_surface,
static const cairo_surface_backend_t cairo_svg_surface_backend = {
CAIRO_SURFACE_TYPE_SVG,
+ _cairo_default_context_create,
+
NULL, /* create_similar: handled by wrapper */
_cairo_svg_surface_finish,
NULL, /* acquire_source_image */
diff --git a/src/cairo-tee-surface.c b/src/cairo-tee-surface.c
index 83811bd7..df0ae997 100644
--- a/src/cairo-tee-surface.c
+++ b/src/cairo-tee-surface.c
@@ -42,6 +42,7 @@
#include "cairo-tee.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-tee-surface-private.h"
#include "cairo-surface-wrapper-private.h"
@@ -395,6 +396,8 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface,
static const cairo_surface_backend_t cairo_tee_surface_backend = {
CAIRO_SURFACE_TYPE_TEE,
+ _cairo_default_context_create, /* XXX */
+
_cairo_tee_surface_create_similar,
_cairo_tee_surface_finish,
_cairo_tee_surface_acquire_source_image,
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 74257d4b..e9e83115 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -42,6 +42,7 @@
#include "cairo-output-stream-private.h"
#include "cairo-recording-surface-private.h"
#include "cairo-analysis-surface-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-surface-clipper-private.h"
@@ -321,6 +322,8 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH,
+ _cairo_default_context_create,
+
NULL, /* _cairo_type3_glyph_surface_create_similar */
_cairo_type3_glyph_surface_finish,
NULL, /* acquire_source_image */
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 967781c1..5460a42b 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -64,6 +64,8 @@ typedef struct _cairo_color_stop cairo_color_stop_t;
typedef struct _cairo_device_backend cairo_device_backend_t;
typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
typedef struct _cairo_gstate cairo_gstate_t;
+typedef struct _cairo_gstate_backend cairo_gstate_backend_t;
+typedef struct _cairo_glyph_text_info cairo_glyph_text_info_t;
typedef struct _cairo_hash_entry cairo_hash_entry_t;
typedef struct _cairo_hash_table cairo_hash_table_t;
typedef struct _cairo_image_surface cairo_image_surface_t;
@@ -174,6 +176,16 @@ struct _cairo_font_options {
cairo_round_glyph_positions_t round_glyph_positions;
};
+struct _cairo_glyph_text_info {
+ const char *utf8;
+ int utf8_len;
+
+ const cairo_text_cluster_t *clusters;
+ int num_clusters;
+ cairo_text_cluster_flags_t cluster_flags;
+};
+
+
/* XXX: Right now, the _cairo_color structure puts unpremultiplied
color in the doubles and premultiplied color in the shorts. Yes,
this is crazy insane, (but at least we don't export this
@@ -209,7 +221,7 @@ struct _cairo_color_stop {
typedef enum _cairo_paginated_mode {
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
CAIRO_PAGINATED_MODE_RENDER, /* render page contents */
- CAIRO_PAGINATED_MODE_FALLBACK /* paint fallback images */
+ CAIRO_PAGINATED_MODE_FALLBACK /* paint fallback images */
} cairo_paginated_mode_t;
/* Sure wish C had a real enum type so that this would be distinct
diff --git a/src/cairo-vg-surface.c b/src/cairo-vg-surface.c
index 0034d73b..06d46c1c 100644
--- a/src/cairo-vg-surface.c
+++ b/src/cairo-vg-surface.c
@@ -39,6 +39,7 @@
#include "cairo-vg.h"
#include "cairo-cache-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-recording-surface-private.h"
@@ -1547,6 +1548,8 @@ _vg_surface_finish (void *abstract_surface)
static const cairo_surface_backend_t cairo_vg_surface_backend = {
CAIRO_SURFACE_TYPE_VG,
+ _cairo_default_context_create, /* XXX */
+
_vg_surface_create_similar,
_vg_surface_finish,
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 8023335a..58d404a6 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -46,6 +46,7 @@
#include "cairoint.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-paginated-private.h"
@@ -1861,6 +1862,8 @@ _cairo_surface_is_win32_printing (cairo_surface_t *surface)
static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
+ _cairo_default_context_create,
+
_cairo_win32_printing_surface_create_similar,
_cairo_win32_surface_finish,
NULL, /* acquire_source_image */
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 1be21924..24b1ba65 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -49,6 +49,7 @@
#include "cairo-clip-private.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-paginated-private.h"
#include "cairo-win32-private.h"
@@ -2089,6 +2090,8 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op,
static const cairo_surface_backend_t cairo_win32_surface_backend = {
CAIRO_SURFACE_TYPE_WIN32,
+ _cairo_default_context_create,
+
_cairo_win32_surface_create_similar,
_cairo_win32_surface_finish,
_cairo_win32_surface_acquire_source_image,
diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c
index 6801e3f2..1a2bcada 100644
--- a/src/cairo-xcb-surface-core.c
+++ b/src/cairo-xcb-surface-core.c
@@ -75,6 +75,7 @@ _cairo_xcb_pixmap_finish (void *abstract_surface)
static const cairo_surface_backend_t _cairo_xcb_pixmap_backend = {
CAIRO_SURFACE_TYPE_XCB,
NULL,
+ NULL,
_cairo_xcb_pixmap_finish,
};
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 5a0bb224..065e8967 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -95,6 +95,7 @@ _cairo_xcb_picture_finish (void *abstract_surface)
static const cairo_surface_backend_t _cairo_xcb_picture_backend = {
CAIRO_SURFACE_TYPE_XCB,
NULL,
+ NULL,
_cairo_xcb_picture_finish,
};
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index bba7a9c7..a890fe8b 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -43,6 +43,8 @@
#include "cairo-xcb.h"
#include "cairo-xcb-private.h"
+#include "cairo-default-context-private.h"
+
#define AllPlanes ((unsigned) -1)
#define CAIRO_ASSUME_PIXMAP 20
#define XLIB_COORD_MAX 32767
@@ -923,6 +925,7 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
const cairo_surface_backend_t _cairo_xcb_surface_backend = {
CAIRO_SURFACE_TYPE_XCB,
+ _cairo_default_context_create,
_cairo_xcb_surface_create_similar,
_cairo_xcb_surface_finish,
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 85852086..4aecac5b 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -52,6 +52,7 @@
#include "cairo-xlib-private.h"
#include "cairo-xlib-surface-private.h"
#include "cairo-clip-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-scaled-font-private.h"
#include "cairo-surface-snapshot-private.h"
@@ -3133,6 +3134,8 @@ _cairo_xlib_surface_is_similar (void *surface_a,
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
CAIRO_SURFACE_TYPE_XLIB,
+ _cairo_default_context_create,
+
_cairo_xlib_surface_create_similar,
_cairo_xlib_surface_finish,
_cairo_xlib_surface_acquire_source_image,
diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c
index 0ffbc4c5..6381e05c 100644
--- a/src/cairo-xlib-xcb-surface.c
+++ b/src/cairo-xlib-xcb-surface.c
@@ -46,6 +46,8 @@
#include "cairo-xcb-private.h"
#include "cairo-xlib-xrender-private.h"
+#include "cairo-default-context-private.h"
+
#include <X11/Xlib-xcb.h>
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
@@ -60,7 +62,7 @@ struct cairo_xlib_xcb_display_t {
};
typedef struct cairo_xlib_xcb_display_t cairo_xlib_xcb_display_t;
-/* List of all cairo_xlib_xcb_display_t alive,
+/* List of all #cairo_xlib_xcb_display_t alive,
* protected by _cairo_xlib_display_mutex */
static cairo_list_t displays;
@@ -232,6 +234,8 @@ _cairo_xlib_xcb_surface_mark_dirty (void *abstract_surface,
static const cairo_surface_backend_t _cairo_xlib_xcb_surface_backend = {
CAIRO_SURFACE_TYPE_XLIB,
+ _cairo_default_context_create, /* XXX */
+
_cairo_xlib_xcb_surface_create_similar,
_cairo_xlib_xcb_surface_finish,
_cairo_xlib_xcb_surface_acquire_source_image,
diff --git a/src/cairo-xml-surface.c b/src/cairo-xml-surface.c
index 83d4f912..cf99ee6c 100644
--- a/src/cairo-xml-surface.c
+++ b/src/cairo-xml-surface.c
@@ -46,6 +46,7 @@
#include "cairo-clip-private.h"
#include "cairo-device-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-recording-surface-private.h"
@@ -989,6 +990,8 @@ _cairo_xml_surface_glyphs (void *abstract_surface,
static const cairo_surface_backend_t
_cairo_xml_surface_backend = {
CAIRO_SURFACE_TYPE_XML,
+ _cairo_default_context_create,
+
_cairo_xml_surface_create_similar,
NULL,
NULL, NULL, /* source image */
diff --git a/src/cairo.c b/src/cairo.c
index 0aae04b2..42e3b5f7 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -3,6 +3,7 @@
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat, Inc.
+ * 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
@@ -34,15 +35,18 @@
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-private.h"
-#include "cairo-arc-private.h"
+#include "cairo-backend-private.h"
#include "cairo-error-private.h"
-#include "cairo-freed-pool-private.h"
#include "cairo-path-private.h"
+#include "cairo-surface-private.h"
+
+#include <assert.h>
/**
* SECTION:cairo
@@ -101,34 +105,12 @@
* space</firstterm>.
*/
-#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1)
-
-#if !defined(INFINITY)
-#define INFINITY HUGE_VAL
-#endif
-
#define DEFINE_NIL_CONTEXT(status) \
{ \
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \
status, /* status */ \
{ 0, 0, 0, NULL }, /* user_data */ \
- NULL, /* gstate */ \
- {{ 0 }, { 0 }}, /* gstate_tail */ \
- NULL, /* gstate_freelist */ \
- {{ /* path */ \
- { 0, 0 }, /* last_move_point */ \
- { 0, 0 }, /* current point */ \
- FALSE, /* has_current_point */ \
- TRUE, /* needs_move_to */ \
- FALSE, /* has_extents */ \
- FALSE, /* has_curve_to */ \
- TRUE, /* stroke_is_rectilinear */ \
- TRUE, /* fill_is_rectilinear */ \
- TRUE, /* fill_maybe_region */ \
- TRUE, /* fill_is_empty */ \
- {{0, 0}, {0, 0}}, /* extents */ \
- {{{NULL,NULL}}} /* link */ \
- }} \
+ NULL \
}
static const cairo_t _cairo_nil[] = {
@@ -170,11 +152,8 @@ static const cairo_t _cairo_nil[] = {
DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_MESH_CONSTRUCTION),
DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_FINISHED)
};
-
COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1);
-#include <assert.h>
-
/**
* _cairo_set_error:
* @cr: a cairo context
@@ -199,9 +178,7 @@ _cairo_set_error (cairo_t *cr, cairo_status_t status)
_cairo_status_set_error (&cr->status, _cairo_error (status));
}
-static freed_pool_t context_pool;
-
-static cairo_t *
+cairo_t *
_cairo_create_in_error (cairo_status_t status)
{
cairo_t *cr;
@@ -214,12 +191,6 @@ _cairo_create_in_error (cairo_status_t status)
return cr;
}
-void
-_cairo_reset_static_data (void)
-{
- _freed_pool_reset (&context_pool);
-}
-
/**
* cairo_create:
* @target: target surface for the context
@@ -247,41 +218,26 @@ _cairo_reset_static_data (void)
cairo_t *
cairo_create (cairo_surface_t *target)
{
- cairo_t *cr;
- cairo_status_t status;
-
if (unlikely (target == NULL))
return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
if (unlikely (target->status))
return _cairo_create_in_error (target->status);
- cr = _freed_pool_get (&context_pool);
- if (unlikely (cr == NULL)) {
- cr = malloc (sizeof (cairo_t));
- if (unlikely (cr == NULL))
- return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
+ return target->backend->create_context (target);
- CAIRO_REFERENCE_COUNT_INIT (&cr->ref_count, 1);
+}
+slim_hidden_def (cairo_create);
+void
+_cairo_init (cairo_t *cr,
+ const cairo_backend_t *backend)
+{
+ CAIRO_REFERENCE_COUNT_INIT (&cr->ref_count, 1);
cr->status = CAIRO_STATUS_SUCCESS;
-
_cairo_user_data_array_init (&cr->user_data);
- _cairo_path_fixed_init (cr->path);
-
- cr->gstate = &cr->gstate_tail[0];
- cr->gstate_freelist = &cr->gstate_tail[1];
- cr->gstate_tail[1].next = NULL;
-
- status = _cairo_gstate_init (cr->gstate, target);
- if (unlikely (status)) {
- _freed_pool_put (&context_pool, cr);
- cr = _cairo_create_in_error (status);
- }
- return cr;
+ cr->backend = backend;
}
-slim_hidden_def (cairo_create);
/**
* cairo_reference:
@@ -309,6 +265,12 @@ cairo_reference (cairo_t *cr)
return cr;
}
+void
+_cairo_fini (cairo_t *cr)
+{
+ _cairo_user_data_array_fini (&cr->user_data);
+}
+
/**
* cairo_destroy:
* @cr: a #cairo_t
@@ -328,27 +290,7 @@ cairo_destroy (cairo_t *cr)
if (! _cairo_reference_count_dec_and_test (&cr->ref_count))
return;
- while (cr->gstate != &cr->gstate_tail[0]) {
- if (_cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist))
- break;
- }
-
- _cairo_gstate_fini (cr->gstate);
- cr->gstate_freelist = cr->gstate_freelist->next; /* skip over tail[1] */
- while (cr->gstate_freelist != NULL) {
- cairo_gstate_t *gstate = cr->gstate_freelist;
- cr->gstate_freelist = gstate->next;
- free (gstate);
- }
-
- _cairo_path_fixed_fini (cr->path);
-
- _cairo_user_data_array_fini (&cr->user_data);
-
- /* mark the context as invalid to protect against misuse */
- cr->status = CAIRO_STATUS_NULL_POINTER;
-
- _freed_pool_put (&context_pool, cr);
+ cr->backend->destroy (cr);
}
slim_hidden_def (cairo_destroy);
@@ -370,8 +312,7 @@ void *
cairo_get_user_data (cairo_t *cr,
const cairo_user_data_key_t *key)
{
- return _cairo_user_data_array_get_data (&cr->user_data,
- key);
+ return _cairo_user_data_array_get_data (&cr->user_data, key);
}
/**
@@ -449,7 +390,7 @@ cairo_save (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_save (&cr->gstate, &cr->gstate_freelist);
+ status = cr->backend->save (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -471,12 +412,7 @@ cairo_restore (cairo_t *cr)
if (unlikely (cr->status))
return;
- if (unlikely (_cairo_gstate_is_group (cr->gstate))) {
- _cairo_set_error (cr, _cairo_error (CAIRO_STATUS_INVALID_RESTORE));
- return;
- }
-
- status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
+ status = cr->backend->restore (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -554,68 +490,12 @@ cairo_push_group (cairo_t *cr)
void
cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
{
- cairo_surface_t *group_surface;
- cairo_clip_t *clip;
cairo_status_t status;
if (unlikely (cr->status))
return;
- clip = _cairo_gstate_get_clip (cr->gstate);
- if (clip->all_clipped) {
- group_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
- status = group_surface->status;
- if (unlikely (status))
- goto bail;
- } else {
- cairo_surface_t *parent_surface;
- const cairo_rectangle_int_t *clip_extents;
- cairo_rectangle_int_t extents;
- cairo_matrix_t matrix;
- cairo_bool_t is_empty;
-
- parent_surface = _cairo_gstate_get_target (cr->gstate);
-
- /* Get the extents that we'll use in creating our new group surface */
- is_empty = _cairo_surface_get_extents (parent_surface, &extents);
- clip_extents = _cairo_clip_get_extents (_cairo_gstate_get_clip (cr->gstate));
- if (clip_extents != NULL)
- _cairo_rectangle_intersect (&extents, clip_extents);
-
- group_surface = _cairo_surface_create_similar_solid (parent_surface,
- content,
- extents.width,
- extents.height,
- CAIRO_COLOR_TRANSPARENT,
- TRUE);
- status = group_surface->status;
- if (unlikely (status))
- goto bail;
-
- /* Set device offsets on the new surface so that logically it appears at
- * the same location on the parent surface -- when we pop_group this,
- * the source pattern will get fixed up for the appropriate target surface
- * device offsets, so we want to set our own surface offsets from /that/,
- * and not from the device origin. */
- cairo_surface_set_device_offset (group_surface,
- parent_surface->device_transform.x0 - extents.x,
- parent_surface->device_transform.y0 - extents.y);
-
- /* If we have a current path, we need to adjust it to compensate for
- * the device offset just applied. */
- cairo_matrix_init_translate (&matrix, -extents.x, -extents.y);
- _cairo_path_fixed_transform (cr->path, &matrix);
- }
-
- /* create a new gstate for the redirect */
- cairo_save (cr);
- if (unlikely (cr->status))
- goto bail;
-
- status = _cairo_gstate_redirect_target (cr->gstate, group_surface);
-
-bail:
- cairo_surface_destroy (group_surface);
+ status = cr->backend->push_group (cr, content);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -645,55 +525,14 @@ slim_hidden_def(cairo_push_group_with_content);
cairo_pattern_t *
cairo_pop_group (cairo_t *cr)
{
- cairo_surface_t *group_surface;
cairo_pattern_t *group_pattern;
- cairo_matrix_t group_matrix, device_transform_matrix;
- cairo_status_t status;
if (unlikely (cr->status))
return _cairo_pattern_create_in_error (cr->status);
- /* Verify that we are at the right nesting level */
- if (unlikely (! _cairo_gstate_is_group (cr->gstate))) {
- _cairo_set_error (cr, CAIRO_STATUS_INVALID_POP_GROUP);
- return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_POP_GROUP);
- }
-
- /* Get a reference to the active surface before restoring */
- group_surface = _cairo_gstate_get_target (cr->gstate);
- group_surface = cairo_surface_reference (group_surface);
-
- status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- group_pattern = cairo_pattern_create_for_surface (group_surface);
- status = group_pattern->status;
- if (unlikely (status)) {
- _cairo_set_error (cr, status);
- goto done;
- }
-
- _cairo_gstate_get_matrix (cr->gstate, &group_matrix);
- /* Transform by group_matrix centered around device_transform so that when
- * we call _cairo_gstate_copy_transformed_pattern the result is a pattern
- * with a matrix equivalent to the device_transform of group_surface. */
- if (_cairo_surface_has_device_transform (group_surface)) {
- cairo_pattern_set_matrix (group_pattern, &group_surface->device_transform);
- _cairo_pattern_transform (group_pattern, &group_matrix);
- _cairo_pattern_transform (group_pattern, &group_surface->device_transform_inverse);
- } else {
- cairo_pattern_set_matrix (group_pattern, &group_matrix);
- }
-
- /* If we have a current path, we need to adjust it to compensate for
- * the device offset just removed. */
- cairo_matrix_multiply (&device_transform_matrix,
- &_cairo_gstate_get_target (cr->gstate)->device_transform,
- &group_surface->device_transform_inverse);
- _cairo_path_fixed_transform (cr->path, &device_transform_matrix);
-
-done:
- cairo_surface_destroy (group_surface);
+ group_pattern = cr->backend->pop_group (cr);
+ if (unlikely (group_pattern->status))
+ _cairo_set_error (cr, group_pattern->status);
return group_pattern;
}
@@ -755,36 +594,39 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_operator (cr->gstate, op);
+ status = cr->backend->set_operator (cr, op);
if (unlikely (status))
_cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_operator);
-static cairo_bool_t
-_current_source_matches_solid (cairo_t *cr,
- double red,
- double green,
- double blue,
- double alpha)
+#if 0
+/**
+ * cairo_set_opacity:
+ * @cr: a #cairo_t
+ * @opacity: the level of opacity to use when compositing
+ *
+ * Sets the compositing opacity to be used for all drawing
+ * operations. The effect is to fade out the operations
+ * using the alpha value.
+ *
+ * The default opacity is 1.
+ **/
+void
+cairo_set_opacity (cairo_t *cr, double opacity)
{
- const cairo_pattern_t *current;
- cairo_color_t color;
-
- current = cr->gstate->source;
- if (current->type != CAIRO_PATTERN_TYPE_SOLID)
- return FALSE;
+ cairo_status_t status;
- red = _cairo_restrict_value (red, 0.0, 1.0);
- green = _cairo_restrict_value (green, 0.0, 1.0);
- blue = _cairo_restrict_value (blue, 0.0, 1.0);
- alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
+ if (unlikely (cr->status))
+ return;
- _cairo_color_init_rgba (&color, red, green, blue, alpha);
- return _cairo_color_equal (&color,
- &((cairo_solid_pattern_t *) current)->color);
+ status = cr->backend->set_opacity (cr, opacity);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
+#endif
+
/**
* cairo_set_source_rgb
* @cr: a cairo context
@@ -806,20 +648,14 @@ _current_source_matches_solid (cairo_t *cr,
void
cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
{
- cairo_pattern_t *pattern;
+ cairo_status_t status;
if (unlikely (cr->status))
return;
- if (_current_source_matches_solid (cr, red, green, blue, 1.))
- return;
-
- /* push the current pattern to the freed lists */
- cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
-
- pattern = cairo_pattern_create_rgb (red, green, blue);
- cairo_set_source (cr, pattern);
- cairo_pattern_destroy (pattern);
+ status = cr->backend->set_source_rgba (cr, red, green, blue, 1.);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_source_rgb);
@@ -847,20 +683,14 @@ cairo_set_source_rgba (cairo_t *cr,
double red, double green, double blue,
double alpha)
{
- cairo_pattern_t *pattern;
+ cairo_status_t status;
if (unlikely (cr->status))
return;
- if (_current_source_matches_solid (cr, red, green, blue, alpha))
- return;
-
- /* push the current pattern to the freed lists */
- cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
-
- pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
- cairo_set_source (cr, pattern);
- cairo_pattern_destroy (pattern);
+ status = cr->backend->set_source_rgba (cr, red, green, blue, alpha);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/**
@@ -892,22 +722,19 @@ cairo_set_source_surface (cairo_t *cr,
double x,
double y)
{
- cairo_pattern_t *pattern;
- cairo_matrix_t matrix;
+ cairo_status_t status;
if (unlikely (cr->status))
return;
- /* push the current pattern to the freed lists */
- cairo_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
-
- pattern = cairo_pattern_create_for_surface (surface);
-
- cairo_matrix_init_translate (&matrix, -x, -y);
- cairo_pattern_set_matrix (pattern, &matrix);
+ if (unlikely (surface == NULL)) {
+ _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
+ return;
+ }
- cairo_set_source (cr, pattern);
- cairo_pattern_destroy (pattern);
+ status = cr->backend->set_source_surface (cr, surface, x, y);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_source_surface);
@@ -938,17 +765,17 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
if (unlikely (cr->status))
return;
- if (source == NULL) {
+ if (unlikely (source == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
- if (source->status) {
+ if (unlikely (source->status)) {
_cairo_set_error (cr, source->status);
return;
}
- status = _cairo_gstate_set_source (cr->gstate, source);
+ status = cr->backend->set_source (cr, source);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -970,7 +797,7 @@ cairo_get_source (cairo_t *cr)
if (unlikely (cr->status))
return _cairo_pattern_create_in_error (cr->status);
- return _cairo_gstate_get_source (cr->gstate);
+ return cr->backend->get_source (cr);
}
/**
@@ -997,10 +824,7 @@ cairo_set_tolerance (cairo_t *cr, double tolerance)
if (unlikely (cr->status))
return;
- if (tolerance < CAIRO_TOLERANCE_MINIMUM)
- tolerance = CAIRO_TOLERANCE_MINIMUM;
-
- status = _cairo_gstate_set_tolerance (cr->gstate, tolerance);
+ status = cr->backend->set_tolerance (cr, tolerance);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1027,7 +851,7 @@ cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_antialias (cr->gstate, antialias);
+ status = cr->backend->set_antialias (cr, antialias);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1053,7 +877,7 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
+ status = cr->backend->set_fill_rule (cr, fill_rule);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1095,7 +919,7 @@ cairo_set_line_width (cairo_t *cr, double width)
if (width < 0.)
width = 0.;
- status = _cairo_gstate_set_line_width (cr->gstate, width);
+ status = cr->backend->set_line_width (cr, width);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1125,7 +949,7 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_line_cap (cr->gstate, line_cap);
+ status = cr->backend->set_line_cap (cr, line_cap);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1155,7 +979,7 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_line_join (cr->gstate, line_join);
+ status = cr->backend->set_line_join (cr, line_join);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1204,8 +1028,7 @@ cairo_set_dash (cairo_t *cr,
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_dash (cr->gstate,
- dashes, num_dashes, offset);
+ status = cr->backend->set_dash (cr, dashes, num_dashes, offset);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1231,7 +1054,7 @@ cairo_get_dash_count (cairo_t *cr)
if (unlikely (cr->status))
return 0;
- _cairo_gstate_get_dash (cr->gstate, NULL, &num_dashes, NULL);
+ cr->backend->get_dash (cr, NULL, &num_dashes, NULL);
return num_dashes;
}
@@ -1256,7 +1079,7 @@ cairo_get_dash (cairo_t *cr,
if (unlikely (cr->status))
return;
- _cairo_gstate_get_dash (cr->gstate, dashes, NULL, offset);
+ cr->backend->get_dash (cr, dashes, NULL, offset);
}
/**
@@ -1295,7 +1118,7 @@ cairo_set_miter_limit (cairo_t *cr, double limit)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_miter_limit (cr->gstate, limit);
+ status = cr->backend->set_miter_limit (cr, limit);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1320,7 +1143,7 @@ cairo_translate (cairo_t *cr, double tx, double ty)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_translate (cr->gstate, tx, ty);
+ status = cr->backend->translate (cr, tx, ty);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1345,7 +1168,7 @@ cairo_scale (cairo_t *cr, double sx, double sy)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_scale (cr->gstate, sx, sy);
+ status = cr->backend->scale (cr, sx, sy);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1371,7 +1194,7 @@ cairo_rotate (cairo_t *cr, double angle)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_rotate (cr->gstate, angle);
+ status = cr->backend->rotate (cr, angle);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1394,7 +1217,7 @@ cairo_transform (cairo_t *cr,
if (unlikely (cr->status))
return;
- status = _cairo_gstate_transform (cr->gstate, matrix);
+ status = cr->backend->transform (cr, matrix);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1417,7 +1240,7 @@ cairo_set_matrix (cairo_t *cr,
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_matrix (cr->gstate, matrix);
+ status = cr->backend->set_matrix (cr, matrix);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1435,10 +1258,14 @@ slim_hidden_def (cairo_set_matrix);
void
cairo_identity_matrix (cairo_t *cr)
{
+ cairo_status_t status;
+
if (unlikely (cr->status))
return;
- _cairo_gstate_identity_matrix (cr->gstate);
+ status = cr->backend->set_identity_matrix (cr);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/**
@@ -1457,7 +1284,7 @@ cairo_user_to_device (cairo_t *cr, double *x, double *y)
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_device (cr->gstate, x, y);
+ cr->backend->user_to_device (cr, x, y);
}
slim_hidden_def (cairo_user_to_device);
@@ -1478,7 +1305,7 @@ cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy)
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
+ cr->backend->user_to_device_distance (cr, dx, dy);
}
slim_hidden_def (cairo_user_to_device_distance);
@@ -1498,8 +1325,9 @@ cairo_device_to_user (cairo_t *cr, double *x, double *y)
if (unlikely (cr->status))
return;
- _cairo_gstate_device_to_user (cr->gstate, x, y);
+ cr->backend->device_to_user (cr, x, y);
}
+slim_hidden_def (cairo_device_to_user);
/**
* cairo_device_to_user_distance:
@@ -1518,7 +1346,7 @@ cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
if (unlikely (cr->status))
return;
- _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
+ cr->backend->device_to_user_distance (cr, dx, dy);
}
/**
@@ -1531,41 +1359,16 @@ cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
void
cairo_new_path (cairo_t *cr)
{
- if (unlikely (cr->status))
- return;
-
- _cairo_path_fixed_fini (cr->path);
- _cairo_path_fixed_init (cr->path);
-}
-slim_hidden_def(cairo_new_path);
-
-/**
- * cairo_move_to:
- * @cr: a cairo context
- * @x: the X coordinate of the new position
- * @y: the Y coordinate of the new position
- *
- * Begin a new sub-path. After this call the current point will be (@x,
- * @y).
- **/
-void
-cairo_move_to (cairo_t *cr, double x, double y)
-{
cairo_status_t status;
- cairo_fixed_t x_fixed, y_fixed;
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
- x_fixed = _cairo_fixed_from_double (x);
- y_fixed = _cairo_fixed_from_double (y);
-
- status = _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed);
+ status = cr->backend->new_path (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
-slim_hidden_def(cairo_move_to);
+slim_hidden_def(cairo_new_path);
/**
* cairo_new_sub_path:
@@ -1588,13 +1391,41 @@ slim_hidden_def(cairo_move_to);
void
cairo_new_sub_path (cairo_t *cr)
{
+ cairo_status_t status;
+
if (unlikely (cr->status))
return;
- _cairo_path_fixed_new_sub_path (cr->path);
+ status = cr->backend->new_sub_path (cr);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/**
+ * cairo_move_to:
+ * @cr: a cairo context
+ * @x: the X coordinate of the new position
+ * @y: the Y coordinate of the new position
+ *
+ * Begin a new sub-path. After this call the current point will be (@x,
+ * @y).
+ **/
+void
+cairo_move_to (cairo_t *cr, double x, double y)
+{
+ cairo_status_t status;
+
+ if (unlikely (cr->status))
+ return;
+
+ status = cr->backend->move_to (cr, x, y);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
+}
+slim_hidden_def(cairo_move_to);
+
+
+/**
* cairo_line_to:
* @cr: a cairo context
* @x: the X coordinate of the end of the new line
@@ -1611,16 +1442,11 @@ void
cairo_line_to (cairo_t *cr, double x, double y)
{
cairo_status_t status;
- cairo_fixed_t x_fixed, y_fixed;
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
- x_fixed = _cairo_fixed_from_double (x);
- y_fixed = _cairo_fixed_from_double (y);
-
- status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
+ status = cr->backend->line_to (cr, x, y);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1652,30 +1478,14 @@ cairo_curve_to (cairo_t *cr,
double x3, double y3)
{
cairo_status_t status;
- cairo_fixed_t x1_fixed, y1_fixed;
- cairo_fixed_t x2_fixed, y2_fixed;
- cairo_fixed_t x3_fixed, y3_fixed;
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
- _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
- _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
-
- x1_fixed = _cairo_fixed_from_double (x1);
- y1_fixed = _cairo_fixed_from_double (y1);
-
- x2_fixed = _cairo_fixed_from_double (x2);
- y2_fixed = _cairo_fixed_from_double (y2);
-
- x3_fixed = _cairo_fixed_from_double (x3);
- y3_fixed = _cairo_fixed_from_double (y3);
-
- status = _cairo_path_fixed_curve_to (cr->path,
- x1_fixed, y1_fixed,
- x2_fixed, y2_fixed,
- x3_fixed, y3_fixed);
+ status = cr->backend->curve_to (cr,
+ x1, y1,
+ x2, y2,
+ x3, y3);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1735,15 +1545,10 @@ cairo_arc (cairo_t *cr,
double radius,
double angle1, double angle2)
{
- if (unlikely (cr->status))
- return;
+ cairo_status_t status;
- /* Do nothing, successfully, if radius is <= 0 */
- if (radius <= 0.0) {
- cairo_line_to (cr, xc, yc); /* might become a move_to */
- cairo_line_to (cr, xc, yc);
+ if (unlikely (cr->status))
return;
- }
if (angle2 < angle1) {
/* increase angle2 by multiples of full circle until it
@@ -1754,12 +1559,9 @@ cairo_arc (cairo_t *cr,
angle2 += angle1;
}
- cairo_line_to (cr,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
-
- _cairo_arc_path (cr, xc, yc, radius,
- angle1, angle2);
+ status = cr->backend->arc (cr, xc, yc, radius, angle1, angle2, TRUE);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/**
@@ -1786,15 +1588,10 @@ cairo_arc_negative (cairo_t *cr,
double radius,
double angle1, double angle2)
{
- if (unlikely (cr->status))
- return;
+ cairo_status_t status;
- /* Do nothing, successfully, if radius is <= 0 */
- if (radius <= 0.0) {
- cairo_line_to (cr, xc, yc); /* might become a move_to */
- cairo_line_to (cr, xc, yc);
+ if (unlikely (cr->status))
return;
- }
if (angle2 > angle1) {
/* decrease angle2 by multiples of full circle until it
@@ -1805,12 +1602,9 @@ cairo_arc_negative (cairo_t *cr,
angle2 += angle1;
}
- cairo_line_to (cr,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
-
- _cairo_arc_path_negative (cr, xc, yc, radius,
- angle1, angle2);
+ status = cr->backend->arc (cr, xc, yc, radius, angle1, angle2, FALSE);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/* XXX: NYI
@@ -1825,10 +1619,23 @@ cairo_arc_to (cairo_t *cr,
if (unlikely (cr->status))
return;
- status = _cairo_gstate_arc_to (cr->gstate,
- x1, y1,
- x2, y2,
- radius);
+ status = cr->backend->arc_to (cr, x1, y1, x2, y2, radius);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
+}
+
+void
+cairo_rel_arc_to (cairo_t *cr,
+ double dx1, double dy1,
+ double dx2, double dy2,
+ double radius)
+{
+ cairo_status_t status;
+
+ if (unlikely (cr->status))
+ return;
+
+ status = cr->backend->rel_arc_to (cr, dx1, dy1, dx2, dy2, radius);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1853,18 +1660,12 @@ cairo_arc_to (cairo_t *cr,
void
cairo_rel_move_to (cairo_t *cr, double dx, double dy)
{
- cairo_fixed_t dx_fixed, dy_fixed;
cairo_status_t status;
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
-
- dx_fixed = _cairo_fixed_from_double (dx);
- dy_fixed = _cairo_fixed_from_double (dy);
-
- status = _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed);
+ status = cr->backend->rel_move_to (cr, dx, dy);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1890,18 +1691,12 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
void
cairo_rel_line_to (cairo_t *cr, double dx, double dy)
{
- cairo_fixed_t dx_fixed, dy_fixed;
cairo_status_t status;
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
-
- dx_fixed = _cairo_fixed_from_double (dx);
- dy_fixed = _cairo_fixed_from_double (dy);
-
- status = _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed);
+ status = cr->backend->rel_line_to (cr, dx, dy);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1938,31 +1733,15 @@ cairo_rel_curve_to (cairo_t *cr,
double dx2, double dy2,
double dx3, double dy3)
{
- cairo_fixed_t dx1_fixed, dy1_fixed;
- cairo_fixed_t dx2_fixed, dy2_fixed;
- cairo_fixed_t dx3_fixed, dy3_fixed;
cairo_status_t status;
if (unlikely (cr->status))
return;
- _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1);
- _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2);
- _cairo_gstate_user_to_device_distance (cr->gstate, &dx3, &dy3);
-
- dx1_fixed = _cairo_fixed_from_double (dx1);
- dy1_fixed = _cairo_fixed_from_double (dy1);
-
- dx2_fixed = _cairo_fixed_from_double (dx2);
- dy2_fixed = _cairo_fixed_from_double (dy2);
-
- dx3_fixed = _cairo_fixed_from_double (dx3);
- dy3_fixed = _cairo_fixed_from_double (dy3);
-
- status = _cairo_path_fixed_rel_curve_to (cr->path,
- dx1_fixed, dy1_fixed,
- dx2_fixed, dy2_fixed,
- dx3_fixed, dy3_fixed);
+ status = cr->backend->rel_curve_to (cr,
+ dx1, dy1,
+ dx2, dy2,
+ dx3, dy3);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -1992,14 +1771,14 @@ cairo_rectangle (cairo_t *cr,
double x, double y,
double width, double height)
{
+ cairo_status_t status;
+
if (unlikely (cr->status))
return;
- cairo_move_to (cr, x, y);
- cairo_rel_line_to (cr, width, 0);
- cairo_rel_line_to (cr, 0, height);
- cairo_rel_line_to (cr, -width, 0);
- cairo_close_path (cr);
+ status = cr->backend->rectangle (cr, x, y, width, height);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
#if 0
@@ -2054,7 +1833,7 @@ cairo_close_path (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_path_fixed_close_path (cr->path);
+ status = cr->backend->close_path (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2108,9 +1887,7 @@ cairo_path_extents (cairo_t *cr,
return;
}
- _cairo_gstate_path_extents (cr->gstate,
- cr->path,
- x1, y1, x2, y2);
+ cr->backend->path_extents (cr, x1, y1, x2, y2);
}
/**
@@ -2128,7 +1905,7 @@ cairo_paint (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_paint (cr->gstate);
+ status = cr->backend->paint (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2149,30 +1926,13 @@ cairo_paint_with_alpha (cairo_t *cr,
double alpha)
{
cairo_status_t status;
- cairo_color_t color;
- cairo_solid_pattern_t pattern;
if (unlikely (cr->status))
return;
- if (CAIRO_ALPHA_IS_OPAQUE (alpha)) {
- cairo_paint (cr);
- return;
- }
-
- if (CAIRO_ALPHA_IS_ZERO (alpha) &&
- _cairo_operator_bounded_by_mask (cr->gstate->op)) {
- return;
- }
-
- _cairo_color_init_rgba (&color, 0., 0., 0., alpha);
- _cairo_pattern_init_solid (&pattern, &color);
-
- status = _cairo_gstate_mask (cr->gstate, &pattern.base);
+ status = cr->backend->paint_with_alpha (cr, alpha);
if (unlikely (status))
_cairo_set_error (cr, status);
-
- _cairo_pattern_fini (&pattern.base);
}
/**
@@ -2194,17 +1954,17 @@ cairo_mask (cairo_t *cr,
if (unlikely (cr->status))
return;
- if (pattern == NULL) {
+ if (unlikely (pattern == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
- if (pattern->status) {
+ if (unlikely (pattern->status)) {
_cairo_set_error (cr, pattern->status);
return;
}
- status = _cairo_gstate_mask (cr->gstate, pattern);
+ status = cr->backend->mask (cr, pattern);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2279,9 +2039,14 @@ cairo_mask_surface (cairo_t *cr,
void
cairo_stroke (cairo_t *cr)
{
- cairo_stroke_preserve (cr);
+ cairo_status_t status;
- cairo_new_path (cr);
+ if (unlikely (cr->status))
+ return;
+
+ status = cr->backend->stroke (cr);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
slim_hidden_def(cairo_stroke);
@@ -2306,7 +2071,7 @@ cairo_stroke_preserve (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_stroke (cr->gstate, cr->path);
+ status = cr->backend->stroke_preserve (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2325,9 +2090,14 @@ slim_hidden_def(cairo_stroke_preserve);
void
cairo_fill (cairo_t *cr)
{
- cairo_fill_preserve (cr);
+ cairo_status_t status;
+
+ if (unlikely (cr->status))
+ return;
- cairo_new_path (cr);
+ status = cr->backend->fill (cr);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/**
@@ -2349,7 +2119,7 @@ cairo_fill_preserve (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_fill (cr->gstate, cr->path);
+ status = cr->backend->fill_preserve (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2375,7 +2145,7 @@ cairo_copy_page (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_copy_page (cr->gstate);
+ status = cr->backend->copy_page (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2398,7 +2168,7 @@ cairo_show_page (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_show_page (cr->gstate);
+ status = cr->backend->show_page (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2430,9 +2200,7 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
if (unlikely (cr->status))
return FALSE;
- status = _cairo_gstate_in_stroke (cr->gstate,
- cr->path,
- x, y, &inside);
+ status = cr->backend->in_stroke (cr, x, y, &inside);
if (unlikely (status))
_cairo_set_error (cr, status);
@@ -2458,10 +2226,17 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
cairo_bool_t
cairo_in_fill (cairo_t *cr, double x, double y)
{
+ cairo_status_t status;
+ cairo_bool_t inside = FALSE;
+
if (unlikely (cr->status))
return FALSE;
- return _cairo_gstate_in_fill (cr->gstate, cr->path, x, y);
+ status = cr->backend->in_fill (cr, x, y, &inside);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
+
+ return inside;
}
/**
@@ -2511,9 +2286,7 @@ cairo_stroke_extents (cairo_t *cr,
return;
}
- status = _cairo_gstate_stroke_extents (cr->gstate,
- cr->path,
- x1, y1, x2, y2);
+ status = cr->backend->stroke_extents (cr, x1, y1, x2, y2);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2562,9 +2335,7 @@ cairo_fill_extents (cairo_t *cr,
return;
}
- status = _cairo_gstate_fill_extents (cr->gstate,
- cr->path,
- x1, y1, x2, y2);
+ status = cr->backend->fill_extents (cr, x1, y1, x2, y2);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2594,9 +2365,14 @@ cairo_fill_extents (cairo_t *cr,
void
cairo_clip (cairo_t *cr)
{
- cairo_clip_preserve (cr);
+ cairo_status_t status;
- cairo_new_path (cr);
+ if (unlikely (cr->status))
+ return;
+
+ status = cr->backend->clip (cr);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/**
@@ -2629,7 +2405,7 @@ cairo_clip_preserve (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_clip (cr->gstate, cr->path);
+ status = cr->backend->clip_preserve (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2659,7 +2435,7 @@ cairo_reset_clip (cairo_t *cr)
if (unlikely (cr->status))
return;
- status = _cairo_gstate_reset_clip (cr->gstate);
+ status = cr->backend->reset_clip (cr);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2682,25 +2458,23 @@ cairo_clip_extents (cairo_t *cr,
double *x1, double *y1,
double *x2, double *y2)
{
- if (unlikely (cr->status)) {
- if (x1)
- *x1 = 0.0;
- if (y1)
- *y1 = 0.0;
- if (x2)
- *x2 = 0.0;
- if (y2)
- *y2 = 0.0;
+ cairo_status_t status;
+
+ if (x1)
+ *x1 = 0.0;
+ if (y1)
+ *y1 = 0.0;
+ if (x2)
+ *x2 = 0.0;
+ if (y2)
+ *y2 = 0.0;
+ if (unlikely (cr->status))
return;
- }
- if (! _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2)) {
- *x1 = -INFINITY;
- *y1 = -INFINITY;
- *x2 = +INFINITY;
- *y2 = +INFINITY;
- }
+ status = cr->backend->clip_extents (cr, x1, y1, x2, y2);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
/**
@@ -2723,10 +2497,17 @@ cairo_clip_extents (cairo_t *cr,
cairo_bool_t
cairo_in_clip (cairo_t *cr, double x, double y)
{
+ cairo_status_t status;
+ cairo_bool_t inside = FALSE;
+
if (unlikely (cr->status))
return FALSE;
- return _cairo_gstate_in_clip (cr->gstate, x, y);
+ status = cr->backend->in_clip (cr, x, y, &inside);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
+
+ return inside;
}
/**
@@ -2752,7 +2533,7 @@ cairo_copy_clip_rectangle_list (cairo_t *cr)
if (unlikely (cr->status))
return _cairo_rectangle_list_create_in_error (cr->status);
- return _cairo_gstate_copy_clip_rectangle_list (cr->gstate);
+ return cr->backend->clip_copy_rectangle_list (cr);
}
/**
@@ -2812,12 +2593,21 @@ cairo_select_font_face (cairo_t *cr,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
+ cairo_font_face_t *font_face;
cairo_status_t status;
if (unlikely (cr->status))
return;
- status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight);
+ font_face = cairo_toy_font_face_create (family, slant, weight);
+ if (unlikely (font_face->status)) {
+ _cairo_set_error (cr, font_face->status);
+ return;
+ }
+
+ status = cr->backend->set_font_face (cr, font_face);
+ cairo_font_face_destroy (font_face);
+
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2845,7 +2635,7 @@ cairo_font_extents (cairo_t *cr,
if (unlikely (cr->status))
return;
- status = _cairo_gstate_get_font_extents (cr->gstate, extents);
+ status = cr->backend->font_extents (cr, extents);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2868,7 +2658,7 @@ cairo_set_font_face (cairo_t *cr,
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_font_face (cr->gstate, font_face);
+ status = cr->backend->set_font_face (cr, font_face);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2894,19 +2684,10 @@ cairo_set_font_face (cairo_t *cr,
cairo_font_face_t *
cairo_get_font_face (cairo_t *cr)
{
- cairo_status_t status;
- cairo_font_face_t *font_face;
-
if (unlikely (cr->status))
return (cairo_font_face_t*) &_cairo_font_face_nil;
- status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
- if (unlikely (status)) {
- _cairo_set_error (cr, status);
- return (cairo_font_face_t*) &_cairo_font_face_nil;
- }
-
- return font_face;
+ return cr->backend->get_font_face (cr);
}
/**
@@ -2927,11 +2708,14 @@ cairo_get_font_face (cairo_t *cr)
void
cairo_set_font_size (cairo_t *cr, double size)
{
- cairo_matrix_t scale;
+ cairo_status_t status;
- cairo_matrix_init_scale (&scale, size, size);
+ if (unlikely (cr->status))
+ return;
- cairo_set_font_matrix (cr, &scale);
+ status = cr->backend->set_font_size (cr, size);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_font_size);
@@ -2957,7 +2741,7 @@ cairo_set_font_matrix (cairo_t *cr,
if (unlikely (cr->status))
return;
- status = _cairo_gstate_set_font_matrix (cr->gstate, matrix);
+ status = cr->backend->set_font_matrix (cr, matrix);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -2979,7 +2763,7 @@ cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix)
return;
}
- _cairo_gstate_get_font_matrix (cr->gstate, matrix);
+ cr->backend->get_font_matrix (cr, matrix);
}
/**
@@ -3008,7 +2792,9 @@ cairo_set_font_options (cairo_t *cr,
return;
}
- _cairo_gstate_set_font_options (cr->gstate, options);
+ status = cr->backend->set_font_options (cr, options);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
}
slim_hidden_def (cairo_set_font_options);
@@ -3036,7 +2822,7 @@ cairo_get_font_options (cairo_t *cr,
return;
}
- _cairo_gstate_get_font_options (cr->gstate, options);
+ cr->backend->get_font_options (cr, options);
}
/**
@@ -3057,42 +2843,24 @@ cairo_set_scaled_font (cairo_t *cr,
const cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
- cairo_bool_t was_previous;
if (unlikely (cr->status))
return;
- if (scaled_font == NULL) {
- status = _cairo_error (CAIRO_STATUS_NULL_POINTER);
- goto BAIL;
+ if ((scaled_font == NULL)) {
+ _cairo_set_error (cr, _cairo_error (CAIRO_STATUS_NULL_POINTER));
+ return;
}
status = scaled_font->status;
- if (unlikely (status))
- goto BAIL;
-
- if (scaled_font == cr->gstate->scaled_font)
+ if (unlikely (status)) {
+ _cairo_set_error (cr, status);
return;
+ }
- was_previous = scaled_font == cr->gstate->previous_scaled_font;
-
- status = _cairo_gstate_set_font_face (cr->gstate, scaled_font->font_face);
- if (unlikely (status))
- goto BAIL;
-
- status = _cairo_gstate_set_font_matrix (cr->gstate, &scaled_font->font_matrix);
+ status = cr->backend->set_scaled_font (cr, (cairo_scaled_font_t *) scaled_font);
if (unlikely (status))
- goto BAIL;
-
- _cairo_gstate_set_font_options (cr->gstate, &scaled_font->options);
-
- if (was_previous)
- cr->gstate->scaled_font = cairo_scaled_font_reference ((cairo_scaled_font_t *) scaled_font);
-
- return;
-
-BAIL:
- _cairo_set_error (cr, status);
+ _cairo_set_error (cr, status);
}
/**
@@ -3118,20 +2886,12 @@ BAIL:
cairo_scaled_font_t *
cairo_get_scaled_font (cairo_t *cr)
{
- cairo_status_t status;
- cairo_scaled_font_t *scaled_font;
-
if (unlikely (cr->status))
return _cairo_scaled_font_create_in_error (cr->status);
- status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
- if (unlikely (status)) {
- _cairo_set_error (cr, status);
- return _cairo_scaled_font_create_in_error (status);
- }
-
- return scaled_font;
+ return cr->backend->get_scaled_font (cr);
}
+slim_hidden_def (cairo_get_scaled_font);
/**
* cairo_text_extents:
@@ -3159,8 +2919,9 @@ cairo_text_extents (cairo_t *cr,
cairo_text_extents_t *extents)
{
cairo_status_t status;
+ cairo_scaled_font_t *scaled_font;
cairo_glyph_t *glyphs = NULL;
- int num_glyphs;
+ int num_glyphs = 0;
double x, y;
extents->x_bearing = 0.0;
@@ -3176,19 +2937,24 @@ cairo_text_extents (cairo_t *cr,
if (utf8 == NULL)
return;
- cairo_get_current_point (cr, &x, &y);
+ scaled_font = cairo_get_scaled_font (cr);
+ if (unlikely (scaled_font->status)) {
+ _cairo_set_error (cr, scaled_font->status);
+ return;
+ }
- status = _cairo_gstate_text_to_glyphs (cr->gstate,
- x, y,
- utf8, strlen (utf8),
- &glyphs, &num_glyphs,
- NULL, NULL,
- NULL);
-
- if (status == CAIRO_STATUS_SUCCESS)
- status = _cairo_gstate_glyph_extents (cr->gstate,
- glyphs, num_glyphs,
- extents);
+ cairo_get_current_point (cr, &x, &y);
+ status = cairo_scaled_font_text_to_glyphs (scaled_font,
+ x, y,
+ utf8, -1,
+ &glyphs, &num_glyphs,
+ NULL, NULL, NULL);
+
+ if (likely (status == CAIRO_STATUS_SUCCESS)) {
+ status = cr->backend->glyph_extents (cr,
+ glyphs, num_glyphs,
+ extents);
+ }
cairo_glyph_free (glyphs);
if (unlikely (status))
@@ -3234,18 +3000,17 @@ cairo_glyph_extents (cairo_t *cr,
if (num_glyphs == 0)
return;
- if (num_glyphs < 0) {
+ if (unlikely (num_glyphs < 0)) {
_cairo_set_error (cr, CAIRO_STATUS_NEGATIVE_COUNT);
return;
}
- if (glyphs == NULL) {
+ if (unlikely (glyphs == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
- status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs,
- extents);
+ status = cr->backend->glyph_extents (cr, glyphs, num_glyphs, extents);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -3290,6 +3055,8 @@ cairo_show_text (cairo_t *cr, const char *utf8)
cairo_bool_t has_show_text_glyphs;
cairo_glyph_t stack_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
cairo_text_cluster_t stack_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
+ cairo_scaled_font_t *scaled_font;
+ cairo_glyph_text_info_t info;
if (unlikely (cr->status))
return;
@@ -3297,7 +3064,11 @@ cairo_show_text (cairo_t *cr, const char *utf8)
if (utf8 == NULL)
return;
- cairo_get_current_point (cr, &x, &y);
+ scaled_font = cairo_get_scaled_font (cr);
+ if (unlikely (scaled_font->status)) {
+ _cairo_set_error (cr, scaled_font->status);
+ return;
+ }
utf8_len = strlen (utf8);
@@ -3315,36 +3086,37 @@ cairo_show_text (cairo_t *cr, const char *utf8)
num_clusters = 0;
}
- status = _cairo_gstate_text_to_glyphs (cr->gstate,
- x, y,
- utf8, utf8_len,
- &glyphs, &num_glyphs,
- has_show_text_glyphs ? &clusters : NULL, &num_clusters,
- &cluster_flags);
+ cairo_get_current_point (cr, &x, &y);
+ status = cairo_scaled_font_text_to_glyphs (scaled_font,
+ x, y,
+ utf8, utf8_len,
+ &glyphs, &num_glyphs,
+ has_show_text_glyphs ? &clusters : NULL, &num_clusters,
+ &cluster_flags);
if (unlikely (status))
goto BAIL;
if (num_glyphs == 0)
return;
- status = _cairo_gstate_show_text_glyphs (cr->gstate,
- utf8, utf8_len,
- glyphs, num_glyphs,
- clusters, num_clusters,
- cluster_flags);
+ info.utf8 = utf8;
+ info.utf8_len = utf8_len;
+ info.clusters = clusters;
+ info.num_clusters = num_clusters;
+ info.cluster_flags = cluster_flags;
+
+ status = cr->backend->glyphs (cr, glyphs, num_glyphs, &info);
if (unlikely (status))
goto BAIL;
last_glyph = &glyphs[num_glyphs - 1];
- status = _cairo_gstate_glyph_extents (cr->gstate,
- last_glyph, 1,
- &extents);
+ status = cr->backend->glyph_extents (cr, last_glyph, 1, &extents);
if (unlikely (status))
goto BAIL;
x = last_glyph->x + extents.x_advance;
y = last_glyph->y + extents.y_advance;
- cairo_move_to (cr, x, y);
+ cr->backend->move_to (cr, x, y);
BAIL:
if (glyphs != stack_glyphs)
@@ -3387,11 +3159,7 @@ cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
return;
}
- status = _cairo_gstate_show_text_glyphs (cr->gstate,
- NULL, 0,
- glyphs, num_glyphs,
- NULL, 0,
- FALSE);
+ status = cr->backend->glyphs (cr, glyphs, num_glyphs, NULL);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -3469,32 +3237,38 @@ cairo_show_text_glyphs (cairo_t *cr,
return;
}
- /* Make sure clusters cover the entire glyphs and utf8 arrays,
- * and that cluster boundaries are UTF-8 boundaries. */
- status = _cairo_validate_text_clusters (utf8, utf8_len,
- glyphs, num_glyphs,
- clusters, num_clusters, cluster_flags);
- if (status == CAIRO_STATUS_INVALID_CLUSTERS) {
- /* Either got invalid UTF-8 text, or cluster mapping is bad.
- * Differentiate those. */
-
- cairo_status_t status2;
-
- status2 = _cairo_utf8_to_ucs4 (utf8, utf8_len, NULL, NULL);
- if (status2)
- status = status2;
-
- _cairo_set_error (cr, status);
- return;
- }
-
if (num_glyphs == 0 && utf8_len == 0)
return;
- status = _cairo_gstate_show_text_glyphs (cr->gstate,
- utf8, utf8_len,
- glyphs, num_glyphs,
- clusters, num_clusters, cluster_flags);
+ if (utf8) {
+ /* Make sure clusters cover the entire glyphs and utf8 arrays,
+ * and that cluster boundaries are UTF-8 boundaries. */
+ status = _cairo_validate_text_clusters (utf8, utf8_len,
+ glyphs, num_glyphs,
+ clusters, num_clusters, cluster_flags);
+ if (status == CAIRO_STATUS_INVALID_CLUSTERS) {
+ /* Either got invalid UTF-8 text, or cluster mapping is bad.
+ * Differentiate those. */
+
+ cairo_status_t status2;
+
+ status2 = _cairo_utf8_to_ucs4 (utf8, utf8_len, NULL, NULL);
+ if (status2)
+ status = status2;
+ } else {
+ cairo_glyph_text_info_t info;
+
+ info.utf8 = utf8;
+ info.utf8_len = utf8_len;
+ info.clusters = clusters;
+ info.num_clusters = num_clusters;
+ info.cluster_flags = cluster_flags;
+
+ status = cr->backend->glyphs (cr, glyphs, num_glyphs, &info);
+ }
+ } else {
+ status = cr->backend->glyphs (cr, glyphs, num_glyphs, NULL);
+ }
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -3524,12 +3298,13 @@ cairo_show_text_glyphs (cairo_t *cr,
* "real" text path API in cairo.
**/
void
-cairo_text_path (cairo_t *cr, const char *utf8)
+cairo_text_path (cairo_t *cr, const char *utf8)
{
cairo_status_t status;
cairo_text_extents_t extents;
cairo_glyph_t stack_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
cairo_glyph_t *glyphs, *last_glyph;
+ cairo_scaled_font_t *scaled_font;
int num_glyphs;
double x, y;
@@ -3539,42 +3314,40 @@ cairo_text_path (cairo_t *cr, const char *utf8)
if (utf8 == NULL)
return;
- cairo_get_current_point (cr, &x, &y);
glyphs = stack_glyphs;
num_glyphs = ARRAY_LENGTH (stack_glyphs);
- status = _cairo_gstate_text_to_glyphs (cr->gstate,
- x, y,
- utf8, strlen (utf8),
- &glyphs, &num_glyphs,
- NULL, NULL,
- NULL);
+ scaled_font = cairo_get_scaled_font (cr);
+ if (unlikely (scaled_font->status)) {
+ _cairo_set_error (cr, scaled_font->status);
+ return;
+ }
- if (unlikely (status))
- goto BAIL;
+ cairo_get_current_point (cr, &x, &y);
+ status = cairo_scaled_font_text_to_glyphs (scaled_font,
+ x, y,
+ utf8, -1,
+ &glyphs, &num_glyphs,
+ NULL, NULL, NULL);
if (num_glyphs == 0)
return;
- status = _cairo_gstate_glyph_path (cr->gstate,
- glyphs, num_glyphs,
- cr->path);
+ status = cr->backend->glyph_path (cr, glyphs, num_glyphs);
if (unlikely (status))
goto BAIL;
last_glyph = &glyphs[num_glyphs - 1];
- status = _cairo_gstate_glyph_extents (cr->gstate,
- last_glyph, 1,
- &extents);
+ status = cr->backend->glyph_extents (cr, last_glyph, 1, &extents);
if (unlikely (status))
goto BAIL;
x = last_glyph->x + extents.x_advance;
y = last_glyph->y + extents.y_advance;
- cairo_move_to (cr, x, y);
+ cr->backend->move_to (cr, x, y);
BAIL:
if (glyphs != stack_glyphs)
@@ -3605,19 +3378,17 @@ cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
if (num_glyphs == 0)
return;
- if (num_glyphs < 0) {
+ if (unlikely (num_glyphs < 0)) {
_cairo_set_error (cr, CAIRO_STATUS_NEGATIVE_COUNT);
return;
}
- if (glyphs == NULL) {
+ if (unlikely (glyphs == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
- status = _cairo_gstate_glyph_path (cr->gstate,
- glyphs, num_glyphs,
- cr->path);
+ status = cr->backend->glyph_path (cr, glyphs, num_glyphs);
if (unlikely (status))
_cairo_set_error (cr, status);
}
@@ -3636,8 +3407,27 @@ cairo_get_operator (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_GSTATE_OPERATOR_DEFAULT;
- return _cairo_gstate_get_operator (cr->gstate);
+ return cr->backend->get_operator (cr);
+}
+
+#if 0
+/**
+ * cairo_get_opacity:
+ * @cr: a cairo context
+ *
+ * Gets the current compositing opacity for a cairo context.
+ *
+ * Return value: the current compositing opacity.
+ **/
+double
+cairo_get_opacity (cairo_t *cr)
+{
+ if (unlikely (cr->status))
+ return 1.;
+
+ return cr->backend->get_opacity (cr);
}
+#endif
/**
* cairo_get_tolerance:
@@ -3653,7 +3443,7 @@ cairo_get_tolerance (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_GSTATE_TOLERANCE_DEFAULT;
- return _cairo_gstate_get_tolerance (cr->gstate);
+ return cr->backend->get_tolerance (cr);
}
slim_hidden_def (cairo_get_tolerance);
@@ -3672,7 +3462,7 @@ cairo_get_antialias (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_ANTIALIAS_DEFAULT;
- return _cairo_gstate_get_antialias (cr->gstate);
+ return cr->backend->get_antialias (cr);
}
/**
@@ -3690,9 +3480,9 @@ cairo_bool_t
cairo_has_current_point (cairo_t *cr)
{
if (unlikely (cr->status))
- return FALSE;
+ return FALSE;
- return cr->path->has_current_point;
+ return cr->backend->has_current_point (cr);
}
/**
@@ -3728,20 +3518,13 @@ cairo_has_current_point (cairo_t *cr)
void
cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
{
- cairo_fixed_t x_fixed, y_fixed;
double x, y;
+ x = y = 0;
if (cr->status == CAIRO_STATUS_SUCCESS &&
- _cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed))
- {
- x = _cairo_fixed_to_double (x_fixed);
- y = _cairo_fixed_to_double (y_fixed);
- _cairo_gstate_backend_to_user (cr->gstate, &x, &y);
- }
- else
+ cr->backend->has_current_point (cr))
{
- x = 0.0;
- y = 0.0;
+ cr->backend->get_current_point (cr, &x, &y);
}
if (x_ret)
@@ -3765,7 +3548,7 @@ cairo_get_fill_rule (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_GSTATE_FILL_RULE_DEFAULT;
- return _cairo_gstate_get_fill_rule (cr->gstate);
+ return cr->backend->get_fill_rule (cr);
}
/**
@@ -3785,7 +3568,7 @@ cairo_get_line_width (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
- return _cairo_gstate_get_line_width (cr->gstate);
+ return cr->backend->get_line_width (cr);
}
slim_hidden_def (cairo_get_line_width);
@@ -3803,7 +3586,7 @@ cairo_get_line_cap (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_GSTATE_LINE_CAP_DEFAULT;
- return _cairo_gstate_get_line_cap (cr->gstate);
+ return cr->backend->get_line_cap (cr);
}
/**
@@ -3820,7 +3603,7 @@ cairo_get_line_join (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_GSTATE_LINE_JOIN_DEFAULT;
- return _cairo_gstate_get_line_join (cr->gstate);
+ return cr->backend->get_line_join (cr);
}
/**
@@ -3837,7 +3620,7 @@ cairo_get_miter_limit (cairo_t *cr)
if (unlikely (cr->status))
return CAIRO_GSTATE_MITER_LIMIT_DEFAULT;
- return _cairo_gstate_get_miter_limit (cr->gstate);
+ return cr->backend->get_miter_limit (cr);
}
/**
@@ -3855,7 +3638,7 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
return;
}
- _cairo_gstate_get_matrix (cr->gstate, matrix);
+ cr->backend->get_matrix (cr, matrix);
}
slim_hidden_def (cairo_get_matrix);
@@ -3881,7 +3664,7 @@ cairo_get_target (cairo_t *cr)
if (unlikely (cr->status))
return _cairo_surface_create_in_error (cr->status);
- return _cairo_gstate_get_original_target (cr->gstate);
+ return cr->backend->get_original_target (cr);
}
slim_hidden_def (cairo_get_target);
@@ -3911,7 +3694,7 @@ cairo_get_group_target (cairo_t *cr)
if (unlikely (cr->status))
return _cairo_surface_create_in_error (cr->status);
- return _cairo_gstate_get_target (cr->gstate);
+ return cr->backend->get_current_target (cr);
}
/**
@@ -3946,7 +3729,7 @@ cairo_copy_path (cairo_t *cr)
if (unlikely (cr->status))
return _cairo_path_create_in_error (cr->status);
- return _cairo_path_create (cr->path, cr->gstate);
+ return cr->backend->copy_path (cr);
}
/**
@@ -3988,7 +3771,7 @@ cairo_copy_path_flat (cairo_t *cr)
if (unlikely (cr->status))
return _cairo_path_create_in_error (cr->status);
- return _cairo_path_create_flat (cr->path, cr->gstate);
+ return cr->backend->copy_path_flat (cr);
}
/**
@@ -4012,12 +3795,12 @@ cairo_append_path (cairo_t *cr,
if (unlikely (cr->status))
return;
- if (path == NULL) {
+ if (unlikely (path == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
- if (path->status) {
+ if (unlikely (path->status)) {
if (path->status > CAIRO_STATUS_SUCCESS &&
path->status <= CAIRO_STATUS_LAST_STATUS)
_cairo_set_error (cr, path->status);
@@ -4029,12 +3812,12 @@ cairo_append_path (cairo_t *cr,
if (path->num_data == 0)
return;
- if (path->data == NULL) {
+ if (unlikely (path->data == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
- status = _cairo_path_append_to_context (path, cr);
+ status = cr->backend->append_path (cr, path);
if (unlikely (status))
_cairo_set_error (cr, status);
}
diff --git a/src/cairoint.h b/src/cairoint.h
index 3ab77016..13d15556 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -409,7 +409,7 @@ struct _cairo_font_face {
};
cairo_private void
-_cairo_reset_static_data (void);
+_cairo_default_context_reset_static_data (void);
cairo_private void
_cairo_toy_font_face_reset_static_data (void);
@@ -599,6 +599,9 @@ extern const cairo_private struct _cairo_font_face_backend _cairo_quartz_font_fa
struct _cairo_surface_backend {
cairo_surface_type_t type;
+ cairo_t *
+ (*create_context) (void *surface);
+
cairo_surface_t *
(*create_similar) (void *surface,
cairo_content_t content,
@@ -1357,7 +1360,7 @@ _cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t *path,
const cairo_matrix_t *ctm,
cairo_boxes_t *boxes);
-cairo_private cairo_status_t
+cairo_private cairo_int_status_t
_cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
const cairo_stroke_style_t *stroke_style,
const cairo_matrix_t *ctm,
@@ -2404,6 +2407,7 @@ slim_hidden_proto (cairo_format_stride_for_width);
slim_hidden_proto (cairo_get_current_point);
slim_hidden_proto (cairo_get_line_width);
slim_hidden_proto (cairo_get_matrix);
+slim_hidden_proto (cairo_get_scaled_font);
slim_hidden_proto (cairo_get_target);
slim_hidden_proto (cairo_get_tolerance);
slim_hidden_proto (cairo_glyph_allocate);
@@ -2511,6 +2515,7 @@ slim_hidden_proto (cairo_user_font_face_create);
slim_hidden_proto (cairo_user_font_face_set_init_func);
slim_hidden_proto (cairo_user_font_face_set_render_glyph_func);
slim_hidden_proto (cairo_user_font_face_set_unicode_to_glyph_func);
+slim_hidden_proto (cairo_device_to_user);
slim_hidden_proto (cairo_user_to_device);
slim_hidden_proto (cairo_user_to_device_distance);
slim_hidden_proto (cairo_version_string);
diff --git a/src/drm/cairo-drm-gallium-surface.c b/src/drm/cairo-drm-gallium-surface.c
index 76fbae64..b4897530 100644
--- a/src/drm/cairo-drm-gallium-surface.c
+++ b/src/drm/cairo-drm-gallium-surface.c
@@ -34,6 +34,7 @@
#include "cairoint.h"
#include "cairo-drm-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include <dlfcn.h>
@@ -462,6 +463,8 @@ gallium_surface_glyphs (void *abstract_surface,
static const cairo_surface_backend_t gallium_surface_backend = {
CAIRO_SURFACE_TYPE_DRM,
+ _cairo_default_context_create,
+
gallium_surface_create_similar,
gallium_surface_finish,
diff --git a/src/drm/cairo-drm-i915-surface.c b/src/drm/cairo-drm-i915-surface.c
index 247d8ad5..2a55889f 100644
--- a/src/drm/cairo-drm-i915-surface.c
+++ b/src/drm/cairo-drm-i915-surface.c
@@ -103,6 +103,7 @@
#include "cairo-boxes-private.h"
#include "cairo-cache-private.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-freelist-private.h"
#include "cairo-list-private.h"
@@ -2338,6 +2339,7 @@ i915_surface_fill (void *abstract_dst,
static const cairo_surface_backend_t i915_surface_backend = {
CAIRO_SURFACE_TYPE_DRM,
+ _cairo_default_context_create,
i915_surface_create_similar,
i915_surface_finish,
diff --git a/src/drm/cairo-drm-i965-surface.c b/src/drm/cairo-drm-i965-surface.c
index 39478362..71061a0e 100644
--- a/src/drm/cairo-drm-i965-surface.c
+++ b/src/drm/cairo-drm-i965-surface.c
@@ -56,6 +56,7 @@
#include "cairo-boxes-private.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-region-private.h"
#include "cairo-surface-offset-private.h"
@@ -1490,6 +1491,7 @@ CLEANUP_BOXES:
static const cairo_surface_backend_t i965_surface_backend = {
CAIRO_SURFACE_TYPE_DRM,
+ _cairo_default_context_create,
i965_surface_create_similar,
i965_surface_finish,
diff --git a/src/drm/cairo-drm-intel-surface.c b/src/drm/cairo-drm-intel-surface.c
index 96d46159..f28c7500 100644
--- a/src/drm/cairo-drm-intel-surface.c
+++ b/src/drm/cairo-drm-intel-surface.c
@@ -32,6 +32,7 @@
#include "cairo-drm-private.h"
#include "cairo-drm-intel-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
/* Basic generic/stub surface for intel chipsets */
@@ -248,6 +249,7 @@ intel_surface_glyphs (void *abstract_surface,
static const cairo_surface_backend_t intel_surface_backend = {
CAIRO_SURFACE_TYPE_DRM,
+ _cairo_default_context_create,
intel_surface_create_similar,
intel_surface_finish,
diff --git a/src/drm/cairo-drm-radeon-surface.c b/src/drm/cairo-drm-radeon-surface.c
index cbcef2a5..9335d7b7 100644
--- a/src/drm/cairo-drm-radeon-surface.c
+++ b/src/drm/cairo-drm-radeon-surface.c
@@ -32,6 +32,7 @@
#include "cairo-drm-private.h"
#include "cairo-drm-radeon-private.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
/* Basic stub surface for radeon chipsets */
@@ -252,6 +253,7 @@ radeon_surface_glyphs (void *abstract_surface,
static const cairo_surface_backend_t radeon_surface_backend = {
CAIRO_SURFACE_TYPE_DRM,
+ _cairo_default_context_create,
radeon_surface_create_similar,
radeon_surface_finish,
diff --git a/src/test-fallback-surface.c b/src/test-fallback-surface.c
index 66399d4a..5695dc96 100644
--- a/src/test-fallback-surface.c
+++ b/src/test-fallback-surface.c
@@ -54,6 +54,7 @@
#include "cairoint.h"
#include "test-fallback-surface.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
typedef struct _test_fallback_surface {
@@ -207,6 +208,8 @@ _test_fallback_surface_get_extents (void *abstract_surface,
static const cairo_surface_backend_t test_fallback_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ _cairo_default_context_create,
+
_test_fallback_surface_create_similar,
_test_fallback_surface_finish,
_test_fallback_surface_acquire_source_image,
diff --git a/src/test-fallback16-surface.c b/src/test-fallback16-surface.c
index ce2febca..2f4da5bf 100644
--- a/src/test-fallback16-surface.c
+++ b/src/test-fallback16-surface.c
@@ -43,6 +43,7 @@
#include "cairoint.h"
#include "test-fallback16-surface.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
typedef struct _test_fallback16_surface {
@@ -204,6 +205,8 @@ _test_fallback16_surface_get_extents (void *abstract_surface,
static const cairo_surface_backend_t test_fallback16_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ _cairo_default_context_create,
+
_test_fallback16_surface_create_similar,
_test_fallback16_surface_finish,
_test_fallback16_surface_acquire_source_image,
diff --git a/src/test-null-surface.c b/src/test-null-surface.c
index 0247d924..620dd2f1 100644
--- a/src/test-null-surface.c
+++ b/src/test-null-surface.c
@@ -40,6 +40,7 @@
#include "test-null-surface.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
slim_hidden_proto (_cairo_test_null_surface_create);
@@ -133,6 +134,7 @@ _cairo_null_surface_has_show_text_glyphs (void *surface)
static const cairo_surface_backend_t null_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
+ _cairo_default_context_create,
_cairo_null_surface_create_similar,
NULL, /* finish */
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index e06cbed7..241f1bd1 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -49,6 +49,7 @@
#include "test-paginated-surface.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-paginated-private.h"
@@ -240,6 +241,7 @@ _test_paginated_surface_set_paginated_mode (void *abstract_surface,
static const cairo_surface_backend_t test_paginated_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
+ _cairo_default_context_create,
/* Since we are a paginated user, we get to regard most of the
* surface backend interface as historical cruft and ignore it. */
diff --git a/src/test-wrapping-surface.c b/src/test-wrapping-surface.c
index 4a60139d..4dd6c4c6 100644
--- a/src/test-wrapping-surface.c
+++ b/src/test-wrapping-surface.c
@@ -43,6 +43,7 @@
#include "test-wrapping-surface.h"
+#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-surface-wrapper-private.h"
@@ -234,6 +235,8 @@ _test_wrapping_surface_show_text_glyphs (void *abstract_surface,
static const cairo_surface_backend_t test_wrapping_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
+ _cairo_default_context_create,
+
_test_wrapping_surface_create_similar,
_test_wrapping_surface_finish,
_test_wrapping_surface_acquire_source_image,