gdi32: Add support for clipping source coordinates to the DC device rectangle.

This commit is contained in:
Alexandre Julliard 2012-04-30 21:17:00 +02:00
parent d2581e6229
commit 41e5bc06d8
6 changed files with 42 additions and 32 deletions

View File

@ -146,13 +146,7 @@ static BOOL get_vis_rectangles( DC *dc_dst, struct bitblt_coords *dst,
}
get_bounding_rect( &rect, src->x, src->y, src->width, src->height );
/* source is not clipped */
if (dc_src->header.type == OBJ_MEMDC)
intersect_rect( &src->visrect, &rect, &dc_src->vis_rect );
else
src->visrect = rect; /* FIXME: clip to device size */
if (is_rect_empty( &src->visrect )) return FALSE;
if (!clip_device_rect( dc_src, &src->visrect, &rect )) return FALSE;
if (is_rect_empty( &dst->visrect )) return FALSE;
return intersect_vis_rectangles( dst, src );
@ -932,9 +926,9 @@ BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heig
if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
src.log_width < 0 || src.log_height < 0 ||
(dcSrc->header.type == OBJ_MEMDC &&
(src.width > dcSrc->vis_rect.right - dcSrc->vis_rect.left - src.x ||
src.height > dcSrc->vis_rect.bottom - dcSrc->vis_rect.top - src.y)))
(!is_rect_empty( &dcSrc->device_rect ) &&
(src.width > dcSrc->device_rect.right - dcSrc->vis_rect.left - src.x ||
src.height > dcSrc->device_rect.bottom - dcSrc->vis_rect.top - src.y)))
{
WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
SetLastError( ERROR_INVALID_PARAMETER );

View File

@ -609,6 +609,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
dc->vis_rect.top = 0;
dc->vis_rect.right = bitmap->dib.dsBm.bmWidth;
dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
dc->device_rect = dc->vis_rect;
GDI_ReleaseObj( handle );
DC_InitDC( dc );
GDI_dec_ref_count( ret );

View File

@ -29,15 +29,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(clipping);
/* return the DC visible rectangle if not empty */
static inline BOOL get_dc_visrect( DC *dc, RECT *rect )
/* return the DC device rectangle if not empty */
static inline BOOL get_dc_device_rect( DC *dc, RECT *rect )
{
if (dc->header.type != OBJ_MEMDC) return FALSE;
rect->left = 0;
rect->top = 0;
rect->right = dc->vis_rect.right - dc->vis_rect.left;
rect->bottom = dc->vis_rect.bottom - dc->vis_rect.top;
return TRUE;
*rect = dc->device_rect;
offset_rect( rect, -dc->vis_rect.left, -dc->vis_rect.top );
return !is_rect_empty( rect );
}
/***********************************************************************
@ -63,6 +60,20 @@ static inline RECT get_clip_rect( DC * dc, int left, int top, int right, int bot
return rect;
}
/***********************************************************************
* clip_device_rect
*
* Clip a rectangle to the whole DC surface.
*/
BOOL clip_device_rect( DC *dc, RECT *dst, const RECT *src )
{
RECT clip;
if (get_dc_device_rect( dc, &clip )) return intersect_rect( dst, src, &clip );
*dst = *src;
return TRUE;
}
/***********************************************************************
* clip_visrect
*
@ -72,11 +83,9 @@ BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src )
{
RECT clip;
if (get_dc_visrect( dc, &clip )) intersect_rect( dst, src, &clip );
else *dst = *src;
if (GetRgnBox( get_dc_region(dc), &clip )) intersect_rect( dst, dst, &clip );
return !is_rect_empty( dst );
if (!clip_device_rect( dc, dst, src )) return FALSE;
if (GetRgnBox( get_dc_region(dc), &clip )) return intersect_rect( dst, dst, &clip );
return TRUE;
}
/***********************************************************************
@ -117,7 +126,7 @@ static inline void create_default_clip_region( DC * dc )
{
RECT rect;
if (!get_dc_visrect( dc, &rect ))
if (!get_dc_device_rect( dc, &rect ))
{
rect.left = 0;
rect.top = 0;
@ -361,7 +370,7 @@ BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
pt.y = y;
LPtoDP( hdc, &pt, 1 );
update_dc( dc );
ret = (!get_dc_visrect( dc, &visrect ) ||
ret = (!get_dc_device_rect( dc, &visrect ) ||
(pt.x >= visrect.left && pt.x < visrect.right &&
pt.y >= visrect.top && pt.y < visrect.bottom));
if (ret && get_dc_region( dc )) ret = PtInRegion( get_dc_region( dc ), pt.x, pt.y );
@ -385,7 +394,7 @@ BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
LPtoDP( hdc, (POINT *)&tmpRect, 2 );
update_dc( dc );
ret = (!get_dc_visrect( dc, &visrect ) || intersect_rect( &visrect, &visrect, &tmpRect ));
ret = (!get_dc_device_rect( dc, &visrect ) || intersect_rect( &visrect, &visrect, &tmpRect ));
if (ret && get_dc_region( dc )) ret = RectInRegion( get_dc_region( dc ), &tmpRect );
release_dc_ptr( dc );
return ret;
@ -406,7 +415,7 @@ INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
if (get_dc_region( dc ))
{
ret = GetRgnBox( get_dc_region( dc ), rect );
if (get_dc_visrect( dc, &visrect ) && !intersect_rect( rect, rect, &visrect ))
if (get_dc_device_rect( dc, &visrect ) && !intersect_rect( rect, rect, &visrect ))
ret = NULLREGION;
}
else
@ -492,7 +501,6 @@ INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
{
INT ret = 1;
RECT visrect;
DC *dc = get_dc_ptr( hDC );
if (!dc) return -1;
@ -516,13 +524,16 @@ INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
case SYSRGN: /* == 4 */
update_dc( dc );
if (dc->hVisRgn)
{
CombineRgn( hRgn, dc->hVisRgn, 0, RGN_COPY );
else if (get_dc_visrect( dc, &visrect ))
SetRectRgn( hRgn, visrect.left, visrect.top, visrect.right, visrect.bottom );
/* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
if (!(GetVersion() & 0x80000000)) OffsetRgn( hRgn, dc->vis_rect.left, dc->vis_rect.top );
}
else if (!is_rect_empty( &dc->device_rect ))
SetRectRgn( hRgn, dc->device_rect.left, dc->device_rect.top,
dc->device_rect.right, dc->device_rect.bottom );
else
ret = 0;
/* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
if (ret && !(GetVersion() & 0x80000000)) OffsetRgn( hRgn, dc->vis_rect.left, dc->vis_rect.top );
break;
default:
WARN("Unknown code %d\n", iCode);

View File

@ -698,6 +698,7 @@ HDC WINAPI CreateCompatibleDC( HDC hdc )
dc->vis_rect.top = 0;
dc->vis_rect.right = 1;
dc->vis_rect.bottom = 1;
dc->device_rect = dc->vis_rect;
ret = dc->hSelf;

View File

@ -1624,6 +1624,7 @@ static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
dc->vis_rect.top = 0;
dc->vis_rect.right = bitmap->dib.dsBm.bmWidth;
dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
dc->device_rect = dc->vis_rect;
GDI_ReleaseObj( handle );
DC_InitDC( dc );
GDI_dec_ref_count( ret );

View File

@ -104,6 +104,7 @@ typedef struct tagDC
SIZE virtual_res; /* Initially HORZRES,VERTRES. Changed by SetVirtualResolution */
SIZE virtual_size; /* Initially HORZSIZE,VERTSIZE. Changed by SetVirtualResolution */
RECT vis_rect; /* visible rectangle in screen coords */
RECT device_rect; /* rectangle for the whole device */
FLOAT miterLimit;
int flags;
@ -217,6 +218,7 @@ extern void free_brush_pattern( struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN;
/* clipping.c */
extern BOOL clip_device_rect( DC *dc, RECT *dst, const RECT *src ) DECLSPEC_HIDDEN;
extern BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src ) DECLSPEC_HIDDEN;
extern void update_dc_clipping( DC * dc ) DECLSPEC_HIDDEN;