| 1 | /* $Id: region.h,v 1.1 1999-05-24 20:19:18 ktk Exp $ */ | 
|---|
| 2 |  | 
|---|
| 3 | /* | 
|---|
| 4 | * GDI region definitions | 
|---|
| 5 | * Mainly taken from the X11 distribution. | 
|---|
| 6 | * Modifications: Copyright 1998 Huw Davies | 
|---|
| 7 | */ | 
|---|
| 8 |  | 
|---|
| 9 | /************************************************************************ | 
|---|
| 10 |  | 
|---|
| 11 | Copyright (c) 1987  X Consortium | 
|---|
| 12 |  | 
|---|
| 13 | Permission is hereby granted, free of charge, to any person obtaining a copy | 
|---|
| 14 | of this software and associated documentation files (the "Software"), to deal | 
|---|
| 15 | in the Software without restriction, including without limitation the rights | 
|---|
| 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
|---|
| 17 | copies of the Software, and to permit persons to whom the Software is | 
|---|
| 18 | furnished to do so, subject to the following conditions: | 
|---|
| 19 |  | 
|---|
| 20 | The above copyright notice and this permission notice shall be included in | 
|---|
| 21 | all copies or substantial portions of the Software. | 
|---|
| 22 |  | 
|---|
| 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
|---|
| 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
|---|
| 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE | 
|---|
| 26 | X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | 
|---|
| 27 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 
|---|
| 28 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 
|---|
| 29 |  | 
|---|
| 30 | Except as contained in this notice, the name of the X Consortium shall not be | 
|---|
| 31 | used in advertising or otherwise to promote the sale, use or other dealings | 
|---|
| 32 | in this Software without prior written authorization from the X Consortium. | 
|---|
| 33 |  | 
|---|
| 34 |  | 
|---|
| 35 | Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. | 
|---|
| 36 |  | 
|---|
| 37 | All Rights Reserved | 
|---|
| 38 |  | 
|---|
| 39 | Permission to use, copy, modify, and distribute this software and its | 
|---|
| 40 | documentation for any purpose and without fee is hereby granted, | 
|---|
| 41 | provided that the above copyright notice appear in all copies and that | 
|---|
| 42 | both that copyright notice and this permission notice appear in | 
|---|
| 43 | supporting documentation, and that the name of Digital not be | 
|---|
| 44 | used in advertising or publicity pertaining to distribution of the | 
|---|
| 45 | software without specific, written prior permission. | 
|---|
| 46 |  | 
|---|
| 47 | DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | 
|---|
| 48 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | 
|---|
| 49 | DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | 
|---|
| 50 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | 
|---|
| 51 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | 
|---|
| 52 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | 
|---|
| 53 | SOFTWARE. | 
|---|
| 54 |  | 
|---|
| 55 | ************************************************************************/ | 
|---|
| 56 | #ifndef __WINE_REGION_H | 
|---|
| 57 | #define __WINE_REGION_H | 
|---|
| 58 |  | 
|---|
| 59 | #include "wingdi.h" | 
|---|
| 60 | #include "gdi.h" | 
|---|
| 61 |  | 
|---|
| 62 |  | 
|---|
| 63 | typedef struct { | 
|---|
| 64 | INT size; | 
|---|
| 65 | INT numRects; | 
|---|
| 66 | INT type; /* NULL, SIMPLE or COMPLEX */ | 
|---|
| 67 | RECT *rects; | 
|---|
| 68 | RECT extents; | 
|---|
| 69 | } WINEREGION; | 
|---|
| 70 |  | 
|---|
| 71 | /* GDI logical region object */ | 
|---|
| 72 | typedef struct | 
|---|
| 73 | { | 
|---|
| 74 | GDIOBJHDR   header; | 
|---|
| 75 | WINEREGION  *rgn; | 
|---|
| 76 | } RGNOBJ; | 
|---|
| 77 |  | 
|---|
| 78 | /*  1 if two RECTs overlap. | 
|---|
| 79 | *  0 if two RECTs do not overlap. | 
|---|
| 80 | */ | 
|---|
| 81 | #define EXTENTCHECK(r1, r2) \ | 
|---|
| 82 | ((r1)->right > (r2)->left && \ | 
|---|
| 83 | (r1)->left < (r2)->right && \ | 
|---|
| 84 | (r1)->bottom > (r2)->top && \ | 
|---|
| 85 | (r1)->top < (r2)->bottom) | 
|---|
| 86 |  | 
|---|
| 87 | /* | 
|---|
| 88 | *   Check to see if there is enough memory in the present region. | 
|---|
| 89 | */ | 
|---|
| 90 | #define MEMCHECK(reg, rect, firstrect){\ | 
|---|
| 91 | if ((reg)->numRects >= ((reg)->size - 1)){\ | 
|---|
| 92 | (firstrect) = HeapReAlloc( SystemHeap, 0, \ | 
|---|
| 93 | (firstrect), (2 * (sizeof(RECT)) * ((reg)->size)));\ | 
|---|
| 94 | if ((firstrect) == 0)\ | 
|---|
| 95 | return;\ | 
|---|
| 96 | (reg)->size *= 2;\ | 
|---|
| 97 | (rect) = &(firstrect)[(reg)->numRects];\ | 
|---|
| 98 | }\ | 
|---|
| 99 | } | 
|---|
| 100 |  | 
|---|
| 101 | #define EMPTY_REGION(pReg) { \ | 
|---|
| 102 | (pReg)->numRects = 0; \ | 
|---|
| 103 | (pReg)->extents.left = (pReg)->extents.top = 0; \ | 
|---|
| 104 | (pReg)->extents.right = (pReg)->extents.bottom = 0; \ | 
|---|
| 105 | (pReg)->type = NULLREGION; \ | 
|---|
| 106 | } | 
|---|
| 107 |  | 
|---|
| 108 | #define REGION_NOT_EMPTY(pReg) pReg->numRects | 
|---|
| 109 |  | 
|---|
| 110 | #define INRECT(r, x, y) \ | 
|---|
| 111 | ( ( ((r).right >  x)) && \ | 
|---|
| 112 | ( ((r).left <= x)) && \ | 
|---|
| 113 | ( ((r).bottom >  y)) && \ | 
|---|
| 114 | ( ((r).top <= y)) ) | 
|---|
| 115 |  | 
|---|
| 116 |  | 
|---|
| 117 | /* | 
|---|
| 118 | * number of points to buffer before sending them off | 
|---|
| 119 | * to scanlines() :  Must be an even number | 
|---|
| 120 | */ | 
|---|
| 121 | #define NUMPTSTOBUFFER 200 | 
|---|
| 122 |  | 
|---|
| 123 | /* | 
|---|
| 124 | * used to allocate buffers for points and link | 
|---|
| 125 | * the buffers together | 
|---|
| 126 | */ | 
|---|
| 127 |  | 
|---|
| 128 | typedef struct _POINTBLOCK { | 
|---|
| 129 | POINT pts[NUMPTSTOBUFFER]; | 
|---|
| 130 | struct _POINTBLOCK *next; | 
|---|
| 131 | } POINTBLOCK; | 
|---|
| 132 |  | 
|---|
| 133 |  | 
|---|
| 134 |  | 
|---|
| 135 | /* | 
|---|
| 136 | *     This file contains a few macros to help track | 
|---|
| 137 | *     the edge of a filled object.  The object is assumed | 
|---|
| 138 | *     to be filled in scanline order, and thus the | 
|---|
| 139 | *     algorithm used is an extension of Bresenham's line | 
|---|
| 140 | *     drawing algorithm which assumes that y is always the | 
|---|
| 141 | *     major axis. | 
|---|
| 142 | *     Since these pieces of code are the same for any filled shape, | 
|---|
| 143 | *     it is more convenient to gather the library in one | 
|---|
| 144 | *     place, but since these pieces of code are also in | 
|---|
| 145 | *     the inner loops of output primitives, procedure call | 
|---|
| 146 | *     overhead is out of the question. | 
|---|
| 147 | *     See the author for a derivation if needed. | 
|---|
| 148 | */ | 
|---|
| 149 |  | 
|---|
| 150 |  | 
|---|
| 151 | /* | 
|---|
| 152 | *  In scan converting polygons, we want to choose those pixels | 
|---|
| 153 | *  which are inside the polygon.  Thus, we add .5 to the starting | 
|---|
| 154 | *  x coordinate for both left and right edges.  Now we choose the | 
|---|
| 155 | *  first pixel which is inside the pgon for the left edge and the | 
|---|
| 156 | *  first pixel which is outside the pgon for the right edge. | 
|---|
| 157 | *  Draw the left pixel, but not the right. | 
|---|
| 158 | * | 
|---|
| 159 | *  How to add .5 to the starting x coordinate: | 
|---|
| 160 | *      If the edge is moving to the right, then subtract dy from the | 
|---|
| 161 | *  error term from the general form of the algorithm. | 
|---|
| 162 | *      If the edge is moving to the left, then add dy to the error term. | 
|---|
| 163 | * | 
|---|
| 164 | *  The reason for the difference between edges moving to the left | 
|---|
| 165 | *  and edges moving to the right is simple:  If an edge is moving | 
|---|
| 166 | *  to the right, then we want the algorithm to flip immediately. | 
|---|
| 167 | *  If it is moving to the left, then we don't want it to flip until | 
|---|
| 168 | *  we traverse an entire pixel. | 
|---|
| 169 | */ | 
|---|
| 170 | #define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \ | 
|---|
| 171 | int dx;      /* local storage */ \ | 
|---|
| 172 | \ | 
|---|
| 173 | /* \ | 
|---|
| 174 | *  if the edge is horizontal, then it is ignored \ | 
|---|
| 175 | *  and assumed not to be processed.  Otherwise, do this stuff. \ | 
|---|
| 176 | */ \ | 
|---|
| 177 | if ((dy) != 0) { \ | 
|---|
| 178 | xStart = (x1); \ | 
|---|
| 179 | dx = (x2) - xStart; \ | 
|---|
| 180 | if (dx < 0) { \ | 
|---|
| 181 | m = dx / (dy); \ | 
|---|
| 182 | m1 = m - 1; \ | 
|---|
| 183 | incr1 = -2 * dx + 2 * (dy) * m1; \ | 
|---|
| 184 | incr2 = -2 * dx + 2 * (dy) * m; \ | 
|---|
| 185 | d = 2 * m * (dy) - 2 * dx - 2 * (dy); \ | 
|---|
| 186 | } else { \ | 
|---|
| 187 | m = dx / (dy); \ | 
|---|
| 188 | m1 = m + 1; \ | 
|---|
| 189 | incr1 = 2 * dx - 2 * (dy) * m1; \ | 
|---|
| 190 | incr2 = 2 * dx - 2 * (dy) * m; \ | 
|---|
| 191 | d = -2 * m * (dy) + 2 * dx; \ | 
|---|
| 192 | } \ | 
|---|
| 193 | } \ | 
|---|
| 194 | } | 
|---|
| 195 |  | 
|---|
| 196 | #define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \ | 
|---|
| 197 | if (m1 > 0) { \ | 
|---|
| 198 | if (d > 0) { \ | 
|---|
| 199 | minval += m1; \ | 
|---|
| 200 | d += incr1; \ | 
|---|
| 201 | } \ | 
|---|
| 202 | else { \ | 
|---|
| 203 | minval += m; \ | 
|---|
| 204 | d += incr2; \ | 
|---|
| 205 | } \ | 
|---|
| 206 | } else {\ | 
|---|
| 207 | if (d >= 0) { \ | 
|---|
| 208 | minval += m1; \ | 
|---|
| 209 | d += incr1; \ | 
|---|
| 210 | } \ | 
|---|
| 211 | else { \ | 
|---|
| 212 | minval += m; \ | 
|---|
| 213 | d += incr2; \ | 
|---|
| 214 | } \ | 
|---|
| 215 | } \ | 
|---|
| 216 | } | 
|---|
| 217 |  | 
|---|
| 218 | /* | 
|---|
| 219 | *     This structure contains all of the information needed | 
|---|
| 220 | *     to run the bresenham algorithm. | 
|---|
| 221 | *     The variables may be hardcoded into the declarations | 
|---|
| 222 | *     instead of using this structure to make use of | 
|---|
| 223 | *     register declarations. | 
|---|
| 224 | */ | 
|---|
| 225 | typedef struct { | 
|---|
| 226 | INT minor_axis;     /* minor axis        */ | 
|---|
| 227 | INT d;              /* decision variable */ | 
|---|
| 228 | INT m, m1;          /* slope and slope+1 */ | 
|---|
| 229 | INT incr1, incr2;   /* error increments */ | 
|---|
| 230 | } BRESINFO; | 
|---|
| 231 |  | 
|---|
| 232 |  | 
|---|
| 233 | #define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \ | 
|---|
| 234 | BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \ | 
|---|
| 235 | bres.m, bres.m1, bres.incr1, bres.incr2) | 
|---|
| 236 |  | 
|---|
| 237 | #define BRESINCRPGONSTRUCT(bres) \ | 
|---|
| 238 | BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2) | 
|---|
| 239 |  | 
|---|
| 240 |  | 
|---|
| 241 |  | 
|---|
| 242 | /* | 
|---|
| 243 | *     These are the data structures needed to scan | 
|---|
| 244 | *     convert regions.  Two different scan conversion | 
|---|
| 245 | *     methods are available -- the even-odd method, and | 
|---|
| 246 | *     the winding number method. | 
|---|
| 247 | *     The even-odd rule states that a point is inside | 
|---|
| 248 | *     the polygon if a ray drawn from that point in any | 
|---|
| 249 | *     direction will pass through an odd number of | 
|---|
| 250 | *     path segments. | 
|---|
| 251 | *     By the winding number rule, a point is decided | 
|---|
| 252 | *     to be inside the polygon if a ray drawn from that | 
|---|
| 253 | *     point in any direction passes through a different | 
|---|
| 254 | *     number of clockwise and counter-clockwise path | 
|---|
| 255 | *     segments. | 
|---|
| 256 | * | 
|---|
| 257 | *     These data structures are adapted somewhat from | 
|---|
| 258 | *     the algorithm in (Foley/Van Dam) for scan converting | 
|---|
| 259 | *     polygons. | 
|---|
| 260 | *     The basic algorithm is to start at the top (smallest y) | 
|---|
| 261 | *     of the polygon, stepping down to the bottom of | 
|---|
| 262 | *     the polygon by incrementing the y coordinate.  We | 
|---|
| 263 | *     keep a list of edges which the current scanline crosses, | 
|---|
| 264 | *     sorted by x.  This list is called the Active Edge Table (AET) | 
|---|
| 265 | *     As we change the y-coordinate, we update each entry in | 
|---|
| 266 | *     in the active edge table to reflect the edges new xcoord. | 
|---|
| 267 | *     This list must be sorted at each scanline in case | 
|---|
| 268 | *     two edges intersect. | 
|---|
| 269 | *     We also keep a data structure known as the Edge Table (ET), | 
|---|
| 270 | *     which keeps track of all the edges which the current | 
|---|
| 271 | *     scanline has not yet reached.  The ET is basically a | 
|---|
| 272 | *     list of ScanLineList structures containing a list of | 
|---|
| 273 | *     edges which are entered at a given scanline.  There is one | 
|---|
| 274 | *     ScanLineList per scanline at which an edge is entered. | 
|---|
| 275 | *     When we enter a new edge, we move it from the ET to the AET. | 
|---|
| 276 | * | 
|---|
| 277 | *     From the AET, we can implement the even-odd rule as in | 
|---|
| 278 | *     (Foley/Van Dam). | 
|---|
| 279 | *     The winding number rule is a little trickier.  We also | 
|---|
| 280 | *     keep the EdgeTableEntries in the AET linked by the | 
|---|
| 281 | *     nextWETE (winding EdgeTableEntry) link.  This allows | 
|---|
| 282 | *     the edges to be linked just as before for updating | 
|---|
| 283 | *     purposes, but only uses the edges linked by the nextWETE | 
|---|
| 284 | *     link as edges representing spans of the polygon to | 
|---|
| 285 | *     drawn (as with the even-odd rule). | 
|---|
| 286 | */ | 
|---|
| 287 |  | 
|---|
| 288 | /* | 
|---|
| 289 | * for the winding number rule | 
|---|
| 290 | */ | 
|---|
| 291 | #define CLOCKWISE          1 | 
|---|
| 292 | #define COUNTERCLOCKWISE  -1 | 
|---|
| 293 |  | 
|---|
| 294 | typedef struct _EdgeTableEntry { | 
|---|
| 295 | INT ymax;           /* ycoord at which we exit this edge. */ | 
|---|
| 296 | BRESINFO bres;        /* Bresenham info to run the edge     */ | 
|---|
| 297 | struct _EdgeTableEntry *next;       /* next in the list     */ | 
|---|
| 298 | struct _EdgeTableEntry *back;       /* for insertion sort   */ | 
|---|
| 299 | struct _EdgeTableEntry *nextWETE;   /* for winding num rule */ | 
|---|
| 300 | int ClockWise;        /* flag for winding number rule       */ | 
|---|
| 301 | } EdgeTableEntry; | 
|---|
| 302 |  | 
|---|
| 303 |  | 
|---|
| 304 | typedef struct _ScanLineList{ | 
|---|
| 305 | INT scanline;            /* the scanline represented */ | 
|---|
| 306 | EdgeTableEntry *edgelist;  /* header node              */ | 
|---|
| 307 | struct _ScanLineList *next;  /* next in the list       */ | 
|---|
| 308 | } ScanLineList; | 
|---|
| 309 |  | 
|---|
| 310 |  | 
|---|
| 311 | typedef struct { | 
|---|
| 312 | INT ymax;               /* ymax for the polygon     */ | 
|---|
| 313 | INT ymin;               /* ymin for the polygon     */ | 
|---|
| 314 | ScanLineList scanlines;   /* header node              */ | 
|---|
| 315 | } EdgeTable; | 
|---|
| 316 |  | 
|---|
| 317 |  | 
|---|
| 318 | /* | 
|---|
| 319 | * Here is a struct to help with storage allocation | 
|---|
| 320 | * so we can allocate a big chunk at a time, and then take | 
|---|
| 321 | * pieces from this heap when we need to. | 
|---|
| 322 | */ | 
|---|
| 323 | #define SLLSPERBLOCK 25 | 
|---|
| 324 |  | 
|---|
| 325 | typedef struct _ScanLineListBlock { | 
|---|
| 326 | ScanLineList SLLs[SLLSPERBLOCK]; | 
|---|
| 327 | struct _ScanLineListBlock *next; | 
|---|
| 328 | } ScanLineListBlock; | 
|---|
| 329 |  | 
|---|
| 330 |  | 
|---|
| 331 | /* | 
|---|
| 332 | * | 
|---|
| 333 | *     a few macros for the inner loops of the fill code where | 
|---|
| 334 | *     performance considerations don't allow a procedure call. | 
|---|
| 335 | * | 
|---|
| 336 | *     Evaluate the given edge at the given scanline. | 
|---|
| 337 | *     If the edge has expired, then we leave it and fix up | 
|---|
| 338 | *     the active edge table; otherwise, we increment the | 
|---|
| 339 | *     x value to be ready for the next scanline. | 
|---|
| 340 | *     The winding number rule is in effect, so we must notify | 
|---|
| 341 | *     the caller when the edge has been removed so he | 
|---|
| 342 | *     can reorder the Winding Active Edge Table. | 
|---|
| 343 | */ | 
|---|
| 344 | #define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \ | 
|---|
| 345 | if (pAET->ymax == y) {          /* leaving this edge */ \ | 
|---|
| 346 | pPrevAET->next = pAET->next; \ | 
|---|
| 347 | pAET = pPrevAET->next; \ | 
|---|
| 348 | fixWAET = 1; \ | 
|---|
| 349 | if (pAET) \ | 
|---|
| 350 | pAET->back = pPrevAET; \ | 
|---|
| 351 | } \ | 
|---|
| 352 | else { \ | 
|---|
| 353 | BRESINCRPGONSTRUCT(pAET->bres); \ | 
|---|
| 354 | pPrevAET = pAET; \ | 
|---|
| 355 | pAET = pAET->next; \ | 
|---|
| 356 | } \ | 
|---|
| 357 | } | 
|---|
| 358 |  | 
|---|
| 359 |  | 
|---|
| 360 | /* | 
|---|
| 361 | *     Evaluate the given edge at the given scanline. | 
|---|
| 362 | *     If the edge has expired, then we leave it and fix up | 
|---|
| 363 | *     the active edge table; otherwise, we increment the | 
|---|
| 364 | *     x value to be ready for the next scanline. | 
|---|
| 365 | *     The even-odd rule is in effect. | 
|---|
| 366 | */ | 
|---|
| 367 | #define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \ | 
|---|
| 368 | if (pAET->ymax == y) {          /* leaving this edge */ \ | 
|---|
| 369 | pPrevAET->next = pAET->next; \ | 
|---|
| 370 | pAET = pPrevAET->next; \ | 
|---|
| 371 | if (pAET) \ | 
|---|
| 372 | pAET->back = pPrevAET; \ | 
|---|
| 373 | } \ | 
|---|
| 374 | else { \ | 
|---|
| 375 | BRESINCRPGONSTRUCT(pAET->bres); \ | 
|---|
| 376 | pPrevAET = pAET; \ | 
|---|
| 377 | pAET = pAET->next; \ | 
|---|
| 378 | } \ | 
|---|
| 379 | } | 
|---|
| 380 |  | 
|---|
| 381 | extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj ); | 
|---|
| 382 | extern BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect ); | 
|---|
| 383 | extern HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt ); | 
|---|
| 384 | extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y ); | 
|---|
| 385 | extern BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc ); | 
|---|
| 386 |  | 
|---|
| 387 | #endif  /* __WINE_REGION_H */ | 
|---|
| 388 |  | 
|---|
| 389 |  | 
|---|