Stub EnumPrintersW.
[wine.git] / objects / clipping.c
blob3f3ad300ddcbac264183e5fef1a6bc93bdcea50f
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 INT32 retval;
64 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
65 if (!dc) return ERROR;
67 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
69 if (hrgn)
71 if (!dc->w.hClipRgn) dc->w.hClipRgn = CreateRectRgn32(0,0,0,0);
72 retval = CombineRgn32( dc->w.hClipRgn, hrgn, 0, RGN_COPY );
74 else
76 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
77 dc->w.hClipRgn = 0;
78 retval = SIMPLEREGION; /* Clip region == whole DC */
81 CLIPPING_UpdateGCRegion( dc );
82 GDI_HEAP_UNLOCK( hdc );
83 return retval;
86 /******************************************************************************
87 * ExtSelectClipRgn [GDI32.97]
89 INT32 WINAPI ExtSelectClipRgn( HDC32 hdc, HRGN32 hrgn, INT32 fnMode )
91 if (fnMode != RGN_COPY)
92 FIXME(clipping, "Unimplemented mode: %d\n", fnMode);
93 return SelectClipRgn32( hdc, hrgn );
96 /***********************************************************************
97 * SelectVisRgn (GDI.105)
99 INT16 WINAPI SelectVisRgn( HDC16 hdc, HRGN16 hrgn )
101 int retval;
102 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
103 if (!dc || !hrgn) return ERROR;
105 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
107 dc->w.flags &= ~DC_DIRTY;
109 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
110 CLIPPING_UpdateGCRegion( dc );
111 GDI_HEAP_UNLOCK( hdc );
112 return retval;
116 /***********************************************************************
117 * OffsetClipRgn16 (GDI.32)
119 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
121 return (INT16)OffsetClipRgn32( hdc, x, y );
125 /***********************************************************************
126 * OffsetClipRgn32 (GDI32.255)
128 INT32 WINAPI OffsetClipRgn32( HDC32 hdc, INT32 x, INT32 y )
130 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
131 if (!dc)
133 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
134 if (!dc) return ERROR;
135 MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
136 GDI_HEAP_UNLOCK( hdc );
137 return NULLREGION; /* ?? */
140 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
142 if (dc->w.hClipRgn)
144 INT32 ret = OffsetRgn32( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
145 CLIPPING_UpdateGCRegion( dc );
146 GDI_HEAP_UNLOCK( hdc );
147 return ret;
149 GDI_HEAP_UNLOCK( hdc );
150 return SIMPLEREGION; /* Clip region == client area */
154 /***********************************************************************
155 * OffsetVisRgn (GDI.102)
157 INT16 WINAPI OffsetVisRgn( HDC16 hdc, INT16 x, INT16 y )
159 INT16 retval;
160 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
161 if (!dc) return ERROR;
162 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
163 retval = OffsetRgn32( dc->w.hVisRgn, x, y );
164 CLIPPING_UpdateGCRegion( dc );
165 GDI_HEAP_UNLOCK( hdc );
166 return retval;
170 /***********************************************************************
171 * CLIPPING_IntersectClipRect
173 * Helper function for {Intersect,Exclude}ClipRect, can be called from
174 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
175 * coordinate conversion.
177 INT32 CLIPPING_IntersectClipRect( DC * dc, INT32 left, INT32 top,
178 INT32 right, INT32 bottom, UINT32 flags )
180 HRGN32 newRgn;
181 INT32 ret;
183 if (!(newRgn = CreateRectRgn32( left, top, right, bottom ))) return ERROR;
184 if (!dc->w.hClipRgn)
186 if( flags & CLIP_INTERSECT )
188 dc->w.hClipRgn = newRgn;
189 CLIPPING_UpdateGCRegion( dc );
190 return SIMPLEREGION;
192 else if( flags & CLIP_EXCLUDE )
194 dc->w.hClipRgn = CreateRectRgn32( 0, 0, 0, 0 );
195 CombineRgn32( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
197 else WARN(clipping,"No hClipRgn and flags are %x\n",flags);
200 ret = CombineRgn32( newRgn, dc->w.hClipRgn, newRgn,
201 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
202 if (ret != ERROR)
204 if (!(flags & CLIP_KEEPRGN)) DeleteObject32( dc->w.hClipRgn );
205 dc->w.hClipRgn = newRgn;
206 CLIPPING_UpdateGCRegion( dc );
208 else DeleteObject32( newRgn );
209 return ret;
213 /***********************************************************************
214 * ExcludeClipRect16 (GDI.21)
216 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
217 INT16 right, INT16 bottom )
219 return (INT16)ExcludeClipRect32( hdc, left, top, right, bottom );
223 /***********************************************************************
224 * ExcludeClipRect32 (GDI32.92)
226 INT32 WINAPI ExcludeClipRect32( HDC32 hdc, INT32 left, INT32 top,
227 INT32 right, INT32 bottom )
229 INT32 ret;
230 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
231 if (!dc)
233 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
234 if (!dc) return ERROR;
235 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
236 GDI_HEAP_UNLOCK( hdc );
237 return NULLREGION; /* ?? */
240 left = XLPTODP( dc, left );
241 right = XLPTODP( dc, right );
242 top = YLPTODP( dc, top );
243 bottom = YLPTODP( dc, bottom );
245 TRACE(clipping, "%04x %dx%d,%dx%d\n",
246 hdc, left, top, right, bottom );
247 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
248 GDI_HEAP_UNLOCK( hdc );
249 return ret;
253 /***********************************************************************
254 * IntersectClipRect16 (GDI.22)
256 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
257 INT16 right, INT16 bottom )
259 return (INT16)IntersectClipRect32( hdc, left, top, right, bottom );
263 /***********************************************************************
264 * IntersectClipRect32 (GDI32.245)
266 INT32 WINAPI IntersectClipRect32( HDC32 hdc, INT32 left, INT32 top,
267 INT32 right, INT32 bottom )
269 INT32 ret;
270 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
271 if (!dc)
273 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
274 if (!dc) return ERROR;
275 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
276 GDI_HEAP_UNLOCK( hdc );
277 return NULLREGION; /* ?? */
280 left = XLPTODP( dc, left );
281 right = XLPTODP( dc, right );
282 top = YLPTODP( dc, top );
283 bottom = YLPTODP( dc, bottom );
285 TRACE(clipping, "%04x %dx%d,%dx%d\n",
286 hdc, left, top, right, bottom );
287 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
288 GDI_HEAP_UNLOCK( hdc );
289 return ret;
293 /***********************************************************************
294 * CLIPPING_IntersectVisRect
296 * Helper function for {Intersect,Exclude}VisRect
298 static INT32 CLIPPING_IntersectVisRect( DC * dc, INT32 left, INT32 top,
299 INT32 right, INT32 bottom,
300 BOOL32 exclude )
302 HRGN32 tempRgn, newRgn;
303 INT32 ret;
305 left = XLPTODP( dc, left );
306 right = XLPTODP( dc, right );
307 top = YLPTODP( dc, top );
308 bottom = YLPTODP( dc, bottom );
310 if (!(newRgn = CreateRectRgn32( 0, 0, 0, 0 ))) return ERROR;
311 if (!(tempRgn = CreateRectRgn32( left, top, right, bottom )))
313 DeleteObject32( newRgn );
314 return ERROR;
316 ret = CombineRgn32( newRgn, dc->w.hVisRgn, tempRgn,
317 exclude ? RGN_DIFF : RGN_AND );
318 DeleteObject32( tempRgn );
320 if (ret != ERROR)
322 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
323 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
324 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
325 DeleteObject32( dc->w.hVisRgn );
326 dc->w.hVisRgn = newRgn;
327 CLIPPING_UpdateGCRegion( dc );
328 GDI_HEAP_UNLOCK( newRgn );
330 else DeleteObject32( newRgn );
331 return ret;
335 /***********************************************************************
336 * ExcludeVisRect (GDI.73)
338 INT16 WINAPI ExcludeVisRect( HDC16 hdc, INT16 left, INT16 top,
339 INT16 right, INT16 bottom )
341 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
342 if (!dc) return ERROR;
343 TRACE(clipping, "%04x %dx%d,%dx%d\n",
344 hdc, left, top, right, bottom );
346 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
350 /***********************************************************************
351 * IntersectVisRect (GDI.98)
353 INT16 WINAPI IntersectVisRect( HDC16 hdc, INT16 left, INT16 top,
354 INT16 right, INT16 bottom )
356 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
357 if (!dc) return ERROR;
358 TRACE(clipping, "%04x %dx%d,%dx%d\n",
359 hdc, left, top, right, bottom );
361 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
365 /***********************************************************************
366 * PtVisible16 (GDI.103)
368 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
370 return PtVisible32( hdc, x, y );
374 /***********************************************************************
375 * PtVisible32 (GDI32.279)
377 BOOL32 WINAPI PtVisible32( HDC32 hdc, INT32 x, INT32 y )
379 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
380 if (!dc) return ERROR;
382 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
383 if (!dc->w.hGCClipRgn) return FALSE;
385 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
386 dc->w.flags &= ~DC_DIRTY;
388 return PtInRegion32( dc->w.hGCClipRgn, XLPTODP(dc,x), YLPTODP(dc,y) );
392 /***********************************************************************
393 * RectVisible16 (GDI.104)
395 BOOL16 WINAPI RectVisible16( HDC16 hdc, LPRECT16 rect )
397 RECT16 tmpRect;
398 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
399 if (!dc) return FALSE;
400 TRACE(clipping,"%04x %d,%dx%d,%d\n",
401 hdc, rect->left, rect->top, rect->right, rect->bottom );
402 if (!dc->w.hGCClipRgn) return FALSE;
403 /* copy rectangle to avoid overwriting by LPtoDP */
404 tmpRect = *rect;
405 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
406 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
410 /***********************************************************************
411 * RectVisible32 (GDI32.282)
413 BOOL32 WINAPI RectVisible32( HDC32 hdc, LPRECT32 rect )
415 RECT16 rect16;
416 CONV_RECT32TO16( rect, &rect16 );
417 return RectVisible16( (HDC16)hdc, &rect16 );
421 /***********************************************************************
422 * GetClipBox16 (GDI.77)
424 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
426 int ret;
427 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
428 if (!dc) return ERROR;
429 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
430 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
431 return ret;
435 /***********************************************************************
436 * GetClipBox32 (GDI32.162)
438 INT32 WINAPI GetClipBox32( HDC32 hdc, LPRECT32 rect )
440 INT32 ret;
441 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
442 if (!dc) return ERROR;
443 ret = GetRgnBox32( dc->w.hGCClipRgn, rect );
444 DPtoLP32( hdc, (LPPOINT32)rect, 2 );
445 return ret;
449 /***********************************************************************
450 * GetClipRgn32 (GDI32.163)
452 INT32 WINAPI GetClipRgn32( HDC32 hdc, HRGN32 hRgn )
454 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
455 if( dc && hRgn )
456 if( dc->w.hClipRgn )
458 /* this assumes that dc->w.hClipRgn is in coordinates
459 relative to the DC origin (not device) */
461 if( CombineRgn32(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
462 return 1;
464 else return 0;
465 return -1;
468 /***********************************************************************
469 * SaveVisRgn (GDI.129)
471 HRGN16 WINAPI SaveVisRgn( HDC16 hdc )
473 HRGN32 copy;
474 RGNOBJ *obj, *copyObj;
475 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
476 if (!dc) return 0;
477 TRACE(clipping, "%04x\n", hdc );
478 if (!dc->w.hVisRgn)
480 ERR(region, "hVisRgn is zero. Please report this.\n" );
481 exit(1);
483 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
484 dc->w.flags &= ~DC_DIRTY;
486 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
488 GDI_HEAP_UNLOCK( hdc );
489 return 0;
491 if (!(copy = CreateRectRgn32( 0, 0, 0, 0 )))
493 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
494 GDI_HEAP_UNLOCK( hdc );
495 return 0;
497 CombineRgn32( copy, dc->w.hVisRgn, 0, RGN_COPY );
498 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
500 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
501 GDI_HEAP_UNLOCK( hdc );
502 return 0;
504 copyObj->header.hNext = obj->header.hNext;
505 obj->header.hNext = copy;
506 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
507 GDI_HEAP_UNLOCK( hdc );
508 GDI_HEAP_UNLOCK( copy );
509 return copy;
513 /***********************************************************************
514 * RestoreVisRgn (GDI.130)
516 INT16 WINAPI RestoreVisRgn( HDC16 hdc )
518 HRGN32 saved;
519 RGNOBJ *obj, *savedObj;
520 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
521 INT16 ret;
523 if (!dc) return ERROR;
524 if (!dc->w.hVisRgn)
526 GDI_HEAP_UNLOCK( hdc );
527 return ERROR;
529 TRACE(clipping, "%04x\n", hdc );
530 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
532 GDI_HEAP_UNLOCK( hdc );
533 return ERROR;
535 if (!(saved = obj->header.hNext))
537 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
538 GDI_HEAP_UNLOCK( hdc );
539 return ERROR;
541 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
543 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
544 GDI_HEAP_UNLOCK( hdc );
545 return ERROR;
547 DeleteObject32( dc->w.hVisRgn );
548 dc->w.hVisRgn = saved;
549 CLIPPING_UpdateGCRegion( dc );
550 GDI_HEAP_UNLOCK( hdc );
551 ret = savedObj->rgn->type; /* FIXME */
552 GDI_HEAP_UNLOCK( saved );
553 return ret;