Fix polygon stroking so last final face is rendered exactly. Fix bug in which XrPolygonAddPt with horizontal edge would then drop the next edge.

This commit is contained in:
Carl Worth 2002-09-05 13:12:23 +00:00
parent bc362fc2e4
commit 44ca388c90
8 changed files with 66 additions and 54 deletions

View file

@ -452,7 +452,7 @@ XrError
XrPenAddPointsForSlopes(XrPen *pen, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrError
XrPenStrokePoints(XrPen *pen, XPointFixed *pt, int num_pts, XrPolygon *polygon);
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon);
/* xrpolygon.c */
void

View file

@ -41,7 +41,7 @@ static int
_SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b);
static XrError
_XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrPolygon *polygon);
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon);
static int
_XrPenVertexCompareByTheta(const void *a, const void *b);
@ -261,14 +261,16 @@ _SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b)
}
static XrError
_XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrPolygon *polygon)
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon)
{
int i;
XrError err;
int start, stop, step;
int active = 0;
XPointFixed hull_pt;
XrSlopeFixed exit_slope;
XrSlopeFixed slope, final_slope;
XPointFixed *pt = spline->pts;
int num_pts = spline->num_pts;
for (i=0; i < pen->num_vertices; i++) {
if (pen->vertex[i].tag == dir) {
@ -279,12 +281,14 @@ _XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrP
if (dir == XrPenVertexTagForward) {
start = 0;
stop = num_pts - 1;
stop = num_pts;
step = 1;
_FindSlope(&spline->c, &spline->d, &final_slope);
} else {
start = num_pts - 1;
stop = 0;
stop = -1;
step = -1;
_FindSlope(&spline->b, &spline->a, &final_slope);
}
i = start;
@ -295,37 +299,42 @@ _XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrP
if (err)
return err;
_FindSlope(&pt[i], &pt[i+step], &exit_slope);
if (_SlopeCounterClockwise(&exit_slope, &pen->vertex[active].slope_ccw)) {
active = active + 1;
if (active == pen->num_vertices)
if (i + step == stop)
slope = final_slope;
else
_FindSlope(&pt[i], &pt[i+step], &slope);
if (_SlopeCounterClockwise(&slope, &pen->vertex[active].slope_ccw)) {
if (++active == pen->num_vertices)
active = 0;
} else if (_SlopeClockwise(&exit_slope, &pen->vertex[active].slope_cw)) {
active = active - 1;
if (active == -1)
} else if (_SlopeClockwise(&slope, &pen->vertex[active].slope_cw)) {
if (--active == -1)
active = pen->num_vertices - 1;
} else {
i += step;
}
}
hull_pt.x = pt[i].x + pen->vertex[active].pt.x;
hull_pt.y = pt[i].y + pen->vertex[active].pt.y;
return XrPolygonAddPoint(polygon, &hull_pt);
return XrErrorSuccess;
}
/* Compute convex hull formed by placing a copy of the pen at each of
the given points. The hull is stored in the provided polygon. */
/* 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. */
XrError
XrPenStrokePoints(XrPen *pen, XPointFixed *pt, int num_pts, XrPolygon *polygon)
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon)
{
XrError err;
err = _XrPenFindHull(pen, pt, num_pts, XrPenVertexTagForward, polygon);
err = XrSplineDecompose(spline, tolerance);
if (err)
return err;
err = _XrPenFindHull(pen, pt, num_pts, XrPenVertexTagReverse, polygon);
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagForward, polygon);
if (err)
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagReverse, polygon);
if (err)
return err;

View file

@ -110,7 +110,7 @@ XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2)
/* drop horizontal edges */
if (p1->y == p2->y) {
return XrErrorSuccess;
goto DONE;
}
if (polygon->num_edges >= polygon->edges_size) {
@ -133,6 +133,7 @@ XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2)
polygon->num_edges++;
DONE:
_XrPolygonSetLastPoint(polygon, p2);
return XrErrorSuccess;

View file

@ -500,9 +500,6 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrPenTaggedPoint extra_points[4];
XrSplineInit(&spline, a, b, c, d);
err = XrSplineDecompose(&spline, gstate->tolerance);
if (err)
goto CLEANUP_SPLINE;
XrPolygonInit(&polygon);
@ -544,7 +541,7 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
if (err)
goto CLEANUP_PEN;
err = XrPenStrokePoints(&pen, spline.pts, spline.num_pts, &polygon);
err = XrPenStrokeSpline(&pen, &spline, gstate->tolerance, &polygon);
if (err)
goto CLEANUP_PEN;
@ -554,7 +551,6 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrPenDeinit(&pen);
CLEANUP_POLYGON:
XrPolygonDeinit(&polygon);
CLEANUP_SPLINE:
XrSplineDeinit(&spline);
return err;

View file

@ -452,7 +452,7 @@ XrError
XrPenAddPointsForSlopes(XrPen *pen, XPointFixed *a, XPointFixed *b, XPointFixed *c, XPointFixed *d);
XrError
XrPenStrokePoints(XrPen *pen, XPointFixed *pt, int num_pts, XrPolygon *polygon);
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon);
/* xrpolygon.c */
void

