- Minor fixes.
[wine/hacks.git] / objects / clipping.c
blobe9f560569cb0d52b2a12818d804c1300a0207edb
1 /*
2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include "dc.h"
9 #include "region.h"
10 #include "debugtools.h"
11 #include "wine/winuser16.h"
13 DEFAULT_DEBUG_CHANNEL(clipping)
14 DECLARE_DEBUG_CHANNEL(region)
16 #define UPDATE_DIRTY_DC(dc) \
17 do { \
18 if ((dc)->hookThunk && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
19 (dc)->hookThunk( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
20 } while(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 );
33 if (!dc->w.hVisRgn)
35 ERR_(region)("hVisRgn is zero. Please report this.\n" );
36 exit(1);
39 if (dc->w.flags & DC_DIRTY)
41 UPDATE_DIRTY_DC(dc);
42 dc->w.flags &= ~DC_DIRTY;
45 if (!dc->w.hClipRgn)
46 CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
47 else
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 * ExtSelectClipRgn16 [GDI.508]
73 INT16 WINAPI ExtSelectClipRgn16( HDC16 hdc, HRGN16 hrgn, INT16 fnMode )
75 return (INT16) ExtSelectClipRgn((HDC) hdc, (HRGN) hrgn, fnMode);
78 /******************************************************************************
79 * ExtSelectClipRgn [GDI32.97]
81 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
83 INT retval;
84 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
85 if (!dc) return ERROR;
87 TRACE("%04x %04x %d\n", hdc, hrgn, fnMode );
89 if (!hrgn)
91 if (fnMode == RGN_COPY)
93 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
94 dc->w.hClipRgn = 0;
95 retval = SIMPLEREGION; /* Clip region == whole DC */
97 else
99 FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
100 return ERROR;
103 else
105 if (!dc->w.hClipRgn)
107 RECT rect;
108 GetRgnBox( dc->w.hVisRgn, &rect );
109 dc->w.hClipRgn = CreateRectRgnIndirect( &rect );
112 OffsetRgn( dc->w.hClipRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
113 if(fnMode == RGN_COPY)
114 retval = CombineRgn( dc->w.hClipRgn, hrgn, 0, fnMode );
115 else
116 retval = CombineRgn( dc->w.hClipRgn, dc->w.hClipRgn, hrgn, fnMode);
117 OffsetRgn( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
121 CLIPPING_UpdateGCRegion( dc );
122 GDI_HEAP_UNLOCK( hdc );
123 return retval;
126 /***********************************************************************
127 * SelectVisRgn (GDI.105)
129 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
131 int retval;
132 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
133 if (!dc || !hrgn) return ERROR;
135 TRACE("%04x %04x\n", hdc, hrgn );
137 dc->w.flags &= ~DC_DIRTY;
139 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
140 CLIPPING_UpdateGCRegion( dc );
141 GDI_HEAP_UNLOCK( hdc );
142 return retval;
146 /***********************************************************************
147 * OffsetClipRgn16 (GDI.32)
149 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
151 return (INT16)OffsetClipRgn( hdc, x, y );
155 /***********************************************************************
156 * OffsetClipRgn32 (GDI32.255)
158 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
160 INT ret = SIMPLEREGION;
161 DC *dc = DC_GetDCPtr( hdc );
162 if (!dc) return ERROR;
164 TRACE("%04x %d,%d\n", hdc, x, y );
166 if(dc->funcs->pOffsetClipRgn)
167 ret = dc->funcs->pOffsetClipRgn( dc, x, y );
168 else if (dc->w.hClipRgn) {
169 ret = OffsetRgn( dc->w.hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
170 CLIPPING_UpdateGCRegion( dc );
172 GDI_HEAP_UNLOCK( hdc );
173 return ret;
177 /***********************************************************************
178 * OffsetVisRgn (GDI.102)
180 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
182 INT16 retval;
183 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
184 if (!dc) return ERROR;
185 TRACE("%04x %d,%d\n", hdc, x, y );
186 retval = OffsetRgn( dc->w.hVisRgn, x, y );
187 CLIPPING_UpdateGCRegion( dc );
188 GDI_HEAP_UNLOCK( hdc );
189 return retval;
193 /***********************************************************************
194 * CLIPPING_IntersectClipRect
196 * Helper function for {Intersect,Exclude}ClipRect, can be called from
197 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
198 * coordinate conversion.
200 INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
201 INT right, INT bottom, UINT flags )
203 HRGN newRgn;
204 INT ret;
206 left += dc->w.DCOrgX;
207 right += dc->w.DCOrgX;
208 top += dc->w.DCOrgY;
209 bottom += dc->w.DCOrgY;
211 if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
212 if (!dc->w.hClipRgn)
214 if( flags & CLIP_INTERSECT )
216 dc->w.hClipRgn = newRgn;
217 CLIPPING_UpdateGCRegion( dc );
218 return SIMPLEREGION;
220 else if( flags & CLIP_EXCLUDE )
222 dc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
223 CombineRgn( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
225 else WARN("No hClipRgn and flags are %x\n",flags);
228 ret = CombineRgn( newRgn, dc->w.hClipRgn, newRgn,
229 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
230 if (ret != ERROR)
232 if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->w.hClipRgn );
233 dc->w.hClipRgn = newRgn;
234 CLIPPING_UpdateGCRegion( dc );
236 else DeleteObject( newRgn );
237 return ret;
241 /***********************************************************************
242 * ExcludeClipRect16 (GDI.21)
244 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
245 INT16 right, INT16 bottom )
247 return (INT16)ExcludeClipRect( hdc, left, top, right, bottom );
251 /***********************************************************************
252 * ExcludeClipRect32 (GDI32.92)
254 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
255 INT right, INT bottom )
257 INT ret;
258 DC *dc = DC_GetDCPtr( hdc );
259 if (!dc) return ERROR;
261 TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
263 if(dc->funcs->pExcludeClipRect)
264 ret = dc->funcs->pExcludeClipRect( dc, left, top, right, bottom );
265 else {
266 left = XLPTODP( dc, left );
267 right = XLPTODP( dc, right );
268 top = YLPTODP( dc, top );
269 bottom = YLPTODP( dc, bottom );
271 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
273 GDI_HEAP_UNLOCK( hdc );
274 return ret;
278 /***********************************************************************
279 * IntersectClipRect16 (GDI.22)
281 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
282 INT16 right, INT16 bottom )
284 return (INT16)IntersectClipRect( hdc, left, top, right, bottom );
288 /***********************************************************************
289 * IntersectClipRect32 (GDI32.245)
291 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
292 INT right, INT bottom )
294 INT ret;
295 DC *dc = DC_GetDCPtr( hdc );
296 if (!dc) return ERROR;
298 TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
300 if(dc->funcs->pIntersectClipRect)
301 ret = dc->funcs->pIntersectClipRect( dc, left, top, right, bottom );
302 else {
303 left = XLPTODP( dc, left );
304 right = XLPTODP( dc, right );
305 top = YLPTODP( dc, top );
306 bottom = YLPTODP( dc, bottom );
308 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
310 GDI_HEAP_UNLOCK( hdc );
311 return ret;
315 /***********************************************************************
316 * CLIPPING_IntersectVisRect
318 * Helper function for {Intersect,Exclude}VisRect, can be called from
319 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
320 * coordinate conversion.
322 INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
323 INT right, INT bottom,
324 BOOL exclude )
326 HRGN tempRgn, newRgn;
327 INT ret;
329 left += dc->w.DCOrgX;
330 right += dc->w.DCOrgX;
331 top += dc->w.DCOrgY;
332 bottom += dc->w.DCOrgY;
334 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
335 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
337 DeleteObject( newRgn );
338 return ERROR;
340 ret = CombineRgn( newRgn, dc->w.hVisRgn, tempRgn,
341 exclude ? RGN_DIFF : RGN_AND );
342 DeleteObject( tempRgn );
344 if (ret != ERROR)
346 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
347 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
348 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
349 DeleteObject( dc->w.hVisRgn );
350 dc->w.hVisRgn = newRgn;
351 CLIPPING_UpdateGCRegion( dc );
352 GDI_HEAP_UNLOCK( newRgn );
354 else DeleteObject( newRgn );
355 return ret;
359 /***********************************************************************
360 * ExcludeVisRect (GDI.73)
362 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
363 INT16 right, INT16 bottom )
365 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
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 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
379 /***********************************************************************
380 * IntersectVisRect (GDI.98)
382 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
383 INT16 right, INT16 bottom )
385 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
386 if (!dc) return ERROR;
388 left = XLPTODP( dc, left );
389 right = XLPTODP( dc, right );
390 top = YLPTODP( dc, top );
391 bottom = YLPTODP( dc, bottom );
393 TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
395 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
399 /***********************************************************************
400 * PtVisible16 (GDI.103)
402 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
404 return PtVisible( hdc, x, y );
408 /***********************************************************************
409 * PtVisible32 (GDI32.279)
411 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
413 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
414 if (!dc) return ERROR;
416 TRACE("%04x %d,%d\n", hdc, x, y );
417 if (!dc->w.hGCClipRgn) return FALSE;
419 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
420 dc->w.flags &= ~DC_DIRTY;
422 return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX,
423 YLPTODP(dc,y) + dc->w.DCOrgY );
427 /***********************************************************************
428 * RectVisible16 (GDI.104)
430 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
432 RECT16 tmpRect;
433 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
434 if (!dc) return FALSE;
435 TRACE("%04x %d,%dx%d,%d\n",
436 hdc, rect->left, rect->top, rect->right, rect->bottom );
437 if (!dc->w.hGCClipRgn) return FALSE;
438 /* copy rectangle to avoid overwriting by LPtoDP */
439 tmpRect = *rect;
440 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
441 OffsetRect16( &tmpRect, dc->w.DCOrgX, dc->w.DCOrgY );
442 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
446 /***********************************************************************
447 * RectVisible32 (GDI32.282)
449 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
451 RECT16 rect16;
452 CONV_RECT32TO16( rect, &rect16 );
453 return RectVisible16( (HDC16)hdc, &rect16 );
457 /***********************************************************************
458 * GetClipBox16 (GDI.77)
460 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
462 int ret;
463 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
464 if (!dc) return ERROR;
465 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
466 OffsetRect16( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
467 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
468 TRACE("%d,%d-%d,%d\n", rect->left,rect->top,rect->right,rect->bottom );
469 return ret;
473 /***********************************************************************
474 * GetClipBox32 (GDI32.162)
476 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
478 INT ret;
479 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
480 if (!dc) return ERROR;
481 ret = GetRgnBox( dc->w.hGCClipRgn, rect );
482 OffsetRect( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
483 DPtoLP( hdc, (LPPOINT)rect, 2 );
484 return ret;
488 /***********************************************************************
489 * GetClipRgn32 (GDI32.163)
491 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
493 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
494 if( dc && hRgn )
496 if( dc->w.hClipRgn )
498 /* this assumes that dc->w.hClipRgn is in coordinates
499 relative to the device (not DC origin) */
501 if( CombineRgn(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
503 OffsetRgn( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
504 return 1;
507 else return 0;
509 return -1;
512 /***********************************************************************
513 * SaveVisRgn (GDI.129)
515 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
517 HRGN copy;
518 RGNOBJ *obj, *copyObj;
519 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
520 if (!dc) return 0;
521 TRACE("%04x\n", hdc );
522 if (!dc->w.hVisRgn)
524 ERR_(region)("hVisRgn is zero. Please report this.\n" );
525 exit(1);
527 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
528 dc->w.flags &= ~DC_DIRTY;
530 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
532 GDI_HEAP_UNLOCK( hdc );
533 return 0;
535 if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
537 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
538 GDI_HEAP_UNLOCK( hdc );
539 return 0;
541 CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
542 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
544 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
545 GDI_HEAP_UNLOCK( hdc );
546 return 0;
548 copyObj->header.hNext = obj->header.hNext;
549 obj->header.hNext = copy;
550 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
551 GDI_HEAP_UNLOCK( hdc );
552 GDI_HEAP_UNLOCK( copy );
553 return copy;
557 /***********************************************************************
558 * RestoreVisRgn (GDI.130)
560 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
562 HRGN saved;
563 RGNOBJ *obj, *savedObj;
564 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
565 INT16 ret;
567 if (!dc) return ERROR;
568 if (!dc->w.hVisRgn)
570 GDI_HEAP_UNLOCK( hdc );
571 return ERROR;
573 TRACE("%04x\n", hdc );
574 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
576 GDI_HEAP_UNLOCK( hdc );
577 return ERROR;
579 if (!(saved = obj->header.hNext))
581 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
582 GDI_HEAP_UNLOCK( hdc );
583 return ERROR;
585 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
587 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
588 GDI_HEAP_UNLOCK( hdc );
589 return ERROR;
591 DeleteObject( dc->w.hVisRgn );
592 dc->w.hVisRgn = saved;
593 CLIPPING_UpdateGCRegion( dc );
594 GDI_HEAP_UNLOCK( hdc );
595 ret = savedObj->rgn->type; /* FIXME */
596 GDI_HEAP_UNLOCK( saved );
597 return ret;