Made more cross-platform by changing ->_fileno to fileno().
[wine/multimedia.git] / objects / clipping.c
blob1e4373dcbaf99e4fdf68b83151b20a0aaf8ba1ae
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"
12 #define UPDATE_DIRTY_DC(dc) \
13 do { \
14 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
15 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
16 } while(0)
20 /***********************************************************************
21 * CLIPPING_UpdateGCRegion
23 * Update the GC clip region when the ClipRgn or VisRgn have changed.
25 void CLIPPING_UpdateGCRegion( DC * dc )
27 if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn32( 0, 0, 0, 0 );
29 if (!dc->w.hVisRgn)
31 ERR(region, "hVisRgn is zero. Please report this.\n" );
32 exit(1);
35 if (dc->w.flags & DC_DIRTY)
37 UPDATE_DIRTY_DC(dc);
38 dc->w.flags &= ~DC_DIRTY;
41 if (!dc->w.hClipRgn)
42 CombineRgn32( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
43 else
44 CombineRgn32(dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND);
45 if (dc->funcs->pSetDeviceClipping) dc->funcs->pSetDeviceClipping( dc );
49 /***********************************************************************
50 * SelectClipRgn16 (GDI.44)
52 INT16 WINAPI SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
54 return (INT16)SelectClipRgn32( hdc, hrgn );
58 /***********************************************************************
59 * SelectClipRgn32 (GDI32.297)
61 INT32 WINAPI SelectClipRgn32( HDC32 hdc, HRGN32 hrgn )
63 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
66 /******************************************************************************
67 * ExtSelectClipRgn [GDI32.97]
69 INT32 WINAPI ExtSelectClipRgn( HDC32 hdc, HRGN32 hrgn, INT32 fnMode )
71 INT32 retval;
72 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
73 if (!dc) return ERROR;
75 TRACE( clipping, "%04x %04x %d\n", hdc, hrgn, fnMode );
77 if (!hrgn)
79 if (fnMode == RGN_COPY)
81 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
82 dc->w.hClipRgn = 0;
83 retval = SIMPLEREGION; /* Clip region == whole DC */
85 else
87 FIXME(clipping, "Unimplemented: hrgn NULL in mode: %d\n", fnMode);
88 return ERROR;
91 else
93 if (!dc->w.hClipRgn)
95 RECT32 rect;
96 GetRgnBox32( dc->w.hVisRgn, &rect );
97 dc->w.hClipRgn = CreateRectRgnIndirect32( &rect );
100 OffsetRgn32( dc->w.hClipRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
101 if(fnMode == RGN_COPY)
102 retval = CombineRgn32( dc->w.hClipRgn, hrgn, 0, fnMode );
103 else
104 retval = CombineRgn32( dc->w.hClipRgn, dc->w.hClipRgn, hrgn, fnMode);
105 OffsetRgn32( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
109 CLIPPING_UpdateGCRegion( dc );
110 GDI_HEAP_UNLOCK( hdc );
111 return retval;
114 /***********************************************************************
115 * SelectVisRgn (GDI.105)
117 INT16 WINAPI SelectVisRgn( HDC16 hdc, HRGN16 hrgn )
119 int retval;
120 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
121 if (!dc || !hrgn) return ERROR;
123 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
125 dc->w.flags &= ~DC_DIRTY;
127 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
128 CLIPPING_UpdateGCRegion( dc );
129 GDI_HEAP_UNLOCK( hdc );
130 return retval;
134 /***********************************************************************
135 * OffsetClipRgn16 (GDI.32)
137 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
139 return (INT16)OffsetClipRgn32( hdc, x, y );
143 /***********************************************************************
144 * OffsetClipRgn32 (GDI32.255)
146 INT32 WINAPI OffsetClipRgn32( HDC32 hdc, INT32 x, INT32 y )
148 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
149 if (!dc)
151 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
152 if (!dc) return ERROR;
153 MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
154 GDI_HEAP_UNLOCK( hdc );
155 return NULLREGION; /* ?? */
158 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
160 if (dc->w.hClipRgn)
162 INT32 ret = OffsetRgn32( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
163 CLIPPING_UpdateGCRegion( dc );
164 GDI_HEAP_UNLOCK( hdc );
165 return ret;
167 GDI_HEAP_UNLOCK( hdc );
168 return SIMPLEREGION; /* Clip region == client area */
172 /***********************************************************************
173 * OffsetVisRgn (GDI.102)
175 INT16 WINAPI OffsetVisRgn( HDC16 hdc, INT16 x, INT16 y )
177 INT16 retval;
178 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
179 if (!dc) return ERROR;
180 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
181 retval = OffsetRgn32( dc->w.hVisRgn, x, y );
182 CLIPPING_UpdateGCRegion( dc );
183 GDI_HEAP_UNLOCK( hdc );
184 return retval;
188 /***********************************************************************
189 * CLIPPING_IntersectClipRect
191 * Helper function for {Intersect,Exclude}ClipRect, can be called from
192 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
193 * coordinate conversion.
195 INT32 CLIPPING_IntersectClipRect( DC * dc, INT32 left, INT32 top,
196 INT32 right, INT32 bottom, UINT32 flags )
198 HRGN32 newRgn;
199 INT32 ret;
201 left += dc->w.DCOrgX;
202 right += dc->w.DCOrgX;
203 top += dc->w.DCOrgY;
204 bottom += dc->w.DCOrgY;
206 if (!(newRgn = CreateRectRgn32( left, top, right, bottom ))) return ERROR;
207 if (!dc->w.hClipRgn)
209 if( flags & CLIP_INTERSECT )
211 dc->w.hClipRgn = newRgn;
212 CLIPPING_UpdateGCRegion( dc );
213 return SIMPLEREGION;
215 else if( flags & CLIP_EXCLUDE )
217 dc->w.hClipRgn = CreateRectRgn32( 0, 0, 0, 0 );
218 CombineRgn32( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
220 else WARN(clipping,"No hClipRgn and flags are %x\n",flags);
223 ret = CombineRgn32( newRgn, dc->w.hClipRgn, newRgn,
224 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
225 if (ret != ERROR)
227 if (!(flags & CLIP_KEEPRGN)) DeleteObject32( dc->w.hClipRgn );
228 dc->w.hClipRgn = newRgn;
229 CLIPPING_UpdateGCRegion( dc );
231 else DeleteObject32( newRgn );
232 return ret;
236 /***********************************************************************
237 * ExcludeClipRect16 (GDI.21)
239 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
240 INT16 right, INT16 bottom )
242 return (INT16)ExcludeClipRect32( hdc, left, top, right, bottom );
246 /***********************************************************************
247 * ExcludeClipRect32 (GDI32.92)
249 INT32 WINAPI ExcludeClipRect32( HDC32 hdc, INT32 left, INT32 top,
250 INT32 right, INT32 bottom )
252 INT32 ret;
253 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
254 if (!dc)
256 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
257 if (!dc) return ERROR;
258 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
259 GDI_HEAP_UNLOCK( hdc );
260 return NULLREGION; /* ?? */
263 left = XLPTODP( dc, left );
264 right = XLPTODP( dc, right );
265 top = YLPTODP( dc, top );
266 bottom = YLPTODP( dc, bottom );
268 TRACE(clipping, "%04x %dx%d,%dx%d\n",
269 hdc, left, top, right, bottom );
270 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
271 GDI_HEAP_UNLOCK( hdc );
272 return ret;
276 /***********************************************************************
277 * IntersectClipRect16 (GDI.22)
279 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
280 INT16 right, INT16 bottom )
282 return (INT16)IntersectClipRect32( hdc, left, top, right, bottom );
286 /***********************************************************************
287 * IntersectClipRect32 (GDI32.245)
289 INT32 WINAPI IntersectClipRect32( HDC32 hdc, INT32 left, INT32 top,
290 INT32 right, INT32 bottom )
292 INT32 ret;
293 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
294 if (!dc)
296 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
297 if (!dc) return ERROR;
298 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
299 GDI_HEAP_UNLOCK( hdc );
300 return NULLREGION; /* ?? */
303 left = XLPTODP( dc, left );
304 right = XLPTODP( dc, right );
305 top = YLPTODP( dc, top );
306 bottom = YLPTODP( dc, bottom );
308 TRACE(clipping, "%04x %dx%d,%dx%d\n",
309 hdc, left, top, right, bottom );
310 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
311 GDI_HEAP_UNLOCK( hdc );
312 return ret;
316 /***********************************************************************
317 * CLIPPING_IntersectVisRect
319 * Helper function for {Intersect,Exclude}VisRect, can be called from
320 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
321 * coordinate conversion.
323 INT32 CLIPPING_IntersectVisRect( DC * dc, INT32 left, INT32 top,
324 INT32 right, INT32 bottom,
325 BOOL32 exclude )
327 HRGN32 tempRgn, newRgn;
328 INT32 ret;
330 left += dc->w.DCOrgX;
331 right += dc->w.DCOrgX;
332 top += dc->w.DCOrgY;
333 bottom += dc->w.DCOrgY;
335 if (!(newRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR;
336 if (!(tempRgn = CreateRectRgn32( left, top, right, bottom )))
338 DeleteObject32( newRgn );
339 return ERROR;
341 ret = CombineRgn32( newRgn, dc->w.hVisRgn, tempRgn,
342 exclude ? RGN_DIFF : RGN_AND );
343 DeleteObject32( tempRgn );
345 if (ret != ERROR)
347 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
348 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
349 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
350 DeleteObject32( dc->w.hVisRgn );
351 dc->w.hVisRgn = newRgn;
352 CLIPPING_UpdateGCRegion( dc );
353 GDI_HEAP_UNLOCK( newRgn );
355 else DeleteObject32( newRgn );
356 return ret;
360 /***********************************************************************
361 * ExcludeVisRect (GDI.73)
363 INT16 WINAPI ExcludeVisRect( HDC16 hdc, INT16 left, INT16 top,
364 INT16 right, INT16 bottom )
366 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
367 if (!dc) return ERROR;
369 left = XLPTODP( dc, left );
370 right = XLPTODP( dc, right );
371 top = YLPTODP( dc, top );
372 bottom = YLPTODP( dc, bottom );
374 TRACE(clipping, "%04x %dx%d,%dx%d\n",
375 hdc, left, top, right, bottom );
377 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
381 /***********************************************************************
382 * IntersectVisRect (GDI.98)
384 INT16 WINAPI IntersectVisRect( HDC16 hdc, INT16 left, INT16 top,
385 INT16 right, INT16 bottom )
387 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
388 if (!dc) return ERROR;
390 left = XLPTODP( dc, left );
391 right = XLPTODP( dc, right );
392 top = YLPTODP( dc, top );
393 bottom = YLPTODP( dc, bottom );
395 TRACE(clipping, "%04x %dx%d,%dx%d\n",
396 hdc, left, top, right, bottom );
398 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
402 /***********************************************************************
403 * PtVisible16 (GDI.103)
405 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
407 return PtVisible32( hdc, x, y );
411 /***********************************************************************
412 * PtVisible32 (GDI32.279)
414 BOOL32 WINAPI PtVisible32( HDC32 hdc, INT32 x, INT32 y )
416 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
417 if (!dc) return ERROR;
419 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
420 if (!dc->w.hGCClipRgn) return FALSE;
422 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
423 dc->w.flags &= ~DC_DIRTY;
425 return PtInRegion32( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX,
426 YLPTODP(dc,y) + dc->w.DCOrgY );
430 /***********************************************************************
431 * RectVisible16 (GDI.104)
433 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
435 RECT16 tmpRect;
436 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
437 if (!dc) return FALSE;
438 TRACE(clipping,"%04x %d,%dx%d,%d\n",
439 hdc, rect->left, rect->top, rect->right, rect->bottom );
440 if (!dc->w.hGCClipRgn) return FALSE;
441 /* copy rectangle to avoid overwriting by LPtoDP */
442 tmpRect = *rect;
443 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
444 OffsetRect16( &tmpRect, dc->w.DCOrgX, dc->w.DCOrgY );
445 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
449 /***********************************************************************
450 * RectVisible32 (GDI32.282)
452 BOOL32 WINAPI RectVisible32( HDC32 hdc, const RECT32* rect )
454 RECT16 rect16;
455 CONV_RECT32TO16( rect, &rect16 );
456 return RectVisible16( (HDC16)hdc, &rect16 );
460 /***********************************************************************
461 * GetClipBox16 (GDI.77)
463 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
465 int ret;
466 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
467 if (!dc) return ERROR;
468 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
469 OffsetRect16( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
470 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
471 TRACE(clipping, "%d,%d-%d,%d\n",
472 rect->left,rect->top,rect->right,rect->bottom );
473 return ret;
477 /***********************************************************************
478 * GetClipBox32 (GDI32.162)
480 INT32 WINAPI GetClipBox32( HDC32 hdc, LPRECT32 rect )
482 INT32 ret;
483 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
484 if (!dc) return ERROR;
485 ret = GetRgnBox32( dc->w.hGCClipRgn, rect );
486 OffsetRect32( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
487 DPtoLP32( hdc, (LPPOINT32)rect, 2 );
488 return ret;
492 /***********************************************************************
493 * GetClipRgn32 (GDI32.163)
495 INT32 WINAPI GetClipRgn32( HDC32 hdc, HRGN32 hRgn )
497 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
498 if( dc && hRgn )
500 if( dc->w.hClipRgn )
502 /* this assumes that dc->w.hClipRgn is in coordinates
503 relative to the device (not DC origin) */
505 if( CombineRgn32(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
507 OffsetRgn32( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
508 return 1;
511 else return 0;
513 return -1;
516 /***********************************************************************
517 * SaveVisRgn (GDI.129)
519 HRGN16 WINAPI SaveVisRgn( HDC16 hdc )
521 HRGN32 copy;
522 RGNOBJ *obj, *copyObj;
523 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
524 if (!dc) return 0;
525 TRACE(clipping, "%04x\n", hdc );
526 if (!dc->w.hVisRgn)
528 ERR(region, "hVisRgn is zero. Please report this.\n" );
529 exit(1);
531 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
532 dc->w.flags &= ~DC_DIRTY;
534 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
536 GDI_HEAP_UNLOCK( hdc );
537 return 0;
539 if (!(copy = CreateRectRgn32( 0, 0, 0, 0 )))
541 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
542 GDI_HEAP_UNLOCK( hdc );
543 return 0;
545 CombineRgn32( copy, dc->w.hVisRgn, 0, RGN_COPY );
546 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
548 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
549 GDI_HEAP_UNLOCK( hdc );
550 return 0;
552 copyObj->header.hNext = obj->header.hNext;
553 obj->header.hNext = copy;
554 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
555 GDI_HEAP_UNLOCK( hdc );
556 GDI_HEAP_UNLOCK( copy );
557 return copy;
561 /***********************************************************************
562 * RestoreVisRgn (GDI.130)
564 INT16 WINAPI RestoreVisRgn( HDC16 hdc )
566 HRGN32 saved;
567 RGNOBJ *obj, *savedObj;
568 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
569 INT16 ret;
571 if (!dc) return ERROR;
572 if (!dc->w.hVisRgn)
574 GDI_HEAP_UNLOCK( hdc );
575 return ERROR;
577 TRACE(clipping, "%04x\n", hdc );
578 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
580 GDI_HEAP_UNLOCK( hdc );
581 return ERROR;
583 if (!(saved = obj->header.hNext))
585 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
586 GDI_HEAP_UNLOCK( hdc );
587 return ERROR;
589 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
591 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
592 GDI_HEAP_UNLOCK( hdc );
593 return ERROR;
595 DeleteObject32( dc->w.hVisRgn );
596 dc->w.hVisRgn = saved;
597 CLIPPING_UpdateGCRegion( dc );
598 GDI_HEAP_UNLOCK( hdc );
599 ret = savedObj->rgn->type; /* FIXME */
600 GDI_HEAP_UNLOCK( saved );
601 return ret;