Release 971221
[wine.git] / objects / region.c
blob65951eaf2e4d2f79f3a3ada3e8410febcf532375
1 /*
2 * GDI region objects
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
6 * RGNOBJ is documented in the Dr. Dobbs Journal March 1993.
7 */
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include "region.h"
12 #include "stddebug.h"
13 #include "debug.h"
16 /***********************************************************************
17 * REGION_DeleteObject
19 BOOL32 REGION_DeleteObject( HRGN32 hrgn, RGNOBJ * obj )
21 dprintf_region(stddeb, "DeleteRegion: %04x\n", hrgn );
22 if (obj->xrgn) XDestroyRegion( obj->xrgn );
23 return GDI_FreeObject( hrgn );
27 /***********************************************************************
28 * OffsetRgn16 (GDI.101)
30 INT16 WINAPI OffsetRgn16( HRGN16 hrgn, INT16 x, INT16 y )
32 return OffsetRgn32( hrgn, x, y );
36 /***********************************************************************
37 * OffsetRgn32 (GDI32.256)
39 INT32 WINAPI OffsetRgn32( HRGN32 hrgn, INT32 x, INT32 y )
41 RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
43 if (obj)
45 INT32 ret;
46 dprintf_region(stddeb, "OffsetRgn: %04x %d,%d\n", hrgn, x, y );
47 if (obj->xrgn)
49 XOffsetRegion( obj->xrgn, x, y );
50 ret = COMPLEXREGION;
52 else
53 ret = NULLREGION;
54 GDI_HEAP_UNLOCK( hrgn );
55 return ret;
57 return ERROR;
61 /***********************************************************************
62 * GetRgnBox16 (GDI.134)
64 INT16 WINAPI GetRgnBox16( HRGN16 hrgn, LPRECT16 rect )
66 RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
67 if (obj)
69 INT16 ret;
70 dprintf_region(stddeb, "GetRgnBox: %04x\n", hrgn );
71 if (obj->xrgn)
73 XRectangle xrect;
74 XClipBox( obj->xrgn, &xrect );
75 SetRect16( rect, xrect.x, xrect.y,
76 xrect.x + xrect.width, xrect.y + xrect.height);
77 ret = COMPLEXREGION;
79 else
81 SetRectEmpty16( rect );
82 ret = NULLREGION;
84 GDI_HEAP_UNLOCK(hrgn);
85 return ret;
87 return ERROR;
91 /***********************************************************************
92 * GetRgnBox32 (GDI32.219)
94 INT32 WINAPI GetRgnBox32( HRGN32 hrgn, LPRECT32 rect )
96 RECT16 r;
97 INT16 ret = GetRgnBox16( hrgn, &r );
98 CONV_RECT16TO32( &r, rect );
99 return ret;
103 /***********************************************************************
104 * CreateRectRgn16 (GDI.64)
106 HRGN16 WINAPI CreateRectRgn16(INT16 left, INT16 top, INT16 right, INT16 bottom)
108 return (HRGN16)CreateRectRgn32( left, top, right, bottom );
112 /***********************************************************************
113 * CreateRectRgn32 (GDI32.59)
115 HRGN32 WINAPI CreateRectRgn32(INT32 left, INT32 top, INT32 right, INT32 bottom)
117 HRGN32 hrgn;
118 RGNOBJ *obj;
120 if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
121 obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
122 if ((right > left) && (bottom > top))
124 XRectangle rect = { left, top, right - left, bottom - top };
125 if (!(obj->xrgn = XCreateRegion()))
127 GDI_FreeObject( hrgn );
128 return 0;
130 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
132 else obj->xrgn = 0;
133 dprintf_region( stddeb, "CreateRectRgn(%d,%d-%d,%d): returning %04x\n",
134 left, top, right, bottom, hrgn );
135 GDI_HEAP_UNLOCK( hrgn );
136 return hrgn;
140 /***********************************************************************
141 * CreateRectRgnIndirect16 (GDI.65)
143 HRGN16 WINAPI CreateRectRgnIndirect16( const RECT16* rect )
145 return CreateRectRgn32( rect->left, rect->top, rect->right, rect->bottom );
149 /***********************************************************************
150 * CreateRectRgnIndirect32 (GDI32.60)
152 HRGN32 WINAPI CreateRectRgnIndirect32( const RECT32* rect )
154 return CreateRectRgn32( rect->left, rect->top, rect->right, rect->bottom );
158 /***********************************************************************
159 * SetRectRgn16 (GDI.172)
161 VOID WINAPI SetRectRgn16( HRGN16 hrgn, INT16 left, INT16 top,
162 INT16 right, INT16 bottom )
164 SetRectRgn32( hrgn, left, top, right, bottom );
168 /***********************************************************************
169 * SetRectRgn32 (GDI32.332)
171 VOID WINAPI SetRectRgn32( HRGN32 hrgn, INT32 left, INT32 top,
172 INT32 right, INT32 bottom )
174 RGNOBJ * obj;
176 dprintf_region(stddeb, "SetRectRgn: %04x %d,%d-%d,%d\n",
177 hrgn, left, top, right, bottom );
179 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return;
180 if (obj->xrgn) XDestroyRegion( obj->xrgn );
181 if ((right > left) && (bottom > top))
183 XRectangle rect = { left, top, right - left, bottom - top };
184 if ((obj->xrgn = XCreateRegion()) != 0)
185 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
187 else obj->xrgn = 0;
188 GDI_HEAP_UNLOCK( hrgn );
192 /***********************************************************************
193 * CreateRoundRectRgn16 (GDI.444)
195 HRGN16 WINAPI CreateRoundRectRgn16( INT16 left, INT16 top,
196 INT16 right, INT16 bottom,
197 INT16 ellipse_width, INT16 ellipse_height )
199 return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
200 ellipse_width, ellipse_height );
204 /***********************************************************************
205 * CreateRoundRectRgn32 (GDI32.61)
207 HRGN32 WINAPI CreateRoundRectRgn32( INT32 left, INT32 top,
208 INT32 right, INT32 bottom,
209 INT32 ellipse_width, INT32 ellipse_height )
211 RGNOBJ * obj;
212 HRGN32 hrgn;
213 XRectangle rect;
214 int asq, bsq, d, xd, yd;
216 /* Check if we can do a normal rectangle instead */
218 if ((right <= left) || (bottom <= top) ||
219 (ellipse_width <= 0) || (ellipse_height <= 0))
220 return CreateRectRgn32( left, top, right, bottom );
222 /* Create region */
224 if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
225 obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
226 obj->xrgn = XCreateRegion();
227 dprintf_region(stddeb,"CreateRoundRectRgn(%d,%d-%d,%d %dx%d): return=%04x\n",
228 left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
230 /* Check parameters */
232 if (ellipse_width > right-left) ellipse_width = right-left;
233 if (ellipse_height > bottom-top) ellipse_height = bottom-top;
235 /* Ellipse algorithm, based on an article by K. Porter */
236 /* in DDJ Graphics Programming Column, 8/89 */
238 asq = ellipse_width * ellipse_width / 4; /* a^2 */
239 bsq = ellipse_height * ellipse_height / 4; /* b^2 */
240 d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */
241 xd = 0;
242 yd = asq * ellipse_height; /* 2a^2b */
244 rect.x = left + ellipse_width / 2;
245 rect.width = right - left - ellipse_width;
246 rect.height = 1;
248 /* Loop to draw first half of quadrant */
250 while (xd < yd)
252 if (d > 0) /* if nearest pixel is toward the center */
254 /* move toward center */
255 rect.y = top++;
256 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
257 rect.y = --bottom;
258 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
259 yd -= 2*asq;
260 d -= yd;
262 rect.x--; /* next horiz point */
263 rect.width += 2;
264 xd += 2*bsq;
265 d += bsq + xd;
268 /* Loop to draw second half of quadrant */
270 d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
271 while (yd >= 0)
273 /* next vertical point */
274 rect.y = top++;
275 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
276 rect.y = --bottom;
277 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
278 if (d < 0) /* if nearest pixel is outside ellipse */
280 rect.x--; /* move away from center */
281 rect.width += 2;
282 xd += 2*bsq;
283 d += xd;
285 yd -= 2*asq;
286 d += asq - yd;
289 /* Add the inside rectangle */
291 if (top <= bottom)
293 rect.y = top;
294 rect.height = bottom - top + 1;
295 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
297 GDI_HEAP_UNLOCK( hrgn );
298 return hrgn;
302 /***********************************************************************
303 * CreateEllipticRgn16 (GDI.54)
305 HRGN16 WINAPI CreateEllipticRgn16( INT16 left, INT16 top,
306 INT16 right, INT16 bottom )
308 return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
309 right-left, bottom-top );
313 /***********************************************************************
314 * CreateEllipticRgn32 (GDI32.39)
316 HRGN32 WINAPI CreateEllipticRgn32( INT32 left, INT32 top,
317 INT32 right, INT32 bottom )
319 return CreateRoundRectRgn32( left, top, right, bottom,
320 right-left, bottom-top );
324 /***********************************************************************
325 * CreateEllipticRgnIndirect16 (GDI.55)
327 HRGN16 WINAPI CreateEllipticRgnIndirect16( const RECT16 *rect )
329 return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
330 rect->bottom, rect->right - rect->left,
331 rect->bottom - rect->top );
335 /***********************************************************************
336 * CreateEllipticRgnIndirect32 (GDI32.40)
338 HRGN32 WINAPI CreateEllipticRgnIndirect32( const RECT32 *rect )
340 return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
341 rect->bottom, rect->right - rect->left,
342 rect->bottom - rect->top );
346 /***********************************************************************
347 * CreatePolygonRgn16 (GDI.63)
349 HRGN16 WINAPI CreatePolygonRgn16( const POINT16 * points, INT16 count,
350 INT16 mode )
352 return CreatePolyPolygonRgn16( points, &count, 1, mode );
356 /***********************************************************************
357 * CreatePolyPolygonRgn16 (GDI.451)
359 HRGN16 WINAPI CreatePolyPolygonRgn16( const POINT16 * points,
360 const INT16 * count,
361 INT16 nbpolygons, INT16 mode )
363 int i,nrofpts;
364 LPINT32 count32;
365 LPPOINT32 points32;
366 HRGN32 ret;
368 nrofpts=0;
369 for (i=nbpolygons;i--;)
370 nrofpts+=count[i];
371 points32 = (LPPOINT32)HeapAlloc( GetProcessHeap(), 0,
372 nrofpts*sizeof(POINT32) );
373 for (i=nrofpts;i--;)
374 CONV_POINT16TO32( &(points[i]), &(points32[i]) );
375 count32 = (LPINT32)HeapAlloc( GetProcessHeap(), 0,
376 sizeof(INT32)*nbpolygons );
377 for (i=nbpolygons;i--;)
378 count32[i]=count[i];
379 ret = CreatePolyPolygonRgn32(points32,count32,nbpolygons,mode);
380 HeapFree( GetProcessHeap(), 0, count32 );
381 HeapFree( GetProcessHeap(), 0, points32 );
382 return ret;
386 /***********************************************************************
387 * CreatePolygonRgn32 (GDI32.58)
389 HRGN32 WINAPI CreatePolygonRgn32( const POINT32 *points, INT32 count,
390 INT32 mode )
392 return CreatePolyPolygonRgn32( points, &count, 1, mode );
396 /***********************************************************************
397 * CreatePolyPolygonRgn32 (GDI32.57)
399 HRGN32 WINAPI CreatePolyPolygonRgn32( const POINT32 * points,
400 const INT32 * count,
401 INT32 nbpolygons, INT32 mode )
403 RGNOBJ * obj;
404 HRGN32 hrgn;
405 int i, j, maxPoints;
406 XPoint *xpoints, *pt;
407 Region xrgn;
409 /* Allocate points array */
411 if (!nbpolygons) return 0;
412 for (i = maxPoints = 0; i < nbpolygons; i++)
413 if (maxPoints < count[i]) maxPoints = count[i];
414 if (!maxPoints) return 0;
415 if (!(xpoints = (XPoint *)HeapAlloc( GetProcessHeap(), 0,
416 sizeof(XPoint) * maxPoints )))
417 return 0;
419 /* Allocate region */
421 if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
423 HeapFree( GetProcessHeap(), 0, xpoints );
424 return 0;
426 obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
427 obj->xrgn = 0;
428 dprintf_region(stddeb, "CreatePolyPolygonRgn: %d polygons, returning %04x\n",
429 nbpolygons, hrgn );
431 /* Create X region */
433 for (i = 0; i < nbpolygons; i++, count++)
435 if (*count <= 1) continue;
436 for (j = *count, pt = xpoints; j > 0; j--, points++, pt++)
438 pt->x = points->x;
439 pt->y = points->y;
441 xrgn = XPolygonRegion( xpoints, *count,
442 (mode == WINDING) ? WindingRule : EvenOddRule );
443 if (!xrgn)
445 if (obj->xrgn) XDestroyRegion( obj->xrgn );
446 HeapFree( GetProcessHeap(), 0, xpoints );
447 GDI_FreeObject( hrgn );
448 return 0;
450 if (obj->xrgn)
452 Region tmprgn = XCreateRegion();
453 if (mode == WINDING) XUnionRegion( xrgn, obj->xrgn, tmprgn );
454 else XXorRegion( xrgn, obj->xrgn, tmprgn );
455 XDestroyRegion( obj->xrgn );
456 obj->xrgn = tmprgn;
458 else obj->xrgn = xrgn;
461 HeapFree( GetProcessHeap(), 0, xpoints );
462 GDI_HEAP_UNLOCK( hrgn );
463 return hrgn;
467 /***********************************************************************
468 * PtInRegion16 (GDI.161)
470 BOOL16 WINAPI PtInRegion16( HRGN16 hrgn, INT16 x, INT16 y )
472 return PtInRegion32( hrgn, x, y );
476 /***********************************************************************
477 * PtInRegion32 (GDI32.278)
479 BOOL32 WINAPI PtInRegion32( HRGN32 hrgn, INT32 x, INT32 y )
481 RGNOBJ * obj;
483 if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
485 BOOL32 ret;
486 if (obj->xrgn)
487 ret = XPointInRegion( obj->xrgn, x, y );
488 else
489 ret = FALSE;
490 GDI_HEAP_UNLOCK( hrgn );
491 return ret;
493 return FALSE;
497 /***********************************************************************
498 * RectInRegion16 (GDI.181)
500 BOOL16 WINAPI RectInRegion16( HRGN16 hrgn, const RECT16 *rect )
502 RGNOBJ * obj;
504 if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
506 BOOL16 ret;
507 if (obj->xrgn)
508 ret = (XRectInRegion( obj->xrgn, rect->left, rect->top,
509 rect->right-rect->left, rect->bottom-rect->top ) != RectangleOut);
510 else
511 ret = FALSE;
512 GDI_HEAP_UNLOCK( hrgn );
513 return ret;
515 return FALSE;
519 /***********************************************************************
520 * RectInRegion32 (GDI32.281)
522 BOOL32 WINAPI RectInRegion32( HRGN32 hrgn, const RECT32 *rect )
524 RGNOBJ * obj;
526 if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
528 BOOL32 ret;
529 if (obj->xrgn)
530 ret = (XRectInRegion( obj->xrgn, rect->left, rect->top,
531 rect->right-rect->left, rect->bottom-rect->top ) != RectangleOut);
532 else
533 ret = FALSE;
534 GDI_HEAP_UNLOCK( hrgn );
535 return ret;
537 return FALSE;
541 /***********************************************************************
542 * EqualRgn16 (GDI.72)
544 BOOL16 WINAPI EqualRgn16( HRGN16 rgn1, HRGN16 rgn2 )
546 return EqualRgn32( rgn1, rgn2 );
550 /***********************************************************************
551 * EqualRgn32 (GDI32.90)
553 BOOL32 WINAPI EqualRgn32( HRGN32 rgn1, HRGN32 rgn2 )
555 RGNOBJ *obj1, *obj2;
556 BOOL32 ret = FALSE;
558 if ((obj1 = (RGNOBJ *) GDI_GetObjPtr( rgn1, REGION_MAGIC )))
560 if ((obj2 = (RGNOBJ *) GDI_GetObjPtr( rgn2, REGION_MAGIC )))
562 if (!obj1->xrgn || !obj2->xrgn)
563 ret = (!obj1->xrgn && !obj2->xrgn);
564 else
565 ret = XEqualRegion( obj1->xrgn, obj2->xrgn );
566 GDI_HEAP_UNLOCK( rgn2 );
568 GDI_HEAP_UNLOCK( rgn1 );
570 return ret;
574 /***********************************************************************
575 * REGION_CopyRegion
577 * Copy region src into dest.
579 static INT32 REGION_CopyRegion( RGNOBJ *src, RGNOBJ *dest )
581 Region tmprgn;
582 if (src->xrgn)
584 if (src->xrgn == dest->xrgn) return COMPLEXREGION;
585 tmprgn = XCreateRegion();
586 if (!dest->xrgn) dest->xrgn = XCreateRegion();
587 XUnionRegion( tmprgn, src->xrgn, dest->xrgn );
588 XDestroyRegion( tmprgn );
589 return COMPLEXREGION;
591 else
593 if (dest->xrgn) XDestroyRegion( dest->xrgn );
594 dest->xrgn = 0;
595 return NULLREGION;
600 /***********************************************************************
601 * REGION_IsEmpty
603 BOOL32 REGION_IsEmpty( HRGN32 hRgn )
605 RGNOBJ* rgnObj = (RGNOBJ*) GDI_GetObjPtr( hRgn, REGION_MAGIC );
606 BOOL32 ret = TRUE;
608 if( rgnObj )
610 if( rgnObj->xrgn && !XEmptyRegion(rgnObj->xrgn) ) ret = FALSE;
611 GDI_HEAP_UNLOCK( hRgn );
613 return ret;
617 /***********************************************************************
618 * REGION_UnionRectWithRgn
620 * Add rc rectangle to the region.
622 BOOL32 REGION_UnionRectWithRgn( HRGN32 hRgn, const RECT32 *rc )
624 RGNOBJ* rgnObj = (RGNOBJ*) GDI_GetObjPtr( hRgn, REGION_MAGIC );
625 XRectangle rect = { rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top };
626 BOOL32 ret = ERROR;
628 if( rgnObj )
630 if( !rgnObj->xrgn )
632 if ((rgnObj->xrgn = XCreateRegion()))
633 ret = SIMPLEREGION;
634 else
635 goto done;
637 else
638 ret = COMPLEXREGION;
639 XUnionRectWithRegion( &rect, rgnObj->xrgn, rgnObj->xrgn );
640 done:
641 GDI_HEAP_UNLOCK( hRgn );
643 return ret;
647 /***********************************************************************
648 * REGION_CreateFrameRgn
650 * Create a region that is a frame around another region
652 BOOL32 REGION_FrameRgn( HRGN32 hDest, HRGN32 hSrc, INT32 x, INT32 y )
654 BOOL32 bRet;
655 RGNOBJ *srcObj = (RGNOBJ*) GDI_GetObjPtr( hSrc, REGION_MAGIC );
657 if (srcObj->xrgn)
659 RGNOBJ* destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC );
660 Region resRgn;
662 REGION_CopyRegion( srcObj, destObj );
663 XShrinkRegion( destObj->xrgn, -x, -y );
664 resRgn = XCreateRegion();
665 XSubtractRegion( destObj->xrgn, srcObj->xrgn, resRgn );
666 XDestroyRegion( destObj->xrgn );
667 destObj->xrgn = resRgn;
668 GDI_HEAP_UNLOCK( hDest );
669 bRet = TRUE;
671 else
672 bRet = FALSE;
673 GDI_HEAP_UNLOCK( hSrc );
674 return bRet;
678 /***********************************************************************
679 * CombineRgn16 (GDI.451)
681 INT16 WINAPI CombineRgn16(HRGN16 hDest, HRGN16 hSrc1, HRGN16 hSrc2, INT16 mode)
683 return (INT16)CombineRgn32( hDest, hSrc1, hSrc2, mode );
687 /***********************************************************************
688 * CombineRgn32 (GDI32.19)
690 * Note: The behavior is correct even if src and dest regions are the same.
692 INT32 WINAPI CombineRgn32(HRGN32 hDest, HRGN32 hSrc1, HRGN32 hSrc2, INT32 mode)
694 RGNOBJ *destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC);
695 INT32 result = ERROR;
697 dprintf_region(stddeb, "CombineRgn: %04x,%04x -> %04x mode=%x\n",
698 hSrc1, hSrc2, hDest, mode );
699 if (destObj)
701 RGNOBJ *src1Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc1, REGION_MAGIC);
703 if (src1Obj)
705 if (mode == RGN_COPY)
706 result = REGION_CopyRegion( src1Obj, destObj );
707 else
709 RGNOBJ *src2Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc2, REGION_MAGIC);
711 if (src2Obj)
713 if (!src1Obj->xrgn || !src2Obj->xrgn)
715 /* Some optimizations for null regions */
716 switch( mode )
718 case RGN_DIFF:
719 if (src1Obj->xrgn)
721 result = REGION_CopyRegion( src1Obj, destObj );
722 break;
724 /* else fall through */
725 case RGN_AND:
726 if (destObj->xrgn)
728 XDestroyRegion( destObj->xrgn );
729 destObj->xrgn = 0;
731 result = NULLREGION;
732 break;
734 case RGN_OR:
735 case RGN_XOR:
736 #define __SRC_RGN ((src1Obj->xrgn) ? src1Obj : src2Obj)
737 result = REGION_CopyRegion( __SRC_RGN, destObj );
738 #undef __SRC_RGN
739 break;
741 case 0:
742 default:
743 /* makes gcc generate more efficient code */
746 else /* both regions are present */
748 Region destRgn = XCreateRegion();
750 if (destRgn)
752 switch (mode)
754 case RGN_AND:
755 XIntersectRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
756 break;
757 case RGN_OR:
758 XUnionRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
759 break;
760 case RGN_XOR:
761 XXorRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
762 break;
763 case RGN_DIFF:
764 XSubtractRegion( src1Obj->xrgn, src2Obj->xrgn, destRgn );
765 break;
767 case 0: /* makes gcc generate more efficient code */
768 default:
769 XDestroyRegion( destRgn );
770 goto done;
773 if ( destObj->xrgn )
774 XDestroyRegion( destObj->xrgn );
775 if ( XEmptyRegion( destRgn ) )
777 XDestroyRegion( destRgn );
778 destObj->xrgn = 0;
779 result = NULLREGION;
781 else
783 destObj->xrgn = destRgn;
784 result = COMPLEXREGION;
788 done:
789 GDI_HEAP_UNLOCK( hSrc2 );
792 GDI_HEAP_UNLOCK( hSrc1 );
794 GDI_HEAP_UNLOCK( hDest );
796 return result;