mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-03 13:40:31 +01:00
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.
This commit is contained in:
parent
618792c8c0
commit
1baa4d1329
17 changed files with 1110 additions and 914 deletions
40
ChangeLog
40
ChangeLog
|
|
@ -1,3 +1,43 @@
|
|||
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:
|
||||
|
|
|
|||
2
TODO
2
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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
57
src/cairo-arc-private.h
Normal file
57
src/cairo-arc-private.h
Normal file
|
|
@ -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 */
|
||||
296
src/cairo-arc.c
Normal file
296
src/cairo-arc.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
|
||||
if (status)
|
||||
goto CLEANUP_FONT;
|
||||
|
||||
status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
|
||||
if (status)
|
||||
goto CLEANUP_PATH;
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
cpdc.tolerance = tolerance;
|
||||
cpdc.current_point.x = 0;
|
||||
cpdc.current_point.y = 0;
|
||||
|
||||
_cairo_gstate_interpret_path (gstate,
|
||||
_cpdc_move_to,
|
||||
_cpdc_line_to,
|
||||
flatten ? NULL : _cpdc_curve_to,
|
||||
_cpdc_close_path,
|
||||
&cpdc);
|
||||
_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;
|
||||
cpdp.ctm_inverse = ctm_inverse;
|
||||
cpdp.tolerance = tolerance;
|
||||
cpdp.current_point.x = 0;
|
||||
cpdp.current_point.y = 0;
|
||||
|
||||
_cairo_gstate_interpret_path (gstate,
|
||||
_cpdp_move_to,
|
||||
_cpdp_line_to,
|
||||
flatten ? NULL : _cpdp_curve_to,
|
||||
_cpdp_close_path,
|
||||
&cpdp);
|
||||
_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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, point, 1);
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
|
||||
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;
|
||||
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, point, 1);
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
331
src/cairo.c
331
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_CHECK_SANITY (cr);
|
||||
if (cr->status)
|
||||
return;
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cr->status = _cairo_gstate_stroke (cr->gstate);
|
||||
CAIRO_CHECK_SANITY (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_fill (cairo_t *cr)
|
||||
cairo_stroke_preserve (cairo_t *cr)
|
||||
{
|
||||
CAIRO_CHECK_SANITY (cr);
|
||||
if (cr->status)
|
||||
return;
|
||||
|
||||
cr->status = _cairo_gstate_fill (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->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.
|
||||
|
|
@ -1539,14 +1705,45 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
10
src/cairo.h
10
src/cairo.h
|
|
@ -465,9 +465,15 @@ cairo_paint (cairo_t *cr);
|
|||
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);
|
||||
|
||||
|
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
|
|
|||
161
src/cairoint.h
161
src/cairoint.h
|
|
@ -1042,74 +1042,22 @@ _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 void
|
||||
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_move_to (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_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 cairo_status_t
|
||||
_cairo_gstate_close_path (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_get_current_point (cairo_gstate_t *gstate, double *x, double *y);
|
||||
|
||||
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);
|
||||
|
||||
|
|
@ -1117,29 +1065,33 @@ 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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue