diff --git a/Imakefile b/Imakefile index 4470484ce..e64edeb5a 100644 --- a/Imakefile +++ b/Imakefile @@ -24,9 +24,11 @@ INCLUDES = -I$(XLIBSRE) SRCS = xr.c \ xrcolor.c \ + xrfiller.c \ xrgstate.c \ xrpath.c \ xrpolygon.c \ + xrspline.c \ xrstate.c \ xrstroker.c \ xrsurface.c \ @@ -35,9 +37,11 @@ SRCS = xr.c \ OBJS = xr.o \ xrcolor.o \ + xrfiller.o \ xrgstate.o \ xrpath.o \ xrpolygon.o \ + xrspline.o \ xrstate.o \ xrstroker.o \ xrsurface.o \ diff --git a/src/xrfiller.c b/src/xrfiller.c new file mode 100644 index 000000000..0034f1a03 --- /dev/null +++ b/src/xrfiller.c @@ -0,0 +1,94 @@ +/* + * $XFree86: $ + * + * Copyright © 2002 Carl D. Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Carl + * D. Worth not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Carl D. Worth makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * CARL D. WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL CARL D. WORTH BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xrint.h" + +void +XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps) +{ + filler->gstate = gstate; + filler->traps = traps; + + XrPolygonInit(&filler->polygon); +} + +void +XrFillerDeinit(XrFiller *filler) +{ + XrPolygonDeinit(&filler->polygon); +} + +XrError +XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) +{ + XrFiller *filler = closure; + XrPolygon *polygon = &filler->polygon; + + return XrPolygonAddEdge(polygon, p1, p2); +} + +XrError +XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d) +{ + int i; + XrError err = XrErrorSuccess; + XrFiller *filler = closure; + XrPolygon *polygon = &filler->polygon; + XrGState *gstate = filler->gstate; + XrSpline spline; + + XrSplineInit(&spline, a, b, c, d); + XrSplineDecompose(&spline, gstate->tolerance); + if (err) + goto CLEANUP_SPLINE; + + for (i = 0; i < spline.num_pts; i++) { + err = XrPolygonAddEdge(polygon, + &spline.pt[i], + i < spline.num_pts ? &spline.pt[i+1] : &spline.pt[0]); + if (err) + goto CLEANUP_SPLINE; + } + + CLEANUP_SPLINE: + XrSplineDeinit(&spline); + + return err; +} + +XrError +XrFillerDoneSubPath (void *closure, XrSubPathDone done) +{ + return XrErrorSuccess; +} + +XrError +XrFillerDonePath (void *closure) +{ + XrFiller *filler = closure; + + return XrTrapsTessellatePolygon(filler->traps, &filler->polygon, filler->gstate->winding); +} + diff --git a/src/xrgstate.c b/src/xrgstate.c index b62dbc683..7ac05b07d 100644 --- a/src/xrgstate.c +++ b/src/xrgstate.c @@ -49,6 +49,8 @@ XrGStateInit(XrGState *gstate, Display *dpy) gstate->operator = XR_GSTATE_OPERATOR_DEFAULT; + gstate->tolerance = XR_GSTATE_TOLERANCE_DEFAULT; + gstate->winding = XR_GSTATE_WINDING_DEFAULT; gstate->line_width = XR_GSTATE_LINE_WIDTH_DEFAULT; @@ -198,8 +200,6 @@ XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join) XrError XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset) { - double *ndashes; - if (gstate->dashes) { free (gstate->dashes); } @@ -273,18 +273,20 @@ XrGStateAddPathOp(XrGState *gstate, XrPathOp op, XPointDouble *pt, int num_pts) switch (op) { case XrPathOpMoveTo: case XrPathOpLineTo: + case XrPathOpCurveTo: for (i=0; i < num_pts; i++) { XrTransformPoint(&gstate->ctm, &pt[i]); } break; case XrPathOpRelMoveTo: case XrPathOpRelLineTo: + case XrPathOpRelCurveTo: for (i=0; i < num_pts; i++) { XrTransformPointWithoutTranslate(&gstate->ctm, &pt[i]); } break; - default: - return XrErrorSuccess; + case XrPathOpClosePath: + break; } pt_fixed = malloc(num_pts * sizeof(XPointFixed)); @@ -326,54 +328,22 @@ XrGStateStroke(XrGState *gstate) { XrError err; - static XrPathCallbacks cb = { XrStrokerAddEdge, XrStrokerDoneSubPath }; + static XrPathCallbacks cb = { + XrStrokerAddEdge, + XrStrokerAddSpline, + XrStrokerDoneSubPath, + XrStrokerDonePath + }; XrStroker stroker; XrTraps traps; - XrStrokerInit(&stroker, gstate, &traps); XrTrapsInit(&traps); + XrStrokerInit(&stroker, gstate, &traps); err = XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &stroker); - if (err) - return err; - - XcCompositeTrapezoids(gstate->dpy, gstate->operator, - gstate->src.xcsurface, gstate->surface.xcsurface, - gstate->alphaFormat, - 0, 0, - traps.xtraps, - traps.num_xtraps); - - XrTrapsDeinit(&traps); - XrStrokerDeinit(&stroker); - - XrGStateNewPath(gstate); - - return XrErrorSuccess; -} - -XrError -XrGStateFill(XrGState *gstate) -{ - XrError err; - static XrPathCallbacks cb = { XrPolygonAddEdge, XrPolygonDoneSubPath }; - - XrPolygon polygon; - XrTraps traps; - - XrPolygonInit(&polygon); - - err = XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &polygon); - if (err) { - XrPolygonDeinit(&polygon); - return err; - } - - XrTrapsInit(&traps); - - err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->winding); if (err) { + XrStrokerDeinit(&stroker); XrTrapsDeinit(&traps); return err; } @@ -385,8 +355,47 @@ XrGStateFill(XrGState *gstate) traps.xtraps, traps.num_xtraps); + XrStrokerDeinit(&stroker); + XrTrapsDeinit(&traps); + + XrGStateNewPath(gstate); + + return XrErrorSuccess; +} + +XrError +XrGStateFill(XrGState *gstate) +{ + XrError err; + static XrPathCallbacks cb = { + XrFillerAddEdge, + XrFillerAddSpline, + XrFillerDoneSubPath, + XrFillerDonePath + }; + + XrFiller filler; + XrTraps traps; + + XrTrapsInit(&traps); + XrFillerInit(&filler, gstate, &traps); + + err = XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &filler); + if (err) { + XrFillerDeinit(&filler); + XrTrapsDeinit(&traps); + return err; + } + + XcCompositeTrapezoids(gstate->dpy, gstate->operator, + gstate->src.xcsurface, gstate->surface.xcsurface, + gstate->alphaFormat, + 0, 0, + traps.xtraps, + traps.num_xtraps); + + XrFillerDeinit(&filler); XrTrapsDeinit(&traps); - XrPolygonDeinit(&polygon); XrGStateNewPath(gstate); diff --git a/src/xrint.h b/src/xrint.h index 0e178917b..3e128a4a1 100644 --- a/src/xrint.h +++ b/src/xrint.h @@ -48,13 +48,13 @@ typedef enum _XrError { } XrError; typedef enum _XrPathOp { - XrPathOpMoveTo, - XrPathOpLineTo, - XrPathOpCurveTo, - XrPathOpRelMoveTo, - XrPathOpRelLineTo, - XrPathOpRelCurveTo, - XrPathOpClosePath + XrPathOpMoveTo = 0, + XrPathOpLineTo = 1, + XrPathOpCurveTo = 2, + XrPathOpRelMoveTo = 3, + XrPathOpRelLineTo = 4, + XrPathOpRelCurveTo = 5, + XrPathOpClosePath = 6 } __attribute__ ((packed)) XrPathOp; /* Don't want 32 bits if we can avoid it. */ typedef enum _XrPathDirection { @@ -69,7 +69,9 @@ typedef enum _XrSubPathDone { typedef struct _XrPathCallbacks { XrError (*AddEdge)(void *closure, XPointFixed *p1, XPointFixed *p2); + XrError (*AddSpline)(void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); XrError (*DoneSubPath) (void *closure, XrSubPathDone done); + XrError (*DonePath) (void *closure); } XrPathCallbacks; #define XR_PATH_BUF_SZ 64 @@ -113,6 +115,31 @@ typedef struct _XrPolygon { XrEdge *edges; } XrPolygon; +typedef struct _XrSpline { + XPointFixed a, b, c, d; + XPointFixed *pt; + int num_pts; +} XrSpline; + +typedef enum _XrPenVertexStart { + XrPenVertexNone, + XrPenVertexForward, + XrPenVertexRevers +} XrPenVertexStart; + +typedef struct _XrPenVertex { + XPointFixed pt; + double theta; + XPointFixed slope_ccw; + XPointFixed slope_cw; + XrPenVertexStart start; +} XrPenVertex; + +typedef struct _XrPen { + int num_vertices; + XrPenVertex *vertex; +} XrPen; + typedef struct _XrSurface { Display *dpy; @@ -148,6 +175,7 @@ typedef struct _XrTraps { } XrTraps; #define XR_GSTATE_OPERATOR_DEFAULT XrOperatorOver +#define XR_GSTATE_TOLERANCE_DEFAULT 0.1 #define XR_GSTATE_WINDING_DEFAULT 1 #define XR_GSTATE_LINE_WIDTH_DEFAULT 2.0 #define XR_GSTATE_LINE_CAP_DEFAULT XrLineCapButt @@ -157,6 +185,8 @@ typedef struct _XrTraps { typedef struct _XrGState { Display *dpy; + double tolerance; + /* stroke style */ double line_width; XrLineCap line_cap; @@ -183,6 +213,8 @@ typedef struct _XrGState { XrPath path; + XrPen pen_regular; + struct _XrGState *next; } XrGState; @@ -207,6 +239,13 @@ typedef struct _XrStroker { XrStrokeFace first; } XrStroker; +typedef struct _XrFiller { + XrGState *gstate; + XrTraps *traps; + + XrPolygon polygon; +} XrFiller; + /* xrstate.c */ #define CURRENT_GSTATE(xrs) (xrs->stack) @@ -356,20 +395,43 @@ XrSurfaceSetVisual(XrSurface *surface, Visual *visual); void XrSurfaceSetFormat(XrSurface *surface, XrFormat format); +/* xrpen.c */ +XrError +XrPenInit(XrPen *pen, double radius); + +XrError +XrPenInitCopy(XrPen *pen, XrPen *other); + +void +XrPenDeinit(XrPen *pen); + +void +XrPenAddPointsForSlopes(XrPen *pen, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); + +XrError +XrPenStrokePoints(XrPen *pen, XPointFixed *pt, int num_pts, XrPolygon *polygon); + /* xrpolygon.c */ void -XrPolygonInit(XrPolygon *poly); +XrPolygonInit(XrPolygon *polygon); void -XrPolygonDeinit(XrPolygon *poly); +XrPolygonDeinit(XrPolygon *polygon); XrError -XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); +XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2); + +/* xrspline.c */ +void +XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); XrError -XrPolygonDoneSubPath (void *closure, XrSubPathDone done); - -/* xrstroke.c */ +XrSplineDecompose(XrSpline *spline, double tolerance); + +void +XrSplineDeinit(XrSpline *spline); + +/* xrstroker.c */ void XrStrokerInit(XrStroker *stroker, XrGState *gstate, XrTraps *traps); @@ -379,9 +441,34 @@ XrStrokerDeinit(XrStroker *stroker); XrError XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); +XrError +XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); + XrError XrStrokerDoneSubPath (void *closure, XrSubPathDone done); +XrError +XrStrokerDonePath (void *closure); + +/* xrfiller.c */ +void +XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps); + +void +XrFillerDeinit(XrFiller *filler); + +XrError +XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); + +XrError +XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); + +XrError +XrFillerDoneSubPath (void *closure, XrSubPathDone done); + +XrError +XrFillerDonePath (void *closure); + /* xrtransform.c */ void XrTransformInit(XrTransform *transform); diff --git a/src/xrpath.c b/src/xrpath.c index 9c75db2bb..127cdafb4 100644 --- a/src/xrpath.c +++ b/src/xrpath.c @@ -270,46 +270,29 @@ _TranslatePointFixed(XPointFixed *pt, XPointFixed *offset) pt->y += offset->y; } -#define START_ARGS(n) \ -{ \ - if (dir != XrPathDirectionForward) \ - { \ - if (arg_i == 0) { \ - arg_buf = arg_buf->prev; \ - arg_i = arg_buf->num_pts; \ - } \ - arg_i -= n; \ - } \ -} +#define XR_PATH_OP_MAX_ARGS 3 -#define NEXT_ARG(pt) \ -{ \ - (pt) = arg_buf->pt[arg_i]; \ - arg_i++; \ - if (arg_i >= arg_buf->num_pts) { \ - arg_buf = arg_buf->next; \ - arg_i = 0; \ - } \ -} - -#define END_ARGS(n) \ -{ \ - if (dir != XrPathDirectionForward) \ - { \ - arg_i -= n; \ - } \ -} +static int num_args[] = +{ + 1, /* XrPathMoveTo */ + 1, /* XrPathOpLineTo */ + 3, /* XrPathOpCurveTo */ + 1, /* XrPathOpRelMoveTo */ + 1, /* XrPathOpRelLineTo */ + 3, /* XrPathOpRelCurveTo */ + 0, /* XrPathOpClosePath */ +}; XrError XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *closure) { XrError err; - int i; + int i, arg; XrPathOpBuf *op_buf; XrPathOp op; XrPathArgBuf *arg_buf = path->arg_head; - int arg_i = 0; - XPointFixed pt; + int buf_i = 0; + XPointFixed pt[XR_PATH_OP_MAX_ARGS]; XPointFixed current = {0, 0}; XPointFixed first = {0, 0}; int has_current = 0; @@ -334,67 +317,76 @@ XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *cl { op = op_buf->op[i]; + if (dir == XrPathDirectionReverse) { + if (buf_i == 0) { + arg_buf = arg_buf->prev; + buf_i = arg_buf->num_pts; + } + buf_i -= num_args[op]; + } + + for (arg = 0; arg < num_args[op]; arg++) { + pt[arg] = arg_buf->pt[buf_i]; + buf_i++; + if (buf_i >= arg_buf->num_pts) { + arg_buf = arg_buf->next; + buf_i = 0; + } + } + + if (dir == XrPathDirectionReverse) { + buf_i -= num_args[op]; + } + switch (op) { + case XrPathOpRelMoveTo: + _TranslatePointFixed(&pt[0], ¤t); + /* fall-through */ case XrPathOpMoveTo: if (has_edge) { err = (*cb->DoneSubPath) (closure, XrSubPathDoneCap); if (err) return err; } - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - first = pt; - current = pt; - has_current = 1; - has_edge = 0; - break; - case XrPathOpLineTo: - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - if (has_current) { - err = (*cb->AddEdge)(closure, ¤t, &pt); - if (err) - return err; - current = pt; - has_edge = 1; - } else { - first = pt; - current = pt; - has_current = 1; - } - break; - case XrPathOpRelMoveTo: - if (has_edge) { - err = (*cb->DoneSubPath) (closure, XrSubPathDoneCap); - if (err) - return err; - } - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - _TranslatePointFixed(&pt, ¤t); - first = pt; - current = pt; + first = pt[0]; + current = pt[0]; has_current = 1; has_edge = 0; break; case XrPathOpRelLineTo: - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - _TranslatePointFixed(&pt, ¤t); + _TranslatePointFixed(&pt[0], ¤t); + /* fall-through */ + case XrPathOpLineTo: if (has_current) { - err = (*cb->AddEdge)(closure, ¤t, &pt); + err = (*cb->AddEdge)(closure, ¤t, &pt[0]); if (err) return err; - current = pt; + current = pt[0]; has_edge = 1; } else { - first = pt; - current = pt; + first = pt[0]; + current = pt[0]; has_current = 1; + has_edge = 0; + } + break; + case XrPathOpRelCurveTo: + for (arg = 0; arg < num_args[op]; arg++) { + _TranslatePointFixed(&pt[arg], ¤t); + } + /* fall-through */ + case XrPathOpCurveTo: + if (has_current) { + err = (*cb->AddSpline)(closure, ¤t, &pt[0], &pt[1], &pt[2]); + if (err) + return err; + current = pt[2]; + has_edge = 1; + } else { + first = pt[2]; + current = pt[2]; + has_current = 1; + has_edge = 0; } break; case XrPathOpClosePath: @@ -415,5 +407,5 @@ XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *cl if (has_edge) (*cb->DoneSubPath) (closure, XrSubPathDoneCap); - return XrErrorSuccess; + return (*cb->DonePath)(closure); } diff --git a/src/xrpolygon.c b/src/xrpolygon.c index eba9bea63..ab1d073c4 100644 --- a/src/xrpolygon.c +++ b/src/xrpolygon.c @@ -31,71 +31,70 @@ /* private functions */ static XrError -_XrPolygonGrowBy(XrPolygon *poly, int additional); +_XrPolygonGrowBy(XrPolygon *polygon, int additional); void -XrPolygonInit(XrPolygon *poly) +XrPolygonInit(XrPolygon *polygon) { - poly->num_edges = 0; + polygon->num_edges = 0; - poly->edges_size = 0; - poly->edges = NULL; + polygon->edges_size = 0; + polygon->edges = NULL; } void -XrPolygonDeinit(XrPolygon *poly) +XrPolygonDeinit(XrPolygon *polygon) { - if (poly->edges_size) { - free(poly->edges); - poly->edges_size = 0; - poly->num_edges = 0; + if (polygon->edges_size) { + free(polygon->edges); + polygon->edges_size = 0; + polygon->num_edges = 0; } } static XrError -_XrPolygonGrowBy(XrPolygon *poly, int additional) +_XrPolygonGrowBy(XrPolygon *polygon, int additional) { XrEdge *new_edges; - int old_size = poly->edges_size; - int new_size = poly->num_edges + additional; + int old_size = polygon->edges_size; + int new_size = polygon->num_edges + additional; - if (new_size <= poly->edges_size) { + if (new_size <= polygon->edges_size) { return XrErrorSuccess; } - poly->edges_size = new_size; - new_edges = realloc(poly->edges, poly->edges_size * sizeof(XrEdge)); + polygon->edges_size = new_size; + new_edges = realloc(polygon->edges, polygon->edges_size * sizeof(XrEdge)); if (new_edges == NULL) { - poly->edges_size = old_size; + polygon->edges_size = old_size; return XrErrorNoMemory; } - poly->edges = new_edges; + polygon->edges = new_edges; return XrErrorSuccess; } XrError -XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) +XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2) { XrError err; XrEdge *edge; - XrPolygon *poly = closure; /* drop horizontal edges */ if (p1->y == p2->y) { return XrErrorSuccess; } - if (poly->num_edges >= poly->edges_size) { - err = _XrPolygonGrowBy(poly, XR_POLYGON_GROWTH_INC); + if (polygon->num_edges >= polygon->edges_size) { + err = _XrPolygonGrowBy(polygon, XR_POLYGON_GROWTH_INC); if (err) { return err; } } - edge = &poly->edges[poly->num_edges]; + edge = &polygon->edges[polygon->num_edges]; if (p1->y < p2->y) { edge->edge.p1 = *p1; edge->edge.p2 = *p2; @@ -106,14 +105,7 @@ XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) edge->clockWise = False; } - poly->num_edges++; + polygon->num_edges++; return XrErrorSuccess; } - -XrError -XrPolygonDoneSubPath (void *closure, XrSubPathDone done) -{ - return XrErrorSuccess; -} - diff --git a/src/xrstroker.c b/src/xrstroker.c index 8f1084fcd..c479e03d1 100644 --- a/src/xrstroker.c +++ b/src/xrstroker.c @@ -166,7 +166,7 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f) case XrLineCapSquare: { XPointDouble vector = f->vector; XPointFixed fvector; - XPointFixed outer, occw, ocw; + XPointFixed occw, ocw; vector.x *= gstate->line_width / 2.0; vector.y *= gstate->line_width / 2.0; XrTransformPointWithoutTranslate(&gstate->ctm, &vector); @@ -269,6 +269,44 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) return XrTrapsTessellateRectangle(traps, quad); } +XrError +XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d) +{ + XrError err = XrErrorSuccess; + XrStroker *stroker = closure; + XrSpline spline; + XrPolygon polygon; + XrPen pen; + + XrSplineInit(&spline, a, b, c, d); + err = XrSplineDecompose(&spline, stroker->gstate->tolerance); + if (err) + goto CLEANUP_SPLINE; + + XrPolygonInit(&polygon); + + err = XrPenInitCopy(&pen, &stroker->gstate->pen_regular); + if (err) + goto CLEANUP_POLYGON; + + XrPenAddPointsForSlopes(&pen, a, b, c, d); + + err = XrPenStrokePoints(&pen, spline.pt, spline.num_pts, &polygon); + if (err) + goto CLEANUP_PEN; + + err = XrTrapsTessellatePolygon(stroker->traps, &polygon, 1); + + CLEANUP_PEN: + XrPenDeinit(&pen); + CLEANUP_POLYGON: + XrPolygonDeinit(&polygon); + CLEANUP_SPLINE: + XrSplineDeinit(&spline); + + return err; +} + XrError XrStrokerDoneSubPath (void *closure, XrSubPathDone done) { @@ -289,3 +327,9 @@ XrStrokerDoneSubPath (void *closure, XrSubPathDone done) return XrErrorSuccess; } + +XrError +XrStrokerDonePath (void *closure) +{ + return XrErrorSuccess; +} diff --git a/src/xrtransform.c b/src/xrtransform.c index 8e859fe89..97cb083b8 100644 --- a/src/xrtransform.c +++ b/src/xrtransform.c @@ -36,14 +36,6 @@ static XrTransform XR_TRANSFORM_DEFAULT = { } }; -static XrTransform XR_TRANSFORM_ZERO = { - { - {0, 0}, - {0, 0}, - {0, 0} - } -}; - void XrTransformInit(XrTransform *transform) { diff --git a/xrfiller.c b/xrfiller.c new file mode 100644 index 000000000..0034f1a03 --- /dev/null +++ b/xrfiller.c @@ -0,0 +1,94 @@ +/* + * $XFree86: $ + * + * Copyright © 2002 Carl D. Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Carl + * D. Worth not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Carl D. Worth makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * CARL D. WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL CARL D. WORTH BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xrint.h" + +void +XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps) +{ + filler->gstate = gstate; + filler->traps = traps; + + XrPolygonInit(&filler->polygon); +} + +void +XrFillerDeinit(XrFiller *filler) +{ + XrPolygonDeinit(&filler->polygon); +} + +XrError +XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) +{ + XrFiller *filler = closure; + XrPolygon *polygon = &filler->polygon; + + return XrPolygonAddEdge(polygon, p1, p2); +} + +XrError +XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d) +{ + int i; + XrError err = XrErrorSuccess; + XrFiller *filler = closure; + XrPolygon *polygon = &filler->polygon; + XrGState *gstate = filler->gstate; + XrSpline spline; + + XrSplineInit(&spline, a, b, c, d); + XrSplineDecompose(&spline, gstate->tolerance); + if (err) + goto CLEANUP_SPLINE; + + for (i = 0; i < spline.num_pts; i++) { + err = XrPolygonAddEdge(polygon, + &spline.pt[i], + i < spline.num_pts ? &spline.pt[i+1] : &spline.pt[0]); + if (err) + goto CLEANUP_SPLINE; + } + + CLEANUP_SPLINE: + XrSplineDeinit(&spline); + + return err; +} + +XrError +XrFillerDoneSubPath (void *closure, XrSubPathDone done) +{ + return XrErrorSuccess; +} + +XrError +XrFillerDonePath (void *closure) +{ + XrFiller *filler = closure; + + return XrTrapsTessellatePolygon(filler->traps, &filler->polygon, filler->gstate->winding); +} + diff --git a/xrgstate.c b/xrgstate.c index b62dbc683..7ac05b07d 100644 --- a/xrgstate.c +++ b/xrgstate.c @@ -49,6 +49,8 @@ XrGStateInit(XrGState *gstate, Display *dpy) gstate->operator = XR_GSTATE_OPERATOR_DEFAULT; + gstate->tolerance = XR_GSTATE_TOLERANCE_DEFAULT; + gstate->winding = XR_GSTATE_WINDING_DEFAULT; gstate->line_width = XR_GSTATE_LINE_WIDTH_DEFAULT; @@ -198,8 +200,6 @@ XrGStateSetLineJoin(XrGState *gstate, XrLineJoin line_join) XrError XrGStateSetDash(XrGState *gstate, double *dashes, int ndash, double offset) { - double *ndashes; - if (gstate->dashes) { free (gstate->dashes); } @@ -273,18 +273,20 @@ XrGStateAddPathOp(XrGState *gstate, XrPathOp op, XPointDouble *pt, int num_pts) switch (op) { case XrPathOpMoveTo: case XrPathOpLineTo: + case XrPathOpCurveTo: for (i=0; i < num_pts; i++) { XrTransformPoint(&gstate->ctm, &pt[i]); } break; case XrPathOpRelMoveTo: case XrPathOpRelLineTo: + case XrPathOpRelCurveTo: for (i=0; i < num_pts; i++) { XrTransformPointWithoutTranslate(&gstate->ctm, &pt[i]); } break; - default: - return XrErrorSuccess; + case XrPathOpClosePath: + break; } pt_fixed = malloc(num_pts * sizeof(XPointFixed)); @@ -326,54 +328,22 @@ XrGStateStroke(XrGState *gstate) { XrError err; - static XrPathCallbacks cb = { XrStrokerAddEdge, XrStrokerDoneSubPath }; + static XrPathCallbacks cb = { + XrStrokerAddEdge, + XrStrokerAddSpline, + XrStrokerDoneSubPath, + XrStrokerDonePath + }; XrStroker stroker; XrTraps traps; - XrStrokerInit(&stroker, gstate, &traps); XrTrapsInit(&traps); + XrStrokerInit(&stroker, gstate, &traps); err = XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &stroker); - if (err) - return err; - - XcCompositeTrapezoids(gstate->dpy, gstate->operator, - gstate->src.xcsurface, gstate->surface.xcsurface, - gstate->alphaFormat, - 0, 0, - traps.xtraps, - traps.num_xtraps); - - XrTrapsDeinit(&traps); - XrStrokerDeinit(&stroker); - - XrGStateNewPath(gstate); - - return XrErrorSuccess; -} - -XrError -XrGStateFill(XrGState *gstate) -{ - XrError err; - static XrPathCallbacks cb = { XrPolygonAddEdge, XrPolygonDoneSubPath }; - - XrPolygon polygon; - XrTraps traps; - - XrPolygonInit(&polygon); - - err = XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &polygon); - if (err) { - XrPolygonDeinit(&polygon); - return err; - } - - XrTrapsInit(&traps); - - err = XrTrapsTessellatePolygon(&traps, &polygon, gstate->winding); if (err) { + XrStrokerDeinit(&stroker); XrTrapsDeinit(&traps); return err; } @@ -385,8 +355,47 @@ XrGStateFill(XrGState *gstate) traps.xtraps, traps.num_xtraps); + XrStrokerDeinit(&stroker); + XrTrapsDeinit(&traps); + + XrGStateNewPath(gstate); + + return XrErrorSuccess; +} + +XrError +XrGStateFill(XrGState *gstate) +{ + XrError err; + static XrPathCallbacks cb = { + XrFillerAddEdge, + XrFillerAddSpline, + XrFillerDoneSubPath, + XrFillerDonePath + }; + + XrFiller filler; + XrTraps traps; + + XrTrapsInit(&traps); + XrFillerInit(&filler, gstate, &traps); + + err = XrPathInterpret(&gstate->path, XrPathDirectionForward, &cb, &filler); + if (err) { + XrFillerDeinit(&filler); + XrTrapsDeinit(&traps); + return err; + } + + XcCompositeTrapezoids(gstate->dpy, gstate->operator, + gstate->src.xcsurface, gstate->surface.xcsurface, + gstate->alphaFormat, + 0, 0, + traps.xtraps, + traps.num_xtraps); + + XrFillerDeinit(&filler); XrTrapsDeinit(&traps); - XrPolygonDeinit(&polygon); XrGStateNewPath(gstate); diff --git a/xrint.h b/xrint.h index 0e178917b..3e128a4a1 100644 --- a/xrint.h +++ b/xrint.h @@ -48,13 +48,13 @@ typedef enum _XrError { } XrError; typedef enum _XrPathOp { - XrPathOpMoveTo, - XrPathOpLineTo, - XrPathOpCurveTo, - XrPathOpRelMoveTo, - XrPathOpRelLineTo, - XrPathOpRelCurveTo, - XrPathOpClosePath + XrPathOpMoveTo = 0, + XrPathOpLineTo = 1, + XrPathOpCurveTo = 2, + XrPathOpRelMoveTo = 3, + XrPathOpRelLineTo = 4, + XrPathOpRelCurveTo = 5, + XrPathOpClosePath = 6 } __attribute__ ((packed)) XrPathOp; /* Don't want 32 bits if we can avoid it. */ typedef enum _XrPathDirection { @@ -69,7 +69,9 @@ typedef enum _XrSubPathDone { typedef struct _XrPathCallbacks { XrError (*AddEdge)(void *closure, XPointFixed *p1, XPointFixed *p2); + XrError (*AddSpline)(void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); XrError (*DoneSubPath) (void *closure, XrSubPathDone done); + XrError (*DonePath) (void *closure); } XrPathCallbacks; #define XR_PATH_BUF_SZ 64 @@ -113,6 +115,31 @@ typedef struct _XrPolygon { XrEdge *edges; } XrPolygon; +typedef struct _XrSpline { + XPointFixed a, b, c, d; + XPointFixed *pt; + int num_pts; +} XrSpline; + +typedef enum _XrPenVertexStart { + XrPenVertexNone, + XrPenVertexForward, + XrPenVertexRevers +} XrPenVertexStart; + +typedef struct _XrPenVertex { + XPointFixed pt; + double theta; + XPointFixed slope_ccw; + XPointFixed slope_cw; + XrPenVertexStart start; +} XrPenVertex; + +typedef struct _XrPen { + int num_vertices; + XrPenVertex *vertex; +} XrPen; + typedef struct _XrSurface { Display *dpy; @@ -148,6 +175,7 @@ typedef struct _XrTraps { } XrTraps; #define XR_GSTATE_OPERATOR_DEFAULT XrOperatorOver +#define XR_GSTATE_TOLERANCE_DEFAULT 0.1 #define XR_GSTATE_WINDING_DEFAULT 1 #define XR_GSTATE_LINE_WIDTH_DEFAULT 2.0 #define XR_GSTATE_LINE_CAP_DEFAULT XrLineCapButt @@ -157,6 +185,8 @@ typedef struct _XrTraps { typedef struct _XrGState { Display *dpy; + double tolerance; + /* stroke style */ double line_width; XrLineCap line_cap; @@ -183,6 +213,8 @@ typedef struct _XrGState { XrPath path; + XrPen pen_regular; + struct _XrGState *next; } XrGState; @@ -207,6 +239,13 @@ typedef struct _XrStroker { XrStrokeFace first; } XrStroker; +typedef struct _XrFiller { + XrGState *gstate; + XrTraps *traps; + + XrPolygon polygon; +} XrFiller; + /* xrstate.c */ #define CURRENT_GSTATE(xrs) (xrs->stack) @@ -356,20 +395,43 @@ XrSurfaceSetVisual(XrSurface *surface, Visual *visual); void XrSurfaceSetFormat(XrSurface *surface, XrFormat format); +/* xrpen.c */ +XrError +XrPenInit(XrPen *pen, double radius); + +XrError +XrPenInitCopy(XrPen *pen, XrPen *other); + +void +XrPenDeinit(XrPen *pen); + +void +XrPenAddPointsForSlopes(XrPen *pen, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); + +XrError +XrPenStrokePoints(XrPen *pen, XPointFixed *pt, int num_pts, XrPolygon *polygon); + /* xrpolygon.c */ void -XrPolygonInit(XrPolygon *poly); +XrPolygonInit(XrPolygon *polygon); void -XrPolygonDeinit(XrPolygon *poly); +XrPolygonDeinit(XrPolygon *polygon); XrError -XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); +XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2); + +/* xrspline.c */ +void +XrSplineInit(XrSpline *spline, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); XrError -XrPolygonDoneSubPath (void *closure, XrSubPathDone done); - -/* xrstroke.c */ +XrSplineDecompose(XrSpline *spline, double tolerance); + +void +XrSplineDeinit(XrSpline *spline); + +/* xrstroker.c */ void XrStrokerInit(XrStroker *stroker, XrGState *gstate, XrTraps *traps); @@ -379,9 +441,34 @@ XrStrokerDeinit(XrStroker *stroker); XrError XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); +XrError +XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); + XrError XrStrokerDoneSubPath (void *closure, XrSubPathDone done); +XrError +XrStrokerDonePath (void *closure); + +/* xrfiller.c */ +void +XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps); + +void +XrFillerDeinit(XrFiller *filler); + +XrError +XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); + +XrError +XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d); + +XrError +XrFillerDoneSubPath (void *closure, XrSubPathDone done); + +XrError +XrFillerDonePath (void *closure); + /* xrtransform.c */ void XrTransformInit(XrTransform *transform); diff --git a/xrpath.c b/xrpath.c index 9c75db2bb..127cdafb4 100644 --- a/xrpath.c +++ b/xrpath.c @@ -270,46 +270,29 @@ _TranslatePointFixed(XPointFixed *pt, XPointFixed *offset) pt->y += offset->y; } -#define START_ARGS(n) \ -{ \ - if (dir != XrPathDirectionForward) \ - { \ - if (arg_i == 0) { \ - arg_buf = arg_buf->prev; \ - arg_i = arg_buf->num_pts; \ - } \ - arg_i -= n; \ - } \ -} +#define XR_PATH_OP_MAX_ARGS 3 -#define NEXT_ARG(pt) \ -{ \ - (pt) = arg_buf->pt[arg_i]; \ - arg_i++; \ - if (arg_i >= arg_buf->num_pts) { \ - arg_buf = arg_buf->next; \ - arg_i = 0; \ - } \ -} - -#define END_ARGS(n) \ -{ \ - if (dir != XrPathDirectionForward) \ - { \ - arg_i -= n; \ - } \ -} +static int num_args[] = +{ + 1, /* XrPathMoveTo */ + 1, /* XrPathOpLineTo */ + 3, /* XrPathOpCurveTo */ + 1, /* XrPathOpRelMoveTo */ + 1, /* XrPathOpRelLineTo */ + 3, /* XrPathOpRelCurveTo */ + 0, /* XrPathOpClosePath */ +}; XrError XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *closure) { XrError err; - int i; + int i, arg; XrPathOpBuf *op_buf; XrPathOp op; XrPathArgBuf *arg_buf = path->arg_head; - int arg_i = 0; - XPointFixed pt; + int buf_i = 0; + XPointFixed pt[XR_PATH_OP_MAX_ARGS]; XPointFixed current = {0, 0}; XPointFixed first = {0, 0}; int has_current = 0; @@ -334,67 +317,76 @@ XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *cl { op = op_buf->op[i]; + if (dir == XrPathDirectionReverse) { + if (buf_i == 0) { + arg_buf = arg_buf->prev; + buf_i = arg_buf->num_pts; + } + buf_i -= num_args[op]; + } + + for (arg = 0; arg < num_args[op]; arg++) { + pt[arg] = arg_buf->pt[buf_i]; + buf_i++; + if (buf_i >= arg_buf->num_pts) { + arg_buf = arg_buf->next; + buf_i = 0; + } + } + + if (dir == XrPathDirectionReverse) { + buf_i -= num_args[op]; + } + switch (op) { + case XrPathOpRelMoveTo: + _TranslatePointFixed(&pt[0], ¤t); + /* fall-through */ case XrPathOpMoveTo: if (has_edge) { err = (*cb->DoneSubPath) (closure, XrSubPathDoneCap); if (err) return err; } - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - first = pt; - current = pt; - has_current = 1; - has_edge = 0; - break; - case XrPathOpLineTo: - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - if (has_current) { - err = (*cb->AddEdge)(closure, ¤t, &pt); - if (err) - return err; - current = pt; - has_edge = 1; - } else { - first = pt; - current = pt; - has_current = 1; - } - break; - case XrPathOpRelMoveTo: - if (has_edge) { - err = (*cb->DoneSubPath) (closure, XrSubPathDoneCap); - if (err) - return err; - } - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - _TranslatePointFixed(&pt, ¤t); - first = pt; - current = pt; + first = pt[0]; + current = pt[0]; has_current = 1; has_edge = 0; break; case XrPathOpRelLineTo: - START_ARGS(1); - NEXT_ARG(pt); - END_ARGS(1); - _TranslatePointFixed(&pt, ¤t); + _TranslatePointFixed(&pt[0], ¤t); + /* fall-through */ + case XrPathOpLineTo: if (has_current) { - err = (*cb->AddEdge)(closure, ¤t, &pt); + err = (*cb->AddEdge)(closure, ¤t, &pt[0]); if (err) return err; - current = pt; + current = pt[0]; has_edge = 1; } else { - first = pt; - current = pt; + first = pt[0]; + current = pt[0]; has_current = 1; + has_edge = 0; + } + break; + case XrPathOpRelCurveTo: + for (arg = 0; arg < num_args[op]; arg++) { + _TranslatePointFixed(&pt[arg], ¤t); + } + /* fall-through */ + case XrPathOpCurveTo: + if (has_current) { + err = (*cb->AddSpline)(closure, ¤t, &pt[0], &pt[1], &pt[2]); + if (err) + return err; + current = pt[2]; + has_edge = 1; + } else { + first = pt[2]; + current = pt[2]; + has_current = 1; + has_edge = 0; } break; case XrPathOpClosePath: @@ -415,5 +407,5 @@ XrPathInterpret(XrPath *path, XrPathDirection dir, XrPathCallbacks *cb, void *cl if (has_edge) (*cb->DoneSubPath) (closure, XrSubPathDoneCap); - return XrErrorSuccess; + return (*cb->DonePath)(closure); } diff --git a/xrpolygon.c b/xrpolygon.c index eba9bea63..ab1d073c4 100644 --- a/xrpolygon.c +++ b/xrpolygon.c @@ -31,71 +31,70 @@ /* private functions */ static XrError -_XrPolygonGrowBy(XrPolygon *poly, int additional); +_XrPolygonGrowBy(XrPolygon *polygon, int additional); void -XrPolygonInit(XrPolygon *poly) +XrPolygonInit(XrPolygon *polygon) { - poly->num_edges = 0; + polygon->num_edges = 0; - poly->edges_size = 0; - poly->edges = NULL; + polygon->edges_size = 0; + polygon->edges = NULL; } void -XrPolygonDeinit(XrPolygon *poly) +XrPolygonDeinit(XrPolygon *polygon) { - if (poly->edges_size) { - free(poly->edges); - poly->edges_size = 0; - poly->num_edges = 0; + if (polygon->edges_size) { + free(polygon->edges); + polygon->edges_size = 0; + polygon->num_edges = 0; } } static XrError -_XrPolygonGrowBy(XrPolygon *poly, int additional) +_XrPolygonGrowBy(XrPolygon *polygon, int additional) { XrEdge *new_edges; - int old_size = poly->edges_size; - int new_size = poly->num_edges + additional; + int old_size = polygon->edges_size; + int new_size = polygon->num_edges + additional; - if (new_size <= poly->edges_size) { + if (new_size <= polygon->edges_size) { return XrErrorSuccess; } - poly->edges_size = new_size; - new_edges = realloc(poly->edges, poly->edges_size * sizeof(XrEdge)); + polygon->edges_size = new_size; + new_edges = realloc(polygon->edges, polygon->edges_size * sizeof(XrEdge)); if (new_edges == NULL) { - poly->edges_size = old_size; + polygon->edges_size = old_size; return XrErrorNoMemory; } - poly->edges = new_edges; + polygon->edges = new_edges; return XrErrorSuccess; } XrError -XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) +XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2) { XrError err; XrEdge *edge; - XrPolygon *poly = closure; /* drop horizontal edges */ if (p1->y == p2->y) { return XrErrorSuccess; } - if (poly->num_edges >= poly->edges_size) { - err = _XrPolygonGrowBy(poly, XR_POLYGON_GROWTH_INC); + if (polygon->num_edges >= polygon->edges_size) { + err = _XrPolygonGrowBy(polygon, XR_POLYGON_GROWTH_INC); if (err) { return err; } } - edge = &poly->edges[poly->num_edges]; + edge = &polygon->edges[polygon->num_edges]; if (p1->y < p2->y) { edge->edge.p1 = *p1; edge->edge.p2 = *p2; @@ -106,14 +105,7 @@ XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) edge->clockWise = False; } - poly->num_edges++; + polygon->num_edges++; return XrErrorSuccess; } - -XrError -XrPolygonDoneSubPath (void *closure, XrSubPathDone done) -{ - return XrErrorSuccess; -} - diff --git a/xrstroker.c b/xrstroker.c index 8f1084fcd..c479e03d1 100644 --- a/xrstroker.c +++ b/xrstroker.c @@ -166,7 +166,7 @@ _XrStrokerCap(XrStroker *stroker, XrStrokeFace *f) case XrLineCapSquare: { XPointDouble vector = f->vector; XPointFixed fvector; - XPointFixed outer, occw, ocw; + XPointFixed occw, ocw; vector.x *= gstate->line_width / 2.0; vector.y *= gstate->line_width / 2.0; XrTransformPointWithoutTranslate(&gstate->ctm, &vector); @@ -269,6 +269,44 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) return XrTrapsTessellateRectangle(traps, quad); } +XrError +XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d) +{ + XrError err = XrErrorSuccess; + XrStroker *stroker = closure; + XrSpline spline; + XrPolygon polygon; + XrPen pen; + + XrSplineInit(&spline, a, b, c, d); + err = XrSplineDecompose(&spline, stroker->gstate->tolerance); + if (err) + goto CLEANUP_SPLINE; + + XrPolygonInit(&polygon); + + err = XrPenInitCopy(&pen, &stroker->gstate->pen_regular); + if (err) + goto CLEANUP_POLYGON; + + XrPenAddPointsForSlopes(&pen, a, b, c, d); + + err = XrPenStrokePoints(&pen, spline.pt, spline.num_pts, &polygon); + if (err) + goto CLEANUP_PEN; + + err = XrTrapsTessellatePolygon(stroker->traps, &polygon, 1); + + CLEANUP_PEN: + XrPenDeinit(&pen); + CLEANUP_POLYGON: + XrPolygonDeinit(&polygon); + CLEANUP_SPLINE: + XrSplineDeinit(&spline); + + return err; +} + XrError XrStrokerDoneSubPath (void *closure, XrSubPathDone done) { @@ -289,3 +327,9 @@ XrStrokerDoneSubPath (void *closure, XrSubPathDone done) return XrErrorSuccess; } + +XrError +XrStrokerDonePath (void *closure) +{ + return XrErrorSuccess; +} diff --git a/xrtransform.c b/xrtransform.c index 8e859fe89..97cb083b8 100644 --- a/xrtransform.c +++ b/xrtransform.c @@ -36,14 +36,6 @@ static XrTransform XR_TRANSFORM_DEFAULT = { } }; -static XrTransform XR_TRANSFORM_ZERO = { - { - {0, 0}, - {0, 0}, - {0, 0} - } -}; - void XrTransformInit(XrTransform *transform) {