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 );