1/* 2 3Copyright 1987, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29 30/* 31 * fill.h 32 * 33 * Created by Brian Kelleher; Oct 1985 34 * 35 * Include file for filled polygon routines. 36 * 37 * These are the data structures needed to scan 38 * convert regions. Two different scan conversion 39 * methods are available -- the even-odd method, and 40 * the winding number method. 41 * The even-odd rule states that a point is inside 42 * the polygon if a ray drawn from that point in any 43 * direction will pass through an odd number of 44 * path segments. 45 * By the winding number rule, a point is decided 46 * to be inside the polygon if a ray drawn from that 47 * point in any direction passes through a different 48 * number of clockwise and counter-clockwise path 49 * segments. 50 * 51 * These data structures are adapted somewhat from 52 * the algorithm in (Foley/Van Dam) for scan converting 53 * polygons. 54 * The basic algorithm is to start at the top (smallest y) 55 * of the polygon, stepping down to the bottom of 56 * the polygon by incrementing the y coordinate. We 57 * keep a list of edges which the current scanline crosses, 58 * sorted by x. This list is called the Active Edge Table (AET) 59 * As we change the y-coordinate, we update each entry in 60 * in the active edge table to reflect the edges new xcoord. 61 * This list must be sorted at each scanline in case 62 * two edges intersect. 63 * We also keep a data structure known as the Edge Table (ET), 64 * which keeps track of all the edges which the current 65 * scanline has not yet reached. The ET is basically a 66 * list of ScanLineList structures containing a list of 67 * edges which are entered at a given scanline. There is one 68 * ScanLineList per scanline at which an edge is entered. 69 * When we enter a new edge, we move it from the ET to the AET. 70 * 71 * From the AET, we can implement the even-odd rule as in 72 * (Foley/Van Dam). 73 * The winding number rule is a little trickier. We also 74 * keep the EdgeTableEntries in the AET linked by the 75 * nextWETE (winding EdgeTableEntry) link. This allows 76 * the edges to be linked just as before for updating 77 * purposes, but only uses the edges linked by the nextWETE 78 * link as edges representing spans of the polygon to 79 * drawn (as with the even-odd rule). 80 */ 81 82/* 83 * for the winding number rule 84 */ 85#define CLOCKWISE 1 86#define COUNTERCLOCKWISE -1 87 88typedef struct _EdgeTableEntry { 89 int ymax; /* ycoord at which we exit this edge. */ 90 BRESINFO bres; /* Bresenham info to run the edge */ 91 struct _EdgeTableEntry *next; /* next in the list */ 92 struct _EdgeTableEntry *back; /* for insertion sort */ 93 struct _EdgeTableEntry *nextWETE; /* for winding num rule */ 94 int ClockWise; /* flag for winding number rule */ 95} EdgeTableEntry; 96 97 98typedef struct _ScanLineList{ 99 int scanline; /* the scanline represented */ 100 EdgeTableEntry *edgelist; /* header node */ 101 struct _ScanLineList *next; /* next in the list */ 102} ScanLineList; 103 104 105typedef struct { 106 int ymax; /* ymax for the polygon */ 107 int ymin; /* ymin for the polygon */ 108 ScanLineList scanlines; /* header node */ 109} EdgeTable; 110 111 112/* 113 * Here is a struct to help with storage allocation 114 * so we can allocate a big chunk at a time, and then take 115 * pieces from this heap when we need to. 116 */ 117#define SLLSPERBLOCK 25 118 119typedef struct _ScanLineListBlock { 120 ScanLineList SLLs[SLLSPERBLOCK]; 121 struct _ScanLineListBlock *next; 122} ScanLineListBlock; 123 124/* 125 * number of points to buffer before sending them off 126 * to scanlines() : Must be an even number 127 */ 128#define NUMPTSTOBUFFER 200 129 130 131/* 132 * 133 * a few macros for the inner loops of the fill code where 134 * performance considerations don't allow a procedure call. 135 * 136 * Evaluate the given edge at the given scanline. 137 * If the edge has expired, then we leave it and fix up 138 * the active edge table; otherwise, we increment the 139 * x value to be ready for the next scanline. 140 * The winding number rule is in effect, so we must notify 141 * the caller when the edge has been removed so he 142 * can reorder the Winding Active Edge Table. 143 */ 144#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \ 145 if (pAET->ymax == y) { /* leaving this edge */ \ 146 pPrevAET->next = pAET->next; \ 147 pAET = pPrevAET->next; \ 148 fixWAET = 1; \ 149 if (pAET) \ 150 pAET->back = pPrevAET; \ 151 } \ 152 else { \ 153 BRESINCRPGONSTRUCT(pAET->bres); \ 154 pPrevAET = pAET; \ 155 pAET = pAET->next; \ 156 } \ 157} 158 159 160/* 161 * Evaluate the given edge at the given scanline. 162 * If the edge has expired, then we leave it and fix up 163 * the active edge table; otherwise, we increment the 164 * x value to be ready for the next scanline. 165 * The even-odd rule is in effect. 166 */ 167#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \ 168 if (pAET->ymax == y) { /* leaving this edge */ \ 169 pPrevAET->next = pAET->next; \ 170 pAET = pPrevAET->next; \ 171 if (pAET) \ 172 pAET->back = pPrevAET; \ 173 } \ 174 else { \ 175 BRESINCRPGONSTRUCT(pAET->bres); \ 176 pPrevAET = pAET; \ 177 pAET = pAET->next; \ 178 } \ 179} 180 181/* mipolyutil.c */ 182 183extern _X_EXPORT Bool miCreateETandAET( 184 int /*count*/, 185 DDXPointPtr /*pts*/, 186 EdgeTable * /*ET*/, 187 EdgeTableEntry * /*AET*/, 188 EdgeTableEntry * /*pETEs*/, 189 ScanLineListBlock * /*pSLLBlock*/ 190); 191 192extern _X_EXPORT void miloadAET( 193 EdgeTableEntry * /*AET*/, 194 EdgeTableEntry * /*ETEs*/ 195); 196 197extern _X_EXPORT void micomputeWAET( 198 EdgeTableEntry * /*AET*/ 199); 200 201extern _X_EXPORT int miInsertionSort( 202 EdgeTableEntry * /*AET*/ 203); 204 205extern _X_EXPORT void miFreeStorage( 206 ScanLineListBlock * /*pSLLBlock*/ 207); 208