mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-31 12:30:13 +01:00
Cleaned up XrPathInterpret. Prepare for splines
This commit is contained in:
parent
20f631ce22
commit
c1c7ee62bc
15 changed files with 772 additions and 348 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
94
src/xrfiller.c
Normal file
94
src/xrfiller.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
113
src/xrint.h
113
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);
|
||||
|
|
|
|||
144
src/xrpath.c
144
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,14 +36,6 @@ static XrTransform XR_TRANSFORM_DEFAULT = {
|
|||
}
|
||||
};
|
||||
|
||||
static XrTransform XR_TRANSFORM_ZERO = {
|
||||
{
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0}
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
XrTransformInit(XrTransform *transform)
|
||||
{
|
||||
|
|
|
|||
94
xrfiller.c
Normal file
94
xrfiller.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
99
xrgstate.c
99
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);
|
||||
|
||||
|
|
|
|||
113
xrint.h
113
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);
|
||||
|
|
|
|||
144
xrpath.c
144
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);
|
||||
}
|
||||
|
|
|
|||
54
xrpolygon.c
54
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
46
xrstroker.c
46
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,14 +36,6 @@ static XrTransform XR_TRANSFORM_DEFAULT = {
|
|||
}
|
||||
};
|
||||
|
||||
static XrTransform XR_TRANSFORM_ZERO = {
|
||||
{
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0}
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
XrTransformInit(XrTransform *transform)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue