gdi32: Add bounds tracking to all the DIB engine entry points.
This commit is contained in:
parent
582a2f511f
commit
34457aa4c3
|
@ -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;
|
||||
|
|
|
@ -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, ®ion->extents );
|
||||
else if (intersect_rect( &rc, rect, ®ion->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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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, ®ion->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 );
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue