2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
12 /* #define DEBUG_CLIPPING */
15 #define UpdateDirtyDC(dc) DC_CallHookProc( dc, DCHC_INVALIDVISRGN, 0 )
17 /***********************************************************************
18 * CLIPPING_SetDeviceClipping
20 * Set the clip region of the physical device.
22 static void CLIPPING_SetDeviceClipping( DC * dc )
24 RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
27 fprintf( stderr, "SetDeviceClipping: Rgn is 0. Please report this.\n");
32 XSetRegion( display, dc->u.x.gc, obj->xrgn );
33 XSetClipOrigin( display, dc->u.x.gc, dc->w.DCOrgX, dc->w.DCOrgY );
35 else /* Clip everything */
37 XSetClipRectangles( display, dc->u.x.gc, 0, 0, NULL, 0, 0 );
42 /***********************************************************************
43 * CLIPPING_UpdateGCRegion
45 * Update the GC clip region when the ClipRgn or VisRgn have changed.
47 void CLIPPING_UpdateGCRegion( DC * dc )
49 if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
53 fprintf( stderr, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
57 if (dc->w.flags & DC_DIRTY)
60 dc->w.flags &= ~DC_DIRTY;
64 CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
66 CombineRgn( dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND );
67 CLIPPING_SetDeviceClipping( dc );
71 /***********************************************************************
72 * SelectClipRgn (GDI.44)
74 int SelectClipRgn( HDC hdc, HRGN hrgn )
77 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
78 if (!dc) return ERROR;
80 dprintf_clipping(stddeb, "SelectClipRgn: %04x %04x\n", hdc, hrgn );
84 if (!dc->w.hClipRgn) dc->w.hClipRgn = CreateRectRgn(0,0,0,0);
85 retval = CombineRgn( dc->w.hClipRgn, hrgn, 0, RGN_COPY );
89 if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
91 retval = SIMPLEREGION; /* Clip region == whole DC */
94 CLIPPING_UpdateGCRegion( dc );
99 /***********************************************************************
100 * SelectVisRgn (GDI.105)
102 int SelectVisRgn( HDC hdc, HRGN hrgn )
105 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
106 if (!dc || !hrgn) return ERROR;
108 dprintf_clipping(stddeb, "SelectVisRgn: %04x %04x\n", hdc, hrgn );
110 dc->w.flags &= ~DC_DIRTY;
112 retval = CombineRgn( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
113 CLIPPING_UpdateGCRegion( dc );
118 /***********************************************************************
119 * OffsetClipRgn (GDI.32)
121 int OffsetClipRgn( HDC hdc, short x, short y )
123 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
126 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
127 if (!dc) return ERROR;
128 MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
129 return NULLREGION; /* ?? */
132 dprintf_clipping(stddeb, "OffsetClipRgn: %04x %d,%d\n", hdc, x, y );
136 int retval = OffsetRgn( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y) );
137 CLIPPING_UpdateGCRegion( dc );
140 else return SIMPLEREGION; /* Clip region == client area */
144 /***********************************************************************
145 * OffsetVisRgn (GDI.102)
147 int OffsetVisRgn( HDC hdc, short x, short y )
150 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
151 if (!dc) return ERROR;
152 dprintf_clipping(stddeb, "OffsetVisRgn: %04x %d,%d\n", hdc, x, y );
153 retval = OffsetRgn( dc->w.hVisRgn, x, y );
154 CLIPPING_UpdateGCRegion( dc );
159 /***********************************************************************
160 * CLIPPING_IntersectClipRect
162 * Helper function for {Intersect,Exclude}ClipRect, can be called from
163 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
164 * coordinate conversion.
166 int CLIPPING_IntersectClipRect( DC * dc, short left, short top,
167 short right, short bottom, UINT16 flags)
172 if ( !(newRgn = CreateRectRgn( left, top, right, bottom )) ) return ERROR;
173 if ( !dc->w.hClipRgn )
175 if( flags & CLIP_INTERSECT )
177 dc->w.hClipRgn = newRgn;
178 CLIPPING_UpdateGCRegion( dc );
183 ret = CombineRgn( newRgn, dc->w.hClipRgn, newRgn,
184 (flags & CLIP_EXCLUDE)? RGN_DIFF : RGN_AND);
187 if ( !(flags & CLIP_KEEPRGN) ) DeleteObject( dc->w.hClipRgn );
188 dc->w.hClipRgn = newRgn;
189 CLIPPING_UpdateGCRegion( dc );
191 else DeleteObject( newRgn );
196 /***********************************************************************
197 * ExcludeClipRect (GDI.21)
199 int ExcludeClipRect( HDC hdc, short left, short top,
200 short right, short bottom )
202 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
205 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
206 if (!dc) return ERROR;
207 MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
208 return NULLREGION; /* ?? */
211 left = XLPTODP( dc, left );
212 right = XLPTODP( dc, right );
213 top = YLPTODP( dc, top );
214 bottom = YLPTODP( dc, bottom );
216 dprintf_clipping(stddeb, "ExcludeClipRect: %04x %dx%d,%dx%d\n",
217 hdc, left, top, right, bottom );
218 return CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
222 /***********************************************************************
223 * IntersectClipRect (GDI.22)
225 int IntersectClipRect( HDC hdc, short left, short top,
226 short right, short bottom )
228 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
231 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
232 if (!dc) return ERROR;
233 MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
234 return NULLREGION; /* ?? */
237 left = XLPTODP( dc, left );
238 right = XLPTODP( dc, right );
239 top = YLPTODP( dc, top );
240 bottom = YLPTODP( dc, bottom );
242 dprintf_clipping(stddeb, "IntersectClipRect: %04x %dx%d,%dx%d\n",
243 hdc, left, top, right, bottom );
244 return CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
248 /***********************************************************************
249 * CLIPPING_IntersectVisRect
251 * Helper function for {Intersect,Exclude}VisRect
253 static int CLIPPING_IntersectVisRect( DC * dc, short left, short top,
254 short right, short bottom, BOOL exclude )
256 HRGN tempRgn, newRgn;
259 left = XLPTODP( dc, left );
260 right = XLPTODP( dc, right );
261 top = YLPTODP( dc, top );
262 bottom = YLPTODP( dc, bottom );
264 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
265 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
267 DeleteObject( newRgn );
270 ret = CombineRgn( newRgn, dc->w.hVisRgn, tempRgn,
271 exclude ? RGN_DIFF : RGN_AND);
272 DeleteObject( tempRgn );
276 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
277 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
278 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
279 DeleteObject( dc->w.hVisRgn );
280 dc->w.hVisRgn = newRgn;
281 CLIPPING_UpdateGCRegion( dc );
283 else DeleteObject( newRgn );
288 /***********************************************************************
289 * ExcludeVisRect (GDI.73)
291 int ExcludeVisRect( HDC hdc, short left, short top, short right, short bottom )
293 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
294 if (!dc) return ERROR;
295 dprintf_clipping(stddeb, "ExcludeVisRect: %04x %dx%d,%dx%d\n",
296 hdc, left, top, right, bottom );
298 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
302 /***********************************************************************
303 * IntersectVisRect (GDI.98)
305 int IntersectVisRect( HDC hdc, short left, short top,
306 short right, short bottom )
308 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
309 if (!dc) return ERROR;
310 dprintf_clipping(stddeb, "IntersectVisRect: %04x %dx%d,%dx%d\n",
311 hdc, left, top, right, bottom );
313 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
317 /***********************************************************************
318 * PtVisible (GDI.103)
320 BOOL PtVisible( HDC hdc, short x, short y )
322 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
323 if (!dc) return ERROR;
325 dprintf_clipping(stddeb, "PtVisible: %04x %d,%d\n", hdc, x, y );
326 if (!dc->w.hGCClipRgn) return FALSE;
328 if( dc->w.flags & DC_DIRTY ) UpdateDirtyDC(dc);
329 dc->w.flags &= ~DC_DIRTY;
331 return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x), YLPTODP(dc,y) );
335 /***********************************************************************
336 * RectVisible16 (GDI.104)
338 BOOL16 RectVisible16( HDC16 hdc, LPRECT16 rect )
341 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
342 if (!dc) return FALSE;
343 dprintf_clipping(stddeb,"RectVisible: %04x %d,%dx%d,%d\n",
344 hdc, rect->left, rect->top, rect->right, rect->bottom );
345 if (!dc->w.hGCClipRgn) return FALSE;
346 /* copy rectangle to avoid overwriting by LPtoDP */
348 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
349 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
353 /***********************************************************************
354 * RectVisible32 (GDI32.282)
356 BOOL32 RectVisible32( HDC32 hdc, LPRECT32 rect )
359 CONV_RECT32TO16( rect, &rect16 );
360 return RectVisible16( (HDC16)hdc, &rect16 );
364 /***********************************************************************
365 * GetClipBox16 (GDI.77)
367 INT16 GetClipBox16( HDC16 hdc, LPRECT16 rect )
370 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
371 if (!dc) return ERROR;
372 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
373 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
378 /***********************************************************************
379 * GetClipBox32 (GDI32.162)
381 INT32 GetClipBox32( HDC32 hdc, LPRECT32 rect )
384 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
385 if (!dc) return ERROR;
386 ret = GetRgnBox32( dc->w.hGCClipRgn, rect );
387 DPtoLP32( hdc, (LPPOINT32)rect, 2 );
392 /***********************************************************************
393 * SaveVisRgn (GDI.129)
395 HRGN SaveVisRgn( HDC hdc )
398 RGNOBJ *obj, *copyObj;
399 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
401 dprintf_clipping(stddeb, "SaveVisRgn: %04x\n", hdc );
404 fprintf( stderr, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
407 if( dc->w.flags & DC_DIRTY ) UpdateDirtyDC(dc);
408 dc->w.flags &= ~DC_DIRTY;
410 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
412 if (!(copy = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
413 CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
414 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
416 copyObj->header.hNext = obj->header.hNext;
417 obj->header.hNext = copy;
422 /***********************************************************************
423 * RestoreVisRgn (GDI.130)
425 int RestoreVisRgn( HDC hdc )
428 RGNOBJ *obj, *savedObj;
429 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
430 if (!dc || !dc->w.hVisRgn) return ERROR;
431 dprintf_clipping(stddeb, "RestoreVisRgn: %04x\n", hdc );
432 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
434 if (!(saved = obj->header.hNext)) return ERROR;
435 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
437 DeleteObject( dc->w.hVisRgn );
438 dc->w.hVisRgn = saved;
439 CLIPPING_UpdateGCRegion( dc );
440 return savedObj->xrgn ? COMPLEXREGION : NULLREGION;