1
/* $XFree86: xc/programs/Xserver/mi/mipolyutil.c,v 1.9 2001/12/14 20:00:26 dawes Exp $ */
2
/***********************************************************
4
Copyright 1987, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of The Open Group shall not be
23
used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from The Open Group.
27
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
31
Permission to use, copy, modify, and distribute this software and its
32
documentation for any purpose and without fee is hereby granted,
33
provided that the above copyright notice appear in all copies and that
34
both that copyright notice and this permission notice appear in
35
supporting documentation, and that the name of Digital not be
36
used in advertising or publicity pertaining to distribution of the
37
software without specific, written prior permission.
39
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47
******************************************************************/
48
/* $Xorg: mipolyutil.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */
49
#include "miscstruct.h"
51
#include "miscanfill.h"
53
#include "misc.h" /* MAXINT */
58
* Written by Brian Kelleher; Oct. 1985
60
* This module contains all of the utility functions
61
* needed to scan convert a polygon.
68
* Insert the given edge into the edge table.
69
* First we must find the correct bucket in the
70
* Edge table, then find the right slot in the
71
* bucket. Finally, we can insert it.
75
miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
79
ScanLineListBlock **SLLBlock;
82
register EdgeTableEntry *start, *prev;
83
register ScanLineList *pSLL, *pPrevSLL;
84
ScanLineListBlock *tmpSLLBlock;
87
* find the right bucket to put the edge into
89
pPrevSLL = &ET->scanlines;
90
pSLL = pPrevSLL->next;
91
while (pSLL && (pSLL->scanline < scanline))
98
* reassign pSLL (pointer to ScanLineList) if necessary
100
if ((!pSLL) || (pSLL->scanline > scanline))
102
if (*iSLLBlock > SLLSPERBLOCK-1)
105
(ScanLineListBlock *)xalloc(sizeof(ScanLineListBlock));
108
(*SLLBlock)->next = tmpSLLBlock;
109
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
110
*SLLBlock = tmpSLLBlock;
113
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
115
pSLL->next = pPrevSLL->next;
116
pSLL->edgelist = (EdgeTableEntry *)NULL;
117
pPrevSLL->next = pSLL;
119
pSLL->scanline = scanline;
122
* now insert the edge in the right bucket
124
prev = (EdgeTableEntry *)NULL;
125
start = pSLL->edgelist;
126
while (start && (start->bres.minor < ETE->bres.minor))
136
pSLL->edgelist = ETE;
143
* This routine creates the edge table for
144
* scan converting polygons.
145
* The Edge Table (ET) looks like:
149
* | ymax | ScanLineLists
150
* |scanline|-->------------>-------------->...
151
* -------- |scanline| |scanline|
152
* |edgelist| |edgelist|
153
* --------- ---------
157
* list of ETEs list of ETEs
159
* where ETE is an EdgeTableEntry data structure,
160
* and there is one ScanLineList per scanline at
161
* which an edge is initially entered.
166
miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
168
register DDXPointPtr pts;
171
register EdgeTableEntry *pETEs;
172
ScanLineListBlock *pSLLBlock;
174
register DDXPointPtr top, bottom;
175
register DDXPointPtr PrevPt, CurrPt;
180
if (count < 2) return TRUE;
183
* initialize the Active Edge Table
185
AET->next = (EdgeTableEntry *)NULL;
186
AET->back = (EdgeTableEntry *)NULL;
187
AET->nextWETE = (EdgeTableEntry *)NULL;
188
AET->bres.minor = MININT;
191
* initialize the Edge Table.
193
ET->scanlines.next = (ScanLineList *)NULL;
196
pSLLBlock->next = (ScanLineListBlock *)NULL;
198
PrevPt = &pts[count-1];
201
* for each vertex in the array of points.
202
* In this loop we are dealing with two vertices at
203
* a time -- these make up one edge of the polygon.
210
* find out which point is above and which is below.
212
if (PrevPt->y > CurrPt->y)
214
bottom = PrevPt, top = CurrPt;
215
pETEs->ClockWise = 0;
219
bottom = CurrPt, top = PrevPt;
220
pETEs->ClockWise = 1;
224
* don't add horizontal edges to the Edge table.
226
if (bottom->y != top->y)
228
pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
231
* initialize integer edge algorithm
233
dy = bottom->y - top->y;
234
BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
236
if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock))
238
miFreeStorage(pSLLBlock->next);
242
ET->ymax = max(ET->ymax, PrevPt->y);
243
ET->ymin = min(ET->ymin, PrevPt->y);
255
* This routine moves EdgeTableEntries from the
256
* EdgeTable into the Active Edge Table,
257
* leaving them sorted by smaller x coordinate.
263
register EdgeTableEntry *AET, *ETEs;
265
register EdgeTableEntry *pPrevAET;
266
register EdgeTableEntry *tmp;
272
while (AET && (AET->bres.minor < ETEs->bres.minor))
281
ETEs->back = pPrevAET;
282
pPrevAET->next = ETEs;
292
* This routine links the AET by the
293
* nextWETE (winding EdgeTableEntry) link for
294
* use by the winding number rule. The final
295
* Active Edge Table (AET) might look something
299
* ---------- --------- ---------
300
* |ymax | |ymax | |ymax |
301
* | ... | |... | |... |
302
* |next |->|next |->|next |->...
303
* |nextWETE| |nextWETE| |nextWETE|
304
* --------- --------- ^--------
306
* V-------------------> V---> ...
311
register EdgeTableEntry *AET;
313
register EdgeTableEntry *pWETE;
314
register int inside = 1;
315
register int isInside = 0;
317
AET->nextWETE = (EdgeTableEntry *)NULL;
327
if ((!inside && !isInside) ||
328
( inside && isInside))
330
pWETE->nextWETE = AET;
336
pWETE->nextWETE = (EdgeTableEntry *)NULL;
342
* Just a simple insertion sort using
343
* pointers and back pointers to sort the Active
350
register EdgeTableEntry *AET;
352
register EdgeTableEntry *pETEchase;
353
register EdgeTableEntry *pETEinsert;
354
register EdgeTableEntry *pETEchaseBackTMP;
355
register int changed = 0;
362
while (pETEchase->back->bres.minor > AET->bres.minor)
363
pETEchase = pETEchase->back;
366
if (pETEchase != pETEinsert)
368
pETEchaseBackTMP = pETEchase->back;
369
pETEinsert->back->next = AET;
371
AET->back = pETEinsert->back;
372
pETEinsert->next = pETEchase;
373
pETEchase->back->next = pETEinsert;
374
pETEchase->back = pETEinsert;
375
pETEinsert->back = pETEchaseBackTMP;
386
miFreeStorage(pSLLBlock)
387
register ScanLineListBlock *pSLLBlock;
389
register ScanLineListBlock *tmpSLLBlock;
393
tmpSLLBlock = pSLLBlock->next;
395
pSLLBlock = tmpSLLBlock;