2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
11 /* #define DEBUG_CLIPPING */
14 /***********************************************************************
15 * CLIPPING_SetDeviceClipping
17 * Set the clip region of the physical device.
19 static void CLIPPING_SetDeviceClipping( DC
* dc
)
21 RGNOBJ
*obj
= (RGNOBJ
*) GDI_GetObjPtr(dc
->w
.hGCClipRgn
, REGION_MAGIC
);
24 fprintf( stderr
, "SetDeviceClipping: Rgn is 0. Please report this.\n");
29 XSetRegion( display
, dc
->u
.x
.gc
, obj
->xrgn
);
30 XSetClipOrigin( display
, dc
->u
.x
.gc
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
32 else /* Clip everything */
34 XSetClipRectangles( display
, dc
->u
.x
.gc
, 0, 0, NULL
, 0, 0 );
39 /***********************************************************************
40 * CLIPPING_UpdateGCRegion
42 * Update the GC clip region when the ClipRgn or VisRgn have changed.
44 void CLIPPING_UpdateGCRegion( DC
* dc
)
46 if (!dc
->w
.hGCClipRgn
) dc
->w
.hGCClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
50 fprintf( stderr
, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
54 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
56 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, RGN_AND
);
57 CLIPPING_SetDeviceClipping( dc
);
61 /***********************************************************************
62 * SelectClipRgn (GDI.44)
64 int SelectClipRgn( HDC hdc
, HRGN hrgn
)
67 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
68 if (!dc
) return ERROR
;
70 dprintf_clipping(stddeb
, "SelectClipRgn: %04x %04x\n", hdc
, hrgn
);
74 if (!dc
->w
.hClipRgn
) dc
->w
.hClipRgn
= CreateRectRgn(0,0,0,0);
75 retval
= CombineRgn( dc
->w
.hClipRgn
, hrgn
, 0, RGN_COPY
);
79 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
81 retval
= SIMPLEREGION
; /* Clip region == whole DC */
83 CLIPPING_UpdateGCRegion( dc
);
88 /***********************************************************************
89 * SelectVisRgn (GDI.105)
91 int SelectVisRgn( HDC hdc
, HRGN hrgn
)
94 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
95 if (!dc
|| !hrgn
) return ERROR
;
97 dprintf_clipping(stddeb
, "SelectVisRgn: %04x %04x\n", hdc
, hrgn
);
99 retval
= CombineRgn( dc
->w
.hVisRgn
, hrgn
, 0, RGN_COPY
);
100 CLIPPING_UpdateGCRegion( dc
);
105 /***********************************************************************
106 * OffsetClipRgn (GDI.32)
108 int OffsetClipRgn( HDC hdc
, short x
, short y
)
110 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
113 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
114 if (!dc
) return ERROR
;
115 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
116 return NULLREGION
; /* ?? */
119 dprintf_clipping(stddeb
, "OffsetClipRgn: %04x %d,%d\n", hdc
, x
, y
);
123 int retval
= OffsetRgn( dc
->w
.hClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
124 CLIPPING_UpdateGCRegion( dc
);
127 else return SIMPLEREGION
; /* Clip region == client area */
131 /***********************************************************************
132 * OffsetVisRgn (GDI.102)
134 int OffsetVisRgn( HDC hdc
, short x
, short y
)
137 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
138 if (!dc
) return ERROR
;
139 dprintf_clipping(stddeb
, "OffsetVisRgn: %04x %d,%d\n", hdc
, x
, y
);
140 retval
= OffsetRgn( dc
->w
.hVisRgn
, x
, y
);
141 CLIPPING_UpdateGCRegion( dc
);
146 /***********************************************************************
147 * CLIPPING_IntersectClipRect
149 * Helper function for {Intersect,Exclude}ClipRect
151 static int CLIPPING_IntersectClipRect( DC
* dc
, short left
, short top
,
152 short right
, short bottom
, BOOL exclude
)
154 HRGN tempRgn
, newRgn
;
157 left
= XLPTODP( dc
, left
);
158 right
= XLPTODP( dc
, right
);
159 top
= YLPTODP( dc
, top
);
160 bottom
= YLPTODP( dc
, bottom
);
162 if (!(newRgn
= CreateRectRgn( 0, 0, 0, 0 ))) return ERROR
;
163 if (!(tempRgn
= CreateRectRgn( left
, top
, right
, bottom
)))
165 DeleteObject( newRgn
);
168 ret
= CombineRgn( newRgn
, dc
->w
.hClipRgn
? dc
->w
.hClipRgn
: dc
->w
.hVisRgn
,
169 tempRgn
, exclude
? RGN_DIFF
: RGN_AND
);
170 DeleteObject( tempRgn
);
174 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
175 dc
->w
.hClipRgn
= newRgn
;
176 CLIPPING_UpdateGCRegion( dc
);
178 else DeleteObject( newRgn
);
183 /***********************************************************************
184 * ExcludeClipRect (GDI.21)
186 int ExcludeClipRect( HDC hdc
, short left
, short top
,
187 short right
, short bottom
)
189 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
192 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
193 if (!dc
) return ERROR
;
194 MF_MetaParam4(dc
, META_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
195 return NULLREGION
; /* ?? */
198 dprintf_clipping(stddeb
, "ExcludeClipRect: %04x %dx%d,%dx%d\n",
199 hdc
, left
, top
, right
, bottom
);
200 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, TRUE
);
204 /***********************************************************************
205 * IntersectClipRect (GDI.22)
207 int IntersectClipRect( HDC hdc
, short left
, short top
,
208 short right
, short bottom
)
210 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
213 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
214 if (!dc
) return ERROR
;
215 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
216 return NULLREGION
; /* ?? */
219 dprintf_clipping(stddeb
, "IntersectClipRect: %04x %dx%d,%dx%d\n",
220 hdc
, left
, top
, right
, bottom
);
221 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, FALSE
);
225 /***********************************************************************
226 * CLIPPING_IntersectVisRect
228 * Helper function for {Intersect,Exclude}VisRect
230 static int CLIPPING_IntersectVisRect( DC
* dc
, short left
, short top
,
231 short right
, short bottom
, BOOL exclude
)
233 HRGN tempRgn
, newRgn
;
236 left
= XLPTODP( dc
, left
);
237 right
= XLPTODP( dc
, right
);
238 top
= YLPTODP( dc
, top
);
239 bottom
= YLPTODP( dc
, bottom
);
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: %04x %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: %04x %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: %04x %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: %04x %d,%dx%d,%d\n",
315 hdc
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
316 if (!dc
->w
.hGCClipRgn
) return FALSE
;
317 /* copy rectangle to avoid overwriting by LPtoDP */
319 LPtoDP( hdc
, (LPPOINT
)&tmpRect
, 2 );
320 return RectInRegion( dc
->w
.hGCClipRgn
, &tmpRect
);
324 /***********************************************************************
325 * GetClipBox (GDI.77)
327 int GetClipBox( HDC hdc
, LPRECT rect
)
330 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
331 if (!dc
) return ERROR
;
332 dprintf_clipping(stddeb
, "GetClipBox: %04x %p\n", hdc
, rect
);
333 ret
= GetRgnBox( dc
->w
.hGCClipRgn
, rect
);
334 DPtoLP( hdc
, (LPPOINT
)rect
, 2 );
339 /***********************************************************************
340 * SaveVisRgn (GDI.129)
342 HRGN
SaveVisRgn( HDC hdc
)
345 RGNOBJ
*obj
, *copyObj
;
346 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
348 dprintf_clipping(stddeb
, "SaveVisRgn: %04x\n", hdc
);
351 fprintf( stderr
, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
354 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
356 if (!(copy
= CreateRectRgn( 0, 0, 0, 0 ))) return 0;
357 CombineRgn( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
358 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
360 copyObj
->header
.hNext
= obj
->header
.hNext
;
361 obj
->header
.hNext
= copy
;
366 /***********************************************************************
367 * RestoreVisRgn (GDI.130)
369 int RestoreVisRgn( HDC hdc
)
372 RGNOBJ
*obj
, *savedObj
;
373 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
374 if (!dc
|| !dc
->w
.hVisRgn
) return ERROR
;
375 dprintf_clipping(stddeb
, "RestoreVisRgn: %04x\n", hdc
);
376 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
378 if (!(saved
= obj
->header
.hNext
)) return ERROR
;
379 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
381 DeleteObject( dc
->w
.hVisRgn
);
382 dc
->w
.hVisRgn
= saved
;
383 CLIPPING_UpdateGCRegion( dc
);
384 return savedObj
->xrgn
? COMPLEXREGION
: NULLREGION
;