2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
13 /* #define DEBUG_CLIPPING /* */
14 /* #undef DEBUG_CLIPPING /* */
17 /***********************************************************************
18 * CLIPPING_SetDeviceClipping
20 * Set the clip region of the physical device.
22 void CLIPPING_SetDeviceClipping( DC
* dc
)
26 RGNOBJ
*obj
= (RGNOBJ
*) GDI_GetObjPtr(dc
->w
.hGCClipRgn
, REGION_MAGIC
);
29 XSetRegion( display
, dc
->u
.x
.gc
, obj
->region
.xrgn
);
30 XSetClipOrigin( display
, dc
->u
.x
.gc
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
32 else if (obj
->region
.pixmap
)
34 XSetClipMask( display
, dc
->u
.x
.gc
, obj
->region
.pixmap
);
35 XSetClipOrigin( display
, dc
->u
.x
.gc
,
36 dc
->w
.DCOrgX
+ obj
->region
.box
.left
,
37 dc
->w
.DCOrgY
+ obj
->region
.box
.top
);
39 else /* Clip everything */
41 XSetClipRectangles( display
, dc
->u
.x
.gc
, 0, 0, NULL
, 0, 0 );
46 XSetClipMask( display
, dc
->u
.x
.gc
, None
);
47 XSetClipOrigin( display
, dc
->u
.x
.gc
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
52 /***********************************************************************
53 * CLIPPING_UpdateGCRegion
55 * Update the GC clip region when the ClipRgn or VisRgn have changed.
57 static void CLIPPING_UpdateGCRegion( DC
* dc
)
59 if (!dc
->w
.hGCClipRgn
) dc
->w
.hGCClipRgn
= CreateRectRgn(0,0,0,0);
65 DeleteObject( dc
->w
.hGCClipRgn
);
69 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
74 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
76 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, RGN_AND
);
78 CLIPPING_SetDeviceClipping( dc
);
82 /***********************************************************************
85 * Helper function for SelectClipRgn() and SelectVisRgn().
87 static int CLIPPING_SelectRgn( DC
* dc
, HRGN
* hrgnPrev
, HRGN hrgn
)
93 if (!*hrgnPrev
) *hrgnPrev
= CreateRectRgn(0,0,0,0);
94 retval
= CombineRgn( *hrgnPrev
, hrgn
, 0, RGN_COPY
);
98 if (*hrgnPrev
) DeleteObject( *hrgnPrev
);
100 retval
= SIMPLEREGION
; /* Clip region == client area */
102 CLIPPING_UpdateGCRegion( dc
);
107 /***********************************************************************
108 * SelectClipRgn (GDI.44)
110 int SelectClipRgn( HDC hdc
, HRGN hrgn
)
112 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
113 if (!dc
) return ERROR
;
115 dprintf_clipping(stddeb
, "SelectClipRgn: %d %d\n", hdc
, hrgn
);
116 return CLIPPING_SelectRgn( dc
, &dc
->w
.hClipRgn
, hrgn
);
120 /***********************************************************************
121 * SelectVisRgn (GDI.105)
123 int SelectVisRgn( HDC hdc
, HRGN hrgn
)
125 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
126 if (!dc
) return ERROR
;
128 dprintf_clipping(stddeb
, "SelectVisRgn: %d %d\n", hdc
, hrgn
);
129 return CLIPPING_SelectRgn( dc
, &dc
->w
.hVisRgn
, hrgn
);
133 /***********************************************************************
134 * OffsetClipRgn (GDI.32)
136 int OffsetClipRgn( HDC hdc
, short x
, short y
)
138 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
141 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
142 if (!dc
) return ERROR
;
143 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
144 return NULLREGION
; /* ?? */
147 dprintf_clipping(stddeb
, "OffsetClipRgn: %d %d,%d\n", hdc
, x
, y
);
151 int retval
= OffsetRgn( dc
->w
.hClipRgn
, x
, y
);
152 CLIPPING_UpdateGCRegion( dc
);
155 else return SIMPLEREGION
; /* Clip region == client area */
159 /***********************************************************************
160 * OffsetVisRgn (GDI.102)
162 int OffsetVisRgn( HDC hdc
, short x
, short y
)
164 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
165 if (!dc
) return ERROR
;
166 dprintf_clipping(stddeb
, "OffsetVisRgn: %d %d,%d\n", hdc
, x
, y
);
170 int retval
= OffsetRgn( dc
->w
.hVisRgn
, x
, y
);
171 CLIPPING_UpdateGCRegion( dc
);
174 else return SIMPLEREGION
; /* Clip region == client area */
178 /***********************************************************************
179 * CLIPPING_IntersectRect
181 * Helper function for {Intersect,Exclude}{Clip,Vis}Rect
183 int CLIPPING_IntersectRect( DC
* dc
, HRGN
* hrgn
, short left
, short top
,
184 short right
, short bottom
, int exclude
)
186 HRGN tempRgn
= 0, prevRgn
= 0, newRgn
= 0;
187 RGNOBJ
*newObj
, *prevObj
;
192 if (!(*hrgn
= CreateRectRgn( 0, 0, dc
->w
.DCSizeX
, dc
->w
.DCSizeY
)))
196 if (!(newRgn
= CreateRectRgn( 0, 0, 0, 0))) goto Error
;
197 if (!(tempRgn
= CreateRectRgn( left
, top
, right
, bottom
))) goto Error
;
199 retval
= CombineRgn( newRgn
, *hrgn
, tempRgn
, exclude
? RGN_DIFF
: RGN_AND
);
200 if (retval
== ERROR
) goto Error
;
202 newObj
= (RGNOBJ
*) GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
203 prevObj
= (RGNOBJ
*) GDI_GetObjPtr( *hrgn
, REGION_MAGIC
);
204 if (newObj
&& prevObj
) newObj
->header
.hNext
= prevObj
->header
.hNext
;
205 DeleteObject( tempRgn
);
206 if (*hrgn
) DeleteObject( *hrgn
);
208 CLIPPING_UpdateGCRegion( dc
);
212 if (tempRgn
) DeleteObject( tempRgn
);
213 if (newRgn
) DeleteObject( newRgn
);
216 DeleteObject( prevRgn
);
223 /***********************************************************************
224 * ExcludeClipRect (GDI.21)
226 int ExcludeClipRect( HDC hdc
, short left
, short top
,
227 short right
, short bottom
)
229 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
232 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
233 if (!dc
) return ERROR
;
234 MF_MetaParam4(dc
, META_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
235 return NULLREGION
; /* ?? */
238 dprintf_clipping(stddeb
, "ExcludeClipRect: %d %dx%d,%dx%d\n",
239 hdc
, left
, top
, right
, bottom
);
240 return CLIPPING_IntersectRect( dc
, &dc
->w
.hClipRgn
, left
, top
,
245 /***********************************************************************
246 * IntersectClipRect (GDI.22)
248 int IntersectClipRect( HDC hdc
, short left
, short top
,
249 short right
, short bottom
)
251 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
254 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
255 if (!dc
) return ERROR
;
256 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
257 return NULLREGION
; /* ?? */
260 dprintf_clipping(stddeb
, "IntersectClipRect: %d %dx%d,%dx%d\n",
261 hdc
, left
, top
, right
, bottom
);
262 return CLIPPING_IntersectRect( dc
, &dc
->w
.hClipRgn
, left
, top
,
267 /***********************************************************************
268 * ExcludeVisRect (GDI.73)
270 int ExcludeVisRect( HDC hdc
, short left
, short top
,
271 short right
, short bottom
)
273 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
274 if (!dc
) return ERROR
;
275 dprintf_clipping(stddeb
, "ExcludeVisRect: %d %dx%d,%dx%d\n",
276 hdc
, left
, top
, right
, bottom
);
277 return CLIPPING_IntersectRect( dc
, &dc
->w
.hVisRgn
, left
, top
,
282 /***********************************************************************
283 * IntersectVisRect (GDI.98)
285 int IntersectVisRect( HDC hdc
, short left
, short top
,
286 short right
, short bottom
)
288 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
289 if (!dc
) return ERROR
;
290 dprintf_clipping(stddeb
, "IntersectVisRect: %d %dx%d,%dx%d\n",
291 hdc
, left
, top
, right
, bottom
);
292 return CLIPPING_IntersectRect( dc
, &dc
->w
.hVisRgn
, left
, top
,
297 /***********************************************************************
298 * PtVisible (GDI.103)
300 BOOL
PtVisible( HDC hdc
, short x
, short y
)
302 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
303 if (!dc
) return ERROR
;
305 dprintf_clipping(stddeb
, "PtVisible: %d %d,%d\n", hdc
, x
, y
);
306 if (!dc
->w
.hGCClipRgn
) return FALSE
;
307 return PtInRegion( dc
->w
.hGCClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
311 /***********************************************************************
312 * RectVisible (GDI.104)
314 BOOL
RectVisible( HDC hdc
, LPRECT rect
)
317 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
318 if (!dc
) return FALSE
;
319 dprintf_clipping(stddeb
,"RectVisible: %d %p\n", hdc
, rect
);
320 if (!dc
->w
.hGCClipRgn
) return FALSE
;
321 tmpRect
.left
= XLPTODP(dc
, rect
->left
);
322 tmpRect
.top
= YLPTODP(dc
, rect
->top
);
323 tmpRect
.right
= XLPTODP(dc
, rect
->right
);
324 tmpRect
.bottom
= YLPTODP(dc
, rect
->bottom
);
325 return RectInRegion( dc
->w
.hGCClipRgn
, &tmpRect
);
329 /***********************************************************************
330 * GetClipBox (GDI.77)
332 int GetClipBox( HDC hdc
, LPRECT rect
)
334 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
335 if (!dc
) return ERROR
;
336 dprintf_clipping(stddeb
, "GetClipBox: %d %p\n", hdc
, rect
);
338 if (dc
->w
.hGCClipRgn
) return GetRgnBox( dc
->w
.hGCClipRgn
, rect
);
341 rect
->top
= rect
->left
= 0;
342 rect
->right
= dc
->w
.DCSizeX
;
343 rect
->bottom
= dc
->w
.DCSizeY
;
349 /***********************************************************************
350 * SaveVisRgn (GDI.129)
352 HRGN
SaveVisRgn( HDC hdc
)
355 RGNOBJ
*obj
, *copyObj
;
356 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
358 dprintf_clipping(stddeb
, "SaveVisRgn: %d\n", hdc
);
359 if (!dc
->w
.hVisRgn
) return 0;
360 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
362 if (!(copy
= CreateRectRgn( 0, 0, 0, 0 ))) return 0;
363 CombineRgn( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
364 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
366 copyObj
->header
.hNext
= obj
->header
.hNext
;
367 obj
->header
.hNext
= copy
;
372 /***********************************************************************
373 * RestoreVisRgn (GDI.130)
375 int RestoreVisRgn( HDC hdc
)
378 RGNOBJ
*obj
, *savedObj
;
379 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
380 if (!dc
) return ERROR
;
381 dprintf_clipping(stddeb
, "RestoreVisRgn: %d\n", hdc
);
382 if (!dc
->w
.hVisRgn
) return ERROR
;
383 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
385 if (!(saved
= obj
->header
.hNext
)) return ERROR
;
386 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
388 DeleteObject( dc
->w
.hVisRgn
);
389 dc
->w
.hVisRgn
= saved
;
390 CLIPPING_UpdateGCRegion( dc
);
391 return savedObj
->region
.type
;