49
xrpen.c
View file

@ -41,7 +41,7 @@ static int
_SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b);
static XrError
_XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrPolygon *polygon);
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon);
static int
_XrPenVertexCompareByTheta(const void *a, const void *b);
@ -261,14 +261,16 @@ _SlopeCounterClockwise(XrSlopeFixed *a, XrSlopeFixed *b)
}
static XrError
_XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrPolygon *polygon)
_XrPenStrokeSplineHalf(XrPen *pen, XrSpline *spline, XrPenVertexTag dir, XrPolygon *polygon)
{
int i;
XrError err;
int start, stop, step;
int active = 0;
XPointFixed hull_pt;
XrSlopeFixed exit_slope;
XrSlopeFixed slope, final_slope;
XPointFixed *pt = spline->pts;
int num_pts = spline->num_pts;
for (i=0; i < pen->num_vertices; i++) {
if (pen->vertex[i].tag == dir) {
@ -279,12 +281,14 @@ _XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrP
if (dir == XrPenVertexTagForward) {
start = 0;
stop = num_pts - 1;
stop = num_pts;
step = 1;
_FindSlope(&spline->c, &spline->d, &final_slope);
} else {
start = num_pts - 1;
stop = 0;
stop = -1;
step = -1;
_FindSlope(&spline->b, &spline->a, &final_slope);
}
i = start;
@ -295,37 +299,42 @@ _XrPenFindHull(XrPen *pen, XPointFixed *pt, int num_pts, XrPenVertexTag dir, XrP
if (err)
return err;
_FindSlope(&pt[i], &pt[i+step], &exit_slope);
if (_SlopeCounterClockwise(&exit_slope, &pen->vertex[active].slope_ccw)) {
active = active + 1;
if (active == pen->num_vertices)
if (i + step == stop)
slope = final_slope;
else
_FindSlope(&pt[i], &pt[i+step], &slope);
if (_SlopeCounterClockwise(&slope, &pen->vertex[active].slope_ccw)) {
if (++active == pen->num_vertices)
active = 0;
} else if (_SlopeClockwise(&exit_slope, &pen->vertex[active].slope_cw)) {
active = active - 1;
if (active == -1)
} else if (_SlopeClockwise(&slope, &pen->vertex[active].slope_cw)) {
if (--active == -1)
active = pen->num_vertices - 1;
} else {
i += step;
}
}
hull_pt.x = pt[i].x + pen->vertex[active].pt.x;
hull_pt.y = pt[i].y + pen->vertex[active].pt.y;
return XrPolygonAddPoint(polygon, &hull_pt);
return XrErrorSuccess;
}
/* Compute convex hull formed by placing a copy of the pen at each of
the given points. The hull is stored in the provided polygon. */
/* 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. */
XrError
XrPenStrokePoints(XrPen *pen, XPointFixed *pt, int num_pts, XrPolygon *polygon)
XrPenStrokeSpline(XrPen *pen, XrSpline *spline, double tolerance, XrPolygon *polygon)
{
XrError err;
err = _XrPenFindHull(pen, pt, num_pts, XrPenVertexTagForward, polygon);
err = XrSplineDecompose(spline, tolerance);
if (err)
return err;
err = _XrPenFindHull(pen, pt, num_pts, XrPenVertexTagReverse, polygon);
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagForward, polygon);
if (err)
return err;
err = _XrPenStrokeSplineHalf(pen, spline, XrPenVertexTagReverse, polygon);
if (err)
return err;

View file

@ -110,7 +110,7 @@ XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2)
/* drop horizontal edges */
if (p1->y == p2->y) {
return XrErrorSuccess;
goto DONE;
}
if (polygon->num_edges >= polygon->edges_size) {
@ -133,6 +133,7 @@ XrPolygonAddEdge(XrPolygon *polygon, XPointFixed *p1, XPointFixed *p2)
polygon->num_edges++;
DONE:
_XrPolygonSetLastPoint(polygon, p2);
return XrErrorSuccess;

View file

@ -500,9 +500,6 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrPenTaggedPoint extra_points[4];
XrSplineInit(&spline, a, b, c, d);
err = XrSplineDecompose(&spline, gstate->tolerance);
if (err)
goto CLEANUP_SPLINE;
XrPolygonInit(&polygon);
@ -544,7 +541,7 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
if (err)
goto CLEANUP_PEN;
err = XrPenStrokePoints(&pen, spline.pts, spline.num_pts, &polygon);
err = XrPenStrokeSpline(&pen, &spline, gstate->tolerance, &polygon);
if (err)
goto CLEANUP_PEN;
@ -554,7 +551,6 @@ XrStrokerAddSpline (void *closure, XPointFixed *a, XPointFixed *b, XPointFixed *
XrPenDeinit(&pen);
CLEANUP_POLYGON:
XrPolygonDeinit(&polygon);
CLEANUP_SPLINE:
XrSplineDeinit(&spline);
return err;