On Jun 11, Carl Worth wrote:
> For that reason, I was just about to code up
> XRenderCompositeDoublePolys. But I think I'll go to bed instead. I'll
> probably get to it early tomorrow morning.
OK,
Here's a patch that implements XRenderCompositeDoublePolys. It
implements the behavior I described earlier. That is, it actually
renders a single shape described by multiple (possibly intersecting)
polygons according to the even-odd or non-zero winding rule.
This really isn't the same function that Jorge requested, since
calling my XRenderCompositeDoublePolys will give different results
than XRenderCompositeDoublePoly multiple times if the polygons
intersect.
Any votes for better naming here to clear things up?
There might still be room for a function to render multiple separate
polygons like Jorge wanted. Then again, that might get messy since the
results would depend on the order in which order the polygons were
rendered.
-Carl
PS. This patch has one infelicity: it discards a const qualifier. I
didn't see a simple way to prevent this without changing the prototype
for XRenderCompositeDoublePoly or introducing a needless copy.
--
Carl Worth
USC Information Sciences Institute [EMAIL PROTECTED]
Index: Poly.c
===================================================================
RCS file: /mirrors/xfree86/xc/lib/Xrender/Poly.c,v
retrieving revision 1.7
diff -u -r1.7 Poly.c
--- Poly.c 4 Jun 2002 23:22:36 -0000 1.7
+++ Poly.c 6 Jun 2002 14:24:22 -0000
@@ -93,6 +93,7 @@
Edge *active;
Edge *e, *en, *next;
XFixed y, next_y, intersect;
+ int in_out;
qsort (edges, nedges, sizeof (Edge), CompareEdge);
@@ -180,7 +181,7 @@
intersect = XRenderComputeIntersect (&e->edge, &e->next->edge);
/* make sure this point is below the actual intersection */
intersect = intersect + 1;
- if (intersect < next_y)
+ if (intersect < next_y && intersect > y)
next_y = intersect;
}
}
@@ -189,8 +190,24 @@
next_y = edges[inactive].edge.p1.y;
/* walk the list generating trapezoids */
- for (e = active; e && (en = e->next); e = en->next)
+ in_out = 0;
+ for (e = active; e && (en = e->next); e = e->next)
{
+ if (winding) {
+ if (e->clockWise) {
+ in_out++;
+ } else {
+ in_out--;
+ }
+ if (in_out == 0) {
+ continue;
+ }
+ } else {
+ in_out++;
+ if (in_out % 2 == 0) {
+ continue;
+ }
+ }
traps->top = y;
traps->bottom = next_y;
traps->left = e->edge;
@@ -233,65 +250,97 @@
int npoints,
int winding)
{
+ XPolygonDouble poly;
+
+ poly.points = fpoints;
+ poly.npoints = npoints;
+
+ XRenderCompositeDoublePolys(dpy, op, src, dst, maskFormat,
+ xSrc, ySrc, xDst, yDst,
+ &poly, 1, winding);
+}
+
+void
+XRenderCompositeDoublePolys (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst XPolygonDouble *polys,
+ int npolys,
+ int winding)
+{
Edge *edges;
XTrapezoid *traps;
- int i, nedges, ntraps;
+ int p, i, nedges, ntraps, npoints_total;
XFixed x, y, prevx = 0, prevy = 0, firstx = 0, firsty = 0;
XFixed top = 0, bottom = 0; /* GCCism */
- edges = (Edge *) Xmalloc (npoints * sizeof (Edge) +
- (npoints * npoints * sizeof (XTrapezoid)));
+ npoints_total = 0;
+ for (p = 0; p < npolys; p++) {
+ npoints_total += polys[p].npoints;
+ }
+
+ edges = (Edge *) Xmalloc (npoints_total * sizeof (Edge) +
+ (npoints_total * npoints_total * sizeof (XTrapezoid)));
if (!edges)
return;
- traps = (XTrapezoid *) (edges + npoints);
+ traps = (XTrapezoid *) (edges + npoints_total);
nedges = 0;
- for (i = 0; i <= npoints; i++)
+ for (p = 0; p < npolys; p++)
{
- if (i == npoints)
+ for (i = 0; i <= polys[p].npoints; i++)
{
- x = firstx;
- y = firsty;
- }
- else
- {
- x = XDoubleToFixed (fpoints[i].x);
- y = XDoubleToFixed (fpoints[i].y);
- }
- if (i)
- {
- if (y < top)
+ if (i == polys[p].npoints)
+ {
+ x = firstx;
+ y = firsty;
+ }
+ else
+ {
+ x = XDoubleToFixed (polys[p].points[i].x);
+ y = XDoubleToFixed (polys[p].points[i].y);
+ }
+ if (i)
+ {
+ if (y < top)
+ top = y;
+ else if (y > bottom)
+ bottom = y;
+ if (prevy < y)
+ {
+ edges[nedges].edge.p1.x = prevx;
+ edges[nedges].edge.p1.y = prevy;
+ edges[nedges].edge.p2.x = x;
+ edges[nedges].edge.p2.y = y;
+ edges[nedges].clockWise = True;
+ nedges++;
+ }
+ else if (prevy > y)
+ {
+ edges[nedges].edge.p1.x = x;
+ edges[nedges].edge.p1.y = y;
+ edges[nedges].edge.p2.x = prevx;
+ edges[nedges].edge.p2.y = prevy;
+ edges[nedges].clockWise = False;
+ nedges++;
+ }
+ /* drop horizontal edges */
+ }
+ else
+ {
top = y;
- else if (y > bottom)
bottom = y;
- if (prevy < y)
- {
- edges[nedges].edge.p1.x = prevx;
- edges[nedges].edge.p1.y = prevy;
- edges[nedges].edge.p2.x = x;
- edges[nedges].edge.p2.y = y;
- edges[nedges].clockWise = True;
- nedges++;
- }
- else if (prevy > y)
- {
- edges[nedges].edge.p1.x = x;
- edges[nedges].edge.p1.y = y;
- edges[nedges].edge.p2.x = prevx;
- edges[nedges].edge.p2.y = prevy;
- edges[nedges].clockWise = False;
- nedges++;
- }
- /* drop horizontal edges */
- }
- else
- {
- top = y;
- bottom = y;
- firstx = x;
- firsty = y;
+ firstx = x;
+ firsty = y;
+ }
+ prevx = x;
+ prevy = y;
}
- prevx = x;
- prevy = y;
}
ntraps = XRenderComputeTrapezoids (edges, nedges, winding, traps);
/* XXX adjust xSrc/xDst */