void GdFillPoly(PSD psd, int count, MWPOINT *points) { MWPOINT *pp; /* current point */ MWCOORD miny; /* minimum row */ MWCOORD maxy; /* maximum row */ MWCOORD minx; /* minimum column */ MWCOORD maxx; /* maximum column */ int i; /* counter */ if (count <= 0) return; /* First determine the minimum and maximum rows for the polygon. */ pp = points; miny = pp->y; maxy = pp->y; for (i = count; i-- > 0; pp++) { if (miny > pp->y) miny = pp->y; if (maxy < pp->y) maxy = pp->y; } if (miny < 0) miny = 0; if (maxy >= psd->yvirtres) maxy = psd->yvirtres - 1; if (miny > maxy) return; /* Now for each row, scan the list of points and determine the * minimum and maximum x coordinate for each line, and plot the row. * The last point connects with the first point automatically. */ for (; miny <= maxy; miny++) { minx = MAX_MWCOORD; maxx = MIN_MWCOORD; pp = points; for (i = count; --i > 0; pp++) extendrow(miny, pp[0].x, pp[0].y, pp[1].x, pp[1].y, &minx, &maxx); extendrow(miny, pp[0].x, pp[0].y, points[0].x, points[0].y, &minx, &maxx); if (minx <= maxx) drawrow(psd, minx, maxx, miny); } GdFixCursor(psd); }
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); }
/** * Draw a filled polygon. * * @param psd Drawing surface. * @param count Number of points in polygon. * @param pointtable The array of points. */ void GdFillPoly(PSD psd, int count, MWPOINT * pointtable) { edge_t *get; /* global edge table */ int nge = 0; /* num global edges */ int cge = 0; /* cur global edge */ edge_t *aet; /* active edge table */ int nae = 0; /* num active edges */ int i, y; if (count < 3) { /* error, polygons require at least three edges (a triangle) */ return; } get = (edge_t *) calloc(count, sizeof(edge_t)); aet = (edge_t *) calloc(count, sizeof(edge_t)); if ((get == 0) || (aet == 0)) { /* error, couldn't allocate one or both of the needed tables */ if (get) free(get); if (aet) free(aet); return; } /* setup the global edge table */ for (i = 0; i < count; ++i) { get[nge].x1 = pointtable[i].x; get[nge].y1 = pointtable[i].y; get[nge].x2 = pointtable[(i + 1) % count].x; get[nge].y2 = pointtable[(i + 1) % count].y; if (get[nge].y1 != get[nge].y2) { if (get[nge].y1 > get[nge].y2) { swap(get[nge].x1, get[nge].x2); swap(get[nge].y1, get[nge].y2); } #if USE_FLOAT get[nge].x = get[nge].x1; get[nge].m = get[nge].x2 - get[nge].x1; get[nge].m /= get[nge].y2 - get[nge].y1; #else get[nge].cx = get[nge].x1; get[nge].mn = get[nge].x2 - get[nge].x1; get[nge].d = get[nge].y2 - get[nge].y1; get[nge].fn = get[nge].mn / 2; #endif ++nge; } } qsort(get, nge, sizeof(get[0]), edge_cmp); /* start with the lowest y in the table */ y = get[0].y1; do { /* add edges to the active table from the global table */ while ((nge > 0) && (get[cge].y1 == y)) { aet[nae] = get[cge++]; --nge; aet[nae++].y1 = 0; } qsort(aet, nae, sizeof(aet[0]), edge_cmp); /* using odd parity, render alternating line segments */ for (i = 1; i < nae; i += 2) { #if USE_FLOAT int l = (int)aet[i - 1].x; int r = (int)aet[i].x; #else int l = (int)aet[i - 1].cx; int r = (int)aet[i].cx; #endif if (r > l) drawrow(psd, l, r - 1, y); } /* prepare for the next scan line */ ++y; /* remove inactive edges from the active edge table */ /* or update the current x position of active edges */ for (i = 0; i < nae; ++i) { if (aet[i].y2 == y) aet[i--] = aet[--nae]; else { #if USE_FLOAT aet[i].x += aet[i].m; #else aet[i].fn += aet[i].mn; if (aet[i].fn < 0) { aet[i].cx += aet[i].fn / aet[i].d - 1; aet[i].fn %= aet[i].d; aet[i].fn += aet[i].d; } if (aet[i].fn >= aet[i].d) { aet[i].cx += aet[i].fn / aet[i].d; aet[i].fn %= aet[i].d; } #endif } } /* keep doing this while there are any edges left */ } while ((nae > 0) || (nge > 0)); /* all done, free the edge tables */ free(get); free(aet); GdFixCursor(psd); }