mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 02:58:02 +02:00
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:
parent
2ba3786b27
commit
1fa0a496bb
12 changed files with 158 additions and 216 deletions
2
Xr.h
2
Xr.h
|
|
@ -43,8 +43,6 @@ XrSave(XrState *xrs);
|
|||
void
|
||||
XrRestore(XrState *xrs);
|
||||
|
||||
/* XXX: NYI: XrClone */
|
||||
|
||||
/* Modify state */
|
||||
void
|
||||
XrSetDrawable(XrState *xrs, Drawable drawable);
|
||||
|
|
|
|||
2
src/Xr.h
2
src/Xr.h
|
|
@ -43,8 +43,6 @@ XrSave(XrState *xrs);
|
|||
void
|
||||
XrRestore(XrState *xrs);
|
||||
|
||||
/* XXX: NYI: XrClone */
|
||||
|
||||
/* Modify state */
|
||||
void
|
||||
XrSetDrawable(XrState *xrs, Drawable drawable);
|
||||
|
|
|
|||
|
|
@ -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
src/xrint.h
26
src/xrint.h
|
|
@ -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
src/xrpen.c
104
src/xrpen.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
17
xrfiller.c
17
xrfiller.c
|
|
@ -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
26
xrint.h
|
|
@ -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
104
xrpen.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
26
xrstroker.c
26
xrstroker.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
12
xrtraps.c
12
xrtraps.c
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue