123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- /***********************************************************
- Copyright 1987, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Digital not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ******************************************************************/
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "regionstr.h"
- #include "gc.h"
- #include "miscanfill.h"
- #include "mipoly.h"
- #include "misc.h" /* MAXINT */
- /*
- * fillUtils.c
- *
- * Written by Brian Kelleher; Oct. 1985
- *
- * This module contains all of the utility functions
- * needed to scan convert a polygon.
- *
- */
- /*
- * InsertEdgeInET
- *
- * Insert the given edge into the edge table.
- * First we must find the correct bucket in the
- * Edge table, then find the right slot in the
- * bucket. Finally, we can insert it.
- *
- */
- Bool
- miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
- EdgeTable *ET;
- EdgeTableEntry *ETE;
- int scanline;
- ScanLineListBlock **SLLBlock;
- int *iSLLBlock;
- {
- EdgeTableEntry *start, *prev;
- ScanLineList *pSLL, *pPrevSLL;
- ScanLineListBlock *tmpSLLBlock;
- /*
- * find the right bucket to put the edge into
- */
- pPrevSLL = &ET->scanlines;
- pSLL = pPrevSLL->next;
- while (pSLL && (pSLL->scanline < scanline))
- {
- pPrevSLL = pSLL;
- pSLL = pSLL->next;
- }
- /*
- * reassign pSLL (pointer to ScanLineList) if necessary
- */
- if ((!pSLL) || (pSLL->scanline > scanline))
- {
- if (*iSLLBlock > SLLSPERBLOCK-1)
- {
- tmpSLLBlock =
- (ScanLineListBlock *)malloc(sizeof(ScanLineListBlock));
- if (!tmpSLLBlock)
- return FALSE;
- (*SLLBlock)->next = tmpSLLBlock;
- tmpSLLBlock->next = (ScanLineListBlock *)NULL;
- *SLLBlock = tmpSLLBlock;
- *iSLLBlock = 0;
- }
- pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
- pSLL->next = pPrevSLL->next;
- pSLL->edgelist = (EdgeTableEntry *)NULL;
- pPrevSLL->next = pSLL;
- }
- pSLL->scanline = scanline;
- /*
- * now insert the edge in the right bucket
- */
- prev = (EdgeTableEntry *)NULL;
- start = pSLL->edgelist;
- while (start && (start->bres.minor < ETE->bres.minor))
- {
- prev = start;
- start = start->next;
- }
- ETE->next = start;
- if (prev)
- prev->next = ETE;
- else
- pSLL->edgelist = ETE;
- return TRUE;
- }
- /*
- * CreateEdgeTable
- *
- * This routine creates the edge table for
- * scan converting polygons.
- * The Edge Table (ET) looks like:
- *
- * EdgeTable
- * --------
- * | ymax | ScanLineLists
- * |scanline|-->------------>-------------->...
- * -------- |scanline| |scanline|
- * |edgelist| |edgelist|
- * --------- ---------
- * | |
- * | |
- * V V
- * list of ETEs list of ETEs
- *
- * where ETE is an EdgeTableEntry data structure,
- * and there is one ScanLineList per scanline at
- * which an edge is initially entered.
- *
- */
- Bool
- miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
- int count;
- DDXPointPtr pts;
- EdgeTable *ET;
- EdgeTableEntry *AET;
- EdgeTableEntry *pETEs;
- ScanLineListBlock *pSLLBlock;
- {
- DDXPointPtr top, bottom;
- DDXPointPtr PrevPt, CurrPt;
- int iSLLBlock = 0;
- int dy;
- if (count < 2) return TRUE;
- /*
- * initialize the Active Edge Table
- */
- AET->next = (EdgeTableEntry *)NULL;
- AET->back = (EdgeTableEntry *)NULL;
- AET->nextWETE = (EdgeTableEntry *)NULL;
- AET->bres.minor = MININT;
- /*
- * initialize the Edge Table.
- */
- ET->scanlines.next = (ScanLineList *)NULL;
- ET->ymax = MININT;
- ET->ymin = MAXINT;
- pSLLBlock->next = (ScanLineListBlock *)NULL;
- PrevPt = &pts[count-1];
- /*
- * for each vertex in the array of points.
- * In this loop we are dealing with two vertices at
- * a time -- these make up one edge of the polygon.
- */
- while (count--)
- {
- CurrPt = pts++;
- /*
- * find out which point is above and which is below.
- */
- if (PrevPt->y > CurrPt->y)
- {
- bottom = PrevPt, top = CurrPt;
- pETEs->ClockWise = 0;
- }
- else
- {
- bottom = CurrPt, top = PrevPt;
- pETEs->ClockWise = 1;
- }
- /*
- * don't add horizontal edges to the Edge table.
- */
- if (bottom->y != top->y)
- {
- pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
- /*
- * initialize integer edge algorithm
- */
- dy = bottom->y - top->y;
- BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
- if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock))
- {
- miFreeStorage(pSLLBlock->next);
- return FALSE;
- }
- ET->ymax = max(ET->ymax, PrevPt->y);
- ET->ymin = min(ET->ymin, PrevPt->y);
- pETEs++;
- }
- PrevPt = CurrPt;
- }
- return TRUE;
- }
- /*
- * loadAET
- *
- * This routine moves EdgeTableEntries from the
- * EdgeTable into the Active Edge Table,
- * leaving them sorted by smaller x coordinate.
- *
- */
- void
- miloadAET(AET, ETEs)
- EdgeTableEntry *AET, *ETEs;
- {
- EdgeTableEntry *pPrevAET;
- EdgeTableEntry *tmp;
- pPrevAET = AET;
- AET = AET->next;
- while (ETEs)
- {
- while (AET && (AET->bres.minor < ETEs->bres.minor))
- {
- pPrevAET = AET;
- AET = AET->next;
- }
- tmp = ETEs->next;
- ETEs->next = AET;
- if (AET)
- AET->back = ETEs;
- ETEs->back = pPrevAET;
- pPrevAET->next = ETEs;
- pPrevAET = ETEs;
- ETEs = tmp;
- }
- }
- /*
- * computeWAET
- *
- * This routine links the AET by the
- * nextWETE (winding EdgeTableEntry) link for
- * use by the winding number rule. The final
- * Active Edge Table (AET) might look something
- * like:
- *
- * AET
- * ---------- --------- ---------
- * |ymax | |ymax | |ymax |
- * | ... | |... | |... |
- * |next |->|next |->|next |->...
- * |nextWETE| |nextWETE| |nextWETE|
- * --------- --------- ^--------
- * | | |
- * V-------------------> V---> ...
- *
- */
- void
- micomputeWAET(AET)
- EdgeTableEntry *AET;
- {
- EdgeTableEntry *pWETE;
- int inside = 1;
- int isInside = 0;
- AET->nextWETE = (EdgeTableEntry *)NULL;
- pWETE = AET;
- AET = AET->next;
- while (AET)
- {
- if (AET->ClockWise)
- isInside++;
- else
- isInside--;
- if ((!inside && !isInside) ||
- ( inside && isInside))
- {
- pWETE->nextWETE = AET;
- pWETE = AET;
- inside = !inside;
- }
- AET = AET->next;
- }
- pWETE->nextWETE = (EdgeTableEntry *)NULL;
- }
- /*
- * InsertionSort
- *
- * Just a simple insertion sort using
- * pointers and back pointers to sort the Active
- * Edge Table.
- *
- */
- int
- miInsertionSort(AET)
- EdgeTableEntry *AET;
- {
- EdgeTableEntry *pETEchase;
- EdgeTableEntry *pETEinsert;
- EdgeTableEntry *pETEchaseBackTMP;
- int changed = 0;
- AET = AET->next;
- while (AET)
- {
- pETEinsert = AET;
- pETEchase = AET;
- while (pETEchase->back->bres.minor > AET->bres.minor)
- pETEchase = pETEchase->back;
- AET = AET->next;
- if (pETEchase != pETEinsert)
- {
- pETEchaseBackTMP = pETEchase->back;
- pETEinsert->back->next = AET;
- if (AET)
- AET->back = pETEinsert->back;
- pETEinsert->next = pETEchase;
- pETEchase->back->next = pETEinsert;
- pETEchase->back = pETEinsert;
- pETEinsert->back = pETEchaseBackTMP;
- changed = 1;
- }
- }
- return(changed);
- }
- /*
- * Clean up our act.
- */
- void
- miFreeStorage(pSLLBlock)
- ScanLineListBlock *pSLLBlock;
- {
- ScanLineListBlock *tmpSLLBlock;
- while (pSLLBlock)
- {
- tmpSLLBlock = pSLLBlock->next;
- free(pSLLBlock);
- pSLLBlock = tmpSLLBlock;
- }
- }
|