4 * Copyright 1993, 1994, 1995 Alexandre Julliard
6 * RGNOBJ is documented in the Dr. Dobbs Journal March 1993.
16 /***********************************************************************
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
);
46 dprintf_region(stddeb
, "OffsetRgn: %04x %d,%d\n", hrgn
, x
, y
);
49 XOffsetRegion( obj
->xrgn
, x
, y
);
54 GDI_HEAP_UNLOCK( hrgn
);
61 /***********************************************************************
62 * GetRgnBox16 (GDI.134)
64 INT16 WINAPI
GetRgnBox16( HRGN16 hrgn
, LPRECT16 rect
)
66 RGNOBJ
* obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
);
70 dprintf_region(stddeb
, "GetRgnBox: %04x\n", hrgn
);
74 XClipBox( obj
->xrgn
, &xrect
);
75 SetRect16( rect
, xrect
.x
, xrect
.y
,
76 xrect
.x
+ xrect
.width
, xrect
.y
+ xrect
.height
);
81 SetRectEmpty16( rect
);
84 GDI_HEAP_UNLOCK(hrgn
);
91 /***********************************************************************
92 * GetRgnBox32 (GDI32.219)
94 INT32 WINAPI
GetRgnBox32( HRGN32 hrgn
, LPRECT32 rect
)
97 INT16 ret
= GetRgnBox16( hrgn
, &r
);
98 CONV_RECT16TO32( &r
, rect
);
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
)
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
);
130 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
133 dprintf_region( stddeb
, "CreateRectRgn(%d,%d-%d,%d): returning %04x\n",
134 left
, top
, right
, bottom
, hrgn
);
135 GDI_HEAP_UNLOCK( 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
)
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
);
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
)
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
);
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 */
242 yd
= asq
* ellipse_height
; /* 2a^2b */
244 rect
.x
= left
+ ellipse_width
/ 2;
245 rect
.width
= right
- left
- ellipse_width
;
248 /* Loop to draw first half of quadrant */
252 if (d
> 0) /* if nearest pixel is toward the center */
254 /* move toward center */
256 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
258 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
262 rect
.x
--; /* next horiz point */
268 /* Loop to draw second half of quadrant */
270 d
+= (3 * (asq
-bsq
) / 2 - (xd
+yd
)) / 2;
273 /* next vertical point */
275 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
277 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
278 if (d
< 0) /* if nearest pixel is outside ellipse */
280 rect
.x
--; /* move away from center */
289 /* Add the inside rectangle */
294 rect
.height
= bottom
- top
+ 1;
295 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
297 GDI_HEAP_UNLOCK( 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
,
352 return CreatePolyPolygonRgn16( points
, &count
, 1, mode
);
356 /***********************************************************************
357 * CreatePolyPolygonRgn16 (GDI.451)
359 HRGN16 WINAPI
CreatePolyPolygonRgn16( const POINT16
* points
,
361 INT16 nbpolygons
, INT16 mode
)
369 for (i
=nbpolygons
;i
--;)
371 points32
= (LPPOINT32
)HeapAlloc( GetProcessHeap(), 0,
372 nrofpts
*sizeof(POINT32
) );
374 CONV_POINT16TO32( &(points
[i
]), &(points32
[i
]) );
375 count32
= (LPINT32
)HeapAlloc( GetProcessHeap(), 0,
376 sizeof(INT32
)*nbpolygons
);
377 for (i
=nbpolygons
;i
--;)
379 ret
= CreatePolyPolygonRgn32(points32
,count32
,nbpolygons
,mode
);
380 HeapFree( GetProcessHeap(), 0, count32
);
381 HeapFree( GetProcessHeap(), 0, points32
);
386 /***********************************************************************
387 * CreatePolygonRgn32 (GDI32.58)
389 HRGN32 WINAPI
CreatePolygonRgn32( const POINT32
*points
, INT32 count
,
392 return CreatePolyPolygonRgn32( points
, &count
, 1, mode
);
396 /***********************************************************************
397 * CreatePolyPolygonRgn32 (GDI32.57)
399 HRGN32 WINAPI
CreatePolyPolygonRgn32( const POINT32
* points
,
401 INT32 nbpolygons
, INT32 mode
)
406 XPoint
*xpoints
, *pt
;
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
)))
419 /* Allocate region */
421 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
)))
423 HeapFree( GetProcessHeap(), 0, xpoints
);
426 obj
= (RGNOBJ
*) GDI_HEAP_LOCK( hrgn
);
428 dprintf_region(stddeb
, "CreatePolyPolygonRgn: %d polygons, returning %04x\n",
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
++)
441 xrgn
= XPolygonRegion( xpoints
, *count
,
442 (mode
== WINDING
) ? WindingRule
: EvenOddRule
);
445 if (obj
->xrgn
) XDestroyRegion( obj
->xrgn
);
446 HeapFree( GetProcessHeap(), 0, xpoints
);
447 GDI_FreeObject( hrgn
);
452 Region tmprgn
= XCreateRegion();
453 if (mode
== WINDING
) XUnionRegion( xrgn
, obj
->xrgn
, tmprgn
);
454 else XXorRegion( xrgn
, obj
->xrgn
, tmprgn
);
455 XDestroyRegion( obj
->xrgn
);
458 else obj
->xrgn
= xrgn
;
461 HeapFree( GetProcessHeap(), 0, xpoints
);
462 GDI_HEAP_UNLOCK( 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
)
483 if ((obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
)))
487 ret
= XPointInRegion( obj
->xrgn
, x
, y
);
490 GDI_HEAP_UNLOCK( hrgn
);
497 /***********************************************************************
498 * RectInRegion16 (GDI.181)
500 BOOL16 WINAPI
RectInRegion16( HRGN16 hrgn
, const RECT16
*rect
)
504 if ((obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
)))
508 ret
= (XRectInRegion( obj
->xrgn
, rect
->left
, rect
->top
,
509 rect
->right
-rect
->left
, rect
->bottom
-rect
->top
) != RectangleOut
);
512 GDI_HEAP_UNLOCK( hrgn
);
519 /***********************************************************************
520 * RectInRegion32 (GDI32.281)
522 BOOL32 WINAPI
RectInRegion32( HRGN32 hrgn
, const RECT32
*rect
)
526 if ((obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
)))
530 ret
= (XRectInRegion( obj
->xrgn
, rect
->left
, rect
->top
,
531 rect
->right
-rect
->left
, rect
->bottom
-rect
->top
) != RectangleOut
);
534 GDI_HEAP_UNLOCK( hrgn
);
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
)
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
);
565 ret
= XEqualRegion( obj1
->xrgn
, obj2
->xrgn
);
566 GDI_HEAP_UNLOCK( rgn2
);
568 GDI_HEAP_UNLOCK( rgn1
);
574 /***********************************************************************
577 * Copy region src into dest.
579 static INT32
REGION_CopyRegion( RGNOBJ
*src
, RGNOBJ
*dest
)
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
;
593 if (dest
->xrgn
) XDestroyRegion( dest
->xrgn
);
600 /***********************************************************************
603 BOOL32
REGION_IsEmpty( HRGN32 hRgn
)
605 RGNOBJ
* rgnObj
= (RGNOBJ
*) GDI_GetObjPtr( hRgn
, REGION_MAGIC
);
610 if( rgnObj
->xrgn
&& !XEmptyRegion(rgnObj
->xrgn
) ) ret
= FALSE
;
611 GDI_HEAP_UNLOCK( hRgn
);
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
};
632 if ((rgnObj
->xrgn
= XCreateRegion()))
639 XUnionRectWithRegion( &rect
, rgnObj
->xrgn
, rgnObj
->xrgn
);
641 GDI_HEAP_UNLOCK( hRgn
);
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
)
655 RGNOBJ
*srcObj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc
, REGION_MAGIC
);
659 RGNOBJ
* destObj
= (RGNOBJ
*) GDI_GetObjPtr( hDest
, REGION_MAGIC
);
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
);
673 GDI_HEAP_UNLOCK( hSrc
);
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
);
701 RGNOBJ
*src1Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc1
, REGION_MAGIC
);
705 if (mode
== RGN_COPY
)
706 result
= REGION_CopyRegion( src1Obj
, destObj
);
709 RGNOBJ
*src2Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc2
, REGION_MAGIC
);
713 if (!src1Obj
->xrgn
|| !src2Obj
->xrgn
)
715 /* Some optimizations for null regions */
721 result
= REGION_CopyRegion( src1Obj
, destObj
);
724 /* else fall through */
728 XDestroyRegion( destObj
->xrgn
);
736 #define __SRC_RGN ((src1Obj->xrgn) ? src1Obj : src2Obj)
737 result
= REGION_CopyRegion( __SRC_RGN
, destObj
);
743 /* makes gcc generate more efficient code */
746 else /* both regions are present */
748 Region destRgn
= XCreateRegion();
755 XIntersectRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destRgn
);
758 XUnionRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destRgn
);
761 XXorRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destRgn
);
764 XSubtractRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destRgn
);
767 case 0: /* makes gcc generate more efficient code */
769 XDestroyRegion( destRgn
);
774 XDestroyRegion( destObj
->xrgn
);
775 if ( XEmptyRegion( destRgn
) )
777 XDestroyRegion( destRgn
);
783 destObj
->xrgn
= destRgn
;
784 result
= COMPLEXREGION
;
789 GDI_HEAP_UNLOCK( hSrc2
);
792 GDI_HEAP_UNLOCK( hSrc1
);
794 GDI_HEAP_UNLOCK( hDest
);