2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
10 #include "debugtools.h"
11 #include "wine/winuser16.h"
13 DECLARE_DEBUG_CHANNEL(clipping)
14 DECLARE_DEBUG_CHANNEL(region)
16 #define UPDATE_DIRTY_DC(dc) \
18 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
19 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
24 /***********************************************************************
25 * CLIPPING_UpdateGCRegion
27 * Update the GC clip region when the ClipRgn or VisRgn have changed.
29 void CLIPPING_UpdateGCRegion( DC * dc )
31 if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
35 ERR_(region)("hVisRgn is zero. Please report this.\n" );
39 if (dc->w.flags & DC_DIRTY)
42 dc->w.flags &= ~DC_DIRTY;
46 CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
48 CombineRgn(dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND);
49 if (dc->funcs->pSetDeviceClipping) dc->funcs->pSetDeviceClipping( dc );
53 /***********************************************************************
54 * SelectClipRgn16 (GDI.44)
56 INT16 WINAPI SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
58 return (INT16)SelectClipRgn( hdc, hrgn );
62 /***********************************************************************
63 * SelectClipRgn32 (GDI32.297)
65 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
67 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
70 /******************************************************************************
71 * ExtSelectClipRgn [GDI32.97]
73 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
76 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
77 if (!dc) return ERROR;
79 TRACE_(clipping)("%04x %04x %d\n", hdc, hrgn, fnMode );
83 if (fnMode == RGN_COPY)
85 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
87 retval = SIMPLEREGION; /* Clip region == whole DC */
91 FIXME_(clipping)("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
100 GetRgnBox( dc->w.hVisRgn, &rect );
101 dc->w.hClipRgn = CreateRectRgnIndirect( &rect );
104 OffsetRgn( dc->w.hClipRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
105 if(fnMode == RGN_COPY)
106 retval = CombineRgn( dc->w.hClipRgn, hrgn, 0, fnMode );
108 retval = CombineRgn( dc->w.hClipRgn, dc->w.hClipRgn, hrgn, fnMode);
109 OffsetRgn( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
113 CLIPPING_UpdateGCRegion( dc );
114 GDI_HEAP_UNLOCK( hdc );
118 /***********************************************************************
119 * SelectVisRgn (GDI.105)
121 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
124 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
125 if (!dc || !hrgn) return ERROR;
127 TRACE_(clipping)("%04x %04x\n", hdc, hrgn );
129 dc->w.flags &= ~DC_DIRTY;
131 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
132 CLIPPING_UpdateGCRegion( dc );
133 GDI_HEAP_UNLOCK( hdc );
138 /***********************************************************************
139 * OffsetClipRgn16 (GDI.32)
141 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
143 return (INT16)OffsetClipRgn( hdc, x, y );
147 /***********************************************************************
148 * OffsetClipRgn32 (GDI32.255)
150 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
152 INT ret = SIMPLEREGION;
153 DC *dc = DC_GetDCPtr( hdc );
154 if (!dc) return ERROR;
156 TRACE_(clipping)("%04x %d,%d\n", hdc, x, y );
158 if(dc->funcs->pOffsetClipRgn)
159 ret = dc->funcs->pOffsetClipRgn( dc, x, y );
160 else if (dc->w.hClipRgn) {
161 ret = OffsetRgn( dc->w.hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
162 CLIPPING_UpdateGCRegion( dc );
164 GDI_HEAP_UNLOCK( hdc );
169 /***********************************************************************
170 * OffsetVisRgn (GDI.102)
172 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
175 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
176 if (!dc) return ERROR;
177 TRACE_(clipping)("%04x %d,%d\n", hdc, x, y );
178 retval = OffsetRgn( dc->w.hVisRgn, x, y );
179 CLIPPING_UpdateGCRegion( dc );
180 GDI_HEAP_UNLOCK( hdc );
185 /***********************************************************************
186 * CLIPPING_IntersectClipRect
188 * Helper function for {Intersect,Exclude}ClipRect, can be called from
189 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
190 * coordinate conversion.
192 INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
193 INT right, INT bottom, UINT flags )
198 left += dc->w.DCOrgX;
199 right += dc->w.DCOrgX;
201 bottom += dc->w.DCOrgY;
203 if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
206 if( flags & CLIP_INTERSECT )
208 dc->w.hClipRgn = newRgn;
209 CLIPPING_UpdateGCRegion( dc );
212 else if( flags & CLIP_EXCLUDE )
214 dc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
215 CombineRgn( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
217 else WARN_(clipping)("No hClipRgn and flags are %x\n",flags);
220 ret = CombineRgn( newRgn, dc->w.hClipRgn, newRgn,
221 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
224 if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->w.hClipRgn );
225 dc->w.hClipRgn = newRgn;
226 CLIPPING_UpdateGCRegion( dc );
228 else DeleteObject( newRgn );
233 /***********************************************************************
234 * ExcludeClipRect16 (GDI.21)
236 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
237 INT16 right, INT16 bottom )
239 return (INT16)ExcludeClipRect( hdc, left, top, right, bottom );
243 /***********************************************************************
244 * ExcludeClipRect32 (GDI32.92)
246 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
247 INT right, INT bottom )
250 DC *dc = DC_GetDCPtr( hdc );
251 if (!dc) return ERROR;
253 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
254 hdc, left, top, right, bottom );
256 if(dc->funcs->pExcludeClipRect)
257 ret = dc->funcs->pExcludeClipRect( dc, left, top, right, bottom );
259 left = XLPTODP( dc, left );
260 right = XLPTODP( dc, right );
261 top = YLPTODP( dc, top );
262 bottom = YLPTODP( dc, bottom );
264 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
266 GDI_HEAP_UNLOCK( hdc );
271 /***********************************************************************
272 * IntersectClipRect16 (GDI.22)
274 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
275 INT16 right, INT16 bottom )
277 return (INT16)IntersectClipRect( hdc, left, top, right, bottom );
281 /***********************************************************************
282 * IntersectClipRect32 (GDI32.245)
284 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
285 INT right, INT bottom )
288 DC *dc = DC_GetDCPtr( hdc );
289 if (!dc) return ERROR;
291 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
292 hdc, left, top, right, bottom );
294 if(dc->funcs->pIntersectClipRect)
295 ret = dc->funcs->pIntersectClipRect( dc, left, top, right, bottom );
297 left = XLPTODP( dc, left );
298 right = XLPTODP( dc, right );
299 top = YLPTODP( dc, top );
300 bottom = YLPTODP( dc, bottom );
302 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
304 GDI_HEAP_UNLOCK( hdc );
309 /***********************************************************************
310 * CLIPPING_IntersectVisRect
312 * Helper function for {Intersect,Exclude}VisRect, can be called from
313 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
314 * coordinate conversion.
316 INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
317 INT right, INT bottom,
320 HRGN tempRgn, newRgn;
323 left += dc->w.DCOrgX;
324 right += dc->w.DCOrgX;
326 bottom += dc->w.DCOrgY;
328 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
329 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
331 DeleteObject( newRgn );
334 ret = CombineRgn( newRgn, dc->w.hVisRgn, tempRgn,
335 exclude ? RGN_DIFF : RGN_AND );
336 DeleteObject( tempRgn );
340 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
341 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
342 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
343 DeleteObject( dc->w.hVisRgn );
344 dc->w.hVisRgn = newRgn;
345 CLIPPING_UpdateGCRegion( dc );
346 GDI_HEAP_UNLOCK( newRgn );
348 else DeleteObject( newRgn );
353 /***********************************************************************
354 * ExcludeVisRect (GDI.73)
356 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
357 INT16 right, INT16 bottom )
359 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
360 if (!dc) return ERROR;
362 left = XLPTODP( dc, left );
363 right = XLPTODP( dc, right );
364 top = YLPTODP( dc, top );
365 bottom = YLPTODP( dc, bottom );
367 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
368 hdc, left, top, right, bottom );
370 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
374 /***********************************************************************
375 * IntersectVisRect (GDI.98)
377 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
378 INT16 right, INT16 bottom )
380 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
381 if (!dc) return ERROR;
383 left = XLPTODP( dc, left );
384 right = XLPTODP( dc, right );
385 top = YLPTODP( dc, top );
386 bottom = YLPTODP( dc, bottom );
388 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
389 hdc, left, top, right, bottom );
391 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
395 /***********************************************************************
396 * PtVisible16 (GDI.103)
398 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
400 return PtVisible( hdc, x, y );
404 /***********************************************************************
405 * PtVisible32 (GDI32.279)
407 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
409 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
410 if (!dc) return ERROR;
412 TRACE_(clipping)("%04x %d,%d\n", hdc, x, y );
413 if (!dc->w.hGCClipRgn) return FALSE;
415 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
416 dc->w.flags &= ~DC_DIRTY;
418 return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX,
419 YLPTODP(dc,y) + dc->w.DCOrgY );
423 /***********************************************************************
424 * RectVisible16 (GDI.104)
426 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
429 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
430 if (!dc) return FALSE;
431 TRACE_(clipping)("%04x %d,%dx%d,%d\n",
432 hdc, rect->left, rect->top, rect->right, rect->bottom );
433 if (!dc->w.hGCClipRgn) return FALSE;
434 /* copy rectangle to avoid overwriting by LPtoDP */
436 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
437 OffsetRect16( &tmpRect, dc->w.DCOrgX, dc->w.DCOrgY );
438 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
442 /***********************************************************************
443 * RectVisible32 (GDI32.282)
445 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
448 CONV_RECT32TO16( rect, &rect16 );
449 return RectVisible16( (HDC16)hdc, &rect16 );
453 /***********************************************************************
454 * GetClipBox16 (GDI.77)
456 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
459 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
460 if (!dc) return ERROR;
461 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
462 OffsetRect16( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
463 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
464 TRACE_(clipping)("%d,%d-%d,%d\n",
465 rect->left,rect->top,rect->right,rect->bottom );
470 /***********************************************************************
471 * GetClipBox32 (GDI32.162)
473 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
476 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
477 if (!dc) return ERROR;
478 ret = GetRgnBox( dc->w.hGCClipRgn, rect );
479 OffsetRect( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
480 DPtoLP( hdc, (LPPOINT)rect, 2 );
485 /***********************************************************************
486 * GetClipRgn32 (GDI32.163)
488 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
490 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
495 /* this assumes that dc->w.hClipRgn is in coordinates
496 relative to the device (not DC origin) */
498 if( CombineRgn(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
500 OffsetRgn( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
509 /***********************************************************************
510 * SaveVisRgn (GDI.129)
512 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
515 RGNOBJ *obj, *copyObj;
516 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
518 TRACE_(clipping)("%04x\n", hdc );
521 ERR_(region)("hVisRgn is zero. Please report this.\n" );
524 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
525 dc->w.flags &= ~DC_DIRTY;
527 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
529 GDI_HEAP_UNLOCK( hdc );
532 if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
534 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
535 GDI_HEAP_UNLOCK( hdc );
538 CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
539 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
541 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
542 GDI_HEAP_UNLOCK( hdc );
545 copyObj->header.hNext = obj->header.hNext;
546 obj->header.hNext = copy;
547 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
548 GDI_HEAP_UNLOCK( hdc );
549 GDI_HEAP_UNLOCK( copy );
554 /***********************************************************************
555 * RestoreVisRgn (GDI.130)
557 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
560 RGNOBJ *obj, *savedObj;
561 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
564 if (!dc) return ERROR;
567 GDI_HEAP_UNLOCK( hdc );
570 TRACE_(clipping)("%04x\n", hdc );
571 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
573 GDI_HEAP_UNLOCK( hdc );
576 if (!(saved = obj->header.hNext))
578 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
579 GDI_HEAP_UNLOCK( hdc );
582 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
584 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
585 GDI_HEAP_UNLOCK( hdc );
588 DeleteObject( dc->w.hVisRgn );
589 dc->w.hVisRgn = saved;
590 CLIPPING_UpdateGCRegion( dc );
591 GDI_HEAP_UNLOCK( hdc );
592 ret = savedObj->rgn->type; /* FIXME */
593 GDI_HEAP_UNLOCK( saved );