Release 990226.
[wine/gsoc-2012-control.git] / objects / clipping.c
blob99316cfdeb1ddd30ec5b42ae7d2796c78f309182
1 /*
2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "dc.h"
8 #include "metafile.h"
9 #include "region.h"
10 #include "debug.h"
11 #include "wine/winuser16.h"
13 #define UPDATE_DIRTY_DC(dc) \
14 do { \
15 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
16 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
17 } while(0)
21 /***********************************************************************
22 * CLIPPING_UpdateGCRegion
24 * Update the GC clip region when the ClipRgn or VisRgn have changed.
26 void CLIPPING_UpdateGCRegion( DC * dc )
28 if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
30 if (!dc->w.hVisRgn)
32 ERR(region, "hVisRgn is zero. Please report this.\n" );
33 exit(1);
36 if (dc->w.flags & DC_DIRTY)
38 UPDATE_DIRTY_DC(dc);
39 dc->w.flags &= ~DC_DIRTY;
42 if (!dc->w.hClipRgn)
43 CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
44 else
45 CombineRgn(dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND);
46 if (dc->funcs->pSetDeviceClipping) dc->funcs->pSetDeviceClipping( dc );
50 /***********************************************************************
51 * SelectClipRgn16 (GDI.44)
53 INT16 WINAPI SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
55 return (INT16)SelectClipRgn( hdc, hrgn );
59 /***********************************************************************
60 * SelectClipRgn32 (GDI32.297)
62 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
64 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
67 /******************************************************************************
68 * ExtSelectClipRgn [GDI32.97]
70 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
72 INT retval;
73 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
74 if (!dc) return ERROR;
76 TRACE( clipping, "%04x %04x %d\n", hdc, hrgn, fnMode );
78 if (!hrgn)
80 if (fnMode == RGN_COPY)
82 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
83 dc->w.hClipRgn = 0;
84 retval = SIMPLEREGION; /* Clip region == whole DC */
86 else
88 FIXME(clipping, "Unimplemented: hrgn NULL in mode: %d\n", fnMode);
89 return ERROR;
92 else
94 if (!dc->w.hClipRgn)
96 RECT rect;
97 GetRgnBox( dc->w.hVisRgn, &rect );
98 dc->w.hClipRgn = CreateRectRgnIndirect( &rect );
101 OffsetRgn( dc->w.hClipRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
102 if(fnMode == RGN_COPY)
103 retval = CombineRgn( dc->w.hClipRgn, hrgn, 0, fnMode );
104 else
105 retval = CombineRgn( dc->w.hClipRgn, dc->w.hClipRgn, hrgn, fnMode);
106 OffsetRgn( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
110 CLIPPING_UpdateGCRegion( dc );
111 GDI_HEAP_UNLOCK( hdc );
112 return retval;
115 /***********************************************************************
116 * SelectVisRgn (GDI.105)
118 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
120 int retval;
121 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
122 if (!dc || !hrgn) return ERROR;
124 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
126 dc->w.flags &= ~DC_DIRTY;
128 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
129 CLIPPING_UpdateGCRegion( dc );
130 GDI_HEAP_UNLOCK( hdc );
131 return retval;
135 /***********************************************************************
136 * OffsetClipRgn16 (GDI.32)
138 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
140 return (INT16)OffsetClipRgn( hdc, x, y );
144 /***********************************************************************
145 * OffsetClipRgn32 (GDI32.255)
147 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
149 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
150 if (!dc)
152 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
153 if (!dc) return ERROR;
154 MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
155 GDI_HEAP_UNLOCK( hdc );
156 return NULLREGION; /* ?? */
159 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
161 if (dc->w.hClipRgn)
163 INT ret = OffsetRgn( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
164 CLIPPING_UpdateGCRegion( dc );
165 GDI_HEAP_UNLOCK( hdc );
166 return ret;
168 GDI_HEAP_UNLOCK( hdc );
169 return SIMPLEREGION; /* Clip region == client area */
173 /***********************************************************************
174 * OffsetVisRgn (GDI.102)
176 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
178 INT16 retval;
179 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
180 if (!dc) return ERROR;
181 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
182 retval = OffsetRgn( dc->w.hVisRgn, x, y );
183 CLIPPING_UpdateGCRegion( dc );
184 GDI_HEAP_UNLOCK( hdc );
185 return retval;
189 /***********************************************************************
190 * CLIPPING_IntersectClipRect
192 * Helper function for {Intersect,Exclude}ClipRect, can be called from
193 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
194 * coordinate conversion.
196 INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
197 INT right, INT bottom, UINT flags )
199 HRGN newRgn;
200 INT ret;
202 left += dc->w.DCOrgX;
203 right += dc->w.DCOrgX;
204 top += dc->w.DCOrgY;
205 bottom += dc->w.DCOrgY;
207 if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
208 if (!dc->w.hClipRgn)
210 if( flags & CLIP_INTERSECT )
212 dc->w.hClipRgn = newRgn;
213 CLIPPING_UpdateGCRegion( dc );
214 return SIMPLEREGION;
216 else if( flags & CLIP_EXCLUDE )
218 dc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
219 CombineRgn( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
221 else WARN(clipping,"No hClipRgn and flags are %x\n",flags);
224 ret = CombineRgn( newRgn, dc->w.hClipRgn, newRgn,
225 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
226 if (ret != ERROR)
228 if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->w.hClipRgn );
229 dc->w.hClipRgn = newRgn;
230 CLIPPING_UpdateGCRegion( dc );
232 else DeleteObject( newRgn );
233 return ret;
237 /***********************************************************************
238 * ExcludeClipRect16 (GDI.21)
240 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
241 INT16 right, INT16 bottom )
243 return (INT16)ExcludeClipRect( hdc, left, top, right, bottom );
247 /***********************************************************************
248 * ExcludeClipRect32 (GDI32.92)
250 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
251 INT right, INT bottom )
253 INT ret;
254 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
255 if (!dc)
257 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
258 if (!dc) return ERROR;
259 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
260 GDI_HEAP_UNLOCK( hdc );
261 return NULLREGION; /* ?? */
264 left = XLPTODP( dc, left );
265 right = XLPTODP( dc, right );
266 top = YLPTODP( dc, top );
267 bottom = YLPTODP( dc, bottom );
269 TRACE(clipping, "%04x %dx%d,%dx%d\n",
270 hdc, left, top, right, bottom );
271 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
272 GDI_HEAP_UNLOCK( hdc );
273 return ret;
277 /***********************************************************************
278 * IntersectClipRect16 (GDI.22)
280 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
281 INT16 right, INT16 bottom )
283 return (INT16)IntersectClipRect( hdc, left, top, right, bottom );
287 /***********************************************************************
288 * IntersectClipRect32 (GDI32.245)
290 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
291 INT right, INT bottom )
293 INT ret;
294 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
295 if (!dc)
297 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
298 if (!dc) return ERROR;
299 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
300 GDI_HEAP_UNLOCK( hdc );
301 return NULLREGION; /* ?? */
304 left = XLPTODP( dc, left );
305 right = XLPTODP( dc, right );
306 top = YLPTODP( dc, top );
307 bottom = YLPTODP( dc, bottom );
309 TRACE(clipping, "%04x %dx%d,%dx%d\n",
310 hdc, left, top, right, bottom );
311 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
312 GDI_HEAP_UNLOCK( hdc );
313 return ret;
317 /***********************************************************************
318 * CLIPPING_IntersectVisRect
320 * Helper function for {Intersect,Exclude}VisRect, can be called from
321 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
322 * coordinate conversion.
324 INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
325 INT right, INT bottom,
326 BOOL exclude )
328 HRGN tempRgn, newRgn;
329 INT ret;
331 left += dc->w.DCOrgX;
332 right += dc->w.DCOrgX;
333 top += dc->w.DCOrgY;
334 bottom += dc->w.DCOrgY;
336 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
337 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
339 DeleteObject( newRgn );
340 return ERROR;
342 ret = CombineRgn( newRgn, dc->w.hVisRgn, tempRgn,
343 exclude ? RGN_DIFF : RGN_AND );
344 DeleteObject( tempRgn );
346 if (ret != ERROR)
348 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
349 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
350 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
351 DeleteObject( dc->w.hVisRgn );
352 dc->w.hVisRgn = newRgn;
353 CLIPPING_UpdateGCRegion( dc );
354 GDI_HEAP_UNLOCK( newRgn );
356 else DeleteObject( newRgn );
357 return ret;
361 /***********************************************************************
362 * ExcludeVisRect (GDI.73)
364 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
365 INT16 right, INT16 bottom )
367 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
368 if (!dc) return ERROR;
370 left = XLPTODP( dc, left );
371 right = XLPTODP( dc, right );
372 top = YLPTODP( dc, top );
373 bottom = YLPTODP( dc, bottom );
375 TRACE(clipping, "%04x %dx%d,%dx%d\n",
376 hdc, left, top, right, bottom );
378 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
382 /***********************************************************************
383 * IntersectVisRect (GDI.98)
385 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
386 INT16 right, INT16 bottom )
388 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
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(clipping, "%04x %dx%d,%dx%d\n",
397 hdc, left, top, right, bottom );
399 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
403 /***********************************************************************
404 * PtVisible16 (GDI.103)
406 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
408 return PtVisible( hdc, x, y );
412 /***********************************************************************
413 * PtVisible32 (GDI32.279)
415 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
417 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
418 if (!dc) return ERROR;
420 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
421 if (!dc->w.hGCClipRgn) return FALSE;
423 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
424 dc->w.flags &= ~DC_DIRTY;
426 return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX,
427 YLPTODP(dc,y) + dc->w.DCOrgY );
431 /***********************************************************************
432 * RectVisible16 (GDI.104)
434 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
436 RECT16 tmpRect;
437 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
438 if (!dc) return FALSE;
439 TRACE(clipping,"%04x %d,%dx%d,%d\n",
440 hdc, rect->left, rect->top, rect->right, rect->bottom );
441 if (!dc->w.hGCClipRgn) return FALSE;
442 /* copy rectangle to avoid overwriting by LPtoDP */
443 tmpRect = *rect;
444 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
445 OffsetRect16( &tmpRect, dc->w.DCOrgX, dc->w.DCOrgY );
446 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
450 /***********************************************************************
451 * RectVisible32 (GDI32.282)
453 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
455 RECT16 rect16;
456 CONV_RECT32TO16( rect, &rect16 );
457 return RectVisible16( (HDC16)hdc, &rect16 );
461 /***********************************************************************
462 * GetClipBox16 (GDI.77)
464 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
466 int ret;
467 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
468 if (!dc) return ERROR;
469 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
470 OffsetRect16( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
471 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
472 TRACE(clipping, "%d,%d-%d,%d\n",
473 rect->left,rect->top,rect->right,rect->bottom );
474 return ret;
478 /***********************************************************************
479 * GetClipBox32 (GDI32.162)
481 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
483 INT ret;
484 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
485 if (!dc) return ERROR;
486 ret = GetRgnBox( dc->w.hGCClipRgn, rect );
487 OffsetRect( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
488 DPtoLP( hdc, (LPPOINT)rect, 2 );
489 return ret;
493 /***********************************************************************
494 * GetClipRgn32 (GDI32.163)
496 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
498 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
499 if( dc && hRgn )
501 if( dc->w.hClipRgn )
503 /* this assumes that dc->w.hClipRgn is in coordinates
504 relative to the device (not DC origin) */
506 if( CombineRgn(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
508 OffsetRgn( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
509 return 1;
512 else return 0;
514 return -1;
517 /***********************************************************************
518 * SaveVisRgn (GDI.129)
520 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
522 HRGN copy;
523 RGNOBJ *obj, *copyObj;
524 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
525 if (!dc) return 0;
526 TRACE(clipping, "%04x\n", hdc );
527 if (!dc->w.hVisRgn)
529 ERR(region, "hVisRgn is zero. Please report this.\n" );
530 exit(1);
532 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
533 dc->w.flags &= ~DC_DIRTY;
535 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
537 GDI_HEAP_UNLOCK( hdc );
538 return 0;
540 if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
542 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
543 GDI_HEAP_UNLOCK( hdc );
544 return 0;
546 CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
547 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
549 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
550 GDI_HEAP_UNLOCK( hdc );
551 return 0;
553 copyObj->header.hNext = obj->header.hNext;
554 obj->header.hNext = copy;
555 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
556 GDI_HEAP_UNLOCK( hdc );
557 GDI_HEAP_UNLOCK( copy );
558 return copy;
562 /***********************************************************************
563 * RestoreVisRgn (GDI.130)
565 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
567 HRGN saved;
568 RGNOBJ *obj, *savedObj;
569 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
570 INT16 ret;
572 if (!dc) return ERROR;
573 if (!dc->w.hVisRgn)
575 GDI_HEAP_UNLOCK( hdc );
576 return ERROR;
578 TRACE(clipping, "%04x\n", hdc );
579 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
581 GDI_HEAP_UNLOCK( hdc );
582 return ERROR;
584 if (!(saved = obj->header.hNext))
586 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
587 GDI_HEAP_UNLOCK( hdc );
588 return ERROR;
590 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
592 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
593 GDI_HEAP_UNLOCK( hdc );
594 return ERROR;
596 DeleteObject( dc->w.hVisRgn );
597 dc->w.hVisRgn = saved;
598 CLIPPING_UpdateGCRegion( dc );
599 GDI_HEAP_UNLOCK( hdc );
600 ret = savedObj->rgn->type; /* FIXME */
601 GDI_HEAP_UNLOCK( saved );
602 return ret;