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
->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 /***********************************************************************
47 * CLIPPING_UpdateGCRegion
49 * Update the GC clip region when the ClipRgn or VisRgn have changed.
51 void CLIPPING_UpdateGCRegion( DC
* dc
)
53 if (!dc
->w
.hGCClipRgn
) dc
->w
.hGCClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
57 fprintf( stderr
, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
61 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
63 CombineRgn( dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, RGN_AND
);
64 CLIPPING_SetDeviceClipping( dc
);
68 /***********************************************************************
69 * SelectClipRgn (GDI.44)
71 int SelectClipRgn( HDC hdc
, HRGN hrgn
)
74 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
75 if (!dc
) return ERROR
;
77 dprintf_clipping(stddeb
, "SelectClipRgn: %d %d\n", hdc
, hrgn
);
81 if (!dc
->w
.hClipRgn
) dc
->w
.hClipRgn
= CreateRectRgn(0,0,0,0);
82 retval
= CombineRgn( dc
->w
.hClipRgn
, hrgn
, 0, RGN_COPY
);
86 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
88 retval
= SIMPLEREGION
; /* Clip region == whole DC */
90 CLIPPING_UpdateGCRegion( dc
);
95 /***********************************************************************
96 * SelectVisRgn (GDI.105)
98 int SelectVisRgn( HDC hdc
, HRGN hrgn
)
101 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
102 if (!dc
|| !hrgn
) return ERROR
;
104 dprintf_clipping(stddeb
, "SelectVisRgn: %d %d\n", hdc
, hrgn
);
106 retval
= CombineRgn( dc
->w
.hVisRgn
, hrgn
, 0, RGN_COPY
);
107 CLIPPING_UpdateGCRegion( dc
);
112 /***********************************************************************
113 * OffsetClipRgn (GDI.32)
115 int OffsetClipRgn( HDC hdc
, short x
, short y
)
117 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
120 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
121 if (!dc
) return ERROR
;
122 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
123 return NULLREGION
; /* ?? */
126 dprintf_clipping(stddeb
, "OffsetClipRgn: %d %d,%d\n", hdc
, x
, y
);
130 int retval
= OffsetRgn( dc
->w
.hClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
131 CLIPPING_UpdateGCRegion( dc
);
134 else return SIMPLEREGION
; /* Clip region == client area */
138 /***********************************************************************
139 * OffsetVisRgn (GDI.102)
141 int OffsetVisRgn( HDC hdc
, short x
, short y
)
144 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
145 if (!dc
) return ERROR
;
146 dprintf_clipping(stddeb
, "OffsetVisRgn: %d %d,%d\n", hdc
, x
, y
);
147 retval
= OffsetRgn( dc
->w
.hVisRgn
, x
, y
);
148 CLIPPING_UpdateGCRegion( dc
);
153 /***********************************************************************
154 * CLIPPING_IntersectClipRect
156 * Helper function for {Intersect,Exclude}ClipRect
158 static int CLIPPING_IntersectClipRect( DC
* dc
, short left
, short top
,
159 short right
, short bottom
, BOOL exclude
)
161 HRGN tempRgn
, newRgn
;
164 left
= XLPTODP( dc
, left
);
165 right
= XLPTODP( dc
, right
);
166 top
= YLPTODP( dc
, top
);
167 bottom
= YLPTODP( dc
, bottom
);
169 if (!(newRgn
= CreateRectRgn( 0, 0, 0, 0 ))) return ERROR
;
170 if (!(tempRgn
= CreateRectRgn( left
, top
, right
, bottom
)))
172 DeleteObject( newRgn
);
175 ret
= CombineRgn( newRgn
, dc
->w
.hClipRgn
? dc
->w
.hClipRgn
: dc
->w
.hVisRgn
,
176 tempRgn
, exclude
? RGN_DIFF
: RGN_AND
);
177 DeleteObject( tempRgn
);
181 if (dc
->w
.hClipRgn
) DeleteObject( dc
->w
.hClipRgn
);
182 dc
->w
.hClipRgn
= newRgn
;
183 CLIPPING_UpdateGCRegion( dc
);
185 else DeleteObject( newRgn
);
190 /***********************************************************************
191 * ExcludeClipRect (GDI.21)
193 int ExcludeClipRect( HDC hdc
, short left
, short top
,
194 short right
, short bottom
)
196 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
199 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
200 if (!dc
) return ERROR
;
201 MF_MetaParam4(dc
, META_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
202 return NULLREGION
; /* ?? */
205 dprintf_clipping(stddeb
, "ExcludeClipRect: %d %dx%d,%dx%d\n",
206 hdc
, left
, top
, right
, bottom
);
207 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, TRUE
);
211 /***********************************************************************
212 * IntersectClipRect (GDI.22)
214 int IntersectClipRect( HDC hdc
, short left
, short top
,
215 short right
, short bottom
)
217 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
220 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
221 if (!dc
) return ERROR
;
222 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
223 return NULLREGION
; /* ?? */
226 dprintf_clipping(stddeb
, "IntersectClipRect: %d %dx%d,%dx%d\n",
227 hdc
, left
, top
, right
, bottom
);
228 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, FALSE
);
232 /***********************************************************************
233 * CLIPPING_IntersectVisRect
235 * Helper function for {Intersect,Exclude}VisRect
237 static int CLIPPING_IntersectVisRect( DC
* dc
, short left
, short top
,
238 short right
, short bottom
, BOOL exclude
)
240 HRGN tempRgn
, newRgn
;
243 left
= XLPTODP( dc
, left
);
244 right
= XLPTODP( dc
, right
);
245 top
= YLPTODP( dc
, top
);
246 bottom
= YLPTODP( dc
, bottom
);
248 if (!(newRgn
= CreateRectRgn( 0, 0, 0, 0 ))) return ERROR
;
249 if (!(tempRgn
= CreateRectRgn( left
, top
, right
, bottom
)))
251 DeleteObject( newRgn
);
254 ret
= CombineRgn( newRgn
, dc
->w
.hVisRgn
, tempRgn
,
255 exclude
? RGN_DIFF
: RGN_AND
);
256 DeleteObject( tempRgn
);
260 RGNOBJ
*newObj
= (RGNOBJ
*)GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
261 RGNOBJ
*prevObj
= (RGNOBJ
*)GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
);
262 if (newObj
&& prevObj
) newObj
->header
.hNext
= prevObj
->header
.hNext
;
263 DeleteObject( dc
->w
.hVisRgn
);
264 dc
->w
.hVisRgn
= newRgn
;
265 CLIPPING_UpdateGCRegion( dc
);
267 else DeleteObject( newRgn
);
272 /***********************************************************************
273 * ExcludeVisRect (GDI.73)
275 int ExcludeVisRect( HDC hdc
, short left
, short top
, short right
, short bottom
)
277 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
278 if (!dc
) return ERROR
;
279 dprintf_clipping(stddeb
, "ExcludeVisRect: %d %dx%d,%dx%d\n",
280 hdc
, left
, top
, right
, bottom
);
281 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, TRUE
);
285 /***********************************************************************
286 * IntersectVisRect (GDI.98)
288 int IntersectVisRect( HDC hdc
, short left
, short top
,
289 short right
, short bottom
)
291 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
292 if (!dc
) return ERROR
;
293 dprintf_clipping(stddeb
, "IntersectVisRect: %d %dx%d,%dx%d\n",
294 hdc
, left
, top
, right
, bottom
);
295 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, FALSE
);
299 /***********************************************************************
300 * PtVisible (GDI.103)
302 BOOL
PtVisible( HDC hdc
, short x
, short y
)
304 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
305 if (!dc
) return ERROR
;
307 dprintf_clipping(stddeb
, "PtVisible: %d %d,%d\n", hdc
, x
, y
);
308 if (!dc
->w
.hGCClipRgn
) return FALSE
;
309 return PtInRegion( dc
->w
.hGCClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
313 /***********************************************************************
314 * RectVisible (GDI.104)
316 BOOL
RectVisible( HDC hdc
, LPRECT rect
)
319 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
320 if (!dc
) return FALSE
;
321 dprintf_clipping(stddeb
,"RectVisible: %d %p\n", hdc
, rect
);
322 if (!dc
->w
.hGCClipRgn
) return FALSE
;
323 LPtoDP( hdc
, (LPPOINT
)rect
, 2 );
324 return RectInRegion( dc
->w
.hGCClipRgn
, &tmpRect
);
328 /***********************************************************************
329 * GetClipBox (GDI.77)
331 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
);
337 ret
= GetRgnBox( dc
->w
.hGCClipRgn
, rect
);
338 DPtoLP( hdc
, (LPPOINT
)rect
, 2 );
343 /***********************************************************************
344 * SaveVisRgn (GDI.129)
346 HRGN
SaveVisRgn( HDC hdc
)
349 RGNOBJ
*obj
, *copyObj
;
350 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
352 dprintf_clipping(stddeb
, "SaveVisRgn: %d\n", hdc
);
355 fprintf( stderr
, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
358 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
360 if (!(copy
= CreateRectRgn( 0, 0, 0, 0 ))) return 0;
361 CombineRgn( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
362 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
364 copyObj
->header
.hNext
= obj
->header
.hNext
;
365 obj
->header
.hNext
= copy
;
370 /***********************************************************************
371 * RestoreVisRgn (GDI.130)
373 int RestoreVisRgn( HDC hdc
)
376 RGNOBJ
*obj
, *savedObj
;
377 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
378 if (!dc
|| !dc
->w
.hVisRgn
) return ERROR
;
379 dprintf_clipping(stddeb
, "RestoreVisRgn: %d\n", hdc
);
380 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
382 if (!(saved
= obj
->header
.hNext
)) return ERROR
;
383 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
385 DeleteObject( dc
->w
.hVisRgn
);
386 dc
->w
.hVisRgn
= saved
;
387 CLIPPING_UpdateGCRegion( dc
);
388 return savedObj
->region
.type
;