Commit 4266fcb2 authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Fix coordinate mapping in Get/SetBoundsRect, with tests.

parent 32c36b75
......@@ -1399,7 +1399,7 @@ HCOLORSPACE WINAPI SetColorSpace( HDC hDC, HCOLORSPACE hColorSpace )
*/
UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
{
UINT ret;
UINT ret = 0;
DC *dc = get_dc_ptr( hdc );
if ( !dc ) return 0;
......@@ -1407,18 +1407,15 @@ UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
if (rect)
{
*rect = dc->BoundsRect;
ret = ((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
ret = is_rect_empty( rect ) ? DCB_RESET : DCB_SET;
DPtoLP( hdc, (POINT *)rect, 2 );
}
else
ret = 0;
if (flags & DCB_RESET)
{
dc->BoundsRect.left = 0;
dc->BoundsRect.top = 0;
dc->BoundsRect.right = 0;
dc->BoundsRect.bottom = 0;
dc->flags &= ~DC_BOUNDS_SET;
}
release_dc_ptr( dc );
return ret;
......@@ -1437,7 +1434,7 @@ UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
if (!(dc = get_dc_ptr( hdc ))) return 0;
ret = ((dc->flags & DC_BOUNDS_ENABLE) ? DCB_ENABLE : DCB_DISABLE) |
((dc->flags & DC_BOUNDS_SET) ? DCB_SET : DCB_RESET);
(is_rect_empty( &dc->BoundsRect ) ? DCB_RESET : DCB_SET);
if (flags & DCB_RESET)
{
......@@ -1445,22 +1442,23 @@ UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
dc->BoundsRect.top = 0;
dc->BoundsRect.right = 0;
dc->BoundsRect.bottom = 0;
dc->flags &= ~DC_BOUNDS_SET;
}
if ((flags & DCB_ACCUMULATE) && rect && rect->left < rect->right && rect->top < rect->bottom)
if ((flags & DCB_ACCUMULATE) && rect)
{
if (dc->flags & DC_BOUNDS_SET)
{
dc->BoundsRect.left = min( dc->BoundsRect.left, rect->left );
dc->BoundsRect.top = min( dc->BoundsRect.top, rect->top );
dc->BoundsRect.right = max( dc->BoundsRect.right, rect->right );
dc->BoundsRect.bottom = max( dc->BoundsRect.bottom, rect->bottom );
}
else
RECT rc = *rect;
LPtoDP( hdc, (POINT *)&rc, 2 );
if (!is_rect_empty( &rc ))
{
dc->BoundsRect = *rect;
dc->flags |= DC_BOUNDS_SET;
if (!is_rect_empty( &dc->BoundsRect))
{
dc->BoundsRect.left = min( dc->BoundsRect.left, rc.left );
dc->BoundsRect.top = min( dc->BoundsRect.top, rc.top );
dc->BoundsRect.right = max( dc->BoundsRect.right, rc.right );
dc->BoundsRect.bottom = max( dc->BoundsRect.bottom, rc.bottom );
}
else dc->BoundsRect = rc;
}
}
......
......@@ -258,7 +258,6 @@ typedef struct tagDC
/* DC flags */
#define DC_BOUNDS_ENABLE 0x0008 /* Bounding rectangle tracking is enabled */
#define DC_BOUNDS_SET 0x0010 /* Bounding rectangle has been set */
/* Certain functions will do no further processing if the driver returns this.
Used by mfdrv for example. */
......
......@@ -30,6 +30,8 @@
#include "winuser.h"
#include "winerror.h"
static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
static void dump_region(HRGN hrgn)
{
DWORD i, size;
......@@ -500,70 +502,148 @@ todo_wine
ok(ret, "UnregisterClassA failed\n");
}
static void test_boundsrect_invalid(void)
static void test_boundsrect(void)
{
HDC hdc;
HBITMAP bitmap;
RECT rect, expect, set_rect;
UINT ret;
hdc = GetDC(NULL);
ok(hdc != NULL, "GetDC failed\n");
hdc = CreateCompatibleDC(0);
ok(hdc != NULL, "CreateCompatibleDC failed\n");
bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
SelectObject( hdc, bitmap );
ret = GetBoundsRect(hdc, NULL, 0);
ok(ret == 0 ||
broken(ret == DCB_RESET), /* Win9x */
"Expected GetBoundsRect to return 0, got %u\n", ret);
ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
ret = GetBoundsRect(hdc, NULL, ~0U);
ok(ret == 0 ||
broken(ret == DCB_RESET), /* Win9x */
ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
/* Test parameter handling order. */
SetRect(&set_rect, 10, 20, 40, 50);
ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
ok(ret & DCB_RESET,
"Expected return flag DCB_RESET to be set, got %u\n", ret);
ret = GetBoundsRect(hdc, NULL, DCB_RESET);
ok(ret == 0,
"Expected GetBoundsRect to return 0, got %u\n", ret);
if (GetBoundsRect(hdc, NULL, 0) == DCB_RESET)
win_skip("Win9x fails catastrophically with first GetBoundsRect call\n");
else
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_RESET,
"Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
SetRect(&expect, 0, 0, 0, 0);
ok(EqualRect(&rect, &expect) ||
broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
"Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
ret = GetBoundsRect(NULL, NULL, 0);
ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
ret = GetBoundsRect(NULL, NULL, ~0U);
ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
ret = SetBoundsRect(NULL, NULL, 0);
ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
ret = SetBoundsRect(NULL, NULL, ~0U);
ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
SetRect(&set_rect, 10, 20, 40, 50);
ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 10, 20, 40, 50);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
SetMapMode( hdc, MM_ANISOTROPIC );
SetViewportExtEx( hdc, 2, 2, NULL );
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 5, 10, 20, 25);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
SetViewportOrgEx( hdc, 20, 30, NULL );
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, -5, -5, 10, 10);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
SetRect(&set_rect, 10, 20, 40, 50);
ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 10, 20, 40, 50);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
SetMapMode( hdc, MM_TEXT );
SetViewportOrgEx( hdc, 0, 0, NULL );
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 40, 70, 100, 130);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
if (pSetLayout)
{
/* Test parameter handling order. */
SetRect(&set_rect, 10, 20, 40, 50);
pSetLayout( hdc, LAYOUT_RTL );
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 159, 70, 99, 130);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
SetRect(&set_rect, 50, 25, 30, 35);
ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
ok(ret & DCB_RESET,
"Expected return flag DCB_RESET to be set, got %u\n", ret);
ret = GetBoundsRect(hdc, NULL, DCB_RESET);
ok(ret == 0,
"Expected GetBoundsRect to return 0, got %u\n", ret);
ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 50, 25, 30, 35);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
pSetLayout( hdc, LAYOUT_LTR );
ret = GetBoundsRect(hdc, &rect, 0);
if (ret != DCB_SET) /* WinME */
{
ok(ret == DCB_RESET,
"Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
SetRect(&expect, 0, 0, 0, 0);
ok(EqualRect(&rect, &expect) ||
broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
"Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
}
ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 149, 25, 169, 35);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
}
if (GetBoundsRect(hdc, NULL, 0) == DCB_RESET)
win_skip("Win9x fails catastrophically with NULL device context parameter\n");
else
/* empty rect resets, except on nt4 */
SetRect(&expect, 20, 20, 10, 10);
ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_RESET || broken(ret == DCB_SET) /* nt4 */,
"GetBoundsRect returned %x\n", ret);
if (ret == DCB_RESET)
{
ret = GetBoundsRect(NULL, NULL, 0);
ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
ret = GetBoundsRect(NULL, NULL, ~0U);
ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
SetRect(&expect, 0, 0, 0, 0);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
ret = SetBoundsRect(NULL, NULL, 0);
ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
ret = SetBoundsRect(NULL, NULL, ~0U);
ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
SetRect(&expect, 20, 20, 20, 20);
ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 0, 0, 0, 0);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
}
ReleaseDC(NULL, hdc);
DeleteDC( hdc );
DeleteObject( bitmap );
}
static void test_desktop_colorres(void)
......@@ -661,13 +741,14 @@ done:
START_TEST(dc)
{
pSetLayout = (void *)GetProcAddress( GetModuleHandle("gdi32.dll"), "SetLayout");
test_savedc();
test_savedc_2();
test_GdiConvertToDevmodeW();
test_CreateCompatibleDC();
test_DC_bitmap();
test_DeleteDC();
test_boundsrect_invalid();
test_boundsrect();
test_desktop_colorres();
test_gamma();
}
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