gdi32: Add bounds tracking to all the DIB engine entry points.

This commit is contained in:
Alexandre Julliard 2012-04-11 14:49:30 +02:00
parent 582a2f511f
commit 34457aa4c3
6 changed files with 118 additions and 25 deletions

View file

@ -964,6 +964,7 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info
clip = tmp_rgn;
}
else if (!clip) clip = pdev->clip;
add_clipped_bounds( &pdev->bounds, &dst->visrect, clip );
}
if (!get_clipped_rects( dib, &dst->visrect, clip, &clipped_rects ))
@ -1020,6 +1021,7 @@ DWORD dibdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_b
init_dib_info_from_bitmapinfo( &src_dib, info, bits->ptr, 0 );
src_dib.bits.is_copy = bits->is_copy;
add_clipped_bounds( &pdev->bounds, &dst->visrect, pdev->clip );
return blend_rect( &pdev->dib, &dst->visrect, &src_dib, &src->visrect, pdev->clip, blend );
update_format:
@ -1405,6 +1407,7 @@ BOOL dibdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
/* Windows bug: no alpha on a8r8g8b8 created with bitfields */
if (pdev->dib.funcs == &funcs_8888 && pdev->dib.compression == BI_BITFIELDS)
vert[0].Alpha = vert[1].Alpha = 0;
add_clipped_bounds( &pdev->bounds, &bounds, pdev->clip );
gradient_rect( &pdev->dib, vert, mode, pdev->clip, &bounds );
}
break;
@ -1416,6 +1419,7 @@ BOOL dibdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
/* Windows bug: no alpha on a8r8g8b8 created with bitfields */
if (pdev->dib.funcs == &funcs_8888 && pdev->dib.compression == BI_BITFIELDS)
vert[0].Alpha = vert[1].Alpha = 0;
add_clipped_bounds( &pdev->bounds, &bounds, pdev->clip );
gradient_rect( &pdev->dib, vert, mode, pdev->clip, &bounds );
}
break;
@ -1427,6 +1431,7 @@ BOOL dibdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
/* Windows bug: no alpha on a8r8g8b8 created with bitfields */
if (pdev->dib.funcs == &funcs_8888 && pdev->dib.compression == BI_BITFIELDS)
vert[0].Alpha = vert[1].Alpha = vert[2].Alpha = 0;
add_clipped_bounds( &pdev->bounds, &bounds, pdev->clip );
if (!gradient_rect( &pdev->dib, vert, mode, pdev->clip, &bounds )) ret = FALSE;
}
break;

View file

@ -298,6 +298,21 @@ int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct cl
return clip_rects->count;
}
void add_clipped_bounds( RECT *bounds, const RECT *rect, HRGN clip )
{
const WINEREGION *region;
RECT rc;
if (clip)
{
if (!(region = get_wine_region( clip ))) return;
if (!rect) add_bounds_rect( bounds, &region->extents );
else if (intersect_rect( &rc, rect, &region->extents )) add_bounds_rect( bounds, &rc );
release_wine_region( clip );
}
else if (rect) add_bounds_rect( bounds, rect );
}
/**********************************************************************
* dibdrv_CreateDC
*/
@ -310,6 +325,7 @@ static BOOL dibdrv_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
clear_dib_info(&pdev->dib);
clear_dib_info(&pdev->brush.dib);
clear_dib_info(&pdev->pen_brush.dib);
reset_bounds( &pdev->bounds );
push_dc_driver( dev, &pdev->dev, &dib_driver );
return TRUE;
}
@ -378,6 +394,19 @@ static void dibdrv_SetDeviceClipping( PHYSDEV dev, HRGN rgn )
pdev->clip = rgn;
}
/***********************************************************************
* dibdrv_GetBoundsRect
*/
static UINT dibdrv_GetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
{
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
if (is_rect_empty( &pdev->bounds )) return DCB_RESET;
if (rect) *rect = pdev->bounds;
if (flags & DCB_RESET) reset_bounds( &pdev->bounds );
return DCB_SET;
}
/***********************************************************************
* dibdrv_ChoosePixelFormat
*/
@ -599,7 +628,7 @@ const struct gdi_dc_funcs dib_driver =
NULL, /* pFrameRgn */
NULL, /* pGdiComment */
NULL, /* pGdiRealizationInfo */
NULL, /* pGetBoundsRect */
dibdrv_GetBoundsRect, /* pGetBoundsRect */
NULL, /* pGetCharABCWidths */
NULL, /* pGetCharABCWidthsI */
NULL, /* pGetCharWidth */

