コード例 #1
0
ファイル: mipoly.c プロジェクト: AmesianX/xorg-server
/*
 * 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;
}
コード例 #2
0
ファイル: drawpoly.c プロジェクト: snayaksnayak/poweros_x86
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);
}