diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | TODO | 52 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/cairo-font.c | 11 | ||||
-rw-r--r-- | src/cairo-gstate.c | 268 | ||||
-rw-r--r-- | src/cairo.c | 47 | ||||
-rw-r--r-- | src/cairo.h | 20 | ||||
-rw-r--r-- | src/cairo_font.c | 11 | ||||
-rw-r--r-- | src/cairo_gstate.c | 268 | ||||
-rw-r--r-- | src/cairoint.h | 12 |
10 files changed, 698 insertions, 14 deletions
@@ -1,4 +1,23 @@ -2003-09-27 Carl Worth <cworth@isi.edu> +2003-09-29 Carl Worth <cworth@isi.edu> + + * configure.in (CAIRO_VERSION): Bumpred version to 0.1.6 to + indicate new cairo_arc and cairo_arc_negative. + + * src/cairo_gstate.c (_arc_error_normalized): + (_arc_max_angle_for_tolerance_normalized): + (_cairo_gstate_arc_segments_needed): + (_cairo_gstate_arc_segment): + (_cairo_gstate_arc_dir): + (_cairo_gstate_arc): + (_cairo_gstate_arc_negative): Several new functions to implement + arc support. + + * src/cairo.h: Added cairo_arc and cairo_arc_negative. + + * src/cairo.c (cairo_arc): + (cairo_arc_negative): Added new arc support. + +2003-09-27 Carl Worth <cworth@isi.edu> * src/cairoint.h: Fixed several enum symbols that had been mistakenly converted to lowercase at some point. @@ -11,12 +11,13 @@ compiled conditionally. * Verification, profiling, optimization. - Some notes on arc support -------------------------- +========================= -"Approximation of circular arcs by cubic poynomials", Michael Goldapp, -Computer Aided Geometric Design 8 (1991) 227-238. +Some general notions +-------------------- +This is from "Approximation of circular arcs by cubic poynomials", +Michael Goldapp, Computer Aided Geometric Design 8 (1991) 227-238. To draw a unit arc from 0 to A with 0 < A < pi/2: @@ -37,9 +38,14 @@ A simpler error function to work with is: e(t) = x^2(t) + y^2(t) - 1 -And from Dokken[cite]: e(t) ~ 2 abs( rho(t) ) +And 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: + + e(t) ~ 2 abs( rho(t) ) -A single cubic Bezier spline approximation must have the 4 control points: +Continuing with Goldapp's analysis, a single cubic Bezier spline +approximation must have the 4 control points: (1, 0) (1, h) @@ -55,7 +61,38 @@ From which we can determine the maximum error: abs( max(e(t)) ) = 4/27 * (sin^6 (A/4)) / (cos^2 (A/4)) t in [0,1] - + +----- + +Now, for Cairo we want to draw an arc of radius R from an angle A to +an angle B, (where B > A). So the equations above have trivial +modifications: + +The spline control points become + + (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)) + +where h = 4/3 * R * tan ((B-A)/4) + +And the maximum deviation in radius is approximately: + + 2/27 * (sin^6 ((B-A)/4) / cos^2 ((B-A)/4)) + +So now we can get down to writing some C code: + +double +_arc_error_normalized (double angle) +{ + return 2/27 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2); +} + +And for accurate drawing the following must hold in device space: + + tolerance/radius >= _arc_error_normalized (B-A) + A comparison with PostScript ============================ @@ -190,4 +227,3 @@ Operators, Rational,Boolean,and Bitwise Operators, Control Operators, Type,Attribute,and Conversion Operators, File Operators, Resource Operators, Virtual Memory Operators, Miscellaneous Operators, Interpreter Parameter Operators, Errors - diff --git a/configure.in b/configure.in index 00507343..4ad94a08 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ AC_INIT(src/cairo.h) dnl =========================================================================== # Package version number, (as distinct from shared library version) -CAIRO_VERSION=0.1.5 +CAIRO_VERSION=0.1.6 # libtool shared library version diff --git a/src/cairo-font.c b/src/cairo-font.c index 4f43f813..0494995b 100644 --- a/src/cairo-font.c +++ b/src/cairo-font.c @@ -142,7 +142,16 @@ _cairo_font_resolve_xft_font (cairo_font_t *font, cairo_gstate_t *gstate, XftFon /* XXX: The determinant gives an area expansion factor, so the math below should be correct for the (common) case of uniform X/Y scaling. Is there anything different we would want to do - for non-uniform X/Y scaling? */ + for non-uniform X/Y scaling? + + XXX: Actually, the reasoning above is bogus. A transformation + such as scale (N, 1/N) will give an expansion_factor of 1. So, + with the code below we'll end up with font_size == 1 instead of + N, (so the hinting will be all wrong). I think we want to use + the maximum eigen value rather than the square root of the + determinant. + + */ _cairo_matrix_compute_determinant (&matrix, &expansion); font_size = sqrt (fabs (expansion)); diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index b874db49..7d1cdfc3 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -707,6 +707,272 @@ _cairo_gstate_curve_to (cairo_gstate_t *gstate, return status; } +/* 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) { + /* 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_min + M_PI, dir); + if (status) + return status; + + status = _cairo_gstate_arc_dir (gstate, xc, yc, radius, + angle_min + M_PI, angle_max, dir); + if (status) + return status; + } else { + status = _cairo_gstate_arc_dir (gstate, xc, yc, radius, + angle_min + M_PI, angle_max, dir); + if (status) + return status; + + status = _cairo_gstate_arc_dir (gstate, xc, yc, radius, + angle_min, angle_min + M_PI, 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; + + 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; + + 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) { @@ -775,7 +1041,7 @@ _cairo_gstate_stroke_path (cairo_gstate_t *gstate) { cairo_status_t status; - _cairo_pen_init (&gstate + _cairo_pen_init (&gstate); return CAIRO_STATUS_SUCCESS; } */ diff --git a/src/cairo.c b/src/cairo.c index b1043ccd..909529c5 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -478,6 +478,53 @@ cairo_curve_to (cairo_t *cr, } void +cairo_arc (cairo_t *cr, + double xc, double yc, + double radius, + double angle1, double angle2) +{ + if (cr->status) + return; + + cr->status = _cairo_gstate_arc (cr->gstate, + xc, yc, + radius, + angle1, angle2); +} + +void +cairo_arc_negative (cairo_t *cr, + double xc, double yc, + double radius, + double angle1, double angle2) +{ + if (cr->status) + return; + + cr->status = _cairo_gstate_arc_negative (cr->gstate, + xc, yc, + radius, + angle1, angle2); +} + +/* XXX: NYI +void +cairo_arc_to (cairo_t *cr, + double x1, double y1, + double x2, double y2, + double radius) +{ + if (cr->status) + return; + + cr->status = _cairo_gstate_arc_to (cr->gstate, + x1, y1, + x2, y2, + radius); +} +*/ + +void cairo_rel_move_to (cairo_t *cr, double dx, double dy) { if (cr->status) diff --git a/src/cairo.h b/src/cairo.h index 171565d1..9a375f0e 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -261,6 +261,26 @@ cairo_curve_to (cairo_t *cr, double x3, double y3); extern void __external_linkage +cairo_arc (cairo_t *cr, + double xc, double yc, + double radius, + double angle1, double angle2); + +extern void __external_linkage +cairo_arc_negative (cairo_t *cr, + double xc, double yc, + double radius, + double angle1, double angle2); + +/* XXX: NYI +extern void __external_linkage +cairo_arc_to (cairo_t *cr, + double x1, double y1, + double x2, double y2, + double radius); +*/ + +extern void __external_linkage cairo_rel_move_to (cairo_t *cr, double dx, double dy); extern void __external_linkage diff --git a/src/cairo_font.c b/src/cairo_font.c index 4f43f813..0494995b 100644 --- a/src/cairo_font.c +++ b/src/cairo_font.c @@ -142,7 +142,16 @@ _cairo_font_resolve_xft_font (cairo_font_t *font, cairo_gstate_t *gstate, XftFon /* XXX: The determinant gives an area expansion factor, so the math below should be correct for the (common) case of uniform X/Y scaling. Is there anything different we would want to do - for non-uniform X/Y scaling? */ + for non-uniform X/Y scaling? + + XXX: Actually, the reasoning above is bogus. A transformation + such as scale (N, 1/N) will give an expansion_factor of 1. So, + with the code below we'll end up with font_size == 1 instead of + N, (so the hinting will be all wrong). I think we want to use + the maximum eigen value rather than the square root of the + determinant. + + */ _cairo_matrix_compute_determinant (&matrix, &expansion); font_size = sqrt (fabs (expansion)); diff --git a/src/cairo_gstate.c b/src/cairo_gstate.c index b874db49..7d1cdfc3 100644 --- a/src/cairo_gstate.c +++ b/src/cairo_gstate.c @@ -707,6 +707,272 @@ _cairo_gstate_curve_to (cairo_gstate_t *gstate, return status; } +/* 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) { + /* 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_min + M_PI, dir); + if (status) + return status; + + status = _cairo_gstate_arc_dir (gstate, xc, yc, radius, + angle_min + M_PI, angle_max, dir); + if (status) + return status; + } else { + status = _cairo_gstate_arc_dir (gstate, xc, yc, radius, + angle_min + M_PI, angle_max, dir); + if (status) + return status; + + status = _cairo_gstate_arc_dir (gstate, xc, yc, radius, + angle_min, angle_min + M_PI, 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; + + 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; + + 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) { @@ -775,7 +1041,7 @@ _cairo_gstate_stroke_path (cairo_gstate_t *gstate) { cairo_status_t status; - _cairo_pen_init (&gstate + _cairo_pen_init (&gstate); return CAIRO_STATUS_SUCCESS; } */ diff --git a/src/cairoint.h b/src/cairoint.h index cd4ec4cd..307b9703 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -544,6 +544,18 @@ _cairo_gstate_curve_to (cairo_gstate_t *gstate, double x3, double y3); extern cairo_status_t __internal_linkage +_cairo_gstate_arc (cairo_gstate_t *gstate, + double xc, double yc, + double radius, + double angle1, double angle2); + +extern cairo_status_t __internal_linkage +_cairo_gstate_arc_negative (cairo_gstate_t *gstate, + double xc, double yc, + double radius, + double angle1, double angle2); + +extern cairo_status_t __internal_linkage _cairo_gstate_rel_move_to (cairo_gstate_t *gstate, double dx, double dy); extern cairo_status_t __internal_linkage |