4 * Copyright 1993, 1994, 1995 Alexandre Julliard
7 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
15 /***********************************************************************
18 BOOL32
REGION_DeleteObject( HRGN32 hrgn
, RGNOBJ
* obj
)
20 dprintf_region(stddeb
, "DeleteRegion: %04x\n", hrgn
);
21 if (obj
->xrgn
) XDestroyRegion( obj
->xrgn
);
22 return GDI_FreeObject( hrgn
);
26 /***********************************************************************
27 * OffsetRgn16 (GDI.101)
29 INT16
OffsetRgn16( HRGN16 hrgn
, INT16 x
, INT16 y
)
31 return OffsetRgn32( hrgn
, x
, y
);
35 /***********************************************************************
36 * OffsetRgn32 (GDI32.256)
38 INT32
OffsetRgn32( HRGN32 hrgn
, INT32 x
, INT32 y
)
40 RGNOBJ
* obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
);
41 if (!obj
) return ERROR
;
42 dprintf_region(stddeb
, "OffsetRgn: %04x %d,%d\n", hrgn
, x
, y
);
43 if (!obj
->xrgn
) return NULLREGION
;
44 XOffsetRegion( obj
->xrgn
, x
, y
);
49 /***********************************************************************
50 * GetRgnBox16 (GDI.134)
52 INT16
GetRgnBox16( HRGN16 hrgn
, LPRECT16 rect
)
54 RGNOBJ
* obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
);
55 if (!obj
) return ERROR
;
56 dprintf_region(stddeb
, "GetRgnBox: %04x\n", hrgn
);
59 SetRectEmpty16( rect
);
65 XClipBox( obj
->xrgn
, &xrect
);
66 SetRect16( rect
, xrect
.x
, xrect
.y
,
67 xrect
.x
+ xrect
.width
, xrect
.y
+ xrect
.height
);
73 /***********************************************************************
74 * GetRgnBox32 (GDI32.219)
76 INT32
GetRgnBox32( HRGN32 hrgn
, LPRECT32 rect
)
79 INT16 ret
= GetRgnBox16( hrgn
, &r
);
80 CONV_RECT16TO32( &r
, rect
);
85 /***********************************************************************
86 * CreateRectRgn16 (GDI.64)
88 HRGN16
CreateRectRgn16( INT16 left
, INT16 top
, INT16 right
, INT16 bottom
)
90 return (HRGN16
)CreateRectRgn32( left
, top
, right
, bottom
);
94 /***********************************************************************
95 * CreateRectRgn32 (GDI32.59)
97 HRGN32
CreateRectRgn32( INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
102 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
))) return 0;
103 obj
= (RGNOBJ
*) GDI_HEAP_LIN_ADDR( hrgn
);
104 if ((right
> left
) && (bottom
> top
))
106 XRectangle rect
= { left
, top
, right
- left
, bottom
- top
};
107 if (!(obj
->xrgn
= XCreateRegion()))
109 GDI_FreeObject( hrgn
);
112 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
115 dprintf_region( stddeb
, "CreateRectRgn(%d,%d-%d,%d): returning %04x\n",
116 left
, top
, right
, bottom
, hrgn
);
121 /***********************************************************************
122 * CreateRectRgnIndirect16 (GDI.65)
124 HRGN16
CreateRectRgnIndirect16( const RECT16
* rect
)
126 return CreateRectRgn32( rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
130 /***********************************************************************
131 * CreateRectRgnIndirect32 (GDI32.60)
133 HRGN32
CreateRectRgnIndirect32( const RECT32
* rect
)
135 return CreateRectRgn32( rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
139 /***********************************************************************
140 * SetRectRgn (GDI.172) (GDI32.332)
142 VOID
SetRectRgn( HRGN32 hrgn
, INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
146 dprintf_region(stddeb
, "SetRectRgn: %04x %d,%d-%d,%d\n",
147 hrgn
, left
, top
, right
, bottom
);
149 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return;
150 if (obj
->xrgn
) XDestroyRegion( obj
->xrgn
);
151 if ((right
> left
) && (bottom
> top
))
153 XRectangle rect
= { left
, top
, right
- left
, bottom
- top
};
154 if ((obj
->xrgn
= XCreateRegion()) != 0)
155 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
161 /***********************************************************************
162 * CreateRoundRectRgn16 (GDI.444)
164 HRGN16
CreateRoundRectRgn16( INT16 left
, INT16 top
, INT16 right
, INT16 bottom
,
165 INT16 ellipse_width
, INT16 ellipse_height
)
167 return (HRGN16
)CreateRoundRectRgn32( left
, top
, right
, bottom
,
168 ellipse_width
, ellipse_height
);
172 /***********************************************************************
173 * CreateRoundRectRgn32 (GDI32.61)
175 HRGN32
CreateRoundRectRgn32( INT32 left
, INT32 top
, INT32 right
, INT32 bottom
,
176 INT32 ellipse_width
, INT32 ellipse_height
)
181 int asq
, bsq
, d
, xd
, yd
;
183 /* Check if we can do a normal rectangle instead */
185 if ((right
<= left
) || (bottom
<= top
) ||
186 (ellipse_width
<= 0) || (ellipse_height
<= 0))
187 return CreateRectRgn32( left
, top
, right
, bottom
);
191 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
))) return 0;
192 obj
= (RGNOBJ
*) GDI_HEAP_LIN_ADDR( hrgn
);
193 obj
->xrgn
= XCreateRegion();
194 dprintf_region(stddeb
,"CreateRoundRectRgn(%d,%d-%d,%d %dx%d): return=%04x\n",
195 left
, top
, right
, bottom
, ellipse_width
, ellipse_height
, hrgn
);
197 /* Check parameters */
199 if (ellipse_width
> right
-left
) ellipse_width
= right
-left
;
200 if (ellipse_height
> bottom
-top
) ellipse_height
= bottom
-top
;
202 /* Ellipse algorithm, based on an article by K. Porter */
203 /* in DDJ Graphics Programming Column, 8/89 */
205 asq
= ellipse_width
* ellipse_width
/ 4; /* a^2 */
206 bsq
= ellipse_height
* ellipse_height
/ 4; /* b^2 */
207 d
= bsq
- asq
* ellipse_height
/ 2 + asq
/ 4; /* b^2 - a^2b + a^2/4 */
209 yd
= asq
* ellipse_height
; /* 2a^2b */
211 rect
.x
= left
+ ellipse_width
/ 2;
212 rect
.width
= right
- left
- ellipse_width
;
215 /* Loop to draw first half of quadrant */
219 if (d
> 0) /* if nearest pixel is toward the center */
221 /* move toward center */
223 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
225 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
229 rect
.x
--; /* next horiz point */
235 /* Loop to draw second half of quadrant */
237 d
+= (3 * (asq
-bsq
) / 2 - (xd
+yd
)) / 2;
240 /* next vertical point */
242 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
244 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
245 if (d
< 0) /* if nearest pixel is outside ellipse */
247 rect
.x
--; /* move away from center */
256 /* Add the inside rectangle */
261 rect
.height
= bottom
- top
+ 1;
262 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
268 /***********************************************************************
269 * CreateEllipticRgn16 (GDI.54)
271 HRGN16
CreateEllipticRgn16( INT16 left
, INT16 top
, INT16 right
, INT16 bottom
)
273 return (HRGN16
)CreateRoundRectRgn32( left
, top
, right
, bottom
,
274 right
-left
, bottom
-top
);
278 /***********************************************************************
279 * CreateEllipticRgn32 (GDI32.39)
281 HRGN32
CreateEllipticRgn32( INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
283 return CreateRoundRectRgn32( left
, top
, right
, bottom
,
284 right
-left
, bottom
-top
);
288 /***********************************************************************
289 * CreateEllipticRgnIndirect16 (GDI.55)
291 HRGN16
CreateEllipticRgnIndirect16( const RECT16
*rect
)
293 return CreateRoundRectRgn32( rect
->left
, rect
->top
, rect
->right
,
294 rect
->bottom
, rect
->right
- rect
->left
,
295 rect
->bottom
- rect
->top
);
299 /***********************************************************************
300 * CreateEllipticRgnIndirect32 (GDI32.40)
302 HRGN32
CreateEllipticRgnIndirect32( const RECT32
*rect
)
304 return CreateRoundRectRgn32( rect
->left
, rect
->top
, rect
->right
,
305 rect
->bottom
, rect
->right
- rect
->left
,
306 rect
->bottom
- rect
->top
);
310 /***********************************************************************
311 * CreatePolygonRgn16 (GDI.63)
313 HRGN16
CreatePolygonRgn16( const POINT16
* points
, INT16 count
, INT16 mode
)
315 return CreatePolyPolygonRgn16( points
, &count
, 1, mode
);
319 /***********************************************************************
320 * CreatePolyPolygonRgn16 (GDI.451)
322 HRGN16
CreatePolyPolygonRgn16( const POINT16
* points
, const INT16
* count
,
323 INT16 nbpolygons
, INT16 mode
)
331 for (i
=nbpolygons
;i
--;)
333 points32
= (LPPOINT32
)HeapAlloc( GetProcessHeap(), 0,
334 nrofpts
*sizeof(POINT32
) );
336 CONV_POINT16TO32( &(points
[i
]), &(points32
[i
]) );
337 count32
= (LPINT32
)HeapAlloc( GetProcessHeap(), 0,
338 sizeof(INT32
)*nbpolygons
);
339 for (i
=nbpolygons
;i
--;)
341 ret
= CreatePolyPolygonRgn32(points32
,count32
,nbpolygons
,mode
);
342 HeapFree( GetProcessHeap(), 0, count32
);
343 HeapFree( GetProcessHeap(), 0, points32
);
348 /***********************************************************************
349 * CreatePolygonRgn32 (GDI32.58)
351 HRGN32
CreatePolygonRgn32( const POINT32
*points
, INT32 count
, INT32 mode
)
353 return CreatePolyPolygonRgn32( points
, &count
, 1, mode
);
357 /***********************************************************************
358 * CreatePolyPolygonRgn32 (GDI32.57)
360 HRGN32
CreatePolyPolygonRgn32( const POINT32
* points
, const INT32
* count
,
361 INT32 nbpolygons
, INT32 mode
)
366 XPoint
*xpoints
, *pt
;
369 /* Allocate points array */
371 if (!nbpolygons
) return 0;
372 for (i
= maxPoints
= 0; i
< nbpolygons
; i
++)
373 if (maxPoints
< count
[i
]) maxPoints
= count
[i
];
374 if (!maxPoints
) return 0;
375 if (!(xpoints
= (XPoint
*)HeapAlloc( GetProcessHeap(), 0,
376 sizeof(XPoint
) * maxPoints
)))
379 /* Allocate region */
381 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
)))
383 HeapFree( GetProcessHeap(), 0, xpoints
);
386 obj
= (RGNOBJ
*) GDI_HEAP_LIN_ADDR( hrgn
);
388 dprintf_region(stddeb
, "CreatePolyPolygonRgn: %d polygons, returning %04x\n",
391 /* Create X region */
393 for (i
= 0; i
< nbpolygons
; i
++, count
++)
395 for (j
= *count
, pt
= xpoints
; j
> 0; j
--, points
++, pt
++)
400 xrgn
= XPolygonRegion( xpoints
, *count
,
401 (mode
== WINDING
) ? WindingRule
: EvenOddRule
);
404 if (obj
->xrgn
) XDestroyRegion( obj
->xrgn
);
405 HeapFree( GetProcessHeap(), 0, xpoints
);
406 GDI_FreeObject( hrgn
);
411 Region tmprgn
= XCreateRegion();
412 if (mode
== WINDING
) XUnionRegion( xrgn
, obj
->xrgn
, tmprgn
);
413 else XXorRegion( xrgn
, obj
->xrgn
, tmprgn
);
414 XDestroyRegion( obj
->xrgn
);
417 else obj
->xrgn
= xrgn
;
420 HeapFree( GetProcessHeap(), 0, xpoints
);
425 /***********************************************************************
426 * PtInRegion16 (GDI.161)
428 BOOL16
PtInRegion16( HRGN16 hrgn
, INT16 x
, INT16 y
)
430 return PtInRegion32( hrgn
, x
, y
);
434 /***********************************************************************
435 * PtInRegion32 (GDI32.278)
437 BOOL32
PtInRegion32( HRGN32 hrgn
, INT32 x
, INT32 y
)
441 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
442 if (!obj
->xrgn
) return FALSE
;
443 return XPointInRegion( obj
->xrgn
, x
, y
);
447 /***********************************************************************
448 * RectInRegion16 (GDI.181)
450 BOOL16
RectInRegion16( HRGN16 hrgn
, const RECT16
*rect
)
454 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
455 if (!obj
->xrgn
) return FALSE
;
456 return (XRectInRegion( obj
->xrgn
, rect
->left
, rect
->top
,
457 rect
->right
-rect
->left
,
458 rect
->bottom
-rect
->top
) != RectangleOut
);
462 /***********************************************************************
463 * RectInRegion32 (GDI32.281)
465 BOOL32
RectInRegion32( HRGN32 hrgn
, const RECT32
*rect
)
469 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
470 if (!obj
->xrgn
) return FALSE
;
471 return (XRectInRegion( obj
->xrgn
, rect
->left
, rect
->top
,
472 rect
->right
-rect
->left
,
473 rect
->bottom
-rect
->top
) != RectangleOut
);
477 /***********************************************************************
478 * EqualRgn16 (GDI.72)
480 BOOL16
EqualRgn16( HRGN16 rgn1
, HRGN16 rgn2
)
482 return EqualRgn32( rgn1
, rgn2
);
486 /***********************************************************************
487 * EqualRgn32 (GDI32.90)
489 BOOL32
EqualRgn32( HRGN32 rgn1
, HRGN32 rgn2
)
492 if (!(obj1
= (RGNOBJ
*) GDI_GetObjPtr( rgn1
, REGION_MAGIC
))) return FALSE
;
493 if (!(obj2
= (RGNOBJ
*) GDI_GetObjPtr( rgn2
, REGION_MAGIC
))) return FALSE
;
494 if (!obj1
->xrgn
|| !obj2
->xrgn
) return (!obj1
->xrgn
&& !obj2
->xrgn
);
495 return XEqualRegion( obj1
->xrgn
, obj2
->xrgn
);
499 /***********************************************************************
502 * Copy region src into dest.
504 static INT32
REGION_CopyRegion( RGNOBJ
*src
, RGNOBJ
*dest
)
509 if (src
->xrgn
== dest
->xrgn
) return COMPLEXREGION
;
510 tmprgn
= XCreateRegion();
511 if (!dest
->xrgn
) dest
->xrgn
= XCreateRegion();
512 XUnionRegion( tmprgn
, src
->xrgn
, dest
->xrgn
);
513 XDestroyRegion( tmprgn
);
514 return COMPLEXREGION
;
518 if (dest
->xrgn
) XDestroyRegion( dest
->xrgn
);
524 /***********************************************************************
525 * REGION_UnionRectWithRgn
527 * Add rectangle to region
529 BOOL32
REGION_UnionRectWithRgn( HRGN32 hRgn
, const RECT32
*rc
)
531 RGNOBJ
*rgnObj
= (RGNOBJ
*) GDI_GetObjPtr( hRgn
, REGION_MAGIC
);
532 XRectangle rect
= { rc
->left
, rc
->top
, rc
->right
- rc
->left
, rc
->bottom
- rc
->top
};
539 if (!(rgnObj
->xrgn
= XCreateRegion()))
541 GDI_FreeObject( hRgn
);
548 XUnionRectWithRegion( &rect
, rgnObj
->xrgn
, rgnObj
->xrgn
);
554 /***********************************************************************
555 * REGION_CreateFrameRgn
557 * Create a region that is a frame around another region
559 BOOL32
REGION_FrameRgn( HRGN32 hDest
, HRGN32 hSrc
, INT32 x
, INT32 y
)
561 RGNOBJ
*destObj
,*srcObj
;
564 destObj
= (RGNOBJ
*) GDI_GetObjPtr( hDest
, REGION_MAGIC
);
565 srcObj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc
, REGION_MAGIC
);
566 if (!srcObj
->xrgn
) return FALSE
;
567 REGION_CopyRegion( srcObj
, destObj
);
568 XShrinkRegion( destObj
->xrgn
, -x
, -y
);
569 result
= XCreateRegion();
570 XSubtractRegion( destObj
->xrgn
, srcObj
->xrgn
, result
);
571 XDestroyRegion( destObj
->xrgn
);
572 destObj
->xrgn
= result
;
577 /***********************************************************************
578 * CombineRgn16 (GDI.451)
580 INT16
CombineRgn16( HRGN16 hDest
, HRGN16 hSrc1
, HRGN16 hSrc2
, INT16 mode
)
582 return (INT16
)CombineRgn32( hDest
, hSrc1
, hSrc2
, mode
);
586 /***********************************************************************
587 * CombineRgn32 (GDI32.19)
589 * Note: The behavior is correct even if src and dest regions are the same.
591 INT32
CombineRgn32( HRGN32 hDest
, HRGN32 hSrc1
, HRGN32 hSrc2
, INT32 mode
)
593 RGNOBJ
*destObj
, *src1Obj
, *src2Obj
;
596 dprintf_region(stddeb
, "CombineRgn: %04x,%04x -> %04x mode=%x\n",
597 hSrc1
, hSrc2
, hDest
, mode
);
599 if (!(destObj
= (RGNOBJ
*) GDI_GetObjPtr( hDest
, REGION_MAGIC
)))
601 if (!(src1Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc1
, REGION_MAGIC
)))
603 if (mode
== RGN_COPY
) return REGION_CopyRegion( src1Obj
, destObj
);
605 if (!(src2Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc2
, REGION_MAGIC
)))
608 /* Some optimizations for null regions */
610 if (!src1Obj
->xrgn
|| !src2Obj
->xrgn
)
616 return REGION_CopyRegion( src1Obj
, destObj
);
617 /* else fall through */
619 if (destObj
->xrgn
) XDestroyRegion( destObj
->xrgn
);
625 return REGION_CopyRegion( src1Obj
, destObj
);
627 return REGION_CopyRegion( src2Obj
, destObj
);
633 /* Perform the operation with the two X regions */
635 if (!(destrgn
= XCreateRegion())) return ERROR
;
639 XIntersectRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
642 XUnionRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
645 XXorRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
648 XSubtractRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
651 XDestroyRegion( destrgn
);
654 if (destObj
->xrgn
) XDestroyRegion( destObj
->xrgn
);
655 destObj
->xrgn
= destrgn
;
656 if (XEmptyRegion(destObj
->xrgn
))
658 XDestroyRegion( destObj
->xrgn
);
662 return COMPLEXREGION
;