Removed state from XrFiller that was redundant with state in XrPolygon. Fixed state update in XrStroker so that paths with multiple subpaths work. Simplified error-prone sorting in XrPenAddPoints. Renamed XrPenVertexTag to XrPenVertexFlag, (to allow for a single vertex that is the starting point for both the forward and reverse half-path).

This commit is contained in:
Carl Worth 2002-09-13 12:55:37 +00:00
parent 2ba3786b27
commit 1fa0a496bb
12 changed files with 158 additions and 216 deletions

2
Xr.h
View file

@ -43,8 +43,6 @@ XrSave(XrState *xrs);
void
XrRestore(XrState *xrs);
/* XXX: NYI: XrClone */
/* Modify state */
void
XrSetDrawable(XrState *xrs, Drawable drawable);

View file

@ -43,8 +43,6 @@ XrSave(XrState *xrs);
void
XrRestore(XrState *xrs);
/* XXX: NYI: XrClone */
/* Modify state */
void
XrSetDrawable(XrState *xrs, Drawable drawable);

View file

@ -32,8 +32,6 @@ XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps)
filler->traps = traps;
XrPolygonInit(&filler->polygon);
filler->have_prev = 0;
}
void
@ -48,12 +46,6 @@ XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
XrFiller *filler = closure;
XrPolygon *polygon = &filler->polygon;
if (filler->have_prev == 0) {
filler->have_prev = 1;
filler->first = *p1;
}
filler->prev = *p2;
return XrPolygonAddEdge(polygon, p1, p2);
}
@ -67,12 +59,6 @@ XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c
XrGState *gstate = filler->gstate;
XrSpline spline;
if (filler->have_prev == 0) {
filler->have_prev = 1;
filler->first = *a;
}
filler->prev = *d;
err = XrSplineInit(&spline, a, b, c, d);
if (err == XrErrorDegenerate)
return XrErrorSuccess;
@ -100,8 +86,7 @@ XrFillerDoneSubPath (void *closure, XrSubPathDone done)
XrFiller *filler = closure;
XrPolygon *polygon = &filler->polygon;
if (filler->have_prev)
err = XrPolygonAddEdge(polygon, &filler->prev, &filler->first);
XrPolygonClose(polygon);
return err;
}

View file

@ -140,20 +140,20 @@ typedef struct _XrSpline {
XPointFixed *pts;
} XrSpline;
typedef enum _XrPenVertexTag {
XrPenVertexTagNone,
XrPenVertexTagForward,
XrPenVertexTagReverse
} XrPenVertexTag;
typedef enum _XrPenVertexFlag {
XrPenVertexFlagNone = 0,
XrPenVertexFlagForward = 1,
XrPenVertexFlagReverse = 2
} XrPenVertexFlag;
typedef struct _XrPenTaggedPoint {
typedef struct _XrPenFlaggedPoint {
XPointFixed pt;
XrPenVertexTag tag;
} XrPenTaggedPoint;
XrPenVertexFlag flag;
} XrPenFlaggedPoint;
typedef struct _XrPenVertex {
XPointFixed pt;
XrPenVertexTag tag;
XrPenVertexFlag flag;
double theta;
XrSlopeFixed slope_ccw;
@ -278,10 +278,6 @@ typedef struct _XrFiller {
XrTraps *traps;
XrPolygon polygon;
int have_prev;
XPointFixed prev;
XPointFixed first;
} XrFiller;
/* xrstate.c */
@ -450,13 +446,13 @@ void
XrPenDeinit(XrPen *pen);
XrError
XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts);
XrPenAddPoints(XrPen *pen, XrPenFlaggedPoint *pt, int num_pts);
XrError
XrPenAddPointsForSlopes(XrPen *pen, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrError
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon);
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrTraps *traps);
/* xrpolygon.c */
void

View file

@ -38,7 +38,7 @@ static int
_SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b);
static XrError
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon);
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexFlag dir, XrPolygon *polygon);
static int
_XrPenVertexCompareByTheta(const void *a, const void *b);
@ -75,6 +75,9 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
pen->tolerance = gstate->tolerance;
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance, &gstate->ctm);
/* number of vertices must be even */
if (pen->num_vertices % 2)
pen->num_vertices++;
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
if (pen->vertex == NULL) {
@ -89,7 +92,7 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
XrTransformPointWithoutTranslate(&gstate->ctm, &pt);
v->pt.x = XDoubleToFixed(pt.x);
v->pt.y = XDoubleToFixed(pt.y);
v->tag = XrPenVertexTagNone;
v->flag = XrPenVertexFlagNone;
}
_XrPenComputeSlopes(pen);
@ -136,60 +139,43 @@ _XrPenVertexCompareByTheta(const void *a, const void *b)
}
XrError
XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts)
XrPenAddPoints(XrPen *pen, XrPenFlaggedPoint *pt, int num_pts)
{
int i, j;
XrPenVertex *v, *new_vertex;
XrPenVertex *vi, *pi;
v = malloc(num_pts * sizeof(XrPenVertex));
if (v == NULL)
return XrErrorNoMemory;
XrPenVertex *v, *v_next, *new_vertex;
pen->num_vertices += num_pts;
new_vertex = realloc(pen->vertex, pen->num_vertices * sizeof(XrPenVertex));
if (new_vertex == NULL) {
free(v);
pen->num_vertices -= num_pts;
return XrErrorNoMemory;
}
pen->vertex = new_vertex;
/* initialize and sort new vertices */
/* initialize new vertices */
for (i=0; i < num_pts; i++) {
v[i].pt.x = pt[i].pt.x;
v[i].pt.y = pt[i].pt.y;
v[i].tag = pt[i].tag;
v[i].theta = atan2(v[i].pt.y, v[i].pt.x);
if (v[i].theta < 0)
v[i].theta += 2 * M_PI;
v = &pen->vertex[pen->num_vertices-(i+1)];
v->pt = pt[i].pt;
v->flag = pt[i].flag;
v->theta = atan2(v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
qsort(v, num_pts, sizeof(XrPenVertex), _XrPenVertexCompareByTheta);
qsort(pen->vertex, pen->num_vertices, sizeof(XrPenVertex), _XrPenVertexCompareByTheta);
/* merge new vertices into original */
pi = pen->vertex + pen->num_vertices - num_pts - 1;
vi = v + num_pts - 1;
for (i = pen->num_vertices - 1; vi >= v; i--) {
if (pi >= pen->vertex
&& vi->pt.x == pi->pt.x && vi->pt.y == pi->pt.y) {
/* Eliminate the duplicate vertex */
for (j=i; j < pen->num_vertices - 1; j++)
/* eliminate any duplicate vertices */
for (i=0; i < pen->num_vertices - 1; i++ ) {
v = &pen->vertex[i];
v_next = &pen->vertex[i+1];
if (v->pt.x == v_next->pt.x && v->pt.y == v_next->pt.y) {
v->flag |= v_next->flag;
for (j=i+1; j < pen->num_vertices - 1; j++)
pen->vertex[j] = pen->vertex[j+1];
pen->vertex[--i] = *vi;
pen->num_vertices--;
pi--;
vi--;
} else if (pi < pen->vertex || vi->theta >= pi->theta) {
pen->vertex[i] = *vi--;
} else {
pen->vertex[i] = *pi--;
}
}
free(v);
_XrPenComputeSlopes(pen);
return XrErrorSuccess;
@ -251,7 +237,7 @@ _SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b)
}
static XrError
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon)
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexFlag dir, XrPolygon *polygon)
{
int i;
XrError err;
@ -263,13 +249,13 @@ _XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolyg
int num_pts = spline->num_pts;
for (i=0; i < pen->num_vertices; i++) {
if (pen->vertex[i].tag == dir) {
active = i;
break;
}
if (pen->vertex[i].flag & dir) {
active = i;
break;
}
}
if (dir == XrPenVertexTagForward) {
if (dir == XrPenVertexFlagForward) {
start = 0;
stop = num_pts;
step = 1;
@ -308,29 +294,35 @@ _XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolyg
return XrErrorSuccess;
}
/* Compute outline of a given spline by decomposing the spline into
line segments, then (conceptually) placing the pen at each point
and computing the convex hull formed by the vertices of all copied
pens. The hull is stored in the provided polygon. */
/* Compute outline of a given spline using the pen.
The trapezoids needed to fill that outline will be added to traps
*/
XrError
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon)
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrTraps *traps)
{
XrError err;
XrPolygon polygon;
XrPolygonInit(&polygon);
err = XrSplineDecompose(spline, tolerance);
if (err)
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagForward, polygon);
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexFlagForward, &polygon);
if (err)
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagReverse, polygon);
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexFlagReverse, &polygon);
if (err)
return err;
return err;
XrPolygonClose(&polygon);
XrTrapsTessellatePolygon(traps, &polygon, 1);
XrPolygonDeinit(&polygon);
XrPolygonClose(polygon);
return XrErrorSuccess;
return XrErrorSuccess;
}

View file

@ -474,20 +474,17 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrStroker *stroker = closure;
XrGState *gstate = stroker->gstate;
XrSpline spline;
XrPolygon polygon;
XrPen pen;
XrStrokeFace start, end;
XrPenTaggedPoint extra_points[4];
XrPenFlaggedPoint extra_points[4];
err = XrSplineInit(&spline, a, b, c, d);
if (err == XrErrorDegenerate)
return XrErrorSuccess;
XrPolygonInit(&polygon);
err = XrPenInitCopy(&pen, &gstate->pen_regular);
if (err)
goto CLEANUP_POLYGON;
goto CLEANUP_SPLINE;
_ComputeFace(a, &spline.initial_slope, gstate, &start);
_ComputeFace(d, &spline.final_slope, gstate, &end);
@ -506,16 +503,16 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
stroker->prev = end;
stroker->is_first = 0;
extra_points[0].pt = start.cw; extra_points[0].tag = XrPenVertexTagForward;
extra_points[0].pt = start.cw; extra_points[0].flag = XrPenVertexFlagForward;
extra_points[0].pt.x -= start.pt.x;
extra_points[0].pt.y -= start.pt.y;
extra_points[1].pt = start.ccw; extra_points[1].tag = XrPenVertexTagNone;
extra_points[1].pt = start.ccw; extra_points[1].flag = XrPenVertexFlagNone;
extra_points[1].pt.x -= start.pt.x;
extra_points[1].pt.y -= start.pt.y;
extra_points[2].pt = end.cw; extra_points[2].tag = XrPenVertexTagNone;
extra_points[2].pt = end.cw; extra_points[2].flag = XrPenVertexFlagNone;
extra_points[2].pt.x -= end.pt.x;
extra_points[2].pt.y -= end.pt.y;
extra_points[3].pt = end.ccw; extra_points[3].tag = XrPenVertexTagReverse;
extra_points[3].pt = end.ccw; extra_points[3].flag = XrPenVertexFlagReverse;
extra_points[3].pt.x -= end.pt.x;
extra_points[3].pt.y -= end.pt.y;
@ -523,16 +520,13 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
if (err)
goto CLEANUP_PEN;
err = XrPenStrokeSpline(&pen, &spline, gstate->tolerance, &polygon);
err = XrPenStrokeSpline(&pen, &spline, gstate->tolerance, stroker->traps);
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;
@ -567,6 +561,10 @@ XrStrokerDoneSubPath (void *closure, XrSubPathDone done)
break;
}
stroker->have_prev = 0;
stroker->have_first = 0;
stroker->is_first = 1;
return XrErrorSuccess;
}

View file

@ -277,12 +277,12 @@ XrTrapsTessellatePolygon (XrTraps *traps,
break;
/* move this edge into the active list */
inactive++;
e->next_x = _ComputeX (&e->edge, y);
e->current_x = _ComputeX (&e->edge, y);
/* insert e at sorted position */
for (en=active, ep=0; en; ep=en, en=en->next)
{
if (en->next_x > e->next_x)
if (en->current_x > e->current_x)
break;
}
e->next = en;
@ -303,9 +303,9 @@ XrTrapsTessellatePolygon (XrTraps *traps,
next_y = e->edge.p2.y;
en = e->next;
/* check intersect */
if (en)
if (en && e->current_x != en->current_x)
{
intersect = _ComputeIntersect (&e->edge, &e->next->edge);
intersect = _ComputeIntersect (&e->edge, &en->edge);
/* make sure this point is below the actual intersection */
intersect = intersect + 1;
/* is intersection within both edges and between y/next_y */
@ -320,7 +320,6 @@ XrTrapsTessellatePolygon (XrTraps *traps,
/* compute x coordinates along this group */
for (e = active; e; e = e->next) {
e->current_x = e->next_x;
e->next_x = _ComputeX (&e->edge, next_y);
}
@ -398,6 +397,9 @@ XrTrapsTessellatePolygon (XrTraps *traps,
}
y = next_y;
for (e = active; e; e = e->next) {
e->current_x = e->next_x;
}
/* delete inactive edges from list */
for (e = active; e; e = next)

View file

@ -32,8 +32,6 @@ XrFillerInit(XrFiller *filler, XrGState *gstate, XrTraps *traps)
filler->traps = traps;
XrPolygonInit(&filler->polygon);
filler->have_prev = 0;
}
void
@ -48,12 +46,6 @@ XrFillerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2)
XrFiller *filler = closure;
XrPolygon *polygon = &filler->polygon;
if (filler->have_prev == 0) {
filler->have_prev = 1;
filler->first = *p1;
}
filler->prev = *p2;
return XrPolygonAddEdge(polygon, p1, p2);
}
@ -67,12 +59,6 @@ XrFillerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *c
XrGState *gstate = filler->gstate;
XrSpline spline;
if (filler->have_prev == 0) {
filler->have_prev = 1;
filler->first = *a;
}
filler->prev = *d;
err = XrSplineInit(&spline, a, b, c, d);
if (err == XrErrorDegenerate)
return XrErrorSuccess;
@ -100,8 +86,7 @@ XrFillerDoneSubPath (void *closure, XrSubPathDone done)
XrFiller *filler = closure;
XrPolygon *polygon = &filler->polygon;
if (filler->have_prev)
err = XrPolygonAddEdge(polygon, &filler->prev, &filler->first);
XrPolygonClose(polygon);
return err;
}

26
xrint.h
View file

@ -140,20 +140,20 @@ typedef struct _XrSpline {
XPointFixed *pts;
} XrSpline;
typedef enum _XrPenVertexTag {
XrPenVertexTagNone,
XrPenVertexTagForward,
XrPenVertexTagReverse
} XrPenVertexTag;
typedef enum _XrPenVertexFlag {
XrPenVertexFlagNone = 0,
XrPenVertexFlagForward = 1,
XrPenVertexFlagReverse = 2
} XrPenVertexFlag;
typedef struct _XrPenTaggedPoint {
typedef struct _XrPenFlaggedPoint {
XPointFixed pt;
XrPenVertexTag tag;
} XrPenTaggedPoint;
XrPenVertexFlag flag;
} XrPenFlaggedPoint;
typedef struct _XrPenVertex {
XPointFixed pt;
XrPenVertexTag tag;
XrPenVertexFlag flag;
double theta;
XrSlopeFixed slope_ccw;
@ -278,10 +278,6 @@ typedef struct _XrFiller {
XrTraps *traps;
XrPolygon polygon;
int have_prev;
XPointFixed prev;
XPointFixed first;
} XrFiller;
/* xrstate.c */
@ -450,13 +446,13 @@ void
XrPenDeinit(XrPen *pen);
XrError
XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts);
XrPenAddPoints(XrPen *pen, XrPenFlaggedPoint *pt, int num_pts);
XrError
XrPenAddPointsForSlopes(XrPen *pen, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrError
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon);
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrTraps *traps);
/* xrpolygon.c */
void

104
xrpen.c
View file

@ -38,7 +38,7 @@ static int
_SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b);
static XrError
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon);
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexFlag dir, XrPolygon *polygon);
static int
_XrPenVertexCompareByTheta(const void *a, const void *b);
@ -75,6 +75,9 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
pen->tolerance = gstate->tolerance;
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance, &gstate->ctm);
/* number of vertices must be even */
if (pen->num_vertices % 2)
pen->num_vertices++;
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
if (pen->vertex == NULL) {
@ -89,7 +92,7 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
XrTransformPointWithoutTranslate(&gstate->ctm, &pt);
v->pt.x = XDoubleToFixed(pt.x);
v->pt.y = XDoubleToFixed(pt.y);
v->tag = XrPenVertexTagNone;
v->flag = XrPenVertexFlagNone;
}
_XrPenComputeSlopes(pen);
@ -136,60 +139,43 @@ _XrPenVertexCompareByTheta(const void *a, const void *b)
}
XrError
XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts)
XrPenAddPoints(XrPen *pen, XrPenFlaggedPoint *pt, int num_pts)
{
int i, j;
XrPenVertex *v, *new_vertex;
XrPenVertex *vi, *pi;
v = malloc(num_pts * sizeof(XrPenVertex));
if (v == NULL)
return XrErrorNoMemory;
XrPenVertex *v, *v_next, *new_vertex;
pen->num_vertices += num_pts;
new_vertex = realloc(pen->vertex, pen->num_vertices * sizeof(XrPenVertex));
if (new_vertex == NULL) {
free(v);
pen->num_vertices -= num_pts;
return XrErrorNoMemory;
}
pen->vertex = new_vertex;
/* initialize and sort new vertices */
/* initialize new vertices */
for (i=0; i < num_pts; i++) {
v[i].pt.x = pt[i].pt.x;
v[i].pt.y = pt[i].pt.y;
v[i].tag = pt[i].tag;
v[i].theta = atan2(v[i].pt.y, v[i].pt.x);
if (v[i].theta < 0)
v[i].theta += 2 * M_PI;
v = &pen->vertex[pen->num_vertices-(i+1)];
v->pt = pt[i].pt;
v->flag = pt[i].flag;
v->theta = atan2(v->pt.y, v->pt.x);
if (v->theta < 0)
v->theta += 2 * M_PI;
}
qsort(v, num_pts, sizeof(XrPenVertex), _XrPenVertexCompareByTheta);
qsort(pen->vertex, pen->num_vertices, sizeof(XrPenVertex), _XrPenVertexCompareByTheta);
/* merge new vertices into original */
pi = pen->vertex + pen->num_vertices - num_pts - 1;
vi = v + num_pts - 1;
for (i = pen->num_vertices - 1; vi >= v; i--) {
if (pi >= pen->vertex
&& vi->pt.x == pi->pt.x && vi->pt.y == pi->pt.y) {
/* Eliminate the duplicate vertex */
for (j=i; j < pen->num_vertices - 1; j++)
/* eliminate any duplicate vertices */
for (i=0; i < pen->num_vertices - 1; i++ ) {
v = &pen->vertex[i];
v_next = &pen->vertex[i+1];
if (v->pt.x == v_next->pt.x && v->pt.y == v_next->pt.y) {
v->flag |= v_next->flag;
for (j=i+1; j < pen->num_vertices - 1; j++)
pen->vertex[j] = pen->vertex[j+1];
pen->vertex[--i] = *vi;
pen->num_vertices--;
pi--;
vi--;
} else if (pi < pen->vertex || vi->theta >= pi->theta) {
pen->vertex[i] = *vi--;
} else {
pen->vertex[i] = *pi--;
}
}
free(v);
_XrPenComputeSlopes(pen);
return XrErrorSuccess;
@ -251,7 +237,7 @@ _SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b)
}
static XrError
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon)
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexFlag dir, XrPolygon *polygon)
{
int i;
XrError err;
@ -263,13 +249,13 @@ _XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolyg
int num_pts = spline->num_pts;
for (i=0; i < pen->num_vertices; i++) {
if (pen->vertex[i].tag == dir) {
active = i;
break;
}
if (pen->vertex[i].flag & dir) {
active = i;
break;
}
}
if (dir == XrPenVertexTagForward) {
if (dir == XrPenVertexFlagForward) {
start = 0;
stop = num_pts;
step = 1;
@ -308,29 +294,35 @@ _XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolyg
return XrErrorSuccess;
}
/* Compute outline of a given spline by decomposing the spline into
line segments, then (conceptually) placing the pen at each point
and computing the convex hull formed by the vertices of all copied
pens. The hull is stored in the provided polygon. */
/* Compute outline of a given spline using the pen.
The trapezoids needed to fill that outline will be added to traps
*/
XrError
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon)
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrTraps *traps)
{
XrError err;
XrPolygon polygon;
XrPolygonInit(&polygon);
err = XrSplineDecompose(spline, tolerance);
if (err)
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagForward, polygon);
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexFlagForward, &polygon);
if (err)
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagReverse, polygon);
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexFlagReverse, &polygon);
if (err)
return err;
return err;
XrPolygonClose(&polygon);
XrTrapsTessellatePolygon(traps, &polygon, 1);
XrPolygonDeinit(&polygon);
XrPolygonClose(polygon);
return XrErrorSuccess;
return XrErrorSuccess;
}

View file

@ -474,20 +474,17 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrStroker *stroker = closure;
XrGState *gstate = stroker->gstate;
XrSpline spline;
XrPolygon polygon;
XrPen pen;
XrStrokeFace start, end;
XrPenTaggedPoint extra_points[4];
XrPenFlaggedPoint extra_points[4];
err = XrSplineInit(&spline, a, b, c, d);
if (err == XrErrorDegenerate)
return XrErrorSuccess;
XrPolygonInit(&polygon);
err = XrPenInitCopy(&pen, &gstate->pen_regular);
if (err)
goto CLEANUP_POLYGON;
goto CLEANUP_SPLINE;
_ComputeFace(a, &spline.initial_slope, gstate, &start);
_ComputeFace(d, &spline.final_slope, gstate, &end);
@ -506,16 +503,16 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
stroker->prev = end;
stroker->is_first = 0;
extra_points[0].pt = start.cw; extra_points[0].tag = XrPenVertexTagForward;
extra_points[0].pt = start.cw; extra_points[0].flag = XrPenVertexFlagForward;
extra_points[0].pt.x -= start.pt.x;
extra_points[0].pt.y -= start.pt.y;
extra_points[1].pt = start.ccw; extra_points[1].tag = XrPenVertexTagNone;
extra_points[1].pt = start.ccw; extra_points[1].flag = XrPenVertexFlagNone;
extra_points[1].pt.x -= start.pt.x;
extra_points[1].pt.y -= start.pt.y;
extra_points[2].pt = end.cw; extra_points[2].tag = XrPenVertexTagNone;
extra_points[2].pt = end.cw; extra_points[2].flag = XrPenVertexFlagNone;
extra_points[2].pt.x -= end.pt.x;
extra_points[2].pt.y -= end.pt.y;
extra_points[3].pt = end.ccw; extra_points[3].tag = XrPenVertexTagReverse;
extra_points[3].pt = end.ccw; extra_points[3].flag = XrPenVertexFlagReverse;
extra_points[3].pt.x -= end.pt.x;
extra_points[3].pt.y -= end.pt.y;
@ -523,16 +520,13 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
if (err)
goto CLEANUP_PEN;
err = XrPenStrokeSpline(&pen, &spline, gstate->tolerance, &polygon);
err = XrPenStrokeSpline(&pen, &spline, gstate->tolerance, stroker->traps);
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;
@ -567,6 +561,10 @@ XrStrokerDoneSubPath (void *closure, XrSubPathDone done)
break;
}
stroker->have_prev = 0;
stroker->have_first = 0;
stroker->is_first = 1;
return XrErrorSuccess;
}

View file

@ -277,12 +277,12 @@ XrTrapsTessellatePolygon (XrTraps *traps,
break;
/* move this edge into the active list */
inactive++;
e->next_x = _ComputeX (&e->edge, y);
e->current_x = _ComputeX (&e->edge, y);
/* insert e at sorted position */
for (en=active, ep=0; en; ep=en, en=en->next)
{
if (en->next_x > e->next_x)
if (en->current_x > e->current_x)
break;
}
e->next = en;
@ -303,9 +303,9 @@ XrTrapsTessellatePolygon (XrTraps *traps,
next_y = e->edge.p2.y;
en = e->next;
/* check intersect */
if (en)
if (en && e->current_x != en->current_x)
{
intersect = _ComputeIntersect (&e->edge, &e->next->edge);
intersect = _ComputeIntersect (&e->edge, &en->edge);
/* make sure this point is below the actual intersection */
intersect = intersect + 1;
/* is intersection within both edges and between y/next_y */
@ -320,7 +320,6 @@ XrTrapsTessellatePolygon (XrTraps *traps,
/* compute x coordinates along this group */
for (e = active; e; e = e->next) {
e->current_x = e->next_x;
e->next_x = _ComputeX (&e->edge, next_y);
}
@ -398,6 +397,9 @@ XrTrapsTessellatePolygon (XrTraps *traps,
}
y = next_y;
for (e = active; e; e = e->next) {
e->current_x = e->next_x;
}
/* delete inactive edges from list */
for (e = active; e; e = next)