Release 980315
[wine/multimedia.git] / objects / clipping.c
blob17360924badc427b8cbd17fc5a8b880ce6453352
1 /*
2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdio.h>
8 #include "dc.h"
9 #include "metafile.h"
10 #include "region.h"
11 #include "debug.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 = CreateRectRgn32( 0, 0, 0, 0 );
30 if (!dc->w.hVisRgn)
32 fprintf( stderr, "UpdateGCRegion: 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 CombineRgn32( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
44 else
45 CombineRgn32(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)SelectClipRgn32( hdc, hrgn );
59 /***********************************************************************
60 * SelectClipRgn32 (GDI32.297)
62 INT32 WINAPI SelectClipRgn32( HDC32 hdc, HRGN32 hrgn )
64 INT32 retval;
65 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
66 if (!dc) return ERROR;
68 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
70 if (hrgn)
72 if (!dc->w.hClipRgn) dc->w.hClipRgn = CreateRectRgn32(0,0,0,0);
73 retval = CombineRgn32( dc->w.hClipRgn, hrgn, 0, RGN_COPY );
75 else
77 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
78 dc->w.hClipRgn = 0;
79 retval = SIMPLEREGION; /* Clip region == whole DC */
82 CLIPPING_UpdateGCRegion( dc );
83 GDI_HEAP_UNLOCK( hdc );
84 return retval;
88 /***********************************************************************
89 * SelectVisRgn (GDI.105)
91 INT16 WINAPI SelectVisRgn( HDC16 hdc, HRGN16 hrgn )
93 int retval;
94 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
95 if (!dc || !hrgn) return ERROR;
97 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
99 dc->w.flags &= ~DC_DIRTY;
101 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
102 CLIPPING_UpdateGCRegion( dc );
103 GDI_HEAP_UNLOCK( hdc );
104 return retval;
108 /***********************************************************************
109 * OffsetClipRgn16 (GDI.32)
111 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
113 return (INT16)OffsetClipRgn32( hdc, x, y );
117 /***********************************************************************
118 * OffsetClipRgn32 (GDI32.255)
120 INT32 WINAPI OffsetClipRgn32( HDC32 hdc, INT32 x, INT32 y )
122 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
123 if (!dc)
125 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
126 if (!dc) return ERROR;
127 MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
128 GDI_HEAP_UNLOCK( hdc );
129 return NULLREGION; /* ?? */
132 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
134 if (dc->w.hClipRgn)
136 INT32 ret = OffsetRgn32( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
137 CLIPPING_UpdateGCRegion( dc );
138 GDI_HEAP_UNLOCK( hdc );
139 return ret;
141 GDI_HEAP_UNLOCK( hdc );
142 return SIMPLEREGION; /* Clip region == client area */
146 /***********************************************************************
147 * OffsetVisRgn (GDI.102)
149 INT16 WINAPI OffsetVisRgn( HDC16 hdc, INT16 x, INT16 y )
151 INT16 retval;
152 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
153 if (!dc) return ERROR;
154 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
155 retval = OffsetRgn32( dc->w.hVisRgn, x, y );
156 CLIPPING_UpdateGCRegion( dc );
157 GDI_HEAP_UNLOCK( hdc );
158 return retval;
162 /***********************************************************************
163 * CLIPPING_IntersectClipRect
165 * Helper function for {Intersect,Exclude}ClipRect, can be called from
166 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
167 * coordinate conversion.
169 INT32 CLIPPING_IntersectClipRect( DC * dc, INT32 left, INT32 top,
170 INT32 right, INT32 bottom, UINT32 flags )
172 HRGN32 newRgn;
173 INT32 ret;
175 if (!(newRgn = CreateRectRgn32( left, top, right, bottom ))) return ERROR;
176 if (!dc->w.hClipRgn)
178 if( flags & CLIP_INTERSECT )
180 dc->w.hClipRgn = newRgn;
181 CLIPPING_UpdateGCRegion( dc );
183 return SIMPLEREGION;
186 ret = CombineRgn32( newRgn, dc->w.hClipRgn, newRgn,
187 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
188 if (ret != ERROR)
190 if (!(flags & CLIP_KEEPRGN)) DeleteObject32( dc->w.hClipRgn );
191 dc->w.hClipRgn = newRgn;
192 CLIPPING_UpdateGCRegion( dc );
194 else DeleteObject32( newRgn );
195 return ret;
199 /***********************************************************************
200 * ExcludeClipRect16 (GDI.21)
202 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
203 INT16 right, INT16 bottom )
205 return (INT16)ExcludeClipRect32( hdc, left, top, right, bottom );
209 /***********************************************************************
210 * ExcludeClipRect32 (GDI32.92)
212 INT32 WINAPI ExcludeClipRect32( HDC32 hdc, INT32 left, INT32 top,
213 INT32 right, INT32 bottom )
215 INT32 ret;
216 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
217 if (!dc)
219 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
220 if (!dc) return ERROR;
221 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
222 GDI_HEAP_UNLOCK( hdc );
223 return NULLREGION; /* ?? */
226 left = XLPTODP( dc, left );
227 right = XLPTODP( dc, right );
228 top = YLPTODP( dc, top );
229 bottom = YLPTODP( dc, bottom );
231 TRACE(clipping, "%04x %dx%d,%dx%d\n",
232 hdc, left, top, right, bottom );
233 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
234 GDI_HEAP_UNLOCK( hdc );
235 return ret;
239 /***********************************************************************
240 * IntersectClipRect16 (GDI.22)
242 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
243 INT16 right, INT16 bottom )
245 return (INT16)IntersectClipRect32( hdc, left, top, right, bottom );
249 /***********************************************************************
250 * IntersectClipRect32 (GDI32.245)
252 INT32 WINAPI IntersectClipRect32( HDC32 hdc, INT32 left, INT32 top,
253 INT32 right, INT32 bottom )
255 INT32 ret;
256 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
257 if (!dc)
259 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
260 if (!dc) return ERROR;
261 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
262 GDI_HEAP_UNLOCK( hdc );
263 return NULLREGION; /* ?? */
266 left = XLPTODP( dc, left );
267 right = XLPTODP( dc, right );
268 top = YLPTODP( dc, top );
269 bottom = YLPTODP( dc, bottom );
271 TRACE(clipping, "%04x %dx%d,%dx%d\n",
272 hdc, left, top, right, bottom );
273 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
274 GDI_HEAP_UNLOCK( hdc );
275 return ret;
279 /***********************************************************************
280 * CLIPPING_IntersectVisRect
282 * Helper function for {Intersect,Exclude}VisRect
284 static INT32 CLIPPING_IntersectVisRect( DC * dc, INT32 left, INT32 top,
285 INT32 right, INT32 bottom,
286 BOOL32 exclude )
288 HRGN32 tempRgn, newRgn;
289 INT32 ret;
291 left = XLPTODP( dc, left );
292 right = XLPTODP( dc, right );
293 top = YLPTODP( dc, top );
294 bottom = YLPTODP( dc, bottom );
296 if (!(newRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR;
297 if (!(tempRgn = CreateRectRgn32( left, top, right, bottom )))
299 DeleteObject32( newRgn );
300 return ERROR;
302 ret = CombineRgn32( newRgn, dc->w.hVisRgn, tempRgn,
303 exclude ? RGN_DIFF : RGN_AND );
304 DeleteObject32( tempRgn );
306 if (ret != ERROR)
308 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
309 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
310 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
311 DeleteObject32( dc->w.hVisRgn );
312 dc->w.hVisRgn = newRgn;
313 CLIPPING_UpdateGCRegion( dc );
314 GDI_HEAP_UNLOCK( newRgn );
316 else DeleteObject32( newRgn );
317 return ret;
321 /***********************************************************************
322 * ExcludeVisRect (GDI.73)
324 INT16 WINAPI ExcludeVisRect( HDC16 hdc, INT16 left, INT16 top,
325 INT16 right, INT16 bottom )
327 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
328 if (!dc) return ERROR;
329 TRACE(clipping, "%04x %dx%d,%dx%d\n",
330 hdc, left, top, right, bottom );
332 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
336 /***********************************************************************
337 * IntersectVisRect (GDI.98)
339 INT16 WINAPI IntersectVisRect( HDC16 hdc, INT16 left, INT16 top,
340 INT16 right, INT16 bottom )
342 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
343 if (!dc) return ERROR;
344 TRACE(clipping, "%04x %dx%d,%dx%d\n",
345 hdc, left, top, right, bottom );
347 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
351 /***********************************************************************
352 * PtVisible16 (GDI.103)
354 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
356 return PtVisible32( hdc, x, y );
360 /***********************************************************************
361 * PtVisible32 (GDI32.279)
363 BOOL32 WINAPI PtVisible32( HDC32 hdc, INT32 x, INT32 y )
365 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
366 if (!dc) return ERROR;
368 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
369 if (!dc->w.hGCClipRgn) return FALSE;
371 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
372 dc->w.flags &= ~DC_DIRTY;
374 return PtInRegion32( dc->w.hGCClipRgn, XLPTODP(dc,x), YLPTODP(dc,y) );
378 /***********************************************************************
379 * RectVisible16 (GDI.104)
381 BOOL16 WINAPI RectVisible16( HDC16 hdc, LPRECT16 rect )
383 RECT16 tmpRect;
384 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
385 if (!dc) return FALSE;
386 TRACE(clipping,"%04x %d,%dx%d,%d\n",
387 hdc, rect->left, rect->top, rect->right, rect->bottom );
388 if (!dc->w.hGCClipRgn) return FALSE;
389 /* copy rectangle to avoid overwriting by LPtoDP */
390 tmpRect = *rect;
391 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
392 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
396 /***********************************************************************
397 * RectVisible32 (GDI32.282)
399 BOOL32 WINAPI RectVisible32( HDC32 hdc, LPRECT32 rect )
401 RECT16 rect16;
402 CONV_RECT32TO16( rect, &rect16 );
403 return RectVisible16( (HDC16)hdc, &rect16 );
407 /***********************************************************************
408 * GetClipBox16 (GDI.77)
410 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
412 int ret;
413 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
414 if (!dc) return ERROR;
415 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
416 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
417 return ret;
421 /***********************************************************************
422 * GetClipBox32 (GDI32.162)
424 INT32 WINAPI GetClipBox32( HDC32 hdc, LPRECT32 rect )
426 INT32 ret;
427 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
428 if (!dc) return ERROR;
429 ret = GetRgnBox32( dc->w.hGCClipRgn, rect );
430 DPtoLP32( hdc, (LPPOINT32)rect, 2 );
431 return ret;
435 /***********************************************************************
436 * GetClipRgn32 (GDI32.163)
438 INT32 WINAPI GetClipRgn32( HDC32 hdc, HRGN32 hRgn )
440 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
441 if( dc && hRgn )
442 if( dc->w.hClipRgn )
444 /* this assumes that dc->w.hClipRgn is in coordinates
445 relative to the DC origin (not device) */
447 if( CombineRgn32(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
448 return 1;
450 else return 0;
451 return -1;
454 /***********************************************************************
455 * SaveVisRgn (GDI.129)
457 HRGN16 WINAPI SaveVisRgn( HDC16 hdc )
459 HRGN32 copy;
460 RGNOBJ *obj, *copyObj;
461 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
462 if (!dc) return 0;
463 TRACE(clipping, "%04x\n", hdc );
464 if (!dc->w.hVisRgn)
466 fprintf( stderr, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
467 exit(1);
469 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
470 dc->w.flags &= ~DC_DIRTY;
472 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
474 GDI_HEAP_UNLOCK( hdc );
475 return 0;
477 if (!(copy = CreateRectRgn32( 0, 0, 0, 0 )))
479 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
480 GDI_HEAP_UNLOCK( hdc );
481 return 0;
483 CombineRgn32( copy, dc->w.hVisRgn, 0, RGN_COPY );
484 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
486 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
487 GDI_HEAP_UNLOCK( hdc );
488 return 0;
490 copyObj->header.hNext = obj->header.hNext;
491 obj->header.hNext = copy;
492 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
493 GDI_HEAP_UNLOCK( hdc );
494 GDI_HEAP_UNLOCK( copy );
495 return copy;
499 /***********************************************************************
500 * RestoreVisRgn (GDI.130)
502 INT16 WINAPI RestoreVisRgn( HDC16 hdc )
504 HRGN32 saved;
505 RGNOBJ *obj, *savedObj;
506 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
507 INT16 ret;
509 if (!dc) return ERROR;
510 if (!dc->w.hVisRgn)
512 GDI_HEAP_UNLOCK( hdc );
513 return ERROR;
515 TRACE(clipping, "%04x\n", hdc );
516 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
518 GDI_HEAP_UNLOCK( hdc );
519 return ERROR;
521 if (!(saved = obj->header.hNext))
523 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
524 GDI_HEAP_UNLOCK( hdc );
525 return ERROR;
527 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
529 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
530 GDI_HEAP_UNLOCK( hdc );
531 return ERROR;
533 DeleteObject32( dc->w.hVisRgn );
534 dc->w.hVisRgn = saved;
535 CLIPPING_UpdateGCRegion( dc );
536 GDI_HEAP_UNLOCK( hdc );
537 ret = savedObj->rgn->type; /* FIXME */
538 GDI_HEAP_UNLOCK( saved );
539 return ret;