2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
14 #define UPDATE_DIRTY_DC(dc) \
16 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
17 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
22 /***********************************************************************
23 * CLIPPING_UpdateGCRegion
25 * Update the GC clip region when the ClipRgn or VisRgn have changed.
27 void CLIPPING_UpdateGCRegion( DC
* dc
)
29 if (!dc
->w
.hGCClipRgn
) dc
->w
.hGCClipRgn
= CreateRectRgn32( 0, 0, 0, 0 );
33 fprintf( stderr
, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
37 if (dc
->w
.flags
& DC_DIRTY
)
40 dc
->w
.flags
&= ~DC_DIRTY
;
44 CombineRgn32( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
46 CombineRgn32(dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, RGN_AND
);
47 if (dc
->funcs
->pSetDeviceClipping
) dc
->funcs
->pSetDeviceClipping( dc
);
51 /***********************************************************************
52 * SelectClipRgn16 (GDI.44)
54 INT16
SelectClipRgn16( HDC16 hdc
, HRGN16 hrgn
)
56 return (INT16
)SelectClipRgn32( hdc
, hrgn
);
60 /***********************************************************************
61 * SelectClipRgn32 (GDI32.297)
63 INT32
SelectClipRgn32( HDC32 hdc
, HRGN32 hrgn
)
66 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
67 if (!dc
) return ERROR
;
69 dprintf_clipping(stddeb
, "SelectClipRgn: %04x %04x\n", hdc
, hrgn
);
73 if (!dc
->w
.hClipRgn
) dc
->w
.hClipRgn
= CreateRectRgn32(0,0,0,0);
74 retval
= CombineRgn32( dc
->w
.hClipRgn
, hrgn
, 0, RGN_COPY
);
78 if (dc
->w
.hClipRgn
) DeleteObject16( dc
->w
.hClipRgn
);
80 retval
= SIMPLEREGION
; /* Clip region == whole DC */
83 CLIPPING_UpdateGCRegion( dc
);
88 /***********************************************************************
89 * SelectVisRgn (GDI.105)
91 INT16
SelectVisRgn( HDC16 hdc
, HRGN16 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 dc
->w
.flags
&= ~DC_DIRTY
;
101 retval
= CombineRgn16( dc
->w
.hVisRgn
, hrgn
, 0, RGN_COPY
);
102 CLIPPING_UpdateGCRegion( dc
);
107 /***********************************************************************
108 * OffsetClipRgn16 (GDI.32)
110 INT16
OffsetClipRgn16( HDC16 hdc
, INT16 x
, INT16 y
)
112 return (INT16
)OffsetClipRgn32( hdc
, x
, y
);
116 /***********************************************************************
117 * OffsetClipRgn32 (GDI32.255)
119 INT32
OffsetClipRgn32( HDC32 hdc
, INT32 x
, INT32 y
)
121 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
124 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
125 if (!dc
) return ERROR
;
126 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
127 return NULLREGION
; /* ?? */
130 dprintf_clipping(stddeb
, "OffsetClipRgn: %04x %d,%d\n", hdc
, x
, y
);
134 INT32 ret
= OffsetRgn32( dc
->w
.hClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
));
135 CLIPPING_UpdateGCRegion( dc
);
138 else return SIMPLEREGION
; /* Clip region == client area */
142 /***********************************************************************
143 * OffsetVisRgn (GDI.102)
145 INT16
OffsetVisRgn( HDC16 hdc
, INT16 x
, INT16 y
)
148 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
149 if (!dc
) return ERROR
;
150 dprintf_clipping(stddeb
, "OffsetVisRgn: %04x %d,%d\n", hdc
, x
, y
);
151 retval
= OffsetRgn32( dc
->w
.hVisRgn
, x
, y
);
152 CLIPPING_UpdateGCRegion( dc
);
157 /***********************************************************************
158 * CLIPPING_IntersectClipRect
160 * Helper function for {Intersect,Exclude}ClipRect, can be called from
161 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
162 * coordinate conversion.
164 INT32
CLIPPING_IntersectClipRect( DC
* dc
, INT32 left
, INT32 top
,
165 INT32 right
, INT32 bottom
, UINT32 flags
)
170 if (!(newRgn
= CreateRectRgn32( left
, top
, right
, bottom
))) return ERROR
;
173 if( flags
& CLIP_INTERSECT
)
175 dc
->w
.hClipRgn
= newRgn
;
176 CLIPPING_UpdateGCRegion( dc
);
181 ret
= CombineRgn32( newRgn
, dc
->w
.hClipRgn
, newRgn
,
182 (flags
& CLIP_EXCLUDE
) ? RGN_DIFF
: RGN_AND
);
185 if (!(flags
& CLIP_KEEPRGN
)) DeleteObject32( dc
->w
.hClipRgn
);
186 dc
->w
.hClipRgn
= newRgn
;
187 CLIPPING_UpdateGCRegion( dc
);
189 else DeleteObject32( newRgn
);
194 /***********************************************************************
195 * ExcludeClipRect16 (GDI.21)
197 INT16
ExcludeClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
198 INT16 right
, INT16 bottom
)
200 return (INT16
)ExcludeClipRect32( hdc
, left
, top
, right
, bottom
);
204 /***********************************************************************
205 * ExcludeClipRect32 (GDI32.92)
207 INT32
ExcludeClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
208 INT32 right
, INT32 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_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
216 return NULLREGION
; /* ?? */
219 left
= XLPTODP( dc
, left
);
220 right
= XLPTODP( dc
, right
);
221 top
= YLPTODP( dc
, top
);
222 bottom
= YLPTODP( dc
, bottom
);
224 dprintf_clipping(stddeb
, "ExcludeClipRect: %04x %dx%d,%dx%d\n",
225 hdc
, left
, top
, right
, bottom
);
226 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_EXCLUDE
);
230 /***********************************************************************
231 * IntersectClipRect16 (GDI.22)
233 INT16
IntersectClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
234 INT16 right
, INT16 bottom
)
236 return (INT16
)IntersectClipRect32( hdc
, left
, top
, right
, bottom
);
240 /***********************************************************************
241 * IntersectClipRect32 (GDI32.245)
243 INT32
IntersectClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
244 INT32 right
, INT32 bottom
)
246 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
249 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
250 if (!dc
) return ERROR
;
251 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
252 return NULLREGION
; /* ?? */
255 left
= XLPTODP( dc
, left
);
256 right
= XLPTODP( dc
, right
);
257 top
= YLPTODP( dc
, top
);
258 bottom
= YLPTODP( dc
, bottom
);
260 dprintf_clipping(stddeb
, "IntersectClipRect: %04x %dx%d,%dx%d\n",
261 hdc
, left
, top
, right
, bottom
);
262 return CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_INTERSECT
);
266 /***********************************************************************
267 * CLIPPING_IntersectVisRect
269 * Helper function for {Intersect,Exclude}VisRect
271 static INT32
CLIPPING_IntersectVisRect( DC
* dc
, INT32 left
, INT32 top
,
272 INT32 right
, INT32 bottom
,
275 HRGN32 tempRgn
, newRgn
;
278 left
= XLPTODP( dc
, left
);
279 right
= XLPTODP( dc
, right
);
280 top
= YLPTODP( dc
, top
);
281 bottom
= YLPTODP( dc
, bottom
);
283 if (!(newRgn
= CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR
;
284 if (!(tempRgn
= CreateRectRgn32( left
, top
, right
, bottom
)))
286 DeleteObject32( newRgn
);
289 ret
= CombineRgn32( newRgn
, dc
->w
.hVisRgn
, tempRgn
,
290 exclude
? RGN_DIFF
: RGN_AND
);
291 DeleteObject32( tempRgn
);
295 RGNOBJ
*newObj
= (RGNOBJ
*)GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
296 RGNOBJ
*prevObj
= (RGNOBJ
*)GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
);
297 if (newObj
&& prevObj
) newObj
->header
.hNext
= prevObj
->header
.hNext
;
298 DeleteObject32( dc
->w
.hVisRgn
);
299 dc
->w
.hVisRgn
= newRgn
;
300 CLIPPING_UpdateGCRegion( dc
);
302 else DeleteObject32( newRgn
);
307 /***********************************************************************
308 * ExcludeVisRect (GDI.73)
310 INT16
ExcludeVisRect( HDC16 hdc
, INT16 left
, INT16 top
,
311 INT16 right
, INT16 bottom
)
313 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
314 if (!dc
) return ERROR
;
315 dprintf_clipping(stddeb
, "ExcludeVisRect: %04x %dx%d,%dx%d\n",
316 hdc
, left
, top
, right
, bottom
);
318 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, TRUE
);
322 /***********************************************************************
323 * IntersectVisRect (GDI.98)
325 INT16
IntersectVisRect( HDC16 hdc
, INT16 left
, INT16 top
,
326 INT16 right
, INT16 bottom
)
328 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
329 if (!dc
) return ERROR
;
330 dprintf_clipping(stddeb
, "IntersectVisRect: %04x %dx%d,%dx%d\n",
331 hdc
, left
, top
, right
, bottom
);
333 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, FALSE
);
337 /***********************************************************************
338 * PtVisible16 (GDI.103)
340 BOOL16
PtVisible16( HDC16 hdc
, INT16 x
, INT16 y
)
342 return PtVisible32( hdc
, x
, y
);
346 /***********************************************************************
347 * PtVisible32 (GDI32.279)
349 BOOL32
PtVisible32( HDC32 hdc
, INT32 x
, INT32 y
)
351 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
352 if (!dc
) return ERROR
;
354 dprintf_clipping(stddeb
, "PtVisible: %04x %d,%d\n", hdc
, x
, y
);
355 if (!dc
->w
.hGCClipRgn
) return FALSE
;
357 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
358 dc
->w
.flags
&= ~DC_DIRTY
;
360 return PtInRegion32( dc
->w
.hGCClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
364 /***********************************************************************
365 * RectVisible16 (GDI.104)
367 BOOL16
RectVisible16( HDC16 hdc
, LPRECT16 rect
)
370 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
371 if (!dc
) return FALSE
;
372 dprintf_clipping(stddeb
,"RectVisible: %04x %d,%dx%d,%d\n",
373 hdc
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
374 if (!dc
->w
.hGCClipRgn
) return FALSE
;
375 /* copy rectangle to avoid overwriting by LPtoDP */
377 LPtoDP16( hdc
, (LPPOINT16
)&tmpRect
, 2 );
378 return RectInRegion16( dc
->w
.hGCClipRgn
, &tmpRect
);
382 /***********************************************************************
383 * RectVisible32 (GDI32.282)
385 BOOL32
RectVisible32( HDC32 hdc
, LPRECT32 rect
)
388 CONV_RECT32TO16( rect
, &rect16
);
389 return RectVisible16( (HDC16
)hdc
, &rect16
);
393 /***********************************************************************
394 * GetClipBox16 (GDI.77)
396 INT16
GetClipBox16( HDC16 hdc
, LPRECT16 rect
)
399 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
400 if (!dc
) return ERROR
;
401 ret
= GetRgnBox16( dc
->w
.hGCClipRgn
, rect
);
402 DPtoLP16( hdc
, (LPPOINT16
)rect
, 2 );
407 /***********************************************************************
408 * GetClipBox32 (GDI32.162)
410 INT32
GetClipBox32( HDC32 hdc
, LPRECT32 rect
)
413 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
414 if (!dc
) return ERROR
;
415 ret
= GetRgnBox32( dc
->w
.hGCClipRgn
, rect
);
416 DPtoLP32( hdc
, (LPPOINT32
)rect
, 2 );
421 /***********************************************************************
422 * GetClipRgn32 (GDI32.163)
424 INT32
GetClipRgn32( HDC32 hdc
, HRGN32 hRgn
)
426 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
430 /* this assumes that dc->w.hClipRgn is in coordinates
431 relative to the DC origin (not device) */
433 if( CombineRgn32(hRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
) != ERROR
)
440 /***********************************************************************
441 * SaveVisRgn (GDI.129)
443 HRGN16
SaveVisRgn( HDC16 hdc
)
446 RGNOBJ
*obj
, *copyObj
;
447 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
449 dprintf_clipping(stddeb
, "SaveVisRgn: %04x\n", hdc
);
452 fprintf( stderr
, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
455 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
456 dc
->w
.flags
&= ~DC_DIRTY
;
458 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
460 if (!(copy
= CreateRectRgn32( 0, 0, 0, 0 ))) return 0;
461 CombineRgn32( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
462 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
464 copyObj
->header
.hNext
= obj
->header
.hNext
;
465 obj
->header
.hNext
= copy
;
470 /***********************************************************************
471 * RestoreVisRgn (GDI.130)
473 INT16
RestoreVisRgn( HDC16 hdc
)
476 RGNOBJ
*obj
, *savedObj
;
477 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
478 if (!dc
|| !dc
->w
.hVisRgn
) return ERROR
;
479 dprintf_clipping(stddeb
, "RestoreVisRgn: %04x\n", hdc
);
480 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
482 if (!(saved
= obj
->header
.hNext
)) return ERROR
;
483 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
485 DeleteObject32( dc
->w
.hVisRgn
);
486 dc
->w
.hVisRgn
= saved
;
487 CLIPPING_UpdateGCRegion( dc
);
488 return savedObj
->xrgn
? COMPLEXREGION
: NULLREGION
;