Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/mifpolycon.c, revision 1.1

1.1     ! root        1: /***********************************************************
        !             2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
        !             3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
        !             4: 
        !             5:                         All Rights Reserved
        !             6: 
        !             7: Permission to use, copy, modify, and distribute this software and its 
        !             8: documentation for any purpose and without fee is hereby granted, 
        !             9: provided that the above copyright notice appear in all copies and that
        !            10: both that copyright notice and this permission notice appear in 
        !            11: supporting documentation, and that the names of Digital or MIT not be
        !            12: used in advertising or publicity pertaining to distribution of the
        !            13: software without specific, written prior permission.  
        !            14: 
        !            15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            21: SOFTWARE.
        !            22: 
        !            23: ******************************************************************/
        !            24: /* $Header: mifpolycon.c,v 1.10 87/09/11 07:20:50 toddb Exp $ */
        !            25: #include "X.h"
        !            26: #include "gcstruct.h"
        !            27: #include "windowstr.h"
        !            28: #include "pixmapstr.h"
        !            29: #include "mifpoly.h"
        !            30: 
        !            31: /*
        !            32:  *     Written by Todd Newman; April. 1987.
        !            33:  *
        !            34:  *     Fill a convex polygon.  If the given polygon
        !            35:  *     is not convex, then the result is undefined.
        !            36:  *     The algorithm is to order the edges from smallest
        !            37:  *     y to largest by partitioning the array into a left
        !            38:  *     edge list and a right edge list.  The algorithm used
        !            39:  *     to traverse each edge is digital differencing analyzer
        !            40:  *     line algorithm with y as the major axis. There's some funny linear
        !            41:  *     interpolation involved because of the subpixel postioning.
        !            42:  *
        !            43:  *     Given the opportunity to write non-portable code, I would replace
        !            44:  *     this with a fixed point extended precision Bresenham line algorithm.
        !            45:  *     Instead of doubles in the SppPointRecs, I'd use 64 bit fixed point
        !            46:  *     values.  I'd have to write a fixed point math pack in assembler,
        !            47:  *     but these things are relatively straight forward. (Alas, not portable.)
        !            48:  *     
        !            49:  *     It can be shown that given 16 bit values for x and y, there's no
        !            50:  *     room to extend the precision and still fit intermediate results in
        !            51:  *     a 32 bit integer.  It should also be clear that trying to write a
        !            52:  *     extended precision math pack in C would not produce code that runs
        !            53:  *     much faster than your average floating point coprocessor.  Even
        !            54:  *     floating point emulation should be able to run faster if the assembly
        !            55:  *     language coding is handled at all well.
        !            56:  *
        !            57:  *     "So why not at least use float, instead of double," my friends ask
        !            58:  *     me.  Well, C is going to cast everything to double as soon as you
        !            59:  *     try to do anything with it anyway.  (Check out K&R.)  I'd rather
        !            60:  *     trade a little space and skip all the superflous type conversions.
        !            61:  *     (This decision could be revisited if you have an ANSI C compiler.)
        !            62:  *
        !            63:  *     So, in sum, I apologize for doing all the wide lines with doubles,
        !            64:  *     but it seems the best trade off  of complexity, performance, and
        !            65:  *     time pressure.
        !            66:  */
        !            67: void
        !            68: miFillSppPoly(dst, pgc, count, ptsIn, xTrans, yTrans)
        !            69:     DrawablePtr        dst;
        !            70:     GCPtr              pgc;
        !            71:     int                        count;          /* number of points */
        !            72:     SppPointPtr        ptsIn;          /* the points */
        !            73:     int                        xTrans, yTrans; /* Translate each point by this */
        !            74: {
        !            75:     double             xl, xr,         /* x vals of left and right edges */
        !            76:                        ml,             /* left edge slope */
        !            77:                        mr,             /* right edge slope */
        !            78:                        dy,             /* delta y */
        !            79:                        i;              /* loop counter */
        !            80:     int                        y,              /* current scanline */
        !            81:                        j,
        !            82:                        imin,           /* index of vertex with smallest y */
        !            83:                        ymin,           /* y-extents of polygon */
        !            84:                        ymax,
        !            85:                        *width,
        !            86:                        *FirstWidth,    /* output buffer */
        !            87:                        *Marked;        /* set if this vertex has been used */
        !            88:     register int       left, right,    /* indices to first endpoints */
        !            89:                        nextleft,
        !            90:                        nextright;      /* indices to second endpoints */
        !            91:     DDXPointPtr        ptsOut,
        !            92:                        FirstPoint;     /* output buffer */
        !            93:     double             ceil();
        !            94: 
        !            95:     if (pgc->miTranslate && (dst->type == DRAWABLE_WINDOW) )
        !            96:     {
        !            97:        xTrans += ((WindowPtr)dst)->absCorner.x;
        !            98:        yTrans += ((WindowPtr)dst)->absCorner.y;
        !            99:     }
        !           100: 
        !           101:     imin = GetFPolyYBounds(ptsIn, count, &ymin, &ymax);
        !           102: 
        !           103:     y = ymax - ymin + 1;
        !           104:     ptsOut = FirstPoint = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * y);
        !           105:     width = FirstWidth = (int *) ALLOCATE_LOCAL(sizeof(int) * y);
        !           106:     Marked = (int *) ALLOCATE_LOCAL(sizeof(int) * count);
        !           107: 
        !           108:     if(!ptsOut || !width || !Marked || (count < 3) || (y <= 0))
        !           109:     {
        !           110:        DEALLOCATE_LOCAL(Marked);
        !           111:        DEALLOCATE_LOCAL(width);
        !           112:        DEALLOCATE_LOCAL(ptsOut);
        !           113:        return;
        !           114:     }
        !           115: 
        !           116:     for(j = 0; j < count; j++)
        !           117:        Marked[j] = 0;
        !           118:     nextleft = nextright = imin;
        !           119:     Marked[imin] = -1;
        !           120:     y = (int) ceil(ptsIn[nextleft].y);
        !           121: 
        !           122:     /*
        !           123:      *  loop through all edges of the polygon
        !           124:      */
        !           125:     do
        !           126:     {
        !           127:         /* add a left edge if we need to */
        !           128:         if ((y > ptsIn[nextleft].y || ISEQUAL(y, ptsIn[nextleft].y)) &&
        !           129:             Marked[nextleft] != 1)
        !           130:        {
        !           131:            Marked[nextleft]++;
        !           132:             left = nextleft++;
        !           133: 
        !           134:             /* find the next edge, considering the end conditions */
        !           135:             if (nextleft >= count)
        !           136:                 nextleft = 0;
        !           137: 
        !           138:             /* now compute the starting point and slope */
        !           139:            dy = ptsIn[nextleft].y - ptsIn[left].y;
        !           140:            if (dy != 0.0)
        !           141:            { 
        !           142:                ml = (ptsIn[nextleft].x - ptsIn[left].x) / dy;
        !           143:                dy = y - ptsIn[left].y;
        !           144:                xl = ptsIn[left].x  + ml * max(dy, 0); 
        !           145:            }
        !           146:         }
        !           147: 
        !           148:         /* add a right edge if we need to */
        !           149:         if (((y > ptsIn[nextright].y) || ISEQUAL(y, ptsIn[nextright].y))
        !           150:             && Marked[nextright] != 1)
        !           151:        {
        !           152:            Marked[nextright]++;
        !           153:             right = nextright--;
        !           154: 
        !           155:             /* find the next edge, considering the end conditions */
        !           156:             if (nextright < 0)
        !           157:                 nextright = count - 1;
        !           158: 
        !           159:             /* now compute the starting point and slope */
        !           160:            dy = ptsIn[nextright].y - ptsIn[right].y;
        !           161:            if (dy != 0.0) 
        !           162:            { 
        !           163:                mr = (ptsIn[nextright].x - ptsIn[right].x) / dy;
        !           164:                dy = y - ptsIn[right].y; 
        !           165:                xr = ptsIn[right].x + mr * max(dy, 0);
        !           166:            }
        !           167:         }
        !           168: 
        !           169: 
        !           170:         /*
        !           171:          *  generate scans to fill while we still have
        !           172:          *  a right edge as well as a left edge.
        !           173:          */
        !           174:         i = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y;
        !           175: 
        !           176:        if (i < EPSILON)
        !           177:        {
        !           178:            if(Marked[nextleft] && Marked[nextright])
        !           179:            {
        !           180:                /* Arrgh, we're trapped! (no more points) 
        !           181:                 * Out, we've got to get out of here before this decadence saps
        !           182:                 * our will completely! */
        !           183:                break;
        !           184:            }
        !           185:            continue;
        !           186:        }
        !           187:        else
        !           188:        {
        !           189:                j = (int) i;
        !           190:                if(!j)
        !           191:                    j++;
        !           192:        }
        !           193:         while (j > 0) 
        !           194:         {
        !           195:             ptsOut->y = (y) + yTrans;
        !           196: 
        !           197:             /* reverse the edges if necessary */
        !           198:             if (xl < xr) 
        !           199:             {
        !           200:                 *(width++) = ROUNDTOINT(xr) - ROUNDTOINT(xl);
        !           201:                 (ptsOut++)->x = ROUNDTOINT(xl) + xTrans;
        !           202:             }
        !           203:             else 
        !           204:             {
        !           205:                 *(width++) = ROUNDTOINT(xl) - ROUNDTOINT(xr);
        !           206:                 (ptsOut++)->x = ROUNDTOINT(xr) + xTrans;
        !           207:             }
        !           208:             y++;
        !           209: 
        !           210:             /* increment down the edges */
        !           211:            xl += ml;
        !           212:            xr += mr;
        !           213:            j--;
        !           214:         }
        !           215:     }  while (y < ymax);
        !           216: 
        !           217:     /* Finally, fill the spans we've collected */
        !           218:     (*pgc->FillSpans)(dst, pgc, 
        !           219:                      ptsOut-FirstPoint, FirstPoint, FirstWidth, 1);
        !           220:     DEALLOCATE_LOCAL(Marked);
        !           221:     DEALLOCATE_LOCAL(FirstWidth);
        !           222:     DEALLOCATE_LOCAL(FirstPoint);
        !           223: }
        !           224: 
        !           225: 
        !           226: /* Find the index of the point with the smallest y.also return the
        !           227:  * smallest and largest y */
        !           228: static
        !           229: int
        !           230: GetFPolyYBounds(pts, n, by, ty)
        !           231:     register SppPointPtr       pts;
        !           232:     int                        n;
        !           233:     int                        *by, *ty;
        !           234: {
        !           235:     register SppPointPtr       ptMin;
        !           236:     double                     ymin, ymax, ceil();
        !           237:     SppPointPtr                        ptsStart = pts;
        !           238: 
        !           239:     ptMin = pts;
        !           240:     ymin = ymax = (pts++)->y;
        !           241: 
        !           242:     while (--n > 0) {
        !           243:         if (pts->y < ymin)
        !           244:        {
        !           245:             ptMin = pts;
        !           246:             ymin = pts->y;
        !           247:         }
        !           248:        if(pts->y > ymax)
        !           249:             ymax = pts->y;
        !           250: 
        !           251:         pts++;
        !           252:     }
        !           253: 
        !           254:     *by = ROUNDTOINT(ymin);
        !           255:     *ty = (int) ceil(ymax);
        !           256:     return(ptMin-ptsStart);
        !           257: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.