Release 961222
[wine/multimedia.git] / objects / clipping.c
blob7ca30a911fdff5cb1c633521a15bd45b141a9b8c
1 /*
2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
8 #include <stdio.h>
9 #include "dc.h"
10 #include "metafile.h"
11 #include "region.h"
12 #include "stddebug.h"
13 #include "debug.h"
15 #define UPDATE_DIRTY_DC(dc) \
16 do { \
17 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
18 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
19 } while(0)
23 /***********************************************************************
24 * CLIPPING_UpdateGCRegion
26 * Update the GC clip region when the ClipRgn or VisRgn have changed.
28 void CLIPPING_UpdateGCRegion( DC * dc )
30 if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn32( 0, 0, 0, 0 );
32 if (!dc->w.hVisRgn)
34 fprintf( stderr, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
35 exit(1);
38 if (dc->w.flags & DC_DIRTY)
40 UPDATE_DIRTY_DC(dc);
41 dc->w.flags &= ~DC_DIRTY;
44 if (!dc->w.hClipRgn)
45 CombineRgn32( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
46 else
47 CombineRgn32(dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND);
48 if (dc->funcs->pSetDeviceClipping) dc->funcs->pSetDeviceClipping( dc );
52 /***********************************************************************
53 * SelectClipRgn16 (GDI.44)
55 INT16 SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
57 return (INT16)SelectClipRgn32( hdc, hrgn );
61 /***********************************************************************
62 * SelectClipRgn32 (GDI32.297)
64 INT32 SelectClipRgn32( HDC32 hdc, HRGN32 hrgn )
66 INT32 retval;
67 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
68 if (!dc) return ERROR;
70 dprintf_clipping(stddeb, "SelectClipRgn: %04x %04x\n", hdc, hrgn );
72 if (hrgn)
74 if (!dc->w.hClipRgn) dc->w.hClipRgn = CreateRectRgn32(0,0,0,0);
75 retval = CombineRgn32( dc->w.hClipRgn, hrgn, 0, RGN_COPY );
77 else
79 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
80 dc->w.hClipRgn = 0;
81 retval = SIMPLEREGION; /* Clip region == whole DC */
84 CLIPPING_UpdateGCRegion( dc );
85 return retval;
89 /***********************************************************************
90 * SelectVisRgn (GDI.105)
92 INT16 SelectVisRgn( HDC16 hdc, HRGN16 hrgn )
94 int retval;
95 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
96 if (!dc || !hrgn) return ERROR;
98 dprintf_clipping(stddeb, "SelectVisRgn: %04x %04x\n", hdc, hrgn );
100 dc->w.flags &= ~DC_DIRTY;
102 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
103 CLIPPING_UpdateGCRegion( dc );
104 return retval;
108 /***********************************************************************
109 * OffsetClipRgn16 (GDI.32)
111 INT16 OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
113 return (INT16)OffsetClipRgn32( hdc, x, y );
117 /***********************************************************************
118 * OffsetClipRgn32 (GDI32.255)
120 INT32 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 return NULLREGION; /* ?? */
131 dprintf_clipping(stddeb, "OffsetClipRgn: %04x %d,%d\n", hdc, x, y );
133 if (dc->w.hClipRgn)
135 INT32 ret = OffsetRgn32( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
136 CLIPPING_UpdateGCRegion( dc );
137 return ret;
139 else return SIMPLEREGION; /* Clip region == client area */
143 /***********************************************************************
144 * OffsetVisRgn (GDI.102)
146 INT16 OffsetVisRgn( HDC16 hdc, INT16 x, INT16 y )
148 INT16 retval;
149 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
150 if (!dc) return ERROR;
151 dprintf_clipping(stddeb, "OffsetVisRgn: %04x %d,%d\n", hdc, x, y );
152 retval = OffsetRgn32( dc->w.hVisRgn, x, y );
153 CLIPPING_UpdateGCRegion( dc );
154 return retval;
158 /***********************************************************************
159 * CLIPPING_IntersectClipRect
161 * Helper function for {Intersect,Exclude}ClipRect, can be called from
162 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
163 * coordinate conversion.
165 INT32 CLIPPING_IntersectClipRect( DC * dc, INT32 left, INT32 top,
166 INT32 right, INT32 bottom, UINT32 flags )
168 HRGN32 newRgn;
169 INT32 ret;
171 if (!(newRgn = CreateRectRgn32( left, top, right, bottom ))) return ERROR;
172 if (!dc->w.hClipRgn)
174 if( flags & CLIP_INTERSECT )
176 dc->w.hClipRgn = newRgn;
177 CLIPPING_UpdateGCRegion( dc );
179 return SIMPLEREGION;
182 ret = CombineRgn32( newRgn, dc->w.hClipRgn, newRgn,
183 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
184 if (ret != ERROR)
186 if (!(flags & CLIP_KEEPRGN)) DeleteObject32( dc->w.hClipRgn );
187 dc->w.hClipRgn = newRgn;
188 CLIPPING_UpdateGCRegion( dc );
190 else DeleteObject32( newRgn );
191 return ret;
195 /***********************************************************************
196 * ExcludeClipRect16 (GDI.21)
198 INT16 ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
199 INT16 right, INT16 bottom )
201 return (INT16)ExcludeClipRect32( hdc, left, top, right, bottom );
205 /***********************************************************************
206 * ExcludeClipRect32 (GDI32.92)
208 INT32 ExcludeClipRect32( HDC32 hdc, INT32 left, INT32 top,
209 INT32 right, INT32 bottom )
211 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
212 if (!dc)
214 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
215 if (!dc) return ERROR;
216 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
217 return NULLREGION; /* ?? */
220 left = XLPTODP( dc, left );
221 right = XLPTODP( dc, right );
222 top = YLPTODP( dc, top );
223 bottom = YLPTODP( dc, bottom );
225 dprintf_clipping(stddeb, "ExcludeClipRect: %04x %dx%d,%dx%d\n",
226 hdc, left, top, right, bottom );
227 return CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
231 /***********************************************************************
232 * IntersectClipRect16 (GDI.22)
234 INT16 IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
235 INT16 right, INT16 bottom )
237 return (INT16)IntersectClipRect32( hdc, left, top, right, bottom );
241 /***********************************************************************
242 * IntersectClipRect32 (GDI32.245)
244 INT32 IntersectClipRect32( HDC32 hdc, INT32 left, INT32 top,
245 INT32 right, INT32 bottom )
247 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
248 if (!dc)
250 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
251 if (!dc) return ERROR;
252 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
253 return NULLREGION; /* ?? */
256 left = XLPTODP( dc, left );
257 right = XLPTODP( dc, right );
258 top = YLPTODP( dc, top );
259 bottom = YLPTODP( dc, bottom );
261 dprintf_clipping(stddeb, "IntersectClipRect: %04x %dx%d,%dx%d\n",
262 hdc, left, top, right, bottom );
263 return CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
267 /***********************************************************************
268 * CLIPPING_IntersectVisRect
270 * Helper function for {Intersect,Exclude}VisRect
272 static INT32 CLIPPING_IntersectVisRect( DC * dc, INT32 left, INT32 top,
273 INT32 right, INT32 bottom,
274 BOOL32 exclude )
276 HRGN32 tempRgn, newRgn;
277 INT32 ret;
279 left = XLPTODP( dc, left );
280 right = XLPTODP( dc, right );
281 top = YLPTODP( dc, top );
282 bottom = YLPTODP( dc, bottom );
284 if (!(newRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR;
285 if (!(tempRgn = CreateRectRgn32( left, top, right, bottom )))
287 DeleteObject32( newRgn );
288 return ERROR;
290 ret = CombineRgn32( newRgn, dc->w.hVisRgn, tempRgn,
291 exclude ? RGN_DIFF : RGN_AND );
292 DeleteObject32( tempRgn );
294 if (ret != ERROR)
296 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
297 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
298 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
299 DeleteObject32( dc->w.hVisRgn );
300 dc->w.hVisRgn = newRgn;
301 CLIPPING_UpdateGCRegion( dc );
303 else DeleteObject32( newRgn );
304 return ret;
308 /***********************************************************************
309 * ExcludeVisRect (GDI.73)
311 INT16 ExcludeVisRect( HDC16 hdc, INT16 left, INT16 top,
312 INT16 right, INT16 bottom )
314 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
315 if (!dc) return ERROR;
316 dprintf_clipping(stddeb, "ExcludeVisRect: %04x %dx%d,%dx%d\n",
317 hdc, left, top, right, bottom );
319 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
323 /***********************************************************************
324 * IntersectVisRect (GDI.98)
326 INT16 IntersectVisRect( HDC16 hdc, INT16 left, INT16 top,
327 INT16 right, INT16 bottom )
329 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
330 if (!dc) return ERROR;
331 dprintf_clipping(stddeb, "IntersectVisRect: %04x %dx%d,%dx%d\n",
332 hdc, left, top, right, bottom );
334 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
338 /***********************************************************************
339 * PtVisible16 (GDI.103)
341 BOOL16 PtVisible16( HDC16 hdc, INT16 x, INT16 y )
343 return PtVisible32( hdc, x, y );
347 /***********************************************************************
348 * PtVisible32 (GDI32.279)
350 BOOL32 PtVisible32( HDC32 hdc, INT32 x, INT32 y )
352 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
353 if (!dc) return ERROR;
355 dprintf_clipping(stddeb, "PtVisible: %04x %d,%d\n", hdc, x, y );
356 if (!dc->w.hGCClipRgn) return FALSE;
358 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
359 dc->w.flags &= ~DC_DIRTY;
361 return PtInRegion32( dc->w.hGCClipRgn, XLPTODP(dc,x), YLPTODP(dc,y) );
365 /***********************************************************************
366 * RectVisible16 (GDI.104)
368 BOOL16 RectVisible16( HDC16 hdc, LPRECT16 rect )
370 RECT16 tmpRect;
371 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
372 if (!dc) return FALSE;
373 dprintf_clipping(stddeb,"RectVisible: %04x %d,%dx%d,%d\n",
374 hdc, rect->left, rect->top, rect->right, rect->bottom );
375 if (!dc->w.hGCClipRgn) return FALSE;
376 /* copy rectangle to avoid overwriting by LPtoDP */
377 tmpRect = *rect;
378 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
379 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
383 /***********************************************************************
384 * RectVisible32 (GDI32.282)
386 BOOL32 RectVisible32( HDC32 hdc, LPRECT32 rect )
388 RECT16 rect16;
389 CONV_RECT32TO16( rect, &rect16 );
390 return RectVisible16( (HDC16)hdc, &rect16 );
394 /***********************************************************************
395 * GetClipBox16 (GDI.77)
397 INT16 GetClipBox16( HDC16 hdc, LPRECT16 rect )
399 int ret;
400 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
401 if (!dc) return ERROR;
402 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
403 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
404 return ret;
408 /***********************************************************************
409 * GetClipBox32 (GDI32.162)
411 INT32 GetClipBox32( HDC32 hdc, LPRECT32 rect )
413 INT32 ret;
414 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
415 if (!dc) return ERROR;
416 ret = GetRgnBox32( dc->w.hGCClipRgn, rect );
417 DPtoLP32( hdc, (LPPOINT32)rect, 2 );
418 return ret;
422 /***********************************************************************
423 * GetClipRgn32 (GDI32.163)
425 INT32 GetClipRgn32( HDC32 hdc, HRGN32 hRgn )
427 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
428 if( dc && hRgn )
429 if( dc->w.hClipRgn )
431 /* this assumes that dc->w.hClipRgn is in coordinates
432 relative to the DC origin (not device) */
434 if( CombineRgn32(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
435 return 1;
437 else return 0;
438 return -1;
441 /***********************************************************************
442 * SaveVisRgn (GDI.129)
444 HRGN16 SaveVisRgn( HDC16 hdc )
446 HRGN32 copy;
447 RGNOBJ *obj, *copyObj;
448 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
449 if (!dc) return 0;
450 dprintf_clipping(stddeb, "SaveVisRgn: %04x\n", hdc );
451 if (!dc->w.hVisRgn)
453 fprintf( stderr, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
454 exit(1);
456 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
457 dc->w.flags &= ~DC_DIRTY;
459 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
460 return 0;
461 if (!(copy = CreateRectRgn32( 0, 0, 0, 0 ))) return 0;
462 CombineRgn32( copy, dc->w.hVisRgn, 0, RGN_COPY );
463 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
464 return 0;
465 copyObj->header.hNext = obj->header.hNext;
466 obj->header.hNext = copy;
467 return copy;
471 /***********************************************************************
472 * RestoreVisRgn (GDI.130)
474 INT16 RestoreVisRgn( HDC16 hdc )
476 HRGN32 saved;
477 RGNOBJ *obj, *savedObj;
478 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
479 if (!dc || !dc->w.hVisRgn) return ERROR;
480 dprintf_clipping(stddeb, "RestoreVisRgn: %04x\n", hdc );
481 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
482 return ERROR;
483 if (!(saved = obj->header.hNext)) return ERROR;
484 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
485 return ERROR;
486 DeleteObject32( dc->w.hVisRgn );
487 dc->w.hVisRgn = saved;
488 CLIPPING_UpdateGCRegion( dc );
489 return savedObj->xrgn ? COMPLEXREGION : NULLREGION;