Release 970914
[wine.git] / objects / clipping.c
blobd417c71e4af9b9ac6203e5cf9825e0f50b51e19d
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 "stddebug.h"
12 #include "debug.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 = CreateRectRgn32( 0, 0, 0, 0 );
31 if (!dc->w.hVisRgn)
33 fprintf( stderr, "UpdateGCRegion: 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 CombineRgn32( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
45 else
46 CombineRgn32(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)SelectClipRgn32( hdc, hrgn );
60 /***********************************************************************
61 * SelectClipRgn32 (GDI32.297)
63 INT32 WINAPI SelectClipRgn32( HDC32 hdc, HRGN32 hrgn )
65 INT32 retval;
66 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
67 if (!dc) return ERROR;
69 dprintf_clipping(stddeb, "SelectClipRgn: %04x %04x\n", hdc, hrgn );
71 if (hrgn)
73 if (!dc->w.hClipRgn) dc->w.hClipRgn = CreateRectRgn32(0,0,0,0);
74 retval = CombineRgn32( dc->w.hClipRgn, hrgn, 0, RGN_COPY );
76 else
78 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
79 dc->w.hClipRgn = 0;
80 retval = SIMPLEREGION; /* Clip region == whole DC */
83 CLIPPING_UpdateGCRegion( dc );
84 GDI_HEAP_UNLOCK( hdc );
85 return retval;
89 /***********************************************************************
90 * SelectVisRgn (GDI.105)
92 INT16 WINAPI 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 GDI_HEAP_UNLOCK( hdc );
105 return retval;
109 /***********************************************************************
110 * OffsetClipRgn16 (GDI.32)
112 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
114 return (INT16)OffsetClipRgn32( hdc, x, y );
118 /***********************************************************************
119 * OffsetClipRgn32 (GDI32.255)
121 INT32 WINAPI OffsetClipRgn32( HDC32 hdc, INT32 x, INT32 y )
123 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
124 if (!dc)
126 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
127 if (!dc) return ERROR;
128 MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
129 GDI_HEAP_UNLOCK( hdc );
130 return NULLREGION; /* ?? */
133 dprintf_clipping(stddeb, "OffsetClipRgn: %04x %d,%d\n", hdc, x, y );
135 if (dc->w.hClipRgn)
137 INT32 ret = OffsetRgn32( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
138 CLIPPING_UpdateGCRegion( dc );
139 GDI_HEAP_UNLOCK( hdc );
140 return ret;
142 GDI_HEAP_UNLOCK( hdc );
143 return SIMPLEREGION; /* Clip region == client area */
147 /***********************************************************************
148 * OffsetVisRgn (GDI.102)
150 INT16 WINAPI OffsetVisRgn( HDC16 hdc, INT16 x, INT16 y )
152 INT16 retval;
153 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
154 if (!dc) return ERROR;
155 dprintf_clipping(stddeb, "OffsetVisRgn: %04x %d,%d\n", hdc, x, y );
156 retval = OffsetRgn32( dc->w.hVisRgn, x, y );
157 CLIPPING_UpdateGCRegion( dc );
158 GDI_HEAP_UNLOCK( hdc );
159 return retval;
163 /***********************************************************************
164 * CLIPPING_IntersectClipRect
166 * Helper function for {Intersect,Exclude}ClipRect, can be called from
167 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
168 * coordinate conversion.
170 INT32 CLIPPING_IntersectClipRect( DC * dc, INT32 left, INT32 top,
171 INT32 right, INT32 bottom, UINT32 flags )
173 HRGN32 newRgn;
174 INT32 ret;
176 if (!(newRgn = CreateRectRgn32( left, top, right, bottom ))) return ERROR;
177 if (!dc->w.hClipRgn)
179 if( flags & CLIP_INTERSECT )
181 dc->w.hClipRgn = newRgn;
182 CLIPPING_UpdateGCRegion( dc );
184 return SIMPLEREGION;
187 ret = CombineRgn32( newRgn, dc->w.hClipRgn, newRgn,
188 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
189 if (ret != ERROR)
191 if (!(flags & CLIP_KEEPRGN)) DeleteObject32( dc->w.hClipRgn );
192 dc->w.hClipRgn = newRgn;
193 CLIPPING_UpdateGCRegion( dc );
195 else DeleteObject32( newRgn );
196 return ret;
200 /***********************************************************************
201 * ExcludeClipRect16 (GDI.21)
203 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
204 INT16 right, INT16 bottom )
206 return (INT16)ExcludeClipRect32( hdc, left, top, right, bottom );
210 /***********************************************************************
211 * ExcludeClipRect32 (GDI32.92)
213 INT32 WINAPI ExcludeClipRect32( HDC32 hdc, INT32 left, INT32 top,
214 INT32 right, INT32 bottom )
216 INT32 ret;
217 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
218 if (!dc)
220 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
221 if (!dc) return ERROR;
222 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
223 GDI_HEAP_UNLOCK( hdc );
224 return NULLREGION; /* ?? */
227 left = XLPTODP( dc, left );
228 right = XLPTODP( dc, right );
229 top = YLPTODP( dc, top );
230 bottom = YLPTODP( dc, bottom );
232 dprintf_clipping(stddeb, "ExcludeClipRect: %04x %dx%d,%dx%d\n",
233 hdc, left, top, right, bottom );
234 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
235 GDI_HEAP_UNLOCK( hdc );
236 return ret;
240 /***********************************************************************
241 * IntersectClipRect16 (GDI.22)
243 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
244 INT16 right, INT16 bottom )
246 return (INT16)IntersectClipRect32( hdc, left, top, right, bottom );
250 /***********************************************************************
251 * IntersectClipRect32 (GDI32.245)
253 INT32 WINAPI IntersectClipRect32( HDC32 hdc, INT32 left, INT32 top,
254 INT32 right, INT32 bottom )
256 INT32 ret;
257 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
258 if (!dc)
260 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
261 if (!dc) return ERROR;
262 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
263 GDI_HEAP_UNLOCK( hdc );
264 return NULLREGION; /* ?? */
267 left = XLPTODP( dc, left );
268 right = XLPTODP( dc, right );
269 top = YLPTODP( dc, top );
270 bottom = YLPTODP( dc, bottom );
272 dprintf_clipping(stddeb, "IntersectClipRect: %04x %dx%d,%dx%d\n",
273 hdc, left, top, right, bottom );
274 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
275 GDI_HEAP_UNLOCK( hdc );
276 return ret;
280 /***********************************************************************
281 * CLIPPING_IntersectVisRect
283 * Helper function for {Intersect,Exclude}VisRect
285 static INT32 CLIPPING_IntersectVisRect( DC * dc, INT32 left, INT32 top,
286 INT32 right, INT32 bottom,
287 BOOL32 exclude )
289 HRGN32 tempRgn, newRgn;
290 INT32 ret;
292 left = XLPTODP( dc, left );
293 right = XLPTODP( dc, right );
294 top = YLPTODP( dc, top );
295 bottom = YLPTODP( dc, bottom );
297 if (!(newRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR;
298 if (!(tempRgn = CreateRectRgn32( left, top, right, bottom )))
300 DeleteObject32( newRgn );
301 return ERROR;
303 ret = CombineRgn32( newRgn, dc->w.hVisRgn, tempRgn,
304 exclude ? RGN_DIFF : RGN_AND );
305 DeleteObject32( tempRgn );
307 if (ret != ERROR)
309 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
310 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
311 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
312 DeleteObject32( dc->w.hVisRgn );
313 dc->w.hVisRgn = newRgn;
314 CLIPPING_UpdateGCRegion( dc );
315 GDI_HEAP_UNLOCK( newRgn );
317 else DeleteObject32( newRgn );
318 return ret;
322 /***********************************************************************
323 * ExcludeVisRect (GDI.73)
325 INT16 WINAPI ExcludeVisRect( HDC16 hdc, INT16 left, INT16 top,
326 INT16 right, INT16 bottom )
328 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
329 if (!dc) return ERROR;
330 dprintf_clipping(stddeb, "ExcludeVisRect: %04x %dx%d,%dx%d\n",
331 hdc, left, top, right, bottom );
333 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
337 /***********************************************************************
338 * IntersectVisRect (GDI.98)
340 INT16 WINAPI IntersectVisRect( HDC16 hdc, INT16 left, INT16 top,
341 INT16 right, INT16 bottom )
343 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
344 if (!dc) return ERROR;
345 dprintf_clipping(stddeb, "IntersectVisRect: %04x %dx%d,%dx%d\n",
346 hdc, left, top, right, bottom );
348 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
352 /***********************************************************************
353 * PtVisible16 (GDI.103)
355 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
357 return PtVisible32( hdc, x, y );
361 /***********************************************************************
362 * PtVisible32 (GDI32.279)
364 BOOL32 WINAPI PtVisible32( HDC32 hdc, INT32 x, INT32 y )
366 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
367 if (!dc) return ERROR;
369 dprintf_clipping(stddeb, "PtVisible: %04x %d,%d\n", hdc, x, y );
370 if (!dc->w.hGCClipRgn) return FALSE;
372 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
373 dc->w.flags &= ~DC_DIRTY;
375 return PtInRegion32( dc->w.hGCClipRgn, XLPTODP(dc,x), YLPTODP(dc,y) );
379 /***********************************************************************
380 * RectVisible16 (GDI.104)
382 BOOL16 WINAPI RectVisible16( HDC16 hdc, LPRECT16 rect )
384 RECT16 tmpRect;
385 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
386 if (!dc) return FALSE;
387 dprintf_clipping(stddeb,"RectVisible: %04x %d,%dx%d,%d\n",
388 hdc, rect->left, rect->top, rect->right, rect->bottom );
389 if (!dc->w.hGCClipRgn) return FALSE;
390 /* copy rectangle to avoid overwriting by LPtoDP */
391 tmpRect = *rect;
392 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
393 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
397 /***********************************************************************
398 * RectVisible32 (GDI32.282)
400 BOOL32 WINAPI RectVisible32( HDC32 hdc, LPRECT32 rect )
402 RECT16 rect16;
403 CONV_RECT32TO16( rect, &rect16 );
404 return RectVisible16( (HDC16)hdc, &rect16 );
408 /***********************************************************************
409 * GetClipBox16 (GDI.77)
411 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
413 int ret;
414 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
415 if (!dc) return ERROR;
416 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
417 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
418 return ret;
422 /***********************************************************************
423 * GetClipBox32 (GDI32.162)
425 INT32 WINAPI GetClipBox32( HDC32 hdc, LPRECT32 rect )
427 INT32 ret;
428 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
429 if (!dc) return ERROR;
430 ret = GetRgnBox32( dc->w.hGCClipRgn, rect );
431 DPtoLP32( hdc, (LPPOINT32)rect, 2 );
432 return ret;
436 /***********************************************************************
437 * GetClipRgn32 (GDI32.163)
439 INT32 WINAPI GetClipRgn32( HDC32 hdc, HRGN32 hRgn )
441 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
442 if( dc && hRgn )
443 if( dc->w.hClipRgn )
445 /* this assumes that dc->w.hClipRgn is in coordinates
446 relative to the DC origin (not device) */
448 if( CombineRgn32(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
449 return 1;
451 else return 0;
452 return -1;
455 /***********************************************************************
456 * SaveVisRgn (GDI.129)
458 HRGN16 WINAPI SaveVisRgn( HDC16 hdc )
460 HRGN32 copy;
461 RGNOBJ *obj, *copyObj;
462 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
463 if (!dc) return 0;
464 dprintf_clipping(stddeb, "SaveVisRgn: %04x\n", hdc );
465 if (!dc->w.hVisRgn)
467 fprintf( stderr, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
468 exit(1);
470 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
471 dc->w.flags &= ~DC_DIRTY;
473 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
475 GDI_HEAP_UNLOCK( hdc );
476 return 0;
478 if (!(copy = CreateRectRgn32( 0, 0, 0, 0 )))
480 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
481 GDI_HEAP_UNLOCK( hdc );
482 return 0;
484 CombineRgn32( copy, dc->w.hVisRgn, 0, RGN_COPY );
485 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
487 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
488 GDI_HEAP_UNLOCK( hdc );
489 return 0;
491 copyObj->header.hNext = obj->header.hNext;
492 obj->header.hNext = copy;
493 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
494 GDI_HEAP_UNLOCK( hdc );
495 GDI_HEAP_UNLOCK( copy );
496 return copy;
500 /***********************************************************************
501 * RestoreVisRgn (GDI.130)
503 INT16 WINAPI RestoreVisRgn( HDC16 hdc )
505 HRGN32 saved;
506 RGNOBJ *obj, *savedObj;
507 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
508 if (!dc) return ERROR;
509 if (!dc->w.hVisRgn)
511 GDI_HEAP_UNLOCK( hdc );
512 return ERROR;
514 dprintf_clipping(stddeb, "RestoreVisRgn: %04x\n", hdc );
515 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
517 GDI_HEAP_UNLOCK( hdc );
518 return ERROR;
520 if (!(saved = obj->header.hNext))
522 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
523 GDI_HEAP_UNLOCK( hdc );
524 return ERROR;
526 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
528 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
529 GDI_HEAP_UNLOCK( hdc );
530 return ERROR;
532 DeleteObject32( dc->w.hVisRgn );
533 dc->w.hVisRgn = saved;
534 CLIPPING_UpdateGCRegion( dc );
535 GDI_HEAP_UNLOCK( hdc );
536 GDI_HEAP_UNLOCK( saved );
537 return savedObj->xrgn ? COMPLEXREGION : NULLREGION;