Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/mipolyutil.c, revision 1.1.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: mipolyutil.c,v 1.12 87/09/11 07:19:12 toddb Exp $ */
                     25: #include "miscstruct.h"
                     26: #include "gc.h"
                     27: #include "miscanfill.h"
                     28: #include "mipoly.h"
                     29: 
                     30: #define MAXINT 0x7fffffff
                     31: #define MININT -MAXINT
                     32: 
                     33: /*
                     34:  *     fillUtils.c
                     35:  *
                     36:  *     Written by Brian Kelleher;  Oct. 1985
                     37:  *
                     38:  *     This module contains all of the utility functions
                     39:  *     needed to scan convert a polygon.
                     40:  *
                     41:  */
                     42: 
                     43: /*
                     44:  *     InsertEdgeInET
                     45:  *
                     46:  *     Insert the given edge into the edge table.
                     47:  *     First we must find the correct bucket in the
                     48:  *     Edge table, then find the right slot in the
                     49:  *     bucket.  Finally, we can insert it.
                     50:  *
                     51:  */
                     52: void
                     53: miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
                     54:     EdgeTable *ET;
                     55:     EdgeTableEntry *ETE;
                     56:     int scanline;
                     57:     ScanLineListBlock **SLLBlock;
                     58:     int *iSLLBlock;
                     59: {
                     60:     register EdgeTableEntry *start, *prev;
                     61:     register ScanLineList *pSLL, *pPrevSLL;
                     62:     ScanLineListBlock *tmpSLLBlock;
                     63: 
                     64:     /*
                     65:      * find the right bucket to put the edge into
                     66:      */
                     67:     pPrevSLL = &ET->scanlines;
                     68:     pSLL = pPrevSLL->next;
                     69:     while (pSLL && (pSLL->scanline < scanline)) 
                     70:     {
                     71:         pPrevSLL = pSLL;
                     72:         pSLL = pSLL->next;
                     73:     }
                     74: 
                     75:     /*
                     76:      * reassign pSLL (pointer to ScanLineList) if necessary
                     77:      */
                     78:     if ((!pSLL) || (pSLL->scanline > scanline)) 
                     79:     {
                     80:         if (*iSLLBlock > SLLSPERBLOCK-1) 
                     81:         {
                     82:             tmpSLLBlock = 
                     83:                  (ScanLineListBlock *)Xalloc(sizeof(ScanLineListBlock));
                     84:             (*SLLBlock)->next = tmpSLLBlock;
                     85:             tmpSLLBlock->next = (ScanLineListBlock *)NULL;
                     86:             *SLLBlock = tmpSLLBlock;
                     87:             *iSLLBlock = 0;
                     88:         }
                     89:         pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
                     90: 
                     91:         pSLL->next = pPrevSLL->next;
                     92:         pSLL->edgelist = (EdgeTableEntry *)NULL;
                     93:         pPrevSLL->next = pSLL;
                     94:     }
                     95:     pSLL->scanline = scanline;
                     96: 
                     97:     /*
                     98:      * now insert the edge in the right bucket
                     99:      */
                    100:     prev = (EdgeTableEntry *)NULL;
                    101:     start = pSLL->edgelist;
                    102:     while (start && (start->bres.minor < ETE->bres.minor)) 
                    103:     {
                    104:         prev = start;
                    105:         start = start->next;
                    106:     }
                    107:     ETE->next = start;
                    108: 
                    109:     if (prev)
                    110:         prev->next = ETE;
                    111:     else
                    112:         pSLL->edgelist = ETE;
                    113: }
                    114: 
                    115: /*
                    116:  *     CreateEdgeTable
                    117:  *
                    118:  *     This routine creates the edge table for
                    119:  *     scan converting polygons. 
                    120:  *     The Edge Table (ET) looks like:
                    121:  *
                    122:  *    EdgeTable
                    123:  *     --------
                    124:  *    |  ymax  |        ScanLineLists
                    125:  *    |scanline|-->------------>-------------->...
                    126:  *     --------   |scanline|   |scanline|
                    127:  *                |edgelist|   |edgelist|
                    128:  *                ---------    ---------
                    129:  *                    |             |
                    130:  *                    |             |
                    131:  *                    V             V
                    132:  *              list of ETEs   list of ETEs
                    133:  *
                    134:  *     where ETE is an EdgeTableEntry data structure,
                    135:  *     and there is one ScanLineList per scanline at
                    136:  *     which an edge is initially entered.
                    137:  *
                    138:  */
                    139: 
                    140: void
                    141: miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
                    142:     register int count;
                    143:     register DDXPointPtr pts;
                    144:     EdgeTable *ET;
                    145:     EdgeTableEntry *AET;
                    146:     register EdgeTableEntry *pETEs;
                    147:     ScanLineListBlock   *pSLLBlock;
                    148: {
                    149:     register DDXPointPtr top, bottom;
                    150:     register DDXPointPtr PrevPt, CurrPt;
                    151:     int iSLLBlock = 0;
                    152: 
                    153:     int dy;
                    154: 
                    155:     if (count < 2)  return;
                    156: 
                    157:     /*
                    158:      *  initialize the Active Edge Table
                    159:      */
                    160:     AET->next = (EdgeTableEntry *)NULL;
                    161:     AET->back = (EdgeTableEntry *)NULL;
                    162:     AET->nextWETE = (EdgeTableEntry *)NULL;
                    163:     AET->bres.minor = MININT;
                    164: 
                    165:     /*
                    166:      *  initialize the Edge Table.
                    167:      */
                    168:     ET->scanlines.next = (ScanLineList *)NULL;
                    169:     ET->ymax = MININT;
                    170:     ET->ymin = MAXINT;
                    171:     pSLLBlock->next = (ScanLineListBlock *)NULL;
                    172: 
                    173:     PrevPt = &pts[count-1];
                    174: 
                    175:     /*
                    176:      *  for each vertex in the array of points.
                    177:      *  In this loop we are dealing with two vertices at
                    178:      *  a time -- these make up one edge of the polygon.
                    179:      */
                    180:     while (count--) 
                    181:     {
                    182:         CurrPt = pts++;
                    183: 
                    184:         /*
                    185:          *  find out which point is above and which is below.
                    186:          */
                    187:         if (PrevPt->y > CurrPt->y) 
                    188:         {
                    189:             bottom = PrevPt, top = CurrPt;
                    190:             pETEs->ClockWise = 0;
                    191:         }
                    192:         else 
                    193:         {
                    194:             bottom = CurrPt, top = PrevPt;
                    195:             pETEs->ClockWise = 1;
                    196:         }
                    197: 
                    198:         /*
                    199:          * don't add horizontal edges to the Edge table.
                    200:          */
                    201:         if (bottom->y != top->y) 
                    202:         {
                    203:             pETEs->ymax = bottom->y-1;  /* -1 so we don't get last scanline */
                    204: 
                    205:             /*
                    206:              *  initialize integer edge algorithm
                    207:              */
                    208:             dy = bottom->y - top->y;
                    209:             BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
                    210: 
                    211:             miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock);
                    212: 
                    213:             ET->ymax = max(ET->ymax, PrevPt->y);
                    214:             ET->ymin = min(ET->ymin, PrevPt->y);
                    215:             pETEs++;
                    216:         }
                    217: 
                    218:         PrevPt = CurrPt;
                    219:     }
                    220: }
                    221: 
                    222: /*
                    223:  *     loadAET
                    224:  *
                    225:  *     This routine moves EdgeTableEntries from the
                    226:  *     EdgeTable into the Active Edge Table,
                    227:  *     leaving them sorted by smaller x coordinate.
                    228:  *
                    229:  */
                    230: 
                    231: void
                    232: miloadAET(AET, ETEs)
                    233:     register EdgeTableEntry *AET, *ETEs;
                    234: {
                    235:     register EdgeTableEntry *pPrevAET;
                    236:     register EdgeTableEntry *tmp;
                    237: 
                    238:     pPrevAET = AET;
                    239:     AET = AET->next;
                    240:     while (ETEs) 
                    241:     {
                    242:         while (AET && (AET->bres.minor < ETEs->bres.minor)) 
                    243:         {
                    244:             pPrevAET = AET;
                    245:             AET = AET->next;
                    246:         }
                    247:         tmp = ETEs->next;
                    248:         ETEs->next = AET;
                    249:         if (AET)
                    250:             AET->back = ETEs;
                    251:         ETEs->back = pPrevAET;
                    252:         pPrevAET->next = ETEs;
                    253:         pPrevAET = ETEs;
                    254: 
                    255:         ETEs = tmp;
                    256:     }
                    257: }
                    258: 
                    259: /*
                    260:  *     computeWAET
                    261:  *
                    262:  *     This routine links the AET by the
                    263:  *     nextWETE (winding EdgeTableEntry) link for
                    264:  *     use by the winding number rule.  The final 
                    265:  *     Active Edge Table (AET) might look something
                    266:  *     like:
                    267:  *
                    268:  *     AET
                    269:  *     ----------  ---------   ---------
                    270:  *     |ymax    |  |ymax    |  |ymax    | 
                    271:  *     | ...    |  |...     |  |...     |
                    272:  *     |next    |->|next    |->|next    |->...
                    273:  *     |nextWETE|  |nextWETE|  |nextWETE|
                    274:  *     ---------   ---------   ^--------
                    275:  *         |                   |       |
                    276:  *         V------------------->       V---> ...
                    277:  *
                    278:  */
                    279: void
                    280: micomputeWAET(AET)
                    281:     register EdgeTableEntry *AET;
                    282: {
                    283:     register EdgeTableEntry *pWETE;
                    284:     register int inside = 1;
                    285:     register int isInside = 0;
                    286: 
                    287:     AET->nextWETE = (EdgeTableEntry *)NULL;
                    288:     pWETE = AET;
                    289:     AET = AET->next;
                    290:     while (AET) 
                    291:     {
                    292:         if (AET->ClockWise)
                    293:             isInside++;
                    294:         else
                    295:             isInside--;
                    296: 
                    297:         if ((!inside && !isInside) ||
                    298:             ( inside &&  isInside)) 
                    299:         {
                    300:             pWETE->nextWETE = AET;
                    301:             pWETE = AET;
                    302:             inside = !inside;
                    303:         }
                    304:         AET = AET->next;
                    305:     }
                    306:     pWETE->nextWETE = (EdgeTableEntry *)NULL;
                    307: }
                    308: 
                    309: /*
                    310:  *     InsertionSort
                    311:  *
                    312:  *     Just a simple insertion sort using
                    313:  *     pointers and back pointers to sort the Active
                    314:  *     Edge Table.
                    315:  *
                    316:  */
                    317: 
                    318: int
                    319: miInsertionSort(AET)
                    320:     register EdgeTableEntry *AET;
                    321: {
                    322:     register EdgeTableEntry *pETEchase;
                    323:     register EdgeTableEntry *pETEinsert;
                    324:     register EdgeTableEntry *pETEchaseBackTMP;
                    325:     register int changed = 0;
                    326: 
                    327:     AET = AET->next;
                    328:     while (AET) 
                    329:     {
                    330:         pETEinsert = AET;
                    331:         pETEchase = AET;
                    332:         while (pETEchase->back->bres.minor > AET->bres.minor)
                    333:             pETEchase = pETEchase->back;
                    334: 
                    335:         AET = AET->next;
                    336:         if (pETEchase != pETEinsert) 
                    337:         {
                    338:             pETEchaseBackTMP = pETEchase->back;
                    339:             pETEinsert->back->next = AET;
                    340:             if (AET)
                    341:                 AET->back = pETEinsert->back;
                    342:             pETEinsert->next = pETEchase;
                    343:             pETEchase->back->next = pETEinsert;
                    344:             pETEchase->back = pETEinsert;
                    345:             pETEinsert->back = pETEchaseBackTMP;
                    346:             changed = 1;
                    347:         }
                    348:     }
                    349:     return(changed);
                    350: }
                    351: 
                    352: /*
                    353:  *     Clean up our act.
                    354:  */
                    355: void
                    356: miFreeStorage(pSLLBlock)
                    357:     register ScanLineListBlock   *pSLLBlock;
                    358: {
                    359:     register ScanLineListBlock   *tmpSLLBlock;
                    360: 
                    361:     while (pSLLBlock) 
                    362:     {
                    363:         tmpSLLBlock = pSLLBlock->next;
                    364:         Xfree(pSLLBlock);
                    365:         pSLLBlock = tmpSLLBlock;
                    366:     }
                    367: }

unix.superglobalmegacorp.com

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