2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
7 #define NO_TRANSITION_TYPES /* This file is Win32-clean */
15 #define UPDATE_DIRTY_DC(dc) \
17 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
18 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 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 );
34 fprintf( stderr
, "UpdateGCRegion: hVisRgn is zero. Please report this.\n" );
38 if (dc
->w
.flags
& DC_DIRTY
)
41 dc
->w
.flags
&= ~DC_DIRTY
;
45 CombineRgn32( dc
->w
.hGCClipRgn
, dc
->w
.hVisRgn
, 0, RGN_COPY
);
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
)
67 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
68 if (!dc
) return ERROR
;
70 dprintf_clipping(stddeb
, "SelectClipRgn: %04x %04x\n", hdc
, hrgn
);
74 if (!dc
->w
.hClipRgn
) dc
->w
.hClipRgn
= CreateRectRgn32(0,0,0,0);
75 retval
= CombineRgn32( dc
->w
.hClipRgn
, hrgn
, 0, RGN_COPY
);
79 if (dc
->w
.hClipRgn
) DeleteObject16( dc
->w
.hClipRgn
);
81 retval
= SIMPLEREGION
; /* Clip region == whole DC */
84 CLIPPING_UpdateGCRegion( dc
);
89 /***********************************************************************
90 * SelectVisRgn (GDI.105)
92 INT16
SelectVisRgn( HDC16 hdc
, HRGN16 hrgn
)
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
);
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
);
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
);
135 INT32 ret
= OffsetRgn32( dc
->w
.hClipRgn
, XLPTODP(dc
,x
), YLPTODP(dc
,y
));
136 CLIPPING_UpdateGCRegion( dc
);
139 else return SIMPLEREGION
; /* Clip region == client area */
143 /***********************************************************************
144 * OffsetVisRgn (GDI.102)
146 INT16
OffsetVisRgn( HDC16 hdc
, INT16 x
, INT16 y
)
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
);
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
)
171 if (!(newRgn
= CreateRectRgn32( left
, top
, right
, bottom
))) return ERROR
;
174 if( flags
& CLIP_INTERSECT
)
176 dc
->w
.hClipRgn
= newRgn
;
177 CLIPPING_UpdateGCRegion( dc
);
182 ret
= CombineRgn32( newRgn
, dc
->w
.hClipRgn
, newRgn
,
183 (flags
& CLIP_EXCLUDE
) ? RGN_DIFF
: RGN_AND
);
186 if (!(flags
& CLIP_KEEPRGN
)) DeleteObject32( dc
->w
.hClipRgn
);
187 dc
->w
.hClipRgn
= newRgn
;
188 CLIPPING_UpdateGCRegion( dc
);
190 else DeleteObject32( newRgn
);
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
);
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
);
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
,
276 HRGN32 tempRgn
, newRgn
;
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
);
290 ret
= CombineRgn32( newRgn
, dc
->w
.hVisRgn
, tempRgn
,
291 exclude
? RGN_DIFF
: RGN_AND
);
292 DeleteObject32( tempRgn
);
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
);
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
)
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 */
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
)
389 CONV_RECT32TO16( rect
, &rect16
);
390 return RectVisible16( (HDC16
)hdc
, &rect16
);
394 /***********************************************************************
395 * GetClipBox16 (GDI.77)
397 INT16
GetClipBox16( HDC16 hdc
, LPRECT16 rect
)
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 );
408 /***********************************************************************
409 * GetClipBox32 (GDI32.162)
411 INT32
GetClipBox32( HDC32 hdc
, LPRECT32 rect
)
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 );
422 /***********************************************************************
423 * GetClipRgn32 (GDI32.163)
425 INT32
GetClipRgn32( HDC32 hdc
, HRGN32 hRgn
)
427 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
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
)
441 /***********************************************************************
442 * SaveVisRgn (GDI.129)
444 HRGN16
SaveVisRgn( HDC16 hdc
)
447 RGNOBJ
*obj
, *copyObj
;
448 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
450 dprintf_clipping(stddeb
, "SaveVisRgn: %04x\n", hdc
);
453 fprintf( stderr
, "SaveVisRgn: hVisRgn is zero. Please report this.\n" );
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
)))
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
)))
465 copyObj
->header
.hNext
= obj
->header
.hNext
;
466 obj
->header
.hNext
= copy
;
471 /***********************************************************************
472 * RestoreVisRgn (GDI.130)
474 INT16
RestoreVisRgn( HDC16 hdc
)
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
)))
483 if (!(saved
= obj
->header
.hNext
)) return ERROR
;
484 if (!(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
)))
486 DeleteObject32( dc
->w
.hVisRgn
);
487 dc
->w
.hVisRgn
= saved
;
488 CLIPPING_UpdateGCRegion( dc
);
489 return savedObj
->xrgn
? COMPLEXREGION
: NULLREGION
;