Originally 2005-10-28 Keith Packard <keithp@keithp.com>:

Remove pen_regular field from the gstate.
Move stroke fallback from gstate to surface where it belongs.
Eliminate dependence on cairo_gstate_t object.
Fix to include just cairo-clip-private.h rather than cairo-gstate.private.h.
This commit is contained in:
Carl Worth 2005-10-31 16:55:21 +00:00
parent 3cae05c4c5
commit a7228cc37a
8 changed files with 333 additions and 151 deletions

View file

@ -1,3 +1,31 @@
2005-10-31 Carl Worth <cworth@cworth.org>
Originally 2005-10-28 Keith Packard <keithp@keithp.com>:
* src/cairo-gstate-private.h: Remove pen_regular field from the
gstate.
* src/cairoint.h:
* src/cairo-gstate.c: (_cairo_gstate_init),
(_cairo_gstate_init_copy), (_cairo_gstate_fini),
(_cairo_gstate_stroke), (_cairo_gstate_in_stroke),
(_cairo_gstate_stroke_extents):
* src/cairo-path-stroke.c: (_cairo_stroker_start_dash),
(_cairo_stroker_step_dash), (_cairo_stroker_init),
(_cairo_stroker_fini), (_cairo_stroker_join),
(_cairo_stroker_add_cap), (_compute_face),
(_cairo_stroker_add_sub_edge), (_cairo_stroker_line_to_dashed),
(_cairo_stroker_curve_to), (_cairo_stroker_curve_to_dashed),
(_cairo_path_fixed_stroke_to_traps):
* src/cairo-surface.c: (_fallback_stroke), (_cairo_surface_stroke):
Move stroke fallback from gstate to surface where it belongs.
* src/cairo-pen.c: (_cairo_pen_init): Eliminate dependence
on cairo_gstate_t object.
* src/cairo-meta-surface.c: Fix to include just
cairo-clip-private.h rather than cairo-gstate.private.h.
2005-10-31 T Rowley <tim.rowley@gmail.com>
* src/cairo-win32-font.c (_cairo_win32_scaled_font_init_glyph_path):

View file

@ -69,8 +69,6 @@ struct _cairo_gstate {
cairo_matrix_t ctm_inverse;
cairo_matrix_t source_ctm_inverse; /* At the time ->source was set */
cairo_pen_t pen_regular;
cairo_pattern_t *source;
struct _cairo_gstate *next;

View file

@ -52,10 +52,6 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
static void
_cairo_gstate_fini (cairo_gstate_t *gstate);
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_traps_t *traps);
static cairo_status_t
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
@ -121,8 +117,6 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
_cairo_gstate_identity_matrix (gstate);
gstate->source_ctm_inverse = gstate->ctm_inverse;
_cairo_pen_init_empty (&gstate->pen_regular);
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
if (gstate->source->status)
return CAIRO_STATUS_NO_MEMORY;
@ -135,7 +129,6 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
static cairo_status_t
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
{
cairo_status_t status;
cairo_gstate_t *next;
/* Copy all members, but don't smash the next pointer */
@ -163,20 +156,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
cairo_pattern_reference (gstate->source);
status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
if (status)
goto CLEANUP_FONT;
return status;
CLEANUP_FONT:
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
free (gstate->dash);
gstate->dash = NULL;
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -197,8 +177,6 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_pattern_destroy (gstate->source);
_cairo_pen_fini (&gstate->pen_regular);
if (gstate->dash) {
free (gstate->dash);
gstate->dash = NULL;
@ -1157,7 +1135,7 @@ cairo_status_t
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_traps_t traps;
cairo_pattern_union_t source_pattern;
if (gstate->source->status)
return gstate->source->status;
@ -1169,21 +1147,28 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (status)
return status;
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
_cairo_traps_init (&traps);
status = _cairo_surface_stroke (gstate->operator,
&source_pattern.base,
gstate->target,
path,
gstate->tolerance,
&gstate->ctm,
&gstate->ctm_inverse,
gstate->antialias,
status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
}
gstate->line_width,
gstate->line_cap,
gstate->line_join,
gstate->miter_limit,
_cairo_gstate_clip_and_composite_trapezoids (gstate, &traps);
gstate->dash,
gstate->num_dashes,
gstate->dash_offset);
return status;
_cairo_traps_fini (&traps);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -1198,11 +1183,21 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
_cairo_gstate_user_to_backend (gstate, &x, &y);
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_cairo_traps_init (&traps);
status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
status = _cairo_path_fixed_stroke_to_traps (path, &traps,
gstate->tolerance,
&gstate->ctm,
&gstate->ctm_inverse,
gstate->line_width,
gstate->line_cap,
gstate->line_join,
gstate->miter_limit,
gstate->dash,
gstate->num_dashes,
gstate->dash_offset);
if (status)
goto BAIL;
@ -1498,28 +1493,6 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
return status;
}
/* Warning: This call modifies the coordinates of traps */
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
cairo_traps_t *traps)
{
cairo_pattern_union_t pattern;
cairo_status_t status;
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_surface_clip_and_composite_trapezoids (&pattern.base,
gstate->operator,
gstate->target,
traps,
&gstate->clip,
gstate->antialias);
_cairo_pattern_fini (&pattern.base);
return status;
}
cairo_status_t
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
@ -1598,11 +1571,21 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
cairo_traps_t traps;
cairo_box_t extents;
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
_cairo_traps_init (&traps);
status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
status = _cairo_path_fixed_stroke_to_traps (path, &traps,
gstate->tolerance,
&gstate->ctm,
&gstate->ctm_inverse,
gstate->line_width,
gstate->line_cap,
gstate->line_join,
gstate->miter_limit,
gstate->dash,
gstate->num_dashes,
gstate->dash_offset);
if (status)
goto BAIL;

View file

@ -35,7 +35,7 @@
#include "cairoint.h"
#include "cairo-meta-surface-private.h"
#include "cairo-gstate-private.h"
#include "cairo-clip-private.h"
static const cairo_surface_backend_t cairo_meta_surface_backend;

View file

@ -36,12 +36,26 @@
#include "cairoint.h"
#include "cairo-gstate-private.h"
typedef struct cairo_stroker {
cairo_gstate_t *gstate;
cairo_traps_t *traps;
cairo_pen_t pen;
cairo_matrix_t *ctm;
cairo_matrix_t *ctm_inverse;
double tolerance;
/* stroke style */
double line_width;
cairo_line_cap_t line_cap;
cairo_line_join_t line_join;
double miter_limit;
/* dash style */
double *dash;
int num_dashes;
double dash_offset;
cairo_bool_t has_current_point;
cairo_point_t current_point;
cairo_point_t first_point;
@ -60,7 +74,21 @@ typedef struct cairo_stroker {
/* private functions */
static void
_cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_traps_t *traps);
_cairo_stroker_init (cairo_stroker_t *stroker,
cairo_traps_t *traps,
double tolerance,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double line_width,
cairo_line_cap_t line_cap,
cairo_line_join_t line_join,
double miter_limit,
double *dash,
int num_dashes,
double dash_offset);
static void
_cairo_stroker_fini (cairo_stroker_t *stroker);
@ -101,49 +129,75 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
static void
_cairo_stroker_start_dash (cairo_stroker_t *stroker)
{
cairo_gstate_t *gstate = stroker->gstate;
double offset;
int on = 1;
int i = 0;
offset = gstate->dash_offset;
while (offset >= gstate->dash[i]) {
offset -= gstate->dash[i];
offset = stroker->dash_offset;
while (offset >= stroker->dash[i]) {
offset -= stroker->dash[i];
on = 1-on;
if (++i == gstate->num_dashes)
if (++i == stroker->num_dashes)
i = 0;
}
stroker->dashed = TRUE;
stroker->dash_index = i;
stroker->dash_on = on;
stroker->dash_remain = gstate->dash[i] - offset;
stroker->dash_remain = stroker->dash[i] - offset;
}
static void
_cairo_stroker_step_dash (cairo_stroker_t *stroker, double step)
{
cairo_gstate_t *gstate = stroker->gstate;
stroker->dash_remain -= step;
if (stroker->dash_remain <= 0) {
stroker->dash_index++;
if (stroker->dash_index == gstate->num_dashes)
if (stroker->dash_index == stroker->num_dashes)
stroker->dash_index = 0;
stroker->dash_on = 1-stroker->dash_on;
stroker->dash_remain = gstate->dash[stroker->dash_index];
stroker->dash_remain = stroker->dash[stroker->dash_index];
}
}
static void
_cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_traps_t *traps)
_cairo_stroker_init (cairo_stroker_t *stroker,
cairo_traps_t *traps,
double tolerance,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double line_width,
cairo_line_cap_t line_cap,
cairo_line_join_t line_join,
double miter_limit,
double *dash,
int num_dashes,
double dash_offset)
{
stroker->gstate = gstate;
stroker->traps = traps;
_cairo_pen_init (&stroker->pen, line_width / 2.0, tolerance, ctm);
stroker->tolerance = tolerance;
stroker->ctm = ctm;
stroker->ctm_inverse = ctm_inverse;
stroker->line_width = line_width;
stroker->line_cap = line_cap;
stroker->line_join = line_join;
stroker->miter_limit = miter_limit;
stroker->dash = dash;
stroker->num_dashes = num_dashes;
stroker->dash_offset = dash_offset;
stroker->has_current_point = FALSE;
stroker->has_current_face = FALSE;
stroker->has_first_face = FALSE;
if (gstate->dash)
if (stroker->dash)
_cairo_stroker_start_dash (stroker);
else
stroker->dashed = FALSE;
@ -152,7 +206,7 @@ _cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_tra
static void
_cairo_stroker_fini (cairo_stroker_t *stroker)
{
/* nothing to do here */
_cairo_pen_fini (&stroker->pen);
}
static void
@ -177,8 +231,7 @@ static cairo_status_t
_cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out)
{
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
int clockwise = _cairo_stroker_face_clockwise (out, in);
int clockwise = _cairo_stroker_face_clockwise (out, in);
cairo_point_t *inpt, *outpt;
if (in->cw.x == out->cw.x
@ -196,12 +249,12 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
outpt = &out->cw;
}
switch (gstate->line_join) {
switch (stroker->line_join) {
case CAIRO_LINE_JOIN_ROUND: {
int i;
int start, step, stop;
cairo_point_t tri[3];
cairo_pen_t *pen = &gstate->pen_regular;
cairo_pen_t *pen = &stroker->pen;
tri[0] = in->point;
if (clockwise) {
@ -237,7 +290,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
/* dot product of incoming slope vector with outgoing slope vector */
double in_dot_out = ((-in->usr_vector.x * out->usr_vector.x)+
(-in->usr_vector.y * out->usr_vector.y));
double ml = gstate->miter_limit;
double ml = stroker->miter_limit;
/*
* Check the miter limit -- lines meeting at an acute angle
@ -285,14 +338,14 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
y1 = _cairo_fixed_to_double (inpt->y);
dx1 = in->usr_vector.x;
dy1 = in->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
cairo_matrix_transform_distance (stroker->ctm, &dx1, &dy1);
/* outer point of outgoing line face */
x2 = _cairo_fixed_to_double (outpt->x);
y2 = _cairo_fixed_to_double (outpt->y);
dx2 = out->usr_vector.x;
dy2 = out->usr_vector.y;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
/*
* Compute the location of the outer corner of the miter.
@ -344,18 +397,17 @@ static cairo_status_t
_cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
{
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
if (gstate->line_cap == CAIRO_LINE_CAP_BUTT)
if (stroker->line_cap == CAIRO_LINE_CAP_BUTT)
return CAIRO_STATUS_SUCCESS;
switch (gstate->line_cap) {
switch (stroker->line_cap) {
case CAIRO_LINE_CAP_ROUND: {
int i;
int start, stop;
cairo_slope_t slope;
cairo_point_t tri[3];
cairo_pen_t *pen = &gstate->pen_regular;
cairo_pen_t *pen = &stroker->pen;
slope = f->dev_vector;
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
@ -383,9 +435,9 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
dx = f->usr_vector.x;
dy = f->usr_vector.y;
dx *= gstate->line_width / 2.0;
dy *= gstate->line_width / 2.0;
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
dx *= stroker->line_width / 2.0;
dy *= stroker->line_width / 2.0;
cairo_matrix_transform_distance (stroker->ctm, &dx, &dy);
fvector.dx = _cairo_fixed_from_double (dx);
fvector.dy = _cairo_fixed_from_double (dy);
occw.x = f->ccw.x + fvector.dx;
@ -460,7 +512,7 @@ _cairo_stroker_add_caps (cairo_stroker_t *stroker)
}
static void
_compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face)
_compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_stroker_t *stroker, cairo_stroke_face_t *face)
{
double mag, det;
double line_dx, line_dy;
@ -472,7 +524,7 @@ _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstat
line_dy = _cairo_fixed_to_double (slope->dy);
/* faces are normal in user space, not device space */
cairo_matrix_transform_distance (&gstate->ctm_inverse, &line_dx, &line_dy);
cairo_matrix_transform_distance (stroker->ctm_inverse, &line_dx, &line_dy);
mag = sqrt (line_dx * line_dx + line_dy * line_dy);
if (mag == 0) {
@ -494,20 +546,20 @@ _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstat
* whether the ctm reflects or not, and that can be determined
* by looking at the determinant of the matrix.
*/
_cairo_matrix_compute_determinant (&gstate->ctm, &det);
_cairo_matrix_compute_determinant (stroker->ctm, &det);
if (det >= 0)
{
face_dx = - line_dy * (gstate->line_width / 2.0);
face_dy = line_dx * (gstate->line_width / 2.0);
face_dx = - line_dy * (stroker->line_width / 2.0);
face_dy = line_dx * (stroker->line_width / 2.0);
}
else
{
face_dx = line_dy * (gstate->line_width / 2.0);
face_dy = - line_dx * (gstate->line_width / 2.0);
face_dx = line_dy * (stroker->line_width / 2.0);
face_dy = - line_dx * (stroker->line_width / 2.0);
}
/* back to device space */
cairo_matrix_transform_distance (&gstate->ctm, &face_dx, &face_dy);
cairo_matrix_transform_distance (stroker->ctm, &face_dx, &face_dy);
offset_ccw.x = _cairo_fixed_from_double (face_dx);
offset_ccw.y = _cairo_fixed_from_double (face_dy);
@ -533,7 +585,6 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
cairo_stroke_face_t *start, cairo_stroke_face_t *end)
{
cairo_status_t status;
cairo_gstate_t *gstate = stroker->gstate;
cairo_polygon_t polygon;
cairo_slope_t slope;
@ -545,12 +596,12 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
}
_cairo_slope_init (&slope, p1, p2);
_compute_face (p1, &slope, gstate, start);
_compute_face (p1, &slope, stroker, start);
/* XXX: This could be optimized slightly by not calling
_compute_face again but rather translating the relevant
fields from start. */
_compute_face (p2, &slope, gstate, end);
_compute_face (p2, &slope, stroker, end);
/* XXX: I should really check the return value of the
move_to/line_to functions here to catch out of memory
@ -648,7 +699,6 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
cairo_gstate_t *gstate = stroker->gstate;
double mag, remain, tmp;
double dx, dy;
double dx2, dy2;
@ -664,7 +714,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
cairo_matrix_transform_distance (&gstate->ctm_inverse, &dx, &dy);
cairo_matrix_transform_distance (stroker->ctm_inverse, &dx, &dy);
mag = sqrt (dx *dx + dy * dy);
remain = mag;
@ -676,7 +726,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
remain -= tmp;
dx2 = dx * (mag - remain)/mag;
dy2 = dy * (mag - remain)/mag;
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
fd2.x = _cairo_fixed_from_double (dx2);
fd2.y = _cairo_fixed_from_double (dy2);
fd2.x += p1->x;
@ -764,7 +814,6 @@ _cairo_stroker_curve_to (void *closure,
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
cairo_gstate_t *gstate = stroker->gstate;
cairo_spline_t spline;
cairo_pen_t pen;
cairo_stroke_face_t start, end;
@ -775,12 +824,12 @@ _cairo_stroker_curve_to (void *closure,
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
status = _cairo_pen_init_copy (&pen, &gstate->pen_regular);
status = _cairo_pen_init_copy (&pen, &stroker->pen);
if (status)
goto CLEANUP_SPLINE;
_compute_face (a, &spline.initial_slope, gstate, &start);
_compute_face (d, &spline.final_slope, gstate, &end);
_compute_face (a, &spline.initial_slope, stroker, &start);
_compute_face (d, &spline.final_slope, stroker, &end);
if (stroker->has_current_face) {
status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
@ -812,7 +861,7 @@ _cairo_stroker_curve_to (void *closure,
if (status)
goto CLEANUP_PEN;
status = _cairo_pen_stroke_spline (&pen, &spline, gstate->tolerance, stroker->traps);
status = _cairo_pen_stroke_spline (&pen, &spline, stroker->tolerance, stroker->traps);
if (status)
goto CLEANUP_PEN;
@ -852,7 +901,6 @@ _cairo_stroker_curve_to_dashed (void *closure,
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t *stroker = closure;
cairo_gstate_t *gstate = stroker->gstate;
cairo_spline_t spline;
cairo_point_t *a = &stroker->current_point;
cairo_line_join_t line_join_save;
@ -864,15 +912,15 @@ _cairo_stroker_curve_to_dashed (void *closure,
/* If the line width is so small that the pen is reduced to a
single point, then we have nothing to do. */
if (gstate->pen_regular.num_vertices <= 1)
if (stroker->pen.num_vertices <= 1)
goto CLEANUP_SPLINE;
/* Temporarily modify the gstate to use round joins to guarantee
/* Temporarily modify the stroker to use round joins to guarantee
* smooth stroked curves. */
line_join_save = gstate->line_join;
gstate->line_join = CAIRO_LINE_JOIN_ROUND;
line_join_save = stroker->line_join;
stroker->line_join = CAIRO_LINE_JOIN_ROUND;
status = _cairo_spline_decompose (&spline, gstate->tolerance);
status = _cairo_spline_decompose (&spline, stroker->tolerance);
if (status)
goto CLEANUP_GSTATE;
@ -886,7 +934,7 @@ _cairo_stroker_curve_to_dashed (void *closure,
}
CLEANUP_GSTATE:
gstate->line_join = line_join_save;
stroker->line_join = line_join_save;
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
@ -923,16 +971,29 @@ _cairo_stroker_close_path (void *closure)
}
cairo_status_t
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_gstate_t *gstate,
cairo_traps_t *traps)
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_traps_t *traps,
double tolerance,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double line_width,
cairo_line_cap_t line_cap,
cairo_line_join_t line_join,
double miter_limit,
double *dash,
int num_dashes,
double dash_offset)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_stroker_t stroker;
_cairo_stroker_init (&stroker, gstate, traps);
_cairo_stroker_init (&stroker, traps, tolerance, ctm, ctm_inverse,
line_width, line_cap, line_join, miter_limit,
dash, num_dashes, dash_offset);
if (gstate->dash)
if (stroker.dash)
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_stroker_move_to,

View file

@ -36,8 +36,6 @@
#include "cairoint.h"
#include "cairo-gstate-private.h"
static int
_cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix);
@ -59,35 +57,28 @@ _cairo_pen_init_empty (cairo_pen_t *pen)
}
cairo_status_t
_cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
_cairo_pen_init (cairo_pen_t *pen,
double radius,
double tolerance,
cairo_matrix_t *ctm)
{
int i;
int reflect;
double det;
if (pen->num_vertices) {
/* XXX: It would be nice to notice that the pen is already properly constructed.
However, this test would also have to account for possible changes in the transformation
matrix.
if (pen->radius == radius && pen->tolerance == tolerance)
return CAIRO_STATUS_SUCCESS;
*/
_cairo_pen_fini (pen);
}
pen->radius = radius;
pen->tolerance = gstate->tolerance;
pen->tolerance = tolerance;
_cairo_matrix_compute_determinant (&gstate->ctm, &det);
_cairo_matrix_compute_determinant (ctm, &det);
if (det >= 0) {
reflect = 0;
} else {
reflect = 1;
}
pen->num_vertices = _cairo_pen_vertices_needed (gstate->tolerance,
pen->num_vertices = _cairo_pen_vertices_needed (tolerance,
radius,
&gstate->ctm);
ctm);
pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL) {
@ -105,7 +96,7 @@ _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
double dx = radius * cos (reflect ? -theta : theta);
double dy = radius * sin (reflect ? -theta : theta);
cairo_pen_vertex_t *v = &pen->vertices[i];
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
cairo_matrix_transform_distance (ctm, &dx, &dy);
v->point.x = _cairo_fixed_from_double (dx);
v->point.y = _cairo_fixed_from_double (dy);
}

View file

@ -38,7 +38,7 @@
#include <stdlib.h>
#include "cairoint.h"
#include "cairo-gstate-private.h"
#include "cairo-clip-private.h"
const cairo_surface_t _cairo_surface_nil = {
&cairo_image_surface_backend, /* backend */
@ -1302,6 +1302,94 @@ _cairo_surface_mask (cairo_operator_t operator,
return _fallback_mask (operator, source_pattern, mask_pattern, dst);
}
static cairo_status_t
_fallback_stroke (cairo_operator_t operator,
cairo_pattern_t *source_pattern,
cairo_surface_t *dst,
cairo_path_fixed_t *path,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias,
double line_width,
cairo_line_cap_t line_cap,
cairo_line_join_t line_join,
double miter_limit,
double *dash,
int num_dashes,
double dash_offset)
{
cairo_status_t status;
cairo_traps_t traps;
_cairo_traps_init (&traps);
status = _cairo_path_fixed_stroke_to_traps (path, &traps, tolerance,
ctm, ctm_inverse,
line_width, line_cap,
line_join, miter_limit,
dash, num_dashes,
dash_offset);
if (status) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_surface_clip_and_composite_trapezoids (source_pattern,
operator,
dst,
&traps,
dst->clip,
antialias);
_cairo_traps_fini (&traps);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_surface_stroke (cairo_operator_t operator,
cairo_pattern_t *source_pattern,
cairo_surface_t *dst,
cairo_path_fixed_t *path,
double tolerance,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
cairo_antialias_t antialias,
double line_width,
cairo_line_cap_t line_cap,
cairo_line_join_t line_join,
double miter_limit,
double *dash,
int num_dashes,
double dash_offset)
{
assert (! dst->is_snapshot);
/* XXX: Need to add this to the backend.
if (dst->backend->stroke) {
cairo_status_t status;
status = dst->backend->stroke (operator, source_pattern, dst, path,
ctm, ctm_inverse, tolerance, antialias,
line_width, line_cap,
line_join, miter_limit,
dash, num_dashes, dash_offset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
*/
return _fallback_stroke (operator, source_pattern, dst, path,
ctm, ctm_inverse, tolerance, antialias,
line_width, line_cap, line_join, miter_limit,
dash, num_dashes, dash_offset);
}
static cairo_status_t
_fallback_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,

View file

@ -1419,9 +1419,20 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
/* cairo_path_stroke.c */
cairo_private cairo_status_t
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_gstate_t *gstate,
cairo_traps_t *traps);
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
cairo_traps_t *traps,
double tolerance,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double line_width,
cairo_line_cap_t line_cap,
cairo_line_join_t line_join,
double miter_limit,
double *dash,
int num_dashes,
double dash_offset);
/* cairo-scaled-font.c */
@ -1581,6 +1592,25 @@ _cairo_surface_mask (cairo_operator_t operator,
cairo_pattern_t *mask_pattern,
cairo_surface_t *dst);
cairo_private cairo_status_t
_cairo_surface_stroke (cairo_operator_t operator,
cairo_pattern_t *source_pattern,
cairo_surface_t *dst,
cairo_path_fixed_t *path,
double tolerance,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
cairo_antialias_t antialias,
double line_width,
cairo_line_cap_t line_cap,
cairo_line_join_t line_join,
double miter_limit,
double *dash,
int num_dashes,
double dash_offset);
cairo_private cairo_status_t
_cairo_surface_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
@ -1762,7 +1792,10 @@ _cairo_surface_is_image (const cairo_surface_t *surface);
/* cairo_pen.c */
cairo_private cairo_status_t
_cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate);
_cairo_pen_init (cairo_pen_t *pen,
double radius,
double tolerance,
cairo_matrix_t *ctm);
cairo_private cairo_status_t
_cairo_pen_init_empty (cairo_pen_t *pen);