/* * Written by Brian Kelleher; Dec. 1985. * * Fill a convex polygon. If the given polygon is not convex, then the result * is undefined. The algorithm is to order the edges from smallest y to * largest by partitioning the array into a left edge list and a right edge * list. The algorithm used to traverse each edge is an extension of * Bresenham's line algorithm with y as the major axis. For a derivation of * the algorithm, see the author of this code. */ static Bool miFillConvexPoly(DrawablePtr dst, GCPtr pgc, int count, DDXPointPtr ptsIn) { int xl = 0, xr = 0; /* x vals of left and right edges */ int dl = 0, dr = 0; /* decision variables */ int ml = 0, m1l = 0; /* left edge slope and slope+1 */ int mr = 0, m1r = 0; /* right edge slope and slope+1 */ int incr1l = 0, incr2l = 0; /* left edge error increments */ int incr1r = 0, incr2r = 0; /* right edge error increments */ int dy; /* delta y */ int y; /* current scanline */ int left, right; /* indices to first endpoints */ int i; /* loop counter */ int nextleft, nextright; /* indices to second endpoints */ DDXPointPtr ptsOut, FirstPoint; /* output buffer */ int *width, *FirstWidth; /* output buffer */ int imin; /* index of smallest vertex (in y) */ int ymin; /* y-extents of polygon */ int ymax; /* * find leftx, bottomy, rightx, topy, and the index * of bottomy. Also translate the points. */ imin = getPolyYBounds(ptsIn, count, &ymin, &ymax); dy = ymax - ymin + 1; if ((count < 3) || (dy < 0)) return TRUE; ptsOut = FirstPoint = xallocarray(dy, sizeof(DDXPointRec)); width = FirstWidth = xallocarray(dy, sizeof(int)); if (!FirstPoint || !FirstWidth) { free(FirstWidth); free(FirstPoint); return FALSE; } nextleft = nextright = imin; y = ptsIn[nextleft].y; /* * loop through all edges of the polygon */ do { /* * add a left edge if we need to */ if (ptsIn[nextleft].y == y) { left = nextleft; /* * find the next edge, considering the end * conditions of the array. */ nextleft++; if (nextleft >= count) nextleft = 0; /* * now compute all of the random information * needed to run the iterative algorithm. */ BRESINITPGON(ptsIn[nextleft].y - ptsIn[left].y, ptsIn[left].x, ptsIn[nextleft].x, xl, dl, ml, m1l, incr1l, incr2l); } /* * add a right edge if we need to */ if (ptsIn[nextright].y == y) { right = nextright; /* * find the next edge, considering the end * conditions of the array. */ nextright--; if (nextright < 0) nextright = count - 1; /* * now compute all of the random information * needed to run the iterative algorithm. */ BRESINITPGON(ptsIn[nextright].y - ptsIn[right].y, ptsIn[right].x, ptsIn[nextright].x, xr, dr, mr, m1r, incr1r, incr2r); } /* * generate scans to fill while we still have * a right edge as well as a left edge. */ i = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y; /* in case we're called with non-convex polygon */ if (i < 0) { free(FirstWidth); free(FirstPoint); return TRUE; } while (i-- > 0) { ptsOut->y = y; /* * reverse the edges if necessary */ if (xl < xr) { *(width++) = xr - xl; (ptsOut++)->x = xl; } else { *(width++) = xl - xr; (ptsOut++)->x = xr; } y++; /* increment down the edges */ BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l); BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r); } } while (y != ymax); /* * Finally, fill the <remaining> spans */ (*pgc->ops->FillSpans) (dst, pgc, ptsOut - FirstPoint, FirstPoint, FirstWidth, 1); free(FirstWidth); free(FirstPoint); return TRUE; }
void cgfx_FillPoly(CoreGfxBase *CoreGfxBase, CRastPort *rp, int count, CGfxPoint *pointtable) { INT32 xl = 0, xr = 0; /* x vals of left and right edges */ int dl = 0, dr = 0; /* decision variables */ int ml = 0, m1l = 0; /* left edge slope and slope+1 */ int mr = 0, m1r = 0; /* right edge slope and slope+1 */ int incr1l = 0, incr2l = 0; /* left edge error increments */ int incr1r = 0, incr2r = 0; /* right edge error increments */ int dy; /* delta y */ INT32 y; /* current scanline */ int left, right; /* indices to first endpoints */ int i; /* loop counter */ int nextleft, nextright; /* indices to second endpoints */ CGfxPoint *ptsOut, *FirstPoint;/* output buffer */ INT32 *width, *FirstWidth;/* output buffer */ int imin; /* index of smallest vertex (in y)*/ int ymin; /* y-extents of polygon */ int ymax; /* * find leftx, bottomy, rightx, topy, and the index * of bottomy. */ imin = getPolyYBounds(pointtable, count, &ymin, &ymax); if (rp->crp_FillMode != FILL_SOLID) { int xmin, xmax; getPolyXBounds(pointtable, count, &xmin, &xmax); set_ts_origin(rp, xmin, ymin); } dy = ymax - ymin + 1; if ((count < 3) || (dy < 0)) return; ptsOut = FirstPoint = (CGfxPoint *)AllocVec(sizeof(CGfxPoint) * dy, MEMF_FAST); width = FirstWidth = (INT32 *)AllocVec(sizeof(INT32) * dy, MEMF_FAST); if(!FirstPoint || !FirstWidth) { if (FirstWidth) FreeVec(FirstWidth); if (FirstPoint) FreeVec(FirstPoint); return; } nextleft = nextright = imin; y = pointtable[nextleft].y; /* * loop through all edges of the polygon */ do { /* * add a left edge if we need to */ if (pointtable[nextleft].y == y) { left = nextleft; /* * find the next edge, considering the end * conditions of the array. */ nextleft++; if (nextleft >= count) nextleft = 0; /* * now compute all of the random information * needed to run the iterative algorithm. */ BRESINITPGON(pointtable[nextleft].y-pointtable[left].y, pointtable[left].x,pointtable[nextleft].x, xl, dl, ml, m1l, incr1l, incr2l); } /* * add a right edge if we need to */ if (pointtable[nextright].y == y) { right = nextright; /* * find the next edge, considering the end * conditions of the array. */ nextright--; if (nextright < 0) nextright = count-1; /* * now compute all of the random information * needed to run the iterative algorithm. */ BRESINITPGON(pointtable[nextright].y-pointtable[right].y, pointtable[right].x,pointtable[nextright].x, xr, dr, mr, m1r, incr1r, incr2r); } /* * generate scans to fill while we still have * a right edge as well as a left edge. */ i = MIN(pointtable[nextleft].y, pointtable[nextright].y) - y; /* in case we're called with non-convex polygon */ if(i < 0) { FreeVec(FirstWidth); FreeVec(FirstPoint); return; } while (i-- > 0) { ptsOut->y = y; /* * reverse the edges if necessary */ if (xl < xr) { *(width++) = xr - xl; (ptsOut++)->x = xl; } else { *(width++) = xl - xr; (ptsOut++)->x = xr; } y++; /* increment down the edges */ BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l); BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r); } } while (y != ymax); /* * Finally, fill the spans */ i = ptsOut-FirstPoint; ptsOut = FirstPoint; width = FirstWidth; while (--i >= 0) { /* calc x extent from width*/ int e = *width++ - 1; if (e >= 0) { if (rp->crp_FillMode != FILL_SOLID) ts_drawrow(CoreGfxBase, rp, ptsOut->x, ptsOut->x + e, ptsOut->y); else drawrow(CoreGfxBase, rp, ptsOut->x, ptsOut->x + e, ptsOut->y); } ++ptsOut; } FreeVec(FirstWidth); FreeVec(FirstPoint); FixCursor(rp->crp_PixMap); }