4 * Copyright 1993, 1994, 1995 Alexandre Julliard
7 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
15 /***********************************************************************
18 BOOL16
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 * OffsetRgn (GDI.101) (GDI32.256)
29 INT16
OffsetRgn( HRGN32 hrgn
, INT32 x
, INT32 y
)
31 RGNOBJ
* obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
);
32 if (!obj
) return ERROR
;
33 dprintf_region(stddeb
, "OffsetRgn: %04x %d,%d\n", hrgn
, x
, y
);
34 if (!obj
->xrgn
) return NULLREGION
;
35 XOffsetRegion( obj
->xrgn
, x
, y
);
40 /***********************************************************************
41 * GetRgnBox16 (GDI.134)
43 INT16
GetRgnBox16( HRGN16 hrgn
, LPRECT16 rect
)
45 RGNOBJ
* obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
);
46 if (!obj
) return ERROR
;
47 dprintf_region(stddeb
, "GetRgnBox: %04x\n", hrgn
);
50 SetRectEmpty16( rect
);
56 XClipBox( obj
->xrgn
, &xrect
);
57 SetRect16( rect
, xrect
.x
, xrect
.y
,
58 xrect
.x
+ xrect
.width
, xrect
.y
+ xrect
.height
);
64 /***********************************************************************
65 * GetRgnBox32 (GDI32.219)
67 INT32
GetRgnBox32( HRGN32 hrgn
, LPRECT32 rect
)
70 INT16 ret
= GetRgnBox16( hrgn
, &r
);
71 CONV_RECT16TO32( &r
, rect
);
76 /***********************************************************************
77 * CreateRectRgn (GDI.64) (GDI32.59)
79 HRGN16
CreateRectRgn( INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
84 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
))) return 0;
85 obj
= (RGNOBJ
*) GDI_HEAP_LIN_ADDR( hrgn
);
86 if ((right
> left
) && (bottom
> top
))
88 XRectangle rect
= { left
, top
, right
- left
, bottom
- top
};
89 if (!(obj
->xrgn
= XCreateRegion()))
91 GDI_FreeObject( hrgn
);
94 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
97 dprintf_region( stddeb
, "CreateRectRgn(%d,%d-%d,%d): returning %04x\n",
98 left
, top
, right
, bottom
, hrgn
);
103 /***********************************************************************
104 * CreateRectRgnIndirect16 (GDI.65)
106 HRGN16
CreateRectRgnIndirect16( const RECT16
* rect
)
108 return CreateRectRgn( rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
112 /***********************************************************************
113 * CreateRectRgnIndirect32 (GDI32.60)
115 HRGN32
CreateRectRgnIndirect32( const RECT32
* rect
)
117 return CreateRectRgn( rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
121 /***********************************************************************
122 * SetRectRgn (GDI.172) (GDI32.332)
124 VOID
SetRectRgn( HRGN32 hrgn
, INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
128 dprintf_region(stddeb
, "SetRectRgn: %04x %d,%d-%d,%d\n",
129 hrgn
, left
, top
, right
, bottom
);
131 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return;
132 if (obj
->xrgn
) XDestroyRegion( obj
->xrgn
);
133 if ((right
> left
) && (bottom
> top
))
135 XRectangle rect
= { left
, top
, right
- left
, bottom
- top
};
136 if ((obj
->xrgn
= XCreateRegion()) != 0)
137 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
143 /***********************************************************************
144 * CreateRoundRectRgn (GDI.444) (GDI32.61)
146 HRGN16
CreateRoundRectRgn( INT32 left
, INT32 top
, INT32 right
, INT32 bottom
,
147 INT32 ellipse_width
, INT32 ellipse_height
)
152 int asq
, bsq
, d
, xd
, yd
;
154 /* Check if we can do a normal rectangle instead */
156 if ((right
<= left
) || (bottom
<= top
) ||
157 (ellipse_width
<= 0) || (ellipse_height
<= 0))
158 return CreateRectRgn( left
, top
, right
, bottom
);
162 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
))) return 0;
163 obj
= (RGNOBJ
*) GDI_HEAP_LIN_ADDR( hrgn
);
164 obj
->xrgn
= XCreateRegion();
165 dprintf_region(stddeb
,"CreateRoundRectRgn(%d,%d-%d,%d %dx%d): return=%04x\n",
166 left
, top
, right
, bottom
, ellipse_width
, ellipse_height
, hrgn
);
168 /* Check parameters */
170 if (ellipse_width
> right
-left
) ellipse_width
= right
-left
;
171 if (ellipse_height
> bottom
-top
) ellipse_height
= bottom
-top
;
173 /* Ellipse algorithm, based on an article by K. Porter */
174 /* in DDJ Graphics Programming Column, 8/89 */
176 asq
= ellipse_width
* ellipse_width
/ 4; /* a^2 */
177 bsq
= ellipse_height
* ellipse_height
/ 4; /* b^2 */
178 d
= bsq
- asq
* ellipse_height
/ 2 + asq
/ 4; /* b^2 - a^2b + a^2/4 */
180 yd
= asq
* ellipse_height
; /* 2a^2b */
182 rect
.x
= left
+ ellipse_width
/ 2;
183 rect
.width
= right
- left
- ellipse_width
;
186 /* Loop to draw first half of quadrant */
190 if (d
> 0) /* if nearest pixel is toward the center */
192 /* move toward center */
194 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
196 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
200 rect
.x
--; /* next horiz point */
206 /* Loop to draw second half of quadrant */
208 d
+= (3 * (asq
-bsq
) / 2 - (xd
+yd
)) / 2;
211 /* next vertical point */
213 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
215 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
216 if (d
< 0) /* if nearest pixel is outside ellipse */
218 rect
.x
--; /* move away from center */
227 /* Add the inside rectangle */
232 rect
.height
= bottom
- top
+ 1;
233 XUnionRectWithRegion( &rect
, obj
->xrgn
, obj
->xrgn
);
239 /***********************************************************************
240 * CreateEllipticRgn (GDI.54) (GDI32.39)
242 HRGN16
CreateEllipticRgn( INT32 left
, INT32 top
, INT32 right
, INT32 bottom
)
244 return CreateRoundRectRgn( left
, top
, right
, bottom
,
245 right
-left
, bottom
-top
);
249 /***********************************************************************
250 * CreateEllipticRgnIndirect16 (GDI.55)
252 HRGN16
CreateEllipticRgnIndirect16( const RECT16
*rect
)
254 return CreateRoundRectRgn(rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
255 rect
->right
-rect
->left
, rect
->bottom
-rect
->top
);
259 /***********************************************************************
260 * CreateEllipticRgnIndirect32 (GDI32.40)
262 HRGN32
CreateEllipticRgnIndirect32( const RECT32
*rect
)
264 return CreateRoundRectRgn(rect
->left
, rect
->top
, rect
->right
, rect
->bottom
,
265 rect
->right
-rect
->left
, rect
->bottom
-rect
->top
);
269 /***********************************************************************
270 * CreatePolygonRgn16 (GDI.63)
272 HRGN16
CreatePolygonRgn16( const POINT16
* points
, INT16 count
, INT16 mode
)
274 return CreatePolyPolygonRgn16( points
, &count
, 1, mode
);
278 /***********************************************************************
279 * CreatePolyPolygonRgn16 (GDI.451)
281 HRGN16
CreatePolyPolygonRgn16( const POINT16
* points
, const INT16
* count
,
282 INT16 nbpolygons
, INT16 mode
)
287 XPoint
*xpoints
, *pt
;
290 /* Allocate points array */
292 if (!nbpolygons
) return 0;
293 for (i
= maxPoints
= 0; i
< nbpolygons
; i
++)
294 if (maxPoints
< count
[i
]) maxPoints
= count
[i
];
295 if (!maxPoints
) return 0;
296 if (!(xpoints
= (XPoint
*) malloc( sizeof(XPoint
) * maxPoints
)))
299 /* Allocate region */
301 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
)))
306 obj
= (RGNOBJ
*) GDI_HEAP_LIN_ADDR( hrgn
);
308 dprintf_region(stddeb
, "CreatePolyPolygonRgn: %d polygons, returning %04x\n",
311 /* Create X region */
313 for (i
= 0; i
< nbpolygons
; i
++, count
++)
315 for (j
= *count
, pt
= xpoints
; j
> 0; j
--, points
++, pt
++)
320 xrgn
= XPolygonRegion( xpoints
, *count
,
321 (mode
== WINDING
) ? WindingRule
: EvenOddRule
);
324 if (obj
->xrgn
) XDestroyRegion( obj
->xrgn
);
326 GDI_FreeObject( hrgn
);
331 Region tmprgn
= XCreateRegion();
332 if (mode
== WINDING
) XUnionRegion( xrgn
, obj
->xrgn
, tmprgn
);
333 else XXorRegion( xrgn
, obj
->xrgn
, tmprgn
);
334 XDestroyRegion( obj
->xrgn
);
337 else obj
->xrgn
= xrgn
;
345 /***********************************************************************
346 * PtInRegion (GDI.161) (GDI32.278)
348 BOOL16
PtInRegion( HRGN32 hrgn
, INT32 x
, INT32 y
)
352 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
353 if (!obj
->xrgn
) return FALSE
;
354 return XPointInRegion( obj
->xrgn
, x
, y
);
358 /***********************************************************************
359 * RectInRegion16 (GDI.181)
361 BOOL16
RectInRegion16( HRGN16 hrgn
, const RECT16
*rect
)
365 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
366 if (!obj
->xrgn
) return FALSE
;
367 return (XRectInRegion( obj
->xrgn
, rect
->left
, rect
->top
,
368 rect
->right
-rect
->left
,
369 rect
->bottom
-rect
->top
) != RectangleOut
);
373 /***********************************************************************
374 * RectInRegion32 (GDI32.281)
376 BOOL32
RectInRegion32( HRGN32 hrgn
, const RECT32
*rect
)
380 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
381 if (!obj
->xrgn
) return FALSE
;
382 return (XRectInRegion( obj
->xrgn
, rect
->left
, rect
->top
,
383 rect
->right
-rect
->left
,
384 rect
->bottom
-rect
->top
) != RectangleOut
);
388 /***********************************************************************
389 * EqualRgn (GDI.72) (GDI32.90)
391 BOOL16
EqualRgn( HRGN32 rgn1
, HRGN32 rgn2
)
394 if (!(obj1
= (RGNOBJ
*) GDI_GetObjPtr( rgn1
, REGION_MAGIC
))) return FALSE
;
395 if (!(obj2
= (RGNOBJ
*) GDI_GetObjPtr( rgn2
, REGION_MAGIC
))) return FALSE
;
396 if (!obj1
->xrgn
|| !obj2
->xrgn
) return (!obj1
->xrgn
&& !obj2
->xrgn
);
397 return XEqualRegion( obj1
->xrgn
, obj2
->xrgn
);
401 /***********************************************************************
404 * Copy region src into dest.
406 static int REGION_CopyRegion( RGNOBJ
*src
, RGNOBJ
*dest
)
411 if (src
->xrgn
== dest
->xrgn
) return COMPLEXREGION
;
412 tmprgn
= XCreateRegion();
413 if (!dest
->xrgn
) dest
->xrgn
= XCreateRegion();
414 XUnionRegion( tmprgn
, src
->xrgn
, dest
->xrgn
);
415 XDestroyRegion( tmprgn
);
416 return COMPLEXREGION
;
420 if (dest
->xrgn
) XDestroyRegion( dest
->xrgn
);
426 /***********************************************************************
427 * REGION_UnionRectWithRgn
429 * Add rectangle to region
431 BOOL16
REGION_UnionRectWithRgn( HRGN32 hRgn
, LPRECT16 rc
)
433 RGNOBJ
*rgnObj
= (RGNOBJ
*) GDI_GetObjPtr( hRgn
, REGION_MAGIC
);
434 XRectangle rect
= { rc
->left
, rc
->top
, rc
->right
- rc
->left
, rc
->bottom
- rc
->top
};
441 if (!(rgnObj
->xrgn
= XCreateRegion()))
443 GDI_FreeObject( hRgn
);
450 XUnionRectWithRegion( &rect
, rgnObj
->xrgn
, rgnObj
->xrgn
);
455 /***********************************************************************
456 * REGION_CreateFrameRgn
458 * Create a region that is a frame around another region
460 BOOL16
REGION_FrameRgn( HRGN32 hDest
, HRGN32 hSrc
, INT32 x
, INT32 y
)
462 RGNOBJ
*destObj
,*srcObj
;
465 destObj
= (RGNOBJ
*) GDI_GetObjPtr( hDest
, REGION_MAGIC
);
466 srcObj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc
, REGION_MAGIC
);
467 if (!srcObj
->xrgn
) return 0;
468 REGION_CopyRegion( srcObj
, destObj
);
469 XShrinkRegion( destObj
->xrgn
, -x
, -y
);
470 result
= XCreateRegion();
471 XSubtractRegion( destObj
->xrgn
, srcObj
->xrgn
, result
);
472 XDestroyRegion( destObj
->xrgn
);
473 destObj
->xrgn
= result
;
477 /***********************************************************************
478 * CombineRgn (GDI.451) (GDI32.19)
480 * The behavior is correct even if src and dest regions are the same.
482 INT16
CombineRgn( HRGN32 hDest
, HRGN32 hSrc1
, HRGN32 hSrc2
, INT32 mode
)
484 RGNOBJ
*destObj
, *src1Obj
, *src2Obj
;
487 dprintf_region(stddeb
, "CombineRgn: %04x,%04x -> %04x mode=%x\n",
488 hSrc1
, hSrc2
, hDest
, mode
);
490 if (!(destObj
= (RGNOBJ
*) GDI_GetObjPtr( hDest
, REGION_MAGIC
)))
492 if (!(src1Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc1
, REGION_MAGIC
)))
494 if (mode
== RGN_COPY
) return REGION_CopyRegion( src1Obj
, destObj
);
496 if (!(src2Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc2
, REGION_MAGIC
)))
499 /* Some optimizations for null regions */
501 if (!src1Obj
->xrgn
|| !src2Obj
->xrgn
)
507 return REGION_CopyRegion( src1Obj
, destObj
);
508 /* else fall through */
510 if (destObj
->xrgn
) XDestroyRegion( destObj
->xrgn
);
516 return REGION_CopyRegion( src1Obj
, destObj
);
518 return REGION_CopyRegion( src2Obj
, destObj
);
524 /* Perform the operation with the two X regions */
526 if (!(destrgn
= XCreateRegion())) return ERROR
;
530 XIntersectRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
533 XUnionRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
536 XXorRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
539 XSubtractRegion( src1Obj
->xrgn
, src2Obj
->xrgn
, destrgn
);
542 XDestroyRegion( destrgn
);
545 if (destObj
->xrgn
) XDestroyRegion( destObj
->xrgn
);
546 destObj
->xrgn
= destrgn
;
547 if (XEmptyRegion(destObj
->xrgn
))
549 XDestroyRegion( destObj
->xrgn
);
553 return COMPLEXREGION
;