Annotation of researchv9/X11/src/X.V11R1/lib/X/poly.h, revision 1.1.1.1

1.1       root        1: /* $Header: poly.h,v 1.1 87/09/11 08:15:38 toddb Exp $ */
                      2: /************************************************************************
                      3: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
                      4: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
                      5: 
                      6:                         All Rights Reserved
                      7: 
                      8: Permission to use, copy, modify, and distribute this software and its 
                      9: documentation for any purpose and without fee is hereby granted, 
                     10: provided that the above copyright notice appear in all copies and that
                     11: both that copyright notice and this permission notice appear in 
                     12: supporting documentation, and that the names of Digital or MIT not be
                     13: used in advertising or publicity pertaining to distribution of the
                     14: software without specific, written prior permission.  
                     15: 
                     16: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     17: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     18: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     19: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     20: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     21: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     22: SOFTWARE.
                     23: 
                     24: ************************************************************************/
                     25: #define NULL 0
                     26: 
                     27: 
                     28: /*
                     29:  *     This file contains a few macros to help track
                     30:  *     the edge of a filled object.  The object is assumed
                     31:  *     to be filled in scanline order, and thus the
                     32:  *     algorithm used is an extension of Bresenham's line
                     33:  *     drawing algorithm which assumes that y is always the
                     34:  *     major axis.
                     35:  *     Since these pieces of code are the same for any filled shape,
                     36:  *     it is more convenient to gather the library in one
                     37:  *     place, but since these pieces of code are also in
                     38:  *     the inner loops of output primitives, procedure call
                     39:  *     overhead is out of the question.
                     40:  *     See the author for a derivation if needed.
                     41:  */
                     42: 
                     43: 
                     44: /*
                     45:  *  In scan converting polygons, we want to choose those pixels
                     46:  *  which are inside the polygon.  Thus, we add .5 to the starting
                     47:  *  x coordinate for both left and right edges.  Now we choose the
                     48:  *  first pixel which is inside the pgon for the left edge and the
                     49:  *  first pixel which is outside the pgon for the right edge.
                     50:  *  Draw the left pixel, but not the right.
                     51:  *
                     52:  *  How to add .5 to the starting x coordinate:
                     53:  *      If the edge is moving to the right, then subtract dy from the
                     54:  *  error term from the general form of the algorithm.
                     55:  *      If the edge is moving to the left, then add dy to the error term.
                     56:  *
                     57:  *  The reason for the difference between edges moving to the left
                     58:  *  and edges moving to the right is simple:  If an edge is moving
                     59:  *  to the right, then we want the algorithm to flip immediately.
                     60:  *  If it is moving to the left, then we don't want it to flip until
                     61:  *  we traverse an entire pixel.
                     62:  */
                     63: #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
                     64:     int dx;      /* local storage */ \
                     65: \
                     66:     /* \
                     67:      *  if the edge is horizontal, then it is ignored \
                     68:      *  and assumed not to be processed.  Otherwise, do this stuff. \
                     69:      */ \
                     70:     if ((dy) != 0) { \
                     71:         xStart = (x1); \
                     72:         dx = (x2) - xStart; \
                     73:         if (dx < 0) { \
                     74:             m = dx / (dy); \
                     75:             m1 = m - 1; \
                     76:             incr1 = -2 * dx + 2 * (dy) * m1; \
                     77:             incr2 = -2 * dx + 2 * (dy) * m; \
                     78:             d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
                     79:         } else { \
                     80:             m = dx / (dy); \
                     81:             m1 = m + 1; \
                     82:             incr1 = 2 * dx - 2 * (dy) * m1; \
                     83:             incr2 = 2 * dx - 2 * (dy) * m; \
                     84:             d = -2 * m * (dy) + 2 * dx; \
                     85:         } \
                     86:     } \
                     87: }
                     88: 
                     89: #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
                     90:     if (m1 > 0) { \
                     91:         if (d > 0) { \
                     92:             minval += m1; \
                     93:             d += incr1; \
                     94:         } \
                     95:         else { \
                     96:             minval += m; \
                     97:             d += incr2; \
                     98:         } \
                     99:     } else {\
                    100:         if (d >= 0) { \
                    101:             minval += m1; \
                    102:             d += incr1; \
                    103:         } \
                    104:         else { \
                    105:             minval += m; \
                    106:             d += incr2; \
                    107:         } \
                    108:     } \
                    109: }
                    110: 
                    111: 
                    112: /*
                    113:  *     This structure contains all of the information needed
                    114:  *     to run the bresenham algorithm.
                    115:  *     The variables may be hardcoded into the declarations
                    116:  *     instead of using this structure to make use of
                    117:  *     register declarations.
                    118:  */
                    119: typedef struct {
                    120:     int minor_axis;    /* minor axis        */
                    121:     int d;             /* decision variable */
                    122:     int m, m1;         /* slope and slope+1 */
                    123:     int incr1, incr2;  /* error increments */
                    124: } BRESINFO;
                    125: 
                    126: 
                    127: #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
                    128:        BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
                    129:                      bres.m, bres.m1, bres.incr1, bres.incr2)
                    130: 
                    131: #define BRESINCRPGONSTRUCT(bres) \
                    132:         BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
                    133: 
                    134: 
                    135: 
                    136: /*
                    137:  *     These are the data structures needed to scan
                    138:  *     convert regions.  Two different scan conversion
                    139:  *     methods are available -- the even-odd method, and
                    140:  *     the winding number method.
                    141:  *     The even-odd rule states that a point is inside
                    142:  *     the polygon if a ray drawn from that point in any
                    143:  *     direction will pass through an odd number of
                    144:  *     path segments.
                    145:  *     By the winding number rule, a point is decided
                    146:  *     to be inside the polygon if a ray drawn from that
                    147:  *     point in any direction passes through a different
                    148:  *     number of clockwise and counter-clockwise path
                    149:  *     segments.
                    150:  *
                    151:  *     These data structures are adapted somewhat from
                    152:  *     the algorithm in (Foley/Van Dam) for scan converting
                    153:  *     polygons.
                    154:  *     The basic algorithm is to start at the top (smallest y)
                    155:  *     of the polygon, stepping down to the bottom of
                    156:  *     the polygon by incrementing the y coordinate.  We
                    157:  *     keep a list of edges which the current scanline crosses,
                    158:  *     sorted by x.  This list is called the Active Edge Table (AET)
                    159:  *     As we change the y-coordinate, we update each entry in 
                    160:  *     in the active edge table to reflect the edges new xcoord.
                    161:  *     This list must be sorted at each scanline in case
                    162:  *     two edges intersect.
                    163:  *     We also keep a data structure known as the Edge Table (ET),
                    164:  *     which keeps track of all the edges which the current
                    165:  *     scanline has not yet reached.  The ET is basically a
                    166:  *     list of ScanLineList structures containing a list of
                    167:  *     edges which are entered at a given scanline.  There is one
                    168:  *     ScanLineList per scanline at which an edge is entered.
                    169:  *     When we enter a new edge, we move it from the ET to the AET.
                    170:  *
                    171:  *     From the AET, we can implement the even-odd rule as in
                    172:  *     (Foley/Van Dam).
                    173:  *     The winding number rule is a little trickier.  We also
                    174:  *     keep the EdgeTableEntries in the AET linked by the
                    175:  *     nextWETE (winding EdgeTableEntry) link.  This allows
                    176:  *     the edges to be linked just as before for updating
                    177:  *     purposes, but only uses the edges linked by the nextWETE
                    178:  *     link as edges representing spans of the polygon to
                    179:  *     drawn (as with the even-odd rule).
                    180:  */
                    181: 
                    182: /*
                    183:  * for the winding number rule
                    184:  */
                    185: #define CLOCKWISE          1
                    186: #define COUNTERCLOCKWISE  -1 
                    187: 
                    188: typedef struct _EdgeTableEntry {
                    189:      int ymax;             /* ycoord at which we exit this edge. */
                    190:      BRESINFO bres;        /* Bresenham info to run the edge     */
                    191:      struct _EdgeTableEntry *next;       /* next in the list     */
                    192:      struct _EdgeTableEntry *back;       /* for insertion sort   */
                    193:      struct _EdgeTableEntry *nextWETE;   /* for winding num rule */
                    194:      int ClockWise;        /* flag for winding number rule       */
                    195: } EdgeTableEntry;
                    196: 
                    197: 
                    198: typedef struct _ScanLineList{
                    199:      int scanline;              /* the scanline represented */
                    200:      EdgeTableEntry *edgelist;  /* header node              */
                    201:      struct _ScanLineList *next;  /* next in the list       */
                    202: } ScanLineList;
                    203: 
                    204: 
                    205: typedef struct {
                    206:      int ymax;                 /* ymax for the polygon     */
                    207:      int ymin;                 /* ymin for the polygon     */
                    208:      ScanLineList scanlines;   /* header node              */
                    209: } EdgeTable;
                    210: 
                    211: 
                    212: /*
                    213:  * Here is a struct to help with storage allocation
                    214:  * so we can allocate a big chunk at a time, and then take
                    215:  * pieces from this heap when we need to.
                    216:  */
                    217: #define SLLSPERBLOCK 25
                    218: 
                    219: typedef struct _ScanLineListBlock {
                    220:      ScanLineList SLLs[SLLSPERBLOCK];
                    221:      struct _ScanLineListBlock *next;
                    222: } ScanLineListBlock;
                    223: 
                    224: 
                    225: 
                    226: /*
                    227:  *
                    228:  *     a few macros for the inner loops of the fill code where
                    229:  *     performance considerations don't allow a procedure call.
                    230:  *
                    231:  *     Evaluate the given edge at the given scanline.
                    232:  *     If the edge has expired, then we leave it and fix up
                    233:  *     the active edge table; otherwise, we increment the
                    234:  *     x value to be ready for the next scanline.
                    235:  *     The winding number rule is in effect, so we must notify
                    236:  *     the caller when the edge has been removed so he
                    237:  *     can reorder the Winding Active Edge Table.
                    238:  */
                    239: #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
                    240:    if (pAET->ymax == y) {          /* leaving this edge */ \
                    241:       pPrevAET->next = pAET->next; \
                    242:       pAET = pPrevAET->next; \
                    243:       fixWAET = 1; \
                    244:       if (pAET) \
                    245:          pAET->back = pPrevAET; \
                    246:    } \
                    247:    else { \
                    248:       BRESINCRPGONSTRUCT(pAET->bres); \
                    249:       pPrevAET = pAET; \
                    250:       pAET = pAET->next; \
                    251:    } \
                    252: }
                    253: 
                    254: 
                    255: /*
                    256:  *     Evaluate the given edge at the given scanline.
                    257:  *     If the edge has expired, then we leave it and fix up
                    258:  *     the active edge table; otherwise, we increment the
                    259:  *     x value to be ready for the next scanline.
                    260:  *     The even-odd rule is in effect.
                    261:  */
                    262: #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
                    263:    if (pAET->ymax == y) {          /* leaving this edge */ \
                    264:       pPrevAET->next = pAET->next; \
                    265:       pAET = pPrevAET->next; \
                    266:       if (pAET) \
                    267:          pAET->back = pPrevAET; \
                    268:    } \
                    269:    else { \
                    270:       BRESINCRPGONSTRUCT(pAET->bres); \
                    271:       pPrevAET = pAET; \
                    272:       pAET = pAET->next; \
                    273:    } \
                    274: }

unix.superglobalmegacorp.com

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