From 1507f1c795478c9cde970d1a750d0602407f6986 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 28 Jan 2003 07:23:54 +0000 Subject: [PATCH] Added triangle tessellation. Converted bevel joins from polygons to triangles. --- ChangeLog | 8 ++++++++ src/xrint.h | 3 +++ src/xrstroker.c | 26 +++++++++++++++++--------- src/xrtraps.c | 31 +++++++++++++++++++++++++++++++ xrint.h | 3 +++ xrstroker.c | 26 +++++++++++++++++--------- xrtraps.c | 31 +++++++++++++++++++++++++++++++ 7 files changed, 110 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05bae7a56..f18100809 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-01-28 Carl Worth + + * xrtraps.c (_XrTrapsTessellateTriangle): Restored triangle + tessellation functionality, (I think it's correct this time). + + * xrstroker.c (_XrStrokerJoin): Bevel joins now use triangle + tessellation rather than polygon tessellation. + 2003-01-24 Carl Worth * xrpolygon.c (_XrPolygonAddEdge): Fixed to handle multiple diff --git a/src/xrint.h b/src/xrint.h index c8835ce81..4e63d5ae6 100644 --- a/src/xrint.h +++ b/src/xrint.h @@ -773,6 +773,9 @@ _XrTrapsInit(XrTraps *traps); void _XrTrapsDeinit(XrTraps *traps); +XrStatus +_XrTrapsTessellateTriangle (XrTraps *traps, XPointFixed t[3]); + XrStatus _XrTrapsTessellateRectangle (XrTraps *traps, XPointFixed q[4]); diff --git a/src/xrstroker.c b/src/xrstroker.c index c8a43d9f4..5a47df749 100644 --- a/src/xrstroker.c +++ b/src/xrstroker.c @@ -113,7 +113,6 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) XrStatus status; XrGState *gstate = stroker->gstate; int clockwise = _XrStrokerFaceClockwise (in, out); - XrPolygon polygon; XPointFixed *inpt, *outpt; /* XXX: There might be a more natural place to check for the @@ -133,13 +132,18 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) inpt = &in->ccw; outpt = &out->ccw; } - _XrPolygonInit (&polygon); + switch (gstate->line_join) { case XrLineJoinRound: + status = XrStatusSuccess; break; case XrLineJoinMiter: { + XrPolygon polygon; XDouble c = (-in->vector.x * out->vector.x)+(-in->vector.y * out->vector.y); XDouble ml = gstate->miter_limit; + + _XrPolygonInit (&polygon); + if (2 <= ml * ml * (1 - c)) { XDouble x1, y1, x2, y2; XDouble mx, my; @@ -171,19 +175,23 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) _XrPolygonAddEdge (&polygon, inpt, &outer); _XrPolygonAddEdge (&polygon, &outer, outpt); _XrPolygonAddEdge (&polygon, outpt, &in->pt); + status = _XrTrapsTessellatePolygon (stroker->traps, + &polygon, + XrFillRuleWinding); + _XrPolygonDeinit (&polygon); break; } /* fall through ... */ } - case XrLineJoinBevel: - _XrPolygonAddEdge (&polygon, &in->pt, inpt); - _XrPolygonAddEdge (&polygon, inpt, outpt); - _XrPolygonAddEdge (&polygon, outpt, &in->pt); + case XrLineJoinBevel: { + XPointFixed tri[3]; + tri[0] = in->pt; + tri[1] = *inpt; + tri[2] = *outpt; + status = _XrTrapsTessellateTriangle (stroker->traps, tri); break; } - - status = _XrTrapsTessellatePolygon (stroker->traps, &polygon, XrFillRuleWinding); - _XrPolygonDeinit (&polygon); + } return status; } diff --git a/src/xrtraps.c b/src/xrtraps.c index 36043e784..a43555330 100644 --- a/src/xrtraps.c +++ b/src/xrtraps.c @@ -161,6 +161,37 @@ _ComparePointFixedByY (const void *av, const void *bv) return ret; } +XrStatus +_XrTrapsTessellateTriangle (XrTraps *traps, XPointFixed t[3]) +{ + XLineFixed line; + double intersect; + + qsort(t, 3, sizeof(XPointFixed), _ComparePointFixedByY); + + /* horizontal top edge requires special handling */ + if (t[0].y == t[1].y) { + if (t[0].x < t[1].x) + _XrTrapsAddTrapFromPoints (traps, t[1].y, t[2].y, t[0], t[2], t[1], t[2]); + else + _XrTrapsAddTrapFromPoints (traps, t[1].y, t[2].y, t[1], t[2], t[0], t[2]); + return; + } + + line.p1 = t[0]; + line.p2 = t[1]; + + intersect = _ComputeX (&line, t[2].y); + + if (intersect < t[2].x) { + _XrTrapsAddTrapFromPoints(traps, t[0].y, t[1].y, t[0], t[1], t[0], t[2]); + _XrTrapsAddTrapFromPoints(traps, t[1].y, t[2].y, t[1], t[2], t[0], t[2]); + } else { + _XrTrapsAddTrapFromPoints(traps, t[0].y, t[1].y, t[0], t[2], t[0], t[1]); + _XrTrapsAddTrapFromPoints(traps, t[1].y, t[2].y, t[0], t[2], t[1], t[2]); + } +} + XrStatus _XrTrapsTessellateRectangle (XrTraps *traps, XPointFixed q[4]) { diff --git a/xrint.h b/xrint.h index c8835ce81..4e63d5ae6 100644 --- a/xrint.h +++ b/xrint.h @@ -773,6 +773,9 @@ _XrTrapsInit(XrTraps *traps); void _XrTrapsDeinit(XrTraps *traps); +XrStatus +_XrTrapsTessellateTriangle (XrTraps *traps, XPointFixed t[3]); + XrStatus _XrTrapsTessellateRectangle (XrTraps *traps, XPointFixed q[4]); diff --git a/xrstroker.c b/xrstroker.c index c8a43d9f4..5a47df749 100644 --- a/xrstroker.c +++ b/xrstroker.c @@ -113,7 +113,6 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) XrStatus status; XrGState *gstate = stroker->gstate; int clockwise = _XrStrokerFaceClockwise (in, out); - XrPolygon polygon; XPointFixed *inpt, *outpt; /* XXX: There might be a more natural place to check for the @@ -133,13 +132,18 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) inpt = &in->ccw; outpt = &out->ccw; } - _XrPolygonInit (&polygon); + switch (gstate->line_join) { case XrLineJoinRound: + status = XrStatusSuccess; break; case XrLineJoinMiter: { + XrPolygon polygon; XDouble c = (-in->vector.x * out->vector.x)+(-in->vector.y * out->vector.y); XDouble ml = gstate->miter_limit; + + _XrPolygonInit (&polygon); + if (2 <= ml * ml * (1 - c)) { XDouble x1, y1, x2, y2; XDouble mx, my; @@ -171,19 +175,23 @@ _XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) _XrPolygonAddEdge (&polygon, inpt, &outer); _XrPolygonAddEdge (&polygon, &outer, outpt); _XrPolygonAddEdge (&polygon, outpt, &in->pt); + status = _XrTrapsTessellatePolygon (stroker->traps, + &polygon, + XrFillRuleWinding); + _XrPolygonDeinit (&polygon); break; } /* fall through ... */ } - case XrLineJoinBevel: - _XrPolygonAddEdge (&polygon, &in->pt, inpt); - _XrPolygonAddEdge (&polygon, inpt, outpt); - _XrPolygonAddEdge (&polygon, outpt, &in->pt); + case XrLineJoinBevel: { + XPointFixed tri[3]; + tri[0] = in->pt; + tri[1] = *inpt; + tri[2] = *outpt; + status = _XrTrapsTessellateTriangle (stroker->traps, tri); break; } - - status = _XrTrapsTessellatePolygon (stroker->traps, &polygon, XrFillRuleWinding); - _XrPolygonDeinit (&polygon); + } return status; } diff --git a/xrtraps.c b/xrtraps.c index 36043e784..a43555330 100644 --- a/xrtraps.c +++ b/xrtraps.c @@ -161,6 +161,37 @@ _ComparePointFixedByY (const void *av, const void *bv) return ret; } +XrStatus +_XrTrapsTessellateTriangle (XrTraps *traps, XPointFixed t[3]) +{ + XLineFixed line; + double intersect; + + qsort(t, 3, sizeof(XPointFixed), _ComparePointFixedByY); + + /* horizontal top edge requires special handling */ + if (t[0].y == t[1].y) { + if (t[0].x < t[1].x) + _XrTrapsAddTrapFromPoints (traps, t[1].y, t[2].y, t[0], t[2], t[1], t[2]); + else + _XrTrapsAddTrapFromPoints (traps, t[1].y, t[2].y, t[1], t[2], t[0], t[2]); + return; + } + + line.p1 = t[0]; + line.p2 = t[1]; + + intersect = _ComputeX (&line, t[2].y); + + if (intersect < t[2].x) { + _XrTrapsAddTrapFromPoints(traps, t[0].y, t[1].y, t[0], t[1], t[0], t[2]); + _XrTrapsAddTrapFromPoints(traps, t[1].y, t[2].y, t[1], t[2], t[0], t[2]); + } else { + _XrTrapsAddTrapFromPoints(traps, t[0].y, t[1].y, t[0], t[2], t[0], t[1]); + _XrTrapsAddTrapFromPoints(traps, t[1].y, t[2].y, t[0], t[2], t[1], t[2]); + } +} + XrStatus _XrTrapsTessellateRectangle (XrTraps *traps, XPointFixed q[4]) {