Update gdi32 winetests, so we don't run out of things to fix.

svn path=/trunk/; revision=37695
This commit is contained in:
Gregor Schneider 2008-11-27 20:52:01 +00:00
parent 1301bd7eb6
commit f9e772b2a2
10 changed files with 1138 additions and 146 deletions

View file

@ -70,13 +70,15 @@ static INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp )
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 @@ static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHE
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 @@ static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHE
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 INT DIB_GetWidthBytes( int width, int bpp )
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 @@ static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER
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 @@ static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER
/* 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 @@ static void test_dibsections(void)
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 @@ static void test_bitmap(void)
HBITMAP hbmp, hbmp_old;
HDC hdc;
BITMAP bm;
BITMAP bma[2];
INT ret;
hdc = CreateCompatibleDC(0);
@ -974,7 +998,8 @@ static void test_bitmap(void)
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 @@ static void test_bitmap(void)
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 @@ static void test_GetDIBits_selected_DIB(UINT bpp)
/* 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 @@ static void test_GetDIBits_selected_DIB(UINT bpp)
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 @@ static void test_GetDIBits_selected_DDB(BOOL monochrome)
/* 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 @@ static void test_GetDIBits_selected_DDB(BOOL monochrome)
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 @@ static void test_GetDIBits_selected_DDB(BOOL monochrome)
}
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);
@ -1455,7 +1499,6 @@ static void test_GetDIBits(void)
"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",
@ -1474,6 +1517,16 @@ todo_wine
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);
@ -1502,7 +1555,6 @@ todo_wine
}
/* 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);
@ -1574,6 +1626,16 @@ todo_wine
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));
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
@ -1675,22 +1737,29 @@ static void test_GetDIBits_BI_BITFIELDS(void)
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);
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" );
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());
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" );
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 @@ static void test_CreateBitmap(void)
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 @@ void test_GdiAlphaBlend()
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;
@ -2120,6 +2189,51 @@ void test_GdiAlphaBlend()
}
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)
{
HMODULE hdll;
@ -2145,4 +2259,5 @@ START_TEST(bitmap)
test_GdiAlphaBlend();
test_bitmapinfoheadersize();
test_get16dibits();
test_clipping();
}

View file

@ -51,8 +51,10 @@ static void test_solidbrush(void)
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 @@ static void test_solidbrush(void)
}
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);
}
}

View file

@ -111,7 +111,9 @@ static void test_GetRandomRgn(void)
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);

View file

@ -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 @@ static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont)
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 @@ static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DW
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);
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);
GetTextMetricsA(hdc, &tm);
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(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, "lf %d != %d\n", lf.lfHeight, lfHeight);
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 @@ static void test_bitmap_font(void)
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,27 +331,285 @@ static void test_bitmap_font(void)
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)
{
LOGFONT *lf = (LOGFONT *)lParam;
@ -781,6 +1105,8 @@ static void test_GetKerningPairs(void)
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 @@ todo_wine {
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 @@ static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
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 @@ static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count
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 @@ static void test_GetFontUnicodeRanges(void)
ReleaseDC(NULL, hdc);
}
#define MAX_ENUM_FONTS 256
#define MAX_ENUM_FONTS 4096
struct enum_font_data
{
@ -1255,17 +1579,46 @@ struct enum_font_data
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_stats(struct enum_font_data *efd,
}
}
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 @@ static void test_EnumFontFamilies(const char *font_name, INT font_charset)
*/
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");
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");
}
efd.total = 0;
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;
@ -1503,6 +1894,12 @@ static void test_negative_width(HDC hdc, const LOGFONTA *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 @@ static void test_text_metrics(const LOGFONTA *lf)
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 @@ static void test_text_metrics(const LOGFONTA *lf)
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 @@ static void test_text_metrics(const LOGFONTA *lf)
"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,17 +2168,41 @@ static void test_GetTextMetrics(void)
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"))
if (!is_truetype_font_installed("Arial") ||
!is_truetype_font_installed("Times New Roman"))
{
skip("Arial not installed\n");
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);
memset(&lf, 0, sizeof(lf));
@ -1794,12 +2211,96 @@ static void test_nonexistent_font(void)
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 @@ static void test_GdiRealizationInfo(void)
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 @@ START_TEST(font)
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 @@ START_TEST(font)
skip("Arial Black or Symbol/Wingdings is not installed\n");
test_GetTextMetrics();
test_GdiRealizationInfo();
test_GetTextFace();
}

View file

@ -43,7 +43,7 @@ static void test_gdi_objects(void)
*/
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 @@ static void test_gdi_objects(void)
/* 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 @@ static void test_GetCurrentObject(void)
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 @@ static void test_GetCurrentObject(void)
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 @@ static void test_GetCurrentObject(void)
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);

View file

@ -51,20 +51,28 @@ static void test_GetICMProfileA( HDC dc )
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_GetICMProfileW( HDC dc )
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 );

View file

@ -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 @@ static void test_modify_world_transform(void)
if(!ret) /* running in win9x so quit */
{
ReleaseDC(0, hdc);
skip("GM_ADVANCED is not supported on this platform\n");
return;
}
@ -53,8 +195,6 @@ static void test_modify_world_transform(void)
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)
{
SIZE windowExt, viewportExt;
@ -158,5 +298,6 @@ static void test_isotropic_mapping(void)
START_TEST(mapping)
{
test_modify_world_transform();
test_world_transform();
test_isotropic_mapping();
}

View file

@ -975,8 +975,24 @@ static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
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 @@ static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr
/* 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 @@ static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr
* 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 @@ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
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 @@ static void test_emf_ExtTextOut_on_path(void)
* 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 @@ static void translate( POINT *pt, UINT count, const XFORM *xform )
}
}
/* 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 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
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 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
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 @@ static void test_emf_clipping(void)
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 @@ static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
{
HDC hdcMf;
HMETAFILE hmf;
HENHMETAFILE hemf;
BOOL ret;
UINT size;
LPBYTE pBits;
@ -1708,7 +1765,9 @@ static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
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 @@ static void test_mf_conversions(void)
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 @@ static void test_mf_conversions(void)
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 @@ static void test_mf_conversions(void)
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 @@ static void test_SetWinMetaFileBits(void)
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 @@ static void test_gdiis(void)
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 @@ static void test_SetEnhMetaFileBits(void)
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 @@ static void test_SetEnhMetaFileBits(void)
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)

View file

@ -110,7 +110,9 @@ static void test_DIB_PAL_COLORS(void) {
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 );

View file

@ -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 @@ static void test_logpen(void)
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 @@ static void test_logpen(void)
/* 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 @@ static void test_logpen(void)
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 @@ static void test_ps_userstyle(void)
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);