summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2005-04-26 12:38:06 +0000
committerCarl Worth <cworth@cworth.org>2005-04-26 12:38:06 +0000
commit1baa4d132903e21395dc66ca792164e2ef8885d2 (patch)
tree4b95e9a13ee0b7bcab4a9f22d919e493376d16eb
parent618792c8c041ee2004acf1ff411e0adbe94a3e63 (diff)
Originally: 2005-04-19 Carl Worth <cworth@cworth.org>
Add cairo_stroke_preserve, cairo_fill_preserve, and cairo_clip_preserve. Rip the path out of cairo_gstate_t. Add path to cairo_t. Bring in most of the path code that used to live in cairo-gstate.c Move arc generation code into its own file. Accept path+ctm_inverse+tolerance instead of gstate. Absorb flattening and device space->user space conversion that used to be in _cairo_gstate_intepret_path. Prefer cairo_fixed_t parameters over ciaro_point_t for cross-file interfaces. Track changes in _cairo_path_fixed interfaces. Port to use cairo_fill_preserve rather than cairo_save/cairo_restore which no longer work for saving the path. Remove get and set of current point since it is no longer affected by cairo_save and cairo_restore. Add get and set testing for cairo_matrix_t.
-rw-r--r--ChangeLog40
-rw-r--r--TODO2
-rw-r--r--src/Makefile.am1
-rw-r--r--src/cairo-arc-private.h57
-rw-r--r--src/cairo-arc.c296
-rw-r--r--src/cairo-ft-font.c60
-rw-r--r--src/cairo-gstate-private.h4
-rw-r--r--src/cairo-gstate.c677
-rw-r--r--src/cairo-path-data-private.h8
-rw-r--r--src/cairo-path-data.c239
-rw-r--r--src/cairo-path.c93
-rw-r--r--src/cairo-private.h4
-rw-r--r--src/cairo.c321
-rw-r--r--src/cairo.h10
-rw-r--r--src/cairoint.h159
-rw-r--r--test/fill-and-stroke.c8
-rw-r--r--test/get-and-set.c37
17 files changed, 1106 insertions, 910 deletions
diff --git a/ChangeLog b/ChangeLog
index cc9f9d55..a0915c39 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,45 @@
2005-04-26 Carl Worth <cworth@cworth.org>
+ Originally: 2005-04-19 Carl Worth <cworth@cworth.org>
+
+ * src/cairo.h: Add cairo_stroke_preserve, cairo_fill_preserve,
+ and cairo_clip_preserve.
+
+ * src/cairoint.h:
+ * src/cairo-gstate-private.h:
+ * src/cairo-gstate.c: Rip the path out of cairo_gstate_t.
+
+ * src/cairo-private.h: Add path to cairo_t.
+
+ * src/cairo.c: Bring in most of the path code that used to live in
+ cairo-gstate.c
+
+ * src/Makefile.am:
+ * src/cairo-arc-private.h:
+ * src/cairo-arc.c: Move arc generation code into its own file.
+
+ * src/cairo-path-data-private.h:
+ * src/cairo-path-data.c: Accept path+ctm_inverse+tolerance instead
+ of gstate. Absorb flattening and device space->user space
+ conversion that used to be in _cairo_gstate_intepret_path.
+
+ * src/cairo-path.c: Prefer cairo_fixed_t parameters over
+ ciaro_point_t for cross-file interfaces.
+
+ * src/cairo-ft-font.c: Track changes in _cairo_path_fixed
+ interfaces.
+
+ * test/fill-and-stroke.c: (draw): Port to use cairo_fill_preserve
+ rather than cairo_save/cairo_restore which no longer work for
+ saving the path.
+
+ * test/get-and-set.c: (settings_set), (settings_get),
+ (settings_equal): Remove get and set of current point since it is
+ no longer affected by cairo_save and cairo_restore. Add get and
+ set testing for cairo_matrix_t.
+
+2005-04-26 Carl Worth <cworth@cworth.org>
+
* test/.cvsignore:
* test/Makefile.am:
* test/cairo-test.h:
diff --git a/TODO b/TODO
index cc9c5fa1..0291162e 100644
--- a/TODO
+++ b/TODO
@@ -23,7 +23,7 @@ PDRTC Making set_source consistent
PDRTC cairo_current_matrix
cairo_mask
cairo_create and eliminating cairo_set_target_surface
-PD T cairo_fill_preserve, cairo_stroke_preserve, cairo_clip_preserve
+PDRTC cairo_fill_preserve, cairo_stroke_preserve, cairo_clip_preserve
cairo_<device>_surface_mark_dirty
PDR C A hidden offset for the xlib backend
Simplifying the operator set
diff --git a/src/Makefile.am b/src/Makefile.am
index c31b94ac..a16cd096 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,6 +78,7 @@ lib_LTLIBRARIES = libcairo.la
libcairo_la_SOURCES = \
cairo.c \
cairo.h \
+ cairo-arc.c \
cairo-array.c \
cairo-cache.c \
cairo-color.c \
diff --git a/src/cairo-arc-private.h b/src/cairo-arc-private.h
new file mode 100644
index 00000000..1cd41cc1
--- /dev/null
+++ b/src/cairo-arc-private.h
@@ -0,0 +1,57 @@
+/* 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_ARC_PRIVATE_H
+#define CAIRO_ARC_PRIVATE_H
+
+#include "cairoint.h"
+
+void
+_cairo_arc_path (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2);
+
+void
+_cairo_arc_path_negative (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2);
+
+#endif /* CAIRO_ARC_PRIVATE_H */
diff --git a/src/cairo-arc.c b/src/cairo-arc.c
new file mode 100644
index 00000000..2e6c6895
--- /dev/null
+++ b/src/cairo-arc.c
@@ -0,0 +1,296 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ */
+
+#include <math.h>
+
+#include "cairo-arc-private.h"
+
+/* Spline deviation from the circle in radius would be given by:
+
+ error = sqrt (x**2 + y**2) - 1
+
+ A simpler error function to work with is:
+
+ e = x**2 + y**2 - 1
+
+ From "Good approximation of circles by curvature-continuous Bezier
+ curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric
+ Design 8 (1990) 22-41, we learn:
+
+ abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4)
+
+ and
+ abs (error) =~ 1/2 * e
+
+ Of course, this error value applies only for the particular spline
+ approximation that is used in _cairo_gstate_arc_segment.
+*/
+static double
+_arc_error_normalized (double angle)
+{
+ return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
+}
+
+static double
+_arc_max_angle_for_tolerance_normalized (double tolerance)
+{
+ double angle, error;
+ int i;
+
+ /* Use table lookup to reduce search time in most cases. */
+ struct {
+ double angle;
+ double error;
+ } table[] = {
+ { M_PI / 1.0, 0.0185185185185185036127 },
+ { M_PI / 2.0, 0.000272567143730179811158 },
+ { M_PI / 3.0, 2.38647043651461047433e-05 },
+ { M_PI / 4.0, 4.2455377443222443279e-06 },
+ { M_PI / 5.0, 1.11281001494389081528e-06 },
+ { M_PI / 6.0, 3.72662000942734705475e-07 },
+ { M_PI / 7.0, 1.47783685574284411325e-07 },
+ { M_PI / 8.0, 6.63240432022601149057e-08 },
+ { M_PI / 9.0, 3.2715520137536980553e-08 },
+ { M_PI / 10.0, 1.73863223499021216974e-08 },
+ { M_PI / 11.0, 9.81410988043554039085e-09 },
+ };
+ int table_size = (sizeof (table) / sizeof (table[0]));
+
+ for (i = 0; i < table_size; i++)
+ if (table[i].error < tolerance)
+ return table[i].angle;
+
+ ++i;
+ do {
+ angle = M_PI / i++;
+ error = _arc_error_normalized (angle);
+ } while (error > tolerance);
+
+ return angle;
+}
+
+static int
+_arc_segments_needed (double angle,
+ double radius,
+ cairo_matrix_t *ctm,
+ double tolerance)
+{
+ double l1, l2, lmax;
+ double max_angle;
+
+ _cairo_matrix_compute_eigen_values (ctm, &l1, &l2);
+
+ l1 = fabs (l1);
+ l2 = fabs (l2);
+ if (l1 > l2)
+ lmax = l1;
+ else
+ lmax = l2;
+
+ max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / (radius * lmax));
+
+ return (int) ceil (angle / max_angle);
+}
+
+/* We want to draw a single spline approximating a circular arc radius
+ R from angle A to angle B. Since we want a symmetric spline that
+ matches the endpoints of the arc in position and slope, we know
+ that the spline control points must be:
+
+ (R * cos(A), R * sin(A))
+ (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
+ (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
+ (R * cos(B), R * sin(B))
+
+ for some value of h.
+
+ "Approximation of circular arcs by cubic poynomials", Michael
+ Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
+ various values of h along with error analysis for each.
+
+ From that paper, a very practical value of h is:
+
+ h = 4/3 * tan(angle/4)
+
+ This value does not give the spline with minimal error, but it does
+ provide a very good approximation, (6th-order convergence), and the
+ error expression is quite simple, (see the comment for
+ _arc_error_normalized).
+*/
+static void
+_cairo_arc_segment (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle_A,
+ double angle_B)
+{
+ double r_sin_A, r_cos_A;
+ double r_sin_B, r_cos_B;
+ double h;
+
+ r_sin_A = radius * sin (angle_A);
+ r_cos_A = radius * cos (angle_A);
+ r_sin_B = radius * sin (angle_B);
+ r_cos_B = radius * cos (angle_B);
+
+ h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
+
+ cairo_curve_to (cr,
+ xc + r_cos_A - h * r_sin_A,
+ yc + r_sin_A + h * r_cos_A,
+ xc + r_cos_B + h * r_sin_B,
+ yc + r_sin_B - h * r_cos_B,
+ xc + r_cos_B,
+ yc + r_sin_B);
+}
+
+static void
+_cairo_arc_in_direction (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle_min,
+ double angle_max,
+ cairo_direction_t dir)
+{
+ while (angle_max - angle_min > 4 * M_PI)
+ angle_max -= 2 * M_PI;
+
+ /* Recurse if drawing arc larger than pi */
+ if (angle_max - angle_min > M_PI) {
+ double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
+ /* XXX: Something tells me this block could be condensed. */
+ if (dir == CAIRO_DIRECTION_FORWARD) {
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_min, angle_mid,
+ dir);
+
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_mid, angle_max,
+ dir);
+ } else {
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_mid, angle_max,
+ dir);
+
+ _cairo_arc_in_direction (cr, xc, yc, radius,
+ angle_min, angle_mid,
+ dir);
+ }
+ } else {
+ cairo_matrix_t ctm;
+ int i, segments;
+ double angle, angle_step;
+
+ cairo_get_matrix (cr, &ctm);
+ segments = _arc_segments_needed (angle_max - angle_min,
+ radius, &ctm,
+ cairo_get_tolerance (cr));
+ angle_step = (angle_max - angle_min) / (double) segments;
+
+ if (dir == CAIRO_DIRECTION_FORWARD) {
+ angle = angle_min;
+ } else {
+ angle = angle_max;
+ angle_step = - angle_step;
+ }
+
+ for (i = 0; i < segments; i++, angle += angle_step) {
+ _cairo_arc_segment (cr, xc, yc,
+ radius,
+ angle,
+ angle + angle_step);
+ }
+ }
+}
+
+/**
+ * _cairo_arc_path_negative:
+ * @cr: a cairo context
+ * @xc: X position of the center of the arc
+ * @yc: Y position of the center of the arc
+ * @radius: the radius of the arc
+ * @angle1: the start angle, in radians
+ * @angle2: the end angle, in radians
+ *
+ * Compute a path for the given arc and append it onto the current
+ * path within @cr. The arc will be accurate within the current
+ * tolerance and given the current transformation.
+ **/
+void
+_cairo_arc_path (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2)
+{
+ _cairo_arc_in_direction (cr, xc, yc,
+ radius,
+ angle1, angle2,
+ CAIRO_DIRECTION_FORWARD);
+}
+
+/**
+ * _cairo_arc_path_negative:
+ * @xc: X position of the center of the arc
+ * @yc: Y position of the center of the arc
+ * @radius: the radius of the arc
+ * @angle1: the start angle, in radians
+ * @angle2: the end angle, in radians
+ * @ctm: the current transformation matrix
+ * @tolerance: the current tolerance value
+ * @path: the path onto which th earc will be appended
+ *
+ * Compute a path for the given arc (defined in the negative
+ * direction) and append it onto the current path within @cr. The arc
+ * will be accurate within the current tolerance and given the current
+ * transformation.
+ **/
+void
+_cairo_arc_path_negative (cairo_t *cr,
+ double xc,
+ double yc,
+ double radius,
+ double angle1,
+ double angle2)
+{
+ return _cairo_arc_in_direction (cr, xc, yc,
+ radius,
+ angle2, angle1,
+ CAIRO_DIRECTION_REVERSE);
+}
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 0ae98902..5c463e44 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1181,13 +1181,13 @@ static int
_move_to (FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
- cairo_point_t point;
+ cairo_fixed_t x, y;
- point.x = _cairo_fixed_from_26_6 (to->x);
- point.y = _cairo_fixed_from_26_6 (to->y);
+ x = _cairo_fixed_from_26_6 (to->x);
+ y = _cairo_fixed_from_26_6 (to->y);
_cairo_path_fixed_close_path (path);
- _cairo_path_fixed_move_to (path, &point);
+ _cairo_path_fixed_move_to (path, x, y);
return 0;
}
@@ -1196,12 +1196,12 @@ static int
_line_to (FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
- cairo_point_t point;
+ cairo_fixed_t x, y;
- point.x = _cairo_fixed_from_26_6 (to->x);
- point.y = _cairo_fixed_from_26_6 (to->y);
+ x = _cairo_fixed_from_26_6 (to->x);
+ y = _cairo_fixed_from_26_6 (to->y);
- _cairo_path_fixed_line_to (path, &point);
+ _cairo_path_fixed_line_to (path, x, y);
return 0;
}
@@ -1211,25 +1211,30 @@ _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
- cairo_point_t p0, p1, p2, p3;
+ cairo_fixed_t x0, y0;
+ cairo_fixed_t x1, y1;
+ cairo_fixed_t x2, y2;
+ cairo_fixed_t x3, y3;
cairo_point_t conic;
- _cairo_path_fixed_get_current_point (path, &p0);
+ _cairo_path_fixed_get_current_point (path, &x0, &y0);
conic.x = _cairo_fixed_from_26_6 (control->x);
conic.y = _cairo_fixed_from_26_6 (control->y);
- p3.x = _cairo_fixed_from_26_6 (to->x);
- p3.y = _cairo_fixed_from_26_6 (to->y);
+ x3 = _cairo_fixed_from_26_6 (to->x);
+ y3 = _cairo_fixed_from_26_6 (to->y);
- p1.x = p0.x + 2.0/3.0 * (conic.x - p0.x);
- p1.y = p0.y + 2.0/3.0 * (conic.y - p0.y);
+ x1 = x0 + 2.0/3.0 * (conic.x - x0);
+ y1 = y0 + 2.0/3.0 * (conic.y - y0);
- p2.x = p3.x + 2.0/3.0 * (conic.x - p3.x);
- p2.y = p3.y + 2.0/3.0 * (conic.y - p3.y);
+ x2 = x3 + 2.0/3.0 * (conic.x - x3);
+ y2 = y3 + 2.0/3.0 * (conic.y - y3);
_cairo_path_fixed_curve_to (path,
- &p1, &p2, &p3);
+ x1, y1,
+ x2, y2,
+ x3, y3);
return 0;
}
@@ -1238,18 +1243,23 @@ static int
_cubic_to (FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
- cairo_point_t p0, p1, p2;
+ cairo_fixed_t x0, y0;
+ cairo_fixed_t x1, y1;
+ cairo_fixed_t x2, y2;
- p0.x = _cairo_fixed_from_26_6 (control1->x);
- p0.y = _cairo_fixed_from_26_6 (control1->y);
+ x0 = _cairo_fixed_from_26_6 (control1->x);
+ y0 = _cairo_fixed_from_26_6 (control1->y);
- p1.x = _cairo_fixed_from_26_6 (control2->x);
- p1.y = _cairo_fixed_from_26_6 (control2->y);
+ x1 = _cairo_fixed_from_26_6 (control2->x);
+ y1 = _cairo_fixed_from_26_6 (control2->y);
- p2.x = _cairo_fixed_from_26_6 (to->x);
- p2.y = _cairo_fixed_from_26_6 (to->y);
+ x2 = _cairo_fixed_from_26_6 (to->x);
+ y2 = _cairo_fixed_from_26_6 (to->y);
- _cairo_path_fixed_curve_to (path, &p0, &p1, &p2);
+ _cairo_path_fixed_curve_to (path,
+ x0, y0,
+ x1, y1,
+ x2, y2);
return 0;
}
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
index f266bbf4..fcf8a23f 100644
--- a/src/cairo-gstate-private.h
+++ b/src/cairo-gstate-private.h
@@ -36,8 +36,6 @@
#ifndef CAIRO_GSTATE_PRIVATE_H
#define CAIRO_GSTATE_PRIVATE_H
-#include "cairo-path-fixed-private.h"
-
struct _cairo_gstate {
cairo_operator_t operator;
@@ -73,8 +71,6 @@ struct _cairo_gstate {
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
- cairo_path_fixed_t path;
-
cairo_pen_t pen_regular;
struct _cairo_gstate *next;
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 4290077f..c0cb7dbd 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -113,8 +113,6 @@ _cairo_gstate_init (cairo_gstate_t *gstate)
_cairo_gstate_identity_matrix (gstate);
- _cairo_path_fixed_init (&gstate->path);
-
_cairo_pen_init_empty (&gstate->pen_regular);
gstate->next = NULL;
@@ -158,19 +156,12 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
cairo_pattern_reference (gstate->source);
- status = _cairo_path_fixed_init_copy (&gstate->path, &other->path);
- if (status)
- goto CLEANUP_FONT;
-
status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
if (status)
- goto CLEANUP_PATH;
+ goto CLEANUP_FONT;
return status;
- CLEANUP_PATH:
- _cairo_path_fixed_fini (&gstate->path);
-
CLEANUP_FONT:
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
@@ -204,8 +195,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_pattern_destroy (gstate->source);
- _cairo_path_fixed_fini (&gstate->path);
-
_cairo_pen_fini (&gstate->pen_regular);
if (gstate->dash) {
@@ -680,7 +669,7 @@ _cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
-static void
+void
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
@@ -690,7 +679,7 @@ _cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
}
}
-static void
+void
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
{
if (gstate->surface) {
@@ -700,393 +689,9 @@ _cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
}
-cairo_status_t
-_cairo_gstate_new_path (cairo_gstate_t *gstate)
-{
- _cairo_path_fixed_fini (&gstate->path);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y)
-{
- cairo_point_t point;
-
- _cairo_gstate_user_to_backend (gstate, &x, &y);
-
- point.x = _cairo_fixed_from_double (x);
- point.y = _cairo_fixed_from_double (y);
-
- return _cairo_path_fixed_move_to (&gstate->path, &point);
-}
-
-cairo_status_t
-_cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y)
-{
- cairo_point_t point;
-
- _cairo_gstate_user_to_backend (gstate, &x, &y);
-
- point.x = _cairo_fixed_from_double (x);
- point.y = _cairo_fixed_from_double (y);
-
- return _cairo_path_fixed_line_to (&gstate->path, &point);
-}
-
-cairo_status_t
-_cairo_gstate_curve_to (cairo_gstate_t *gstate,
- double x0, double y0,
- double x1, double y1,
- double x2, double y2)
-{
- cairo_point_t p0, p1, p2;
-
- _cairo_gstate_user_to_backend (gstate, &x0, &y0);
- _cairo_gstate_user_to_backend (gstate, &x1, &y1);
- _cairo_gstate_user_to_backend (gstate, &x2, &y2);
-
- p0.x = _cairo_fixed_from_double (x0);
- p0.y = _cairo_fixed_from_double (y0);
-
- p1.x = _cairo_fixed_from_double (x1);
- p1.y = _cairo_fixed_from_double (y1);
-
- p2.x = _cairo_fixed_from_double (x2);
- p2.y = _cairo_fixed_from_double (y2);
-
- return _cairo_path_fixed_curve_to (&gstate->path, &p0, &p1, &p2);
-}
-
-/* Spline deviation from the circle in radius would be given by:
-
- error = sqrt (x**2 + y**2) - 1
-
- A simpler error function to work with is:
-
- e = x**2 + y**2 - 1
-
- From "Good approximation of circles by curvature-continuous Bezier
- curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric
- Design 8 (1990) 22-41, we learn:
-
- abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4)
-
- and
- abs (error) =~ 1/2 * e
-
- Of course, this error value applies only for the particular spline
- approximation that is used in _cairo_gstate_arc_segment.
-*/
-static double
-_arc_error_normalized (double angle)
-{
- return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
-}
-
-static double
-_arc_max_angle_for_tolerance_normalized (double tolerance)
-{
- double angle, error;
- int i;
-
- /* Use table lookup to reduce search time in most cases. */
- struct {
- double angle;
- double error;
- } table[] = {
- { M_PI / 1.0, 0.0185185185185185036127 },
- { M_PI / 2.0, 0.000272567143730179811158 },
- { M_PI / 3.0, 2.38647043651461047433e-05 },
- { M_PI / 4.0, 4.2455377443222443279e-06 },
- { M_PI / 5.0, 1.11281001494389081528e-06 },
- { M_PI / 6.0, 3.72662000942734705475e-07 },
- { M_PI / 7.0, 1.47783685574284411325e-07 },
- { M_PI / 8.0, 6.63240432022601149057e-08 },
- { M_PI / 9.0, 3.2715520137536980553e-08 },
- { M_PI / 10.0, 1.73863223499021216974e-08 },
- { M_PI / 11.0, 9.81410988043554039085e-09 },
- };
- int table_size = (sizeof (table) / sizeof (table[0]));
-
- for (i = 0; i < table_size; i++)
- if (table[i].error < tolerance)
- return table[i].angle;
-
- ++i;
- do {
- angle = M_PI / i++;
- error = _arc_error_normalized (angle);
- } while (error > tolerance);
-
- return angle;
-}
-
-static int
-_cairo_gstate_arc_segments_needed (cairo_gstate_t *gstate,
- double angle,
- double radius)
-{
- double l1, l2, lmax;
- double max_angle;
-
- _cairo_matrix_compute_eigen_values (&gstate->ctm, &l1, &l2);
-
- l1 = fabs (l1);
- l2 = fabs (l2);
- if (l1 > l2)
- lmax = l1;
- else
- lmax = l2;
-
- max_angle = _arc_max_angle_for_tolerance_normalized (gstate->tolerance / (radius * lmax));
-
- return (int) ceil (angle / max_angle);
-}
-
-/* We want to draw a single spline approximating a circular arc radius
- R from angle A to angle B. Since we want a symmetric spline that
- matches the endpoints of the arc in position and slope, we know
- that the spline control points must be:
-
- (R * cos(A), R * sin(A))
- (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
- (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
- (R * cos(B), R * sin(B))
-
- for some value of h.
-
- "Approximation of circular arcs by cubic poynomials", Michael
- Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
- various values of h along with error analysis for each.
-
- From that paper, a very practical value of h is:
-
- h = 4/3 * tan(angle/4)
-
- This value does not give the spline with minimal error, but it does
- provide a very good approximation, (6th-order convergence), and the
- error expression is quite simple, (see the comment for
- _arc_error_normalized).
-*/
-static cairo_status_t
-_cairo_gstate_arc_segment (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle_A, double angle_B)
-{
- cairo_status_t status;
- double r_sin_A, r_cos_A;
- double r_sin_B, r_cos_B;
- double h;
-
- r_sin_A = radius * sin (angle_A);
- r_cos_A = radius * cos (angle_A);
- r_sin_B = radius * sin (angle_B);
- r_cos_B = radius * cos (angle_B);
-
- h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
-
- status = _cairo_gstate_curve_to (gstate,
- xc + r_cos_A - h * r_sin_A, yc + r_sin_A + h * r_cos_A,
- xc + r_cos_B + h * r_sin_B, yc + r_sin_B - h * r_cos_B,
- xc + r_cos_B, yc + r_sin_B);
- if (status)
- return status;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_gstate_arc_dir (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle_min,
- double angle_max,
- cairo_direction_t dir)
-{
- cairo_status_t status;
-
- while (angle_max - angle_min > 4 * M_PI)
- angle_max -= 2 * M_PI;
-
- /* Recurse if drawing arc larger than pi */
- if (angle_max - angle_min > M_PI) {
- double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
- /* XXX: Something tells me this block could be condensed. */
- if (dir == CAIRO_DIRECTION_FORWARD) {
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_min, angle_mid, dir);
- if (status)
- return status;
-
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_mid, angle_max, dir);
- if (status)
- return status;
- } else {
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_mid, angle_max, dir);
- if (status)
- return status;
-
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle_min, angle_mid, dir);
- if (status)
- return status;
- }
- } else {
- int i, segments;
- double angle, angle_step;
-
- segments = _cairo_gstate_arc_segments_needed (gstate,
- angle_max - angle_min,
- radius);
- angle_step = (angle_max - angle_min) / (double) segments;
-
- if (dir == CAIRO_DIRECTION_FORWARD) {
- angle = angle_min;
- } else {
- angle = angle_max;
- angle_step = - angle_step;
- }
-
- for (i = 0; i < segments; i++, angle += angle_step) {
- _cairo_gstate_arc_segment (gstate,
- xc, yc,
- radius,
- angle,
- angle + angle_step);
- }
-
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_arc (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle1, double angle2)
-{
- cairo_status_t status;
-
- if (radius <= 0.0)
- return CAIRO_STATUS_SUCCESS;
-
- while (angle2 < angle1)
- angle2 += 2 * M_PI;
-
- status = _cairo_gstate_line_to (gstate,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
- if (status)
- return status;
-
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle1, angle2, CAIRO_DIRECTION_FORWARD);
- if (status)
- return status;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_arc_negative (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle1, double angle2)
-{
- cairo_status_t status;
-
- if (radius <= 0.0)
- return CAIRO_STATUS_SUCCESS;
-
- while (angle2 > angle1)
- angle2 -= 2 * M_PI;
-
- status = _cairo_gstate_line_to (gstate,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
- if (status)
- return status;
-
- status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
- angle2, angle1, CAIRO_DIRECTION_REVERSE);
- if (status)
- return status;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* XXX: NYI
-cairo_status_t
-_cairo_gstate_arc_to (cairo_gstate_t *gstate,
- double x1, double y1,
- double x2, double y2,
- double radius)
-{
-
-}
-*/
-
-cairo_status_t
-_cairo_gstate_rel_move_to (cairo_gstate_t *gstate, double dx, double dy)
-{
- cairo_distance_t distance;
-
- cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
-
- distance.dx = _cairo_fixed_from_double (dx);
- distance.dy = _cairo_fixed_from_double (dy);
-
- return _cairo_path_fixed_rel_move_to (&gstate->path, &distance);
-}
-
-cairo_status_t
-_cairo_gstate_rel_line_to (cairo_gstate_t *gstate, double dx, double dy)
-{
- cairo_distance_t distance;
-
- cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
-
- distance.dx = _cairo_fixed_from_double (dx);
- distance.dy = _cairo_fixed_from_double (dy);
-
- return _cairo_path_fixed_rel_line_to (&gstate->path, &distance);
-}
-
-cairo_status_t
-_cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
- double dx0, double dy0,
- double dx1, double dy1,
- double dx2, double dy2)
-{
- cairo_distance_t distance[3];
-
- cairo_matrix_transform_distance (&gstate->ctm, &dx0, &dy0);
- cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
- cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
-
- distance[0].dx = _cairo_fixed_from_double (dx0);
- distance[0].dy = _cairo_fixed_from_double (dy0);
-
- distance[1].dx = _cairo_fixed_from_double (dx1);
- distance[1].dy = _cairo_fixed_from_double (dy1);
-
- distance[2].dx = _cairo_fixed_from_double (dx2);
- distance[2].dy = _cairo_fixed_from_double (dy2);
-
- return _cairo_path_fixed_rel_curve_to (&gstate->path,
- &distance[0],
- &distance[1],
- &distance[2]);
-}
-
/* XXX: NYI
cairo_status_t
-_cairo_gstate_stroke_path (cairo_gstate_t *gstate)
+_cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
{
cairo_status_t status;
@@ -1095,194 +700,6 @@ _cairo_gstate_stroke_path (cairo_gstate_t *gstate)
}
*/
-cairo_status_t
-_cairo_gstate_close_path (cairo_gstate_t *gstate)
-{
- return _cairo_path_fixed_close_path (&gstate->path);
-}
-
-cairo_status_t
-_cairo_gstate_get_current_point (cairo_gstate_t *gstate, double *x_ret, double *y_ret)
-{
- cairo_status_t status;
- cairo_point_t point;
- double x, y;
-
- status = _cairo_path_fixed_get_current_point (&gstate->path, &point);
- if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
- x = 0.0;
- y = 0.0;
- } else {
- x = _cairo_fixed_to_double (point.x);
- y = _cairo_fixed_to_double (point.y);
- _cairo_gstate_backend_to_user (gstate, &x, &y);
- }
-
- if (x_ret)
- *x_ret = x;
- if (y_ret)
- *y_ret = y;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-typedef struct gstate_path_interpreter {
- cairo_matrix_t ctm_inverse;
- double tolerance;
- cairo_point_t current_point;
-
- cairo_move_to_func_t *move_to;
- cairo_line_to_func_t *line_to;
- cairo_curve_to_func_t *curve_to;
- cairo_close_path_func_t *close_path;
-
- void *closure;
-} gpi_t;
-
-static cairo_status_t
-_gpi_move_to (void *closure, cairo_point_t *point)
-{
- gpi_t *gpi = closure;
- double x, y;
-
- x = _cairo_fixed_to_double (point->x);
- y = _cairo_fixed_to_double (point->y);
-
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
-
- gpi->move_to (gpi->closure, x, y);
- gpi->current_point = *point;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_gpi_line_to (void *closure, cairo_point_t *point)
-{
- gpi_t *gpi = closure;
- double x, y;
-
- x = _cairo_fixed_to_double (point->x);
- y = _cairo_fixed_to_double (point->y);
-
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
-
- gpi->line_to (gpi->closure, x, y);
- gpi->current_point = *point;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_gpi_curve_to (void *closure,
- cairo_point_t *p1,
- cairo_point_t *p2,
- cairo_point_t *p3)
-{
- gpi_t *gpi = closure;
- cairo_status_t status;
- cairo_spline_t spline;
- double x1, y1, x2, y2, x3, y3;
-
- if (gpi->curve_to) {
- x1 = _cairo_fixed_to_double (p1->x);
- y1 = _cairo_fixed_to_double (p1->y);
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x1, &y1);
-
- x2 = _cairo_fixed_to_double (p2->x);
- y2 = _cairo_fixed_to_double (p2->y);
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x2, &y2);
-
- x3 = _cairo_fixed_to_double (p3->x);
- y3 = _cairo_fixed_to_double (p3->y);
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x3, &y3);
-
- gpi->curve_to (gpi->closure, x1, y1, x2, y2, x3, y3);
- } else {
- cairo_point_t *p0 = &gpi->current_point;
- int i;
- double x, y;
-
- status = _cairo_spline_init (&spline, p0, p1, p2, p3);
- if (status == CAIRO_INT_STATUS_DEGENERATE)
- return CAIRO_STATUS_SUCCESS;
-
- status = _cairo_spline_decompose (&spline, gpi->tolerance);
- if (status)
- return status;
-
- for (i=1; i < spline.num_points; i++) {
- x = _cairo_fixed_to_double (spline.points[i].x);
- y = _cairo_fixed_to_double (spline.points[i].y);
-
- cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
-
- gpi->line_to (gpi->closure, x, y);
- }
- }
-
- gpi->current_point = *p3;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_gpi_close_path (void *closure)
-{
- gpi_t *gpi = closure;
-
- gpi->close_path (gpi->closure);
-
- gpi->current_point.x = 0;
- gpi->current_point.y = 0;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* It's OK for curve_path to be NULL. In that case, all curves in the
- path will be decomposed into one or more calls to the line_to
- function, (according to the current tolerance). */
-cairo_status_t
-_cairo_gstate_interpret_path (cairo_gstate_t *gstate,
- cairo_move_to_func_t *move_to,
- cairo_line_to_func_t *line_to,
- cairo_curve_to_func_t *curve_to,
- cairo_close_path_func_t *close_path,
- void *closure)
-{
- cairo_path_fixed_t path;
- gpi_t gpi;
-
- /* Anything we want from gstate must be copied. We must not retain
- pointers into gstate. */
- _cairo_path_fixed_init_copy (&path, &gstate->path);
-
- gpi.ctm_inverse = gstate->ctm_inverse;
- if (gstate->surface)
- cairo_matrix_translate (&gpi.ctm_inverse,
- - gstate->surface->device_x_offset,
- - gstate->surface->device_y_offset);
-
- gpi.tolerance = gstate->tolerance;
-
- gpi.move_to = move_to;
- gpi.line_to = line_to;
- gpi.curve_to = curve_to;
- gpi.close_path = close_path;
- gpi.closure = closure;
-
- gpi.current_point.x = 0;
- gpi.current_point.y = 0;
-
- return _cairo_path_fixed_interpret (&path,
- CAIRO_DIRECTION_FORWARD,
- _gpi_move_to,
- _gpi_line_to,
- _gpi_curve_to,
- _gpi_close_path,
- &gpi);
-}
-
static void
_cairo_gstate_pattern_transform (cairo_gstate_t *gstate,
cairo_pattern_t *pattern)
@@ -1305,7 +722,7 @@ _cairo_gstate_get_clip_extents (cairo_gstate_t *gstate,
}
cairo_status_t
-_cairo_gstate_stroke (cairo_gstate_t *gstate)
+_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_traps_t traps;
@@ -1317,7 +734,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_stroke_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
@@ -1331,16 +748,15 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate)
_cairo_traps_fini (&traps);
- _cairo_gstate_new_path (gstate);
-
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
- double x,
- double y,
- cairo_bool_t *inside_ret)
+_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double x,
+ double y,
+ cairo_bool_t *inside_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_traps_t traps;
@@ -1351,7 +767,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_stroke_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -1835,14 +1251,14 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
}
cairo_status_t
-_cairo_gstate_fill (cairo_gstate_t *gstate)
+_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_traps_t traps;
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
@@ -1856,16 +1272,15 @@ _cairo_gstate_fill (cairo_gstate_t *gstate)
_cairo_traps_fini (&traps);
- _cairo_gstate_new_path (gstate);
-
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
-_cairo_gstate_in_fill (cairo_gstate_t *gstate,
- double x,
- double y,
- cairo_bool_t *inside_ret)
+_cairo_gstate_in_fill (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double x,
+ double y,
+ cairo_bool_t *inside_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_traps_t traps;
@@ -1874,7 +1289,7 @@ _cairo_gstate_in_fill (cairo_gstate_t *gstate,
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -1905,7 +1320,8 @@ _cairo_gstate_show_page (cairo_gstate_t *gstate)
}
cairo_status_t
-_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2)
{
@@ -1917,7 +1333,7 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_stroke_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -1938,7 +1354,8 @@ BAIL:
}
cairo_status_t
-_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2)
{
@@ -1948,7 +1365,7 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
if (status)
goto BAIL;
@@ -2008,7 +1425,7 @@ _cairo_gstate_restore_external_state (cairo_gstate_t *gstate)
}
cairo_status_t
-_cairo_gstate_clip (cairo_gstate_t *gstate)
+_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_pattern_union_t pattern;
@@ -2019,7 +1436,7 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
/* Fill the clip region as traps. */
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+ status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
if (!CAIRO_OK (status)) {
_cairo_traps_fini (&traps);
return status;
@@ -2104,8 +1521,10 @@ _cairo_gstate_clip (cairo_gstate_t *gstate)
cairo_status_t
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
cairo_surface_t *surface,
- int width,
- int height)
+ double x,
+ double y,
+ double width,
+ double height)
{
/* We are dealing with 6 coordinate spaces in this function. this makes
@@ -2199,7 +1618,8 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate,
image_to_backend = image_to_device;
}
- _cairo_gstate_get_current_point (gstate, &backend_x, &backend_y);
+ backend_x = x;
+ backend_y = y;
backend_width = width;
backend_height = height;
_cairo_matrix_transform_bounding_box (&image_to_backend,
@@ -2480,30 +1900,18 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
const char *utf8,
+ double x,
+ double y,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
cairo_status_t status;
-
- cairo_point_t point;
- double origin_x, origin_y;
int i;
status = _cairo_gstate_ensure_font (gstate);
if (status)
return status;
- status = _cairo_path_fixed_get_current_point (&gstate->path, &point);
- if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
- origin_x = 0.0;
- origin_y = 0.0;
- } else {
- origin_x = _cairo_fixed_to_double (point.x);
- origin_y = _cairo_fixed_to_double (point.y);
- _cairo_gstate_backend_to_user (gstate,
- &origin_x, &origin_y);
- }
-
status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font,
utf8, glyphs, num_glyphs);
@@ -2518,8 +1926,8 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
cairo_matrix_transform_point (&gstate->font_matrix,
&((*glyphs)[i].x),
&((*glyphs)[i].y));
- (*glyphs)[i].x += origin_x;
- (*glyphs)[i].y += origin_y;
+ (*glyphs)[i].x += x;
+ (*glyphs)[i].y += y;
}
return CAIRO_STATUS_SUCCESS;
@@ -2703,9 +2111,10 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
cairo_status_t
-_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
- cairo_glyph_t *glyphs,
- int num_glyphs)
+_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_fixed_t *path)
{
cairo_status_t status;
int i;
@@ -2725,7 +2134,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
- &gstate->path);
+ path);
free (transformed_glyphs);
return status;
diff --git a/src/cairo-path-data-private.h b/src/cairo-path-data-private.h
index 2833e2ea..946efca6 100644
--- a/src/cairo-path-data-private.h
+++ b/src/cairo-path-data-private.h
@@ -41,10 +41,14 @@
extern cairo_path_t _cairo_path_nil;
cairo_path_t *
-_cairo_path_data_create (cairo_gstate_t *gstate);
+_cairo_path_data_create (cairo_path_fixed_t *path,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance);
cairo_path_t *
-_cairo_path_data_create_flat (cairo_gstate_t *gstate);
+_cairo_path_data_create_flat (cairo_path_fixed_t *path,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance);
cairo_status_t
_cairo_path_data_append_to_context (cairo_path_t *path,
diff --git a/src/cairo-path-data.c b/src/cairo-path-data.c
index 84d26554..3bb5fff7 100644
--- a/src/cairo-path-data.c
+++ b/src/cairo-path-data.c
@@ -34,6 +34,8 @@
*/
#include "cairo-path-data-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-gstate-private.h"
cairo_path_t
_cairo_path_nil = { NULL, 0 };
@@ -41,56 +43,113 @@ _cairo_path_nil = { NULL, 0 };
/* Closure for path interpretation. */
typedef struct cairo_path_data_count {
int count;
+ double tolerance;
+ cairo_point_t current_point;
} cpdc_t;
-static void
-_cpdc_move_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdc_move_to (void *closure, cairo_point_t *point)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
+
+ cpdc->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
}
-static void
-_cpdc_line_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdc_line_to (void *closure, cairo_point_t *point)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
+
+ cpdc->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
}
-static void
-_cpdc_curve_to (void *closure,
- double x1, double y1,
- double x2, double y2,
- double x3, double y3)
+static cairo_status_t
+_cpdc_curve_to (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
{
cpdc_t *cpdc = closure;
cpdc->count += 4;
+
+ cpdc->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
}
-static void
+static cairo_status_t
+_cpdc_curve_to_flatten (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
+{
+ cpdc_t *cpdc = closure;
+ cairo_status_t status;
+ cairo_spline_t spline;
+ int i;
+
+ cairo_point_t *p0 = &cpdc->current_point;
+
+ status = _cairo_spline_init (&spline, p0, p1, p2, p3);
+ if (status == CAIRO_INT_STATUS_DEGENERATE)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_spline_decompose (&spline, cpdc->tolerance);
+ if (status)
+ return status;
+
+ for (i=1; i < spline.num_points; i++)
+ _cpdc_line_to (cpdc, &spline.points[i]);
+
+ cpdc->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
_cpdc_close_path (void *closure)
{
cpdc_t *cpdc = closure;
cpdc->count += 1;
+
+ cpdc->current_point.x = 0;
+ cpdc->current_point.y = 0;
+
+ return CAIRO_STATUS_SUCCESS;
}
static int
-_cairo_path_data_count (cairo_gstate_t *gstate, cairo_bool_t flatten)
+_cairo_path_data_count (cairo_path_t *path,
+ cairo_path_fixed_t *path_fixed,
+ double tolerance,
+ cairo_bool_t flatten)
{
cpdc_t cpdc;
cpdc.count = 0;
-
- _cairo_gstate_interpret_path (gstate,
- _cpdc_move_to,
- _cpdc_line_to,
- flatten ? NULL : _cpdc_curve_to,
- _cpdc_close_path,
- &cpdc);
+ cpdc.tolerance = tolerance;
+ cpdc.current_point.x = 0;
+ cpdc.current_point.y = 0;
+
+ _cairo_path_fixed_interpret (path_fixed,
+ CAIRO_DIRECTION_FORWARD,
+ _cpdc_move_to,
+ _cpdc_line_to,
+ flatten ?
+ _cpdc_curve_to_flatten :
+ _cpdc_curve_to,
+ _cpdc_close_path,
+ &cpdc);
return cpdc.count;
}
@@ -98,13 +157,22 @@ _cairo_path_data_count (cairo_gstate_t *gstate, cairo_bool_t flatten)
/* Closure for path interpretation. */
typedef struct cairo_path_data_populate {
cairo_path_data_t *data;
+ cairo_matrix_t *ctm_inverse;
+ double tolerance;
+ cairo_point_t current_point;
} cpdp_t;
-static void
-_cpdp_move_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdp_move_to (void *closure, cairo_point_t *point)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
+ double x, y;
+
+ x = _cairo_fixed_to_double (point->x);
+ y = _cairo_fixed_to_double (point->y);
+
+ cairo_matrix_transform_point (cpdp->ctm_inverse, &x, &y);
data->header.type = CAIRO_PATH_MOVE_TO;
data->header.length = 2;
@@ -114,13 +182,23 @@ _cpdp_move_to (void *closure, double x, double y)
data[1].point.y = y;
cpdp->data += data->header.length;
+
+ cpdp->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
}
-static void
-_cpdp_line_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdp_line_to (void *closure, cairo_point_t *point)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
+ double x, y;
+
+ x = _cairo_fixed_to_double (point->x);
+ y = _cairo_fixed_to_double (point->y);
+
+ cairo_matrix_transform_point (cpdp->ctm_inverse, &x, &y);
data->header.type = CAIRO_PATH_LINE_TO;
data->header.length = 2;
@@ -130,16 +208,35 @@ _cpdp_line_to (void *closure, double x, double y)
data[1].point.y = y;
cpdp->data += data->header.length;
+
+ cpdp->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
}
-static void
-_cpdp_curve_to (void *closure,
- double x1, double y1,
- double x2, double y2,
- double x3, double y3)
+static cairo_status_t
+_cpdp_curve_to (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
+ double x1, y1;
+ double x2, y2;
+ double x3, y3;
+
+ x1 = _cairo_fixed_to_double (p1->x);
+ y1 = _cairo_fixed_to_double (p1->y);
+ cairo_matrix_transform_point (cpdp->ctm_inverse, &x1, &y1);
+
+ x2 = _cairo_fixed_to_double (p2->x);
+ y2 = _cairo_fixed_to_double (p2->y);
+ cairo_matrix_transform_point (cpdp->ctm_inverse, &x2, &y2);
+
+ x3 = _cairo_fixed_to_double (p3->x);
+ y3 = _cairo_fixed_to_double (p3->y);
+ cairo_matrix_transform_point (cpdp->ctm_inverse, &x3, &y3);
data->header.type = CAIRO_PATH_CURVE_TO;
data->header.length = 4;
@@ -155,9 +252,42 @@ _cpdp_curve_to (void *closure,
data[3].point.y = y3;
cpdp->data += data->header.length;
+
+ cpdp->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
}
-static void
+static cairo_status_t
+_cpdp_curve_to_flatten (void *closure,
+ cairo_point_t *p1,
+ cairo_point_t *p2,
+ cairo_point_t *p3)
+{
+ cpdp_t *cpdp = closure;
+ cairo_status_t status;
+ cairo_spline_t spline;
+ int i;
+
+ cairo_point_t *p0 = &cpdp->current_point;
+
+ status = _cairo_spline_init (&spline, p0, p1, p2, p3);
+ if (status == CAIRO_INT_STATUS_DEGENERATE)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_spline_decompose (&spline, cpdp->tolerance);
+ if (status)
+ return status;
+
+ for (i=1; i < spline.num_points; i++)
+ _cpdp_line_to (cpdp, &spline.points[i]);
+
+ cpdp->current_point = *p3;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
_cpdp_close_path (void *closure)
{
cpdp_t *cpdp = closure;
@@ -167,30 +297,47 @@ _cpdp_close_path (void *closure)
data->header.length = 1;
cpdp->data += data->header.length;
+
+ cpdp->current_point.x = 0;
+ cpdp->current_point.y = 0;
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_path_data_populate (cairo_path_t *path,
- cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path_fixed,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
cairo_bool_t flatten)
{
cpdp_t cpdp;
cpdp.data = path->data;
-
- _cairo_gstate_interpret_path (gstate,
- _cpdp_move_to,
- _cpdp_line_to,
- flatten ? NULL : _cpdp_curve_to,
- _cpdp_close_path,
- &cpdp);
+ cpdp.ctm_inverse = ctm_inverse;
+ cpdp.tolerance = tolerance;
+ cpdp.current_point.x = 0;
+ cpdp.current_point.y = 0;
+
+ _cairo_path_fixed_interpret (path_fixed,
+ CAIRO_DIRECTION_FORWARD,
+ _cpdp_move_to,
+ _cpdp_line_to,
+ flatten ?
+ _cpdp_curve_to_flatten :
+ _cpdp_curve_to,
+ _cpdp_close_path,
+ &cpdp);
/* Sanity check the count */
assert (cpdp.data - path->data == path->num_data);
}
static cairo_path_t *
-_cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten)
+_cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_bool_t flatten)
{
cairo_path_t *path;
@@ -198,7 +345,8 @@ _cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten)
if (path == NULL)
return &_cairo_path_nil;
- path->num_data = _cairo_path_data_count (gstate, flatten);
+ path->num_data = _cairo_path_data_count (path, path_fixed,
+ tolerance, flatten);
path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
if (path->data == NULL) {
@@ -206,7 +354,8 @@ _cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten)
return &_cairo_path_nil;
}
- _cairo_path_data_populate (path, gstate, flatten);
+ _cairo_path_data_populate (path, path_fixed,
+ ctm_inverse, tolerance, flatten);
return path;
}
@@ -220,15 +369,19 @@ cairo_path_destroy (cairo_path_t *path)
}
cairo_path_t *
-_cairo_path_data_create (cairo_gstate_t *gstate)
+_cairo_path_data_create (cairo_path_fixed_t *path,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance)
{
- return _cairo_path_data_create_real (gstate, FALSE);
+ return _cairo_path_data_create_real (path, ctm_inverse, tolerance, FALSE);
}
cairo_path_t *
-_cairo_path_data_create_flat (cairo_gstate_t *gstate)
+_cairo_path_data_create_flat (cairo_path_fixed_t *path,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance)
{
- return _cairo_path_data_create_real (gstate, TRUE);
+ return _cairo_path_data_create_real (path, ctm_inverse, tolerance, TRUE);
}
cairo_status_t
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 21125e0f..53c2375c 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -156,16 +156,21 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
}
cairo_status_t
-_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
- cairo_point_t *point)
+_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
+ cairo_fixed_t x,
+ cairo_fixed_t y)
{
cairo_status_t status;
+ cairo_point_t point;
+
+ point.x = x;
+ point.y = y;
- status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, point, 1);
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (status)
return status;
- path->current_point = *point;
+ path->current_point = point;
path->has_current_point = 1;
path->last_move_point = path->current_point;
@@ -174,27 +179,33 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
- cairo_distance_t *distance)
+ cairo_fixed_t dx,
+ cairo_fixed_t dy)
{
- cairo_point_t point;
+ cairo_fixed_t x, y;
- point.x = path->current_point.x + distance->dx;
- point.y = path->current_point.y + distance->dy;
+ x = path->current_point.x + dx;
+ y = path->current_point.y + dy;
- return _cairo_path_fixed_move_to (path, &point);
+ return _cairo_path_fixed_move_to (path, x, y);
}
cairo_status_t
_cairo_path_fixed_line_to (cairo_path_fixed_t *path,
- cairo_point_t *point)
+ cairo_fixed_t x,
+ cairo_fixed_t y)
{
cairo_status_t status;
+ cairo_point_t point;
+
+ point.x = x;
+ point.y = y;
- status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, point, 1);
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
if (status)
return status;
- path->current_point = *point;
+ path->current_point = point;
path->has_current_point = 1;
return CAIRO_STATUS_SUCCESS;
@@ -202,34 +213,35 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
cairo_status_t
_cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
- cairo_distance_t *distance)
+ cairo_fixed_t dx,
+ cairo_fixed_t dy)
{
- cairo_point_t point;
+ cairo_fixed_t x, y;
- point.x = path->current_point.x + distance->dx;
- point.y = path->current_point.y + distance->dy;
+ x = path->current_point.x + dx;
+ y = path->current_point.y + dy;
- return _cairo_path_fixed_line_to (path, &point);
+ return _cairo_path_fixed_line_to (path, x, y);
}
cairo_status_t
_cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
- cairo_point_t *p0,
- cairo_point_t *p1,
- cairo_point_t *p2)
+ cairo_fixed_t x0, cairo_fixed_t y0,
+ cairo_fixed_t x1, cairo_fixed_t y1,
+ cairo_fixed_t x2, cairo_fixed_t y2)
{
cairo_status_t status;
cairo_point_t point[3];
- point[0] = *p0;
- point[1] = *p1;
- point[2] = *p2;
+ point[0].x = x0; point[0].y = y0;
+ point[1].x = x1; point[1].y = y1;
+ point[2].x = x2; point[2].y = y2;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (status)
return status;
- path->current_point = *p2;
+ path->current_point = point[2];
path->has_current_point = 1;
return CAIRO_STATUS_SUCCESS;
@@ -237,22 +249,27 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
cairo_status_t
_cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
- cairo_distance_t *d0,
- cairo_distance_t *d1,
- cairo_distance_t *d2)
+ cairo_fixed_t dx0, cairo_fixed_t dy0,
+ cairo_fixed_t dx1, cairo_fixed_t dy1,
+ cairo_fixed_t dx2, cairo_fixed_t dy2)
{
- cairo_point_t p0, p1, p2;
+ cairo_fixed_t x0, y0;
+ cairo_fixed_t x1, y1;
+ cairo_fixed_t x2, y2;
- p0.x = path->current_point.x + d0->dx;
- p0.y = path->current_point.y + d0->dy;
+ x0 = path->current_point.x + dx0;
+ y0 = path->current_point.y + dy0;
- p1.x = path->current_point.x + d1->dx;
- p1.y = path->current_point.y + d1->dy;
+ x1 = path->current_point.x + dx0;
+ y1 = path->current_point.y + dy0;
- p2.x = path->current_point.x + d2->dx;
- p2.y = path->current_point.y + d2->dy;
+ x2 = path->current_point.x + dx0;
+ y2 = path->current_point.y + dy0;
- return _cairo_path_fixed_curve_to (path, &p0, &p1, &p2);
+ return _cairo_path_fixed_curve_to (path,
+ x0, y0,
+ x1, y1,
+ x2, y2);
}
cairo_status_t
@@ -273,12 +290,14 @@ _cairo_path_fixed_close_path (cairo_path_fixed_t *path)
cairo_status_t
_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
- cairo_point_t *point)
+ cairo_fixed_t *x,
+ cairo_fixed_t *y)
{
if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
- *point = path->current_point;
+ *x = path->current_point.x;
+ *y = path->current_point.y;
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-private.h b/src/cairo-private.h
index e125a4b1..a43c8ef7 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -37,10 +37,14 @@
#define CAIRO_PRIVATE_H
#include "cairo-gstate-private.h"
+#include "cairo-path-fixed-private.h"
struct _cairo {
unsigned int ref_count;
+
cairo_gstate_t *gstate;
+ cairo_path_fixed_t path;
+
cairo_status_t status;
};
diff --git a/src/cairo.c b/src/cairo.c
index 0faddb35..ce25f3f1 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -36,8 +36,9 @@
*/
#include "cairoint.h"
-
#include "cairo-private.h"
+
+#include "cairo-arc-private.h"
#include "cairo-path-data-private.h"
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
@@ -101,6 +102,8 @@ cairo_create (void)
if (cr->gstate == NULL)
cr->status = CAIRO_STATUS_NO_MEMORY;
+ _cairo_path_fixed_init (&cr->path);
+
CAIRO_CHECK_SANITY (cr);
return cr;
}
@@ -147,6 +150,8 @@ cairo_destroy (cairo_t *cr)
_cairo_gstate_destroy (tmp);
}
+ _cairo_path_fixed_fini (&cr->path);
+
free (cr);
}
@@ -1161,18 +1166,27 @@ cairo_new_path (cairo_t *cr)
if (cr->status)
return;
- cr->status = _cairo_gstate_new_path (cr->gstate);
+ _cairo_path_fixed_fini (&cr->path);
+
CAIRO_CHECK_SANITY (cr);
}
+slim_hidden_def(cairo_new_path);
void
cairo_move_to (cairo_t *cr, double x, double y)
{
+ cairo_fixed_t x_fixed, y_fixed;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_move_to (cr->gstate, x, y);
+ _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
+ x_fixed = _cairo_fixed_from_double (x);
+ y_fixed = _cairo_fixed_from_double (y);
+
+ cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed);
+
CAIRO_CHECK_SANITY (cr);
}
slim_hidden_def(cairo_move_to);
@@ -1180,11 +1194,18 @@ slim_hidden_def(cairo_move_to);
void
cairo_line_to (cairo_t *cr, double x, double y)
{
+ cairo_fixed_t x_fixed, y_fixed;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_line_to (cr->gstate, x, y);
+ _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
+ x_fixed = _cairo_fixed_from_double (x);
+ y_fixed = _cairo_fixed_from_double (y);
+
+ cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed);
+
CAIRO_CHECK_SANITY (cr);
}
@@ -1194,14 +1215,32 @@ cairo_curve_to (cairo_t *cr,
double x2, double y2,
double x3, double y3)
{
+ cairo_fixed_t x1_fixed, y1_fixed;
+ cairo_fixed_t x2_fixed, y2_fixed;
+ cairo_fixed_t x3_fixed, y3_fixed;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_curve_to (cr->gstate,
- x1, y1,
- x2, y2,
- x3, y3);
+ _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);
+
+ cr->status = _cairo_path_fixed_curve_to (&cr->path,
+ x1_fixed, y1_fixed,
+ x2_fixed, y2_fixed,
+ x3_fixed, y3_fixed);
+
CAIRO_CHECK_SANITY (cr);
}
@@ -1248,10 +1287,20 @@ cairo_arc (cairo_t *cr,
if (cr->status)
return;
- cr->status = _cairo_gstate_arc (cr->gstate,
- xc, yc,
- radius,
- angle1, angle2);
+ /* Do nothing, successfully, if radius is <= 0 */
+ if (radius <= 0.0)
+ return;
+
+ while (angle2 < angle1)
+ angle2 += 2 * M_PI;
+
+ cairo_line_to (cr,
+ xc + radius * cos (angle1),
+ yc + radius * sin (angle1));
+
+ _cairo_arc_path (cr, xc, yc, radius,
+ angle1, angle2);
+
CAIRO_CHECK_SANITY (cr);
}
@@ -1279,10 +1328,20 @@ cairo_arc_negative (cairo_t *cr,
if (cr->status)
return;
- cr->status = _cairo_gstate_arc_negative (cr->gstate,
- xc, yc,
- radius,
- angle1, angle2);
+ /* Do nothing, successfully, if radius is <= 0 */
+ if (radius <= 0.0)
+ return;
+
+ while (angle2 > angle1)
+ angle2 -= 2 * M_PI;
+
+ cairo_line_to (cr,
+ xc + radius * cos (angle1),
+ yc + radius * sin (angle1));
+
+ _cairo_arc_path_negative (cr, xc, yc, radius,
+ angle1, angle2);
+
CAIRO_CHECK_SANITY (cr);
}
@@ -1306,22 +1365,36 @@ 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_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_rel_move_to (cr->gstate, dx, dy);
+ _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
+ dx_fixed = _cairo_fixed_from_double (dx);
+ dy_fixed = _cairo_fixed_from_double (dy);
+
+ cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed);
+
CAIRO_CHECK_SANITY (cr);
}
void
cairo_rel_line_to (cairo_t *cr, double dx, double dy)
{
+ cairo_fixed_t dx_fixed, dy_fixed;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_rel_line_to (cr->gstate, dx, dy);
+ _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
+ dx_fixed = _cairo_fixed_from_double (dx);
+ dy_fixed = _cairo_fixed_from_double (dy);
+
+ cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed);
+
CAIRO_CHECK_SANITY (cr);
}
slim_hidden_def(cairo_rel_line_to);
@@ -1332,14 +1405,32 @@ 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_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_rel_curve_to (cr->gstate,
- dx1, dy1,
- dx2, dy2,
- dx3, dy3);
+ _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);
+
+ cr->status = _cairo_path_fixed_rel_curve_to (&cr->path,
+ dx1_fixed, dy1_fixed,
+ dx2_fixed, dy2_fixed,
+ dx3_fixed, dy3_fixed);
+
CAIRO_CHECK_SANITY (cr);
}
@@ -1378,7 +1469,8 @@ cairo_close_path (cairo_t *cr)
if (cr->status)
return;
- cr->status = _cairo_gstate_close_path (cr->gstate);
+ cr->status = _cairo_path_fixed_close_path (&cr->path);
+
CAIRO_CHECK_SANITY (cr);
}
slim_hidden_def(cairo_close_path);
@@ -1412,27 +1504,90 @@ cairo_paint (cairo_t *cr)
CAIRO_CHECK_SANITY (cr);
}
+/**
+ * cairo_stroke:
+ * @cr: a cairo context
+ *
+ * A drawing operator that strokes the current path according to the
+ * current line width, line join, line cap, and dash settings. After
+ * cairo_stroke, the current path will be cleared from the cairo
+ * context. See cairo_set_line_width(), cairo_set_line_join(),
+ * cairo_set_line_cap(), cairo_set_dash(), and
+ * cairo_stroke_preserve().
+ **/
void
cairo_stroke (cairo_t *cr)
{
+ cairo_stroke_preserve (cr);
+
+ cairo_new_path (cr);
+}
+
+/**
+ * cairo_stroke_preserve:
+ * @cr: a cairo context
+ *
+ * A drawing operator that strokes the current path according to the
+ * current line width, line join, line cap, and dash settings. Unlike
+ * cairo_stroke(), cairo_stroke_preserve preserves the path within the
+ * cairo context.
+ *
+ * See cairo_set_line_width(), cairo_set_line_join(),
+ * cairo_set_line_cap(), cairo_set_dash(), and
+ * cairo_stroke_preserve().
+ **/
+void
+cairo_stroke_preserve (cairo_t *cr)
+{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_stroke (cr->gstate);
+ cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path);
+
CAIRO_CHECK_SANITY (cr);
}
+slim_hidden_def(cairo_stroke_preserve);
+/**
+ * cairo_fill:
+ * @cr: a cairo context
+ *
+ * A drawing operator that fills the current path according to the
+ * current fill rule. After cairo_fill, the current path will be
+ * cleared from the cairo context. See cairo_set_fill_rule() and
+ * cairo_fill_preserve().
+ **/
void
cairo_fill (cairo_t *cr)
{
+ cairo_fill_preserve (cr);
+
+ cairo_new_path (cr);
+}
+
+/**
+ * cairo_fill_preserve:
+ * @cr: a cairo context
+ *
+ * A drawing operator that fills the current path according to the
+ * current fill rule. Unlike cairo_fill(), cairo_fill_preserve
+ * preserves the path within the cairo context.
+ *
+ * See cairo_set_fill_rule() and cairo_fill().
+ **/
+void
+cairo_fill_preserve (cairo_t *cr)
+{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_fill (cr->gstate);
+ cr->status = _cairo_gstate_fill (cr->gstate, &cr->path);
+
CAIRO_CHECK_SANITY (cr);
}
+slim_hidden_def(cairo_fill_preserve);
void
cairo_copy_page (cairo_t *cr)
@@ -1465,7 +1620,9 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
if (cr->status)
return 0;
- cr->status = _cairo_gstate_in_stroke (cr->gstate, x, y, &inside);
+ cr->status = _cairo_gstate_in_stroke (cr->gstate,
+ &cr->path,
+ x, y, &inside);
CAIRO_CHECK_SANITY (cr);
@@ -1484,7 +1641,9 @@ cairo_in_fill (cairo_t *cr, double x, double y)
if (cr->status)
return 0;
- cr->status = _cairo_gstate_in_fill (cr->gstate, x, y, &inside);
+ cr->status = _cairo_gstate_in_fill (cr->gstate,
+ &cr->path,
+ x, y, &inside);
CAIRO_CHECK_SANITY (cr);
@@ -1502,7 +1661,9 @@ cairo_stroke_extents (cairo_t *cr,
if (cr->status)
return;
- cr->status = _cairo_gstate_stroke_extents (cr->gstate, x1, y1, x2, y2);
+ cr->status = _cairo_gstate_stroke_extents (cr->gstate,
+ &cr->path,
+ x1, y1, x2, y2);
CAIRO_CHECK_SANITY (cr);
}
@@ -1514,7 +1675,9 @@ cairo_fill_extents (cairo_t *cr,
if (cr->status)
return;
- cr->status = _cairo_gstate_fill_extents (cr->gstate, x1, y1, x2, y2);
+ cr->status = _cairo_gstate_fill_extents (cr->gstate,
+ &cr->path,
+ x1, y1, x2, y2);
CAIRO_CHECK_SANITY (cr);
}
@@ -1526,6 +1689,9 @@ cairo_fill_extents (cairo_t *cr,
* region with the current path as it would be filled by cairo_fill()
* and according to the current fill rule (see cairo_set_fill_rule()).
*
+ * After cairo_clip, the current path will be cleared from the cairo
+ * context.
+ *
* The current clip region affects all drawing operations by
* effectively masking out any changes to the surface that are outside
* the current clip region.
@@ -1540,13 +1706,44 @@ cairo_fill_extents (cairo_t *cr,
void
cairo_clip (cairo_t *cr)
{
+ cairo_clip_preserve (cr);
+
+ cairo_new_path (cr);
+}
+
+/**
+ * cairo_clip_preserve:
+ * @cr: a cairo context
+ *
+ * Establishes a new clip region by intersecting the current clip
+ * region with the current path as it would be filled by cairo_fill()
+ * and according to the current fill rule (see cairo_set_fill_rule()).
+ *
+ * Unlike cairo_clip(), cairo_clip_preserve preserves the path within
+ * the cairo context.
+ *
+ * The current clip region affects all drawing operations by
+ * effectively masking out any changes to the surface that are outside
+ * the current clip region.
+ *
+ * Calling cairo_clip() can only make the clip region smaller, never
+ * larger. But the current clip is part of the graphics state, so a
+ * tempoarary restriction of the clip region can be achieved by
+ * calling cairo_clip() within a cairo_save()/cairo_restore()
+ * pair. The only other means of increasing the size of the clip
+ * region is cairo_reset_clip().
+ **/
+void
+cairo_clip_preserve (cairo_t *cr)
+{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
- cr->status = _cairo_gstate_clip (cr->gstate);
+ cr->status = _cairo_gstate_clip (cr->gstate, &cr->path);
CAIRO_CHECK_SANITY (cr);
}
+slim_hidden_def(cairo_clip_preserve);
/**
* cairo_reset_clip:
@@ -1763,6 +1960,7 @@ cairo_text_extents (cairo_t *cr,
{
cairo_glyph_t *glyphs = NULL;
int num_glyphs;
+ double x, y;
CAIRO_CHECK_SANITY (cr);
if (cr->status)
@@ -1778,7 +1976,11 @@ cairo_text_extents (cairo_t *cr,
return;
}
- cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, &glyphs, &num_glyphs);
+ cairo_get_current_point (cr, &x, &y);
+
+ cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+ x, y,
+ &glyphs, &num_glyphs);
CAIRO_CHECK_SANITY (cr);
if (cr->status) {
@@ -1832,6 +2034,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
{
cairo_glyph_t *glyphs = NULL;
int num_glyphs;
+ double x, y;
CAIRO_CHECK_SANITY (cr);
if (cr->status)
@@ -1840,7 +2043,10 @@ cairo_show_text (cairo_t *cr, const char *utf8)
if (utf8 == NULL)
return;
+ cairo_get_current_point (cr, &x, &y);
+
cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+ x, y,
&glyphs, &num_glyphs);
CAIRO_CHECK_SANITY (cr);
@@ -1873,12 +2079,16 @@ cairo_text_path (cairo_t *cr, const char *utf8)
{
cairo_glyph_t *glyphs = NULL;
int num_glyphs;
+ double x, y;
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
+ cairo_get_current_point (cr, &x, &y);
+
cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+ x, y,
&glyphs, &num_glyphs);
CAIRO_CHECK_SANITY (cr);
@@ -1888,7 +2098,9 @@ cairo_text_path (cairo_t *cr, const char *utf8)
return;
}
- cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs);
+ cr->status = _cairo_gstate_glyph_path (cr->gstate,
+ glyphs, num_glyphs,
+ &cr->path);
CAIRO_CHECK_SANITY (cr);
if (glyphs)
@@ -1902,7 +2114,10 @@ cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
if (cr->status)
return;
- cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs);
+ cr->status = _cairo_gstate_glyph_path (cr->gstate,
+ glyphs, num_glyphs,
+ &cr->path);
+
CAIRO_CHECK_SANITY (cr);
}
@@ -1912,12 +2127,18 @@ cairo_show_surface (cairo_t *cr,
int width,
int height)
{
+ double x, y;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
+ cairo_get_current_point (cr, &x, &y);
+
cr->status = _cairo_gstate_show_surface (cr->gstate,
- surface, width, height);
+ surface,
+ x, y,
+ width, height);
CAIRO_CHECK_SANITY (cr);
}
@@ -2001,12 +2222,32 @@ DEPRECATE (cairo_current_tolerance, cairo_get_tolerance);
* cairo_text_path(), cairo_stroke_to_path()
**/
void
-cairo_get_current_point (cairo_t *cr, double *x, double *y)
+cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
{
+ cairo_status_t status;
+ cairo_fixed_t x_fixed, y_fixed;
+ double x, y;
+
CAIRO_CHECK_SANITY (cr);
- _cairo_gstate_get_current_point (cr->gstate, x, y);
+
+ status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed);
+ if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
+ x = 0.0;
+ y = 0.0;
+ } else {
+ x = _cairo_fixed_to_double (x_fixed);
+ y = _cairo_fixed_to_double (y_fixed);
+ _cairo_gstate_backend_to_user (cr->gstate, &x, &y);
+ }
+
+ if (x_ret)
+ *x_ret = x;
+ if (y_ret)
+ *y_ret = y;
+
CAIRO_CHECK_SANITY (cr);
}
+slim_hidden_def(cairo_get_current_point);
DEPRECATE (cairo_current_point, cairo_get_current_point);
/**
@@ -2228,7 +2469,9 @@ cairo_copy_path (cairo_t *cr)
if (cr->status)
return &_cairo_path_nil;
- return _cairo_path_data_create (cr->gstate);
+ return _cairo_path_data_create (&cr->path,
+ &cr->gstate->ctm_inverse,
+ cr->gstate->tolerance);
}
/**
@@ -2257,7 +2500,9 @@ cairo_copy_path_flat (cairo_t *cr)
if (cr->status)
return &_cairo_path_nil;
- return _cairo_path_data_create_flat (cr->gstate);
+ return _cairo_path_data_create_flat (&cr->path,
+ &cr->gstate->ctm_inverse,
+ cr->gstate->tolerance);
}
/**
diff --git a/src/cairo.h b/src/cairo.h
index cf70a27b..e6cd720c 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -466,9 +466,15 @@ void
cairo_stroke (cairo_t *cr);
void
+cairo_stroke_preserve (cairo_t *cr);
+
+void
cairo_fill (cairo_t *cr);
void
+cairo_fill_preserve (cairo_t *cr);
+
+void
cairo_copy_page (cairo_t *cr);
void
@@ -496,10 +502,12 @@ cairo_fill_extents (cairo_t *cr,
void
cairo_reset_clip (cairo_t *cr);
-/* Note: cairo_clip does not consume the current path */
void
cairo_clip (cairo_t *cr);
+void
+cairo_clip_preserve (cairo_t *cr);
+
/* Font/Text functions */
/**
diff --git a/src/cairoint.h b/src/cairoint.h
index d046d45a..324c2f32 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1042,104 +1042,56 @@ _cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y);
cairo_private cairo_status_t
_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate, double *dx, double *dy);
-cairo_private cairo_status_t
-_cairo_gstate_new_path (cairo_gstate_t *gstate);
-
-cairo_private cairo_status_t
-_cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y);
-
-cairo_private cairo_status_t
-_cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y);
-
-cairo_private cairo_status_t
-_cairo_gstate_curve_to (cairo_gstate_t *gstate,
- double x1, double y1,
- double x2, double y2,
- double x3, double y3);
-
-cairo_private cairo_status_t
-_cairo_gstate_arc (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle1, double angle2);
-
-cairo_private cairo_status_t
-_cairo_gstate_arc_negative (cairo_gstate_t *gstate,
- double xc, double yc,
- double radius,
- double angle1, double angle2);
-
-cairo_private cairo_status_t
-_cairo_gstate_rel_move_to (cairo_gstate_t *gstate, double dx, double dy);
-
-cairo_private cairo_status_t
-_cairo_gstate_rel_line_to (cairo_gstate_t *gstate, double dx, double dy);
-
-cairo_private cairo_status_t
-_cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
- double dx1, double dy1,
- double dx2, double dy2,
- double dx3, double dy3);
-
-/* XXX: NYI
-cairo_private cairo_status_t
-_cairo_gstate_stroke_path (cairo_gstate_t *gstate);
-*/
+cairo_private void
+_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y);
-cairo_private cairo_status_t
-_cairo_gstate_close_path (cairo_gstate_t *gstate);
+cairo_private void
+_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y);
cairo_private cairo_status_t
-_cairo_gstate_get_current_point (cairo_gstate_t *gstate, double *x, double *y);
+_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
cairo_private cairo_status_t
-_cairo_gstate_interpret_path (cairo_gstate_t *gstate,
- cairo_move_to_func_t *move_to,
- cairo_line_to_func_t *line_to,
- cairo_curve_to_func_t *curve_to,
- cairo_close_path_func_t *close_path,
- void *closure);
+_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_gstate_get_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_t *rectangle);
cairo_private cairo_status_t
-_cairo_gstate_stroke (cairo_gstate_t *gstate);
-
-cairo_private cairo_status_t
-_cairo_gstate_fill (cairo_gstate_t *gstate);
-
-cairo_private cairo_status_t
_cairo_gstate_copy_page (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_show_page (cairo_gstate_t *gstate);
cairo_private cairo_status_t
-_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2);
cairo_private cairo_status_t
-_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
double *x1, double *y1,
double *x2, double *y2);
cairo_private cairo_status_t
-_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
- double x,
- double y,
- cairo_bool_t *inside_ret);
+_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double x,
+ double y,
+ cairo_bool_t *inside_ret);
cairo_private cairo_status_t
-_cairo_gstate_in_fill (cairo_gstate_t *gstate,
- double x,
- double y,
- cairo_bool_t *inside_ret);
+_cairo_gstate_in_fill (cairo_gstate_t *gstate,
+ cairo_path_fixed_t *path,
+ double x,
+ double y,
+ cairo_bool_t *inside_ret);
cairo_private cairo_status_t
-_cairo_gstate_clip (cairo_gstate_t *gstate);
+_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate);
@@ -1150,8 +1102,10 @@ _cairo_gstate_restore_external_state (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
cairo_surface_t *surface,
- int width,
- int height);
+ double x,
+ double y,
+ double width,
+ double height);
cairo_private cairo_status_t
_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
@@ -1185,6 +1139,8 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_private cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *font,
const char *utf8,
+ double x,
+ double y,
cairo_glyph_t **glyphs,
int *num_glyphs);
@@ -1200,9 +1156,10 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
int num_glyphs);
cairo_private cairo_status_t
-_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
- cairo_glyph_t *glyphs,
- int num_glyphs);
+_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_fixed_t *path);
/* cairo_color.c */
@@ -1331,40 +1288,45 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
cairo_private void
_cairo_path_fixed_fini (cairo_path_fixed_t *path);
-cairo_private cairo_status_t
-_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
- cairo_point_t *point);
+cairo_status_t
+_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
+ cairo_fixed_t x,
+ cairo_fixed_t y);
-cairo_private cairo_status_t
+cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
- cairo_slope_t *slope);
+ cairo_fixed_t dx,
+ cairo_fixed_t dy);
-cairo_private cairo_status_t
-_cairo_path_fixed_line_to (cairo_path_fixed_t *path,
- cairo_point_t *point);
+cairo_status_t
+_cairo_path_fixed_line_to (cairo_path_fixed_t *path,
+ cairo_fixed_t x,
+ cairo_fixed_t y);
-cairo_private cairo_status_t
+cairo_status_t
_cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
- cairo_slope_t *slope);
+ cairo_fixed_t dx,
+ cairo_fixed_t dy);
-cairo_private cairo_status_t
-_cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
- cairo_point_t *p0,
- cairo_point_t *p1,
- cairo_point_t *p2);
+cairo_status_t
+_cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
+ cairo_fixed_t x0, cairo_fixed_t y0,
+ cairo_fixed_t x1, cairo_fixed_t y1,
+ cairo_fixed_t x2, cairo_fixed_t y2);
-cairo_private cairo_status_t
+cairo_status_t
_cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
- cairo_slope_t *s0,
- cairo_slope_t *s1,
- cairo_slope_t *s2);
+ cairo_fixed_t dx0, cairo_fixed_t dy0,
+ cairo_fixed_t dx1, cairo_fixed_t dy1,
+ cairo_fixed_t dx2, cairo_fixed_t dy2);
cairo_private cairo_status_t
_cairo_path_fixed_close_path (cairo_path_fixed_t *path);
-cairo_private cairo_status_t
-_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
- cairo_point_t *point);
+cairo_status_t
+_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
+ cairo_fixed_t *x,
+ cairo_fixed_t *y);
typedef cairo_status_t
(cairo_path_fixed_move_to_func_t) (void *closure,
@@ -1805,6 +1767,9 @@ _cairo_output_stream_create_for_file (FILE *fp);
/* Avoid unnecessary PLT entries. */
+slim_hidden_proto(cairo_get_current_point)
+slim_hidden_proto(cairo_fill_preserve)
+slim_hidden_proto(cairo_clip_preserve)
slim_hidden_proto(cairo_close_path)
slim_hidden_proto(cairo_matrix_copy)
slim_hidden_proto(cairo_matrix_invert)
@@ -1818,10 +1783,12 @@ slim_hidden_proto(cairo_matrix_init_rotate)
slim_hidden_proto(cairo_matrix_transform_distance)
slim_hidden_proto(cairo_matrix_transform_point)
slim_hidden_proto(cairo_move_to)
+slim_hidden_proto(cairo_new_path)
slim_hidden_proto(cairo_rel_line_to)
slim_hidden_proto(cairo_restore)
slim_hidden_proto(cairo_save)
slim_hidden_proto(cairo_set_target_surface)
+slim_hidden_proto(cairo_stroke_preserve)
slim_hidden_proto(cairo_surface_destroy)
slim_hidden_proto(cairo_surface_get_matrix)
slim_hidden_proto(cairo_surface_set_matrix)
diff --git a/test/fill-and-stroke.c b/test/fill-and-stroke.c
index 5e0e4942..98931711 100644
--- a/test/fill-and-stroke.c
+++ b/test/fill-and-stroke.c
@@ -38,10 +38,8 @@ static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_rectangle (cr, PAD, PAD, SIZE, SIZE);
- cairo_save (cr);
cairo_set_source_rgb (cr, 0, 0, 1);
- cairo_fill (cr);
- cairo_restore (cr);
+ cairo_fill_preserve (cr);
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_stroke (cr);
@@ -51,9 +49,7 @@ draw (cairo_t *cr, int width, int height)
PAD + SIZE / 2, PAD + SIZE / 2,
SIZE / 2,
0, 2 * M_PI);
- cairo_save (cr);
- cairo_fill (cr);
- cairo_restore (cr);
+ cairo_fill_preserve (cr);
cairo_set_source_rgb (cr, 0, 0, 1);
cairo_stroke (cr);
diff --git a/test/get-and-set.c b/test/get-and-set.c
index c7d54a67..72d66104 100644
--- a/test/get-and-set.c
+++ b/test/get-and-set.c
@@ -34,14 +34,12 @@ cairo_test_t test = {
typedef struct {
cairo_operator_t operator;
double tolerance;
- double point_x;
- double point_y;
cairo_fill_rule_t fill_rule;
double line_width;
cairo_line_cap_t line_cap;
cairo_line_join_t line_join;
double miter_limit;
- /* XXX: Add cairo_matrix_t here when it is exposed */
+ cairo_matrix_t matrix;
} settings_t;
/* Two sets of settings, no defaults */
@@ -49,24 +47,22 @@ settings_t settings[] = {
{
CAIRO_OPERATOR_IN,
2.0,
- 12.3,
- 4.56,
CAIRO_FILL_RULE_EVEN_ODD,
7.7,
CAIRO_LINE_CAP_SQUARE,
CAIRO_LINE_JOIN_ROUND,
- 3.14
+ 3.14,
+ {1.0, 2.0, 3.0, 4.0, 5.0, 6.0}
},
{
CAIRO_OPERATOR_ATOP,
5.25,
- 99.99,
- 0.001,
CAIRO_FILL_RULE_WINDING,
2.17,
CAIRO_LINE_CAP_ROUND,
CAIRO_LINE_JOIN_BEVEL,
- 1000.0
+ 1000.0,
+ {.1, .01, .001, .0001, .00001, .000001}
}
};
@@ -75,12 +71,12 @@ settings_set (cairo_t *cr, settings_t *settings)
{
cairo_set_operator (cr, settings->operator);
cairo_set_tolerance (cr, settings->tolerance);
- cairo_move_to (cr, settings->point_x, settings->point_y);
cairo_set_fill_rule (cr, settings->fill_rule);
cairo_set_line_width (cr, settings->line_width);
cairo_set_line_cap (cr, settings->line_cap);
cairo_set_line_join (cr, settings->line_join);
cairo_set_miter_limit (cr, settings->miter_limit);
+ cairo_set_matrix (cr, &settings->matrix);
}
static void
@@ -88,21 +84,12 @@ settings_get (cairo_t *cr, settings_t *settings)
{
settings->operator = cairo_get_operator (cr);
settings->tolerance = cairo_get_tolerance (cr);
- cairo_get_current_point (cr, &settings->point_x, &settings->point_y);
settings->fill_rule = cairo_get_fill_rule (cr);
settings->line_width = cairo_get_line_width (cr);
settings->line_cap = cairo_get_line_cap (cr);
settings->line_join = cairo_get_line_join (cr);
settings->miter_limit = cairo_get_miter_limit (cr);
-}
-
-/* Maximum error is one part of our fixed-point grid */
-#define EPSILON (1.0 / 65536.0)
-
-static int
-DOUBLES_WITHIN_EPSILON(double a, double b) {
- double delta = fabs(a - b);
- return delta < EPSILON;
+ cairo_get_matrix (cr, &settings->matrix);
}
static int
@@ -110,13 +97,17 @@ settings_equal (settings_t *a, settings_t *b)
{
return (a->operator == b->operator &&
a->tolerance == b->tolerance &&
- DOUBLES_WITHIN_EPSILON (a->point_x, b->point_x) &&
- DOUBLES_WITHIN_EPSILON (a->point_y, b->point_y) &&
a->fill_rule == b->fill_rule &&
a->line_width == b->line_width &&
a->line_cap == b->line_cap &&
a->line_join == b->line_join &&
- a->miter_limit == b->miter_limit);
+ a->miter_limit == b->miter_limit &&
+ a->matrix.xx == b->matrix.xx &&
+ a->matrix.xy == b->matrix.xy &&
+ a->matrix.x0 == b->matrix.x0 &&
+ a->matrix.yx == b->matrix.yx &&
+ a->matrix.yy == b->matrix.yy &&
+ a->matrix.y0 == b->matrix.y0);
}
static cairo_test_status_t