2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "wine/winuser16.h"
29 #include "gdi_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
35 /***********************************************************************
38 * Return the total clip region (if any).
40 static inline HRGN get_clip_region( DC * dc )
42 if (dc->hMetaClipRgn) return dc->hMetaClipRgn;
43 if (dc->hMetaRgn) return dc->hMetaRgn;
48 /***********************************************************************
49 * CLIPPING_UpdateGCRegion
51 * Update the GC clip region when the ClipRgn or VisRgn have changed.
53 void CLIPPING_UpdateGCRegion( DC * dc )
59 ERR("hVisRgn is zero. Please report this.\n" );
63 if (dc->flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
65 /* update the intersection of meta and clip regions */
66 if (dc->hMetaRgn && dc->hClipRgn)
68 if (!dc->hMetaClipRgn) dc->hMetaClipRgn = CreateRectRgn( 0, 0, 0, 0 );
69 CombineRgn( dc->hMetaClipRgn, dc->hClipRgn, dc->hMetaRgn, RGN_AND );
70 clip_rgn = dc->hMetaClipRgn;
72 else /* only one is set, no need for an intersection */
74 if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
76 clip_rgn = dc->hMetaRgn ? dc->hMetaRgn : dc->hClipRgn;
79 if (dc->funcs->pSetDeviceClipping)
80 dc->funcs->pSetDeviceClipping( dc->physDev, dc->hVisRgn, clip_rgn );
83 /***********************************************************************
84 * create_default_clip_region
86 * Create a default clipping region when none already exists.
88 static inline void create_default_clip_region( DC * dc )
90 dc->hClipRgn = CreateRectRgn(0, 0,
91 GetDeviceCaps( dc->hSelf, HORZRES ),
92 GetDeviceCaps( dc->hSelf, VERTRES ));
96 /***********************************************************************
97 * SelectClipRgn (GDI32.@)
99 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
101 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
105 /******************************************************************************
106 * ExtSelectClipRgn [GDI32.@]
108 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
112 DC * dc = DC_GetDCUpdate( hdc );
113 if (!dc) return ERROR;
115 TRACE("%p %p %d\n", hdc, hrgn, fnMode );
117 if (dc->funcs->pExtSelectClipRgn)
119 retval = dc->funcs->pExtSelectClipRgn( dc->physDev, hrgn, fnMode );
120 GDI_ReleaseObj( hdc );
126 if (fnMode == RGN_COPY)
128 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
133 FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
134 GDI_ReleaseObj( hdc );
141 create_default_clip_region( dc );
143 if(fnMode == RGN_COPY)
144 CombineRgn( dc->hClipRgn, hrgn, 0, fnMode );
146 CombineRgn( dc->hClipRgn, dc->hClipRgn, hrgn, fnMode);
149 CLIPPING_UpdateGCRegion( dc );
150 GDI_ReleaseObj( hdc );
152 return GetClipBox(hdc, &rect);
155 /***********************************************************************
156 * SelectVisRgn (GDI.105)
158 INT16 WINAPI SelectVisRgn16( HDC16 hdc16, HRGN16 hrgn )
161 HDC hdc = HDC_32( hdc16 );
164 if (!hrgn) return ERROR;
165 if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
167 TRACE("%p %04x\n", hdc, hrgn );
169 dc->flags &= ~DC_DIRTY;
171 retval = CombineRgn( dc->hVisRgn, HRGN_32(hrgn), 0, RGN_COPY );
172 CLIPPING_UpdateGCRegion( dc );
173 GDI_ReleaseObj( hdc );
178 /***********************************************************************
179 * OffsetClipRgn (GDI32.@)
181 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
183 INT ret = SIMPLEREGION;
184 DC *dc = DC_GetDCUpdate( hdc );
185 if (!dc) return ERROR;
187 TRACE("%p %d,%d\n", hdc, x, y );
189 if(dc->funcs->pOffsetClipRgn)
190 ret = dc->funcs->pOffsetClipRgn( dc->physDev, x, y );
191 else if (dc->hClipRgn) {
192 ret = OffsetRgn( dc->hClipRgn, MulDiv( x, dc->vportExtX, dc->wndExtX ),
193 MulDiv( y, dc->vportExtY, dc->wndExtY ) );
194 CLIPPING_UpdateGCRegion( dc );
196 GDI_ReleaseObj( hdc );
201 /***********************************************************************
202 * OffsetVisRgn (GDI.102)
204 INT16 WINAPI OffsetVisRgn16( HDC16 hdc16, INT16 x, INT16 y )
207 HDC hdc = HDC_32( hdc16 );
208 DC * dc = DC_GetDCUpdate( hdc );
209 if (!dc) return ERROR;
210 TRACE("%p %d,%d\n", hdc, x, y );
211 retval = OffsetRgn( dc->hVisRgn, x, y );
212 CLIPPING_UpdateGCRegion( dc );
213 GDI_ReleaseObj( hdc );
218 /***********************************************************************
219 * ExcludeClipRect (GDI32.@)
221 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
222 INT right, INT bottom )
226 DC *dc = DC_GetDCUpdate( hdc );
227 if (!dc) return ERROR;
229 TRACE("%p %dx%d,%dx%d\n", hdc, left, top, right, bottom );
231 if(dc->funcs->pExcludeClipRect)
232 ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
241 LPtoDP( hdc, pt, 2 );
242 if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
246 create_default_clip_region( dc );
247 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
248 DeleteObject( newRgn );
250 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
252 GDI_ReleaseObj( hdc );
257 /***********************************************************************
258 * IntersectClipRect (GDI32.@)
260 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom )
263 DC *dc = DC_GetDCUpdate( hdc );
264 if (!dc) return ERROR;
266 TRACE("%p %d,%d - %d,%d\n", hdc, left, top, right, bottom );
268 if(dc->funcs->pIntersectClipRect)
269 ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
279 LPtoDP( hdc, pt, 2 );
283 dc->hClipRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y );
290 if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
293 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
294 DeleteObject( newRgn );
297 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
299 GDI_ReleaseObj( hdc );
304 /***********************************************************************
305 * ExcludeVisRect (GDI.73)
307 INT16 WINAPI ExcludeVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
312 HDC hdc = HDC_32( hdc16 );
313 DC * dc = DC_GetDCUpdate( hdc );
314 if (!dc) return ERROR;
321 LPtoDP( hdc, pt, 2 );
323 TRACE("%p %ld,%ld - %ld,%ld\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
325 if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
328 ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
329 DeleteObject( tempRgn );
331 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
332 GDI_ReleaseObj( hdc );
337 /***********************************************************************
338 * IntersectVisRect (GDI.98)
340 INT16 WINAPI IntersectVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
345 HDC hdc = HDC_32( hdc16 );
346 DC * dc = DC_GetDCUpdate( hdc );
347 if (!dc) return ERROR;
354 LPtoDP( hdc, pt, 2 );
356 TRACE("%p %ld,%ld - %ld,%ld\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
359 if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
362 ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
363 DeleteObject( tempRgn );
365 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
366 GDI_ReleaseObj( hdc );
371 /***********************************************************************
372 * PtVisible (GDI32.@)
374 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
379 DC *dc = DC_GetDCUpdate( hdc );
381 TRACE("%p %d,%d\n", hdc, x, y );
382 if (!dc) return FALSE;
386 LPtoDP( hdc, &pt, 1 );
387 ret = PtInRegion( dc->hVisRgn, pt.x, pt.y );
388 if (ret && (clip = get_clip_region(dc))) ret = PtInRegion( clip, pt.x, pt.y );
389 GDI_ReleaseObj( hdc );
394 /***********************************************************************
395 * RectVisible (GDI32.@)
397 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
402 DC *dc = DC_GetDCUpdate( hdc );
403 if (!dc) return FALSE;
404 TRACE("%p %ld,%ldx%ld,%ld\n", hdc, rect->left, rect->top, rect->right, rect->bottom );
407 LPtoDP( hdc, (POINT *)&tmpRect, 2 );
409 if ((clip = get_clip_region(dc)))
411 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
412 CombineRgn( hrgn, dc->hVisRgn, clip, RGN_AND );
413 ret = RectInRegion( hrgn, &tmpRect );
414 DeleteObject( hrgn );
416 else ret = RectInRegion( dc->hVisRgn, &tmpRect );
417 GDI_ReleaseObj( hdc );
422 /***********************************************************************
423 * GetClipBox (GDI32.@)
425 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
429 DC *dc = DC_GetDCUpdate( hdc );
430 if (!dc) return ERROR;
431 if ((clip = get_clip_region(dc)))
433 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
434 CombineRgn( hrgn, dc->hVisRgn, clip, RGN_AND );
435 ret = GetRgnBox( hrgn, rect );
436 DeleteObject( hrgn );
438 else ret = GetRgnBox( dc->hVisRgn, rect );
439 DPtoLP( hdc, (LPPOINT)rect, 2 );
440 GDI_ReleaseObj( hdc );
445 /***********************************************************************
446 * GetClipRgn (GDI32.@)
448 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
452 if (hRgn && (dc = DC_GetDCPtr( hdc )))
456 if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1;
459 GDI_ReleaseObj( hdc );
465 /***********************************************************************
466 * GetMetaRgn (GDI32.@)
468 INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
471 DC * dc = DC_GetDCPtr( hdc );
475 if (dc->hMetaRgn && CombineRgn( hRgn, dc->hMetaRgn, 0, RGN_COPY ) != ERROR)
477 GDI_ReleaseObj( hdc );
483 /***********************************************************************
484 * SaveVisRgn (GDI.129)
486 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc16 )
488 struct saved_visrgn *saved;
489 HDC hdc = HDC_32( hdc16 );
490 DC *dc = DC_GetDCUpdate( hdc );
495 if (!(saved = HeapAlloc( GetProcessHeap(), 0, sizeof(*saved) ))) goto error;
496 if (!(saved->hrgn = CreateRectRgn( 0, 0, 0, 0 ))) goto error;
497 CombineRgn( saved->hrgn, dc->hVisRgn, 0, RGN_COPY );
498 saved->next = dc->saved_visrgn;
499 dc->saved_visrgn = saved;
500 GDI_ReleaseObj( hdc );
501 return HRGN_16(saved->hrgn);
504 GDI_ReleaseObj( hdc );
505 HeapFree( GetProcessHeap(), 0, saved );
510 /***********************************************************************
511 * RestoreVisRgn (GDI.130)
513 INT16 WINAPI RestoreVisRgn16( HDC16 hdc16 )
515 struct saved_visrgn *saved;
516 HDC hdc = HDC_32( hdc16 );
517 DC *dc = DC_GetDCPtr( hdc );
520 if (!dc) return ERROR;
524 if (!(saved = dc->saved_visrgn)) goto done;
526 ret = CombineRgn( dc->hVisRgn, saved->hrgn, 0, RGN_COPY );
527 dc->saved_visrgn = saved->next;
528 DeleteObject( saved->hrgn );
529 HeapFree( GetProcessHeap(), 0, saved );
530 dc->flags &= ~DC_DIRTY;
531 CLIPPING_UpdateGCRegion( dc );
533 GDI_ReleaseObj( hdc );
538 /***********************************************************************
539 * GetRandomRgn [GDI32.@]
542 * This function is documented in MSDN online for the case of
543 * iCode == SYSRGN (4).
545 * For iCode == 1 it should return the clip region
546 * 2 " " " the meta region
547 * 3 " " " the intersection of the clip with
548 * the meta region (== 'Rao' region).
550 * See http://www.codeproject.com/gdi/cliprgnguide.asp
552 INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
555 DC *dc = DC_GetDCPtr( hDC );
568 rgn = dc->hMetaClipRgn;
570 case SYSRGN: /* == 4 */
574 WARN("Unknown code %d\n", iCode);
575 GDI_ReleaseObj( hDC );
578 if (rgn) CombineRgn( hRgn, rgn, 0, RGN_COPY );
579 GDI_ReleaseObj( hDC );
581 /* On Windows NT/2000, the region returned is in screen coordinates */
582 if (!(GetVersion() & 0x80000000))
585 GetDCOrgEx( hDC, &org );
586 OffsetRgn( hRgn, org.x, org.y );
592 /***********************************************************************
593 * SetMetaRgn (GDI32.@)
595 INT WINAPI SetMetaRgn( HDC hdc )
599 DC *dc = DC_GetDCPtr( hdc );
601 if (!dc) return ERROR;
603 if (dc->hMetaClipRgn)
605 /* the intersection becomes the new meta region */
606 DeleteObject( dc->hMetaRgn );
607 DeleteObject( dc->hClipRgn );
608 dc->hMetaRgn = dc->hMetaClipRgn;
610 dc->hMetaClipRgn = 0;
612 else if (dc->hClipRgn)
614 dc->hMetaRgn = dc->hClipRgn;
617 /* else nothing to do */
619 /* Note: no need to call CLIPPING_UpdateGCRegion, the overall clip region hasn't changed */
621 ret = GetRgnBox( dc->hMetaRgn, &dummy );
622 GDI_ReleaseObj( hdc );