1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
47 #ifdef HAVE_DIX_CONFIG_H
48 #include <dix-config.h>
51 #include "regionstr.h"
53 #include "miscanfill.h"
55 #include "misc.h" /* MAXINT */
60 * Written by Brian Kelleher; Oct. 1985
62 * This module contains all of the utility functions
63 * needed to scan convert a polygon.
70 * Insert the given edge into the edge table.
71 * First we must find the correct bucket in the
72 * Edge table, then find the right slot in the
73 * bucket. Finally, we can insert it.
77 miInsertEdgeInET(EdgeTable
*ET
, EdgeTableEntry
*ETE
, int scanline
,
78 ScanLineListBlock
**SLLBlock
, int *iSLLBlock
)
80 EdgeTableEntry
*start
, *prev
;
81 ScanLineList
*pSLL
, *pPrevSLL
;
82 ScanLineListBlock
*tmpSLLBlock
;
85 * find the right bucket to put the edge into
87 pPrevSLL
= &ET
->scanlines
;
88 pSLL
= pPrevSLL
->next
;
89 while (pSLL
&& (pSLL
->scanline
< scanline
))
96 * reassign pSLL (pointer to ScanLineList) if necessary
98 if ((!pSLL
) || (pSLL
->scanline
> scanline
))
100 if (*iSLLBlock
> SLLSPERBLOCK
-1)
103 (ScanLineListBlock
*)xalloc(sizeof(ScanLineListBlock
));
106 (*SLLBlock
)->next
= tmpSLLBlock
;
107 tmpSLLBlock
->next
= (ScanLineListBlock
*)NULL
;
108 *SLLBlock
= tmpSLLBlock
;
111 pSLL
= &((*SLLBlock
)->SLLs
[(*iSLLBlock
)++]);
113 pSLL
->next
= pPrevSLL
->next
;
114 pSLL
->edgelist
= (EdgeTableEntry
*)NULL
;
115 pPrevSLL
->next
= pSLL
;
117 pSLL
->scanline
= scanline
;
120 * now insert the edge in the right bucket
122 prev
= (EdgeTableEntry
*)NULL
;
123 start
= pSLL
->edgelist
;
124 while (start
&& (start
->bres
.minor
< ETE
->bres
.minor
))
134 pSLL
->edgelist
= ETE
;
141 * This routine creates the edge table for
142 * scan converting polygons.
143 * The Edge Table (ET) looks like:
147 * | ymax | ScanLineLists
148 * |scanline|-->------------>-------------->...
149 * -------- |scanline| |scanline|
150 * |edgelist| |edgelist|
151 * --------- ---------
155 * list of ETEs list of ETEs
157 * where ETE is an EdgeTableEntry data structure,
158 * and there is one ScanLineList per scanline at
159 * which an edge is initially entered.
164 miCreateETandAET(count
, pts
, ET
, AET
, pETEs
, pSLLBlock
)
169 EdgeTableEntry
*pETEs
;
170 ScanLineListBlock
*pSLLBlock
;
172 DDXPointPtr top
, bottom
;
173 DDXPointPtr PrevPt
, CurrPt
;
178 if (count
< 2) return TRUE
;
181 * initialize the Active Edge Table
183 AET
->next
= (EdgeTableEntry
*)NULL
;
184 AET
->back
= (EdgeTableEntry
*)NULL
;
185 AET
->nextWETE
= (EdgeTableEntry
*)NULL
;
186 AET
->bres
.minor
= MININT
;
189 * initialize the Edge Table.
191 ET
->scanlines
.next
= (ScanLineList
*)NULL
;
194 pSLLBlock
->next
= (ScanLineListBlock
*)NULL
;
196 PrevPt
= &pts
[count
-1];
199 * for each vertex in the array of points.
200 * In this loop we are dealing with two vertices at
201 * a time -- these make up one edge of the polygon.
208 * find out which point is above and which is below.
210 if (PrevPt
->y
> CurrPt
->y
)
212 bottom
= PrevPt
, top
= CurrPt
;
213 pETEs
->ClockWise
= 0;
217 bottom
= CurrPt
, top
= PrevPt
;
218 pETEs
->ClockWise
= 1;
222 * don't add horizontal edges to the Edge table.
224 if (bottom
->y
!= top
->y
)
226 pETEs
->ymax
= bottom
->y
-1; /* -1 so we don't get last scanline */
229 * initialize integer edge algorithm
231 dy
= bottom
->y
- top
->y
;
232 BRESINITPGONSTRUCT(dy
, top
->x
, bottom
->x
, pETEs
->bres
);
234 if (!miInsertEdgeInET(ET
, pETEs
, top
->y
, &pSLLBlock
, &iSLLBlock
))
236 miFreeStorage(pSLLBlock
->next
);
240 ET
->ymax
= max(ET
->ymax
, PrevPt
->y
);
241 ET
->ymin
= min(ET
->ymin
, PrevPt
->y
);
253 * This routine moves EdgeTableEntries from the
254 * EdgeTable into the Active Edge Table,
255 * leaving them sorted by smaller x coordinate.
261 EdgeTableEntry
*AET
, *ETEs
;
263 EdgeTableEntry
*pPrevAET
;
270 while (AET
&& (AET
->bres
.minor
< ETEs
->bres
.minor
))
279 ETEs
->back
= pPrevAET
;
280 pPrevAET
->next
= ETEs
;
290 * This routine links the AET by the
291 * nextWETE (winding EdgeTableEntry) link for
292 * use by the winding number rule. The final
293 * Active Edge Table (AET) might look something
297 * ---------- --------- ---------
298 * |ymax | |ymax | |ymax |
299 * | ... | |... | |... |
300 * |next |->|next |->|next |->...
301 * |nextWETE| |nextWETE| |nextWETE|
302 * --------- --------- ^--------
304 * V-------------------> V---> ...
311 EdgeTableEntry
*pWETE
;
315 AET
->nextWETE
= (EdgeTableEntry
*)NULL
;
325 if ((!inside
&& !isInside
) ||
326 ( inside
&& isInside
))
328 pWETE
->nextWETE
= AET
;
334 pWETE
->nextWETE
= (EdgeTableEntry
*)NULL
;
340 * Just a simple insertion sort using
341 * pointers and back pointers to sort the Active
350 EdgeTableEntry
*pETEchase
;
351 EdgeTableEntry
*pETEinsert
;
352 EdgeTableEntry
*pETEchaseBackTMP
;
360 while (pETEchase
->back
->bres
.minor
> AET
->bres
.minor
)
361 pETEchase
= pETEchase
->back
;
364 if (pETEchase
!= pETEinsert
)
366 pETEchaseBackTMP
= pETEchase
->back
;
367 pETEinsert
->back
->next
= AET
;
369 AET
->back
= pETEinsert
->back
;
370 pETEinsert
->next
= pETEchase
;
371 pETEchase
->back
->next
= pETEinsert
;
372 pETEchase
->back
= pETEinsert
;
373 pETEinsert
->back
= pETEchaseBackTMP
;
384 miFreeStorage(pSLLBlock
)
385 ScanLineListBlock
*pSLLBlock
;
387 ScanLineListBlock
*tmpSLLBlock
;
391 tmpSLLBlock
= pSLLBlock
->next
;
393 pSLLBlock
= tmpSLLBlock
;