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 static void CLIPPING_SetDeviceClipping( DC
* dc
)
24 RGNOBJ
*obj
= (RGNOBJ
*) GDI_GetObjPtr(dc
->w
.hGCClipRgn
, REGION_MAGIC
);
27 fprintf( stderr
, "SetDeviceClipping: Rgn is 0. Please report this.\n");
32 XSetRegion( display
, dc
->u
.x
.gc
, obj
->region
.xrgn
);
33 XSetClipOrigin( display
, dc
->u
.x
.gc
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
35 else if (obj
->region
.pixmap
)
37 XSetClipMask( display
, dc
->u
.x
.gc
, obj
->region
.pixmap
);
38 XSetClipOrigin( display
, dc
->u
.x
.gc
,
39 dc
->w
.DCOrgX
+ obj
->region
.box
.left
,
40 dc
->w
.DCOrgY
+ obj
->region
.box
.top
);
42 else /* Clip everything */
44 XSetClipRectangles( display
, dc
->u
.x
.gc
, 0, 0, NULL
, 0, 0 );
49 /***********************************************************************
50 * CLIPPING_UpdateGCRegion
52 * Update the GC clip region when the ClipRgn or VisRgn have changed.
54 void CLIPPING_UpdateGCRegion( DC
* dc
)
56 if (!dc
->w
.hGCClipRgn
) dc
->w
.hGCClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
60 fprintf( stderr
, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
64 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
66 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, RGN_AND
);
67 CLIPPING_SetDeviceClipping( dc
);
71 /***********************************************************************
72 * SelectClipRgn (GDI.44)
74 int SelectClipRgn( HDC hdc
, HRGN hrgn
)
77 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
78 if (!dc
) return ERROR
;
80 dprintf_clipping(stddeb
, "SelectClipRgn: %d %d\n", hdc
, hrgn
);
84 if (!dc
->w
.hClipRgn
) dc
->w
.hClipRgn
= CreateRectRgn(0,0,0,0);
85 retval
= CombineRgn( dc
->w
.hClipRgn
, hrgn
, 0, RGN_COPY
);
89 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
91 retval
= SIMPLEREGION
; /* Clip region == whole DC */
93 CLIPPING_UpdateGCRegion( dc
);
98 /***********************************************************************
99 * SelectVisRgn (GDI.105)
101 int SelectVisRgn( HDC hdc
, HRGN hrgn
)
104 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
105 if (!dc
|| !hrgn
) return ERROR
;
107 dprintf_clipping(stddeb
, "SelectVisRgn: %d %d\n", hdc
, hrgn
);
109 retval
= CombineRgn( dc
->w
.hVisRgn
, hrgn
, 0, RGN_COPY
);
110 CLIPPING_UpdateGCRegion( dc
);
115 /***********************************************************************
116 * OffsetClipRgn (GDI.32)
118 int OffsetClipRgn( HDC hdc
, short x
, short y
)
120 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
123 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
124 if (!dc
) return ERROR
;
125 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
126 return NULLREGION
; /* ?? */
129 dprintf_clipping(stddeb
, "OffsetClipRgn: %d %d,%d\n", hdc
, x
, y
);
133 int retval
= OffsetRgn( dc
->w
.hClipRgn
, x
, y
);
134 CLIPPING_UpdateGCRegion( dc
);
137 else return SIMPLEREGION
; /* Clip region == client area */
141 /***********************************************************************
142 * OffsetVisRgn (GDI.102)
144 int OffsetVisRgn( HDC hdc
, short x
, short y
)
147 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
148 if (!dc
) return ERROR
;
149 dprintf_clipping(stddeb
, "OffsetVisRgn: %d %d,%d\n", hdc
, x
, y
);
150 retval
= OffsetRgn( dc
->w
.hVisRgn
, x
, y
);
151 CLIPPING_UpdateGCRegion( dc
);
156 /***********************************************************************
157 * CLIPPING_IntersectClipRect
159 * Helper function for {Intersect,Exclude}ClipRect
161 static int CLIPPING_IntersectClipRect( DC
* dc
, short left
, short top
,
162 short right
, short bottom
, BOOL exclude
)
164 HRGN tempRgn
, newRgn
;
167 if (!(newRgn
= CreateRectRgn( 0, 0, 0, 0 ))) return ERROR
;
168 if (!(tempRgn
= CreateRectRgn( left
, top
, right
, bottom
)))
170 DeleteObject( newRgn
);
173 ret
= CombineRgn( newRgn
, dc
->w
.hClipRgn
? dc
->w
.hClipRgn
: dc
->w
.hVisRgn
,
174 tempRgn
, exclude
? RGN_DIFF
: RGN_AND
);
175 DeleteObject( tempRgn
);
179 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
180 dc
->w
.hClipRgn
= newRgn
;
181 CLIPPING_UpdateGCRegion( dc
);
183 else DeleteObject( newRgn
);
188 /***********************************************************************
189 * ExcludeClipRect (GDI.21)
191 int ExcludeClipRect( HDC hdc
, short left
, short top
,
192 short right
, short bottom
)
194 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
197 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
198 if (!dc
) return ERROR
;
199 MF_MetaParam4(dc
, META_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
200 return NULLREGION
; /* ?? */
203 dprintf_clipping(stddeb
, "ExcludeClipRect: %d %dx%d,%dx%d\n",
204 hdc
, left
, top
, right
, bottom
);
205 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, TRUE
);
209 /***********************************************************************
210 * IntersectClipRect (GDI.22)
212 int IntersectClipRect( HDC hdc
, short left
, short top
,
213 short right
, short bottom
)
215 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
218 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
219 if (!dc
) return ERROR
;
220 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
221 return NULLREGION
; /* ?? */
224 dprintf_clipping(stddeb
, "IntersectClipRect: %d %dx%d,%dx%d\n",
225 hdc
, left
, top
, right
, bottom
);
226 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, FALSE
);
230 /***********************************************************************
231 * CLIPPING_IntersectVisRect
233 * Helper function for {Intersect,Exclude}VisRect
235 static int CLIPPING_IntersectVisRect( DC
* dc
, short left
, short top
,
236 short right
, short bottom
, BOOL exclude
)
238 HRGN tempRgn
, newRgn
;
241 if (!(newRgn
= CreateRectRgn( 0, 0, 0, 0 ))) return ERROR
;
242 if (!(tempRgn
= CreateRectRgn( left
, top
, right
, bottom
)))
244 DeleteObject( newRgn
);
247 ret
= CombineRgn( newRgn
, dc
->w
.hVisRgn
, tempRgn
,
248 exclude
? RGN_DIFF
: RGN_AND
);
249 DeleteObject( tempRgn
);
253 RGNOBJ
*newObj
= (RGNOBJ
*)GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
254 RGNOBJ
*prevObj
= (RGNOBJ
*)GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
);
255 if (newObj
&& prevObj
) newObj
->header
.hNext
= prevObj
->header
.hNext
;
256 DeleteObject( dc
->w
.hVisRgn
);
257 dc
->w
.hVisRgn
= newRgn
;
258 CLIPPING_UpdateGCRegion( dc
);
260 else DeleteObject( newRgn
);
265 /***********************************************************************
266 * ExcludeVisRect (GDI.73)
268 int ExcludeVisRect( HDC hdc
, short left
, short top
, short right
, short bottom
)
270 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
271 if (!dc
) return ERROR
;
272 dprintf_clipping(stddeb
, "ExcludeVisRect: %d %dx%d,%dx%d\n",
273 hdc
, left
, top
, right
, bottom
);
274 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, TRUE
);
278 /***********************************************************************
279 * IntersectVisRect (GDI.98)
281 int IntersectVisRect( HDC hdc
, short left
, short top
,
282 short right
, short bottom
)
284 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
285 if (!dc
) return ERROR
;
286 dprintf_clipping(stddeb
, "IntersectVisRect: %d %dx%d,%dx%d\n",
287 hdc
, left
, top
, right
, bottom
);
288 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, FALSE
);
292 /***********************************************************************
293 * PtVisible (GDI.103)
295 BOOL
PtVisible( HDC hdc
, short x
, short y
)
297 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
298 if (!dc
) return ERROR
;
300 dprintf_clipping(stddeb
, "PtVisible: %d %d,%d\n", hdc
, x
, y
);
301 if (!dc
->w
.hGCClipRgn
) return FALSE
;
302 return PtInRegion( dc
->w
.hGCClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
306 /***********************************************************************
307 * RectVisible (GDI.104)
309 BOOL
RectVisible( HDC hdc
, LPRECT rect
)
312 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
313 if (!dc
) return FALSE
;
314 dprintf_clipping(stddeb
,"RectVisible: %d %p\n", hdc
, rect
);
315 if (!dc
->w
.hGCClipRgn
) return FALSE
;
316 tmpRect
.left
= XLPTODP(dc
, rect
->left
);
317 tmpRect
.top
= YLPTODP(dc
, rect
->top
);
318 tmpRect
.right
= XLPTODP(dc
, rect
->right
);
319 tmpRect
.bottom
= YLPTODP(dc
, rect
->bottom
);
320 return RectInRegion( dc
->w
.hGCClipRgn
, &tmpRect
);
324 /***********************************************************************
325 * GetClipBox (GDI.77)
327 int GetClipBox( HDC hdc
, LPRECT rect
)
329 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
330 if (!dc
) return ERROR
;
331 dprintf_clipping(stddeb
, "GetClipBox: %d %p\n", hdc
, rect
);
332 return GetRgnBox( dc
->w
.hGCClipRgn
, rect
);
336 /***********************************************************************
337 * SaveVisRgn (GDI.129)
339 HRGN
SaveVisRgn( HDC hdc
)
342 RGNOBJ
*obj
, *copyObj
;
343 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
345 dprintf_clipping(stddeb
, "SaveVisRgn: %d\n", hdc
);
348 fprintf( stderr
, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
351 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
353 if (!(copy
= CreateRectRgn( 0, 0, 0, 0 ))) return 0;
354 CombineRgn( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
355 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
357 copyObj
->header
.hNext
= obj
->header
.hNext
;
358 obj
->header
.hNext
= copy
;
363 /***********************************************************************
364 * RestoreVisRgn (GDI.130)
366 int RestoreVisRgn( HDC hdc
)
369 RGNOBJ
*obj
, *savedObj
;
370 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
371 if (!dc
|| !dc
->w
.hVisRgn
) return ERROR
;
372 dprintf_clipping(stddeb
, "RestoreVisRgn: %d\n", hdc
);
373 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
375 if (!(saved
= obj
->header
.hNext
)) return ERROR
;
376 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
378 DeleteObject( dc
->w
.hVisRgn
);
379 dc
->w
.hVisRgn
= saved
;
380 CLIPPING_UpdateGCRegion( dc
);
381 return savedObj
->region
.type
;