Author: gschneider Date: Thu Nov 27 14:52:01 2008 New Revision: 37695
URL: http://svn.reactos.org/svn/reactos?rev=37695&view=rev Log: Update gdi32 winetests, so we don't run out of things to fix.
Modified: trunk/rostests/winetests/gdi32/bitmap.c trunk/rostests/winetests/gdi32/brush.c trunk/rostests/winetests/gdi32/clipping.c trunk/rostests/winetests/gdi32/font.c trunk/rostests/winetests/gdi32/gdiobj.c trunk/rostests/winetests/gdi32/icm.c trunk/rostests/winetests/gdi32/mapping.c trunk/rostests/winetests/gdi32/metafile.c trunk/rostests/winetests/gdi32/palette.c trunk/rostests/winetests/gdi32/pen.c
Modified: trunk/rostests/winetests/gdi32/bitmap.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/bitmap.c?r... ============================================================================== --- trunk/rostests/winetests/gdi32/bitmap.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/bitmap.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -70,13 +70,15 @@ static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHEADER *bmih) { BITMAP bm; + BITMAP bma[2]; INT ret, width_bytes; char buf[512], buf_cmp[512]; + DWORD gle;
ret = GetObject(hbm, sizeof(bm), &bm); ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
- ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType); + ok(bm.bmType == 0 || broken(bm.bmType == 21072 /* Win9x */), "wrong bm.bmType %d\n", bm.bmType); ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth); ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight); width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel); @@ -88,8 +90,10 @@ assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight); assert(sizeof(buf) == sizeof(buf_cmp));
+ SetLastError(0xdeadbeef); ret = GetBitmapBits(hbm, 0, NULL); - ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight); + gle=GetLastError(); + ok(ret == bm.bmWidthBytes * bm.bmHeight || (ret == 0 && gle == ERROR_INVALID_PARAMETER /* Win9x */), "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
memset(buf_cmp, 0xAA, sizeof(buf_cmp)); memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight); @@ -100,20 +104,24 @@ ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
/* test various buffer sizes for GetObject */ - ret = GetObject(hbm, 0, NULL); - ok(ret == sizeof(bm), "wrong size %d\n", ret); - - ret = GetObject(hbm, sizeof(bm) * 2, &bm); - ok(ret == sizeof(bm), "wrong size %d\n", ret); + ret = GetObject(hbm, sizeof(*bma) * 2, bma); + ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong size %d\n", ret);
ret = GetObject(hbm, sizeof(bm) / 2, &bm); - ok(ret == 0, "%d != 0\n", ret); + ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n", ret);
ret = GetObject(hbm, 0, &bm); ok(ret == 0, "%d != 0\n", ret);
ret = GetObject(hbm, 1, &bm); - ok(ret == 0, "%d != 0\n", ret); + ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret); + + /* Don't trust Win9x not to try to write to NULL */ + if (ret == 0) + { + ret = GetObject(hbm, 0, NULL); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + } }
static void test_createdibitmap(void) @@ -275,7 +283,9 @@ static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER *bmih) { BITMAP bm; + BITMAP bma[2]; DIBSECTION ds; + DIBSECTION dsa[2]; INT ret, bm_width_bytes, dib_width_bytes; BYTE *buf;
@@ -298,8 +308,11 @@ buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight + 4096);
/* GetBitmapBits returns not 32-bit aligned data */ + SetLastError(0xdeadbeef); ret = GetBitmapBits(hbm, 0, NULL); - ok(ret == bm_width_bytes * bm.bmHeight, "%d != %d\n", ret, bm_width_bytes * bm.bmHeight); + ok(ret == bm_width_bytes * bm.bmHeight || + broken(ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */ + "%d != %d\n", ret, bm_width_bytes * bm.bmHeight);
memset(buf, 0xAA, bm.bmWidthBytes * bm.bmHeight + 4096); ret = GetBitmapBits(hbm, bm.bmWidthBytes * bm.bmHeight + 4096, buf); @@ -309,27 +322,30 @@
/* test various buffer sizes for GetObject */ memset(&ds, 0xAA, sizeof(ds)); - ret = GetObject(hbm, sizeof(bm) * 2, &bm); - ok(ret == sizeof(bm), "wrong size %d\n", ret); + ret = GetObject(hbm, sizeof(*bma) * 2, bma); + ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong size %d\n", ret); ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth); ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight); ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
ret = GetObject(hbm, sizeof(bm) / 2, &bm); - ok(ret == 0, "%d != 0\n", ret); + ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n", ret);
ret = GetObject(hbm, 0, &bm); ok(ret == 0, "%d != 0\n", ret);
ret = GetObject(hbm, 1, &bm); - ok(ret == 0, "%d != 0\n", ret); + ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
/* test various buffer sizes for GetObject */ ret = GetObject(hbm, 0, NULL); ok(ret == sizeof(bm), "wrong size %d\n", ret);
+ ret = GetObject(hbm, sizeof(*dsa) * 2, dsa); + ok(ret == sizeof(*dsa) || broken(ret == sizeof(*dsa) * 2 /* Win9x */), "wrong size %d\n", ret); + memset(&ds, 0xAA, sizeof(ds)); - ret = GetObject(hbm, sizeof(ds) * 2, &ds); + ret = GetObject(hbm, sizeof(ds), &ds); ok(ret == sizeof(ds), "wrong size %d\n", ret);
ok(ds.dsBm.bmBits == bits, "wrong bm.bmBits %p != %p\n", ds.dsBm.bmBits, bits); @@ -416,6 +432,13 @@ pbmi->bmiHeader.biCompression = BI_RGB;
SetLastError(0xdeadbeef); + + /* invalid pointer for BITMAPINFO + (*bits should be NULL on error) */ + bits = (BYTE*)0xdeadbeef; + hdib = CreateDIBSection(hdc, NULL, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ok(hdib == NULL && bits == NULL, "CreateDIBSection failed for invalid parameter: bmi == 0x0\n"); + hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError()); ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n"); @@ -965,6 +988,7 @@ HBITMAP hbmp, hbmp_old; HDC hdc; BITMAP bm; + BITMAP bma[2]; INT ret;
hdc = CreateCompatibleDC(0); @@ -974,7 +998,8 @@ hbmp = CreateBitmap(0x7ffffff, 1, 1, 1, NULL); if (!hbmp) { - ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, + ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY /* XP */ || + GetLastError() == ERROR_INVALID_PARAMETER /* Win2k */, "expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError()); } else @@ -1047,17 +1072,17 @@ ok(hbmp_old == hbmp, "wrong old bitmap %p\n", hbmp_old);
/* test various buffer sizes for GetObject */ - ret = GetObject(hbmp, sizeof(bm) * 2, &bm); - ok(ret == sizeof(bm), "wrong size %d\n", ret); + ret = GetObject(hbmp, sizeof(*bma) * 2, bma); + ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong size %d\n", ret);
ret = GetObject(hbmp, sizeof(bm) / 2, &bm); - ok(ret == 0, "%d != 0\n", ret); + ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n", ret);
ret = GetObject(hbmp, 0, &bm); ok(ret == 0, "%d != 0\n", ret);
ret = GetObject(hbmp, 1, &bm); - ok(ret == 0, "%d != 0\n", ret); + ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
DeleteObject(hbmp); DeleteDC(hdc); @@ -1133,7 +1158,7 @@
/* Select the DIB into a DC */ dib_dc = CreateCompatibleDC(NULL); - old_bmp = (HBITMAP) SelectObject(dib_dc, dib); + old_bmp = SelectObject(dib_dc, dib); dc = CreateCompatibleDC(NULL); bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dib_size); assert(bits2); @@ -1168,10 +1193,7 @@ break; } } - if (bpp != 1) - ok(equalContents, "GetDIBits with %d bpp DIB selected in DC: Invalid DIB bits\n",bpp); - else - todo_wine ok(equalContents, "GetDIBits with %d bpp DIB selected in DC: Invalid DIB bits\n",bpp); + ok(equalContents, "GetDIBits with %d bpp DIB selected in DC: Invalid DIB bits\n",bpp);
HeapFree(GetProcessHeap(), 0, bits2); DeleteDC(dc); @@ -1217,7 +1239,7 @@
/* Set the pixels */ ddb_dc = CreateCompatibleDC(NULL); - old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb); + old_bmp = SelectObject(ddb_dc, ddb); for (i = 0; i < width; i++) { for (j=0; j < height; j++) @@ -1259,7 +1281,7 @@ memcpy(info2, info, sizeof(BITMAPINFOHEADER));
/* Select the DDB into another DC */ - old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb); + old_bmp = SelectObject(ddb_dc, ddb);
/* Get the bits */ res = GetDIBits(dc, ddb, 0, height, bits2, info2, DIB_RGB_COLORS); @@ -1293,6 +1315,28 @@ } ok(equalContents, "GetDIBits with DDB selected in DC: Got different DIB bits\n");
+ /* Test the palette */ + equalContents = TRUE; + if (info2->bmiHeader.biBitCount <= 8) + { + WORD *colors = (WORD*)info2->bmiColors; + + /* Get the palette indices */ + res = GetDIBits(dc, ddb, 0, 0, NULL, info2, DIB_PAL_COLORS); + ok(res, "GetDIBits failed\n"); + + for (i=0;i < 1 << info->bmiHeader.biSizeImage; i++) + { + if (colors[i] != i) + { + equalContents = FALSE; + break; + } + } + } + + ok(equalContents, "GetDIBits with DDB selected in DC: non 1:1 palette indices\n"); + HeapFree(GetProcessHeap(), 0, bits2); HeapFree(GetProcessHeap(), 0, bits); DeleteDC(dc); @@ -1442,107 +1486,6 @@ ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); ok(bi->bmiHeader.biSizeImage == 0, "expected 0, got %u\n", bi->bmiHeader.biSizeImage);
- memset(buf, 0xAA, sizeof(buf)); - SetLastError(0xdeadbeef); - lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS); - ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n", - lines, bm.bmHeight, GetLastError()); - ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_1), "expected 16*4, got %u\n", bi->bmiHeader.biSizeImage); - - /* the color table consists of black and white */ - ok(bi->bmiColors[0].rgbRed == 0 && bi->bmiColors[0].rgbGreen == 0 && - bi->bmiColors[0].rgbBlue == 0 && bi->bmiColors[0].rgbReserved == 0, - "expected bmiColors[0] 0,0,0,0 - got %x %x %x %x\n", - bi->bmiColors[0].rgbRed, bi->bmiColors[0].rgbGreen, - bi->bmiColors[0].rgbBlue, bi->bmiColors[0].rgbReserved); -todo_wine - ok(bi->bmiColors[1].rgbRed == 0xff && bi->bmiColors[1].rgbGreen == 0xff && - bi->bmiColors[1].rgbBlue == 0xff && bi->bmiColors[1].rgbReserved == 0, - "expected bmiColors[0] 0xff,0xff,0xff,0 - got %x %x %x %x\n", - bi->bmiColors[1].rgbRed, bi->bmiColors[1].rgbGreen, - bi->bmiColors[1].rgbBlue, bi->bmiColors[1].rgbReserved); - for (i = 2; i < 256; i++) - { - ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA && - bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA, - "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i, - bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen, - bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved); - } - - /* returned bits are DWORD aligned and upside down */ -todo_wine - ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)), "DIB bits don't match\n"); - - /* retrieve 24-bit DIB data */ - memset(bi, 0, sizeof(*bi)); - bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi->bmiHeader.biWidth = bm.bmWidth; - bi->bmiHeader.biHeight = bm.bmHeight; - bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = 24; - bi->bmiHeader.biCompression = BI_RGB; - bi->bmiHeader.biSizeImage = 0; - memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256); - memset(buf, 0xAA, sizeof(buf)); - SetLastError(0xdeadbeef); - lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS); - ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n", - lines, bm.bmHeight, GetLastError()); - ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_24), "expected 16*16*3, got %u\n", bi->bmiHeader.biSizeImage); - - /* the color table doesn't exist for 24-bit images */ - for (i = 0; i < 256; i++) - { - ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA && - bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA, - "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i, - bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen, - bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved); - } - - /* returned bits are DWORD aligned and upside down */ -todo_wine - ok(!memcmp(buf, dib_bits_24, sizeof(dib_bits_24)), "DIB bits don't match\n"); - DeleteObject(hbmp); - - /* 24-bit source bitmap data */ - hbmp = CreateCompatibleBitmap(hdc, 16, 16); - ok(hbmp != 0, "CreateBitmap failed\n"); - SetLastError(0xdeadbeef); - bi->bmiHeader.biHeight = -bm.bmHeight; /* indicate bottom-up data */ - lines = SetDIBits(hdc, hbmp, 0, bm.bmHeight, bmp_bits_24, bi, DIB_RGB_COLORS); - ok(lines == bm.bmHeight, "SetDIBits copied %d lines of %d, error %u\n", - lines, bm.bmHeight, GetLastError()); - - memset(&bm, 0xAA, sizeof(bm)); - bytes = GetObject(hbmp, sizeof(bm), &bm); - ok(bytes == sizeof(bm), "GetObject returned %d\n", bytes); - ok(bm.bmType == 0, "wrong bmType %d\n", bm.bmType); - ok(bm.bmWidth == 16, "wrong bmWidth %d\n", bm.bmWidth); - ok(bm.bmHeight == 16, "wrong bmHeight %d\n", bm.bmHeight); - ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong bmWidthBytes %d\n", bm.bmWidthBytes); - ok(bm.bmPlanes == GetDeviceCaps(hdc, PLANES), "wrong bmPlanes %u\n", bm.bmPlanes); - ok(bm.bmBitsPixel == GetDeviceCaps(hdc, BITSPIXEL), "wrong bmBitsPixel %d\n", bm.bmBitsPixel); - ok(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits); - - bytes = GetBitmapBits(hbmp, 0, NULL); - ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n", - bm.bmWidthBytes * bm.bmHeight, bytes); - bytes = GetBitmapBits(hbmp, sizeof(buf), buf); - ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n", - bm.bmWidthBytes * bm.bmHeight, bytes); - - /* retrieve 1-bit DIB data */ - memset(bi, 0, sizeof(*bi)); - bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi->bmiHeader.biWidth = bm.bmWidth; - bi->bmiHeader.biHeight = bm.bmHeight; - bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = 1; - bi->bmiHeader.biCompression = BI_RGB; - bi->bmiHeader.biSizeImage = 0; - memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256); memset(buf, 0xAA, sizeof(buf)); SetLastError(0xdeadbeef); lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS); @@ -1573,6 +1516,125 @@ /* returned bits are DWORD aligned and upside down */ todo_wine ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)), "DIB bits don't match\n"); + + /* Test the palette indices */ + memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256); + SetLastError(0xdeadbeef); + lines = GetDIBits(hdc, hbmp, 0, 0, NULL, bi, DIB_PAL_COLORS); + + ok(((WORD*)bi->bmiColors)[0] == 0, "Color 0 is %d\n", ((WORD*)bi->bmiColors)[0]); + ok(((WORD*)bi->bmiColors)[1] == 1, "Color 1 is %d\n", ((WORD*)bi->bmiColors)[1]); + for (i = 2; i < 256; i++) + ok(((WORD*)bi->bmiColors)[i] == 0xAAAA, "Color %d is %d\n", i, ((WORD*)bi->bmiColors)[1]); + + /* retrieve 24-bit DIB data */ + memset(bi, 0, sizeof(*bi)); + bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi->bmiHeader.biWidth = bm.bmWidth; + bi->bmiHeader.biHeight = bm.bmHeight; + bi->bmiHeader.biPlanes = 1; + bi->bmiHeader.biBitCount = 24; + bi->bmiHeader.biCompression = BI_RGB; + bi->bmiHeader.biSizeImage = 0; + memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256); + memset(buf, 0xAA, sizeof(buf)); + SetLastError(0xdeadbeef); + lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS); + ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n", + lines, bm.bmHeight, GetLastError()); + ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_24), "expected 16*16*3, got %u\n", bi->bmiHeader.biSizeImage); + + /* the color table doesn't exist for 24-bit images */ + for (i = 0; i < 256; i++) + { + ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA && + bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA, + "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i, + bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen, + bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved); + } + + /* returned bits are DWORD aligned and upside down */ + ok(!memcmp(buf, dib_bits_24, sizeof(dib_bits_24)), "DIB bits don't match\n"); + DeleteObject(hbmp); + + /* 24-bit source bitmap data */ + hbmp = CreateCompatibleBitmap(hdc, 16, 16); + ok(hbmp != 0, "CreateBitmap failed\n"); + SetLastError(0xdeadbeef); + bi->bmiHeader.biHeight = -bm.bmHeight; /* indicate bottom-up data */ + lines = SetDIBits(hdc, hbmp, 0, bm.bmHeight, bmp_bits_24, bi, DIB_RGB_COLORS); + ok(lines == bm.bmHeight, "SetDIBits copied %d lines of %d, error %u\n", + lines, bm.bmHeight, GetLastError()); + + memset(&bm, 0xAA, sizeof(bm)); + bytes = GetObject(hbmp, sizeof(bm), &bm); + ok(bytes == sizeof(bm), "GetObject returned %d\n", bytes); + ok(bm.bmType == 0, "wrong bmType %d\n", bm.bmType); + ok(bm.bmWidth == 16, "wrong bmWidth %d\n", bm.bmWidth); + ok(bm.bmHeight == 16, "wrong bmHeight %d\n", bm.bmHeight); + ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong bmWidthBytes %d\n", bm.bmWidthBytes); + ok(bm.bmPlanes == GetDeviceCaps(hdc, PLANES), "wrong bmPlanes %u\n", bm.bmPlanes); + ok(bm.bmBitsPixel == GetDeviceCaps(hdc, BITSPIXEL), "wrong bmBitsPixel %d\n", bm.bmBitsPixel); + ok(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits); + + bytes = GetBitmapBits(hbmp, 0, NULL); + ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n", + bm.bmWidthBytes * bm.bmHeight, bytes); + bytes = GetBitmapBits(hbmp, sizeof(buf), buf); + ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n", + bm.bmWidthBytes * bm.bmHeight, bytes); + + /* retrieve 1-bit DIB data */ + memset(bi, 0, sizeof(*bi)); + bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi->bmiHeader.biWidth = bm.bmWidth; + bi->bmiHeader.biHeight = bm.bmHeight; + bi->bmiHeader.biPlanes = 1; + bi->bmiHeader.biBitCount = 1; + bi->bmiHeader.biCompression = BI_RGB; + bi->bmiHeader.biSizeImage = 0; + memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256); + memset(buf, 0xAA, sizeof(buf)); + SetLastError(0xdeadbeef); + lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS); + ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n", + lines, bm.bmHeight, GetLastError()); + ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_1), "expected 16*4, got %u\n", bi->bmiHeader.biSizeImage); + + /* the color table consists of black and white */ + ok(bi->bmiColors[0].rgbRed == 0 && bi->bmiColors[0].rgbGreen == 0 && + bi->bmiColors[0].rgbBlue == 0 && bi->bmiColors[0].rgbReserved == 0, + "expected bmiColors[0] 0,0,0,0 - got %x %x %x %x\n", + bi->bmiColors[0].rgbRed, bi->bmiColors[0].rgbGreen, + bi->bmiColors[0].rgbBlue, bi->bmiColors[0].rgbReserved); + ok(bi->bmiColors[1].rgbRed == 0xff && bi->bmiColors[1].rgbGreen == 0xff && + bi->bmiColors[1].rgbBlue == 0xff && bi->bmiColors[1].rgbReserved == 0, + "expected bmiColors[0] 0xff,0xff,0xff,0 - got %x %x %x %x\n", + bi->bmiColors[1].rgbRed, bi->bmiColors[1].rgbGreen, + bi->bmiColors[1].rgbBlue, bi->bmiColors[1].rgbReserved); + for (i = 2; i < 256; i++) + { + ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA && + bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA, + "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i, + bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen, + bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved); + } + + /* returned bits are DWORD aligned and upside down */ +todo_wine + ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)), "DIB bits don't match\n"); + + /* Test the palette indices */ + memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256); + SetLastError(0xdeadbeef); + lines = GetDIBits(hdc, hbmp, 0, 0, NULL, bi, DIB_PAL_COLORS); + + ok(((WORD*)bi->bmiColors)[0] == 0, "Color 0 is %d\n", ((WORD*)bi->bmiColors)[0]); + ok(((WORD*)bi->bmiColors)[1] == 1, "Color 1 is %d\n", ((WORD*)bi->bmiColors)[1]); + for (i = 2; i < 256; i++) + ok(((WORD*)bi->bmiColors)[i] == 0xAAAA, "Color %d is %d\n", i, ((WORD*)bi->bmiColors)[i]);
/* retrieve 24-bit DIB data */ memset(bi, 0, sizeof(*bi)); @@ -1675,22 +1737,29 @@ memset(dibinfo, 0, sizeof(dibinfo_buf)); dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); dibinfo->bmiHeader.biSizeImage = 0xdeadbeef; + SetLastError(0xdeadbeef); ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS); - - ok( !bitmasks[0], "red mask is set\n" ); - ok( !bitmasks[1], "green mask is set\n" ); - ok( !bitmasks[2], "blue mask is set\n" ); - ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" ); - - memset(bitmasks, 0, 3*sizeof(DWORD)); - dibinfo->bmiHeader.biSizeImage = 0xdeadbeef; - ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS); - ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError()); - - ok( bitmasks[0] != 0, "red mask is not set\n" ); - ok( bitmasks[1] != 0, "green mask is not set\n" ); - ok( bitmasks[2] != 0, "blue mask is not set\n" ); - ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" ); + if (ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER) + win_skip("Win9x/WinMe doesn't handle 0 for the number of scan lines\n"); + else + { + ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError()); + + ok( !bitmasks[0], "red mask is set\n" ); + ok( !bitmasks[1], "green mask is set\n" ); + ok( !bitmasks[2], "blue mask is set\n" ); + ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" ); + + memset(bitmasks, 0, 3*sizeof(DWORD)); + dibinfo->bmiHeader.biSizeImage = 0xdeadbeef; + ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS); + ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError()); + + ok( bitmasks[0] != 0, "red mask is not set\n" ); + ok( bitmasks[1] != 0, "green mask is not set\n" ); + ok( bitmasks[2] != 0, "blue mask is not set\n" ); + ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" ); + } } else skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\n");
@@ -1825,15 +1894,15 @@ HBITMAP bm1 = CreateCompatibleBitmap(screenDC, 0, 0); HBITMAP bm4 = CreateBitmap(0, 1, 0, 0, 0); HBITMAP bm5 = CreateDiscardableBitmap(hdc, 0, 0); - HBITMAP curObj1 = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP); - HBITMAP curObj2 = (HBITMAP)GetCurrentObject(screenDC, OBJ_BITMAP); + HBITMAP curObj1 = GetCurrentObject(hdc, OBJ_BITMAP); + HBITMAP curObj2 = GetCurrentObject(screenDC, OBJ_BITMAP);
/* these 2 are not the stock monochrome bitmap */ HBITMAP bm2 = CreateCompatibleBitmap(hdc, 1, 1); HBITMAP bm3 = CreateBitmap(1, 1, 1, 1, 0);
- HBITMAP old1 = (HBITMAP)SelectObject(hdc, bm2); - HBITMAP old2 = (HBITMAP)SelectObject(screenDC, bm3); + HBITMAP old1 = SelectObject(hdc, bm2); + HBITMAP old2 = SelectObject(screenDC, bm3); SelectObject(hdc, old1); SelectObject(screenDC, old2);
@@ -2084,8 +2153,8 @@ bmpSrc = CreateDIBSection(hdcDst, &bmi, DIB_RGB_COLORS, &bits, NULL, 0); ok(bmpSrc != NULL, "Couldn't create source bitmap\n");
- oldDst = (HBITMAP)SelectObject(hdcDst, bmpDst); - oldSrc = (HBITMAP)SelectObject(hdcSrc, bmpSrc); + oldDst = SelectObject(hdcDst, bmpDst); + oldSrc = SelectObject(hdcSrc, bmpSrc);
blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; @@ -2118,6 +2187,51 @@
ReleaseDC(NULL, hdcNull);
+} + +static void test_clipping(void) +{ + HBITMAP bmpDst; + HBITMAP oldDst; + HBITMAP bmpSrc; + HBITMAP oldSrc; + HRGN hRgn; + LPVOID bits; + BOOL result; + + HDC hdcDst = CreateCompatibleDC( NULL ); + HDC hdcSrc = CreateCompatibleDC( NULL ); + + BITMAPINFO bmpinfo={{0}}; + bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmpinfo.bmiHeader.biWidth = 100; + bmpinfo.bmiHeader.biHeight = 100; + bmpinfo.bmiHeader.biPlanes = 1; + bmpinfo.bmiHeader.biBitCount = GetDeviceCaps( hdcDst, BITSPIXEL ); + bmpinfo.bmiHeader.biCompression = BI_RGB; + + bmpDst = CreateDIBSection( hdcDst, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 ); + ok(bmpDst != NULL, "Couldn't create destination bitmap\n"); + oldDst = SelectObject( hdcDst, bmpDst ); + + bmpSrc = CreateDIBSection( hdcSrc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 ); + ok(bmpSrc != NULL, "Couldn't create source bitmap\n"); + oldSrc = SelectObject( hdcSrc, bmpSrc ); + + result = BitBlt( hdcDst, 0, 0, 100, 100, hdcSrc, 100, 100, SRCCOPY ); + ok(result, "BitBlt failed\n"); + + hRgn = CreateRectRgn( 0,0,0,0 ); + SelectClipRgn( hdcDst, hRgn ); + + result = BitBlt( hdcDst, 0, 0, 100, 100, hdcSrc, 0, 0, SRCCOPY ); + ok(result, "BitBlt failed\n"); + + DeleteObject( bmpDst ); + DeleteObject( bmpSrc ); + DeleteObject( hRgn ); + DeleteDC( hdcDst ); + DeleteDC( hdcSrc ); }
START_TEST(bitmap) @@ -2145,4 +2259,5 @@ test_GdiAlphaBlend(); test_bitmapinfoheadersize(); test_get16dibits(); + test_clipping(); }
Modified: trunk/rostests/winetests/gdi32/brush.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/brush.c?re... ============================================================================== --- trunk/rostests/winetests/gdi32/brush.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/brush.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -51,8 +51,10 @@ solidBrush = CreateSolidBrush(stock[i].color);
if(stock[i].stockobj != -1) { - stockBrush = (HBRUSH)GetStockObject(stock[i].stockobj); - ok(stockBrush!=solidBrush, "Stock %s brush equals solid %s brush\n", stock[i].name, stock[i].name); + stockBrush = GetStockObject(stock[i].stockobj); + ok(stockBrush!=solidBrush || + broken(stockBrush==solidBrush), /* win9x does return stock object */ + "Stock %s brush equals solid %s brush\n", stock[i].name, stock[i].name); } else stockBrush = NULL; @@ -70,7 +72,10 @@ }
DeleteObject(solidBrush); - ok(GetObject(solidBrush, sizeof(br), &br)==0, "GetObject succeeded on a deleted %s brush\n", stock[i].name); + ret = GetObject(solidBrush, sizeof(br), &br); + ok(ret==0 || + broken(ret!=0), /* win9x */ + "GetObject succeeded on a deleted %s brush\n", stock[i].name); } }
Modified: trunk/rostests/winetests/gdi32/clipping.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/clipping.c... ============================================================================== --- trunk/rostests/winetests/gdi32/clipping.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/clipping.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -111,7 +111,9 @@ GetRgnBox(hrgn, &ret_rc); if(GetVersion() & 0x80000000) OffsetRect(&window_rc, -window_rc.left, -window_rc.top); - ok(EqualRect(&window_rc, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n", + ok(EqualRect(&window_rc, &ret_rc) || + broken(IsRectEmpty(&ret_rc)), /* win95 */ + "GetRandomRgn %d,%d - %d,%d\n", ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
DeleteObject(hrgn);
Modified: trunk/rostests/winetests/gdi32/font.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/font.c?rev... ============================================================================== --- trunk/rostests/winetests/gdi32/font.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/font.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -30,6 +30,7 @@
#include "wine/test.h"
+#define near_match(a, b) (abs((a) - (b)) <= 6) #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
LONG (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height); @@ -105,7 +106,7 @@ minlen++; minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1; ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret); - ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test); + ok(!memcmp(lf, &getobj_lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test); ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName), "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName); } @@ -158,56 +159,119 @@ return 1; /* continue enumeration */ }
+static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm) +{ + ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight); + ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent); + ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent); + ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading); + ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading); + ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth); + ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth); + ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight); + ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang); + ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX); + ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY); + ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar); + ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar); + ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar); + ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar); + ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic); + ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined); + ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut); + ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily); + ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet); +} + static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight, LONG lfWidth, const char *test_str, INT test_str_len, const TEXTMETRICA *tm_orig, const SIZE *size_orig, INT width_of_A_orig, INT scale_x, INT scale_y) { - HFONT old_hfont; LOGFONTA lf; + OUTLINETEXTMETRIC otm; TEXTMETRICA tm; SIZE size; INT width_of_A, cx, cy; + UINT ret;
if (!hfont) return;
+ ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n"); + GetObjectA(hfont, sizeof(lf), &lf);
- old_hfont = SelectObject(hdc, hfont); - - GetTextMetricsA(hdc, &tm); + if (GetOutlineTextMetricsA(hdc, 0, NULL)) + { + otm.otmSize = sizeof(otm) / 2; + ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm); + ok(ret == sizeof(otm)/2 /* XP */ || + ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret); + + memset(&otm, 0x1, sizeof(otm)); + otm.otmSize = sizeof(otm); + ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm); + ok(ret == sizeof(otm) /* XP */ || + ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret); + + memset(&tm, 0x2, sizeof(tm)); + ret = GetTextMetricsA(hdc, &tm); + ok(ret, "GetTextMetricsA failed\n"); + /* the structure size is aligned */ + if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1)) + { + ok(0, "tm != otm\n"); + compare_tm(&tm, &otm.otmTextMetrics); + } + + tm = otm.otmTextMetrics; +if (0) /* these metrics are scaled too, but with rounding errors */ +{ + ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent); + ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent); +} + ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent); + ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n"); + ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n"); + ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n"); + ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent); + ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare); + } + else + { + ret = GetTextMetricsA(hdc, &tm); + ok(ret, "GetTextMetricsA failed\n"); + }
cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth; cy = tm.tmHeight / tm_orig->tmHeight; ok(cx == scale_x && cy == scale_y, "expected scale_x %d, scale_y %d, got cx %d, cy %d\n", scale_x, scale_y, cx, cy); - ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y); - ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y); - ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y); - ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x); - ok(tm.tmMaxCharWidth == tm_orig->tmMaxCharWidth * scale_x, "%d != %d\n", tm.tmAveCharWidth, tm_orig->tmMaxCharWidth * scale_x); - - ok(lf.lfHeight == lfHeight, "lf %d != %d\n", lf.lfHeight, lfHeight); + ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y); + ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y); + ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y); + ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x); + ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x); + + ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight); if (lf.lfHeight) { if (lf.lfWidth) - ok(lf.lfWidth == tm.tmAveCharWidth, "lf %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth); + ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth); } else - ok(lf.lfWidth == lfWidth, "lf %d != %d\n", lf.lfWidth, lfWidth); + ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
- ok(size.cx == size_orig->cx * scale_x, "%d != %d\n", size.cx, size_orig->cx * scale_x); - ok(size.cy == size_orig->cy * scale_y, "%d != %d\n", size.cy, size_orig->cy * scale_y); + ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x); + ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y);
GetCharWidthA(hdc, 'A', 'A', &width_of_A);
- ok(width_of_A == width_of_A_orig * scale_x, "%d != %d\n", width_of_A, width_of_A_orig * scale_x); - - SelectObject(hdc, old_hfont); + ok(near_match(width_of_A, width_of_A_orig * scale_x), "width A %d != %d\n", width_of_A, width_of_A_orig * scale_x); }
/* Test how GDI scales bitmap font metrics */ @@ -248,7 +312,9 @@ bitmap_lf.lfHeight = 0; bitmap_lf.lfWidth = 4; hfont = create_font("bitmap", &bitmap_lf); + old_hfont = SelectObject(hdc, hfont); test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1); + SelectObject(hdc, old_hfont); DeleteObject(hfont);
bitmap_lf.lfHeight = height_orig; @@ -265,25 +331,283 @@ nearest_height = scale * height_orig; /* XP allows not more than 10% deviation */ if (scale > 1 && nearest_height - i > nearest_height / 10) scale--; + old_hfont = SelectObject(hdc, hfont); test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, scale); - DeleteObject(hfont); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); }
/* test integer scaling 3x2 */ bitmap_lf.lfHeight = height_orig * 2; bitmap_lf.lfWidth *= 3; hfont = create_font("3x2", &bitmap_lf); + old_hfont = SelectObject(hdc, hfont); test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2); + SelectObject(hdc, old_hfont); DeleteObject(hfont);
/* test integer scaling 3x3 */ bitmap_lf.lfHeight = height_orig * 3; bitmap_lf.lfWidth = 0; hfont = create_font("3x3", &bitmap_lf); + old_hfont = SelectObject(hdc, hfont); test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3); + SelectObject(hdc, old_hfont); DeleteObject(hfont);
ReleaseDC(0, hdc); +} + +/* Test how GDI scales outline font metrics */ +static void test_outline_font(void) +{ + static const char test_str[11] = "Test String"; + HDC hdc, hdc_2; + LOGFONTA lf; + HFONT hfont, old_hfont, old_hfont_2; + OUTLINETEXTMETRICA otm; + SIZE size_orig; + INT width_orig, height_orig, lfWidth; + XFORM xform; + GLYPHMETRICS gm; + MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} }; + MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} }; + POINT pt; + INT ret; + + if (!is_truetype_font_installed("Arial")) + { + skip("Arial is not installed\n"); + return; + } + + hdc = CreateCompatibleDC(0); + + memset(&lf, 0, sizeof(lf)); + strcpy(lf.lfFaceName, "Arial"); + lf.lfHeight = 72; + hfont = create_font("outline", &lf); + old_hfont = SelectObject(hdc, hfont); + otm.otmSize = sizeof(otm); + ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n"); + ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n"); + ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n"); + + test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + + /* font of otmEMSquare height helps to avoid a lot of rounding errors */ + lf.lfHeight = otm.otmEMSquare; + lf.lfHeight = -lf.lfHeight; + hfont = create_font("outline", &lf); + old_hfont = SelectObject(hdc, hfont); + otm.otmSize = sizeof(otm); + ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n"); + ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n"); + ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n"); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + + height_orig = otm.otmTextMetrics.tmHeight; + lfWidth = otm.otmTextMetrics.tmAveCharWidth; + + /* test integer scaling 3x2 */ + lf.lfHeight = height_orig * 2; + lf.lfWidth = lfWidth * 3; + hfont = create_font("3x2", &lf); + old_hfont = SelectObject(hdc, hfont); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + + /* test integer scaling 3x3 */ + lf.lfHeight = height_orig * 3; + lf.lfWidth = lfWidth * 3; + hfont = create_font("3x3", &lf); + old_hfont = SelectObject(hdc, hfont); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + + /* test integer scaling 1x1 */ + lf.lfHeight = height_orig * 1; + lf.lfWidth = lfWidth * 1; + hfont = create_font("1x1", &lf); + old_hfont = SelectObject(hdc, hfont); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + + /* test integer scaling 1x1 */ + lf.lfHeight = height_orig; + lf.lfWidth = 0; + hfont = create_font("1x1", &lf); + old_hfont = SelectObject(hdc, hfont); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + + /* Test that changing the DC transformation affects only the font + * selected on this DC and doesn't affect the same font selected on + * another DC. + */ + hdc_2 = CreateCompatibleDC(0); + old_hfont_2 = SelectObject(hdc_2, hfont); + test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + SetMapMode(hdc, MM_ANISOTROPIC); + + /* font metrics on another DC should be unchanged */ + test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + /* test restrictions of compatibility mode GM_COMPATIBLE */ + /* part 1: rescaling only X should not change font scaling on screen. + So compressing the X axis by 2 is not done, and this + appears as X scaling of 2 that no one requested. */ + SetWindowExtEx(hdc, 100, 100, NULL); + SetViewportExtEx(hdc, 50, 100, NULL); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1); + /* font metrics on another DC should be unchanged */ + test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + /* part 2: rescaling only Y should change font scaling. + As also X is scaled by a factor of 2, but this is not + requested by the DC transformation, we get a scaling factor + of 2 in the X coordinate. */ + SetViewportExtEx(hdc, 100, 200, NULL); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 2, 1); + /* font metrics on another DC should be unchanged */ + test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + /* restore scaling */ + SetMapMode(hdc, MM_TEXT); + + /* font metrics on another DC should be unchanged */ + test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + SelectObject(hdc_2, old_hfont_2); + DeleteDC(hdc_2); + + if (!SetGraphicsMode(hdc, GM_ADVANCED)) + { + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + DeleteDC(hdc); + skip("GM_ADVANCED is not supported on this platform\n"); + return; + } + + xform.eM11 = 20.0f; + xform.eM12 = 0.0f; + xform.eM21 = 0.0f; + xform.eM22 = 20.0f; + xform.eDx = 0.0f; + xform.eDy = 0.0f; + + SetLastError(0xdeadbeef); + ret = SetWorldTransform(hdc, &xform); + ok(ret, "SetWorldTransform error %u\n", GetLastError()); + + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x); + ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2); + ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_LOMETRIC); + ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError()); + + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX, pt.x); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_TEXT); + ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError()); + + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x); + ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2); + ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + DeleteDC(hdc); }
static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam) @@ -781,6 +1105,8 @@ kd[i].otmDescent, otm.otmDescent); ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n", kd[i].otmLineGap, otm.otmLineGap); + ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n", + kd[i].otmMacDescent, otm.otmMacDescent); todo_wine { ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n", kd[i].otmsCapEmHeight, otm.otmsCapEmHeight); @@ -788,8 +1114,6 @@ kd[i].otmsXHeight, otm.otmsXHeight); ok(kd[i].otmMacAscent == otm.otmMacAscent, "expected %d, got %d\n", kd[i].otmMacAscent, otm.otmMacAscent); - ok(kd[i].otmMacDescent == otm.otmMacDescent, "expected %d, got %d\n", - kd[i].otmMacDescent, otm.otmMacDescent); /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */ if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n", kd[i].otmMacLineGap, otm.otmMacLineGap); @@ -1020,7 +1344,7 @@
for (e = 0; e < nErrors; e++) { - ok(error[e].TabbedTextOutWidth == areaWidth, + ok(near_match(error[e].TabbedTextOutWidth, areaWidth), "The output text ("%s") width should be %d, not %d.\n", error[e].extent, areaWidth, error[e].TabbedTextOutWidth); /* The width returned by GetTextExtentPoint32() is exactly the same @@ -1097,8 +1421,8 @@ ok(cs == charset, "expected %d, got %d\n", charset, cs);
SetLastError(0xdeadbeef); - ret = GetTextFace(hdc, sizeof(name), name); - ok(ret, "GetTextFace error %u\n", GetLastError()); + ret = GetTextFaceA(hdc, sizeof(name), name); + ok(ret, "GetTextFaceA error %u\n", GetLastError());
if (charset == SYMBOL_CHARSET) { @@ -1247,7 +1571,7 @@ ReleaseDC(NULL, hdc); }
-#define MAX_ENUM_FONTS 256 +#define MAX_ENUM_FONTS 4096
struct enum_font_data { @@ -1255,17 +1579,46 @@ LOGFONT lf[MAX_ENUM_FONTS]; };
+struct enum_font_dataW +{ + int total; + LOGFONTW lf[MAX_ENUM_FONTS]; +}; + static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type, LPARAM lParam) { struct enum_font_data *efd = (struct enum_font_data *)lParam; + + ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight);
if (type != TRUETYPE_FONTTYPE) return 1; #if 0 - trace("enumed font "%s", charset %d, weight %d, italic %d\n", - lf->lfFaceName, lf->lfCharSet, lf->lfWeight, lf->lfItalic); + trace("enumed font "%s", charset %d, height %d, weight %d, italic %d\n", + lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic); #endif if (efd->total < MAX_ENUM_FONTS) efd->lf[efd->total++] = *lf; + else + trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS); + + return 1; +} + +static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam) +{ + struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam; + + ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n", lf->lfHeight, tm->tmHeight); + + if (type != TRUETYPE_FONTTYPE) return 1; +#if 0 + trace("enumed font "%s", charset %d, height %d, weight %d, italic %d\n", + lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic); +#endif + if (efd->total < MAX_ENUM_FONTS) + efd->lf[efd->total++] = *lf; + else + trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
return 1; } @@ -1297,9 +1650,37 @@ } }
+static void get_charset_statsW(struct enum_font_dataW *efd, + int *ansi_charset, int *symbol_charset, + int *russian_charset) +{ + int i; + + *ansi_charset = 0; + *symbol_charset = 0; + *russian_charset = 0; + + for (i = 0; i < efd->total; i++) + { + switch (efd->lf[i].lfCharSet) + { + case ANSI_CHARSET: + (*ansi_charset)++; + break; + case SYMBOL_CHARSET: + (*symbol_charset)++; + break; + case RUSSIAN_CHARSET: + (*russian_charset)++; + break; + } + } +} + static void test_EnumFontFamilies(const char *font_name, INT font_charset) { struct enum_font_data efd; + struct enum_font_dataW efdw; LOGFONT lf; HDC hdc; int i, ret, ansi_charset, symbol_charset, russian_charset; @@ -1319,29 +1700,39 @@ */ if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */ { - efd.total = 0; + /* + * Use EnumFontFamiliesW since win98 crashes when the + * second parameter is NULL using EnumFontFamilies + */ + efdw.total = 0; SetLastError(0xdeadbeef); - ret = EnumFontFamilies(hdc, NULL, arial_enum_proc, (LPARAM)&efd); - ok(ret, "EnumFontFamilies error %u\n", GetLastError()); - get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset); - trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n", - ansi_charset, symbol_charset, russian_charset); - ok(efd.total > 0, "no fonts enumerated: NULL\n"); - ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n"); - ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n"); - ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n"); - - efd.total = 0; + ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw); + ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW error %u\n", GetLastError()); + if(ret) + { + get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset); + trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n", + ansi_charset, symbol_charset, russian_charset); + ok(efdw.total > 0, "fonts enumerated: NULL\n"); + ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n"); + ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n"); + ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n"); + } + + efdw.total = 0; SetLastError(0xdeadbeef); - ret = EnumFontFamiliesEx(hdc, NULL, arial_enum_proc, (LPARAM)&efd, 0); - ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError()); - get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset); - trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n", - ansi_charset, symbol_charset, russian_charset); - ok(efd.total > 0, "no fonts enumerated: NULL\n"); - ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n"); - ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n"); - ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n"); + ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0); + ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW error %u\n", GetLastError()); + if(ret) + { + get_charset_statsW(&efdw, &ansi_charset, &symbol_charset, &russian_charset); + trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n", + ansi_charset, symbol_charset, russian_charset); + ok(efdw.total > 0, "fonts enumerated: NULL\n"); + ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n"); + ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n"); + ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n"); + } }
efd.total = 0; @@ -1502,6 +1893,12 @@ LOGFONTA lf2 = *lf; WORD idx; MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} }; + + if(!pGetGlyphIndicesA) + { + skip("GetGlyphIndicesA is unavailable\n"); + return; + }
/* negative widths are handled just as positive ones */ lf2.lfWidth = -lf->lfWidth; @@ -1633,8 +2030,6 @@ LONG size, ret; const char *font_name = lf->lfFaceName;
- trace("Testing font metrics for %s, charset %d\n", font_name, lf->lfCharSet); - hdc = GetDC(0);
SetLastError(0xdeadbeef); @@ -1660,21 +2055,19 @@ ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
version = GET_BE_WORD(tt_os2.version); - trace("OS/2 chunk version %u, vendor %4.4s\n", version, (LPCSTR)&tt_os2.achVendID);
first_unicode_char = GET_BE_WORD(tt_os2.usFirstCharIndex); last_unicode_char = GET_BE_WORD(tt_os2.usLastCharIndex); default_char = GET_BE_WORD(tt_os2.usDefaultChar); break_char = GET_BE_WORD(tt_os2.usBreakChar);
- trace("for %s first %x, last %x, default %x, break %x\n", font_name, - first_unicode_char, last_unicode_char, default_char, break_char); + trace("font %s charset %u: %x-%x default %x break %x OS/2 version %u vendor %4.4s\n", + font_name, lf->lfCharSet, first_unicode_char, last_unicode_char, default_char, break_char, + version, (LPCSTR)&tt_os2.achVendID);
SetLastError(0xdeadbeef); ret = GetTextMetricsA(hdc, &tmA); ok(ret, "GetTextMetricsA error %u\n", GetLastError()); - trace("A: first %x, last %x, default %x, break %x\n", - tmA.tmFirstChar, tmA.tmLastChar, tmA.tmDefaultChar, tmA.tmBreakChar);
#if 0 /* FIXME: This doesn't appear to be what Windows does */ test_char = min(first_unicode_char - 1, 255); @@ -1700,9 +2093,9 @@ "GetTextMetricsW error %u\n", GetLastError()); if (ret) { - trace("W: first %x, last %x, default %x, break %x\n", - tmW.tmFirstChar, tmW.tmLastChar, tmW.tmDefaultChar, - tmW.tmBreakChar); + trace("%04x-%04x (%02x-%02x) default %x (%x) break %x (%x)\n", + tmW.tmFirstChar, tmW.tmLastChar, tmA.tmFirstChar, tmA.tmLastChar, + tmW.tmDefaultChar, tmA.tmDefaultChar, tmW.tmBreakChar, tmA.tmBreakChar);
if (lf->lfCharSet == SYMBOL_CHARSET) { @@ -1775,16 +2168,40 @@
static void test_nonexistent_font(void) { + static const struct + { + const char *name; + int charset; + } font_subst[] = + { + { "Times New Roman Baltic", 186 }, + { "Times New Roman CE", 238 }, + { "Times New Roman CYR", 204 }, + { "Times New Roman Greek", 161 }, + { "Times New Roman TUR", 162 } + }; LOGFONTA lf; HDC hdc; HFONT hfont; + CHARSETINFO csi; + INT cs, expected_cs, i; char buf[LF_FACESIZE];
- if (!is_truetype_font_installed("Arial Black")) - { - skip("Arial not installed\n"); + if (!is_truetype_font_installed("Arial") || + !is_truetype_font_installed("Times New Roman")) + { + skip("Arial or Times New Roman not installed\n"); return; } + + expected_cs = GetACP(); + if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE)) + { + skip("TranslateCharsetInfo failed for code page %d\n", expected_cs); + return; + } + expected_cs = csi.ciCharset; + trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
hdc = GetDC(0);
@@ -1794,12 +2211,96 @@ lf.lfCharSet = ANSI_CHARSET; lf.lfPitchAndFamily = FF_SWISS; strcpy(lf.lfFaceName, "Nonexistent font"); - hfont = CreateFontIndirectA(&lf); hfont = SelectObject(hdc, hfont); GetTextFaceA(hdc, sizeof(buf), buf); ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf); + cs = GetTextCharset(hdc); + ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs); DeleteObject(SelectObject(hdc, hfont)); + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -13; + lf.lfWeight = FW_DONTCARE; + strcpy(lf.lfFaceName, "Nonexistent font"); + hfont = CreateFontIndirectA(&lf); + hfont = SelectObject(hdc, hfont); + GetTextFaceA(hdc, sizeof(buf), buf); +todo_wine /* Wine uses Arial for all substitutions */ + ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ || + !lstrcmpiA(buf, "MS Serif") || /* Win9x */ + !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */ + "Got %s\n", buf); + cs = GetTextCharset(hdc); + ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs); + DeleteObject(SelectObject(hdc, hfont)); + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -13; + lf.lfWeight = FW_REGULAR; + strcpy(lf.lfFaceName, "Nonexistent font"); + hfont = CreateFontIndirectA(&lf); + hfont = SelectObject(hdc, hfont); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ || + !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf); + cs = GetTextCharset(hdc); + ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs); + DeleteObject(SelectObject(hdc, hfont)); + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -13; + lf.lfWeight = FW_DONTCARE; + strcpy(lf.lfFaceName, "Times New Roman"); + hfont = CreateFontIndirectA(&lf); + hfont = SelectObject(hdc, hfont); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf); + cs = GetTextCharset(hdc); + ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs); + DeleteObject(SelectObject(hdc, hfont)); + + for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++) + { + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -13; + lf.lfWeight = FW_REGULAR; + strcpy(lf.lfFaceName, font_subst[i].name); + hfont = CreateFontIndirectA(&lf); + hfont = SelectObject(hdc, hfont); + cs = GetTextCharset(hdc); + if (font_subst[i].charset == expected_cs) + { + ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf); + } + else + { + ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ || + !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s\n", buf); + } + DeleteObject(SelectObject(hdc, hfont)); + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -13; + lf.lfWeight = FW_DONTCARE; + strcpy(lf.lfFaceName, font_subst[i].name); + hfont = CreateFontIndirectA(&lf); + hfont = SelectObject(hdc, hfont); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, "Arial") /* Wine */ || + !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ || + !lstrcmpiA(buf, "MS Serif") /* Win9x */ || + !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */ + "got %s\n", buf); + cs = GetTextCharset(hdc); + ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs); + DeleteObject(SelectObject(hdc, hfont)); + } + ReleaseDC(0, hdc); }
@@ -1850,12 +2351,137 @@ ReleaseDC(0, hdc); }
+/* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include + the nul in the count of characters copied when the face name buffer is not + NULL, whereas it does if the buffer is NULL. Further, the Unicode version + always includes it. */ +static void test_GetTextFace(void) +{ + static const char faceA[] = "Tahoma"; + static const WCHAR faceW[] = {'T','a','h','o','m','a', 0}; + LOGFONTA fA = {0}; + LOGFONTW fW = {0}; + char bufA[LF_FACESIZE]; + WCHAR bufW[LF_FACESIZE]; + HFONT f, g; + HDC dc; + int n; + + if(!is_font_installed("Tahoma")) + { + skip("Tahoma is not installed so skipping this test\n"); + return; + } + + /* 'A' case. */ + memcpy(fA.lfFaceName, faceA, sizeof faceA); + f = CreateFontIndirectA(&fA); + ok(f != NULL, "CreateFontIndirectA failed\n"); + + dc = GetDC(NULL); + g = SelectObject(dc, f); + n = GetTextFaceA(dc, sizeof bufA, bufA); + ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n); + ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n"); + + /* Play with the count arg. */ + bufA[0] = 'x'; + n = GetTextFaceA(dc, 0, bufA); + ok(n == 0, "GetTextFaceA returned %d\n", n); + ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]); + + bufA[0] = 'x'; + n = GetTextFaceA(dc, 1, bufA); + ok(n == 0, "GetTextFaceA returned %d\n", n); + ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]); + + bufA[0] = 'x'; bufA[1] = 'y'; + n = GetTextFaceA(dc, 2, bufA); + ok(n == 1, "GetTextFaceA returned %d\n", n); + ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n"); + + n = GetTextFaceA(dc, 0, NULL); + ok(n == sizeof faceA, "GetTextFaceA returned %d\n", n); + + DeleteObject(SelectObject(dc, g)); + ReleaseDC(NULL, dc); + + /* 'W' case. */ + memcpy(fW.lfFaceName, faceW, sizeof faceW); + SetLastError(0xdeadbeef); + f = CreateFontIndirectW(&fW); + if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("CreateFontIndirectW is not implemented\n"); + return; + } + ok(f != NULL, "CreateFontIndirectW failed\n"); + + dc = GetDC(NULL); + g = SelectObject(dc, f); + n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW); + ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n); + ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n"); + + /* Play with the count arg. */ + bufW[0] = 'x'; + n = GetTextFaceW(dc, 0, bufW); + ok(n == 0, "GetTextFaceW returned %d\n", n); + ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]); + + bufW[0] = 'x'; + n = GetTextFaceW(dc, 1, bufW); + ok(n == 1, "GetTextFaceW returned %d\n", n); + ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]); + + bufW[0] = 'x'; bufW[1] = 'y'; + n = GetTextFaceW(dc, 2, bufW); + ok(n == 2, "GetTextFaceW returned %d\n", n); + ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n"); + + n = GetTextFaceW(dc, 0, NULL); + ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n); + + DeleteObject(SelectObject(dc, g)); + ReleaseDC(NULL, dc); +} + +static void test_orientation(void) +{ + static const char test_str[11] = "Test String"; + HDC hdc; + LOGFONTA lf; + HFONT hfont, old_hfont; + SIZE size; + + if (!is_truetype_font_installed("Arial")) + { + skip("Arial is not installed\n"); + return; + } + + hdc = CreateCompatibleDC(0); + memset(&lf, 0, sizeof(lf)); + lstrcpyA(lf.lfFaceName, "Arial"); + lf.lfHeight = 72; + lf.lfOrientation = lf.lfEscapement = 900; + hfont = create_font("orientation", &lf); + old_hfont = SelectObject(hdc, hfont); + ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL, &size), "GetTextExtentExPointA failed\n"); + ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx); + ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + DeleteDC(hdc); +} + START_TEST(font) { init();
test_logfont(); test_bitmap_font(); + test_outline_font(); test_bitmap_font_metrics(); test_GdiGetCharDimensions(); test_GetCharABCWidths(); @@ -1867,6 +2493,7 @@ test_font_charset(); test_GetFontUnicodeRanges(); test_nonexistent_font(); + test_orientation();
/* On Windows Arial has a lot of default charset aliases such as Arial Cyr, * I'd like to avoid them in this test. @@ -1884,4 +2511,5 @@ skip("Arial Black or Symbol/Wingdings is not installed\n"); test_GetTextMetrics(); test_GdiRealizationInfo(); -} + test_GetTextFace(); +}
Modified: trunk/rostests/winetests/gdi32/gdiobj.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/gdiobj.c?r... ============================================================================== --- trunk/rostests/winetests/gdi32/gdiobj.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/gdiobj.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -43,7 +43,7 @@ */ SetLastError(0); hp = SelectObject(NULL, GetStockObject(BLACK_PEN)); - ok(!hp && GetLastError() == ERROR_INVALID_HANDLE, + ok(!hp && (GetLastError() == ERROR_INVALID_HANDLE || broken(!GetLastError())), "SelectObject(NULL DC) expected 0, ERROR_INVALID_HANDLE, got %p, %u\n", hp, GetLastError());
@@ -77,7 +77,7 @@ /* GetObject does not SetLastError() on a null object */ SetLastError(0); i = GetObjectA(NULL, sizeof(buff), buff); - ok (!i && !GetLastError(), + ok (!i && (GetLastError() == 0 || GetLastError() == ERROR_INVALID_PARAMETER), "GetObject(NULL obj), expected 0, NO_ERROR, got %d, %u\n", i, GetLastError());
@@ -207,7 +207,7 @@ hobj = GetCurrentObject(hdc, OBJ_PEN); ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj); hobj = GetCurrentObject(hdc, OBJ_EXTPEN); - ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj); + ok(hobj == hpen || broken(hobj == 0) /* win9x */, "OBJ_EXTPEN is wrong: %p\n", hobj);
hbrush = CreateSolidBrush(RGB(10, 20, 30)); assert(hbrush != 0); @@ -243,7 +243,7 @@ hobj = GetCurrentObject(hdc, OBJ_PEN); ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj); hobj = GetCurrentObject(hdc, OBJ_EXTPEN); - ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj); + ok(hobj == hpen || broken(hobj == 0) /* win9x */, "OBJ_EXTPEN is wrong: %p\n", hobj);
hcs = GetColorSpace(hdc); if (hcs) @@ -254,7 +254,7 @@ ok(hcs != 0, "CreateColorSpace failed\n"); SelectObject(hdc, hcs); hobj = GetCurrentObject(hdc, OBJ_COLORSPACE); - ok(hobj == hcs, "OBJ_COLORSPACE is wrong: %p\n", hobj); + ok(hobj == hcs || broken(hobj == 0) /* win9x */, "OBJ_COLORSPACE is wrong: %p\n", hobj); }
hrgn = CreateRectRgn(1, 1, 100, 100);
Modified: trunk/rostests/winetests/gdi32/icm.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/icm.c?rev=... ============================================================================== --- trunk/rostests/winetests/gdi32/icm.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/icm.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -51,20 +51,28 @@ ret = GetICMProfileA( dc, &size, NULL ); ok( !ret, "GetICMProfileA succeeded\n" );
- ret = GetICMProfileA( dc, NULL, filename ); - ok( !ret, "GetICMProfileA succeeded\n" ); - size = MAX_PATH; ret = GetICMProfileA( NULL, &size, filename ); ok( !ret, "GetICMProfileA succeeded\n" );
size = 0; + filename[0] = 0; SetLastError(0xdeadbeef); ret = GetICMProfileA( dc, &size, filename ); error = GetLastError(); ok( !ret, "GetICMProfileA succeeded\n" ); ok( size, "expected size > 0\n" ); - ok( error == ERROR_INSUFFICIENT_BUFFER, "got %d, expected ERROR_INSUFFICIENT_BUFFER\n", error ); + ok( filename[0] == 0, "Expected filename to be empty\n" ); + ok( error == ERROR_INSUFFICIENT_BUFFER || + error == ERROR_SUCCESS, /* Win95 */ + "got %d, expected ERROR_INSUFFICIENT_BUFFER or ERROR_SUCCESS(Win95)\n", error ); + + /* Next test will crash on Win95 */ + if ( error == ERROR_INSUFFICIENT_BUFFER ) + { + ret = GetICMProfileA( dc, NULL, filename ); + ok( !ret, "GetICMProfileA succeeded\n" ); + }
size = MAX_PATH; ret = GetICMProfileA( dc, &size, filename ); @@ -122,6 +130,15 @@ static void test_SetICMMode( HDC dc ) { INT ret, knob, save; + BOOL impl; + + SetLastError( 0xdeadbeef ); + impl = GetICMProfileA( NULL, NULL, NULL ); + if ( !impl && ( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED ) ) + { + skip( "On NT4 where SetICMMode is not implemented but this is not advertised\n" ); + return; + }
SetLastError( 0xdeadbeef ); ret = SetICMMode( NULL, 0 );
Modified: trunk/rostests/winetests/gdi32/mapping.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/mapping.c?... ============================================================================== --- trunk/rostests/winetests/gdi32/mapping.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/mapping.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -2,6 +2,7 @@ * Unit tests for mapping functions * * Copyright (c) 2005 Huw Davies + * Copyright (c) 2008 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +29,146 @@ #include "winuser.h" #include "winerror.h"
+#define rough_match(got, expected) (abs((got) - (expected)) <= 5) + +#define expect_LPtoDP(_hdc, _x, _y) \ +{ \ + POINT _pt = { 1000, 1000 }; \ + LPtoDP(_hdc, &_pt, 1); \ + ok(rough_match(_pt.x, _x), "expected x %d, got %d\n", (_x), _pt.x); \ + ok(rough_match(_pt.y, _y), "expected y %d, got %d\n", (_y), _pt.y); \ +} + +#define expect_world_trasform(_hdc, _em11, _em22) \ +{ \ + BOOL _ret; \ + XFORM _xform; \ + SetLastError(0xdeadbeef); \ + _ret = GetWorldTransform(_hdc, &_xform); \ + if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) \ + { \ + ok(_ret, "GetWorldTransform error %u\n", GetLastError()); \ + ok(_xform.eM11 == (_em11), "expected %f, got %f\n", (_em11), _xform.eM11); \ + ok(_xform.eM12 == 0.0, "expected 0.0, got %f\n", _xform.eM12); \ + ok(_xform.eM21 == 0.0, "expected 0.0, got %f\n", _xform.eM21); \ + ok(_xform.eM22 == (_em22), "expected %f, got %f\n", (_em22), _xform.eM22); \ + ok(_xform.eDx == 0.0, "expected 0.0, got %f\n", _xform.eDx); \ + ok(_xform.eDy == 0.0, "expected 0.0, got %f\n", _xform.eDy); \ + } \ +} + +#define expect_dc_ext(_func, _hdc, _cx, _cy) \ +{ \ + BOOL _ret; \ + SIZE _size; \ + SetLastError(0xdeadbeef); \ + _ret = _func(_hdc, &_size); \ + ok(_ret, #_func " error %u\n", GetLastError()); \ + ok(_size.cx == (_cx), "expected cx %d, got %d\n", (_cx), _size.cx); \ + ok(_size.cy == (_cy), "expected cy %d, got %d\n", (_cy), _size.cy); \ +} + +#define expect_viewport_ext(_hdc, _cx, _cy) expect_dc_ext(GetViewportExtEx, _hdc, _cx, _cy) +#define expect_window_ext(_hdc, _cx, _cy) expect_dc_ext(GetWindowExtEx, _hdc, _cx, _cy) + +static void test_world_transform(void) +{ + BOOL is_win9x; + HDC hdc; + INT ret, size_cx, size_cy, res_x, res_y; + XFORM xform; + + SetLastError(0xdeadbeef); + GetWorldTransform(0, NULL); + is_win9x = GetLastError() == ERROR_CALL_NOT_IMPLEMENTED; + + hdc = CreateCompatibleDC(0); + + size_cx = GetDeviceCaps(hdc, HORZSIZE); + size_cy = GetDeviceCaps(hdc, VERTSIZE); + res_x = GetDeviceCaps(hdc, HORZRES); + res_y = GetDeviceCaps(hdc, VERTRES); + trace("dc size %d x %d, resolution %d x %d\n", size_cx, size_cy, res_x, res_y); + + expect_viewport_ext(hdc, 1, 1); + expect_window_ext(hdc, 1, 1); + expect_world_trasform(hdc, 1.0, 1.0); + expect_LPtoDP(hdc, 1000, 1000); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_LOMETRIC); + ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret); + + if (is_win9x) + { + expect_viewport_ext(hdc, GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY)); + expect_window_ext(hdc, 254, -254); + } + else + { + expect_viewport_ext(hdc, res_x, -res_y); + expect_window_ext(hdc, size_cx * 10, size_cy * 10); + } + expect_world_trasform(hdc, 1.0, 1.0); + expect_LPtoDP(hdc, MulDiv(1000 / 10, res_x, size_cx), -MulDiv(1000 / 10, res_y, size_cy)); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_TEXT); + ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret); + + expect_viewport_ext(hdc, 1, 1); + expect_window_ext(hdc, 1, 1); + expect_world_trasform(hdc, 1.0, 1.0); + expect_LPtoDP(hdc, 1000, 1000); + + ret = SetGraphicsMode(hdc, GM_ADVANCED); + if (!ret) + { + DeleteDC(hdc); + skip("GM_ADVANCED is not supported on this platform\n"); + return; + } + + expect_viewport_ext(hdc, 1, 1); + expect_window_ext(hdc, 1, 1); + expect_world_trasform(hdc, 1.0, 1.0); + expect_LPtoDP(hdc, 1000, 1000); + + xform.eM11 = 20.0f; + xform.eM12 = 0.0f; + xform.eM21 = 0.0f; + xform.eM22 = 20.0f; + xform.eDx = 0.0f; + xform.eDy = 0.0f; + SetLastError(0xdeadbeef); + ret = SetWorldTransform(hdc, &xform); + ok(ret, "SetWorldTransform error %u\n", GetLastError()); + + expect_viewport_ext(hdc, 1, 1); + expect_window_ext(hdc, 1, 1); + expect_world_trasform(hdc, 20.0, 20.0); + expect_LPtoDP(hdc, 20000, 20000); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_LOMETRIC); + ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret); + + expect_viewport_ext(hdc, res_x, -res_y); + expect_window_ext(hdc, size_cx * 10, size_cy * 10); + expect_world_trasform(hdc, 20.0, 20.0); + expect_LPtoDP(hdc, MulDiv(1000 * 2, res_x, size_cx), -MulDiv(1000 * 2, res_y, size_cy)); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_TEXT); + ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret); + + expect_viewport_ext(hdc, 1, 1); + expect_window_ext(hdc, 1, 1); + expect_world_trasform(hdc, 20.0, 20.0); + expect_LPtoDP(hdc, 20000, 20000); + + DeleteDC(hdc); +}
static void test_modify_world_transform(void) { @@ -38,6 +179,7 @@ if(!ret) /* running in win9x so quit */ { ReleaseDC(0, hdc); + skip("GM_ADVANCED is not supported on this platform\n"); return; }
@@ -52,8 +194,6 @@
ReleaseDC(0, hdc); } - -#define rough_match(got, expected) ((got >= expected - 2) && (got <= expected + 2))
static void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy) { @@ -158,5 +298,6 @@ START_TEST(mapping) { test_modify_world_transform(); + test_world_transform(); test_isotropic_mapping(); }
Modified: trunk/rostests/winetests/gdi32/metafile.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/metafile.c... ============================================================================== --- trunk/rostests/winetests/gdi32/metafile.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/metafile.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -975,8 +975,24 @@ printf ("};\n"); }
+static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto) +{ + trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top, + eto->rclBounds.right, eto->rclBounds.bottom); + trace("iGraphicsMode %u\n", eto->iGraphicsMode); + trace("exScale: %f\n", eto->exScale); + trace("eyScale: %f\n", eto->eyScale); + trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y); + trace("emrtext.nChars %u\n", eto->emrtext.nChars); + trace("emrtext.offString %#x\n", eto->emrtext.offString); + trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions); + trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top, + eto->emrtext.rcl.right, eto->emrtext.rcl.bottom); + trace("emrtext.offDx %#x\n", eto->emrtext.offDx); +} + static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2, - const char *desc, BOOL todo) + const char *desc, BOOL ignore_scaling, BOOL todo) { int diff;
@@ -1010,7 +1026,37 @@ /* contents of EMR_GDICOMMENT are not interesting */ if (emr1->iType == EMR_GDICOMMENT) return TRUE;
- diff = memcmp(emr1->dParm, emr2->dParm, emr1->nSize - sizeof(EMR)); + /* different Windows versions setup DC scaling differently when + * converting an old style metafile to an EMF. + */ + if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX || + emr1->iType == EMR_SETVIEWPORTEXTEX)) + return TRUE; + + if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA) + { + EMREXTTEXTOUTW *eto1, *eto2; + + eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize); + memcpy(eto1, emr1, emr1->nSize); + eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize); + memcpy(eto2, emr2, emr2->nSize); + + /* different Windows versions setup DC scaling differently */ + eto1->exScale = eto1->eyScale = 0.0; + eto2->exScale = eto2->eyScale = 0.0; + + diff = memcmp(eto1, eto2, emr1->nSize); + if (diff) + { + dump_EMREXTTEXTOUT(eto1); + dump_EMREXTTEXTOUT(eto2); + } + HeapFree(GetProcessHeap(), 0, eto1); + HeapFree(GetProcessHeap(), 0, eto2); + } + else + diff = memcmp(emr1, emr2, emr1->nSize); if (diff && todo) { todo_wine @@ -1035,7 +1081,8 @@ * otherwise returns the number of non-matching bytes. */ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits, - UINT bsize, const char *desc, BOOL todo) + UINT bsize, const char *desc, + BOOL ignore_scaling, BOOL todo) { unsigned char buf[MF_BUFSIZE]; UINT mfsize, offset; @@ -1093,7 +1140,7 @@ trace("EMF record %u, size %u/record %u, size %u\n", emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
- if (!match_emf_record(emr1, emr2, desc, todo)) return -1; + if (!match_emf_record(emr1, emr2, desc, ignore_scaling, todo)) return -1;
offset += emr1->nSize; } @@ -1433,7 +1480,7 @@ * are there, but their contents don't match for different reasons. */ if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS), - "emf_TextOut_on_path", TRUE) != 0) + "emf_TextOut_on_path", FALSE, FALSE) != 0) { dump_emf_bits(hMetafile, "emf_TextOut_on_path"); dump_emf_records(hMetafile, "emf_TextOut_on_path"); @@ -1488,6 +1535,15 @@ } }
+/* Compare rectangles allowing rounding errors */ +static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2) +{ + return abs(rc1->left - rc2->left) <= 1 && + abs(rc1->top - rc2->top) <= 1 && + abs(rc1->right - rc2->right) <= 1 && + abs(rc1->bottom - rc2->bottom) <= 1; +} + static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, const ENHMETARECORD *emr, int n_objs, LPARAM param) { @@ -1574,7 +1630,7 @@ translate((POINT *)&rc_transformed, 2, &xform); trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top, rc_transformed.right, rc_transformed.bottom); - ok(EqualRect(&rect, &rc_transformed), "rects don't match\n"); + ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
rect = *(const RECT *)rgn2.data.Buffer; trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); @@ -1582,7 +1638,7 @@ translate((POINT *)&rc_transformed, 2, &xform); trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top, rc_transformed.right, rc_transformed.bottom); - ok(EqualRect(&rect, &rc_transformed), "rects don't match\n"); + ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
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); @@ -1620,7 +1676,7 @@ ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING), - "emf_clipping", TRUE) != 0) + "emf_clipping", FALSE, FALSE) != 0) { dump_emf_bits(hemf, "emf_clipping"); dump_emf_records(hemf, "emf_clipping"); @@ -1686,6 +1742,7 @@ { HDC hdcMf; HMETAFILE hmf; + HENHMETAFILE hemf; BOOL ret; UINT size; LPBYTE pBits; @@ -1708,7 +1765,9 @@ pBits = HeapAlloc(GetProcessHeap(), 0, size); GetMetaFileBitsEx(hmf, size, pBits); DeleteMetaFile(hmf); - return SetWinMetaFileBits(size, pBits, NULL, mfp); + hemf = SetWinMetaFileBits(size, pBits, NULL, mfp); + HeapFree(GetProcessHeap(), 0, pBits); + return hemf; }
static void test_mf_conversions(void) @@ -1726,7 +1785,7 @@ hemf = create_converted_emf(&mfp);
if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS), - "emf_LineTo MM_ANISOTROPIC", TRUE) != 0) + "emf_LineTo MM_ANISOTROPIC", TRUE, FALSE) != 0) { dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC"); dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC"); @@ -1751,7 +1810,7 @@ hemf = create_converted_emf(&mfp);
if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS), - "emf_LineTo MM_TEXT", TRUE) != 0) + "emf_LineTo MM_TEXT", TRUE, FALSE) != 0) { dump_emf_bits(hemf, "emf_LineTo MM_TEXT"); dump_emf_records(hemf, "emf_LineTo MM_TEXT"); @@ -1771,7 +1830,7 @@ hemf = create_converted_emf(NULL);
if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS), - "emf_LineTo NULL", TRUE) != 0) + "emf_LineTo NULL", TRUE, FALSE) != 0) { dump_emf_bits(hemf, "emf_LineTo NULL"); dump_emf_records(hemf, "emf_LineTo NULL"); @@ -1920,12 +1979,17 @@ ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
dc = CreateCompatibleDC(NULL); + + /* Allow 1 mm difference (rounding errors) */ + diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2; + diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2; + if (diffx < 0) diffx = -diffx; + if (diffy < 0) diffy = -diffy; todo_wine { - ok(rclBoundsAnisotropic.right == GetDeviceCaps(dc, HORZRES) / 2 - 1 && - rclBoundsAnisotropic.bottom == GetDeviceCaps(dc, VERTRES) / 2 - 1, + ok(diffx <= 1 && diffy <= 1, "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n", - GetDeviceCaps(dc, HORZRES) / 2 - 1, GetDeviceCaps(dc, VERTRES) / 2 - 1, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom); + GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom); }
/* Allow 1 mm difference (rounding errors) */ @@ -2012,9 +2076,11 @@ pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC"); pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
- /* they should all exist or none should exist */ - if(!pGdiIsMetaPrintDC) + if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC) + { + win_skip("Needed GdiIs* functions are not available\n"); return; + }
/* try with nothing */ ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n"); @@ -2053,7 +2119,9 @@ SetLastError(0xdeadbeef); hemf = SetEnhMetaFileBits(sizeof(data), data); ok(!hemf, "SetEnhMetaFileBits should fail\n"); - ok(GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %u\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_DATA || + GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */ + "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
emh = (ENHMETAHEADER *)data; memset(emh, 0, sizeof(*emh)); @@ -2075,15 +2143,23 @@ emh->nBytes++; SetLastError(0xdeadbeef); hemf = SetEnhMetaFileBits(emh->nBytes, data); - ok(!hemf, "SetEnhMetaFileBits should fail\n"); - /* XP doesn't set error in this case */ + ok(!hemf || + broken(hemf != NULL), /* Win9x, WinMe */ + "SetEnhMetaFileBits should fail\n"); + todo_wine + ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError()); + DeleteEnhMetaFile(hemf);
emh->dSignature = 0; emh->nBytes--; SetLastError(0xdeadbeef); hemf = SetEnhMetaFileBits(emh->nBytes, data); - ok(!hemf, "SetEnhMetaFileBits should fail\n"); - /* XP doesn't set error in this case */ + ok(!hemf || + broken(hemf != NULL), /* Win9x, WinMe */ + "SetEnhMetaFileBits should fail\n"); + todo_wine + ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError()); + DeleteEnhMetaFile(hemf); }
START_TEST(metafile)
Modified: trunk/rostests/winetests/gdi32/palette.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/palette.c?... ============================================================================== --- trunk/rostests/winetests/gdi32/palette.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/palette.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -110,7 +110,9 @@ SetPixel( memhdc, 0, 0, setColor ); chkColor = RGB( logpalettedata[3].peRed, logpalettedata[3].peGreen, logpalettedata[3].peBlue ); getColor = GetPixel( memhdc, 0, 0 ); - ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor ); + ok( getColor == chkColor || + broken(getColor == 0), /* win9x */ + "getColor=%08X\n", (UINT)getColor );
SelectPalette( memhdc, hpalOld, FALSE ); DeleteObject( hpal );
Modified: trunk/rostests/winetests/gdi32/pen.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/pen.c?rev=... ============================================================================== --- trunk/rostests/winetests/gdi32/pen.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/pen.c [iso-8859-1] Thu Nov 27 14:52:01 2008 @@ -29,6 +29,8 @@ #include "wine/test.h"
#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) +#define expect2(expected, alt, got) ok(got == expected || got == alt, \ + "Expected %.8x or %.8x, got %.8x\n", expected, alt, got)
static void test_logpen(void) { @@ -68,7 +70,7 @@
for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++) { - trace("testing style %u\n", pen[i].style); + trace("%d: testing style %u\n", i, pen[i].style);
/********************** cosmetic pens **********************/ /* CreatePenIndirect behaviour */ @@ -142,6 +144,7 @@ /* for some reason XP differentiates PS_NULL here */ if (pen[i].style == PS_NULL) { + ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n"); ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n", size, GetLastError()); ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, elp.elpPenStyle); ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth); @@ -204,7 +207,10 @@ obj_type = GetObjectType(hpen); /* for some reason XP differentiates PS_NULL here */ if (pen[i].style == PS_NULL) + { ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type); + ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n"); + } else ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
@@ -504,7 +510,7 @@
pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style); ok(pen == 0, "ExtCreatePen should fail\n"); - expect(0xdeadbeef, GetLastError()); + expect2(0xdeadbeef, ERROR_INVALID_PARAMETER, GetLastError()); DeleteObject(pen); SetLastError(0xdeadbeef);