2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
12 #define UPDATE_DIRTY_DC(dc) \
14 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
15 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
20 /***********************************************************************
21 * CLIPPING_UpdateGCRegion
23 * Update the GC clip region when the ClipRgn or VisRgn have changed.
25 void CLIPPING_UpdateGCRegion( DC
* dc
)
27 if (!dc
->w
.hGCClipRgn
) dc
->w
.hGCClipRgn
= CreateRectRgn32( 0, 0, 0, 0 );
31 ERR(region
, "hVisRgn is zero. Please report this.\n" );
35 if (dc
->w
.flags
& DC_DIRTY
)
38 dc
->w
.flags
&= ~DC_DIRTY
;
42 CombineRgn32( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
44 CombineRgn32(dc
->w
.hGCClipRgn
, dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, RGN_AND
);
45 if (dc
->funcs
->pSetDeviceClipping
) dc
->funcs
->pSetDeviceClipping( dc
);
49 /***********************************************************************
50 * SelectClipRgn16 (GDI.44)
52 INT16 WINAPI
SelectClipRgn16( HDC16 hdc
, HRGN16 hrgn
)
54 return (INT16
)SelectClipRgn32( hdc
, hrgn
);
58 /***********************************************************************
59 * SelectClipRgn32 (GDI32.297)
61 INT32 WINAPI
SelectClipRgn32( HDC32 hdc
, HRGN32 hrgn
)
63 return ExtSelectClipRgn( hdc
, hrgn
, RGN_COPY
);
66 /******************************************************************************
67 * ExtSelectClipRgn [GDI32.97]
69 INT32 WINAPI
ExtSelectClipRgn( HDC32 hdc
, HRGN32 hrgn
, INT32 fnMode
)
72 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
73 if (!dc
) return ERROR
;
75 TRACE( clipping
, "%04x %04x %d\n", hdc
, hrgn
, fnMode
);
79 if (fnMode
== RGN_COPY
)
81 if (dc
->w
.hClipRgn
) DeleteObject16( dc
->w
.hClipRgn
);
83 retval
= SIMPLEREGION
; /* Clip region == whole DC */
87 FIXME(clipping
, "Unimplemented: hrgn NULL in mode: %d\n", fnMode
);
96 GetRgnBox32( dc
->w
.hVisRgn
, &rect
);
97 dc
->w
.hClipRgn
= CreateRectRgnIndirect32( &rect
);
100 OffsetRgn32( dc
->w
.hClipRgn
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
101 if(fnMode
== RGN_COPY
)
102 retval
= CombineRgn32( dc
->w
.hClipRgn
, hrgn
, 0, fnMode
);
104 retval
= CombineRgn32( dc
->w
.hClipRgn
, dc
->w
.hClipRgn
, hrgn
, fnMode
);
105 OffsetRgn32( dc
->w
.hClipRgn
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
109 CLIPPING_UpdateGCRegion( dc
);
110 GDI_HEAP_UNLOCK( hdc
);
114 /***********************************************************************
115 * SelectVisRgn (GDI.105)
117 INT16 WINAPI
SelectVisRgn( HDC16 hdc
, HRGN16 hrgn
)
120 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
121 if (!dc
|| !hrgn
) return ERROR
;
123 TRACE(clipping
, "%04x %04x\n", hdc
, hrgn
);
125 dc
->w
.flags
&= ~DC_DIRTY
;
127 retval
= CombineRgn16( dc
->w
.hVisRgn
, hrgn
, 0, RGN_COPY
);
128 CLIPPING_UpdateGCRegion( dc
);
129 GDI_HEAP_UNLOCK( hdc
);
134 /***********************************************************************
135 * OffsetClipRgn16 (GDI.32)
137 INT16 WINAPI
OffsetClipRgn16( HDC16 hdc
, INT16 x
, INT16 y
)
139 return (INT16
)OffsetClipRgn32( hdc
, x
, y
);
143 /***********************************************************************
144 * OffsetClipRgn32 (GDI32.255)
146 INT32 WINAPI
OffsetClipRgn32( HDC32 hdc
, INT32 x
, INT32 y
)
148 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
151 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
152 if (!dc
) return ERROR
;
153 MF_MetaParam2(dc
, META_OFFSETCLIPRGN
, x
, y
);
154 GDI_HEAP_UNLOCK( hdc
);
155 return NULLREGION
; /* ?? */
158 TRACE(clipping
, "%04x %d,%d\n", hdc
, x
, y
);
162 INT32 ret
= OffsetRgn32( dc
->w
.hClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
));
163 CLIPPING_UpdateGCRegion( dc
);
164 GDI_HEAP_UNLOCK( hdc
);
167 GDI_HEAP_UNLOCK( hdc
);
168 return SIMPLEREGION
; /* Clip region == client area */
172 /***********************************************************************
173 * OffsetVisRgn (GDI.102)
175 INT16 WINAPI
OffsetVisRgn( HDC16 hdc
, INT16 x
, INT16 y
)
178 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
179 if (!dc
) return ERROR
;
180 TRACE(clipping
, "%04x %d,%d\n", hdc
, x
, y
);
181 retval
= OffsetRgn32( dc
->w
.hVisRgn
, x
, y
);
182 CLIPPING_UpdateGCRegion( dc
);
183 GDI_HEAP_UNLOCK( hdc
);
188 /***********************************************************************
189 * CLIPPING_IntersectClipRect
191 * Helper function for {Intersect,Exclude}ClipRect, can be called from
192 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
193 * coordinate conversion.
195 INT32
CLIPPING_IntersectClipRect( DC
* dc
, INT32 left
, INT32 top
,
196 INT32 right
, INT32 bottom
, UINT32 flags
)
201 left
+= dc
->w
.DCOrgX
;
202 right
+= dc
->w
.DCOrgX
;
204 bottom
+= dc
->w
.DCOrgY
;
206 if (!(newRgn
= CreateRectRgn32( left
, top
, right
, bottom
))) return ERROR
;
209 if( flags
& CLIP_INTERSECT
)
211 dc
->w
.hClipRgn
= newRgn
;
212 CLIPPING_UpdateGCRegion( dc
);
215 else if( flags
& CLIP_EXCLUDE
)
217 dc
->w
.hClipRgn
= CreateRectRgn32( 0, 0, 0, 0 );
218 CombineRgn32( dc
->w
.hClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
220 else WARN(clipping
,"No hClipRgn and flags are %x\n",flags
);
223 ret
= CombineRgn32( newRgn
, dc
->w
.hClipRgn
, newRgn
,
224 (flags
& CLIP_EXCLUDE
) ? RGN_DIFF
: RGN_AND
);
227 if (!(flags
& CLIP_KEEPRGN
)) DeleteObject32( dc
->w
.hClipRgn
);
228 dc
->w
.hClipRgn
= newRgn
;
229 CLIPPING_UpdateGCRegion( dc
);
231 else DeleteObject32( newRgn
);
236 /***********************************************************************
237 * ExcludeClipRect16 (GDI.21)
239 INT16 WINAPI
ExcludeClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
240 INT16 right
, INT16 bottom
)
242 return (INT16
)ExcludeClipRect32( hdc
, left
, top
, right
, bottom
);
246 /***********************************************************************
247 * ExcludeClipRect32 (GDI32.92)
249 INT32 WINAPI
ExcludeClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
250 INT32 right
, INT32 bottom
)
253 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
256 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
257 if (!dc
) return ERROR
;
258 MF_MetaParam4(dc
, META_EXCLUDECLIPRECT
, left
, top
, right
, bottom
);
259 GDI_HEAP_UNLOCK( hdc
);
260 return NULLREGION
; /* ?? */
263 left
= XLPTODP( dc
, left
);
264 right
= XLPTODP( dc
, right
);
265 top
= YLPTODP( dc
, top
);
266 bottom
= YLPTODP( dc
, bottom
);
268 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
269 hdc
, left
, top
, right
, bottom
);
270 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_EXCLUDE
);
271 GDI_HEAP_UNLOCK( hdc
);
276 /***********************************************************************
277 * IntersectClipRect16 (GDI.22)
279 INT16 WINAPI
IntersectClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
280 INT16 right
, INT16 bottom
)
282 return (INT16
)IntersectClipRect32( hdc
, left
, top
, right
, bottom
);
286 /***********************************************************************
287 * IntersectClipRect32 (GDI32.245)
289 INT32 WINAPI
IntersectClipRect32( HDC32 hdc
, INT32 left
, INT32 top
,
290 INT32 right
, INT32 bottom
)
293 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
296 dc
= (DC
*)GDI_GetObjPtr(hdc
, METAFILE_DC_MAGIC
);
297 if (!dc
) return ERROR
;
298 MF_MetaParam4(dc
, META_INTERSECTCLIPRECT
, left
, top
, right
, bottom
);
299 GDI_HEAP_UNLOCK( hdc
);
300 return NULLREGION
; /* ?? */
303 left
= XLPTODP( dc
, left
);
304 right
= XLPTODP( dc
, right
);
305 top
= YLPTODP( dc
, top
);
306 bottom
= YLPTODP( dc
, bottom
);
308 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
309 hdc
, left
, top
, right
, bottom
);
310 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_INTERSECT
);
311 GDI_HEAP_UNLOCK( hdc
);
316 /***********************************************************************
317 * CLIPPING_IntersectVisRect
319 * Helper function for {Intersect,Exclude}VisRect, can be called from
320 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
321 * coordinate conversion.
323 INT32
CLIPPING_IntersectVisRect( DC
* dc
, INT32 left
, INT32 top
,
324 INT32 right
, INT32 bottom
,
327 HRGN32 tempRgn
, newRgn
;
330 left
+= dc
->w
.DCOrgX
;
331 right
+= dc
->w
.DCOrgX
;
333 bottom
+= dc
->w
.DCOrgY
;
335 if (!(newRgn
= CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR
;
336 if (!(tempRgn
= CreateRectRgn32( left
, top
, right
, bottom
)))
338 DeleteObject32( newRgn
);
341 ret
= CombineRgn32( newRgn
, dc
->w
.hVisRgn
, tempRgn
,
342 exclude
? RGN_DIFF
: RGN_AND
);
343 DeleteObject32( tempRgn
);
347 RGNOBJ
*newObj
= (RGNOBJ
*)GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
348 RGNOBJ
*prevObj
= (RGNOBJ
*)GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
);
349 if (newObj
&& prevObj
) newObj
->header
.hNext
= prevObj
->header
.hNext
;
350 DeleteObject32( dc
->w
.hVisRgn
);
351 dc
->w
.hVisRgn
= newRgn
;
352 CLIPPING_UpdateGCRegion( dc
);
353 GDI_HEAP_UNLOCK( newRgn
);
355 else DeleteObject32( newRgn
);
360 /***********************************************************************
361 * ExcludeVisRect (GDI.73)
363 INT16 WINAPI
ExcludeVisRect( HDC16 hdc
, INT16 left
, INT16 top
,
364 INT16 right
, INT16 bottom
)
366 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
367 if (!dc
) return ERROR
;
369 left
= XLPTODP( dc
, left
);
370 right
= XLPTODP( dc
, right
);
371 top
= YLPTODP( dc
, top
);
372 bottom
= YLPTODP( dc
, bottom
);
374 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
375 hdc
, left
, top
, right
, bottom
);
377 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, TRUE
);
381 /***********************************************************************
382 * IntersectVisRect (GDI.98)
384 INT16 WINAPI
IntersectVisRect( HDC16 hdc
, INT16 left
, INT16 top
,
385 INT16 right
, INT16 bottom
)
387 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
388 if (!dc
) return ERROR
;
390 left
= XLPTODP( dc
, left
);
391 right
= XLPTODP( dc
, right
);
392 top
= YLPTODP( dc
, top
);
393 bottom
= YLPTODP( dc
, bottom
);
395 TRACE(clipping
, "%04x %dx%d,%dx%d\n",
396 hdc
, left
, top
, right
, bottom
);
398 return CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, FALSE
);
402 /***********************************************************************
403 * PtVisible16 (GDI.103)
405 BOOL16 WINAPI
PtVisible16( HDC16 hdc
, INT16 x
, INT16 y
)
407 return PtVisible32( hdc
, x
, y
);
411 /***********************************************************************
412 * PtVisible32 (GDI32.279)
414 BOOL32 WINAPI
PtVisible32( HDC32 hdc
, INT32 x
, INT32 y
)
416 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
417 if (!dc
) return ERROR
;
419 TRACE(clipping
, "%04x %d,%d\n", hdc
, x
, y
);
420 if (!dc
->w
.hGCClipRgn
) return FALSE
;
422 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
423 dc
->w
.flags
&= ~DC_DIRTY
;
425 return PtInRegion32( dc
->w
.hGCClipRgn
, XLPTODP(dc
,x
) + dc
->w
.DCOrgX
,
426 YLPTODP(dc
,y
) + dc
->w
.DCOrgY
);
430 /***********************************************************************
431 * RectVisible16 (GDI.104)
433 BOOL16 WINAPI
RectVisible16( HDC16 hdc
, const RECT16
* rect
)
436 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
437 if (!dc
) return FALSE
;
438 TRACE(clipping
,"%04x %d,%dx%d,%d\n",
439 hdc
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
440 if (!dc
->w
.hGCClipRgn
) return FALSE
;
441 /* copy rectangle to avoid overwriting by LPtoDP */
443 LPtoDP16( hdc
, (LPPOINT16
)&tmpRect
, 2 );
444 OffsetRect16( &tmpRect
, dc
->w
.DCOrgX
, dc
->w
.DCOrgY
);
445 return RectInRegion16( dc
->w
.hGCClipRgn
, &tmpRect
);
449 /***********************************************************************
450 * RectVisible32 (GDI32.282)
452 BOOL32 WINAPI
RectVisible32( HDC32 hdc
, const RECT32
* rect
)
455 CONV_RECT32TO16( rect
, &rect16
);
456 return RectVisible16( (HDC16
)hdc
, &rect16
);
460 /***********************************************************************
461 * GetClipBox16 (GDI.77)
463 INT16 WINAPI
GetClipBox16( HDC16 hdc
, LPRECT16 rect
)
466 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
467 if (!dc
) return ERROR
;
468 ret
= GetRgnBox16( dc
->w
.hGCClipRgn
, rect
);
469 OffsetRect16( rect
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
470 DPtoLP16( hdc
, (LPPOINT16
)rect
, 2 );
471 TRACE(clipping
, "%d,%d-%d,%d\n",
472 rect
->left
,rect
->top
,rect
->right
,rect
->bottom
);
477 /***********************************************************************
478 * GetClipBox32 (GDI32.162)
480 INT32 WINAPI
GetClipBox32( HDC32 hdc
, LPRECT32 rect
)
483 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
484 if (!dc
) return ERROR
;
485 ret
= GetRgnBox32( dc
->w
.hGCClipRgn
, rect
);
486 OffsetRect32( rect
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
487 DPtoLP32( hdc
, (LPPOINT32
)rect
, 2 );
492 /***********************************************************************
493 * GetClipRgn32 (GDI32.163)
495 INT32 WINAPI
GetClipRgn32( HDC32 hdc
, HRGN32 hRgn
)
497 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
502 /* this assumes that dc->w.hClipRgn is in coordinates
503 relative to the device (not DC origin) */
505 if( CombineRgn32(hRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
) != ERROR
)
507 OffsetRgn32( hRgn
, -dc
->w
.DCOrgX
, -dc
->w
.DCOrgY
);
516 /***********************************************************************
517 * SaveVisRgn (GDI.129)
519 HRGN16 WINAPI
SaveVisRgn( HDC16 hdc
)
522 RGNOBJ
*obj
, *copyObj
;
523 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
525 TRACE(clipping
, "%04x\n", hdc
);
528 ERR(region
, "hVisRgn is zero. Please report this.\n" );
531 if( dc
->w
.flags
& DC_DIRTY
) UPDATE_DIRTY_DC(dc
);
532 dc
->w
.flags
&= ~DC_DIRTY
;
534 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
536 GDI_HEAP_UNLOCK( hdc
);
539 if (!(copy
= CreateRectRgn32( 0, 0, 0, 0 )))
541 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
542 GDI_HEAP_UNLOCK( hdc
);
545 CombineRgn32( copy
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
546 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
548 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
549 GDI_HEAP_UNLOCK( hdc
);
552 copyObj
->header
.hNext
= obj
->header
.hNext
;
553 obj
->header
.hNext
= copy
;
554 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
555 GDI_HEAP_UNLOCK( hdc
);
556 GDI_HEAP_UNLOCK( copy
);
561 /***********************************************************************
562 * RestoreVisRgn (GDI.130)
564 INT16 WINAPI
RestoreVisRgn( HDC16 hdc
)
567 RGNOBJ
*obj
, *savedObj
;
568 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
571 if (!dc
) return ERROR
;
574 GDI_HEAP_UNLOCK( hdc
);
577 TRACE(clipping
, "%04x\n", hdc
);
578 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->w
.hVisRgn
, REGION_MAGIC
)))
580 GDI_HEAP_UNLOCK( hdc
);
583 if (!(saved
= obj
->header
.hNext
))
585 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
586 GDI_HEAP_UNLOCK( hdc
);
589 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
591 GDI_HEAP_UNLOCK( dc
->w
.hVisRgn
);
592 GDI_HEAP_UNLOCK( hdc
);
595 DeleteObject32( dc
->w
.hVisRgn
);
596 dc
->w
.hVisRgn
= saved
;
597 CLIPPING_UpdateGCRegion( dc
);
598 GDI_HEAP_UNLOCK( hdc
);
599 ret
= savedObj
->rgn
->type
; /* FIXME */
600 GDI_HEAP_UNLOCK( saved
);