Commit 41e5bc06 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent d2581e62
...@@ -146,13 +146,7 @@ static BOOL get_vis_rectangles( DC *dc_dst, struct bitblt_coords *dst, ...@@ -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 ); get_bounding_rect( &rect, src->x, src->y, src->width, src->height );
/* source is not clipped */ if (!clip_device_rect( dc_src, &src->visrect, &rect )) return FALSE;
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 (is_rect_empty( &dst->visrect )) return FALSE; if (is_rect_empty( &dst->visrect )) return FALSE;
return intersect_vis_rectangles( dst, src ); return intersect_vis_rectangles( dst, src );
...@@ -932,9 +926,9 @@ BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heig ...@@ -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 || if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
src.log_width < 0 || src.log_height < 0 || src.log_width < 0 || src.log_height < 0 ||
(dcSrc->header.type == OBJ_MEMDC && (!is_rect_empty( &dcSrc->device_rect ) &&
(src.width > dcSrc->vis_rect.right - dcSrc->vis_rect.left - src.x || (src.width > dcSrc->device_rect.right - dcSrc->vis_rect.left - src.x ||
src.height > dcSrc->vis_rect.bottom - dcSrc->vis_rect.top - src.y))) 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 ); WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
SetLastError( ERROR_INVALID_PARAMETER ); SetLastError( ERROR_INVALID_PARAMETER );
......
...@@ -609,6 +609,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) ...@@ -609,6 +609,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
dc->vis_rect.top = 0; dc->vis_rect.top = 0;
dc->vis_rect.right = bitmap->dib.dsBm.bmWidth; dc->vis_rect.right = bitmap->dib.dsBm.bmWidth;
dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight; dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
dc->device_rect = dc->vis_rect;
GDI_ReleaseObj( handle ); GDI_ReleaseObj( handle );
DC_InitDC( dc ); DC_InitDC( dc );
GDI_dec_ref_count( ret ); GDI_dec_ref_count( ret );
......
...@@ -29,15 +29,12 @@ ...@@ -29,15 +29,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(clipping); WINE_DEFAULT_DEBUG_CHANNEL(clipping);
/* return the DC visible rectangle if not empty */ /* return the DC device rectangle if not empty */
static inline BOOL get_dc_visrect( DC *dc, RECT *rect ) static inline BOOL get_dc_device_rect( DC *dc, RECT *rect )
{ {
if (dc->header.type != OBJ_MEMDC) return FALSE; *rect = dc->device_rect;
rect->left = 0; offset_rect( rect, -dc->vis_rect.left, -dc->vis_rect.top );
rect->top = 0; return !is_rect_empty( rect );
rect->right = dc->vis_rect.right - dc->vis_rect.left;
rect->bottom = dc->vis_rect.bottom - dc->vis_rect.top;
return TRUE;
} }
/*********************************************************************** /***********************************************************************
...@@ -64,6 +61,20 @@ static inline RECT get_clip_rect( DC * dc, int left, int top, int right, int bot ...@@ -64,6 +61,20 @@ static inline RECT get_clip_rect( DC * dc, int left, int top, int right, int bot
} }
/*********************************************************************** /***********************************************************************
* 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 * clip_visrect
* *
* Clip a rectangle to the DC visible rect. * Clip a rectangle to the DC visible rect.
...@@ -72,11 +83,9 @@ BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src ) ...@@ -72,11 +83,9 @@ BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src )
{ {
RECT clip; RECT clip;
if (get_dc_visrect( dc, &clip )) intersect_rect( dst, src, &clip ); if (!clip_device_rect( dc, dst, src )) return FALSE;
else *dst = *src; if (GetRgnBox( get_dc_region(dc), &clip )) return intersect_rect( dst, dst, &clip );
return TRUE;
if (GetRgnBox( get_dc_region(dc), &clip )) intersect_rect( dst, dst, &clip );
return !is_rect_empty( dst );
} }
/*********************************************************************** /***********************************************************************
...@@ -117,7 +126,7 @@ static inline void create_default_clip_region( DC * dc ) ...@@ -117,7 +126,7 @@ static inline void create_default_clip_region( DC * dc )
{ {
RECT rect; RECT rect;
if (!get_dc_visrect( dc, &rect )) if (!get_dc_device_rect( dc, &rect ))
{ {
rect.left = 0; rect.left = 0;
rect.top = 0; rect.top = 0;
...@@ -361,7 +370,7 @@ BOOL WINAPI PtVisible( HDC hdc, INT x, INT y ) ...@@ -361,7 +370,7 @@ BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
pt.y = y; pt.y = y;
LPtoDP( hdc, &pt, 1 ); LPtoDP( hdc, &pt, 1 );
update_dc( dc ); 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.x >= visrect.left && pt.x < visrect.right &&
pt.y >= visrect.top && pt.y < visrect.bottom)); pt.y >= visrect.top && pt.y < visrect.bottom));
if (ret && get_dc_region( dc )) ret = PtInRegion( get_dc_region( dc ), pt.x, pt.y ); 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 ) ...@@ -385,7 +394,7 @@ BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
LPtoDP( hdc, (POINT *)&tmpRect, 2 ); LPtoDP( hdc, (POINT *)&tmpRect, 2 );
update_dc( dc ); 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 ); if (ret && get_dc_region( dc )) ret = RectInRegion( get_dc_region( dc ), &tmpRect );
release_dc_ptr( dc ); release_dc_ptr( dc );
return ret; return ret;
...@@ -406,7 +415,7 @@ INT WINAPI GetClipBox( HDC hdc, LPRECT rect ) ...@@ -406,7 +415,7 @@ INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
if (get_dc_region( dc )) if (get_dc_region( dc ))
{ {
ret = GetRgnBox( get_dc_region( dc ), rect ); 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; ret = NULLREGION;
} }
else else
...@@ -492,7 +501,6 @@ INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn ) ...@@ -492,7 +501,6 @@ INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode) INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
{ {
INT ret = 1; INT ret = 1;
RECT visrect;
DC *dc = get_dc_ptr( hDC ); DC *dc = get_dc_ptr( hDC );
if (!dc) return -1; if (!dc) return -1;
...@@ -516,13 +524,16 @@ INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode) ...@@ -516,13 +524,16 @@ INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
case SYSRGN: /* == 4 */ case SYSRGN: /* == 4 */
update_dc( dc ); update_dc( dc );
if (dc->hVisRgn) if (dc->hVisRgn)
{
CombineRgn( hRgn, dc->hVisRgn, 0, RGN_COPY ); CombineRgn( hRgn, dc->hVisRgn, 0, RGN_COPY );
else if (get_dc_visrect( dc, &visrect )) /* On Windows NT/2000, the SYSRGN returned is in screen coordinates */
SetRectRgn( hRgn, visrect.left, visrect.top, visrect.right, visrect.bottom ); 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 else
ret = 0; 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; break;
default: default:
WARN("Unknown code %d\n", iCode); WARN("Unknown code %d\n", iCode);
......
...@@ -698,6 +698,7 @@ HDC WINAPI CreateCompatibleDC( HDC hdc ) ...@@ -698,6 +698,7 @@ HDC WINAPI CreateCompatibleDC( HDC hdc )
dc->vis_rect.top = 0; dc->vis_rect.top = 0;
dc->vis_rect.right = 1; dc->vis_rect.right = 1;
dc->vis_rect.bottom = 1; dc->vis_rect.bottom = 1;
dc->device_rect = dc->vis_rect;
ret = dc->hSelf; ret = dc->hSelf;
......
...@@ -1624,6 +1624,7 @@ static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc ) ...@@ -1624,6 +1624,7 @@ static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
dc->vis_rect.top = 0; dc->vis_rect.top = 0;
dc->vis_rect.right = bitmap->dib.dsBm.bmWidth; dc->vis_rect.right = bitmap->dib.dsBm.bmWidth;
dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight; dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
dc->device_rect = dc->vis_rect;
GDI_ReleaseObj( handle ); GDI_ReleaseObj( handle );
DC_InitDC( dc ); DC_InitDC( dc );
GDI_dec_ref_count( ret ); GDI_dec_ref_count( ret );
......
...@@ -104,6 +104,7 @@ typedef struct tagDC ...@@ -104,6 +104,7 @@ typedef struct tagDC
SIZE virtual_res; /* Initially HORZRES,VERTRES. Changed by SetVirtualResolution */ SIZE virtual_res; /* Initially HORZRES,VERTRES. Changed by SetVirtualResolution */
SIZE virtual_size; /* Initially HORZSIZE,VERTSIZE. Changed by SetVirtualResolution */ SIZE virtual_size; /* Initially HORZSIZE,VERTSIZE. Changed by SetVirtualResolution */
RECT vis_rect; /* visible rectangle in screen coords */ RECT vis_rect; /* visible rectangle in screen coords */
RECT device_rect; /* rectangle for the whole device */
FLOAT miterLimit; FLOAT miterLimit;
int flags; int flags;
...@@ -217,6 +218,7 @@ extern void free_brush_pattern( struct brush_pattern *pattern ) DECLSPEC_HIDDEN; ...@@ -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; extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN;
/* clipping.c */ /* 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 BOOL clip_visrect( DC *dc, RECT *dst, const RECT *src ) DECLSPEC_HIDDEN;
extern void update_dc_clipping( DC * dc ) DECLSPEC_HIDDEN; extern void update_dc_clipping( DC * dc ) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment