mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-09 07:18:04 +02:00
Added triangle tessellation. Converted bevel joins from polygons to triangles.
This commit is contained in:
parent
f93c88efbf
commit
1507f1c795
7 changed files with 110 additions and 18 deletions
|
|
@ -1,3 +1,11 @@
|
|||
2003-01-28 Carl Worth <cworth@east.isi.edu>
|
||||
|
||||
* 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 <cworth@east.isi.edu>
|
||||
|
||||
* xrpolygon.c (_XrPolygonAddEdge): Fixed to handle multiple
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
{
|
||||
|
|
|
|||
3
xrint.h
3
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]);
|
||||
|
||||
|
|
|
|||
26
xrstroker.c
26
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;
|
||||
}
|
||||
|
|
|
|||
31
xrtraps.c
31
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])
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue