diff --git a/rostests/winetests/gdi32/bitmap.c b/rostests/winetests/gdi32/bitmap.c index a0d4531d511..517033c6887 100755 --- a/rostests/winetests/gdi32/bitmap.c +++ b/rostests/winetests/gdi32/bitmap.c @@ -780,7 +780,9 @@ static void test_dibsections(void) BitBlt(hdcmem2, 0, 0, 16,16, hdcmem, 0, 0, SRCCOPY); ok(bits32[0] == 0xff00, "lower left pixel is %08x\n", bits32[0]); - ok(bits32[17] == 0xff00ff, "bottom but one, left pixel is %08x\n", bits32[17]); + ok(bits32[17] == 0xff00ff || + broken(bits32[17] == 0x00ff00), /* Intermittent on Win9x/ME */ + "bottom but one, left pixel is %08x\n", bits32[17]); SelectObject(hdcmem2, oldbm2); test_dib_info(hdib2, bits32, &pbmi->bmiHeader); @@ -1954,7 +1956,9 @@ static void test_select_object(void) ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong bmWidthBytes %d\n", bm.bmWidthBytes); ok(bm.bmPlanes == planes, "wrong bmPlanes %u\n", bm.bmPlanes); if(depths[i] == 15) { - ok(bm.bmBitsPixel == 16, "wrong bmBitsPixel %d(15 bpp special)\n", bm.bmBitsPixel); + ok(bm.bmBitsPixel == 16 || + broken(bm.bmBitsPixel == 15), /* Win9x/WinME */ + "wrong bmBitsPixel %d(15 bpp special)\n", bm.bmBitsPixel); } else { ok(bm.bmBitsPixel == depths[i], "wrong bmBitsPixel %d\n", bm.bmBitsPixel); } @@ -2248,6 +2252,469 @@ static void test_get16dibits(void) ReleaseDC(NULL, screen_dc); } +static BOOL compare_buffers_no_alpha(UINT32 *a, UINT32 *b, int length) +{ + int i; + for(i = 0; i < length; i++) + if((a[i] & 0x00FFFFFF) != (b[i] & 0x00FFFFFF)) + return FALSE; + return TRUE; +} + +static void check_BitBlt_pixel(HDC hdcDst, HDC hdcSrc, UINT32 *dstBuffer, UINT32 *srcBuffer, + DWORD dwRop, UINT32 expected, int line) +{ + *srcBuffer = 0xFEDCBA98; + *dstBuffer = 0x89ABCDEF; + Rectangle(hdcSrc, 0, 0, 1, 1); /* A null operation to ensure dibs are coerced to X11 */ + BitBlt(hdcDst, 0, 0, 1, 1, hdcSrc, 0, 0, dwRop); + ok(expected == *dstBuffer, + "BitBlt with dwRop %06X. Expected 0x%08X, got 0x%08X from line %d\n", + dwRop, expected, *dstBuffer, line); +} + +static void test_BitBlt(void) +{ + HBITMAP bmpDst, bmpSrc; + HBITMAP oldDst, oldSrc; + HDC hdcScreen, hdcDst, hdcSrc; + UINT32 *dstBuffer, *srcBuffer; + HBRUSH hBrush, hOldBrush; + BITMAPINFO bitmapInfo; + + memset(&bitmapInfo, 0, sizeof(BITMAPINFO)); + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = 1; + bitmapInfo.bmiHeader.biHeight = 1; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biBitCount = 32; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32); + + hdcScreen = CreateCompatibleDC(0); + hdcDst = CreateCompatibleDC(hdcScreen); + hdcSrc = CreateCompatibleDC(hdcDst); + + /* Setup the destination dib section */ + bmpDst = CreateDIBSection(hdcScreen, &bitmapInfo, DIB_RGB_COLORS, (void**)&dstBuffer, + NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + hBrush = CreateSolidBrush(0x012345678); + hOldBrush = SelectObject(hdcDst, hBrush); + + /* Setup the source dib section */ + bmpSrc = CreateDIBSection(hdcScreen, &bitmapInfo, DIB_RGB_COLORS, (void**)&srcBuffer, + NULL, 0); + oldSrc = SelectObject(hdcSrc, bmpSrc); + + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCCOPY, 0xFEDCBA98, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCPAINT, 0xFFFFFFFF, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCAND, 0x88888888, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCINVERT, 0x77777777, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCERASE, 0x76543210, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCCOPY, 0x01234567, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCERASE, 0x00000000, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGECOPY, 0x00581210, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGEPAINT, 0x89ABCDEF, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATCOPY, 0x00785634, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATPAINT, 0x89FBDFFF, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATINVERT, 0x89D39BDB, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, DSTINVERT, 0x76543210, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, BLACKNESS, 0x00000000, __LINE__); + check_BitBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, WHITENESS, 0xFFFFFFFF, __LINE__); + + /* Tidy up */ + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + DeleteDC(hdcSrc); + + SelectObject(hdcDst, hOldBrush); + DeleteObject(hBrush); + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + DeleteDC(hdcDst); + + + DeleteDC(hdcScreen); +} + +static void check_StretchBlt_pixel(HDC hdcDst, HDC hdcSrc, UINT32 *dstBuffer, UINT32 *srcBuffer, + DWORD dwRop, UINT32 expected, int line) +{ + *srcBuffer = 0xFEDCBA98; + *dstBuffer = 0x89ABCDEF; + StretchBlt(hdcDst, 0, 0, 2, 1, hdcSrc, 0, 0, 1, 1, dwRop); + ok(expected == *dstBuffer, + "StretchBlt with dwRop %06X. Expected 0x%08X, got 0x%08X from line %d\n", + dwRop, expected, *dstBuffer, line); +} + +static void check_StretchBlt_stretch(HDC hdcDst, HDC hdcSrc, UINT32 *dstBuffer, UINT32 *srcBuffer, + int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, + int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, + UINT32 expected[4], UINT32 legacy_expected[4], int line) +{ + memset(dstBuffer, 0, 16); + StretchBlt(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, + hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY); + ok(memcmp(dstBuffer, expected, 16) == 0 || + broken(compare_buffers_no_alpha(dstBuffer, legacy_expected, 4)), + "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X } " + "stretching { %d, %d, %d, %d } to { %d, %d, %d, %d } from line %d\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3], + nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, + nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, line); +} + +static void test_StretchBlt(void) +{ + HBITMAP bmpDst, bmpSrc; + HBITMAP oldDst, oldSrc; + HDC hdcScreen, hdcDst, hdcSrc; + UINT32 *dstBuffer, *srcBuffer; + HBRUSH hBrush, hOldBrush; + BITMAPINFO biDst, biSrc; + UINT32 expected[4], legacy_expected[4]; + + memset(&biDst, 0, sizeof(BITMAPINFO)); + biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + biDst.bmiHeader.biWidth = 2; + biDst.bmiHeader.biHeight = -2; + biDst.bmiHeader.biPlanes = 1; + biDst.bmiHeader.biBitCount = 32; + biDst.bmiHeader.biCompression = BI_RGB; + memcpy(&biSrc, &biDst, sizeof(BITMAPINFO)); + + hdcScreen = CreateCompatibleDC(0); + hdcDst = CreateCompatibleDC(hdcScreen); + hdcSrc = CreateCompatibleDC(hdcDst); + + /* Pixel Tests */ + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, + NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + bmpSrc = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&srcBuffer, + NULL, 0); + oldSrc = SelectObject(hdcSrc, bmpSrc); + + hBrush = CreateSolidBrush(0x012345678); + hOldBrush = SelectObject(hdcDst, hBrush); + + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCCOPY, 0xFEDCBA98, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCPAINT, 0xFFFFFFFF, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCAND, 0x88888888, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCINVERT, 0x77777777, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, SRCERASE, 0x76543210, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCCOPY, 0x01234567, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, NOTSRCERASE, 0x00000000, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGECOPY, 0x00581210, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, MERGEPAINT, 0x89ABCDEF, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATCOPY, 0x00785634, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATPAINT, 0x89FBDFFF, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, PATINVERT, 0x89D39BDB, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, DSTINVERT, 0x76543210, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, BLACKNESS, 0x00000000, __LINE__); + check_StretchBlt_pixel(hdcDst, hdcSrc, dstBuffer, srcBuffer, WHITENESS, 0xFFFFFFFF, __LINE__); + + SelectObject(hdcDst, hOldBrush); + DeleteObject(hBrush); + + /* Top-down to top-down tests */ + srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE; + srcBuffer[2] = 0xFEDCBA98, srcBuffer[3] = 0x76543210; + + expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE; + expected[2] = 0xFEDCBA98, expected[3] = 0x76543210; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + expected[0] = 0xCAFED00D, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0x00000000; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 1, 1, expected, expected, __LINE__); + + expected[0] = 0xCAFED00D, expected[1] = 0xCAFED00D; + expected[2] = 0xCAFED00D, expected[3] = 0xCAFED00D; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 1, 1, expected, expected, __LINE__); + + expected[0] = 0xCAFED00D, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0x00000000; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 2, 2, expected, expected, __LINE__); + + expected[0] = 0x76543210, expected[1] = 0xFEDCBA98; + expected[2] = 0xFEEDFACE, expected[3] = 0xCAFED00D; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__); + + expected[0] = 0x76543210, expected[1] = 0xFEDCBA98; + expected[2] = 0xFEEDFACE, expected[3] = 0xCAFED00D; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 1, 1, -2, -2, 0, 0, 2, 2, expected, expected, __LINE__); + + /* This result seems broken. One might expect the following result: + * 0xCAFED00D 0xFEEDFACE + * 0xFEDCBA98 0x76543210 + */ + expected[0] = 0xCAFED00D, expected[1] = 0x00000000; + expected[2] = 0xFEDCBA98, expected[3] = 0x76543210; + legacy_expected[0] = 0xCAFED00D, legacy_expected[1] = 0x00000000; + legacy_expected[2] = 0x00000000, legacy_expected[3] = 0x00000000; + todo_wine check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 1, 1, -2, -2, 1, 1, -2, -2, expected, + legacy_expected, __LINE__); + + expected[0] = 0x00000000, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0xCAFED00D; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 1, 1, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + + /* Top-down to bottom-up tests */ + biDst.bmiHeader.biHeight = 2; + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, + NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + expected[0] = 0xFEDCBA98, expected[1] = 0x76543210; + expected[2] = 0xCAFED00D, expected[3] = 0xFEEDFACE; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D; + expected[2] = 0x76543210, expected[3] = 0xFEDCBA98; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + + /* Bottom-up to bottom-up tests */ + biSrc.bmiHeader.biHeight = 2; + bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, + NULL, 0); + srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE; + srcBuffer[2] = 0xFEDCBA98, srcBuffer[3] = 0x76543210; + oldSrc = SelectObject(hdcSrc, bmpSrc); + + expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE; + expected[2] = 0xFEDCBA98, expected[3] = 0x76543210; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + expected[0] = 0x76543210, expected[1] = 0xFEDCBA98; + expected[2] = 0xFEEDFACE, expected[3] = 0xCAFED00D; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + + /* Bottom-up to top-down tests */ + biDst.bmiHeader.biHeight = -2; + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, + NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + expected[0] = 0xFEDCBA98, expected[1] = 0x76543210; + expected[2] = 0xCAFED00D, expected[3] = 0xFEEDFACE; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + expected[0] = 0xFEEDFACE, expected[1] = 0xCAFED00D; + expected[2] = 0x76543210, expected[3] = 0xFEDCBA98; + check_StretchBlt_stretch(hdcDst, hdcSrc, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__); + + /* Tidy up */ + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + DeleteDC(hdcSrc); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + DeleteDC(hdcDst); + + DeleteDC(hdcScreen); +} + +static void check_StretchDIBits_pixel(HDC hdcDst, UINT32 *dstBuffer, UINT32 *srcBuffer, + DWORD dwRop, UINT32 expected, int line) +{ + const UINT32 buffer[2] = { 0xFEDCBA98, 0 }; + BITMAPINFO bitmapInfo; + + memset(&bitmapInfo, 0, sizeof(BITMAPINFO)); + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = 2; + bitmapInfo.bmiHeader.biHeight = 1; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biBitCount = 32; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + bitmapInfo.bmiHeader.biSizeImage = sizeof(buffer); + + *dstBuffer = 0x89ABCDEF; + + StretchDIBits(hdcDst, 0, 0, 2, 1, 0, 0, 1, 1, &buffer, &bitmapInfo, DIB_RGB_COLORS, dwRop); + ok(expected == *dstBuffer, + "StretchDIBits with dwRop %06X. Expected 0x%08X, got 0x%08X from line %d\n", + dwRop, expected, *dstBuffer, line); +} + +static void check_StretchDIBits_stretch(HDC hdcDst, UINT32 *dstBuffer, UINT32 *srcBuffer, + int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, + int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, + UINT32 expected[4], UINT32 legacy_expected[4], int line) +{ + BITMAPINFO bitmapInfo; + + memset(&bitmapInfo, 0, sizeof(BITMAPINFO)); + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = 2; + bitmapInfo.bmiHeader.biHeight = -2; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biBitCount = 32; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + + memset(dstBuffer, 0, 16); + StretchDIBits(hdcDst, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, + nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, + srcBuffer, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY); + ok(memcmp(dstBuffer, expected, 16) == 0 || /* Win2k/XP */ + broken(compare_buffers_no_alpha(dstBuffer, legacy_expected, 4)) || /* Win9X/ME */ + broken(nWidthSrc < 0 || nHeightSrc < 0), /* Win9X/ME */ + "StretchDIBits expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X } " + "stretching { %d, %d, %d, %d } to { %d, %d, %d, %d } from line %d\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3], + nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, + nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, line); +} + +static void test_StretchDIBits(void) +{ + HBITMAP bmpDst; + HBITMAP oldDst; + HDC hdcScreen, hdcDst; + UINT32 *dstBuffer, srcBuffer[4]; + HBRUSH hBrush, hOldBrush; + BITMAPINFO biDst; + UINT32 expected[4], legacy_expected[4]; + + memset(&biDst, 0, sizeof(BITMAPINFO)); + biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + biDst.bmiHeader.biWidth = 2; + biDst.bmiHeader.biHeight = -2; + biDst.bmiHeader.biPlanes = 1; + biDst.bmiHeader.biBitCount = 32; + biDst.bmiHeader.biCompression = BI_RGB; + + hdcScreen = CreateCompatibleDC(0); + hdcDst = CreateCompatibleDC(hdcScreen); + + /* Pixel Tests */ + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, + NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + hBrush = CreateSolidBrush(0x012345678); + hOldBrush = SelectObject(hdcDst, hBrush); + + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCCOPY, 0xFEDCBA98, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCPAINT, 0xFFFFFFFF, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCAND, 0x88888888, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCINVERT, 0x77777777, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, SRCERASE, 0x76543210, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, NOTSRCCOPY, 0x01234567, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, NOTSRCERASE, 0x00000000, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, MERGECOPY, 0x00581210, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, MERGEPAINT, 0x89ABCDEF, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, PATCOPY, 0x00785634, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, PATPAINT, 0x89FBDFFF, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, PATINVERT, 0x89D39BDB, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, DSTINVERT, 0x76543210, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, BLACKNESS, 0x00000000, __LINE__); + check_StretchDIBits_pixel(hdcDst, dstBuffer, srcBuffer, WHITENESS, 0xFFFFFFFF, __LINE__); + + SelectObject(hdcDst, hOldBrush); + DeleteObject(hBrush); + + /* Top-down destination tests */ + srcBuffer[0] = 0xCAFED00D, srcBuffer[1] = 0xFEEDFACE; + srcBuffer[2] = 0xFEDCBA98, srcBuffer[3] = 0x76543210; + + expected[0] = 0xCAFED00D, expected[1] = 0xFEEDFACE; + expected[2] = 0xFEDCBA98, expected[3] = 0x76543210; + check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + expected[0] = 0xCAFED00D, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0x00000000; + legacy_expected[0] = 0xFEDCBA98, legacy_expected[1] = 0x00000000; + legacy_expected[2] = 0x00000000, legacy_expected[3] = 0x00000000; + todo_wine check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 1, 1, expected, legacy_expected, __LINE__); + + expected[0] = 0xFEDCBA98, expected[1] = 0xFEDCBA98; + expected[2] = 0xFEDCBA98, expected[3] = 0xFEDCBA98; + check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 1, 1, expected, expected, __LINE__); + + expected[0] = 0x42441000, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0x00000000; + legacy_expected[0] = 0x00543210, legacy_expected[1] = 0x00000000; + legacy_expected[2] = 0x00000000, legacy_expected[3] = 0x00000000; + todo_wine check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 0, 0, 1, 1, 0, 0, 2, 2, expected, legacy_expected, __LINE__); + + expected[0] = 0x00000000, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0x00000000; + check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__); + + expected[0] = 0x00000000, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0x00000000; + check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 1, 1, -2, -2, expected, expected, __LINE__); + + expected[0] = 0x00000000, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0x00000000; + check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 1, 1, -2, -2, 1, 1, -2, -2, expected, expected, __LINE__); + + expected[0] = 0x00000000, expected[1] = 0x00000000; + expected[2] = 0x00000000, expected[3] = 0xCAFED00D; + check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 1, 1, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + + /* Bottom up destination tests */ + biDst.bmiHeader.biHeight = 2; + bmpDst = CreateDIBSection(hdcScreen, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, + NULL, 0); + oldDst = SelectObject(hdcDst, bmpDst); + + expected[0] = 0xFEDCBA98, expected[1] = 0x76543210; + expected[2] = 0xCAFED00D, expected[3] = 0xFEEDFACE; + check_StretchDIBits_stretch(hdcDst, dstBuffer, srcBuffer, + 0, 0, 2, 2, 0, 0, 2, 2, expected, expected, __LINE__); + + /* Tidy up */ + SelectObject(hdcDst, oldDst); + DeleteObject(bmpDst); + DeleteDC(hdcDst); + + DeleteDC(hdcScreen); +} + static void test_GdiAlphaBlend(void) { /* test out-of-bound parameters for GdiAlphaBlend */ @@ -2311,6 +2778,10 @@ static void test_GdiAlphaBlend(void) expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, -1, 0, 30, 30, blend), TRUE, BOOL, "%d"); expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 0, -1, 30, 30, blend), TRUE, BOOL, "%d"); + SetLastError(0xdeadbeef); + expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, NULL, 0, 0, 20, 20, blend), FALSE, BOOL, "%d"); + expect_eq(GetLastError(), 0xdeadbeef, int, "%d"); + SelectObject(hdcDst, oldDst); SelectObject(hdcSrc, oldSrc); DeleteObject(bmpSrc); @@ -2389,6 +2860,9 @@ START_TEST(bitmap) test_GetDIBits_BI_BITFIELDS(); test_select_object(); test_CreateBitmap(); + test_BitBlt(); + test_StretchBlt(); + test_StretchDIBits(); test_GdiAlphaBlend(); test_bitmapinfoheadersize(); test_get16dibits(); diff --git a/rostests/winetests/gdi32/clipping.c b/rostests/winetests/gdi32/clipping.c index eff87c3c463..06cb22a03c5 100644 --- a/rostests/winetests/gdi32/clipping.c +++ b/rostests/winetests/gdi32/clipping.c @@ -189,13 +189,13 @@ static void test_ExtCreateRegion(void) HRGN hrgn; XFORM xform; -if (0) /* crashes under Win9x */ -{ - SetLastError(0xdeadbeef); - hrgn = ExtCreateRegion(NULL, 0, NULL); - ok(!hrgn, "ExtCreateRegion should fail\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, "ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); -} + if (0) /* crashes under Win9x */ + { + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, 0, NULL); + ok(!hrgn, "ExtCreateRegion should fail\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + } rgn.data.rdh.dwSize = 0; rgn.data.rdh.iType = 0; diff --git a/rostests/winetests/gdi32/font.c b/rostests/winetests/gdi32/font.c index b92a2295440..bd0574a4eba 100644 --- a/rostests/winetests/gdi32/font.c +++ b/rostests/winetests/gdi32/font.c @@ -2175,7 +2175,7 @@ static void get_seg4(cmap_format_4 *cmap, USHORT seg_num, cmap_format_4_seg *seg seg->id_range_offset = GET_BE_WORD(cmap->end_count[3 * segs + 1 + seg_num]); } -static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last) +static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last, DWORD limit) { int i; cmap_format_4 *cmap = (cmap_format_4*)ptr; @@ -2200,7 +2200,15 @@ static BOOL get_first_last_from_cmap4(void *ptr, DWORD *first, DWORD *last) + code - seg.start_count + i - seg_count; - index = GET_BE_WORD(glyph_ids[index]); + /* some fonts have broken last segment */ + if ((char *)(glyph_ids + index + sizeof(*glyph_ids)) < (char *)ptr + limit) + index = GET_BE_WORD(glyph_ids[index]); + else + { + trace("segment %04x/%04x index %04x points to nowhere\n", + seg.start_count, seg.end_count, index); + index = 0; + } if(index) index += seg.id_delta; } if(*first == 0x10000) @@ -2273,7 +2281,7 @@ static BOOL get_first_last_from_cmap(HDC hdc, DWORD *first, DWORD *last, cmap_ty r = get_first_last_from_cmap0(cmap, first, last); break; case 4: - r = get_first_last_from_cmap4(cmap, first, last); + r = get_first_last_from_cmap4(cmap, first, last, size); break; default: trace("unhandled cmap format %d\n", format); @@ -2914,10 +2922,67 @@ static void test_GetGlyphOutline(void) DeleteDC(hdc); } +/* bug #9995: there is a limit to the character width that can be specified */ +static void test_GetTextMetrics2(const char *fontname, int font_height) +{ + HFONT of, hf; + HDC hdc; + TEXTMETRICA tm; + BOOL ret; + int ave_width, height, width, ratio, scale; + + if (!is_truetype_font_installed( fontname)) { + skip("%s is not installed\n", fontname); + return; + } + hdc = CreateCompatibleDC(0); + ok( hdc != NULL, "CreateCompatibleDC failed\n"); + /* select width = 0 */ + hf = CreateFontA(font_height, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, + DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES, + DEFAULT_QUALITY, VARIABLE_PITCH, + fontname); + ok( hf != NULL, "CreateFontA failed\n"); + of = SelectObject( hdc, hf); + ret = GetTextMetricsA( hdc, &tm); + ok(ret, "GetTextMetricsA error %u\n", GetLastError()); + height = tm.tmHeight; + ave_width = tm.tmAveCharWidth; + SelectObject( hdc, of); + DeleteObject( hf); + + trace("height %d, ave width %d\n", height, ave_width); + + for (width = ave_width * 2; /* nothing*/; width += ave_width) + { + hf = CreateFont(height, width, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, + DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_LH_ANGLES, + DEFAULT_QUALITY, VARIABLE_PITCH, fontname); + ok(hf != 0, "CreateFont failed\n"); + of = SelectObject(hdc, hf); + ret = GetTextMetrics(hdc, &tm); + ok(ret, "GetTextMetrics error %u\n", GetLastError()); + SelectObject(hdc, of); + DeleteObject(hf); + + if (tm.tmAveCharWidth == ave_width || width / height > 200) + break; + } + + DeleteDC(hdc); + + ratio = width / height; + scale = width / ave_width; + + trace("max width/height ratio (%d / %d) %d, max width scale (%d / %d) %d\n", + width, height, ratio, width, ave_width, scale); + + ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio); +} + START_TEST(font) { init(); - test_logfont(); test_bitmap_font(); test_outline_font(); @@ -2952,4 +3017,10 @@ START_TEST(font) test_GdiRealizationInfo(); test_GetTextFace(); test_GetGlyphOutline(); + test_GetTextMetrics2("Tahoma", -11); + test_GetTextMetrics2("Tahoma", -55); + test_GetTextMetrics2("Tahoma", -110); + test_GetTextMetrics2("Arial", -11); + test_GetTextMetrics2("Arial", -55); + test_GetTextMetrics2("Arial", -110); } diff --git a/rostests/winetests/gdi32/gdiobj.c b/rostests/winetests/gdi32/gdiobj.c index 67a135e3cb9..c1adc0f57f9 100755 --- a/rostests/winetests/gdi32/gdiobj.c +++ b/rostests/winetests/gdi32/gdiobj.c @@ -266,9 +266,49 @@ static void test_GetCurrentObject(void) DeleteDC(hdc); } +static void test_region(void) +{ + HRGN hrgn = CreateRectRgn(10, 10, 20, 20); + RECT rc = { 5, 5, 15, 15 }; + BOOL ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + /* swap left and right */ + SetRect( &rc, 15, 5, 5, 15 ); + ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + /* swap top and bottom */ + SetRect( &rc, 5, 15, 15, 5 ); + ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + /* swap both */ + SetRect( &rc, 15, 15, 5, 5 ); + ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + DeleteObject(hrgn); + /* swap left and right in the region */ + hrgn = CreateRectRgn(20, 10, 10, 20); + SetRect( &rc, 5, 5, 15, 15 ); + ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + /* swap left and right */ + SetRect( &rc, 15, 5, 5, 15 ); + ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + /* swap top and bottom */ + SetRect( &rc, 5, 15, 15, 5 ); + ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + /* swap both */ + SetRect( &rc, 15, 15, 5, 5 ); + ret = RectInRegion( hrgn, &rc); + ok( ret, "RectInRegion should return TRUE\n"); + DeleteObject(hrgn); +} + START_TEST(gdiobj) { test_gdi_objects(); test_thread_objects(); test_GetCurrentObject(); + test_region(); } diff --git a/rostests/winetests/gdi32/mapping.c b/rostests/winetests/gdi32/mapping.c index 03428174617..8c53e2fea87 100644 --- a/rostests/winetests/gdi32/mapping.c +++ b/rostests/winetests/gdi32/mapping.c @@ -342,9 +342,227 @@ static void test_isotropic_mapping(void) ReleaseDC(0, hdc); } +static void test_setvirtualresolution(void) +{ + HDC hdc = CreateICA("DISPLAY", NULL, NULL, NULL); + DWORD r; + DWORD (WINAPI *pSetVirtualResolution)(HDC, DWORD, DWORD, DWORD, DWORD); + INT horz_res = GetDeviceCaps(hdc, HORZRES); + INT horz_size = GetDeviceCaps(hdc, HORZSIZE); + INT log_pixels_x = GetDeviceCaps(hdc, LOGPIXELSX); + SIZE orig_lometric_vp, orig_lometric_wnd; + + pSetVirtualResolution = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "SetVirtualResolution"); + + if(!pSetVirtualResolution) + { + win_skip("Don't have SetVirtualResolution\n"); + return; + } + + /* Get the true resolution limits */ + SetMapMode(hdc, MM_LOMETRIC); + GetViewportExtEx(hdc, &orig_lometric_vp); + GetWindowExtEx(hdc, &orig_lometric_wnd); + SetMapMode(hdc, MM_TEXT); + + r = pSetVirtualResolution(hdc, 4000, 1000, 400, 200); /* 10 pix/mm x 5 pix/mm */ + ok(r == TRUE, "got %d\n", r); + expect_LPtoDP(hdc, 1000, 1000); + expect_viewport_ext(hdc, 1, 1); + expect_window_ext(hdc, 1, 1); + + SetMapMode(hdc, MM_LOMETRIC); + expect_LPtoDP(hdc, 1000, -500); + expect_viewport_ext(hdc, 4000, -1000); + expect_window_ext(hdc, 4000, 2000); + + /* Doesn't change the device caps */ + ok(horz_res == GetDeviceCaps(hdc, HORZRES), "horz_res changed\n"); + ok(horz_size == GetDeviceCaps(hdc, HORZSIZE), "horz_size changed\n"); + ok(log_pixels_x == GetDeviceCaps(hdc, LOGPIXELSX), "log_pixels_x changed\n"); + + r = pSetVirtualResolution(hdc, 8000, 1000, 400, 200); /* 20 pix/mm x 5 pix/mm */ + ok(r == TRUE, "got %d\n", r); + expect_LPtoDP(hdc, 1000, -500); /* No change, need to re-set the mapping mode */ + SetMapMode(hdc, MM_TEXT); + SetMapMode(hdc, MM_LOMETRIC); + expect_LPtoDP(hdc, 2000, -500); + expect_viewport_ext(hdc, 8000, -1000); + expect_window_ext(hdc, 4000, 2000); + + r = pSetVirtualResolution(hdc, 8000, 1000, 200, 200); /* 40 pix/mm x 5 pix/mm */ + ok(r == TRUE, "got %d\n", r); + SetMapMode(hdc, MM_TEXT); + SetMapMode(hdc, MM_LOMETRIC); + expect_LPtoDP(hdc, 4000, -500); + expect_viewport_ext(hdc, 8000, -1000); + expect_window_ext(hdc, 2000, 2000); + + r = pSetVirtualResolution(hdc, 8000, 1000, 200, 200); /* 40 pix/mm x 5 pix/mm */ + ok(r == TRUE, "got %d\n", r); + SetMapMode(hdc, MM_TEXT); + SetMapMode(hdc, MM_LOMETRIC); + expect_LPtoDP(hdc, 4000, -500); + expect_viewport_ext(hdc, 8000, -1000); + expect_window_ext(hdc, 2000, 2000); + + r = pSetVirtualResolution(hdc, 8000, 2000, 200, 200); /* 40 pix/mm x 10 pix/mm */ + ok(r == TRUE, "got %d\n", r); + SetMapMode(hdc, MM_TEXT); + SetMapMode(hdc, MM_LOMETRIC); + expect_LPtoDP(hdc, 4000, -1000); + expect_viewport_ext(hdc, 8000, -2000); + expect_window_ext(hdc, 2000, 2000); + + r = pSetVirtualResolution(hdc, 0, 0, 10, 0); /* Error */ + ok(r == FALSE, "got %d\n", r); + SetMapMode(hdc, MM_TEXT); + SetMapMode(hdc, MM_LOMETRIC); + expect_LPtoDP(hdc, 4000, -1000); + expect_viewport_ext(hdc, 8000, -2000); + expect_window_ext(hdc, 2000, 2000); + + r = pSetVirtualResolution(hdc, 0, 0, 0, 0); /* Reset to true resolution */ + ok(r == TRUE, "got %d\n", r); + SetMapMode(hdc, MM_TEXT); + SetMapMode(hdc, MM_LOMETRIC); + expect_viewport_ext(hdc, orig_lometric_vp.cx, orig_lometric_vp.cy); + expect_window_ext(hdc, orig_lometric_wnd.cx, orig_lometric_wnd.cy); + + DeleteDC(hdc); +} + + +static inline void expect_identity(int line, XFORM *xf) +{ + ok(xf->eM11 == 1.0, "%d: got %f\n", line, xf->eM11); + ok(xf->eM12 == 0.0, "%d: got %f\n", line, xf->eM12); + ok(xf->eM21 == 0.0, "%d: got %f\n", line, xf->eM21); + ok(xf->eM22 == 1.0, "%d: got %f\n", line, xf->eM22); + ok(xf->eDx == 0.0, "%d: got %f\n", line, xf->eDx); + ok(xf->eDy == 0.0, "%d: got %f\n", line, xf->eDy); +} + +static inline void xform_near_match(int line, XFORM *got, XFORM *expect) +{ + ok(fabs(got->eM11 - expect->eM11) < 0.001, "%d: got %f expect %f\n", line, got->eM11, expect->eM11); + ok(fabs(got->eM12 - expect->eM12) < 0.001, "%d: got %f expect %f\n", line, got->eM12, expect->eM12); + ok(fabs(got->eM21 - expect->eM21) < 0.001, "%d: got %f expect %f\n", line, got->eM21, expect->eM21); + ok(fabs(got->eM22 - expect->eM22) < 0.001, "%d: got %f expect %f\n", line, got->eM22, expect->eM22); + ok(fabs(got->eDx - expect->eDx) < 0.001, "%d: got %f expect %f\n", line, got->eDx, expect->eDx); + ok(fabs(got->eDy - expect->eDy) < 0.001, "%d: got %f expect %f\n", line, got->eDy, expect->eDy); +} + + +static void test_gettransform(void) +{ + HDC hdc = CreateICA("DISPLAY", NULL, NULL, NULL); + BOOL (WINAPI *pGetTransform)(HDC, DWORD, XFORM *); + XFORM xform, expect; + BOOL r; + SIZE lometric_vp, lometric_wnd; + + pGetTransform = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GetTransform"); + + if(!pGetTransform) + { + win_skip("Don't have GetTransform\n"); + return; + } + + r = pGetTransform(hdc, 0x203, &xform); /* World -> Page */ + ok(r == TRUE, "got %d\n", r); + expect_identity(__LINE__, &xform); + r = pGetTransform(hdc, 0x304, &xform); /* Page -> Device */ + ok(r == TRUE, "got %d\n", r); + expect_identity(__LINE__, &xform); + r = pGetTransform(hdc, 0x204, &xform); /* World -> Device */ + ok(r == TRUE, "got %d\n", r); + expect_identity(__LINE__, &xform); + r = pGetTransform(hdc, 0x402, &xform); /* Device -> World */ + ok(r == TRUE, "got %d\n", r); + expect_identity(__LINE__, &xform); + + SetMapMode(hdc, MM_LOMETRIC); + GetViewportExtEx(hdc, &lometric_vp); + GetWindowExtEx(hdc, &lometric_wnd); + + r = pGetTransform(hdc, 0x203, &xform); /* World -> Page */ + ok(r == TRUE, "got %d\n", r); + expect_identity(__LINE__, &xform); + + r = pGetTransform(hdc, 0x304, &xform); /* Page -> Device */ + ok(r == TRUE, "got %d\n", r); + expect.eM11 = (FLOAT) lometric_vp.cx / lometric_wnd.cx; + expect.eM12 = expect.eM21 = 0.0; + expect.eM22 = (FLOAT) lometric_vp.cy / lometric_wnd.cy; + expect.eDx = expect.eDy = 0.0; + xform_near_match(__LINE__, &xform, &expect); + + r = pGetTransform(hdc, 0x204, &xform); /* World -> Device */ + ok(r == TRUE, "got %d\n", r); + xform_near_match(__LINE__, &xform, &expect); + + r = pGetTransform(hdc, 0x402, &xform); /* Device -> World */ + ok(r == TRUE, "got %d\n", r); + expect.eM11 = (FLOAT) lometric_wnd.cx / lometric_vp.cx; + expect.eM22 = (FLOAT) lometric_wnd.cy / lometric_vp.cy; + xform_near_match(__LINE__, &xform, &expect); + + + SetGraphicsMode(hdc, GM_ADVANCED); + + expect.eM11 = 10.0; + expect.eM22 = 20.0; + SetWorldTransform(hdc, &expect); + r = pGetTransform(hdc, 0x203, &xform); /* World -> Page */ + ok(r == TRUE, "got %d\n", r); + xform_near_match(__LINE__, &xform, &expect); + + r = pGetTransform(hdc, 0x304, &xform); /* Page -> Device */ + ok(r == TRUE, "got %d\n", r); + expect.eM11 = (FLOAT) lometric_vp.cx / lometric_wnd.cx; + expect.eM22 = (FLOAT) lometric_vp.cy / lometric_wnd.cy; + xform_near_match(__LINE__, &xform, &expect); + + r = pGetTransform(hdc, 0x204, &xform); /* World -> Device */ + ok(r == TRUE, "got %d\n", r); + expect.eM11 *= 10.0; + expect.eM22 *= 20.0; + xform_near_match(__LINE__, &xform, &expect); + + r = pGetTransform(hdc, 0x402, &xform); /* Device -> World */ + ok(r == TRUE, "got %d\n", r); + expect.eM11 = 1 / expect.eM11; + expect.eM22 = 1 / expect.eM22; + xform_near_match(__LINE__, &xform, &expect); + + r = pGetTransform(hdc, 0x102, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0x103, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0x104, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0x202, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0x302, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0x303, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0x403, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0x404, &xform); + ok(r == FALSE, "got %d\n", r); + r = pGetTransform(hdc, 0xffff, &xform); + ok(r == FALSE, "got %d\n", r); +} + START_TEST(mapping) { test_modify_world_transform(); test_world_transform(); test_isotropic_mapping(); + test_setvirtualresolution(); + test_gettransform(); } diff --git a/rostests/winetests/gdi32/metafile.c b/rostests/winetests/gdi32/metafile.c index 077977ec0de..a186608c0ac 100755 --- a/rostests/winetests/gdi32/metafile.c +++ b/rostests/winetests/gdi32/metafile.c @@ -1277,6 +1277,26 @@ static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr HeapFree(GetProcessHeap(), 0, eto1); HeapFree(GetProcessHeap(), 0, eto2); } + else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping")) + { + /* We have to take care of NT4 differences here */ + diff = memcmp(emr1, emr2, emr1->nSize); + if (diff) + { + ENHMETARECORD *emr_nt4; + + emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize); + memcpy(emr_nt4, emr2, emr2->nSize); + /* Correct the nRgnSize field */ + emr_nt4->dParm[5] = sizeof(RECT); + + diff = memcmp(emr1, emr_nt4, emr1->nSize); + if (!diff) + win_skip("Catered for NT4 differences\n"); + + HeapFree(GetProcessHeap(), 0, emr_nt4); + } + } else diff = memcmp(emr1, emr2, emr1->nSize); @@ -1302,15 +1322,22 @@ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits, BOOL ignore_scaling) { unsigned char buf[MF_BUFSIZE]; - UINT mfsize, offset; + UINT mfsize, offset1, offset2, diff_nt4, diff_9x; const ENHMETAHEADER *emh1, *emh2; mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf); ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError()); + /* ENHMETAHEADER size could differ, depending on platform */ + diff_nt4 = sizeof(SIZEL); + diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD); + if (mfsize < MF_BUFSIZE) { - ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize); + ok(mfsize == bsize || + broken(mfsize == bsize - diff_nt4) || /* NT4 */ + broken(mfsize == bsize - diff_9x), /* Win9x/WinME */ + "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize); } else ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n", @@ -1325,23 +1352,32 @@ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits, ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature); ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType); - ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize); + ok(emh1->nSize == emh2->nSize || + broken(emh1->nSize - diff_nt4 == emh2->nSize) || + broken(emh1->nSize - diff_9x == emh2->nSize), + "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize); ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature); - ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes); - ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords); + ok(emh1->nBytes == emh2->nBytes || + broken(emh1->nBytes - diff_nt4 == emh2->nBytes) || + broken(emh1->nBytes - diff_9x == emh2->nBytes), + "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes); + ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords); - offset = emh1->nSize; - while (offset < emh1->nBytes) + offset1 = emh1->nSize; + offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */ + while (offset1 < emh1->nBytes) { - const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset); - const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset); + const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1); + const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2); - trace("EMF record %u, size %u/record %u, size %u\n", - emr1->iType, emr1->nSize, emr2->iType, emr2->nSize); + trace("%s: EMF record %u, size %u/record %u, size %u\n", + desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize); if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1; - offset += emr1->nSize; + /* We have already bailed out if iType or nSize don't match */ + offset1 += emr1->nSize; + offset2 += emr2->nSize; } return 0; } @@ -1421,8 +1457,8 @@ static void test_CopyMetaFile(void) if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0) { - dump_mf_bits(hMetafile, "mf_Blank"); - EnumMetaFile(0, hMetafile, mf_enum_proc, 0); + dump_mf_bits(hmf_copy, "mf_Blank"); + EnumMetaFile(0, hmf_copy, mf_enum_proc, 0); } ret = DeleteMetaFile(hmf_copy); @@ -1440,6 +1476,7 @@ static void test_SetMetaFileBits(void) METAHEADER *mh; hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS); + trace("hmf %p\n", hmf); ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError()); type = GetObjectType(hmf); ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type); @@ -1456,21 +1493,23 @@ static void test_SetMetaFileBits(void) /* NULL data crashes XP SP1 */ /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/ - /* Now with not zero size */ + /* Now with zero size */ SetLastError(0xdeadbeef); hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS); + trace("hmf %p\n", hmf); ok(!hmf, "SetMetaFileBitsEx should fail\n"); ok(GetLastError() == ERROR_INVALID_DATA || broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ "wrong error %d\n", GetLastError()); - /* Now with not even size */ + /* Now with odd size */ SetLastError(0xdeadbeef); hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS); + trace("hmf %p\n", hmf); ok(!hmf, "SetMetaFileBitsEx should fail\n"); ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError()); - /* Now with zeroed out or faked some header fields */ + /* Now with zeroed out header fields */ assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS)); memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS)); mh = (METAHEADER *)buf; @@ -1480,6 +1519,7 @@ static void test_SetMetaFileBits(void) mh->mtHeaderSize = 0; SetLastError(0xdeadbeef); hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); + trace("hmf %p\n", hmf); ok(!hmf, "SetMetaFileBitsEx should fail\n"); ok(GetLastError() == ERROR_INVALID_DATA || broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ @@ -1491,6 +1531,7 @@ static void test_SetMetaFileBits(void) /* corruption of mtSize doesn't lead to a failure */ mh->mtSize *= 2; hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); + trace("hmf %p\n", hmf); ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError()); if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) @@ -1508,6 +1549,7 @@ static void test_SetMetaFileBits(void) /* zeroing mtSize doesn't lead to a failure */ mh->mtSize = 0; hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); + trace("hmf %p\n", hmf); ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError()); if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) @@ -1793,7 +1835,9 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize); ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType); ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount); - ok(rgn1->data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize); + ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) || + broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */ + "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize); hrgn = CreateRectRgn(0, 0, 0, 0); @@ -1812,7 +1856,7 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs); ret = GetClipRgn(hdc, hrgn); - ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret); + ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret); /* Win9x returns empty clipping region */ if (is_win9x) return 1; @@ -1846,7 +1890,9 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize); ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType); ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount); - ok(rgn2.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize); + ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) || + broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */ + "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize); DeleteObject(hrgn); } @@ -1862,6 +1908,7 @@ static void test_emf_clipping(void) HENHMETAFILE hemf; HRGN hrgn; INT ret; + RECT rc_res, rc_sclip; SetLastError(0xdeadbeef); hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); @@ -1900,6 +1947,22 @@ static void test_emf_clipping(void) DeleteEnhMetaFile(hemf); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); + + hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL); + + SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom); + SelectClipRgn(hdc, hrgn); + GetClipBox(hdc, &rc_res); + todo_wine ok(EqualRect(&rc_res, &rc_sclip), + "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n", + rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom, + rc_res.left, rc_res.top, rc_res.right, rc_res.bottom); + + hemf = CloseEnhMetaFile(hdc); + DeleteEnhMetaFile(hemf); + DeleteObject(hrgn); + DeleteDC(hdc); } static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData) @@ -2262,6 +2325,198 @@ static void test_SetWinMetaFileBits(void) HeapFree(GetProcessHeap(), 0, buffer); } +static BOOL near_match(int x, int y) +{ + int epsilon = min(abs(x), abs(y)); + + epsilon = max(epsilon/100, 2); + + if(x < y - epsilon || x > y + epsilon) return FALSE; + return TRUE; +} + +static void getwinmetafilebits(UINT mode, int scale, RECT *rc) +{ + HENHMETAFILE emf; + HDC display_dc, emf_dc; + ENHMETAHEADER *enh_header; + UINT size, emf_size, i; + WORD check = 0; + DWORD rec_num = 0; + METAHEADER *mh = NULL; + METARECORD *rec; + INT horz_res, vert_res, horz_size, vert_size; + + display_dc = GetDC(NULL); + ok(display_dc != NULL, "display_dc is NULL\n"); + + horz_res = GetDeviceCaps(display_dc, HORZRES); + vert_res = GetDeviceCaps(display_dc, VERTRES); + horz_size = GetDeviceCaps(display_dc, HORZSIZE); + vert_size = GetDeviceCaps(display_dc, VERTSIZE); + + emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL); + ok(emf_dc != NULL, "emf_dc is NULL\n"); + for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */ + Rectangle(emf_dc, 0, 0, 1000, 20); + emf = CloseEnhMetaFile(emf_dc); + ok(emf != NULL, "emf is NULL\n"); + + emf_size = GetEnhMetaFileBits(emf, 0, NULL); + enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size); + emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header); + DeleteEnhMetaFile(emf); + /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs + have different resolutions */ + enh_header->szlDevice.cx *= scale; + emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header); + ok(emf != NULL, "emf is NULL\n"); + ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n"); + + size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc); + ok(size || + broken(size == 0), /* some versions of winxp fail for some reason */ + "GetWinMetaFileBits returns 0\n"); + if(!size) goto end; + mh = HeapAlloc(GetProcessHeap(), 0, size); + GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc); + + for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i]; + ok(check == 0, "check %04x\n", check); + + rec = (METARECORD*)(mh + 1); + + while(rec->rdSize && rec->rdFunction) + { + const DWORD chunk_size = 0x2000; + DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size; + + if(rec_num < mfcomment_chunks) + { + DWORD this_chunk_size = chunk_size; + + if(rec_num == mfcomment_chunks - 1) + this_chunk_size = emf_size - rec_num * chunk_size; + + ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2); + ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction); + if(rec->rdSize < (this_chunk_size + 44) / 2) break; + ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]); + ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34); + ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */ + ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */ + ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]); + ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]); + ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]); + ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]); + /* parm[8] is the checksum, tested above */ + if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]); + ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]); + ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]); + ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */ + ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]); + ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size); + ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]); + ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15)); /* DWORD size remaining after current chunk */ + ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size); + ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n"); + } + + else if(rec_num == mfcomment_chunks) + { + ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction); + ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]); + } + else if(rec_num == mfcomment_chunks + 1) + { + POINT pt; + ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction); + switch(mode) + { + case MM_TEXT: + case MM_ISOTROPIC: + case MM_ANISOTROPIC: + pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1; + pt.x = MulDiv(rc->left, horz_res, horz_size * 100); + break; + case MM_LOMETRIC: + pt.y = MulDiv(-rc->top, 1, 10) + 1; + pt.x = MulDiv( rc->left, 1, 10); + break; + case MM_HIMETRIC: + pt.y = -rc->top + 1; + pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */ + break; + case MM_LOENGLISH: + pt.y = MulDiv(-rc->top, 10, 254) + 1; + pt.x = MulDiv( rc->left, 10, 254); + break; + case MM_HIENGLISH: + pt.y = MulDiv(-rc->top, 100, 254) + 1; + pt.x = MulDiv( rc->left, 100, 254); + break; + case MM_TWIPS: + pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1; + pt.x = MulDiv( rc->left, 72 * 20, 2540); + break; + default: + pt.x = pt.y = 0; + } + ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y); + ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x); + } + if(rec_num == mfcomment_chunks + 2) + { + ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction); + ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)), + "got %d\n", (short)rec->rdParm[0]); + ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)), + "got %d\n", (short)rec->rdParm[1]); + } + + rec_num++; + rec = (METARECORD*)((WORD*)rec + rec->rdSize); + } + +end: + HeapFree(GetProcessHeap(), 0, mh); + HeapFree(GetProcessHeap(), 0, enh_header); + DeleteEnhMetaFile(emf); + + ReleaseDC(NULL, display_dc); +} + +static void test_GetWinMetaFileBits(void) +{ + UINT mode; + RECT frames[] = + { + { 1000, 2000, 3000, 6000}, + {-1000, 2000, 3000, 6000}, + { 1000, -2000, 3000, 6000}, + { 1005, 2005, 3000, 6000}, + {-1005, -2005, 3000, 6000}, + {-1005, -2010, 3000, 6000}, + {-1005, 2010, 3000, 6000}, + { 0, 0, 1, 1}, + { -1, -1, 1, 1}, + { 0, 0, 0, 0} + }; + + for(mode = MM_MIN; mode <= MM_MAX; mode++) + { + RECT *rc; + trace("mode %d\n", mode); + + for(rc = frames; rc->right - rc->left > 0; rc++) + { + trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom); + getwinmetafilebits(mode, 1, rc); + getwinmetafilebits(mode, 2, rc); + } + } +} + static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC); static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC); static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC); @@ -2385,6 +2640,7 @@ START_TEST(metafile) /* For metafile conversions */ test_mf_conversions(); test_SetWinMetaFileBits(); + test_GetWinMetaFileBits(); test_gdiis(); test_SetEnhMetaFileBits();