Remove more unneeded wine 16bit header usage.
[wine/wine64.git] / dlls / gdi32 / clipping.c
blobb33543dd1a8fb6a4373b1e8f9576ebee31d85d6a
1 /*
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "wownt32.h"
27 #include "gdi_private.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
33 /***********************************************************************
34 * get_clip_region
36 * Return the total clip region (if any).
38 static inline HRGN get_clip_region( DC * dc )
40 if (dc->hMetaClipRgn) return dc->hMetaClipRgn;
41 if (dc->hMetaRgn) return dc->hMetaRgn;
42 return dc->hClipRgn;
46 /***********************************************************************
47 * CLIPPING_UpdateGCRegion
49 * Update the GC clip region when the ClipRgn or VisRgn have changed.
51 void CLIPPING_UpdateGCRegion( DC * dc )
53 HRGN clip_rgn;
55 if (!dc->hVisRgn)
57 ERR("hVisRgn is zero. Please report this.\n" );
58 exit(1);
61 if (dc->flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
63 /* update the intersection of meta and clip regions */
64 if (dc->hMetaRgn && dc->hClipRgn)
66 if (!dc->hMetaClipRgn) dc->hMetaClipRgn = CreateRectRgn( 0, 0, 0, 0 );
67 CombineRgn( dc->hMetaClipRgn, dc->hClipRgn, dc->hMetaRgn, RGN_AND );
68 clip_rgn = dc->hMetaClipRgn;
70 else /* only one is set, no need for an intersection */
72 if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
73 dc->hMetaClipRgn = 0;
74 clip_rgn = dc->hMetaRgn ? dc->hMetaRgn : dc->hClipRgn;
77 if (dc->funcs->pSetDeviceClipping)
78 dc->funcs->pSetDeviceClipping( dc->physDev, dc->hVisRgn, clip_rgn );
81 /***********************************************************************
82 * create_default_clip_region
84 * Create a default clipping region when none already exists.
86 static inline void create_default_clip_region( DC * dc )
88 UINT width, height;
90 if (GDIMAGIC( dc->header.wMagic ) == MEMORY_DC_MAGIC)
92 BITMAP bitmap;
94 GetObjectW( dc->hBitmap, sizeof(bitmap), &bitmap );
95 width = bitmap.bmWidth;
96 height = bitmap.bmHeight;
98 else
100 width = GetDeviceCaps( dc->hSelf, DESKTOPHORZRES );
101 height = GetDeviceCaps( dc->hSelf, DESKTOPVERTRES );
103 dc->hClipRgn = CreateRectRgn( 0, 0, width, height );
107 /***********************************************************************
108 * SelectClipRgn (GDI32.@)
110 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
112 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
116 /******************************************************************************
117 * ExtSelectClipRgn [GDI32.@]
119 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
121 INT retval;
122 RECT rect;
123 DC * dc = DC_GetDCUpdate( hdc );
124 if (!dc) return ERROR;
126 TRACE("%p %p %d\n", hdc, hrgn, fnMode );
128 if (dc->funcs->pExtSelectClipRgn)
130 retval = dc->funcs->pExtSelectClipRgn( dc->physDev, hrgn, fnMode );
131 DC_ReleaseDCPtr( dc );
132 return retval;
135 if (!hrgn)
137 if (fnMode == RGN_COPY)
139 if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
140 dc->hClipRgn = 0;
142 else
144 FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
145 DC_ReleaseDCPtr( dc );
146 return ERROR;
149 else
151 if (!dc->hClipRgn)
152 create_default_clip_region( dc );
154 if(fnMode == RGN_COPY)
155 CombineRgn( dc->hClipRgn, hrgn, 0, fnMode );
156 else
157 CombineRgn( dc->hClipRgn, dc->hClipRgn, hrgn, fnMode);
160 CLIPPING_UpdateGCRegion( dc );
161 DC_ReleaseDCPtr( dc );
163 return GetClipBox(hdc, &rect);
166 /***********************************************************************
167 * SelectVisRgn (GDI.105)
169 INT16 WINAPI SelectVisRgn16( HDC16 hdc16, HRGN16 hrgn )
171 int retval;
172 HDC hdc = HDC_32( hdc16 );
173 DC * dc;
175 if (!hrgn) return ERROR;
176 if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
178 TRACE("%p %04x\n", hdc, hrgn );
180 dc->flags &= ~DC_DIRTY;
182 retval = CombineRgn( dc->hVisRgn, HRGN_32(hrgn), 0, RGN_COPY );
183 CLIPPING_UpdateGCRegion( dc );
184 DC_ReleaseDCPtr( dc );
185 return retval;
189 /***********************************************************************
190 * OffsetClipRgn (GDI32.@)
192 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
194 INT ret = SIMPLEREGION;
195 DC *dc = DC_GetDCUpdate( hdc );
196 if (!dc) return ERROR;
198 TRACE("%p %d,%d\n", hdc, x, y );
200 if(dc->funcs->pOffsetClipRgn)
202 ret = dc->funcs->pOffsetClipRgn( dc->physDev, x, y );
203 /* FIXME: ret is just a success flag, we should return a proper value */
205 else if (dc->hClipRgn) {
206 ret = OffsetRgn( dc->hClipRgn, MulDiv( x, dc->vportExtX, dc->wndExtX ),
207 MulDiv( y, dc->vportExtY, dc->wndExtY ) );
208 CLIPPING_UpdateGCRegion( dc );
210 DC_ReleaseDCPtr( dc );
211 return ret;
215 /***********************************************************************
216 * OffsetVisRgn (GDI.102)
218 INT16 WINAPI OffsetVisRgn16( HDC16 hdc16, INT16 x, INT16 y )
220 INT16 retval;
221 HDC hdc = HDC_32( hdc16 );
222 DC * dc = DC_GetDCUpdate( hdc );
223 if (!dc) return ERROR;
224 TRACE("%p %d,%d\n", hdc, x, y );
225 retval = OffsetRgn( dc->hVisRgn, x, y );
226 CLIPPING_UpdateGCRegion( dc );
227 DC_ReleaseDCPtr( dc );
228 return retval;
232 /***********************************************************************
233 * ExcludeClipRect (GDI32.@)
235 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
236 INT right, INT bottom )
238 HRGN newRgn;
239 INT ret;
240 DC *dc = DC_GetDCUpdate( hdc );
241 if (!dc) return ERROR;
243 TRACE("%p %dx%d,%dx%d\n", hdc, left, top, right, bottom );
245 if(dc->funcs->pExcludeClipRect)
247 ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
248 /* FIXME: ret is just a success flag, we should return a proper value */
250 else
252 POINT pt[2];
254 pt[0].x = left;
255 pt[0].y = top;
256 pt[1].x = right;
257 pt[1].y = bottom;
258 LPtoDP( hdc, pt, 2 );
259 if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
260 else
262 if (!dc->hClipRgn)
263 create_default_clip_region( dc );
264 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
265 DeleteObject( newRgn );
267 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
269 DC_ReleaseDCPtr( dc );
270 return ret;
274 /***********************************************************************
275 * IntersectClipRect (GDI32.@)
277 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom )
279 INT ret;
280 DC *dc = DC_GetDCUpdate( hdc );
281 if (!dc) return ERROR;
283 TRACE("%p %d,%d - %d,%d\n", hdc, left, top, right, bottom );
285 if(dc->funcs->pIntersectClipRect)
287 ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
288 /* FIXME: ret is just a success flag, we should return a proper value */
290 else
292 POINT pt[2];
294 pt[0].x = left;
295 pt[0].y = top;
296 pt[1].x = right;
297 pt[1].y = bottom;
299 LPtoDP( hdc, pt, 2 );
301 if (!dc->hClipRgn)
303 dc->hClipRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y );
304 ret = SIMPLEREGION;
306 else
308 HRGN newRgn;
310 if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
311 else
313 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
314 DeleteObject( newRgn );
317 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
319 DC_ReleaseDCPtr( dc );
320 return ret;
324 /***********************************************************************
325 * ExcludeVisRect (GDI.73)
327 INT16 WINAPI ExcludeVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
329 HRGN tempRgn;
330 INT16 ret;
331 POINT pt[2];
332 HDC hdc = HDC_32( hdc16 );
333 DC * dc = DC_GetDCUpdate( hdc );
334 if (!dc) return ERROR;
336 pt[0].x = left;
337 pt[0].y = top;
338 pt[1].x = right;
339 pt[1].y = bottom;
341 LPtoDP( hdc, pt, 2 );
343 TRACE("%p %d,%d - %d,%d\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
345 if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
346 else
348 ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
349 DeleteObject( tempRgn );
351 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
352 DC_ReleaseDCPtr( dc );
353 return ret;
357 /***********************************************************************
358 * IntersectVisRect (GDI.98)
360 INT16 WINAPI IntersectVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
362 HRGN tempRgn;
363 INT16 ret;
364 POINT pt[2];
365 HDC hdc = HDC_32( hdc16 );
366 DC * dc = DC_GetDCUpdate( hdc );
367 if (!dc) return ERROR;
369 pt[0].x = left;
370 pt[0].y = top;
371 pt[1].x = right;
372 pt[1].y = bottom;
374 LPtoDP( hdc, pt, 2 );
376 TRACE("%p %d,%d - %d,%d\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
379 if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
380 else
382 ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
383 DeleteObject( tempRgn );
385 if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
386 DC_ReleaseDCPtr( dc );
387 return ret;
391 /***********************************************************************
392 * PtVisible (GDI32.@)
394 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
396 POINT pt;
397 BOOL ret;
398 HRGN clip;
399 DC *dc = DC_GetDCUpdate( hdc );
401 TRACE("%p %d,%d\n", hdc, x, y );
402 if (!dc) return FALSE;
404 pt.x = x;
405 pt.y = y;
406 LPtoDP( hdc, &pt, 1 );
407 ret = PtInRegion( dc->hVisRgn, pt.x, pt.y );
408 if (ret && (clip = get_clip_region(dc))) ret = PtInRegion( clip, pt.x, pt.y );
409 DC_ReleaseDCPtr( dc );
410 return ret;
414 /***********************************************************************
415 * RectVisible (GDI32.@)
417 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
419 RECT tmpRect;
420 BOOL ret;
421 HRGN clip;
422 DC *dc = DC_GetDCUpdate( hdc );
423 if (!dc) return FALSE;
424 TRACE("%p %d,%dx%d,%d\n", hdc, rect->left, rect->top, rect->right, rect->bottom );
426 tmpRect = *rect;
427 LPtoDP( hdc, (POINT *)&tmpRect, 2 );
429 if ((clip = get_clip_region(dc)))
431 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
432 CombineRgn( hrgn, dc->hVisRgn, clip, RGN_AND );
433 ret = RectInRegion( hrgn, &tmpRect );
434 DeleteObject( hrgn );
436 else ret = RectInRegion( dc->hVisRgn, &tmpRect );
437 DC_ReleaseDCPtr( dc );
438 return ret;
442 /***********************************************************************
443 * GetClipBox (GDI32.@)
445 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
447 INT ret;
448 HRGN clip;
449 DC *dc = DC_GetDCUpdate( hdc );
450 if (!dc) return ERROR;
451 if ((clip = get_clip_region(dc)))
453 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
454 CombineRgn( hrgn, dc->hVisRgn, clip, RGN_AND );
455 ret = GetRgnBox( hrgn, rect );
456 DeleteObject( hrgn );
458 else ret = GetRgnBox( dc->hVisRgn, rect );
459 DPtoLP( hdc, (LPPOINT)rect, 2 );
460 DC_ReleaseDCPtr( dc );
461 return ret;
465 /***********************************************************************
466 * GetClipRgn (GDI32.@)
468 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
470 INT ret = -1;
471 DC * dc;
472 if (hRgn && (dc = DC_GetDCPtr( hdc )))
474 if( dc->hClipRgn )
476 if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1;
478 else ret = 0;
479 DC_ReleaseDCPtr( dc );
481 return ret;
485 /***********************************************************************
486 * GetMetaRgn (GDI32.@)
488 INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
490 INT ret = 0;
491 DC * dc = DC_GetDCPtr( hdc );
493 if (dc)
495 if (dc->hMetaRgn && CombineRgn( hRgn, dc->hMetaRgn, 0, RGN_COPY ) != ERROR)
496 ret = 1;
497 DC_ReleaseDCPtr( dc );
499 return ret;
503 /***********************************************************************
504 * SaveVisRgn (GDI.129)
506 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc16 )
508 struct saved_visrgn *saved;
509 HDC hdc = HDC_32( hdc16 );
510 DC *dc = DC_GetDCUpdate( hdc );
512 if (!dc) return 0;
513 TRACE("%p\n", hdc );
515 if (!(saved = HeapAlloc( GetProcessHeap(), 0, sizeof(*saved) ))) goto error;
516 if (!(saved->hrgn = CreateRectRgn( 0, 0, 0, 0 ))) goto error;
517 CombineRgn( saved->hrgn, dc->hVisRgn, 0, RGN_COPY );
518 saved->next = dc->saved_visrgn;
519 dc->saved_visrgn = saved;
520 DC_ReleaseDCPtr( dc );
521 return HRGN_16(saved->hrgn);
523 error:
524 DC_ReleaseDCPtr( dc );
525 HeapFree( GetProcessHeap(), 0, saved );
526 return 0;
530 /***********************************************************************
531 * RestoreVisRgn (GDI.130)
533 INT16 WINAPI RestoreVisRgn16( HDC16 hdc16 )
535 struct saved_visrgn *saved;
536 HDC hdc = HDC_32( hdc16 );
537 DC *dc = DC_GetDCPtr( hdc );
538 INT16 ret = ERROR;
540 if (!dc) return ERROR;
542 TRACE("%p\n", hdc );
544 if (!(saved = dc->saved_visrgn)) goto done;
546 ret = CombineRgn( dc->hVisRgn, saved->hrgn, 0, RGN_COPY );
547 dc->saved_visrgn = saved->next;
548 DeleteObject( saved->hrgn );
549 HeapFree( GetProcessHeap(), 0, saved );
550 dc->flags &= ~DC_DIRTY;
551 CLIPPING_UpdateGCRegion( dc );
552 done:
553 DC_ReleaseDCPtr( dc );
554 return ret;
558 /***********************************************************************
559 * GetRandomRgn [GDI32.@]
561 * NOTES
562 * This function is documented in MSDN online for the case of
563 * iCode == SYSRGN (4).
565 * For iCode == 1 it should return the clip region
566 * 2 " " " the meta region
567 * 3 " " " the intersection of the clip with
568 * the meta region (== 'Rao' region).
570 * See http://www.codeproject.com/gdi/cliprgnguide.asp
572 INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
574 HRGN rgn;
575 DC *dc = DC_GetDCPtr( hDC );
577 if (!dc) return -1;
579 switch (iCode)
581 case 1:
582 rgn = dc->hClipRgn;
583 break;
584 case 2:
585 rgn = dc->hMetaRgn;
586 break;
587 case 3:
588 rgn = dc->hMetaClipRgn;
589 if(!rgn) rgn = dc->hClipRgn;
590 if(!rgn) rgn = dc->hMetaRgn;
591 break;
592 case SYSRGN: /* == 4 */
593 rgn = dc->hVisRgn;
594 break;
595 default:
596 WARN("Unknown code %d\n", iCode);
597 DC_ReleaseDCPtr( dc );
598 return -1;
600 if (rgn) CombineRgn( hRgn, rgn, 0, RGN_COPY );
601 DC_ReleaseDCPtr( dc );
603 /* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
604 if (iCode == SYSRGN && !(GetVersion() & 0x80000000))
606 POINT org;
607 GetDCOrgEx( hDC, &org );
608 OffsetRgn( hRgn, org.x, org.y );
610 return (rgn != 0);
614 /***********************************************************************
615 * SetMetaRgn (GDI32.@)
617 INT WINAPI SetMetaRgn( HDC hdc )
619 INT ret;
620 RECT dummy;
621 DC *dc = DC_GetDCPtr( hdc );
623 if (!dc) return ERROR;
625 if (dc->hMetaClipRgn)
627 /* the intersection becomes the new meta region */
628 DeleteObject( dc->hMetaRgn );
629 DeleteObject( dc->hClipRgn );
630 dc->hMetaRgn = dc->hMetaClipRgn;
631 dc->hClipRgn = 0;
632 dc->hMetaClipRgn = 0;
634 else if (dc->hClipRgn)
636 dc->hMetaRgn = dc->hClipRgn;
637 dc->hClipRgn = 0;
639 /* else nothing to do */
641 /* Note: no need to call CLIPPING_UpdateGCRegion, the overall clip region hasn't changed */
643 ret = GetRgnBox( dc->hMetaRgn, &dummy );
644 DC_ReleaseDCPtr( dc );
645 return ret;