diff --git a/src/xrgstate.c b/src/xrgstate.c index 0383d09d0..e6a6f15e0 100644 --- a/src/xrgstate.c +++ b/src/xrgstate.c @@ -261,7 +261,7 @@ XrGStateClosePath(XrGState *gstate) void XrGStateStroke(XrGState *gstate) { - static XrPathCallbacks cb = { XrStrokerAddEdge }; + static XrPathCallbacks cb = { XrStrokerAddEdge, XrStrokerDoneSubPath }; XrStroker stroker; XrTraps traps; @@ -287,7 +287,7 @@ XrGStateStroke(XrGState *gstate) void XrGStateFill(XrGState *gstate) { - static XrPathCallbacks cb = { XrPolygonAddEdge }; + static XrPathCallbacks cb = { XrPolygonAddEdge, XrPolygonDoneSubPath }; XrPolygon polygon; XrTraps traps; diff --git a/src/xrint.h b/src/xrint.h index 1332e2997..37d18b748 100644 --- a/src/xrint.h +++ b/src/xrint.h @@ -359,6 +359,9 @@ XrPolygonDeinit(XrPolygon *poly); void XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); +void +XrPolygonDoneSubPath (void *closure, XrSubPathDone done); + /* xrstroke.c */ void XrStrokerInit(XrStroker *stroker, XrGState *gstate, XrTraps *traps); diff --git a/src/xrpath.c b/src/xrpath.c index 985e13225..1125625b1 100644 --- a/src/xrpath.c +++ b/src/xrpath.c @@ -257,11 +257,6 @@ _TranslatePointFixed(XPointFixed *pt, XPointFixed *offset) pt->y += offset->y; } -void -XrPolygonDoneSubPath (void *closure, XrSubPathDone done) -{ -} - #define START_ARGS(n) \ { \ if (dir != XrPathDirectionForward) \ diff --git a/src/xrpolygon.c b/src/xrpolygon.c index f895cd720..6b20992a5 100644 --- a/src/xrpolygon.c +++ b/src/xrpolygon.c @@ -102,3 +102,9 @@ XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) poly->num_edges++; } + +void +XrPolygonDoneSubPath (void *closure, XrSubPathDone done) +{ +} + diff --git a/src/xrstroker.c b/src/xrstroker.c index 3120694ec..a9dc59b22 100644 --- a/src/xrstroker.c +++ b/src/xrstroker.c @@ -50,10 +50,50 @@ _TranslatePoint(XPointFixed *pt, XPointFixed *offset) pt->y += offset->y; } -void -XrStrokerJoin(XrStroker *stroker, XrStrokeFace *f1, XrStrokeFace *f2) +static int +XrStrokerFaceClockwise(XrStrokeFace *in, XrStrokeFace *out) { - XrGState *gstate = stroker->gstate; + XPointFixed d_in, d_out; + + d_in.x = in->cw.x - in->pt.x; + d_in.y = in->cw.y - in->pt.y; + d_out.x = out->cw.x - in->pt.x; + d_out.y = out->cw.y - in->pt.y; + + return d_out.y * d_in.x > d_in.y * d_out.x; +} + +void +XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) +{ + XrGState *gstate = stroker->gstate; + int clockwise = XrStrokerFaceClockwise (in, out); + + switch (gstate->stroke_style.line_join) { + case XrLineJoinRound: { + } + case XrLineJoinMiter: { + } + case XrLineJoinBevel: { + XPointFixed t[3]; + + t[0].x = in->pt.x; + t[0].y = in->pt.y; + if (clockwise) { + t[1].x = in->cw.x; + t[1].y = in->cw.y; + t[2].x = out->cw.x; + t[2].y = out->cw.y; + } else { + t[1].x = in->ccw.x; + t[1].y = in->ccw.y; + t[2].x = out->ccw.x; + t[2].y = out->ccw.y; + } + XrTrapsTessellateTriangle (stroker->traps, t); + break; + } + } } void @@ -105,21 +145,25 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) _TranslatePoint(&quad[1], &offset_ccw); quad[2] = *p2; - _TranslatePoint(&quad[1], &offset_ccw); + _TranslatePoint(&quad[2], &offset_ccw); quad[3] = *p2; - _TranslatePoint(&quad[2], &offset_cw); + _TranslatePoint(&quad[3], &offset_cw); - face.ccw = quad[2]; - face.pt = *p2; - face.cw = quad[3]; + face.cw = quad[0]; + face.pt = *p1; + face.ccw = quad[1]; if (stroker->have_prev) XrStrokerJoin (stroker, &stroker->prev, &face); - else + else { + stroker->have_prev = 1; stroker->first = face; - stroker->prev = face; - stroker->have_prev = 1; + } + + stroker->prev.ccw = quad[2]; + stroker->prev.pt = *p2; + stroker->prev.cw = quad[3]; XrTrapsTessellateConvexQuad(traps, quad); } diff --git a/xrgstate.c b/xrgstate.c index 0383d09d0..e6a6f15e0 100644 --- a/xrgstate.c +++ b/xrgstate.c @@ -261,7 +261,7 @@ XrGStateClosePath(XrGState *gstate) void XrGStateStroke(XrGState *gstate) { - static XrPathCallbacks cb = { XrStrokerAddEdge }; + static XrPathCallbacks cb = { XrStrokerAddEdge, XrStrokerDoneSubPath }; XrStroker stroker; XrTraps traps; @@ -287,7 +287,7 @@ XrGStateStroke(XrGState *gstate) void XrGStateFill(XrGState *gstate) { - static XrPathCallbacks cb = { XrPolygonAddEdge }; + static XrPathCallbacks cb = { XrPolygonAddEdge, XrPolygonDoneSubPath }; XrPolygon polygon; XrTraps traps; diff --git a/xrint.h b/xrint.h index 1332e2997..37d18b748 100644 --- a/xrint.h +++ b/xrint.h @@ -359,6 +359,9 @@ XrPolygonDeinit(XrPolygon *poly); void XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2); +void +XrPolygonDoneSubPath (void *closure, XrSubPathDone done); + /* xrstroke.c */ void XrStrokerInit(XrStroker *stroker, XrGState *gstate, XrTraps *traps); diff --git a/xrpath.c b/xrpath.c index 985e13225..1125625b1 100644 --- a/xrpath.c +++ b/xrpath.c @@ -257,11 +257,6 @@ _TranslatePointFixed(XPointFixed *pt, XPointFixed *offset) pt->y += offset->y; } -void -XrPolygonDoneSubPath (void *closure, XrSubPathDone done) -{ -} - #define START_ARGS(n) \ { \ if (dir != XrPathDirectionForward) \ diff --git a/xrpolygon.c b/xrpolygon.c index f895cd720..6b20992a5 100644 --- a/xrpolygon.c +++ b/xrpolygon.c @@ -102,3 +102,9 @@ XrPolygonAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) poly->num_edges++; } + +void +XrPolygonDoneSubPath (void *closure, XrSubPathDone done) +{ +} + diff --git a/xrstroker.c b/xrstroker.c index 3120694ec..a9dc59b22 100644 --- a/xrstroker.c +++ b/xrstroker.c @@ -50,10 +50,50 @@ _TranslatePoint(XPointFixed *pt, XPointFixed *offset) pt->y += offset->y; } -void -XrStrokerJoin(XrStroker *stroker, XrStrokeFace *f1, XrStrokeFace *f2) +static int +XrStrokerFaceClockwise(XrStrokeFace *in, XrStrokeFace *out) { - XrGState *gstate = stroker->gstate; + XPointFixed d_in, d_out; + + d_in.x = in->cw.x - in->pt.x; + d_in.y = in->cw.y - in->pt.y; + d_out.x = out->cw.x - in->pt.x; + d_out.y = out->cw.y - in->pt.y; + + return d_out.y * d_in.x > d_in.y * d_out.x; +} + +void +XrStrokerJoin(XrStroker *stroker, XrStrokeFace *in, XrStrokeFace *out) +{ + XrGState *gstate = stroker->gstate; + int clockwise = XrStrokerFaceClockwise (in, out); + + switch (gstate->stroke_style.line_join) { + case XrLineJoinRound: { + } + case XrLineJoinMiter: { + } + case XrLineJoinBevel: { + XPointFixed t[3]; + + t[0].x = in->pt.x; + t[0].y = in->pt.y; + if (clockwise) { + t[1].x = in->cw.x; + t[1].y = in->cw.y; + t[2].x = out->cw.x; + t[2].y = out->cw.y; + } else { + t[1].x = in->ccw.x; + t[1].y = in->ccw.y; + t[2].x = out->ccw.x; + t[2].y = out->ccw.y; + } + XrTrapsTessellateTriangle (stroker->traps, t); + break; + } + } } void @@ -105,21 +145,25 @@ XrStrokerAddEdge(void *closure, XPointFixed *p1, XPointFixed *p2) _TranslatePoint(&quad[1], &offset_ccw); quad[2] = *p2; - _TranslatePoint(&quad[1], &offset_ccw); + _TranslatePoint(&quad[2], &offset_ccw); quad[3] = *p2; - _TranslatePoint(&quad[2], &offset_cw); + _TranslatePoint(&quad[3], &offset_cw); - face.ccw = quad[2]; - face.pt = *p2; - face.cw = quad[3]; + face.cw = quad[0]; + face.pt = *p1; + face.ccw = quad[1]; if (stroker->have_prev) XrStrokerJoin (stroker, &stroker->prev, &face); - else + else { + stroker->have_prev = 1; stroker->first = face; - stroker->prev = face; - stroker->have_prev = 1; + } + + stroker->prev.ccw = quad[2]; + stroker->prev.pt = *p2; + stroker->prev.cw = quad[3]; XrTrapsTessellateConvexQuad(traps, quad); }