Implemented SendMessageTimeout() functions.
[wine/multimedia.git] / objects / clipping.c
blob428aa272169235de875485e9c37efc4877ea19f6
1 /*
2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include "dc.h"
9 #include "metafile.h"
10 #include "region.h"
11 #include "debug.h"
12 #include "wine/winuser16.h"
14 #define UPDATE_DIRTY_DC(dc) \
15 do { \
16 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
17 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
18 } while(0)
22 /***********************************************************************
23 * CLIPPING_UpdateGCRegion
25 * Update the GC clip region when the ClipRgn or VisRgn have changed.
27 void CLIPPING_UpdateGCRegion( DC * dc )
29 if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
31 if (!dc->w.hVisRgn)
33 ERR(region, "hVisRgn is zero. Please report this.\n" );
34 exit(1);
37 if (dc->w.flags & DC_DIRTY)
39 UPDATE_DIRTY_DC(dc);
40 dc->w.flags &= ~DC_DIRTY;
43 if (!dc->w.hClipRgn)
44 CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
45 else
46 CombineRgn(dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND);
47 if (dc->funcs->pSetDeviceClipping) dc->funcs->pSetDeviceClipping( dc );
51 /***********************************************************************
52 * SelectClipRgn16 (GDI.44)
54 INT16 WINAPI SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
56 return (INT16)SelectClipRgn( hdc, hrgn );
60 /***********************************************************************
61 * SelectClipRgn32 (GDI32.297)
63 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
65 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
68 /******************************************************************************
69 * ExtSelectClipRgn [GDI32.97]
71 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
73 INT retval;
74 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
75 if (!dc) return ERROR;
77 TRACE( clipping, "%04x %04x %d\n", hdc, hrgn, fnMode );
79 if (!hrgn)
81 if (fnMode == RGN_COPY)
83 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
84 dc->w.hClipRgn = 0;
85 retval = SIMPLEREGION; /* Clip region == whole DC */
87 else
89 FIXME(clipping, "Unimplemented: hrgn NULL in mode: %d\n", fnMode);
90 return ERROR;
93 else
95 if (!dc->w.hClipRgn)
97 RECT rect;
98 GetRgnBox( dc->w.hVisRgn, &rect );
99 dc->w.hClipRgn = CreateRectRgnIndirect( &rect );
102 OffsetRgn( dc->w.hClipRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
103 if(fnMode == RGN_COPY)
104 retval = CombineRgn( dc->w.hClipRgn, hrgn, 0, fnMode );
105 else
106 retval = CombineRgn( dc->w.hClipRgn, dc->w.hClipRgn, hrgn, fnMode);
107 OffsetRgn( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
111 CLIPPING_UpdateGCRegion( dc );
112 GDI_HEAP_UNLOCK( hdc );
113 return retval;
116 /***********************************************************************
117 * SelectVisRgn (GDI.105)
119 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
121 int retval;
122 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
123 if (!dc || !hrgn) return ERROR;
125 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
127 dc->w.flags &= ~DC_DIRTY;
129 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
130 CLIPPING_UpdateGCRegion( dc );
131 GDI_HEAP_UNLOCK( hdc );
132 return retval;
136 /***********************************************************************
137 * OffsetClipRgn16 (GDI.32)
139 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
141 return (INT16)OffsetClipRgn( hdc, x, y );
145 /***********************************************************************
146 * OffsetClipRgn32 (GDI32.255)
148 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
150 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
151 if (!dc)
153 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
154 if (!dc) return ERROR;
155 MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
156 GDI_HEAP_UNLOCK( hdc );
157 return NULLREGION; /* ?? */
160 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
162 if (dc->w.hClipRgn)
164 INT ret = OffsetRgn( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
165 CLIPPING_UpdateGCRegion( dc );
166 GDI_HEAP_UNLOCK( hdc );
167 return ret;
169 GDI_HEAP_UNLOCK( hdc );
170 return SIMPLEREGION; /* Clip region == client area */
174 /***********************************************************************
175 * OffsetVisRgn (GDI.102)
177 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
179 INT16 retval;
180 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
181 if (!dc) return ERROR;
182 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
183 retval = OffsetRgn( dc->w.hVisRgn, x, y );
184 CLIPPING_UpdateGCRegion( dc );
185 GDI_HEAP_UNLOCK( hdc );
186 return retval;
190 /***********************************************************************
191 * CLIPPING_IntersectClipRect
193 * Helper function for {Intersect,Exclude}ClipRect, can be called from
194 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
195 * coordinate conversion.
197 INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
198 INT right, INT bottom, UINT flags )
200 HRGN newRgn;
201 INT ret;
203 left += dc->w.DCOrgX;
204 right += dc->w.DCOrgX;
205 top += dc->w.DCOrgY;
206 bottom += dc->w.DCOrgY;
208 if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
209 if (!dc->w.hClipRgn)
211 if( flags & CLIP_INTERSECT )
213 dc->w.hClipRgn = newRgn;
214 CLIPPING_UpdateGCRegion( dc );
215 return SIMPLEREGION;
217 else if( flags & CLIP_EXCLUDE )
219 dc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
220 CombineRgn( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
222 else WARN(clipping,"No hClipRgn and flags are %x\n",flags);
225 ret = CombineRgn( newRgn, dc->w.hClipRgn, newRgn,
226 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
227 if (ret != ERROR)
229 if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->w.hClipRgn );
230 dc->w.hClipRgn = newRgn;
231 CLIPPING_UpdateGCRegion( dc );
233 else DeleteObject( newRgn );
234 return ret;
238 /***********************************************************************
239 * ExcludeClipRect16 (GDI.21)
241 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
242 INT16 right, INT16 bottom )
244 return (INT16)ExcludeClipRect( hdc, left, top, right, bottom );
248 /***********************************************************************
249 * ExcludeClipRect32 (GDI32.92)
251 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
252 INT right, INT bottom )
254 INT ret;
255 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
256 if (!dc)
258 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
259 if (!dc) return ERROR;
260 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
261 GDI_HEAP_UNLOCK( hdc );
262 return NULLREGION; /* ?? */
265 left = XLPTODP( dc, left );
266 right = XLPTODP( dc, right );
267 top = YLPTODP( dc, top );
268 bottom = YLPTODP( dc, bottom );
270 TRACE(clipping, "%04x %dx%d,%dx%d\n",
271 hdc, left, top, right, bottom );
272 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 *) GDI_GetObjPtr( hdc, DC_MAGIC );
296 if (!dc)
298 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
299 if (!dc) return ERROR;
300 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
301 GDI_HEAP_UNLOCK( hdc );
302 return NULLREGION; /* ?? */
305 left = XLPTODP( dc, left );
306 right = XLPTODP( dc, right );
307 top = YLPTODP( dc, top );
308 bottom = YLPTODP( dc, bottom );
310 TRACE(clipping, "%04x %dx%d,%dx%d\n",
311 hdc, left, top, right, bottom );
312 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
313 GDI_HEAP_UNLOCK( hdc );
314 return ret;
318 /***********************************************************************
319 * CLIPPING_IntersectVisRect
321 * Helper function for {Intersect,Exclude}VisRect, can be called from
322 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
323 * coordinate conversion.
325 INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
326 INT right, INT bottom,
327 BOOL exclude )
329 HRGN tempRgn, newRgn;
330 INT ret;
332 left += dc->w.DCOrgX;
333 right += dc->w.DCOrgX;
334 top += dc->w.DCOrgY;
335 bottom += dc->w.DCOrgY;
337 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
338 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
340 DeleteObject( newRgn );
341 return ERROR;
343 ret = CombineRgn( newRgn, dc->w.hVisRgn, tempRgn,
344 exclude ? RGN_DIFF : RGN_AND );
345 DeleteObject( tempRgn );
347 if (ret != ERROR)
349 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
350 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
351 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
352 DeleteObject( dc->w.hVisRgn );
353 dc->w.hVisRgn = newRgn;
354 CLIPPING_UpdateGCRegion( dc );
355 GDI_HEAP_UNLOCK( newRgn );
357 else DeleteObject( newRgn );
358 return ret;
362 /***********************************************************************
363 * ExcludeVisRect (GDI.73)
365 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
366 INT16 right, INT16 bottom )
368 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
369 if (!dc) return ERROR;
371 left = XLPTODP( dc, left );
372 right = XLPTODP( dc, right );
373 top = YLPTODP( dc, top );
374 bottom = YLPTODP( dc, bottom );
376 TRACE(clipping, "%04x %dx%d,%dx%d\n",
377 hdc, left, top, right, bottom );
379 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
383 /***********************************************************************
384 * IntersectVisRect (GDI.98)
386 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
387 INT16 right, INT16 bottom )
389 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
390 if (!dc) return ERROR;
392 left = XLPTODP( dc, left );
393 right = XLPTODP( dc, right );
394 top = YLPTODP( dc, top );
395 bottom = YLPTODP( dc, bottom );
397 TRACE(clipping, "%04x %dx%d,%dx%d\n",
398 hdc, left, top, right, bottom );
400 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
404 /***********************************************************************
405 * PtVisible16 (GDI.103)
407 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
409 return PtVisible( hdc, x, y );
413 /***********************************************************************
414 * PtVisible32 (GDI32.279)
416 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
418 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
419 if (!dc) return ERROR;
421 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
422 if (!dc->w.hGCClipRgn) return FALSE;
424 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
425 dc->w.flags &= ~DC_DIRTY;
427 return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX,
428 YLPTODP(dc,y) + dc->w.DCOrgY );
432 /***********************************************************************
433 * RectVisible16 (GDI.104)
435 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
437 RECT16 tmpRect;
438 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
439 if (!dc) return FALSE;
440 TRACE(clipping,"%04x %d,%dx%d,%d\n",
441 hdc, rect->left, rect->top, rect->right, rect->bottom );
442 if (!dc->w.hGCClipRgn) return FALSE;
443 /* copy rectangle to avoid overwriting by LPtoDP */
444 tmpRect = *rect;
445 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
446 OffsetRect16( &tmpRect, dc->w.DCOrgX, dc->w.DCOrgY );
447 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
451 /***********************************************************************
452 * RectVisible32 (GDI32.282)
454 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
456 RECT16 rect16;
457 CONV_RECT32TO16( rect, &rect16 );
458 return RectVisible16( (HDC16)hdc, &rect16 );
462 /***********************************************************************
463 * GetClipBox16 (GDI.77)
465 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
467 int ret;
468 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
469 if (!dc) return ERROR;
470 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
471 OffsetRect16( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
472 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
473 TRACE(clipping, "%d,%d-%d,%d\n",
474 rect->left,rect->top,rect->right,rect->bottom );
475 return ret;
479 /***********************************************************************
480 * GetClipBox32 (GDI32.162)
482 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
484 INT ret;
485 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
486 if (!dc) return ERROR;
487 ret = GetRgnBox( dc->w.hGCClipRgn, rect );
488 OffsetRect( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
489 DPtoLP( hdc, (LPPOINT)rect, 2 );
490 return ret;
494 /***********************************************************************
495 * GetClipRgn32 (GDI32.163)
497 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
499 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
500 if( dc && hRgn )
502 if( dc->w.hClipRgn )
504 /* this assumes that dc->w.hClipRgn is in coordinates
505 relative to the device (not DC origin) */
507 if( CombineRgn(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
509 OffsetRgn( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
510 return 1;
513 else return 0;
515 return -1;
518 /***********************************************************************
519 * SaveVisRgn (GDI.129)
521 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
523 HRGN copy;
524 RGNOBJ *obj, *copyObj;
525 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
526 if (!dc) return 0;
527 TRACE(clipping, "%04x\n", hdc );
528 if (!dc->w.hVisRgn)
530 ERR(region, "hVisRgn is zero. Please report this.\n" );
531 exit(1);
533 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
534 dc->w.flags &= ~DC_DIRTY;
536 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
538 GDI_HEAP_UNLOCK( hdc );
539 return 0;
541 if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
543 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
544 GDI_HEAP_UNLOCK( hdc );
545 return 0;
547 CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
548 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
550 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
551 GDI_HEAP_UNLOCK( hdc );
552 return 0;
554 copyObj->header.hNext = obj->header.hNext;
555 obj->header.hNext = copy;
556 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
557 GDI_HEAP_UNLOCK( hdc );
558 GDI_HEAP_UNLOCK( copy );
559 return copy;
563 /***********************************************************************
564 * RestoreVisRgn (GDI.130)
566 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
568 HRGN saved;
569 RGNOBJ *obj, *savedObj;
570 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
571 INT16 ret;
573 if (!dc) return ERROR;
574 if (!dc->w.hVisRgn)
576 GDI_HEAP_UNLOCK( hdc );
577 return ERROR;
579 TRACE(clipping, "%04x\n", hdc );
580 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
582 GDI_HEAP_UNLOCK( hdc );
583 return ERROR;
585 if (!(saved = obj->header.hNext))
587 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
588 GDI_HEAP_UNLOCK( hdc );
589 return ERROR;
591 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
593 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
594 GDI_HEAP_UNLOCK( hdc );
595 return ERROR;
597 DeleteObject( dc->w.hVisRgn );
598 dc->w.hVisRgn = saved;
599 CLIPPING_UpdateGCRegion( dc );
600 GDI_HEAP_UNLOCK( hdc );
601 ret = savedObj->rgn->type; /* FIXME */
602 GDI_HEAP_UNLOCK( saved );
603 return ret;