2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/winuser16.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(clipping
);
32 /***********************************************************************
33 * CLIPPING_UpdateGCRegion
35 * Update the GC clip region when the ClipRgn or VisRgn have changed.
37 void CLIPPING_UpdateGCRegion( DC
* dc
)
39 if (!dc
->hGCClipRgn
) dc
->hGCClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
43 ERR("hVisRgn is zero. Please report this.\n" );
47 if (dc
->flags
& DC_DIRTY
) ERR( "DC is dirty. Please report this.\n" );
50 CombineRgn( dc
->hGCClipRgn
, dc
->hVisRgn
, 0, RGN_COPY
);
52 CombineRgn(dc
->hGCClipRgn
, dc
->hClipRgn
, dc
->hVisRgn
, RGN_AND
);
53 if (dc
->funcs
->pSetDeviceClipping
)
54 dc
->funcs
->pSetDeviceClipping( dc
->physDev
, dc
->hGCClipRgn
);
58 /***********************************************************************
59 * SelectClipRgn (GDI.44)
61 INT16 WINAPI
SelectClipRgn16( HDC16 hdc
, HRGN16 hrgn
)
63 return (INT16
)SelectClipRgn( hdc
, hrgn
);
67 /***********************************************************************
68 * SelectClipRgn (GDI32.@)
70 INT WINAPI
SelectClipRgn( HDC hdc
, HRGN hrgn
)
72 return ExtSelectClipRgn( hdc
, hrgn
, RGN_COPY
);
75 /******************************************************************************
76 * ExtSelectClipRgn [GDI.508]
78 INT16 WINAPI
ExtSelectClipRgn16( HDC16 hdc
, HRGN16 hrgn
, INT16 fnMode
)
80 return (INT16
) ExtSelectClipRgn((HDC
) hdc
, (HRGN
) hrgn
, fnMode
);
83 /******************************************************************************
84 * ExtSelectClipRgn [GDI32.@]
86 INT WINAPI
ExtSelectClipRgn( HDC hdc
, HRGN hrgn
, INT fnMode
)
89 DC
* dc
= DC_GetDCUpdate( hdc
);
90 if (!dc
) return ERROR
;
92 TRACE("%04x %04x %d\n", hdc
, hrgn
, fnMode
);
94 if (dc
->funcs
->pExtSelectClipRgn
)
96 retval
= dc
->funcs
->pExtSelectClipRgn( dc
->physDev
, hrgn
, fnMode
);
97 GDI_ReleaseObj( hdc
);
103 if (fnMode
== RGN_COPY
)
105 if (dc
->hClipRgn
) DeleteObject( dc
->hClipRgn
);
107 retval
= SIMPLEREGION
; /* Clip region == whole DC */
111 FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode
);
112 GDI_ReleaseObj( hdc
);
121 GetRgnBox( dc
->hVisRgn
, &rect
);
122 dc
->hClipRgn
= CreateRectRgnIndirect( &rect
);
125 OffsetRgn( dc
->hClipRgn
, -dc
->DCOrgX
, -dc
->DCOrgY
);
126 if(fnMode
== RGN_COPY
)
127 retval
= CombineRgn( dc
->hClipRgn
, hrgn
, 0, fnMode
);
129 retval
= CombineRgn( dc
->hClipRgn
, dc
->hClipRgn
, hrgn
, fnMode
);
130 OffsetRgn( dc
->hClipRgn
, dc
->DCOrgX
, dc
->DCOrgY
);
133 CLIPPING_UpdateGCRegion( dc
);
134 GDI_ReleaseObj( hdc
);
138 /***********************************************************************
139 * SelectVisRgn (GDI.105)
141 INT16 WINAPI
SelectVisRgn16( HDC16 hdc
, HRGN16 hrgn
)
146 if (!hrgn
) return ERROR
;
147 if (!(dc
= DC_GetDCPtr( hdc
))) return ERROR
;
149 TRACE("%04x %04x\n", hdc
, hrgn
);
151 dc
->flags
&= ~DC_DIRTY
;
153 retval
= CombineRgn16( dc
->hVisRgn
, hrgn
, 0, RGN_COPY
);
154 CLIPPING_UpdateGCRegion( dc
);
155 GDI_ReleaseObj( hdc
);
160 /***********************************************************************
161 * OffsetClipRgn (GDI.32)
163 INT16 WINAPI
OffsetClipRgn16( HDC16 hdc
, INT16 x
, INT16 y
)
165 return (INT16
)OffsetClipRgn( hdc
, x
, y
);
169 /***********************************************************************
170 * OffsetClipRgn (GDI32.@)
172 INT WINAPI
OffsetClipRgn( HDC hdc
, INT x
, INT y
)
174 INT ret
= SIMPLEREGION
;
175 DC
*dc
= DC_GetDCUpdate( hdc
);
176 if (!dc
) return ERROR
;
178 TRACE("%04x %d,%d\n", hdc
, x
, y
);
180 if(dc
->funcs
->pOffsetClipRgn
)
181 ret
= dc
->funcs
->pOffsetClipRgn( dc
->physDev
, x
, y
);
182 else if (dc
->hClipRgn
) {
183 ret
= OffsetRgn( dc
->hClipRgn
, XLSTODS(dc
,x
), YLSTODS(dc
,y
));
184 CLIPPING_UpdateGCRegion( dc
);
186 GDI_ReleaseObj( hdc
);
191 /***********************************************************************
192 * OffsetVisRgn (GDI.102)
194 INT16 WINAPI
OffsetVisRgn16( HDC16 hdc
, INT16 x
, INT16 y
)
197 DC
* dc
= DC_GetDCUpdate( hdc
);
198 if (!dc
) return ERROR
;
199 TRACE("%04x %d,%d\n", hdc
, x
, y
);
200 retval
= OffsetRgn( dc
->hVisRgn
, x
, y
);
201 CLIPPING_UpdateGCRegion( dc
);
202 GDI_ReleaseObj( hdc
);
207 /***********************************************************************
208 * CLIPPING_IntersectClipRect
210 * Helper function for {Intersect,Exclude}ClipRect, can be called from
211 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
212 * coordinate conversion.
214 INT
CLIPPING_IntersectClipRect( DC
* dc
, INT left
, INT top
,
215 INT right
, INT bottom
, UINT flags
)
223 bottom
+= dc
->DCOrgY
;
225 if (!(newRgn
= CreateRectRgn( left
, top
, right
, bottom
))) return ERROR
;
228 if( flags
& CLIP_INTERSECT
)
230 dc
->hClipRgn
= newRgn
;
231 CLIPPING_UpdateGCRegion( dc
);
234 else if( flags
& CLIP_EXCLUDE
)
236 dc
->hClipRgn
= CreateRectRgn( 0, 0, 0, 0 );
237 CombineRgn( dc
->hClipRgn
, dc
->hVisRgn
, 0, RGN_COPY
);
239 else WARN("No hClipRgn and flags are %x\n",flags
);
242 ret
= CombineRgn( newRgn
, dc
->hClipRgn
, newRgn
,
243 (flags
& CLIP_EXCLUDE
) ? RGN_DIFF
: RGN_AND
);
246 if (!(flags
& CLIP_KEEPRGN
)) DeleteObject( dc
->hClipRgn
);
247 dc
->hClipRgn
= newRgn
;
248 CLIPPING_UpdateGCRegion( dc
);
250 else DeleteObject( newRgn
);
255 /***********************************************************************
256 * ExcludeClipRect (GDI.21)
258 INT16 WINAPI
ExcludeClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
259 INT16 right
, INT16 bottom
)
261 return (INT16
)ExcludeClipRect( hdc
, left
, top
, right
, bottom
);
265 /***********************************************************************
266 * ExcludeClipRect (GDI32.@)
268 INT WINAPI
ExcludeClipRect( HDC hdc
, INT left
, INT top
,
269 INT right
, INT bottom
)
272 DC
*dc
= DC_GetDCUpdate( hdc
);
273 if (!dc
) return ERROR
;
275 TRACE("%04x %dx%d,%dx%d\n", hdc
, left
, top
, right
, bottom
);
277 if(dc
->funcs
->pExcludeClipRect
)
278 ret
= dc
->funcs
->pExcludeClipRect( dc
->physDev
, left
, top
, right
, bottom
);
280 left
= XLPTODP( dc
, left
);
281 right
= XLPTODP( dc
, right
);
282 top
= YLPTODP( dc
, top
);
283 bottom
= YLPTODP( dc
, bottom
);
285 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_EXCLUDE
);
287 GDI_ReleaseObj( hdc
);
292 /***********************************************************************
293 * IntersectClipRect (GDI.22)
295 INT16 WINAPI
IntersectClipRect16( HDC16 hdc
, INT16 left
, INT16 top
,
296 INT16 right
, INT16 bottom
)
298 return (INT16
)IntersectClipRect( hdc
, left
, top
, right
, bottom
);
302 /***********************************************************************
303 * IntersectClipRect (GDI32.@)
305 INT WINAPI
IntersectClipRect( HDC hdc
, INT left
, INT top
,
306 INT right
, INT bottom
)
309 DC
*dc
= DC_GetDCUpdate( hdc
);
310 if (!dc
) return ERROR
;
312 TRACE("%04x %dx%d,%dx%d\n", hdc
, left
, top
, right
, bottom
);
314 if(dc
->funcs
->pIntersectClipRect
)
315 ret
= dc
->funcs
->pIntersectClipRect( dc
->physDev
, left
, top
, right
, bottom
);
317 left
= XLPTODP( dc
, left
);
318 right
= XLPTODP( dc
, right
);
319 top
= YLPTODP( dc
, top
);
320 bottom
= YLPTODP( dc
, bottom
);
322 ret
= CLIPPING_IntersectClipRect( dc
, left
, top
, right
, bottom
, CLIP_INTERSECT
);
324 GDI_ReleaseObj( hdc
);
329 /***********************************************************************
330 * CLIPPING_IntersectVisRect
332 * Helper function for {Intersect,Exclude}VisRect, can be called from
333 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
334 * coordinate conversion.
336 INT
CLIPPING_IntersectVisRect( DC
* dc
, INT left
, INT top
,
337 INT right
, INT bottom
,
340 HRGN tempRgn
, newRgn
;
346 bottom
+= dc
->DCOrgY
;
348 if (!(newRgn
= CreateRectRgn( 0, 0, 0, 0 ))) return ERROR
;
349 if (!(tempRgn
= CreateRectRgn( left
, top
, right
, bottom
)))
351 DeleteObject( newRgn
);
354 ret
= CombineRgn( newRgn
, dc
->hVisRgn
, tempRgn
,
355 exclude
? RGN_DIFF
: RGN_AND
);
356 DeleteObject( tempRgn
);
360 RGNOBJ
*newObj
= (RGNOBJ
*)GDI_GetObjPtr( newRgn
, REGION_MAGIC
);
363 RGNOBJ
*prevObj
= (RGNOBJ
*)GDI_GetObjPtr( dc
->hVisRgn
, REGION_MAGIC
);
366 newObj
->header
.hNext
= prevObj
->header
.hNext
;
367 GDI_ReleaseObj( dc
->hVisRgn
);
369 GDI_ReleaseObj( newRgn
);
371 DeleteObject( dc
->hVisRgn
);
372 dc
->hVisRgn
= newRgn
;
373 CLIPPING_UpdateGCRegion( dc
);
375 else DeleteObject( newRgn
);
380 /***********************************************************************
381 * ExcludeVisRect (GDI.73)
383 INT16 WINAPI
ExcludeVisRect16( HDC16 hdc
, INT16 left
, INT16 top
,
384 INT16 right
, INT16 bottom
)
387 DC
* dc
= DC_GetDCUpdate( hdc
);
388 if (!dc
) return ERROR
;
390 left
= XLPTODP( dc
, left
);
391 right
= XLPTODP( dc
, right
);
392 top
= YLPTODP( dc
, top
);
393 bottom
= YLPTODP( dc
, bottom
);
395 TRACE("%04x %dx%d,%dx%d\n", hdc
, left
, top
, right
, bottom
);
397 ret
= CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, TRUE
);
398 GDI_ReleaseObj( hdc
);
403 /***********************************************************************
404 * IntersectVisRect (GDI.98)
406 INT16 WINAPI
IntersectVisRect16( HDC16 hdc
, INT16 left
, INT16 top
,
407 INT16 right
, INT16 bottom
)
410 DC
* dc
= DC_GetDCUpdate( hdc
);
411 if (!dc
) return ERROR
;
413 left
= XLPTODP( dc
, left
);
414 right
= XLPTODP( dc
, right
);
415 top
= YLPTODP( dc
, top
);
416 bottom
= YLPTODP( dc
, bottom
);
418 TRACE("%04x %dx%d,%dx%d\n", hdc
, left
, top
, right
, bottom
);
420 ret
= CLIPPING_IntersectVisRect( dc
, left
, top
, right
, bottom
, FALSE
);
421 GDI_ReleaseObj( hdc
);
426 /***********************************************************************
427 * PtVisible (GDI.103)
429 BOOL16 WINAPI
PtVisible16( HDC16 hdc
, INT16 x
, INT16 y
)
431 return PtVisible( hdc
, x
, y
);
435 /***********************************************************************
436 * PtVisible (GDI32.@)
438 BOOL WINAPI
PtVisible( HDC hdc
, INT x
, INT y
)
441 DC
*dc
= DC_GetDCUpdate( hdc
);
443 TRACE("%04x %d,%d\n", hdc
, x
, y
);
444 if (!dc
) return FALSE
;
447 ret
= PtInRegion( dc
->hGCClipRgn
, XLPTODP(dc
,x
) + dc
->DCOrgX
,
448 YLPTODP(dc
,y
) + dc
->DCOrgY
);
450 GDI_ReleaseObj( hdc
);
455 /***********************************************************************
456 * RectVisible (GDI.465)
457 * RectVisibleOld (GDI.104)
459 BOOL16 WINAPI
RectVisible16( HDC16 hdc
, const RECT16
* rect16
)
462 CONV_RECT16TO32( rect16
, &rect
);
463 return RectVisible( hdc
, &rect
);
467 /***********************************************************************
468 * RectVisible (GDI32.@)
470 BOOL WINAPI
RectVisible( HDC hdc
, const RECT
* rect
)
474 DC
*dc
= DC_GetDCUpdate( hdc
);
475 if (!dc
) return FALSE
;
476 TRACE("%04x %d,%dx%d,%d\n",
477 hdc
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
480 /* copy rectangle to avoid overwriting by LPtoDP */
482 LPtoDP( hdc
, (LPPOINT
)&tmpRect
, 2 );
483 tmpRect
.left
+= dc
->DCOrgX
;
484 tmpRect
.right
+= dc
->DCOrgX
;
485 tmpRect
.top
+= dc
->DCOrgY
;
486 tmpRect
.bottom
+= dc
->DCOrgY
;
487 ret
= RectInRegion( dc
->hGCClipRgn
, &tmpRect
);
489 GDI_ReleaseObj( hdc
);
494 /***********************************************************************
495 * GetClipBox (GDI.77)
497 INT16 WINAPI
GetClipBox16( HDC16 hdc
, LPRECT16 rect
)
500 DC
*dc
= DC_GetDCUpdate( hdc
);
501 if (!dc
) return ERROR
;
502 ret
= GetRgnBox16( dc
->hGCClipRgn
, rect
);
503 rect
->left
-= dc
->DCOrgX
;
504 rect
->right
-= dc
->DCOrgX
;
505 rect
->top
-= dc
->DCOrgY
;
506 rect
->bottom
-= dc
->DCOrgY
;
507 DPtoLP16( hdc
, (LPPOINT16
)rect
, 2 );
508 TRACE("%d,%d-%d,%d\n", rect
->left
,rect
->top
,rect
->right
,rect
->bottom
);
509 GDI_ReleaseObj( hdc
);
514 /***********************************************************************
515 * GetClipBox (GDI32.@)
517 INT WINAPI
GetClipBox( HDC hdc
, LPRECT rect
)
520 DC
*dc
= DC_GetDCUpdate( hdc
);
521 if (!dc
) return ERROR
;
522 ret
= GetRgnBox( dc
->hGCClipRgn
, rect
);
523 rect
->left
-= dc
->DCOrgX
;
524 rect
->right
-= dc
->DCOrgX
;
525 rect
->top
-= dc
->DCOrgY
;
526 rect
->bottom
-= dc
->DCOrgY
;
527 DPtoLP( hdc
, (LPPOINT
)rect
, 2 );
528 GDI_ReleaseObj( hdc
);
533 /***********************************************************************
534 * GetClipRgn (GDI32.@)
536 INT WINAPI
GetClipRgn( HDC hdc
, HRGN hRgn
)
540 if (hRgn
&& (dc
= DC_GetDCPtr( hdc
)))
544 /* this assumes that dc->hClipRgn is in coordinates
545 relative to the device (not DC origin) */
547 if( CombineRgn(hRgn
, dc
->hClipRgn
, 0, RGN_COPY
) != ERROR
)
549 OffsetRgn( hRgn
, -dc
->DCOrgX
, -dc
->DCOrgY
);
554 GDI_ReleaseObj( hdc
);
559 /***********************************************************************
560 * SaveVisRgn (GDI.129)
562 HRGN16 WINAPI
SaveVisRgn16( HDC16 hdc
)
565 RGNOBJ
*obj
, *copyObj
;
566 DC
*dc
= DC_GetDCUpdate( hdc
);
569 TRACE("%04x\n", hdc
);
571 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->hVisRgn
, REGION_MAGIC
)))
573 GDI_ReleaseObj( hdc
);
576 if (!(copy
= CreateRectRgn( 0, 0, 0, 0 )))
578 GDI_ReleaseObj( dc
->hVisRgn
);
579 GDI_ReleaseObj( hdc
);
582 CombineRgn( copy
, dc
->hVisRgn
, 0, RGN_COPY
);
583 if (!(copyObj
= (RGNOBJ
*) GDI_GetObjPtr( copy
, REGION_MAGIC
)))
585 DeleteObject( copy
);
586 GDI_ReleaseObj( dc
->hVisRgn
);
587 GDI_ReleaseObj( hdc
);
590 copyObj
->header
.hNext
= obj
->header
.hNext
;
591 obj
->header
.hNext
= copy
;
592 GDI_ReleaseObj( copy
);
593 GDI_ReleaseObj( dc
->hVisRgn
);
594 GDI_ReleaseObj( hdc
);
599 /***********************************************************************
600 * RestoreVisRgn (GDI.130)
602 INT16 WINAPI
RestoreVisRgn16( HDC16 hdc
)
605 RGNOBJ
*obj
, *savedObj
;
606 DC
*dc
= DC_GetDCPtr( hdc
);
609 if (!dc
) return ERROR
;
610 if (!dc
->hVisRgn
) goto done
;
611 TRACE("%04x\n", hdc
);
612 if (!(obj
= (RGNOBJ
*) GDI_GetObjPtr( dc
->hVisRgn
, REGION_MAGIC
))) goto done
;
614 saved
= obj
->header
.hNext
;
615 GDI_ReleaseObj( dc
->hVisRgn
);
616 if (!saved
|| !(savedObj
= (RGNOBJ
*) GDI_GetObjPtr( saved
, REGION_MAGIC
))) goto done
;
618 DeleteObject( dc
->hVisRgn
);
620 dc
->flags
&= ~DC_DIRTY
;
621 CLIPPING_UpdateGCRegion( dc
);
622 ret
= savedObj
->rgn
->type
; /* FIXME */
623 GDI_ReleaseObj( saved
);
625 GDI_ReleaseObj( hdc
);