4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
12 #include <X11/Xutil.h>
15 /* GC used for region operations */
16 static GC regionGC
= 0;
18 /***********************************************************************
25 /* CreateGC needs a drawable */
26 tmpPixmap
= XCreatePixmap( display
, rootWindow
, 1, 1, 1 );
29 regionGC
= XCreateGC( XT_display
, tmpPixmap
, 0, NULL
);
30 XFreePixmap( XT_display
, tmpPixmap
);
31 if (!regionGC
) return FALSE
;
32 XSetForeground( XT_display
, regionGC
, 1 );
33 XSetGraphicsExposures( XT_display
, regionGC
, False
);
40 /***********************************************************************
43 * Set the bounding box of the region and create the pixmap.
44 * The hrgn must be valid.
46 static BOOL
REGION_SetRect( HRGN hrgn
, LPRECT rect
)
52 REGION
* region
= &((RGNOBJ
*)GDI_HEAP_ADDR( hrgn
))->region
;
53 width
= rect
->right
- rect
->left
;
54 height
= rect
->bottom
- rect
->top
;
55 if ((width
<= 0) || (height
<= 0))
57 region
->type
= NULLREGION
;
59 region
->box
.right
= 0;
61 region
->box
.bottom
= 0;
65 region
->type
= SIMPLEREGION
;
70 region
->pixmap
= XCreatePixmap( display
, rootWindow
, width
, height
, 1 );
71 if (!region
->pixmap
) return FALSE
;
75 XSetFunction( XT_display
, regionGC
, GXclear
);
76 XFillRectangle( XT_display
, region
->pixmap
, regionGC
,
77 0, 0, width
, height
);
82 /***********************************************************************
85 BOOL
REGION_DeleteObject( HRGN hrgn
, RGNOBJ
* obj
)
87 if (obj
->region
.pixmap
) XFreePixmap( XT_display
, obj
->region
.pixmap
);
88 return GDI_FreeObject( hrgn
);
92 /***********************************************************************
95 int OffsetRgn( HRGN hrgn
, short x
, short y
)
97 RGNOBJ
* obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
);
98 if (!obj
) return ERROR
;
100 printf( "OffsetRgn: %d %d,%d\n", hrgn
, x
, y
);
102 OffsetRect( &obj
->region
.box
, x
, y
);
103 return obj
->region
.type
;
107 /***********************************************************************
108 * GetRgnBox (GDI.134)
110 int GetRgnBox( HRGN hrgn
, LPRECT rect
)
112 RGNOBJ
* obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
);
113 if (!obj
) return ERROR
;
115 printf( "GetRgnBox: %d\n", hrgn
);
117 *rect
= obj
->region
.box
;
118 return obj
->region
.type
;
122 /***********************************************************************
123 * CreateRectRgn (GDI.64)
125 HRGN
CreateRectRgn( short left
, short top
, short right
, short bottom
)
127 RECT rect
= { left
, top
, right
, bottom
};
128 return CreateRectRgnIndirect( &rect
);
132 /***********************************************************************
133 * CreateRectRgnIndirect (GDI.65)
135 HRGN
CreateRectRgnIndirect( LPRECT rect
)
141 printf( "CreateRectRgnIndirect: %d,%d-%d,%d\n",
142 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
147 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
))) return 0;
148 if (!REGION_SetRect( hrgn
, rect
))
150 GDI_FreeObject( hrgn
);
153 rgnObj
= (RGNOBJ
*) GDI_HEAP_ADDR( hrgn
);
157 if (rgnObj
->region
.type
!= NULLREGION
)
159 int width
= rgnObj
->region
.box
.right
- rgnObj
->region
.box
.left
;
160 int height
= rgnObj
->region
.box
.bottom
- rgnObj
->region
.box
.top
;
161 XSetFunction( XT_display
, regionGC
, GXcopy
);
162 XFillRectangle( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
163 0, 0, width
, height
);
170 /***********************************************************************
171 * CreateRoundRectRgn (GDI.444)
173 HRGN
CreateRoundRectRgn( short left
, short top
, short right
, short bottom
,
174 short ellipse_width
, short ellipse_height
)
176 RECT rect
= { left
, top
, right
, bottom
};
181 printf( "CreateRoundRectRgn: %d,%d-%d,%d %dx%d\n",
182 left
, top
, right
, bottom
, ellipse_width
, ellipse_height
);
187 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
))) return 0;
188 if (!REGION_SetRect( hrgn
, &rect
))
190 GDI_FreeObject( hrgn
);
193 rgnObj
= (RGNOBJ
*) GDI_HEAP_ADDR( hrgn
);
197 if (rgnObj
->region
.type
!= NULLREGION
)
199 int width
= rgnObj
->region
.box
.right
- rgnObj
->region
.box
.left
;
200 int height
= rgnObj
->region
.box
.bottom
- rgnObj
->region
.box
.top
;
201 XSetFunction( XT_display
, regionGC
, GXcopy
);
202 XFillRectangle( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
203 0, ellipse_height
/ 2,
204 width
, height
- ellipse_height
);
205 XFillRectangle( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
206 ellipse_width
/ 2, 0,
207 width
- ellipse_width
, height
);
208 XFillArc( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
210 ellipse_width
, ellipse_height
, 0, 360*64 );
211 XFillArc( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
212 width
- ellipse_width
, 0,
213 ellipse_width
, ellipse_height
, 0, 360*64 );
214 XFillArc( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
215 0, height
- ellipse_height
,
216 ellipse_width
, ellipse_height
, 0, 360*64 );
217 XFillArc( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
218 width
- ellipse_width
, height
- ellipse_height
,
219 ellipse_width
, ellipse_height
, 0, 360*64 );
226 /***********************************************************************
227 * SetRectRgn (GDI.172)
229 void SetRectRgn( HRGN hrgn
, short left
, short top
, short right
, short bottom
)
231 RECT rect
= { left
, top
, right
, bottom
};
235 printf( "SetRectRgn: %d %d,%d-%d,%d\n", hrgn
, left
, top
, right
, bottom
);
238 /* Free previous pixmap */
240 if (!(rgnObj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return;
241 if (rgnObj
->region
.pixmap
)
242 XFreePixmap( XT_display
, rgnObj
->region
.pixmap
);
244 if (!REGION_SetRect( hrgn
, &rect
)) return;
248 if (rgnObj
->region
.type
!= NULLREGION
)
250 int width
= rgnObj
->region
.box
.right
- rgnObj
->region
.box
.left
;
251 int height
= rgnObj
->region
.box
.bottom
- rgnObj
->region
.box
.top
;
252 XSetFunction( XT_display
, regionGC
, GXcopy
);
253 XFillRectangle( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
254 0, 0, width
, height
);
259 /***********************************************************************
260 * CreateEllipticRgn (GDI.54)
262 HRGN
CreateEllipticRgn( short left
, short top
, short right
, short bottom
)
264 RECT rect
= { left
, top
, right
, bottom
};
265 return CreateEllipticRgnIndirect( &rect
);
269 /***********************************************************************
270 * CreateEllipticRgnIndirect (GDI.55)
272 HRGN
CreateEllipticRgnIndirect( LPRECT rect
)
278 printf( "CreateEllipticRgnIndirect: %d,%d-%d,%d\n",
279 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
284 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
))) return 0;
285 if (!REGION_SetRect( hrgn
, rect
))
287 GDI_FreeObject( hrgn
);
290 rgnObj
= (RGNOBJ
*) GDI_HEAP_ADDR( hrgn
);
294 if (rgnObj
->region
.type
!= NULLREGION
)
296 int width
= rgnObj
->region
.box
.right
- rgnObj
->region
.box
.left
;
297 int height
= rgnObj
->region
.box
.bottom
- rgnObj
->region
.box
.top
;
298 XSetFunction( XT_display
, regionGC
, GXcopy
);
299 XFillArc( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
300 0, 0, width
, height
, 0, 360*64 );
307 /***********************************************************************
308 * CreatePolygonRgn (GDI.63)
310 HRGN
CreatePolygonRgn( POINT
* points
, short count
, short mode
)
312 return CreatePolyPolygonRgn( points
, &count
, 1, mode
);
316 /***********************************************************************
317 * CreatePolyPolygonRgn (GDI.451)
319 HRGN
CreatePolyPolygonRgn( POINT
* points
, short * count
,
320 short nbpolygons
, short mode
)
325 int i
, j
, totalPoints
;
329 if (!nbpolygons
) return 0;
331 printf( "CreatePolyPolygonRgn: %d polygons\n", nbpolygons
);
334 /* Find bounding box */
336 box
.top
= box
.left
= 32767;
337 box
.right
= box
.bottom
= 0;
338 for (i
= totalPoints
= 0, pt
= points
; i
< nbpolygons
; i
++)
340 totalPoints
+= count
[i
];
341 for (j
= 0; j
< count
[i
]; j
++, pt
++)
343 if (pt
->x
< box
.left
) box
.left
= pt
->x
;
344 if (pt
->x
> box
.right
) box
.right
= pt
->x
;
345 if (pt
->y
< box
.top
) box
.top
= pt
->y
;
346 if (pt
->y
> box
.bottom
) box
.bottom
= pt
->y
;
349 if (!totalPoints
) return 0;
351 /* Build points array */
353 xpoints
= (XPoint
*) malloc( sizeof(XPoint
) * totalPoints
);
354 if (!xpoints
) return 0;
355 for (i
= 0, pt
= points
; i
< totalPoints
; i
++, pt
++)
357 xpoints
[i
].x
= pt
->x
- box
.left
;
358 xpoints
[i
].y
= pt
->y
- box
.top
;
363 if (!(hrgn
= GDI_AllocObject( sizeof(RGNOBJ
), REGION_MAGIC
)) ||
364 !REGION_SetRect( hrgn
, &box
))
366 if (hrgn
) GDI_FreeObject( hrgn
);
370 rgnObj
= (RGNOBJ
*) GDI_HEAP_ADDR( hrgn
);
374 if (rgnObj
->region
.type
!= NULLREGION
)
376 XSetFunction( XT_display
, regionGC
, GXcopy
);
377 if (mode
== WINDING
) XSetFillRule( XT_display
, regionGC
, WindingRule
);
378 else XSetFillRule( XT_display
, regionGC
, EvenOddRule
);
379 for (i
= j
= 0; i
< nbpolygons
; i
++)
381 XFillPolygon( XT_display
, rgnObj
->region
.pixmap
, regionGC
,
382 &xpoints
[j
], count
[i
], Complex
, CoordModeOrigin
);
392 /***********************************************************************
393 * PtInRegion (GDI.161)
395 BOOL
PtInRegion( HRGN hrgn
, short x
, short y
)
402 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
403 if (!PtInRect( &obj
->region
.box
, pt
)) return FALSE
;
404 image
= XGetImage( XT_display
, obj
->region
.pixmap
,
405 x
- obj
->region
.box
.left
, y
- obj
->region
.box
.top
,
406 1, 1, AllPlanes
, ZPixmap
);
407 if (!image
) return FALSE
;
408 res
= (XGetPixel( image
, 0, 0 ) != 0);
409 XDestroyImage( image
);
414 /***********************************************************************
415 * RectInRegion (GDI.181)
417 BOOL
RectInRegion( HRGN hrgn
, LPRECT rect
)
424 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( hrgn
, REGION_MAGIC
))) return FALSE
;
425 if (!IntersectRect( &intersect
, &obj
->region
.box
, rect
)) return FALSE
;
427 image
= XGetImage( XT_display
, obj
->region
.pixmap
,
428 intersect
.left
- obj
->region
.box
.left
,
429 intersect
.top
- obj
->region
.box
.top
,
430 intersect
.right
- intersect
.left
,
431 intersect
.bottom
- intersect
.top
,
432 AllPlanes
, ZPixmap
);
433 if (!image
) return FALSE
;
434 for (y
= 0; y
< image
->height
; y
++)
435 for (x
= 0; x
< image
->width
; x
++)
436 if (XGetPixel( image
, x
, y
) != 0)
438 XDestroyImage( image
);
442 XDestroyImage( image
);
447 /***********************************************************************
450 BOOL
EqualRgn( HRGN rgn1
, HRGN rgn2
)
453 XImage
*image1
, *image2
;
454 int width
, height
, x
, y
;
456 /* Compare bounding boxes */
458 if (!(obj1
= (RGNOBJ
*) GDI_GetObjPtr( rgn1
, REGION_MAGIC
))) return FALSE
;
459 if (!(obj2
= (RGNOBJ
*) GDI_GetObjPtr( rgn2
, REGION_MAGIC
))) return FALSE
;
460 if (obj1
->region
.type
== NULLREGION
)
461 return (obj2
->region
.type
== NULLREGION
);
462 else if (obj2
->region
.type
== NULLREGION
) return FALSE
;
463 if (!EqualRect( &obj1
->region
.box
, &obj2
->region
.box
)) return FALSE
;
465 /* Get pixmap contents */
467 width
= obj1
->region
.box
.right
- obj1
->region
.box
.left
;
468 height
= obj1
->region
.box
.bottom
- obj1
->region
.box
.top
;
469 image1
= XGetImage( XT_display
, obj1
->region
.pixmap
,
470 0, 0, width
, height
, AllPlanes
, ZPixmap
);
471 if (!image1
) return FALSE
;
472 image2
= XGetImage( XT_display
, obj2
->region
.pixmap
,
473 0, 0, width
, height
, AllPlanes
, ZPixmap
);
476 XDestroyImage( image1
);
480 /* Compare pixmaps */
481 for (y
= 0; y
< height
; y
++)
482 for (x
= 0; x
< width
; x
++)
483 if (XGetPixel( image1
, x
, y
) != XGetPixel( image2
, x
, y
))
485 XDestroyImage( image1
);
486 XDestroyImage( image2
);
490 XDestroyImage( image1
);
491 XDestroyImage( image2
);
496 /***********************************************************************
497 * REGION_CopyIntersection
499 * Copy to dest->pixmap the area of src->pixmap delimited by
500 * the intersection of dest and src regions, using the current GC function.
502 void REGION_CopyIntersection( REGION
* dest
, REGION
* src
)
505 if (!IntersectRect( &inter
, &dest
->box
, &src
->box
)) return;
506 XCopyArea( XT_display
, src
->pixmap
, dest
->pixmap
, regionGC
,
507 inter
.left
- src
->box
.left
, inter
.top
- src
->box
.top
,
508 inter
.right
- inter
.left
, inter
.bottom
- inter
.top
,
509 inter
.left
- dest
->box
.left
, inter
.top
- dest
->box
.top
);
513 /***********************************************************************
514 * CombineRgn (GDI.451)
516 int CombineRgn( HRGN hDest
, HRGN hSrc1
, HRGN hSrc2
, short mode
)
518 RGNOBJ
*destObj
, *src1Obj
, *src2Obj
;
524 printf( "CombineRgn: %d %d %d %d\n", hDest
, hSrc1
, hSrc2
, mode
);
527 if (!(destObj
= (RGNOBJ
*) GDI_GetObjPtr( hDest
, REGION_MAGIC
)))
529 if (!(src1Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc1
, REGION_MAGIC
)))
531 if (mode
!= RGN_COPY
)
532 if (!(src2Obj
= (RGNOBJ
*) GDI_GetObjPtr( hSrc2
, REGION_MAGIC
)))
534 region
= &destObj
->region
;
539 res
= IntersectRect( ®ion
->box
, &src1Obj
->region
.box
,
540 &src2Obj
->region
.box
);
541 region
->type
= COMPLEXREGION
;
546 res
= UnionRect( ®ion
->box
, &src1Obj
->region
.box
,
547 &src2Obj
->region
.box
);
548 region
->type
= COMPLEXREGION
;
552 res
= SubtractRect( ®ion
->box
, &src1Obj
->region
.box
,
553 &src2Obj
->region
.box
);
554 region
->type
= COMPLEXREGION
;
558 region
->box
= src1Obj
->region
.box
;
559 region
->type
= src1Obj
->region
.type
;
560 res
= (region
->type
!= NULLREGION
);
567 if (region
->pixmap
) XFreePixmap( XT_display
, region
->pixmap
);
570 region
->type
= NULLREGION
;
575 width
= region
->box
.right
- region
->box
.left
;
576 height
= region
->box
.bottom
- region
->box
.top
;
577 if (!width
|| !height
)
579 printf( "CombineRgn: width or height is 0. Please report this.\n" );
580 printf( "src1=%d,%d-%d,%d src2=%d,%d-%d,%d dst=%d,%d-%d,%d op=%d\n",
581 src1Obj
->region
.box
.left
, src1Obj
->region
.box
.top
,
582 src1Obj
->region
.box
.right
, src1Obj
->region
.box
.bottom
,
583 src2Obj
->region
.box
.left
, src2Obj
->region
.box
.top
,
584 src2Obj
->region
.box
.right
, src2Obj
->region
.box
.bottom
,
585 region
->box
.left
, region
->box
.top
,
586 region
->box
.right
, region
->box
.bottom
, mode
);
589 region
->pixmap
= XCreatePixmap( display
, rootWindow
, width
, height
, 1 );
594 XSetFunction( XT_display
, regionGC
, GXcopy
);
595 REGION_CopyIntersection( region
, &src1Obj
->region
);
596 XSetFunction( XT_display
, regionGC
, GXand
);
597 REGION_CopyIntersection( region
, &src2Obj
->region
);
602 XSetFunction( XT_display
, regionGC
, GXclear
);
603 XFillRectangle( XT_display
, region
->pixmap
, regionGC
,
604 0, 0, width
, height
);
605 XSetFunction( XT_display
, regionGC
, (mode
== RGN_OR
) ? GXor
: GXxor
);
606 REGION_CopyIntersection( region
, &src1Obj
->region
);
607 REGION_CopyIntersection( region
, &src2Obj
->region
);
611 XSetFunction( XT_display
, regionGC
, GXclear
);
612 XFillRectangle( XT_display
, region
->pixmap
, regionGC
,
613 0, 0, width
, height
);
614 XSetFunction( XT_display
, regionGC
, GXcopy
);
615 REGION_CopyIntersection( region
, &src1Obj
->region
);
616 XSetFunction( XT_display
, regionGC
, GXandInverted
);
617 REGION_CopyIntersection( region
, &src2Obj
->region
);
621 XSetFunction( XT_display
, regionGC
, GXcopy
);
622 XCopyArea( XT_display
, src1Obj
->region
.pixmap
, region
->pixmap
,
623 regionGC
, 0, 0, width
, height
, 0, 0 );