Release 970824
[wine/multimedia.git] / objects / region.c
bloba8e86e804252f3d34cd6c6ba4534c5eeacd97718
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 );
42 if (!obj) return ERROR;
43 dprintf_region(stddeb, "OffsetRgn: %04x %d,%d\n", hrgn, x, y );
44 if (!obj->xrgn)
46 GDI_HEAP_UNLOCK( hrgn );
47 return NULLREGION;
49 XOffsetRegion( obj->xrgn, x, y );
50 GDI_HEAP_UNLOCK( hrgn );
51 return COMPLEXREGION;
55 /***********************************************************************
56 * GetRgnBox16 (GDI.134)
58 INT16 WINAPI GetRgnBox16( HRGN16 hrgn, LPRECT16 rect )
60 RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
61 if (!obj) return ERROR;
62 dprintf_region(stddeb, "GetRgnBox: %04x\n", hrgn );
63 if (!obj->xrgn)
65 SetRectEmpty16( rect );
66 GDI_HEAP_UNLOCK( hrgn );
67 return NULLREGION;
69 else
71 XRectangle xrect;
72 XClipBox( obj->xrgn, &xrect );
73 GDI_HEAP_UNLOCK(hrgn);
74 SetRect16( rect, xrect.x, xrect.y,
75 xrect.x + xrect.width, xrect.y + xrect.height);
76 return COMPLEXREGION;
81 /***********************************************************************
82 * GetRgnBox32 (GDI32.219)
84 INT32 WINAPI GetRgnBox32( HRGN32 hrgn, LPRECT32 rect )
86 RECT16 r;
87 INT16 ret = GetRgnBox16( hrgn, &r );
88 CONV_RECT16TO32( &r, rect );
89 return ret;
93 /***********************************************************************
94 * CreateRectRgn16 (GDI.64)
96 HRGN16 WINAPI CreateRectRgn16(INT16 left, INT16 top, INT16 right, INT16 bottom)
98 return (HRGN16)CreateRectRgn32( left, top, right, bottom );
102 /***********************************************************************
103 * CreateRectRgn32 (GDI32.59)
105 HRGN32 WINAPI CreateRectRgn32(INT32 left, INT32 top, INT32 right, INT32 bottom)
107 HRGN32 hrgn;
108 RGNOBJ *obj;
110 if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
111 obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
112 if ((right > left) && (bottom > top))
114 XRectangle rect = { left, top, right - left, bottom - top };
115 if (!(obj->xrgn = XCreateRegion()))
117 GDI_FreeObject( hrgn );
118 return 0;
120 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
122 else obj->xrgn = 0;
123 dprintf_region( stddeb, "CreateRectRgn(%d,%d-%d,%d): returning %04x\n",
124 left, top, right, bottom, hrgn );
125 GDI_HEAP_UNLOCK( hrgn );
126 return hrgn;
130 /***********************************************************************
131 * CreateRectRgnIndirect16 (GDI.65)
133 HRGN16 WINAPI CreateRectRgnIndirect16( const RECT16* rect )
135 return CreateRectRgn32( rect->left, rect->top, rect->right, rect->bottom );
139 /***********************************************************************
140 * CreateRectRgnIndirect32 (GDI32.60)
142 HRGN32 WINAPI CreateRectRgnIndirect32( const RECT32* rect )
144 return CreateRectRgn32( rect->left, rect->top, rect->right, rect->bottom );
148 /***********************************************************************
149 * SetRectRgn16 (GDI.172)
151 VOID WINAPI SetRectRgn16( HRGN16 hrgn, INT16 left, INT16 top,
152 INT16 right, INT16 bottom )
154 SetRectRgn32( hrgn, left, top, right, bottom );
158 /***********************************************************************
159 * SetRectRgn32 (GDI32.332)
161 VOID WINAPI SetRectRgn32( HRGN32 hrgn, INT32 left, INT32 top,
162 INT32 right, INT32 bottom )
164 RGNOBJ * obj;
166 dprintf_region(stddeb, "SetRectRgn: %04x %d,%d-%d,%d\n",
167 hrgn, left, top, right, bottom );
169 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return;
170 if (obj->xrgn) XDestroyRegion( obj->xrgn );
171 if ((right > left) && (bottom > top))
173 XRectangle rect = { left, top, right - left, bottom - top };
174 if ((obj->xrgn = XCreateRegion()) != 0)
175 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
177 else obj->xrgn = 0;
178 GDI_HEAP_UNLOCK( hrgn );
182 /***********************************************************************
183 * CreateRoundRectRgn16 (GDI.444)
185 HRGN16 WINAPI CreateRoundRectRgn16( INT16 left, INT16 top,
186 INT16 right, INT16 bottom,
187 INT16 ellipse_width, INT16 ellipse_height )
189 return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
190 ellipse_width, ellipse_height );
194 /***********************************************************************
195 * CreateRoundRectRgn32 (GDI32.61)
197 HRGN32 WINAPI CreateRoundRectRgn32( INT32 left, INT32 top,
198 INT32 right, INT32 bottom,
199 INT32 ellipse_width, INT32 ellipse_height )
201 RGNOBJ * obj;
202 HRGN32 hrgn;
203 XRectangle rect;
204 int asq, bsq, d, xd, yd;
206 /* Check if we can do a normal rectangle instead */
208 if ((right <= left) || (bottom <= top) ||
209 (ellipse_width <= 0) || (ellipse_height <= 0))
210 return CreateRectRgn32( left, top, right, bottom );
212 /* Create region */
214 if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
215 obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
216 obj->xrgn = XCreateRegion();
217 dprintf_region(stddeb,"CreateRoundRectRgn(%d,%d-%d,%d %dx%d): return=%04x\n",
218 left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
220 /* Check parameters */
222 if (ellipse_width > right-left) ellipse_width = right-left;
223 if (ellipse_height > bottom-top) ellipse_height = bottom-top;
225 /* Ellipse algorithm, based on an article by K. Porter */
226 /* in DDJ Graphics Programming Column, 8/89 */
228 asq = ellipse_width * ellipse_width / 4; /* a^2 */
229 bsq = ellipse_height * ellipse_height / 4; /* b^2 */
230 d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */
231 xd = 0;
232 yd = asq * ellipse_height; /* 2a^2b */
234 rect.x = left + ellipse_width / 2;
235 rect.width = right - left - ellipse_width;
236 rect.height = 1;
238 /* Loop to draw first half of quadrant */
240 while (xd < yd)
242 if (d > 0) /* if nearest pixel is toward the center */
244 /* move toward center */
245 rect.y = top++;
246 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
247 rect.y = --bottom;
248 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
249 yd -= 2*asq;
250 d -= yd;
252 rect.x--; /* next horiz point */
253 rect.width += 2;
254 xd += 2*bsq;
255 d += bsq + xd;
258 /* Loop to draw second half of quadrant */
260 d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
261 while (yd >= 0)
263 /* next vertical point */
264 rect.y = top++;
265 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
266 rect.y = --bottom;
267 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
268 if (d < 0) /* if nearest pixel is outside ellipse */
270 rect.x--; /* move away from center */
271 rect.width += 2;
272 xd += 2*bsq;
273 d += xd;
275 yd -= 2*asq;
276 d += asq - yd;
279 /* Add the inside rectangle */
281 if (top <= bottom)
283 rect.y = top;
284 rect.height = bottom - top + 1;
285 XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
287 GDI_HEAP_UNLOCK( hrgn );
288 return hrgn;
292 /***********************************************************************
293 * CreateEllipticRgn16 (GDI.54)
295 HRGN16 WINAPI CreateEllipticRgn16( INT16 left, INT16 top,
296 INT16 right, INT16 bottom )
298 return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
299 right-left, bottom-top );
303 /***********************************************************************
304 * CreateEllipticRgn32 (GDI32.39)
306 HRGN32 WINAPI CreateEllipticRgn32( INT32 left, INT32 top,
307 INT32 right, INT32 bottom )
309 return CreateRoundRectRgn32( left, top, right, bottom,
310 right-left, bottom-top );
314 /***********************************************************************
315 * CreateEllipticRgnIndirect16 (GDI.55)
317 HRGN16 WINAPI CreateEllipticRgnIndirect16( const RECT16 *rect )
319 return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
320 rect->bottom, rect->right - rect->left,
321 rect->bottom - rect->top );
325 /***********************************************************************
326 * CreateEllipticRgnIndirect32 (GDI32.40)
328 HRGN32 WINAPI CreateEllipticRgnIndirect32( const RECT32 *rect )
330 return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
331 rect->bottom, rect->right - rect->left,
332 rect->bottom - rect->top );
336 /***********************************************************************
337 * CreatePolygonRgn16 (GDI.63)
339 HRGN16 WINAPI CreatePolygonRgn16( const POINT16 * points, INT16 count,
340 INT16 mode )
342 return CreatePolyPolygonRgn16( points, &count, 1, mode );
346 /***********************************************************************
347 * CreatePolyPolygonRgn16 (GDI.451)
349 HRGN16 WINAPI CreatePolyPolygonRgn16( const POINT16 * points,
350 const INT16 * count,
351 INT16 nbpolygons, INT16 mode )
353 int i,nrofpts;
354 LPINT32 count32;
355 LPPOINT32 points32;
356 HRGN32 ret;
358 nrofpts=0;
359 for (i=nbpolygons;i--;)
360 nrofpts+=count[i];
361 points32 = (LPPOINT32)HeapAlloc( GetProcessHeap(), 0,
362 nrofpts*sizeof(POINT32) );
363 for (i=nrofpts;i--;)
364 CONV_POINT16TO32( &(points[i]), &(points32[i]) );
365 count32 = (LPINT32)HeapAlloc( GetProcessHeap(), 0,
366 sizeof(INT32)*nbpolygons );
367 for (i=nbpolygons;i--;)
368 count32[i]=count[i];
369 ret = CreatePolyPolygonRgn32(points32,count32,nbpolygons,mode);
370 HeapFree( GetProcessHeap(), 0, count32 );
371 HeapFree( GetProcessHeap(), 0, points32 );
372 return ret;
376 /***********************************************************************
377 * CreatePolygonRgn32 (GDI32.58)
379 HRGN32 WINAPI CreatePolygonRgn32( const POINT32 *points, INT32 count,
380 INT32 mode )
382 return CreatePolyPolygonRgn32( points, &count, 1, mode );
386 /***********************************************************************
387 * CreatePolyPolygonRgn32 (GDI32.57)
389 HRGN32 WINAPI CreatePolyPolygonRgn32( const POINT32 * points,
390 const INT32 * count,
391 INT32 nbpolygons, INT32 mode )
393 RGNOBJ * obj;
394 HRGN32 hrgn;
395 int i, j, maxPoints;
396 XPoint *xpoints, *pt;
397 Region xrgn;
399 /* Allocate points array */
401 if (!nbpolygons) return 0;
402 for (i = maxPoints = 0; i < nbpolygons; i++)
403 if (maxPoints < count[i]) maxPoints = count[i];
404 if (!maxPoints) return 0;
405 if (!(xpoints = (XPoint *)HeapAlloc( GetProcessHeap(), 0,
406 sizeof(XPoint) * maxPoints )))
407 return 0;
409 /* Allocate region */
411 if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
413 HeapFree( GetProcessHeap(), 0, xpoints );
414 return 0;
416 obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
417 obj->xrgn = 0;
418 dprintf_region(stddeb, "CreatePolyPolygonRgn: %d polygons, returning %04x\n",
419 nbpolygons, hrgn );
421 /* Create X region */
423 for (i = 0; i < nbpolygons; i++, count++)
425 for (j = *count, pt = xpoints; j > 0; j--, points++, pt++)
427 pt->x = points->x;
428 pt->y = points->y;
430 xrgn = XPolygonRegion( xpoints, *count,
431 (mode == WINDING) ? WindingRule : EvenOddRule );
432 if (!xrgn)
434 if (obj->xrgn) XDestroyRegion( obj->xrgn );
435 HeapFree( GetProcessHeap(), 0, xpoints );
436 GDI_FreeObject( hrgn );
437 return 0;
439 if (i > 0)
441 Region tmprgn = XCreateRegion();
442 if (mode == WINDING) XUnionRegion( xrgn, obj->xrgn, tmprgn );
443 else XXorRegion( xrgn, obj->xrgn, tmprgn );
444 XDestroyRegion( obj->xrgn );
445 obj->xrgn = tmprgn;
447 else obj->xrgn = xrgn;
450 HeapFree( GetProcessHeap(), 0, xpoints );
451 GDI_HEAP_UNLOCK( hrgn );
452 return hrgn;
456 /***********************************************************************
457 * PtInRegion16 (GDI.161)
459 BOOL16 WINAPI PtInRegion16( HRGN16 hrgn, INT16 x, INT16 y )
461 return PtInRegion32( hrgn, x, y );
465 /***********************************************************************
466 * PtInRegion32 (GDI32.278)
468 BOOL32 WINAPI PtInRegion32( HRGN32 hrgn, INT32 x, INT32 y )
470 RGNOBJ * obj;
471 BOOL32 result;
473 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
474 if (!obj->xrgn) result = FALSE;
475 else result = XPointInRegion( obj->xrgn, x, y );
476 GDI_HEAP_UNLOCK( hrgn );
477 return result;
481 /***********************************************************************
482 * RectInRegion16 (GDI.181)
484 BOOL16 WINAPI RectInRegion16( HRGN16 hrgn, const RECT16 *rect )
486 RGNOBJ * obj;
487 BOOL16 result;
489 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
490 if (!obj->xrgn) result = FALSE;
491 else result = (XRectInRegion( obj->xrgn, rect->left, rect->top,
492 rect->right-rect->left,
493 rect->bottom-rect->top ) != RectangleOut);
494 GDI_HEAP_UNLOCK( hrgn );
495 return result;
499 /***********************************************************************
500 * RectInRegion32 (GDI32.281)
502 BOOL32 WINAPI RectInRegion32( HRGN32 hrgn, const RECT32 *rect )
504 RGNOBJ * obj;
505 BOOL32 result;
507 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
508 if (!obj->xrgn) result = FALSE;
509 else result = (XRectInRegion( obj->xrgn, rect->left, rect->top,
510 rect->right-rect->left,
511 rect->bottom-rect->top ) != RectangleOut);
512 GDI_HEAP_UNLOCK( hrgn );
513 return result;
517 /***********************************************************************
518 * EqualRgn16 (GDI.72)
520 BOOL16 WINAPI EqualRgn16( HRGN16 rgn1, HRGN16 rgn2 )
522 return EqualRgn32( rgn1, rgn2 );
526 /***********************************************************************
527 * EqualRgn32 (GDI32.90)
529 BOOL32 WINAPI EqualRgn32( HRGN32 rgn1, HRGN32 rgn2 )
531 RGNOBJ *obj1, *obj2;
532 BOOL32 result;
534 if (!(obj1 = (RGNOBJ *) GDI_GetObjPtr( rgn1, REGION_MAGIC ))) return FALSE;
535 if (!(obj2 = (RGNOBJ *) GDI_GetObjPtr( rgn2, REGION_MAGIC )))
537 GDI_HEAP_UNLOCK( rgn1 );
538 return FALSE;
540 if (!obj1->xrgn || !obj2->xrgn) result = (!obj1->xrgn && !obj2->xrgn);
541 else result = XEqualRegion( obj1->xrgn, obj2->xrgn );
542 GDI_HEAP_UNLOCK( rgn1 );
543 GDI_HEAP_UNLOCK( rgn2 );
544 return result;
548 /***********************************************************************
549 * REGION_CopyRegion
551 * Copy region src into dest.
553 static INT32 REGION_CopyRegion( RGNOBJ *src, RGNOBJ *dest )
555 Region tmprgn;
556 if (src->xrgn)
558 if (src->xrgn == dest->xrgn) return COMPLEXREGION;
559 tmprgn = XCreateRegion();
560 if (!dest->xrgn) dest->xrgn = XCreateRegion();
561 XUnionRegion( tmprgn, src->xrgn, dest->xrgn );
562 XDestroyRegion( tmprgn );
563 return COMPLEXREGION;
565 else
567 if (dest->xrgn) XDestroyRegion( dest->xrgn );
568 dest->xrgn = 0;
569 return NULLREGION;
573 /***********************************************************************
574 * REGION_UnionRectWithRgn
576 * Add rectangle to region
578 BOOL32 REGION_UnionRectWithRgn( HRGN32 hRgn, const RECT32 *rc )
580 RGNOBJ *rgnObj = (RGNOBJ*) GDI_GetObjPtr( hRgn, REGION_MAGIC );
581 XRectangle rect = { rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top };
582 BOOL32 ret = FALSE;
584 if( rgnObj )
586 if( !rgnObj->xrgn )
588 if (!(rgnObj->xrgn = XCreateRegion()))
590 GDI_FreeObject( hRgn );
591 return 0;
593 ret = SIMPLEREGION;
595 else
596 ret = COMPLEXREGION;
597 XUnionRectWithRegion( &rect, rgnObj->xrgn, rgnObj->xrgn );
598 GDI_HEAP_UNLOCK( hRgn );
600 return ret;
604 /***********************************************************************
605 * REGION_CreateFrameRgn
607 * Create a region that is a frame around another region
609 BOOL32 REGION_FrameRgn( HRGN32 hDest, HRGN32 hSrc, INT32 x, INT32 y )
611 RGNOBJ *destObj,*srcObj;
612 Region result;
614 destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC );
615 srcObj = (RGNOBJ*) GDI_GetObjPtr( hSrc, REGION_MAGIC );
616 if (!srcObj->xrgn)
618 GDI_HEAP_UNLOCK( hDest );
619 GDI_HEAP_UNLOCK( hSrc );
620 return FALSE;
622 REGION_CopyRegion( srcObj, destObj );
623 XShrinkRegion( destObj->xrgn, -x, -y );
624 result = XCreateRegion();
625 XSubtractRegion( destObj->xrgn, srcObj->xrgn, result );
626 XDestroyRegion( destObj->xrgn );
627 destObj->xrgn = result;
628 GDI_HEAP_UNLOCK( hDest );
629 GDI_HEAP_UNLOCK( hSrc );
630 return TRUE;
634 /***********************************************************************
635 * CombineRgn16 (GDI.451)
637 INT16 WINAPI CombineRgn16(HRGN16 hDest, HRGN16 hSrc1, HRGN16 hSrc2, INT16 mode)
639 return (INT16)CombineRgn32( hDest, hSrc1, hSrc2, mode );
643 /***********************************************************************
644 * CombineRgn32 (GDI32.19)
646 * Note: The behavior is correct even if src and dest regions are the same.
648 INT32 WINAPI CombineRgn32(HRGN32 hDest, HRGN32 hSrc1, HRGN32 hSrc2, INT32 mode)
650 RGNOBJ *destObj, *src1Obj, *src2Obj;
651 Region destrgn;
652 INT32 result;
654 dprintf_region(stddeb, "CombineRgn: %04x,%04x -> %04x mode=%x\n",
655 hSrc1, hSrc2, hDest, mode );
657 if (!(destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC )))
658 return ERROR;
659 if (!(src1Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc1, REGION_MAGIC )))
661 GDI_HEAP_UNLOCK( hDest );
662 return ERROR;
664 if (mode == RGN_COPY)
666 result = REGION_CopyRegion( src1Obj, destObj );
667 GDI_HEAP_UNLOCK( hDest );
668 GDI_HEAP_UNLOCK( hSrc1 );
669 return result;
672 if (!(src2Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc2, REGION_MAGIC )))
674 GDI_HEAP_UNLOCK( hDest );
675 GDI_HEAP_UNLOCK( hSrc1 );
676 return ERROR;
678 /* Some optimizations for null regions */
680 if (!src1Obj->xrgn || !src2Obj->xrgn)
682 switch(mode)
684 case RGN_DIFF:
685 if (src1Obj->xrgn)
687 result = REGION_CopyRegion( src1Obj, destObj );
688 GDI_HEAP_UNLOCK( hDest );
689 GDI_HEAP_UNLOCK( hSrc1 );
690 GDI_HEAP_UNLOCK( hSrc2 );
691 return result;
693 /* else fall through */
694 case RGN_AND:
695 if (destObj->xrgn) XDestroyRegion( destObj->xrgn );
696 destObj->xrgn = 0;
697 GDI_HEAP_UNLOCK( hDest );
698 GDI_HEAP_UNLOCK( hSrc1 );
699 GDI_HEAP_UNLOCK( hSrc2 );
700 return NULLREGION;
701 case RGN_OR:
702 case RGN_XOR:
703 if (src1Obj->xrgn)
704 result = REGION_CopyRegion( src1Obj, destObj );
705 else
706 result = REGION_CopyRegion( src2Obj, destObj );
707 GDI_HEAP_UNLOCK( hDest );
708 GDI_HEAP_UNLOCK( hSrc1 );
709 GDI_HEAP_UNLOCK( hSrc2 );
710 return result;
711 default:
712 GDI_HEAP_UNLOCK( hDest );
713 GDI_HEAP_UNLOCK( hSrc1 );
714 GDI_HEAP_UNLOCK( hSrc2 );
715 return ERROR;
719 /* Perform the operation with the two X regions */
721 if (!(destrgn = XCreateRegion()))
723 GDI_HEAP_UNLOCK( hDest );
724 GDI_HEAP_UNLOCK( hSrc1 );
725 GDI_HEAP_UNLOCK( hSrc2 );
726 return ERROR;
728 switch(mode)
730 case RGN_AND:
731 XIntersectRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
732 break;
733 case RGN_OR:
734 XUnionRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
735 break;
736 case RGN_XOR:
737 XXorRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
738 break;
739 case RGN_DIFF:
740 XSubtractRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
741 break;
742 default:
743 XDestroyRegion( destrgn );
744 GDI_HEAP_UNLOCK( hDest );
745 GDI_HEAP_UNLOCK( hSrc1 );
746 GDI_HEAP_UNLOCK( hSrc2 );
747 return ERROR;
749 if (destObj->xrgn) XDestroyRegion( destObj->xrgn );
750 destObj->xrgn = destrgn;
751 if (XEmptyRegion(destObj->xrgn))
753 XDestroyRegion( destObj->xrgn );
754 destObj->xrgn = 0;
755 GDI_HEAP_UNLOCK( hDest );
756 GDI_HEAP_UNLOCK( hSrc1 );
757 GDI_HEAP_UNLOCK( hSrc2 );
758 return NULLREGION;
760 GDI_HEAP_UNLOCK( hDest );
761 GDI_HEAP_UNLOCK( hSrc1 );
762 GDI_HEAP_UNLOCK( hSrc2 );
763 return COMPLEXREGION;