Added DM_REPOSITION.
[wine/multimedia.git] / objects / clipping.c
blobf10a2f0198c98f10fd85a705a3d6cadb5da65f84
1 /*
2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include "windef.h"
9 #include "wingdi.h"
10 #include "wine/winuser16.h"
11 #include "gdi.h"
12 #include "region.h"
13 #include "debugtools.h"
15 DEFAULT_DEBUG_CHANNEL(clipping);
18 /***********************************************************************
19 * CLIPPING_UpdateGCRegion
21 * Update the GC clip region when the ClipRgn or VisRgn have changed.
23 void CLIPPING_UpdateGCRegion( DC * dc )
25 if (!dc->hGCClipRgn) dc->hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
27 if (!dc->hVisRgn)
29 ERR("hVisRgn is zero. Please report this.\n" );
30 exit(1);
33 if (dc->flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
35 if (!dc->hClipRgn)
36 CombineRgn( dc->hGCClipRgn, dc->hVisRgn, 0, RGN_COPY );
37 else
38 CombineRgn(dc->hGCClipRgn, dc->hClipRgn, dc->hVisRgn, RGN_AND);
39 if (dc->funcs->pSetDeviceClipping) dc->funcs->pSetDeviceClipping( dc );
43 /***********************************************************************
44 * SelectClipRgn16 (GDI.44)
46 INT16 WINAPI SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
48 return (INT16)SelectClipRgn( hdc, hrgn );
52 /***********************************************************************
53 * SelectClipRgn (GDI32.297)
55 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
57 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
60 /******************************************************************************
61 * ExtSelectClipRgn16 [GDI.508]
63 INT16 WINAPI ExtSelectClipRgn16( HDC16 hdc, HRGN16 hrgn, INT16 fnMode )
65 return (INT16) ExtSelectClipRgn((HDC) hdc, (HRGN) hrgn, fnMode);
68 /******************************************************************************
69 * ExtSelectClipRgn [GDI32.97]
71 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
73 INT retval;
74 DC * dc = DC_GetDCUpdate( hdc );
75 if (!dc) return ERROR;
77 TRACE("%04x %04x %d\n", hdc, hrgn, fnMode );
79 if (!hrgn)
81 if (fnMode == RGN_COPY)
83 if (dc->hClipRgn) DeleteObject16( dc->hClipRgn );
84 dc->hClipRgn = 0;
85 retval = SIMPLEREGION; /* Clip region == whole DC */
87 else
89 FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
90 GDI_ReleaseObj( hdc );
91 return ERROR;
94 else
96 if (!dc->hClipRgn)
98 RECT rect;
99 GetRgnBox( dc->hVisRgn, &rect );
100 dc->hClipRgn = CreateRectRgnIndirect( &rect );
103 OffsetRgn( dc->hClipRgn, -dc->DCOrgX, -dc->DCOrgY );
104 if(fnMode == RGN_COPY)
105 retval = CombineRgn( dc->hClipRgn, hrgn, 0, fnMode );
106 else
107 retval = CombineRgn( dc->hClipRgn, dc->hClipRgn, hrgn, fnMode);
108 OffsetRgn( dc->hClipRgn, dc->DCOrgX, dc->DCOrgY );
111 CLIPPING_UpdateGCRegion( dc );
112 GDI_ReleaseObj( hdc );
113 return retval;
116 /***********************************************************************
117 * SelectVisRgn (GDI.105)
119 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
121 int retval;
122 DC * dc;
124 if (!hrgn) return ERROR;
125 if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
127 TRACE("%04x %04x\n", hdc, hrgn );
129 dc->flags &= ~DC_DIRTY;
131 retval = CombineRgn16( dc->hVisRgn, hrgn, 0, RGN_COPY );
132 CLIPPING_UpdateGCRegion( dc );
133 GDI_ReleaseObj( hdc );
134 return retval;
138 /***********************************************************************
139 * OffsetClipRgn16 (GDI.32)
141 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
143 return (INT16)OffsetClipRgn( hdc, x, y );
147 /***********************************************************************
148 * OffsetClipRgn (GDI32.255)
150 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
152 INT ret = SIMPLEREGION;
153 DC *dc = DC_GetDCUpdate( hdc );
154 if (!dc) return ERROR;
156 TRACE("%04x %d,%d\n", hdc, x, y );
158 if(dc->funcs->pOffsetClipRgn)
159 ret = dc->funcs->pOffsetClipRgn( dc, x, y );
160 else if (dc->hClipRgn) {
161 ret = OffsetRgn( dc->hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
162 CLIPPING_UpdateGCRegion( dc );
164 GDI_ReleaseObj( hdc );
165 return ret;
169 /***********************************************************************
170 * OffsetVisRgn (GDI.102)
172 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
174 INT16 retval;
175 DC * dc = DC_GetDCUpdate( hdc );
176 if (!dc) return ERROR;
177 TRACE("%04x %d,%d\n", hdc, x, y );
178 retval = OffsetRgn( dc->hVisRgn, x, y );
179 CLIPPING_UpdateGCRegion( dc );
180 GDI_ReleaseObj( hdc );
181 return retval;
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 )
195 HRGN newRgn;
196 INT ret;
198 left += dc->DCOrgX;
199 right += dc->DCOrgX;
200 top += dc->DCOrgY;
201 bottom += dc->DCOrgY;
203 if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
204 if (!dc->hClipRgn)
206 if( flags & CLIP_INTERSECT )
208 dc->hClipRgn = newRgn;
209 CLIPPING_UpdateGCRegion( dc );
210 return SIMPLEREGION;
212 else if( flags & CLIP_EXCLUDE )
214 dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
215 CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
217 else WARN("No hClipRgn and flags are %x\n",flags);
220 ret = CombineRgn( newRgn, dc->hClipRgn, newRgn,
221 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
222 if (ret != ERROR)
224 if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->hClipRgn );
225 dc->hClipRgn = newRgn;
226 CLIPPING_UpdateGCRegion( dc );
228 else DeleteObject( newRgn );
229 return ret;
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 * ExcludeClipRect (GDI32.92)
246 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
247 INT right, INT bottom )
249 INT ret;
250 DC *dc = DC_GetDCUpdate( hdc );
251 if (!dc) return ERROR;
253 TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
255 if(dc->funcs->pExcludeClipRect)
256 ret = dc->funcs->pExcludeClipRect( dc, left, top, right, bottom );
257 else {
258 left = XLPTODP( dc, left );
259 right = XLPTODP( dc, right );
260 top = YLPTODP( dc, top );
261 bottom = YLPTODP( dc, bottom );
263 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
265 GDI_ReleaseObj( hdc );
266 return ret;
270 /***********************************************************************
271 * IntersectClipRect16 (GDI.22)
273 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
274 INT16 right, INT16 bottom )
276 return (INT16)IntersectClipRect( hdc, left, top, right, bottom );
280 /***********************************************************************
281 * IntersectClipRect (GDI32.245)
283 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
284 INT right, INT bottom )
286 INT ret;
287 DC *dc = DC_GetDCUpdate( hdc );
288 if (!dc) return ERROR;
290 TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
292 if(dc->funcs->pIntersectClipRect)
293 ret = dc->funcs->pIntersectClipRect( dc, left, top, right, bottom );
294 else {
295 left = XLPTODP( dc, left );
296 right = XLPTODP( dc, right );
297 top = YLPTODP( dc, top );
298 bottom = YLPTODP( dc, bottom );
300 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
302 GDI_ReleaseObj( hdc );
303 return ret;
307 /***********************************************************************
308 * CLIPPING_IntersectVisRect
310 * Helper function for {Intersect,Exclude}VisRect, can be called from
311 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
312 * coordinate conversion.
314 INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
315 INT right, INT bottom,
316 BOOL exclude )
318 HRGN tempRgn, newRgn;
319 INT ret;
321 left += dc->DCOrgX;
322 right += dc->DCOrgX;
323 top += dc->DCOrgY;
324 bottom += dc->DCOrgY;
326 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
327 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
329 DeleteObject( newRgn );
330 return ERROR;
332 ret = CombineRgn( newRgn, dc->hVisRgn, tempRgn,
333 exclude ? RGN_DIFF : RGN_AND );
334 DeleteObject( tempRgn );
336 if (ret != ERROR)
338 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
339 if (newObj)
341 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC);
342 if (prevObj)
344 newObj->header.hNext = prevObj->header.hNext;
345 GDI_ReleaseObj( dc->hVisRgn );
347 GDI_ReleaseObj( newRgn );
349 DeleteObject( dc->hVisRgn );
350 dc->hVisRgn = newRgn;
351 CLIPPING_UpdateGCRegion( dc );
353 else DeleteObject( newRgn );
354 return ret;
358 /***********************************************************************
359 * ExcludeVisRect (GDI.73)
361 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
362 INT16 right, INT16 bottom )
364 INT16 ret;
365 DC * dc = DC_GetDCUpdate( hdc );
366 if (!dc) return ERROR;
368 left = XLPTODP( dc, left );
369 right = XLPTODP( dc, right );
370 top = YLPTODP( dc, top );
371 bottom = YLPTODP( dc, bottom );
373 TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
375 ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
376 GDI_ReleaseObj( hdc );
377 return ret;
381 /***********************************************************************
382 * IntersectVisRect (GDI.98)
384 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
385 INT16 right, INT16 bottom )
387 INT16 ret;
388 DC * dc = DC_GetDCUpdate( hdc );
389 if (!dc) return ERROR;
391 left = XLPTODP( dc, left );
392 right = XLPTODP( dc, right );
393 top = YLPTODP( dc, top );
394 bottom = YLPTODP( dc, bottom );
396 TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
398 ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
399 GDI_ReleaseObj( hdc );
400 return ret;
404 /***********************************************************************
405 * PtVisible16 (GDI.103)
407 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
409 return PtVisible( hdc, x, y );
413 /***********************************************************************
414 * PtVisible (GDI32.279)
416 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
418 BOOL ret = FALSE;
419 DC *dc = DC_GetDCUpdate( hdc );
421 TRACE("%04x %d,%d\n", hdc, x, y );
422 if (!dc) return FALSE;
423 if (dc->hGCClipRgn)
425 ret = PtInRegion( dc->hGCClipRgn, XLPTODP(dc,x) + dc->DCOrgX,
426 YLPTODP(dc,y) + dc->DCOrgY );
428 GDI_ReleaseObj( hdc );
429 return ret;
433 /***********************************************************************
434 * RectVisible16 (GDI.104)
436 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
438 BOOL ret = FALSE;
439 RECT16 tmpRect;
440 DC *dc = DC_GetDCUpdate( hdc );
441 if (!dc) return FALSE;
442 TRACE("%04x %d,%dx%d,%d\n",
443 hdc, rect->left, rect->top, rect->right, rect->bottom );
444 if (dc->hGCClipRgn)
446 /* copy rectangle to avoid overwriting by LPtoDP */
447 tmpRect = *rect;
448 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
449 tmpRect.left += dc->DCOrgX;
450 tmpRect.right += dc->DCOrgX;
451 tmpRect.top += dc->DCOrgY;
452 tmpRect.bottom += dc->DCOrgY;
453 ret = RectInRegion16( dc->hGCClipRgn, &tmpRect );
455 GDI_ReleaseObj( hdc );
456 return ret;
460 /***********************************************************************
461 * RectVisible (GDI32.282)
463 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
465 RECT16 rect16;
466 CONV_RECT32TO16( rect, &rect16 );
467 return RectVisible16( (HDC16)hdc, &rect16 );
471 /***********************************************************************
472 * GetClipBox16 (GDI.77)
474 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
476 int ret;
477 DC *dc = DC_GetDCPtr( hdc );
478 if (!dc) return ERROR;
479 ret = GetRgnBox16( dc->hGCClipRgn, rect );
480 rect->left -= dc->DCOrgX;
481 rect->right -= dc->DCOrgX;
482 rect->top -= dc->DCOrgY;
483 rect->bottom -= dc->DCOrgY;
484 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
485 TRACE("%d,%d-%d,%d\n", rect->left,rect->top,rect->right,rect->bottom );
486 GDI_ReleaseObj( hdc );
487 return ret;
491 /***********************************************************************
492 * GetClipBox (GDI32.162)
494 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
496 INT ret;
497 DC *dc = DC_GetDCPtr( hdc );
498 if (!dc) return ERROR;
499 ret = GetRgnBox( dc->hGCClipRgn, rect );
500 rect->left -= dc->DCOrgX;
501 rect->right -= dc->DCOrgX;
502 rect->top -= dc->DCOrgY;
503 rect->bottom -= dc->DCOrgY;
504 DPtoLP( hdc, (LPPOINT)rect, 2 );
505 GDI_ReleaseObj( hdc );
506 return ret;
510 /***********************************************************************
511 * GetClipRgn (GDI32.163)
513 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
515 INT ret = -1;
516 DC * dc;
517 if (hRgn && (dc = DC_GetDCPtr( hdc )))
519 if( dc->hClipRgn )
521 /* this assumes that dc->hClipRgn is in coordinates
522 relative to the device (not DC origin) */
524 if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR )
526 OffsetRgn( hRgn, -dc->DCOrgX, -dc->DCOrgY );
527 ret = 1;
530 else ret = 0;
531 GDI_ReleaseObj( hdc );
533 return ret;
536 /***********************************************************************
537 * SaveVisRgn (GDI.129)
539 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
541 HRGN copy;
542 RGNOBJ *obj, *copyObj;
543 DC *dc = DC_GetDCUpdate( hdc );
545 if (!dc) return 0;
546 TRACE("%04x\n", hdc );
548 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
550 GDI_ReleaseObj( hdc );
551 return 0;
553 if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
555 GDI_ReleaseObj( dc->hVisRgn );
556 GDI_ReleaseObj( hdc );
557 return 0;
559 CombineRgn( copy, dc->hVisRgn, 0, RGN_COPY );
560 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
562 DeleteObject( copy );
563 GDI_ReleaseObj( dc->hVisRgn );
564 GDI_ReleaseObj( hdc );
565 return 0;
567 copyObj->header.hNext = obj->header.hNext;
568 obj->header.hNext = copy;
569 GDI_ReleaseObj( copy );
570 GDI_ReleaseObj( dc->hVisRgn );
571 GDI_ReleaseObj( hdc );
572 return copy;
576 /***********************************************************************
577 * RestoreVisRgn (GDI.130)
579 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
581 HRGN saved;
582 RGNOBJ *obj, *savedObj;
583 DC *dc = DC_GetDCPtr( hdc );
584 INT16 ret = ERROR;
586 if (!dc) return ERROR;
587 if (!dc->hVisRgn) goto done;
588 TRACE("%04x\n", hdc );
589 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
591 saved = obj->header.hNext;
592 GDI_ReleaseObj( dc->hVisRgn );
593 if (!saved || !(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC ))) goto done;
595 DeleteObject( dc->hVisRgn );
596 dc->hVisRgn = saved;
597 dc->flags &= ~DC_DIRTY;
598 CLIPPING_UpdateGCRegion( dc );
599 ret = savedObj->rgn->type; /* FIXME */
600 GDI_ReleaseObj( saved );
601 done:
602 GDI_ReleaseObj( hdc );
603 return ret;