| 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 | 
 | 
|---|