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 WINAPI
SelectClipRgn16( HDC16 hdc
, HRGN16 hrgn
)
56 return (INT16
)SelectClipRgn32( hdc
, hrgn
);
60 /***********************************************************************
61 * SelectClipRgn32 (GDI32.297)
63 INT32 WINAPI
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
);
84 GDI_HEAP_UNLOCK( hdc
);
89 /***********************************************************************
90 * SelectVisRgn (GDI.105)
92 INT16 WINAPI
SelectVisRgn( HDC16 hdc
, HRGN16 hrgn
)
95 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
96 if (!dc
|| !hrgn
) return ERROR
;
98 dprintf_clipping(stddeb
, "SelectVisRgn: %04x %04x\n", hdc
, hrgn
);
100 dc
->w
.flags
&= ~DC_DIRTY
;
102 retval
= CombineRgn16( dc
->w
.hVisRgn
, hrgn
, 0, RGN_COPY
);
103 CLIPPING_UpdateGCRegion( dc
);
104 GDI_HEAP_UNLOCK( hdc
);
109 /***********************************************************************
110 * OffsetClipRgn16 (GDI.32)
112 INT16 WINAPI
OffsetClipRgn16( HDC16 hdc
, INT16 x
, INT16 y
)
114 return (INT16
)OffsetClipRgn32( hdc
, x
, y
);
118 /***********************************************************************
119 * OffsetClipRgn32 (GDI32.255)
121 INT32 WINAPI
OffsetClipRgn32( HDC32 hdc
, INT32 x
, INT32 y
)
123 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
126 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
127 if (!dc
) return ERROR
;
128 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
129 GDI_HEAP_UNLOCK( hdc
);
130 return NULLREGION
; /* ?? */
133 dprintf_clipping(stddeb
, "OffsetClipRgn: %04x %d,%d\n", hdc
, x
, y
);
137 INT32 ret
= OffsetRgn32( dc
->w
.hClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
));
138 CLIPPING_UpdateGCRegion( dc
);
139 GDI_HEAP_UNLOCK( hdc
);
142 GDI_HEAP_UNLOCK( hdc
);
143 return SIMPLEREGION
; /* Clip region == client area */
147 /***********************************************************************
148 * OffsetVisRgn (GDI.102)
150 INT16 WINAPI
OffsetVisRgn( HDC16 hdc
, INT16 x
, INT16 y
)
153 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
154 if (!dc
) return ERROR
;
155 dprintf_clipping(stddeb
, "OffsetVisRgn: %04x %d,%d\n", hdc
, x
, y
);
156 retval
= OffsetRgn32( dc
->w
.hVisRgn
, x
, y
);
157 CLIPPING_UpdateGCRegion( dc
);
158 GDI_HEAP_UNLOCK( hdc
);
163 /***********************************************************************
164 * CLIPPING_IntersectClipRect
166 * Helper function for {Intersect,Exclude}ClipRect, can be called from
167 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
168 * coordinate conversion.
170 INT32
CLIPPING_IntersectClipRect( DC
* dc
, INT32 left
, INT32 top
,
171 INT32 right
, INT32 bottom
, UINT32 flags
)
176 if (!(newRgn
= CreateRectRgn32( left
, top
, right
, bottom
))) return ERROR
;
179 if( flags
& CLIP_INTERSECT
)
181 dc
->w
.hClipRgn
= newRgn
;
182 CLIPPING_UpdateGCRegion( dc
);
187 ret
= CombineRgn32( newRgn
, dc
->w
.hClipRgn
, newRgn
,
188 (flags
& CLIP_EXCLUDE
) ? RGN_DIFF
: RGN_AND
);
191 if (!(flags
& CLIP_KEEPRGN
)) DeleteObject32( dc
->w
.hClipRgn
);
192 dc
->w
.hClipRgn
= newRgn
;
193 CLIPPING_UpdateGCRegion( dc
);
195 else DeleteObject32( newRgn
);
200 /***********************************************************************
201 * ExcludeClipRect16 (GDI.21)
203 INT16 WINAPI
ExcludeClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
204 INT16 right
, INT16 bottom
)
206 return (INT16
)ExcludeClipRect32( hdc
, left
, top
, right
, bottom
);
210 /***********************************************************************
211 * ExcludeClipRect32 (GDI32.92)
213 INT32 WINAPI
ExcludeClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
214 INT32 right
, INT32 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_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
223 GDI_HEAP_UNLOCK( hdc
);
224 return NULLREGION
; /* ?? */
227 left
= XLPTODP( dc
, left
);
228 right
= XLPTODP( dc
, right
);
229 top
= YLPTODP( dc
, top
);
230 bottom
= YLPTODP( dc
, bottom
);
232 dprintf_clipping(stddeb
, "ExcludeClipRect: %04x %dx%d,%dx%d\n",
233 hdc
, left
, top
, right
, bottom
);
234 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_EXCLUDE
);
235 GDI_HEAP_UNLOCK( hdc
);
240 /***********************************************************************
241 * IntersectClipRect16 (GDI.22)
243 INT16 WINAPI
IntersectClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
244 INT16 right
, INT16 bottom
)
246 return (INT16
)IntersectClipRect32( hdc
, left
, top
, right
, bottom
);
250 /***********************************************************************
251 * IntersectClipRect32 (GDI32.245)
253 INT32 WINAPI
IntersectClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
254 INT32 right
, INT32 bottom
)
257 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
260 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
261 if (!dc
) return ERROR
;
262 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
263 GDI_HEAP_UNLOCK( hdc
);
264 return NULLREGION
; /* ?? */
267 left
= XLPTODP( dc
, left
);
268 right
= XLPTODP( dc
, right
);
269 top
= YLPTODP( dc
, top
);
270 bottom
= YLPTODP( dc
, bottom
);
272 dprintf_clipping(stddeb
, "IntersectClipRect: %04x %dx%d,%dx%d\n",
273 hdc
, left
, top
, right
, bottom
);
274 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_INTERSECT
);
275 GDI_HEAP_UNLOCK( hdc
);
280 /***********************************************************************
281 * CLIPPING_IntersectVisRect
283 * Helper function for {Intersect,Exclude}VisRect
285 static INT32
CLIPPING_IntersectVisRect( DC
* dc
, INT32 left
, INT32 top
,
286 INT32 right
, INT32 bottom
,
289 HRGN32 tempRgn
, newRgn
;
292 left
= XLPTODP( dc
, left
);
293 right
= XLPTODP( dc
, right
);
294 top
= YLPTODP( dc
, top
);
295 bottom
= YLPTODP( dc
, bottom
);
297 if (!(newRgn
= CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR
;
298 if (!(tempRgn
= CreateRectRgn32( left
, top
, right
, bottom
)))
300 DeleteObject32( newRgn
);
303 ret
= CombineRgn32( newRgn
, dc
->w
.hVisRgn
, tempRgn
,
304 exclude
? RGN_DIFF
: RGN_AND
);
305 DeleteObject32( tempRgn
);
309 RGNOBJ
*newObj
= (RGNOBJ
*)GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
310 RGNOBJ
*prevObj
= (RGNOBJ
*)GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
);
311 if (newObj
&& prevObj
) newObj
->header
.hNext
= prevObj
->header
.hNext
;
312 DeleteObject32( dc
->w
.hVisRgn
);
313 dc
->w
.hVisRgn
= newRgn
;
314 CLIPPING_UpdateGCRegion( dc
);
315 GDI_HEAP_UNLOCK( newRgn
);
317 else DeleteObject32( newRgn
);
322 /***********************************************************************
323 * ExcludeVisRect (GDI.73)
325 INT16 WINAPI
ExcludeVisRect( 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
, "ExcludeVisRect: %04x %dx%d,%dx%d\n",
331 hdc
, left
, top
, right
, bottom
);
333 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, TRUE
);
337 /***********************************************************************
338 * IntersectVisRect (GDI.98)
340 INT16 WINAPI
IntersectVisRect( HDC16 hdc
, INT16 left
, INT16 top
,
341 INT16 right
, INT16 bottom
)
343 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
344 if (!dc
) return ERROR
;
345 dprintf_clipping(stddeb
, "IntersectVisRect: %04x %dx%d,%dx%d\n",
346 hdc
, left
, top
, right
, bottom
);
348 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, FALSE
);
352 /***********************************************************************
353 * PtVisible16 (GDI.103)
355 BOOL16 WINAPI
PtVisible16( HDC16 hdc
, INT16 x
, INT16 y
)
357 return PtVisible32( hdc
, x
, y
);
361 /***********************************************************************
362 * PtVisible32 (GDI32.279)
364 BOOL32 WINAPI
PtVisible32( HDC32 hdc
, INT32 x
, INT32 y
)
366 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
367 if (!dc
) return ERROR
;
369 dprintf_clipping(stddeb
, "PtVisible: %04x %d,%d\n", hdc
, x
, y
);
370 if (!dc
->w
.hGCClipRgn
) return FALSE
;
372 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
373 dc
->w
.flags
&= ~DC_DIRTY
;
375 return PtInRegion32( dc
->w
.hGCClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
) );
379 /***********************************************************************
380 * RectVisible16 (GDI.104)
382 BOOL16 WINAPI
RectVisible16( HDC16 hdc
, LPRECT16 rect
)
385 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
386 if (!dc
) return FALSE
;
387 dprintf_clipping(stddeb
,"RectVisible: %04x %d,%dx%d,%d\n",
388 hdc
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
389 if (!dc
->w
.hGCClipRgn
) return FALSE
;
390 /* copy rectangle to avoid overwriting by LPtoDP */
392 LPtoDP16( hdc
, (LPPOINT16
)&tmpRect
, 2 );
393 return RectInRegion16( dc
->w
.hGCClipRgn
, &tmpRect
);
397 /***********************************************************************
398 * RectVisible32 (GDI32.282)
400 BOOL32 WINAPI
RectVisible32( HDC32 hdc
, LPRECT32 rect
)
403 CONV_RECT32TO16( rect
, &rect16
);
404 return RectVisible16( (HDC16
)hdc
, &rect16
);
408 /***********************************************************************
409 * GetClipBox16 (GDI.77)
411 INT16 WINAPI
GetClipBox16( HDC16 hdc
, LPRECT16 rect
)
414 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
415 if (!dc
) return ERROR
;
416 ret
= GetRgnBox16( dc
->w
.hGCClipRgn
, rect
);
417 DPtoLP16( hdc
, (LPPOINT16
)rect
, 2 );
422 /***********************************************************************
423 * GetClipBox32 (GDI32.162)
425 INT32 WINAPI
GetClipBox32( HDC32 hdc
, LPRECT32 rect
)
428 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
429 if (!dc
) return ERROR
;
430 ret
= GetRgnBox32( dc
->w
.hGCClipRgn
, rect
);
431 DPtoLP32( hdc
, (LPPOINT32
)rect
, 2 );
436 /***********************************************************************
437 * GetClipRgn32 (GDI32.163)
439 INT32 WINAPI
GetClipRgn32( HDC32 hdc
, HRGN32 hRgn
)
441 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
445 /* this assumes that dc->w.hClipRgn is in coordinates
446 relative to the DC origin (not device) */
448 if( CombineRgn32(hRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
) != ERROR
)
455 /***********************************************************************
456 * SaveVisRgn (GDI.129)
458 HRGN16 WINAPI
SaveVisRgn( HDC16 hdc
)
461 RGNOBJ
*obj
, *copyObj
;
462 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
464 dprintf_clipping(stddeb
, "SaveVisRgn: %04x\n", hdc
);
467 fprintf( stderr
, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
470 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
471 dc
->w
.flags
&= ~DC_DIRTY
;
473 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
475 GDI_HEAP_UNLOCK( hdc
);
478 if (!(copy
= CreateRectRgn32( 0, 0, 0, 0 )))
480 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
481 GDI_HEAP_UNLOCK( hdc
);
484 CombineRgn32( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
485 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
487 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
488 GDI_HEAP_UNLOCK( hdc
);
491 copyObj
->header
.hNext
= obj
->header
.hNext
;
492 obj
->header
.hNext
= copy
;
493 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
494 GDI_HEAP_UNLOCK( hdc
);
495 GDI_HEAP_UNLOCK( copy
);
500 /***********************************************************************
501 * RestoreVisRgn (GDI.130)
503 INT16 WINAPI
RestoreVisRgn( HDC16 hdc
)
506 RGNOBJ
*obj
, *savedObj
;
507 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
508 if (!dc
) return ERROR
;
511 GDI_HEAP_UNLOCK( hdc
);
514 dprintf_clipping(stddeb
, "RestoreVisRgn: %04x\n", hdc
);
515 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
517 GDI_HEAP_UNLOCK( hdc
);
520 if (!(saved
= obj
->header
.hNext
))
522 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
523 GDI_HEAP_UNLOCK( hdc
);
526 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
528 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
529 GDI_HEAP_UNLOCK( hdc
);
532 DeleteObject32( dc
->w
.hVisRgn
);
533 dc
->w
.hVisRgn
= saved
;
534 CLIPPING_UpdateGCRegion( dc
);
535 GDI_HEAP_UNLOCK( hdc
);
536 GDI_HEAP_UNLOCK( saved
);
537 return savedObj
->xrgn
? COMPLEXREGION
: NULLREGION
;