2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
13 #define UPDATE_DIRTY_DC(dc) \
15 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
16 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
21 /***********************************************************************
22 * CLIPPING_UpdateGCRegion
24 * Update the GC clip region when the ClipRgn or VisRgn have changed.
26 void CLIPPING_UpdateGCRegion( DC
* dc
)
28 if (!dc
->w
.hGCClipRgn
) dc
->w
.hGCClipRgn
= CreateRectRgn32( 0, 0, 0, 0 );
32 fprintf( stderr
, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
36 if (dc
->w
.flags
& DC_DIRTY
)
39 dc
->w
.flags
&= ~DC_DIRTY
;
43 CombineRgn32( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
45 CombineRgn32(dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, RGN_AND
);
46 if (dc
->funcs
->pSetDeviceClipping
) dc
->funcs
->pSetDeviceClipping( dc
);
50 /***********************************************************************
51 * SelectClipRgn16 (GDI.44)
53 INT16 WINAPI
SelectClipRgn16( HDC16 hdc
, HRGN16 hrgn
)
55 return (INT16
)SelectClipRgn32( hdc
, hrgn
);
59 /***********************************************************************
60 * SelectClipRgn32 (GDI32.297)
62 INT32 WINAPI
SelectClipRgn32( HDC32 hdc
, HRGN32 hrgn
)
65 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
66 if (!dc
) return ERROR
;
68 TRACE(clipping
, "%04x %04x\n", hdc
, hrgn
);
72 if (!dc
->w
.hClipRgn
) dc
->w
.hClipRgn
= CreateRectRgn32(0,0,0,0);
73 retval
= CombineRgn32( dc
->w
.hClipRgn
, hrgn
, 0, RGN_COPY
);
77 if (dc
->w
.hClipRgn
) DeleteObject16( dc
->w
.hClipRgn
);
79 retval
= SIMPLEREGION
; /* Clip region == whole DC */
82 CLIPPING_UpdateGCRegion( dc
);
83 GDI_HEAP_UNLOCK( hdc
);
88 /***********************************************************************
89 * SelectVisRgn (GDI.105)
91 INT16 WINAPI
SelectVisRgn( HDC16 hdc
, HRGN16 hrgn
)
94 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
95 if (!dc
|| !hrgn
) return ERROR
;
97 TRACE(clipping
, "%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
);
103 GDI_HEAP_UNLOCK( hdc
);
108 /***********************************************************************
109 * OffsetClipRgn16 (GDI.32)
111 INT16 WINAPI
OffsetClipRgn16( HDC16 hdc
, INT16 x
, INT16 y
)
113 return (INT16
)OffsetClipRgn32( hdc
, x
, y
);
117 /***********************************************************************
118 * OffsetClipRgn32 (GDI32.255)
120 INT32 WINAPI
OffsetClipRgn32( HDC32 hdc
, INT32 x
, INT32 y
)
122 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
125 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
126 if (!dc
) return ERROR
;
127 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
128 GDI_HEAP_UNLOCK( hdc
);
129 return NULLREGION
; /* ?? */
132 TRACE(clipping
, "%04x %d,%d\n", hdc
, x
, y
);
136 INT32 ret
= OffsetRgn32( dc
->w
.hClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
));
137 CLIPPING_UpdateGCRegion( dc
);
138 GDI_HEAP_UNLOCK( hdc
);
141 GDI_HEAP_UNLOCK( hdc
);
142 return SIMPLEREGION
; /* Clip region == client area */
146 /***********************************************************************
147 * OffsetVisRgn (GDI.102)
149 INT16 WINAPI
OffsetVisRgn( HDC16 hdc
, INT16 x
, INT16 y
)
152 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
153 if (!dc
) return ERROR
;
154 TRACE(clipping
, "%04x %d,%d\n", hdc
, x
, y
);
155 retval
= OffsetRgn32( dc
->w
.hVisRgn
, x
, y
);
156 CLIPPING_UpdateGCRegion( dc
);
157 GDI_HEAP_UNLOCK( hdc
);
162 /***********************************************************************
163 * CLIPPING_IntersectClipRect
165 * Helper function for {Intersect,Exclude}ClipRect, can be called from
166 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
167 * coordinate conversion.
169 INT32
CLIPPING_IntersectClipRect( DC
* dc
, INT32 left
, INT32 top
,
170 INT32 right
, INT32 bottom
, UINT32 flags
)
175 if (!(newRgn
= CreateRectRgn32( left
, top
, right
, bottom
))) return ERROR
;
178 if( flags
& CLIP_INTERSECT
)
180 dc
->w
.hClipRgn
= newRgn
;
181 CLIPPING_UpdateGCRegion( dc
);
186 ret
= CombineRgn32( newRgn
, dc
->w
.hClipRgn
, newRgn
,
187 (flags
& CLIP_EXCLUDE
) ? RGN_DIFF
: RGN_AND
);
190 if (!(flags
& CLIP_KEEPRGN
)) DeleteObject32( dc
->w
.hClipRgn
);
191 dc
->w
.hClipRgn
= newRgn
;
192 CLIPPING_UpdateGCRegion( dc
);
194 else DeleteObject32( newRgn
);
199 /***********************************************************************
200 * ExcludeClipRect16 (GDI.21)
202 INT16 WINAPI
ExcludeClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
203 INT16 right
, INT16 bottom
)
205 return (INT16
)ExcludeClipRect32( hdc
, left
, top
, right
, bottom
);
209 /***********************************************************************
210 * ExcludeClipRect32 (GDI32.92)
212 INT32 WINAPI
ExcludeClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
213 INT32 right
, INT32 bottom
)
216 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
219 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
220 if (!dc
) return ERROR
;
221 MF_MetaParam4(dc
, META_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
222 GDI_HEAP_UNLOCK( hdc
);
223 return NULLREGION
; /* ?? */
226 left
= XLPTODP( dc
, left
);
227 right
= XLPTODP( dc
, right
);
228 top
= YLPTODP( dc
, top
);
229 bottom
= YLPTODP( dc
, bottom
);
231 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
232 hdc
, left
, top
, right
, bottom
);
233 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_EXCLUDE
);
234 GDI_HEAP_UNLOCK( hdc
);
239 /***********************************************************************
240 * IntersectClipRect16 (GDI.22)
242 INT16 WINAPI
IntersectClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
243 INT16 right
, INT16 bottom
)
245 return (INT16
)IntersectClipRect32( hdc
, left
, top
, right
, bottom
);
249 /***********************************************************************
250 * IntersectClipRect32 (GDI32.245)
252 INT32 WINAPI
IntersectClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
253 INT32 right
, INT32 bottom
)
256 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
259 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
260 if (!dc
) return ERROR
;
261 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
262 GDI_HEAP_UNLOCK( hdc
);
263 return NULLREGION
; /* ?? */
266 left
= XLPTODP( dc
, left
);
267 right
= XLPTODP( dc
, right
);
268 top
= YLPTODP( dc
, top
);
269 bottom
= YLPTODP( dc
, bottom
);
271 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
272 hdc
, left
, top
, right
, bottom
);
273 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_INTERSECT
);
274 GDI_HEAP_UNLOCK( hdc
);
279 /***********************************************************************
280 * CLIPPING_IntersectVisRect
282 * Helper function for {Intersect,Exclude}VisRect
284 static INT32
CLIPPING_IntersectVisRect( DC
* dc
, INT32 left
, INT32 top
,
285 INT32 right
, INT32 bottom
,
288 HRGN32 tempRgn
, newRgn
;
291 left
= XLPTODP( dc
, left
);
292 right
= XLPTODP( dc
, right
);
293 top
= YLPTODP( dc
, top
);
294 bottom
= YLPTODP( dc
, bottom
);
296 if (!(newRgn
= CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR
;
297 if (!(tempRgn
= CreateRectRgn32( left
, top
, right
, bottom
)))
299 DeleteObject32( newRgn
);
302 ret
= CombineRgn32( newRgn
, dc
->w
.hVisRgn
, tempRgn
,
303 exclude
? RGN_DIFF
: RGN_AND
);
304 DeleteObject32( tempRgn
);
308 RGNOBJ
*newObj
= (RGNOBJ
*)GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
309 RGNOBJ
*prevObj
= (RGNOBJ
*)GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
);
310 if (newObj
&& prevObj
) newObj
->header
.hNext
= prevObj
->header
.hNext
;
311 DeleteObject32( dc
->w
.hVisRgn
);
312 dc
->w
.hVisRgn
= newRgn
;
313 CLIPPING_UpdateGCRegion( dc
);
314 GDI_HEAP_UNLOCK( newRgn
);
316 else DeleteObject32( newRgn
);
321 /***********************************************************************
322 * ExcludeVisRect (GDI.73)
324 INT16 WINAPI
ExcludeVisRect( HDC16 hdc
, INT16 left
, INT16 top
,
325 INT16 right
, INT16 bottom
)
327 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
328 if (!dc
) return ERROR
;
329 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
330 hdc
, left
, top
, right
, bottom
);
332 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, TRUE
);
336 /***********************************************************************
337 * IntersectVisRect (GDI.98)
339 INT16 WINAPI
IntersectVisRect( HDC16 hdc
, INT16 left
, INT16 top
,
340 INT16 right
, INT16 bottom
)
342 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
343 if (!dc
) return ERROR
;
344 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
345 hdc
, left
, top
, right
, bottom
);
347 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, FALSE
);
351 /***********************************************************************
352 * PtVisible16 (GDI.103)
354 BOOL16 WINAPI
PtVisible16( HDC16 hdc
, INT16 x
, INT16 y
)
356 return PtVisible32( hdc
, x
, y
);
360 /***********************************************************************
361 * PtVisible32 (GDI32.279)
363 BOOL32 WINAPI
PtVisible32( HDC32 hdc
, INT32 x
, INT32 y
)
365 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
366 if (!dc
) return ERROR
;
368 TRACE(clipping
, "%04x %d,%d\n", hdc
, x
, y
);
369 if (!dc
->w
.hGCClipRgn
) return FALSE
;
371 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
372 dc
->w
.flags
&= ~DC_DIRTY
;
374 return PtInRegion32( dc
->w
.hGCClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
378 /***********************************************************************
379 * RectVisible16 (GDI.104)
381 BOOL16 WINAPI
RectVisible16( HDC16 hdc
, LPRECT16 rect
)
384 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
385 if (!dc
) return FALSE
;
386 TRACE(clipping
,"%04x %d,%dx%d,%d\n",
387 hdc
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
388 if (!dc
->w
.hGCClipRgn
) return FALSE
;
389 /* copy rectangle to avoid overwriting by LPtoDP */
391 LPtoDP16( hdc
, (LPPOINT16
)&tmpRect
, 2 );
392 return RectInRegion16( dc
->w
.hGCClipRgn
, &tmpRect
);
396 /***********************************************************************
397 * RectVisible32 (GDI32.282)
399 BOOL32 WINAPI
RectVisible32( HDC32 hdc
, LPRECT32 rect
)
402 CONV_RECT32TO16( rect
, &rect16
);
403 return RectVisible16( (HDC16
)hdc
, &rect16
);
407 /***********************************************************************
408 * GetClipBox16 (GDI.77)
410 INT16 WINAPI
GetClipBox16( HDC16 hdc
, LPRECT16 rect
)
413 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
414 if (!dc
) return ERROR
;
415 ret
= GetRgnBox16( dc
->w
.hGCClipRgn
, rect
);
416 DPtoLP16( hdc
, (LPPOINT16
)rect
, 2 );
421 /***********************************************************************
422 * GetClipBox32 (GDI32.162)
424 INT32 WINAPI
GetClipBox32( HDC32 hdc
, LPRECT32 rect
)
427 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
428 if (!dc
) return ERROR
;
429 ret
= GetRgnBox32( dc
->w
.hGCClipRgn
, rect
);
430 DPtoLP32( hdc
, (LPPOINT32
)rect
, 2 );
435 /***********************************************************************
436 * GetClipRgn32 (GDI32.163)
438 INT32 WINAPI
GetClipRgn32( HDC32 hdc
, HRGN32 hRgn
)
440 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
444 /* this assumes that dc->w.hClipRgn is in coordinates
445 relative to the DC origin (not device) */
447 if( CombineRgn32(hRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
) != ERROR
)
454 /***********************************************************************
455 * SaveVisRgn (GDI.129)
457 HRGN16 WINAPI
SaveVisRgn( HDC16 hdc
)
460 RGNOBJ
*obj
, *copyObj
;
461 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
463 TRACE(clipping
, "%04x\n", hdc
);
466 fprintf( stderr
, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
469 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
470 dc
->w
.flags
&= ~DC_DIRTY
;
472 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
474 GDI_HEAP_UNLOCK( hdc
);
477 if (!(copy
= CreateRectRgn32( 0, 0, 0, 0 )))
479 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
480 GDI_HEAP_UNLOCK( hdc
);
483 CombineRgn32( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
484 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
486 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
487 GDI_HEAP_UNLOCK( hdc
);
490 copyObj
->header
.hNext
= obj
->header
.hNext
;
491 obj
->header
.hNext
= copy
;
492 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
493 GDI_HEAP_UNLOCK( hdc
);
494 GDI_HEAP_UNLOCK( copy
);
499 /***********************************************************************
500 * RestoreVisRgn (GDI.130)
502 INT16 WINAPI
RestoreVisRgn( HDC16 hdc
)
505 RGNOBJ
*obj
, *savedObj
;
506 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
509 if (!dc
) return ERROR
;
512 GDI_HEAP_UNLOCK( hdc
);
515 TRACE(clipping
, "%04x\n", hdc
);
516 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
518 GDI_HEAP_UNLOCK( hdc
);
521 if (!(saved
= obj
->header
.hNext
))
523 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
524 GDI_HEAP_UNLOCK( hdc
);
527 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
529 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
530 GDI_HEAP_UNLOCK( hdc
);
533 DeleteObject32( dc
->w
.hVisRgn
);
534 dc
->w
.hVisRgn
= saved
;
535 CLIPPING_UpdateGCRegion( dc
);
536 GDI_HEAP_UNLOCK( hdc
);
537 ret
= savedObj
->rgn
->type
; /* FIXME */
538 GDI_HEAP_UNLOCK( saved
);