Got rid of THREAD_InitDone.
[wine/multimedia.git] / objects / clipping.c
blob841ad8a36cd6c80936f028f2432f469b22fda00f
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 DECLARE_DEBUG_CHANNEL(clipping)
14 DECLARE_DEBUG_CHANNEL(region)
16 #define UPDATE_DIRTY_DC(dc) \
17 do { \
18 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
19 (dc)->hookProc( (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 * ExtSelectClipRgn [GDI32.97]
73 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
75 INT retval;
76 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
77 if (!dc) return ERROR;
79 TRACE_(clipping)("%04x %04x %d\n", hdc, hrgn, fnMode );
81 if (!hrgn)
83 if (fnMode == RGN_COPY)
85 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
86 dc->w.hClipRgn = 0;
87 retval = SIMPLEREGION; /* Clip region == whole DC */
89 else
91 FIXME_(clipping)("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
92 return ERROR;
95 else
97 if (!dc->w.hClipRgn)
99 RECT rect;
100 GetRgnBox( dc->w.hVisRgn, &rect );
101 dc->w.hClipRgn = CreateRectRgnIndirect( &rect );
104 OffsetRgn( dc->w.hClipRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
105 if(fnMode == RGN_COPY)
106 retval = CombineRgn( dc->w.hClipRgn, hrgn, 0, fnMode );
107 else
108 retval = CombineRgn( dc->w.hClipRgn, dc->w.hClipRgn, hrgn, fnMode);
109 OffsetRgn( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
113 CLIPPING_UpdateGCRegion( dc );
114 GDI_HEAP_UNLOCK( hdc );
115 return retval;
118 /***********************************************************************
119 * SelectVisRgn (GDI.105)
121 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
123 int retval;
124 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
125 if (!dc || !hrgn) return ERROR;
127 TRACE_(clipping)("%04x %04x\n", hdc, hrgn );
129 dc->w.flags &= ~DC_DIRTY;
131 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
132 CLIPPING_UpdateGCRegion( dc );
133 GDI_HEAP_UNLOCK( 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 * OffsetClipRgn32 (GDI32.255)
150 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
152 INT ret = SIMPLEREGION;
153 DC *dc = DC_GetDCPtr( hdc );
154 if (!dc) return ERROR;
156 TRACE_(clipping)("%04x %d,%d\n", hdc, x, y );
158 if(dc->funcs->pOffsetClipRgn)
159 ret = dc->funcs->pOffsetClipRgn( dc, x, y );
160 else if (dc->w.hClipRgn) {
161 ret = OffsetRgn( dc->w.hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
162 CLIPPING_UpdateGCRegion( dc );
164 GDI_HEAP_UNLOCK( 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 *) GDI_GetObjPtr( hdc, DC_MAGIC );
176 if (!dc) return ERROR;
177 TRACE_(clipping)("%04x %d,%d\n", hdc, x, y );
178 retval = OffsetRgn( dc->w.hVisRgn, x, y );
179 CLIPPING_UpdateGCRegion( dc );
180 GDI_HEAP_UNLOCK( 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->w.DCOrgX;
199 right += dc->w.DCOrgX;
200 top += dc->w.DCOrgY;
201 bottom += dc->w.DCOrgY;
203 if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
204 if (!dc->w.hClipRgn)
206 if( flags & CLIP_INTERSECT )
208 dc->w.hClipRgn = newRgn;
209 CLIPPING_UpdateGCRegion( dc );
210 return SIMPLEREGION;
212 else if( flags & CLIP_EXCLUDE )
214 dc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
215 CombineRgn( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
217 else WARN_(clipping)("No hClipRgn and flags are %x\n",flags);
220 ret = CombineRgn( newRgn, dc->w.hClipRgn, newRgn,
221 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
222 if (ret != ERROR)
224 if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->w.hClipRgn );
225 dc->w.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 * ExcludeClipRect32 (GDI32.92)
246 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
247 INT right, INT bottom )
249 INT ret;
250 DC *dc = DC_GetDCPtr( hdc );
251 if (!dc) return ERROR;
253 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
254 hdc, left, top, right, bottom );
256 if(dc->funcs->pExcludeClipRect)
257 ret = dc->funcs->pExcludeClipRect( dc, left, top, right, bottom );
258 else {
259 left = XLPTODP( dc, left );
260 right = XLPTODP( dc, right );
261 top = YLPTODP( dc, top );
262 bottom = YLPTODP( dc, bottom );
264 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
266 GDI_HEAP_UNLOCK( hdc );
267 return ret;
271 /***********************************************************************
272 * IntersectClipRect16 (GDI.22)
274 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
275 INT16 right, INT16 bottom )
277 return (INT16)IntersectClipRect( hdc, left, top, right, bottom );
281 /***********************************************************************
282 * IntersectClipRect32 (GDI32.245)
284 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
285 INT right, INT bottom )
287 INT ret;
288 DC *dc = DC_GetDCPtr( hdc );
289 if (!dc) return ERROR;
291 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
292 hdc, left, top, right, bottom );
294 if(dc->funcs->pIntersectClipRect)
295 ret = dc->funcs->pIntersectClipRect( dc, left, top, right, bottom );
296 else {
297 left = XLPTODP( dc, left );
298 right = XLPTODP( dc, right );
299 top = YLPTODP( dc, top );
300 bottom = YLPTODP( dc, bottom );
302 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
304 GDI_HEAP_UNLOCK( hdc );
305 return ret;
309 /***********************************************************************
310 * CLIPPING_IntersectVisRect
312 * Helper function for {Intersect,Exclude}VisRect, can be called from
313 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
314 * coordinate conversion.
316 INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
317 INT right, INT bottom,
318 BOOL exclude )
320 HRGN tempRgn, newRgn;
321 INT ret;
323 left += dc->w.DCOrgX;
324 right += dc->w.DCOrgX;
325 top += dc->w.DCOrgY;
326 bottom += dc->w.DCOrgY;
328 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
329 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
331 DeleteObject( newRgn );
332 return ERROR;
334 ret = CombineRgn( newRgn, dc->w.hVisRgn, tempRgn,
335 exclude ? RGN_DIFF : RGN_AND );
336 DeleteObject( tempRgn );
338 if (ret != ERROR)
340 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
341 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
342 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
343 DeleteObject( dc->w.hVisRgn );
344 dc->w.hVisRgn = newRgn;
345 CLIPPING_UpdateGCRegion( dc );
346 GDI_HEAP_UNLOCK( newRgn );
348 else DeleteObject( newRgn );
349 return ret;
353 /***********************************************************************
354 * ExcludeVisRect (GDI.73)
356 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
357 INT16 right, INT16 bottom )
359 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
360 if (!dc) return ERROR;
362 left = XLPTODP( dc, left );
363 right = XLPTODP( dc, right );
364 top = YLPTODP( dc, top );
365 bottom = YLPTODP( dc, bottom );
367 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
368 hdc, left, top, right, bottom );
370 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
374 /***********************************************************************
375 * IntersectVisRect (GDI.98)
377 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
378 INT16 right, INT16 bottom )
380 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
381 if (!dc) return ERROR;
383 left = XLPTODP( dc, left );
384 right = XLPTODP( dc, right );
385 top = YLPTODP( dc, top );
386 bottom = YLPTODP( dc, bottom );
388 TRACE_(clipping)("%04x %dx%d,%dx%d\n",
389 hdc, left, top, right, bottom );
391 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
395 /***********************************************************************
396 * PtVisible16 (GDI.103)
398 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
400 return PtVisible( hdc, x, y );
404 /***********************************************************************
405 * PtVisible32 (GDI32.279)
407 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
409 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
410 if (!dc) return ERROR;
412 TRACE_(clipping)("%04x %d,%d\n", hdc, x, y );
413 if (!dc->w.hGCClipRgn) return FALSE;
415 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
416 dc->w.flags &= ~DC_DIRTY;
418 return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX,
419 YLPTODP(dc,y) + dc->w.DCOrgY );
423 /***********************************************************************
424 * RectVisible16 (GDI.104)
426 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
428 RECT16 tmpRect;
429 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
430 if (!dc) return FALSE;
431 TRACE_(clipping)("%04x %d,%dx%d,%d\n",
432 hdc, rect->left, rect->top, rect->right, rect->bottom );
433 if (!dc->w.hGCClipRgn) return FALSE;
434 /* copy rectangle to avoid overwriting by LPtoDP */
435 tmpRect = *rect;
436 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
437 OffsetRect16( &tmpRect, dc->w.DCOrgX, dc->w.DCOrgY );
438 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
442 /***********************************************************************
443 * RectVisible32 (GDI32.282)
445 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
447 RECT16 rect16;
448 CONV_RECT32TO16( rect, &rect16 );
449 return RectVisible16( (HDC16)hdc, &rect16 );
453 /***********************************************************************
454 * GetClipBox16 (GDI.77)
456 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
458 int ret;
459 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
460 if (!dc) return ERROR;
461 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
462 OffsetRect16( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
463 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
464 TRACE_(clipping)("%d,%d-%d,%d\n",
465 rect->left,rect->top,rect->right,rect->bottom );
466 return ret;
470 /***********************************************************************
471 * GetClipBox32 (GDI32.162)
473 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
475 INT ret;
476 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
477 if (!dc) return ERROR;
478 ret = GetRgnBox( dc->w.hGCClipRgn, rect );
479 OffsetRect( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
480 DPtoLP( hdc, (LPPOINT)rect, 2 );
481 return ret;
485 /***********************************************************************
486 * GetClipRgn32 (GDI32.163)
488 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
490 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
491 if( dc && hRgn )
493 if( dc->w.hClipRgn )
495 /* this assumes that dc->w.hClipRgn is in coordinates
496 relative to the device (not DC origin) */
498 if( CombineRgn(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
500 OffsetRgn( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
501 return 1;
504 else return 0;
506 return -1;
509 /***********************************************************************
510 * SaveVisRgn (GDI.129)
512 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
514 HRGN copy;
515 RGNOBJ *obj, *copyObj;
516 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
517 if (!dc) return 0;
518 TRACE_(clipping)("%04x\n", hdc );
519 if (!dc->w.hVisRgn)
521 ERR_(region)("hVisRgn is zero. Please report this.\n" );
522 exit(1);
524 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
525 dc->w.flags &= ~DC_DIRTY;
527 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
529 GDI_HEAP_UNLOCK( hdc );
530 return 0;
532 if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
534 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
535 GDI_HEAP_UNLOCK( hdc );
536 return 0;
538 CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
539 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
541 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
542 GDI_HEAP_UNLOCK( hdc );
543 return 0;
545 copyObj->header.hNext = obj->header.hNext;
546 obj->header.hNext = copy;
547 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
548 GDI_HEAP_UNLOCK( hdc );
549 GDI_HEAP_UNLOCK( copy );
550 return copy;
554 /***********************************************************************
555 * RestoreVisRgn (GDI.130)
557 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
559 HRGN saved;
560 RGNOBJ *obj, *savedObj;
561 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
562 INT16 ret;
564 if (!dc) return ERROR;
565 if (!dc->w.hVisRgn)
567 GDI_HEAP_UNLOCK( hdc );
568 return ERROR;
570 TRACE_(clipping)("%04x\n", hdc );
571 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
573 GDI_HEAP_UNLOCK( hdc );
574 return ERROR;
576 if (!(saved = obj->header.hNext))
578 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
579 GDI_HEAP_UNLOCK( hdc );
580 return ERROR;
582 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
584 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
585 GDI_HEAP_UNLOCK( hdc );
586 return ERROR;
588 DeleteObject( dc->w.hVisRgn );
589 dc->w.hVisRgn = saved;
590 CLIPPING_UpdateGCRegion( dc );
591 GDI_HEAP_UNLOCK( hdc );
592 ret = savedObj->rgn->type; /* FIXME */
593 GDI_HEAP_UNLOCK( saved );
594 return ret;