View file

@ -96,6 +96,7 @@ typedef struct dibdrv_physdev
dib_brush brush;
HRGN clip;
RECT bounds;
/* pen */
DWORD pen_style, pen_endcap, pen_join;
@ -246,6 +247,7 @@ extern COLORREF make_rgb_colorref( HDC hdc, dib_info *dib, COLORREF color, BOOL
extern DWORD get_pixel_color(dibdrv_physdev *pdev, COLORREF color, BOOL mono_fixup) DECLSPEC_HIDDEN;
extern BOOL brush_rect( dibdrv_physdev *pdev, dib_brush *brush, const RECT *rect, HRGN clip, INT rop ) DECLSPEC_HIDDEN;
extern int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects ) DECLSPEC_HIDDEN;
extern void add_clipped_bounds( RECT *bounds, const RECT *rect, HRGN clip ) DECLSPEC_HIDDEN;
extern int clip_line(const POINT *start, const POINT *end, const RECT *clip,
const bres_params *params, POINT *pt1, POINT *pt2) DECLSPEC_HIDDEN;

View file

@ -86,6 +86,50 @@ static BOOL get_pen_device_rect( dibdrv_physdev *dev, RECT *rect, int left, int
return TRUE;
}
static void add_pen_lines_bounds( dibdrv_physdev *dev, int count, const POINT *points, HRGN rgn )
{
const WINEREGION *region;
RECT bounds, rect;
int width = 0;
reset_bounds( &bounds );
if (dev->pen_uses_region)
{
/* Windows uses some heuristics to estimate the distance from the point that will be painted */
width = dev->pen_width + 2;
if (dev->pen_join == PS_JOIN_MITER)
{
width *= 5;
if (dev->pen_endcap == PS_ENDCAP_SQUARE) width = (width * 3 + 1) / 2;
}
else
{
if (dev->pen_endcap == PS_ENDCAP_SQUARE) width -= width / 4;
else width = (width + 1) / 2;
}
/* in case the heuristics are wrong, add the actual region too */
if ((region = get_wine_region( rgn )))
{
add_bounds_rect( &bounds, &region->extents );
release_wine_region( rgn );
}
}
while (count-- > 0)
{
rect.left = points->x - width;
rect.top = points->y - width;
rect.right = points->x + width + 1;
rect.bottom = points->y + width + 1;
add_bounds_rect( &bounds, &rect );
points++;
}
add_clipped_bounds( &dev->bounds, &bounds, dev->clip );
}
/* compute the points for the first quadrant of an ellipse, counterclockwise from the x axis */
/* 'data' must contain enough space, (width+height)/2 is a reasonable upper bound */
static int ellipse_first_quadrant( int width, int height, POINT *data )
@ -299,6 +343,7 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
reset_dash_origin( pdev );
pdev->pen_lines( pdev, count, points, extra_lines > 0, outline );
add_pen_lines_bounds( pdev, count, points, outline );
if (interior)
{
@ -384,7 +429,8 @@ static inline void get_text_bkgnd_masks( dibdrv_physdev *pdev, rop_mask *mask )
static void draw_glyph( dibdrv_physdev *pdev, const POINT *origin, const GLYPHMETRICS *metrics,
const struct gdi_image_bits *image, DWORD text_color,
const struct intensity_range *ranges, const struct clipped_rects *clipped_rects )
const struct intensity_range *ranges, const struct clipped_rects *clipped_rects,
RECT *bounds )
{
int i;
RECT rect, clipped_rect;
@ -401,6 +447,7 @@ static void draw_glyph( dibdrv_physdev *pdev, const POINT *origin, const GLYPHME
rect.top = origin->y - metrics->gmptGlyphOrigin.y;
rect.right = rect.left + metrics->gmBlackBoxX;
rect.bottom = rect.top + metrics->gmBlackBoxY;
add_bounds_rect( bounds, &rect );
for (i = 0; i < clipped_rects->count; i++)
{
@ -590,15 +637,18 @@ BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
struct clipped_rects clipped_rects;
UINT aa_flags, i;
POINT origin;
RECT bounds;
DWORD text_color, err;
struct intensity_range ranges[17];
init_clipped_rects( &clipped_rects );
reset_bounds( &bounds );
if (flags & ETO_OPAQUE)
{
rop_mask bkgnd_color;
get_text_bkgnd_masks( pdev, &bkgnd_color );
add_bounds_rect( &bounds, rect );
get_clipped_rects( &pdev->dib, rect, pdev->clip, &clipped_rects );
pdev->dib.funcs->solid_rects( &pdev->dib, clipped_rects.count, clipped_rects.rects,
bkgnd_color.and, bkgnd_color.xor );
@ -632,7 +682,9 @@ BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
err = get_glyph_bitmap( dev->hdc, (UINT)str[i], aa_flags, &metrics, &image );
if (err) continue;
if (image.ptr) draw_glyph( pdev, &origin, &metrics, &image, text_color, ranges, &clipped_rects );
if (image.ptr)
draw_glyph( pdev, &origin, &metrics, &image, text_color, ranges, &clipped_rects, &bounds );
if (image.free) image.free( &image );
if (dx)
@ -651,6 +703,7 @@ BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
origin.y += metrics.gmCellIncY;
}
}
add_clipped_bounds( &pdev->bounds, &bounds, pdev->clip );
done:
free_clipped_rects( &clipped_rects );
@ -760,6 +813,7 @@ BOOL dibdrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type )
fill_row( &pdev->dib, pdev->clip, &row, pixel, type, rgn );
add_clipped_bounds( &pdev->bounds, NULL, rgn );
brush_region( pdev, rgn );
DeleteObject( rgn );
@ -824,6 +878,7 @@ BOOL dibdrv_LineTo( PHYSDEV dev, INT x, INT y )
reset_dash_origin(pdev);
ret = pdev->pen_lines(pdev, 2, pts, FALSE, region);
add_pen_lines_bounds( pdev, 2, pts, region );
if (region)
{
@ -853,6 +908,7 @@ BOOL dibdrv_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
TRACE("(%p, %d, %d, %d, %d, %06x)\n", dev, dst->x, dst->y, dst->width, dst->height, rop);
add_bounds_rect( &pdev->bounds, &dst->visrect );
return brush_rect( pdev, &pdev->brush, &dst->visrect, pdev->clip, get_rop2_from_rop(rop) );
}
@ -864,10 +920,12 @@ BOOL dibdrv_PaintRgn( PHYSDEV dev, HRGN rgn )
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
const WINEREGION *region;
int i;
RECT rect;
RECT rect, bounds;
TRACE("%p, %p\n", dev, rgn);
reset_bounds( &bounds );
region = get_wine_region( rgn );
if(!region) return FALSE;
@ -875,10 +933,12 @@ BOOL dibdrv_PaintRgn( PHYSDEV dev, HRGN rgn )
{
rect = get_device_rect( dev->hdc, region->rects[i].left, region->rects[i].top,
region->rects[i].right, region->rects[i].bottom, FALSE );
add_bounds_rect( &bounds, &rect );
brush_rect( pdev, &pdev->brush, &rect, pdev->clip, GetROP2( dev->hdc ) );
}
release_wine_region( rgn );
add_clipped_bounds( &pdev->bounds, &bounds, pdev->clip );
return TRUE;
}
@ -927,6 +987,7 @@ BOOL dibdrv_PolyPolygon( PHYSDEV dev, const POINT *pt, const INT *counts, DWORD
pdev->pen_lines( pdev, counts[i], points + pos, TRUE, outline );
pos += counts[i];
}
add_pen_lines_bounds( pdev, total, points, outline );
if (interior)
{
@ -977,6 +1038,7 @@ BOOL dibdrv_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWO
pdev->pen_lines( pdev, counts[i], points + pos, FALSE, outline );
pos += counts[i];
}
add_pen_lines_bounds( pdev, total, points, outline );
if (outline)
{
@ -1048,6 +1110,7 @@ BOOL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
}
pdev->pen_lines(pdev, 4, pts, TRUE, outline);
add_pen_lines_bounds( pdev, 4, pts, outline );
if (outline)
{
@ -1168,6 +1231,7 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
reset_dash_origin( pdev );
pdev->pen_lines( pdev, count, points, TRUE, outline );
add_pen_lines_bounds( pdev, count, points, outline );
if (interior)
{
@ -1213,6 +1277,7 @@ COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
rect.top = pt.y;
rect.right = rect.left + 1;
rect.bottom = rect.top + 1;
add_clipped_bounds( &pdev->bounds, &rect, pdev->clip );
/* SetPixel doesn't do the 1bpp massaging like other fg colors */
pixel = get_pixel_color( pdev, color, FALSE );

View file

@ -391,10 +391,15 @@ static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr )
SetMapMode( hdc, MM_TEXT );
Rectangle( hdc, 2, 2, 4, 4 );
type = GetBoundsRect( hdc, &rect, DCB_RESET );
todo_wine
ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
"GetBoundsRect returned %d,%d,%d,%d type %x on memdc for %s\n",
rect.left, rect.top, rect.right, rect.bottom, type, descr );
if (GetObjectType( hdc ) != OBJ_MEMDC || GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASDISPLAY)
todo_wine
ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
"GetBoundsRect returned %d,%d,%d,%d type %x for %s\n",
rect.left, rect.top, rect.right, rect.bottom, type, descr );
else
ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
"GetBoundsRect returned %d,%d,%d,%d type %x for %s\n",
rect.left, rect.top, rect.right, rect.bottom, type, descr );
}
type = GetClipBox( ref_dc, &rect );
@ -451,7 +456,6 @@ static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr )
SetMapMode( hdc, MM_TEXT );
Rectangle( hdc, 5, 5, 12, 14 );
type = GetBoundsRect( hdc, &rect, DCB_RESET );
todo_wine
ok( rect.left == 5 && rect.top == 5 && rect.right == 12 && rect.bottom == 14 && type == DCB_SET,
"GetBoundsRect returned %d,%d,%d,%d type %x on memdc for %s\n",
rect.left, rect.top, rect.right, rect.bottom, type, descr );
@ -968,19 +972,16 @@ static void test_boundsrect(void)
ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 6, 6, 56, 51 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
LineTo( hdc, 300, 30 );
ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 6, 6, 256, 51 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
LineTo( hdc, -300, -300 );
ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 0, 0, 256, 51 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
/* test the wide pen heuristics */
@ -1022,7 +1023,6 @@ static void test_boundsrect(void)
expect.top = max( expect.top, 0 );
expect.right = min( expect.right, 256 );
expect.bottom = min( expect.bottom, 256 );
todo_wine
ok( EqualRect(&rect, &expect),
"Got %d,%d,%d,%d expected %d,%d,%d,%d %u/%x/%x\n",
rect.left, rect.top, rect.right, rect.bottom,

View file

@ -1260,18 +1260,10 @@ static void compare_bounds( HDC hdc, const char *info )
return;
}
if (current_bounds->left == 0 && current_bounds->top == 0 &&
current_bounds->right == 0 && current_bounds->bottom == 0)
ok( !memcmp( current_bounds, &rect, sizeof(RECT) ),
"%s: %s: expected bounds %d,%d,%d,%d got %d,%d,%d,%d\n", dst_format, info,
current_bounds->left, current_bounds->top, current_bounds->right, current_bounds->bottom,
rect.left, rect.top, rect.right, rect.bottom );
else
todo_wine
ok( !memcmp( current_bounds, &rect, sizeof(RECT) ),
"%s: %s: expected bounds %d,%d,%d,%d got %d,%d,%d,%d\n", dst_format, info,
current_bounds->left, current_bounds->top, current_bounds->right, current_bounds->bottom,
rect.left, rect.top, rect.right, rect.bottom );
ok( !memcmp( current_bounds, &rect, sizeof(RECT) ),
"%s: %s: expected bounds %d,%d,%d,%d got %d,%d,%d,%d\n", dst_format, info,
current_bounds->left, current_bounds->top, current_bounds->right, current_bounds->bottom,
rect.left, rect.top, rect.right, rect.bottom );
current_bounds++;
}