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