[GDI32_WINETEST] Sync with Wine Staging 1.9.11. CORE-11368 CORE-11331

svn path=/trunk/; revision=71779
This commit is contained in:
Amine Khaldi 2016-07-03 11:29:52 +00:00
parent b5f83611ac
commit 5ed7ca77cb
4 changed files with 853 additions and 68 deletions

View file

@ -23,15 +23,25 @@
#include <assert.h>
#include <string.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmsystem.h"
#include "wine/winternl.h"
#ifndef __REACTOS__ /* CORE-11331 */
#include "wine/ddk/d3dkmthk.h"
#endif
#include "wine/test.h"
#ifndef __REACTOS__ /* CORE-11331 */
static NTSTATUS (WINAPI *pD3DKMTCreateDCFromMemory)( D3DKMT_CREATEDCFROMMEMORY *desc );
static NTSTATUS (WINAPI *pD3DKMTDestroyDCFromMemory)( const D3DKMT_DESTROYDCFROMMEMORY *desc );
#endif
static BOOL (WINAPI *pGdiAlphaBlend)(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION);
static BOOL (WINAPI *pGdiGradientFill)(HDC,TRIVERTEX*,ULONG,void*,ULONG,ULONG);
static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
@ -5651,14 +5661,265 @@ static void test_SetDIBitsToDevice_RLE8(void)
HeapFree( GetProcessHeap(), 0, info );
}
#ifndef __REACTOS__ /* CORE-11331 */
static void test_D3DKMTCreateDCFromMemory( void )
{
D3DKMT_DESTROYDCFROMMEMORY destroy_desc;
D3DKMT_CREATEDCFROMMEMORY create_desc;
unsigned int width_bytes;
unsigned int i, x, y, z;
DWORD expected, colour;
BYTE data[12][48];
NTSTATUS status;
HGDIOBJ *bitmap;
DIBSECTION dib;
BOOL fail, ret;
DWORD type;
int size;
static const struct
{
const char *name;
D3DDDIFORMAT format;
unsigned int bit_count;
DWORD mask_r, mask_g, mask_b;
NTSTATUS status;
}
test_data[] =
{
{ "R8G8B8", D3DDDIFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS },
{ "A8R8G8B8", D3DDDIFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS },
{ "X8R8G8B8", D3DDDIFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS },
{ "R5G6B5", D3DDDIFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, STATUS_SUCCESS },
{ "X1R5G5B5", D3DDDIFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, STATUS_SUCCESS },
{ "A1R5G5B5", D3DDDIFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, STATUS_SUCCESS },
{ "R3G3B2", D3DDDIFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "A2B10G10R10", D3DDDIFMT_A2B10G10R10, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "A8B8G8R8", D3DDDIFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "X8B8G8R8", D3DDDIFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "A2R10G10B10", D3DDDIFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "P8", D3DDDIFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS },
{ "L8", D3DDDIFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "A8L8", D3DDDIFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "V8U8", D3DDDIFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "Q8W8V8U8", D3DDDIFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "DXT1", D3DDDIFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "DXT2", D3DDDIFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "DXT3", D3DDDIFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "DXT4", D3DDDIFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
{ "DXT5", D3DDDIFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER },
};
if (!pD3DKMTCreateDCFromMemory)
{
win_skip("D3DKMTCreateDCFromMemory() is not implemented.\n");
return;
}
status = pD3DKMTCreateDCFromMemory( NULL );
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status);
for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
{
memset( data, 0xaa, sizeof(data) );
create_desc.pMemory = data;
create_desc.Format = test_data[i].format;
create_desc.Width = 9;
create_desc.Height = 7;
create_desc.Pitch = sizeof(*data);
create_desc.hDeviceDc = NULL;
create_desc.pColorTable = NULL;
create_desc.hDc = (void *)0x010baade;
create_desc.hBitmap = (void *)0x020baade;
status = pD3DKMTCreateDCFromMemory( &create_desc );
ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n",
test_data[i].name, status);
create_desc.hDeviceDc = CreateCompatibleDC( NULL );
create_desc.pMemory = NULL;
status = pD3DKMTCreateDCFromMemory( &create_desc );
ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n",
test_data[i].name, status);
create_desc.pMemory = data;
create_desc.Height = 0;
status = pD3DKMTCreateDCFromMemory( &create_desc );
ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n",
test_data[i].name, status);
ok(create_desc.hDc == (void *)0x010baade, "%s: Got unexpected dc %p.\n",
test_data[i].name, create_desc.hDc);
ok(create_desc.hBitmap == (void *)0x020baade, "%s: Got unexpected bitmap %p.\n",
test_data[i].name, create_desc.hBitmap);
create_desc.Height = 7;
create_desc.Width = 0;
status = pD3DKMTCreateDCFromMemory( &create_desc );
ok(status == test_data[i].status, "%s: Got unexpected status %#x, expected %#x.\n",
test_data[i].name, status, test_data[i].status);
if (status == STATUS_SUCCESS)
{
destroy_desc.hDc = create_desc.hDc;
destroy_desc.hBitmap = create_desc.hBitmap;
status = pD3DKMTDestroyDCFromMemory( &destroy_desc );
ok(status == STATUS_SUCCESS, "%s: Got unexpected status %#x.\n", test_data[i].name, status);
create_desc.hDc = (void *)0x010baade;
create_desc.hBitmap = (void *)0x020baade;
}
create_desc.Pitch = 0;
status = pD3DKMTCreateDCFromMemory( &create_desc );
ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n",
test_data[i].name, status);
ok(create_desc.hDc == (void *)0x010baade, "%s: Got unexpected dc %p.\n",
test_data[i].name, create_desc.hDc);
ok(create_desc.hBitmap == (void *)0x020baade, "%s: Got unexpected bitmap %p.\n",
test_data[i].name, create_desc.hBitmap);
create_desc.Width = 9;
create_desc.Pitch = sizeof(*data);
status = pD3DKMTCreateDCFromMemory( &create_desc );
ok(status == test_data[i].status, "%s: Got unexpected status %#x, expected %#x.\n",
test_data[i].name, status, test_data[i].status);
if (status == STATUS_SUCCESS)
{
ok(!!create_desc.hDc, "%s: Got unexpected dc %p.\n",
test_data[i].name, create_desc.hDc);
ok(!!create_desc.hBitmap, "%s: Got unexpected bitmap %p.\n",
test_data[i].name, create_desc.hBitmap);
}
else
{
ok(create_desc.hDc == (void *)0x010baade, "%s: Got unexpected dc %p.\n",
test_data[i].name, create_desc.hDc);
ok(create_desc.hBitmap == (void *)0x020baade, "%s: Got unexpected bitmap %p.\n",
test_data[i].name, create_desc.hBitmap);
continue;
}
type = GetObjectType( create_desc.hDc );
ok(type == OBJ_MEMDC, "%s: Got unexpected object type %#x.\n", test_data[i].name, type);
type = GetObjectType( create_desc.hBitmap );
ok(type == OBJ_BITMAP, "%s: Got unexpected object type %#x.\n", test_data[i].name, type);
bitmap = GetCurrentObject( create_desc.hDc, OBJ_BITMAP );
ok(bitmap == create_desc.hBitmap, "%s: Got unexpected bitmap %p, expected %p.\n",
test_data[i].name, bitmap, create_desc.hBitmap);
size = GetObjectA( bitmap, sizeof(dib), &dib );
ok(size == sizeof(dib), "%s: Got unexpected size %d.\n", test_data[i].name, size);
ok(!dib.dsBm.bmType, "%s: Got unexpected type %#x.\n",
test_data[i].name, dib.dsBm.bmType);
ok(dib.dsBm.bmWidth == create_desc.Width, "%s: Got unexpected width %d.\n",
test_data[i].name, dib.dsBm.bmWidth);
ok(dib.dsBm.bmHeight == create_desc.Height, "%s: Got unexpected height %d.\n",
test_data[i].name, dib.dsBm.bmHeight);
width_bytes = get_dib_stride( create_desc.Width, test_data[i].bit_count );
ok(dib.dsBm.bmWidthBytes == width_bytes, "%s: Got unexpected width bytes %d.\n",
test_data[i].name, dib.dsBm.bmWidthBytes);
ok(dib.dsBm.bmPlanes == 1, "%s: Got unexpected plane count %d.\n",
test_data[i].name, dib.dsBm.bmPlanes);
ok(dib.dsBm.bmBitsPixel == test_data[i].bit_count, "%s: Got unexpected bit count %d.\n",
test_data[i].name, dib.dsBm.bmBitsPixel);
ok(dib.dsBm.bmBits == create_desc.pMemory, "%s: Got unexpected bits %p, expected %p.\n",
test_data[i].name, dib.dsBm.bmBits, create_desc.pMemory);
ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "%s: Got unexpected size %u.\n",
test_data[i].name, dib.dsBmih.biSize);
ok(dib.dsBmih.biWidth == create_desc.Width, "%s: Got unexpected width %d.\n",
test_data[i].name, dib.dsBmih.biHeight);
ok(dib.dsBmih.biHeight == create_desc.Height, "%s: Got unexpected height %d.\n",
test_data[i].name, dib.dsBmih.biHeight);
ok(dib.dsBmih.biPlanes == 1, "%s: Got unexpected plane count %u.\n",
test_data[i].name, dib.dsBmih.biPlanes);
ok(dib.dsBmih.biBitCount == test_data[i].bit_count, "%s: Got unexpected bit count %u.\n",
test_data[i].name, dib.dsBmih.biBitCount);
ok(dib.dsBmih.biCompression == (test_data[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
"%s: Got unexpected compression %#x.\n",
test_data[i].name, dib.dsBmih.biCompression);
ok(!dib.dsBmih.biSizeImage, "%s: Got unexpected image size %u.\n",
test_data[i].name, dib.dsBmih.biSizeImage);
ok(!dib.dsBmih.biXPelsPerMeter, "%s: Got unexpected horizontal resolution %d.\n",
test_data[i].name, dib.dsBmih.biXPelsPerMeter);
ok(!dib.dsBmih.biYPelsPerMeter, "%s: Got unexpected vertical resolution %d.\n",
test_data[i].name, dib.dsBmih.biYPelsPerMeter);
if (test_data[i].format == D3DDDIFMT_P8)
{
ok(dib.dsBmih.biClrUsed == 256, "%s: Got unexpected used colour count %u.\n",
test_data[i].name, dib.dsBmih.biClrUsed);
ok(dib.dsBmih.biClrImportant == 256, "%s: Got unexpected important colour count %u.\n",
test_data[i].name, dib.dsBmih.biClrImportant);
}
else
{
ok(!dib.dsBmih.biClrUsed, "%s: Got unexpected used colour count %u.\n",
test_data[i].name, dib.dsBmih.biClrUsed);
ok(!dib.dsBmih.biClrImportant, "%s: Got unexpected important colour count %u.\n",
test_data[i].name, dib.dsBmih.biClrImportant);
}
ok(dib.dsBitfields[0] == test_data[i].mask_r && dib.dsBitfields[1] == test_data[i].mask_g
&& dib.dsBitfields[2] == test_data[i].mask_b,
"%s: Got unexpected colour masks 0x%08x 0x%08x 0x%08x.\n",
test_data[i].name, dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2]);
ok(!dib.dshSection, "%s: Got unexpected section %p.\n", test_data[i].name, dib.dshSection);
ok(!dib.dsOffset, "%s: Got unexpected offset %u.\n", test_data[i].name, dib.dsOffset);
ret = BitBlt( create_desc.hDc, 0, 0, 4, 10, NULL, 0, 0, BLACKNESS );
ok(ret, "Failed to blit.\n");
ret = BitBlt( create_desc.hDc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS );
ok(ret, "Failed to blit.\n");
destroy_desc.hDc = create_desc.hDc;
destroy_desc.hBitmap = create_desc.hBitmap;
status = pD3DKMTDestroyDCFromMemory( NULL );
ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", test_data[i].name, status);
status = pD3DKMTDestroyDCFromMemory( &destroy_desc );
ok(status == STATUS_SUCCESS, "%s: Got unexpected status %#x.\n", test_data[i].name, status);
status = pD3DKMTDestroyDCFromMemory( &destroy_desc );
ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", test_data[i].name, status);
ret = DeleteDC( create_desc.hDeviceDc );
ok(ret, "Failed to delete dc.\n");
for (y = 0, fail = FALSE; y < 12 && !fail; ++y)
{
for (x = 0; x < sizeof(*data) / (test_data[i].bit_count / 8) && !fail; ++x)
{
for (z = 0, colour = 0; z < test_data[i].bit_count / 8; ++z)
{
colour = colour << 8 | data[y][x * (test_data[i].bit_count / 8) + z];
}
if ((x == 1 || x == 2) && (y == 1 || y == 2))
expected = 0xffffffff >> (32 - test_data[i].bit_count);
else if (x < 4 && y < 7)
expected = 0x00000000;
else
expected = 0xaaaaaaaa >> (32 - test_data[i].bit_count);
ok(colour == expected, "%s: Got unexpected colour 0x%08x at %u, %u, expected 0x%08x.\n",
test_data[i].name, colour, x, y, expected);
if (colour != expected)
fail = TRUE;
}
}
}
}
#endif /* __REACTOS__ */
START_TEST(bitmap)
{
HMODULE hdll;
hdll = GetModuleHandleA("gdi32.dll");
pGdiAlphaBlend = (void*)GetProcAddress(hdll, "GdiAlphaBlend");
pGdiGradientFill = (void*)GetProcAddress(hdll, "GdiGradientFill");
pSetLayout = (void*)GetProcAddress(hdll, "SetLayout");
#ifndef __REACTOS__ /* CORE-11331 */
pD3DKMTCreateDCFromMemory = (void *)GetProcAddress( hdll, "D3DKMTCreateDCFromMemory" );
pD3DKMTDestroyDCFromMemory = (void *)GetProcAddress( hdll, "D3DKMTDestroyDCFromMemory" );
#endif
pGdiAlphaBlend = (void *)GetProcAddress( hdll, "GdiAlphaBlend" );
pGdiGradientFill = (void *)GetProcAddress( hdll, "GdiGradientFill" );
pSetLayout = (void *)GetProcAddress( hdll, "SetLayout" );
test_createdibitmap();
test_dibsections();
@ -5695,4 +5956,7 @@ START_TEST(bitmap)
test_SetDIBits_RLE8();
test_SetDIBitsToDevice();
test_SetDIBitsToDevice_RLE8();
#ifndef __REACTOS__ /* CORE-11331 */
test_D3DKMTCreateDCFromMemory();
#endif
}

View file

@ -2,7 +2,7 @@
* Unit tests for dc functions
*
* Copyright (c) 2005 Huw Davies
* Copyright (c) 2005 Dmitry Timoshkov
* Copyright (c) 2005,2016 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -812,7 +812,6 @@ static void test_DeleteDC(void)
ok(ret, "UnregisterClassA failed\n");
ret = GetObjectType(hdc_test);
todo_wine
ok(!ret, "GetObjectType should fail for a deleted DC\n");
/* CS_OWNDC */
@ -891,7 +890,7 @@ static void test_boundsrect(void)
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_RESET,
"Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
SetRect(&expect, 0, 0, 0, 0);
SetRectEmpty(&expect);
ok(EqualRect(&rect, &expect) ||
broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
"Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
@ -986,7 +985,7 @@ static void test_boundsrect(void)
"GetBoundsRect returned %x\n", ret);
if (ret == DCB_RESET)
{
SetRect(&expect, 0, 0, 0, 0);
SetRectEmpty(&expect);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
@ -995,7 +994,7 @@ static void test_boundsrect(void)
ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
ret = GetBoundsRect(hdc, &rect, 0);
ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
SetRect(&expect, 0, 0, 0, 0);
SetRectEmpty(&expect);
ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
rect.left, rect.top, rect.right, rect.bottom);
}
@ -1386,6 +1385,119 @@ static void test_printer_dc(void)
DeleteObject( bmp );
}
static void print_something(HDC hdc)
{
static const char psadobe[10] = "%!PS-Adobe";
char buf[1024], *p;
char temp_path[MAX_PATH], file_name[MAX_PATH];
DOCINFOA di;
DWORD ret;
HANDLE hfile;
GetTempPathA(sizeof(temp_path), temp_path);
GetTempFileNameA(temp_path, "ps", 0, file_name);
di.cbSize = sizeof(di);
di.lpszDocName = "Let's dance";
di.lpszOutput = file_name;
di.lpszDatatype = NULL;
di.fwType = 0;
ret = StartDocA(hdc, &di);
ok(ret > 0, "StartDoc failed: %d\n", ret);
strcpy(buf + 2, "\n% ===> before DOWNLOADHEADER <===\n");
*(WORD *)buf = strlen(buf + 2);
ret = Escape(hdc, POSTSCRIPT_PASSTHROUGH, 0, buf, NULL);
ok(ret == *(WORD *)buf, "POSTSCRIPT_PASSTHROUGH failed: %d\n", ret);
strcpy(buf, "deadbeef");
ret = ExtEscape(hdc, DOWNLOADHEADER, 0, NULL, sizeof(buf), buf );
ok(ret == 1, "DOWNLOADHEADER failed\n");
ok(strcmp(buf, "deadbeef") != 0, "DOWNLOADHEADER failed\n");
strcpy(buf + 2, "\n% ===> after DOWNLOADHEADER <===\n");
*(WORD *)buf = strlen(buf + 2);
ret = Escape(hdc, POSTSCRIPT_PASSTHROUGH, 0, buf, NULL);
ok(ret == *(WORD *)buf, "POSTSCRIPT_PASSTHROUGH failed: %d\n", ret);
ret = EndDoc(hdc);
ok(ret == 1, "EndDoc failed\n");
hfile = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
memset(buf, 0, sizeof(buf));
ret = ReadFile(hfile, buf, sizeof(buf), &ret, NULL);
ok(ret, "ReadFile failed\n");
CloseHandle(hfile);
/* skip the HP PCL language selector */
buf[sizeof(buf) - 1] = 0;
p = buf;
while (*p)
{
if (!(p[0] == 0x1b && p[1] == '%') && memcmp(p, "@PJL", 4) != 0)
break;
p = strchr(p, '\n');
if (!p) break;
while (*p == '\r' || *p == '\n') p++;
}
ok(p && !memcmp(p, psadobe, sizeof(psadobe)), "wrong signature: %.14s\n", p ? p : buf);
DeleteFileA(file_name);
}
static void test_pscript_printer_dc(void)
{
HDC hdc;
char buf[256];
DWORD query, ret;
hdc = create_printer_dc(100, FALSE);
if (!hdc) return;
if (!is_postscript_printer(hdc))
{
skip("Default printer is not a PostScript device\n");
DeleteDC( hdc );
return;
}
query = GETFACENAME;
ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
ok(!ret, "GETFACENAME is supported\n");
query = DOWNLOADFACE;
ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
ok(ret == 1, "DOWNLOADFACE is not supported\n");
query = OPENCHANNEL;
ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
ok(ret == 1, "OPENCHANNEL is not supported\n");
query = DOWNLOADHEADER;
ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
ok(ret == 1, "DOWNLOADHEADER is not supported\n");
query = CLOSECHANNEL;
ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
ok(ret == 1, "CLOSECHANNEL is not supported\n");
query = POSTSCRIPT_PASSTHROUGH;
ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
ok(ret == 1, "POSTSCRIPT_PASSTHROUGH is not supported\n");
ret = ExtEscape(hdc, GETFACENAME, 0, NULL, sizeof(buf), buf);
ok(ret == 1, "GETFACENAME failed\n");
trace("face name: %s\n", buf);
print_something(hdc);
DeleteDC(hdc);
}
START_TEST(dc)
{
pSetLayout = (void *)GetProcAddress( GetModuleHandleA("gdi32.dll"), "SetLayout");
@ -1400,4 +1512,5 @@ START_TEST(dc)
test_desktop_colorres();
test_gamma();
test_printer_dc();
test_pscript_printer_dc();
}

View file

@ -107,6 +107,22 @@ static void init(void)
system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID());
}
static void *heap_alloc( size_t len )
{
return HeapAlloc( GetProcessHeap(), 0, len );
}
static void *heap_realloc( void *p, size_t len )
{
if (!p) return heap_alloc( len );
return HeapReAlloc( GetProcessHeap(), 0, p, len );
}
static void heap_free( void *p )
{
HeapFree( GetProcessHeap(), 0, p );
}
static INT CALLBACK is_truetype_font_installed_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
{
if (type != TRUETYPE_FONTTYPE) return 1;
@ -1016,7 +1032,7 @@ static void test_bitmap_font_metrics(void)
ok(ret == expected_cs, "got charset %d, expected %d\n", ret, expected_cs);
trace("created %s, height %d charset %x dpi %d\n", face_name, tm.tmHeight, tm.tmCharSet, tm.tmDigitizedAspectX);
trace("expected %s, height %d scaled_hight %d, dpi %d\n", fd[i].face_name, height, fd[i].scaled_height, fd[i].dpi);
trace("expected %s, height %d scaled_height %d, dpi %d\n", fd[i].face_name, height, fd[i].scaled_height, fd[i].dpi);
if(fd[i].dpi == tm.tmDigitizedAspectX)
{
@ -2736,24 +2752,22 @@ static void test_GetFontUnicodeRanges(void)
ReleaseDC(NULL, hdc);
}
#define MAX_ENUM_FONTS 4096
struct enum_font_data
{
int total;
LOGFONTA lf[MAX_ENUM_FONTS];
int total, size;
LOGFONTA *lf;
};
struct enum_fullname_data
{
int total;
ENUMLOGFONTA elf[MAX_ENUM_FONTS];
int total, size;
ENUMLOGFONTA *elf;
};
struct enum_font_dataW
{
int total;
LOGFONTW lf[MAX_ENUM_FONTS];
int total, size;
LOGFONTW *lf;
};
static INT CALLBACK arial_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
@ -2771,10 +2785,13 @@ static INT CALLBACK arial_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, D
if (0) /* Disabled to limit console spam */
trace("enumed font \"%s\", charset %d, height %d, weight %d, italic %d\n",
lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
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);
if (efd->total >= efd->size)
{
efd->size = max( (efd->total + 1) * 2, 256 );
efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
if (!efd->lf) return 0;
}
efd->lf[efd->total++] = *lf;
return 1;
}
@ -2794,10 +2811,13 @@ static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm,
if (0) /* Disabled to limit console spam */
trace("enumed font %s, charset %d, height %d, weight %d, italic %d\n",
wine_dbgstr_w(lf->lfFaceName), lf->lfCharSet, lf->lfHeight, lf->lfWeight, lf->lfItalic);
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);
if (efd->total >= efd->size)
{
efd->size = max( (efd->total + 1) * 2, 256 );
efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
if (!efd->lf) return 0;
}
efd->lf[efd->total++] = *lf;
return 1;
}
@ -2871,6 +2891,8 @@ static void test_EnumFontFamilies(const char *font_name, INT font_charset)
skip("%s is not installed\n", font_name);
return;
}
memset( &efd, 0, sizeof(efd) );
memset( &efdw, 0, sizeof(efdw) );
hdc = GetDC(0);
@ -3064,6 +3086,9 @@ else
}
ReleaseDC(0, hdc);
heap_free( efd.lf );
heap_free( efdw.lf );
}
static INT CALLBACK enum_multi_charset_font_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lParam)
@ -3093,10 +3118,13 @@ static INT CALLBACK enum_font_data_proc(const LOGFONTA *lf, const TEXTMETRICA *n
if (type != TRUETYPE_FONTTYPE) return 1;
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);
if (efd->total >= efd->size)
{
efd->size = max( (efd->total + 1) * 2, 256 );
efd->lf = heap_realloc( efd->lf, efd->size * sizeof(*efd->lf) );
if (!efd->lf) return 0;
}
efd->lf[efd->total++] = *lf;
return 1;
}
@ -3107,10 +3135,13 @@ static INT CALLBACK enum_fullname_data_proc(const LOGFONTA *lf, const TEXTMETRIC
if (type != TRUETYPE_FONTTYPE) return 1;
if (efnd->total < MAX_ENUM_FONTS)
efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
else
trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS);
if (efnd->total >= efnd->size)
{
efnd->size = max( (efnd->total + 1) * 2, 256 );
efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
if (!efnd->elf) return 0;
}
efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
return 1;
}
@ -3144,7 +3175,7 @@ static void test_EnumFontFamiliesEx_default_charset(void)
target.lfCharSet = ANSI_CHARSET;
}
efd.total = 0;
memset(&efd, 0, sizeof(efd));
memset(&enum_font, 0, sizeof(enum_font));
strcpy(enum_font.lfFaceName, target.lfFaceName);
enum_font.lfCharSet = DEFAULT_CHARSET;
@ -3152,15 +3183,14 @@ static void test_EnumFontFamiliesEx_default_charset(void)
ReleaseDC(0, hdc);
trace("'%s' has %d charsets.\n", target.lfFaceName, efd.total);
if (efd.total < 2) {
if (efd.total < 2)
ok(0, "EnumFontFamilies is broken. Expected >= 2, got %d.\n", efd.total);
return;
}
ok(efd.lf[0].lfCharSet == target.lfCharSet,
"(%s) got charset %d expected %d\n",
efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, target.lfCharSet);
else
ok(efd.lf[0].lfCharSet == target.lfCharSet,
"(%s) got charset %d expected %d\n",
efd.lf[0].lfFaceName, efd.lf[0].lfCharSet, target.lfCharSet);
heap_free(efd.lf);
return;
}
@ -5215,6 +5245,12 @@ if (0) /* Disabled to limit console spam */
if (type != TRUETYPE_FONTTYPE) return 1;
if (strcmp(lf->lfFaceName, "MS Shell Dlg") != 0) return 1;
if (efnd->total >= efnd->size)
{
efnd->size = max( (efnd->total + 1) * 2, 256 );
efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
if (!efnd->elf) return 0;
}
efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
return 0;
}
@ -5230,6 +5266,12 @@ if (0) /* Disabled to limit console spam */
if (type != TRUETYPE_FONTTYPE) return 1;
if (strcmp(lf->lfFaceName, "MS Shell Dlg 2") != 0) return 1;
if (efnd->total >= efnd->size)
{
efnd->size = max( (efnd->total + 1) * 2, 256 );
efnd->elf = heap_realloc( efnd->elf, efnd->size * sizeof(*efnd->elf) );
if (!efnd->elf) return 0;
}
efnd->elf[efnd->total++] = *(ENUMLOGFONTA *)lf;
return 0;
}
@ -5261,7 +5303,7 @@ static void test_EnumFonts_subst(void)
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET;
memset(&efnd, 0, sizeof(efnd));
efnd.total = 0;
strcpy(lf.lfFaceName, "MS Shell Dlg");
ret = EnumFontFamiliesExA(hdc, &lf, enum_ms_shell_dlg_proc, (LPARAM)&efnd, 0);
ok(!ret, "MS Shell Dlg should be enumerated\n");
@ -5271,12 +5313,12 @@ static void test_EnumFonts_subst(void)
ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg");
ok(ret, "did not expect MS Shell Dlg\n");
memset(&efnd, 0, sizeof(efnd));
efnd.total = 0;
ret = EnumFontFamiliesExA(hdc, NULL, enum_ms_shell_dlg2_proc, (LPARAM)&efnd, 0);
ok(ret, "MS Shell Dlg 2 should not be enumerated\n");
ok(!efnd.total, "MS Shell Dlg 2 should not be enumerated\n");
memset(&efnd, 0, sizeof(efnd));
efnd.total = 0;
strcpy(lf.lfFaceName, "MS Shell Dlg 2");
ret = EnumFontFamiliesExA(hdc, &lf, enum_ms_shell_dlg2_proc, (LPARAM)&efnd, 0);
ok(!ret, "MS Shell Dlg 2 should be enumerated\n");
@ -5286,6 +5328,7 @@ static void test_EnumFonts_subst(void)
ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg 2");
ok(ret, "did not expect MS Shell Dlg 2\n");
heap_free(efnd.elf);
DeleteDC(hdc);
}
@ -5396,7 +5439,7 @@ static void test_fullname2_helper(const char *Family)
lf.lfItalic = FALSE;
lf.lfWeight = FW_DONTCARE;
strcpy(lf.lfFaceName, Family);
efnd.total = 0;
memset(&efnd, 0, sizeof(efnd));
EnumFontFamiliesExA(hdc, &lf, enum_fullname_data_proc, (LPARAM)&efnd, 0);
if (efnd.total == 0)
skip("%s is not installed\n", lf.lfFaceName);
@ -5477,6 +5520,7 @@ static void test_fullname2_helper(const char *Family)
HeapFree(GetProcessHeap(), 0, bufW);
HeapFree(GetProcessHeap(), 0, bufA);
}
heap_free(efnd.elf);
DeleteDC(hdc);
}
@ -6225,7 +6269,7 @@ static void test_vertical_order(void)
lf.lfQuality = DEFAULT_QUALITY;
lf.lfItalic = FALSE;
lf.lfWeight = FW_DONTCARE;
efd.total = 0;
memset( &efd, 0, sizeof(efd) );
EnumFontFamiliesExA(hdc, &lf, enum_font_data_proc, (LPARAM)&efd, 0);
for (i = 0; i < efd.total; i++)
{
@ -6239,6 +6283,7 @@ static void test_vertical_order(void)
}
}
}
heap_free( efd.lf );
DeleteDC( hdc );
}

View file

@ -148,6 +148,13 @@ static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
ok(!emr_ExtTextOutW->rclBounds.left, "emr_ExtTextOutW->rclBounds.left = %d\n",
emr_ExtTextOutW->rclBounds.left);
ok(emr_ExtTextOutW->rclBounds.right != -1, "emr_ExtTextOutW->rclBounds.right = %d\n",
emr_ExtTextOutW->rclBounds.right);
ok(emr_ExtTextOutW->rclBounds.bottom != -1, "emr_ExtTextOutW->rclBounds.bottom = %d\n",
emr_ExtTextOutW->rclBounds.bottom);
for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
{
ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
@ -229,6 +236,20 @@ static void test_ExtTextOut(void)
ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
ok( ret, "ExtTextOutA error %d\n", GetLastError());
/* 3. pass NULL lprc */
ret = ExtTextOutA(hdcMetafile, 0, 40, 0, NULL, text, lstrlenA(text), NULL);
ok( ret, "ExtTextOutA error %d\n", GetLastError());
/* 4. test with unmatched BeginPath/EndPath calls */
ret = BeginPath(hdcMetafile);
ok( ret, "BeginPath error %d\n", GetLastError());
ret = BeginPath(hdcMetafile);
ok( ret, "BeginPath error %d\n", GetLastError());
ret = EndPath(hdcMetafile);
ok( ret, "BeginPath error %d\n", GetLastError());
ret = ExtTextOutA(hdcMetafile, 0, 60, 0, NULL, text, lstrlenA(text), NULL);
ok( ret, "ExtTextOutA error %d\n", GetLastError());
hFont = SelectObject(hdcMetafile, hFont);
ret = DeleteObject(hFont);
ok( ret, "DeleteObject error %d\n", GetLastError());
@ -989,7 +1010,7 @@ static void test_mf_SaveDC(void)
/* with the nominal results. */
/* Maximum size of sample metafiles in bytes. */
#define MF_BUFSIZE 512
#define MF_BUFSIZE 1024
/* 8x8 bitmap data for a pattern brush */
static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
@ -1269,16 +1290,16 @@ static const unsigned char EMF_BITBLT[] =
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -1314,9 +1335,34 @@ static const unsigned char EMF_BITBLT[] =
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00
};
static const unsigned char EMF_DCBRUSH_BITS[] =
@ -1409,6 +1455,97 @@ static const unsigned char EMF_BEZIER_BITS[] =
0x14, 0x00, 0x00, 0x00
};
static const unsigned char EMF_POLYPOLYLINE_BITS[] =
{
0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00
};
static const unsigned char EMF_GRADIENTFILL_BITS[] =
{
0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00
};
/* For debugging or dumping the raw metafiles produced by
* new test functions.
*/
@ -1757,6 +1894,14 @@ static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
broken(emh1->nSize - diff_9x == emh2->nSize),
"expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
ok(emh1->rclBounds.left == emh2->rclBounds.left, "%s: expected rclBounds.left = %d, got %d\n",
desc, emh1->rclBounds.left, emh2->rclBounds.left);
ok(emh1->rclBounds.top == emh2->rclBounds.top, "%s: expected rclBounds.top = %d, got %d\n",
desc, emh1->rclBounds.top, emh2->rclBounds.top);
ok(emh1->rclBounds.right == emh2->rclBounds.right, "%s: expected rclBounds.right = %d, got %d\n",
desc, emh1->rclBounds.right, emh2->rclBounds.right);
ok(emh1->rclBounds.bottom == emh2->rclBounds.bottom, "%s: expected rclBounds.bottom = %d, got %d\n",
desc, emh1->rclBounds.bottom, emh2->rclBounds.bottom);
ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
ok(emh1->nBytes == emh2->nBytes ||
broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
@ -1805,6 +1950,7 @@ static void test_emf_BitBlt(void)
0, /* biClrImportant */
};
void *bits;
XFORM xform;
BOOL ret;
hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
@ -1812,6 +1958,7 @@ static void test_emf_BitBlt(void)
hdcBitmap = CreateCompatibleDC(hdcDisplay);
ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n");
bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
@ -1830,6 +1977,19 @@ static void test_emf_BitBlt(void)
ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
ok( ret, "BitBlt(WHITENESS) failed\n" );
ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n");
ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n");
ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n");
ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n");
ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n");
memset(&xform, 0, sizeof(xform));
xform.eM11 = 0.5;
xform.eM22 = 1.0;
ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n");
ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY);
ok( ret, "StretchBlt(SRCCOPY) failed\n" );
hMetafile = CloseEnhMetaFile(hdcMetafile);
ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
@ -2777,6 +2937,63 @@ static void test_mf_clipping(void)
DestroyWindow(hwnd);
}
static const unsigned char MF_PATH_BITS[] =
{
0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
};
static void test_mf_GetPath(void)
{
HDC hdc;
HMETAFILE hmf;
BOOL ret;
int size;
SetLastError(0xdeadbeef);
hdc = CreateMetaFileA(NULL);
ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
ret = BeginPath(hdc);
ok(!ret, "BeginPath on metafile DC should fail\n");
ret = MoveToEx(hdc, 50, 50, NULL);
ok( ret, "MoveToEx error %d.\n", GetLastError());
ret = LineTo(hdc, 50, 150);
ok( ret, "LineTo error %d.\n", GetLastError());
ret = LineTo(hdc, 150, 150);
ok( ret, "LineTo error %d.\n", GetLastError());
ret = LineTo(hdc, 150, 50);
ok( ret, "LineTo error %d.\n", GetLastError());
ret = LineTo(hdc, 50, 50);
ok( ret, "LineTo error %d.\n", GetLastError());
Rectangle(hdc, 10, 10, 20, 20);
EndPath(hdc);
size = GetPath(hdc, NULL, NULL, 0);
ok( size == -1, "GetPath returned %d.\n", size);
hmf = CloseMetaFile(hdc);
ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0)
{
dump_mf_bits(hmf, "mf_GetPath");
EnumMetaFile(0, hmf, mf_enum_proc, 0);
}
ret = DeleteMetaFile(hmf);
ok( ret, "DeleteMetaFile error %d\n", GetLastError());
}
static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
{
LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
@ -3483,16 +3700,16 @@ static const unsigned char EMF_PATH_BITS[] =
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe6, 0xff, 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff,
0xef, 0xff, 0xff, 0xff, 0xea, 0xff, 0xff, 0xff,
0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
0xf8, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x0c, 0x02, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x07, 0x00, 0x00, 0xd3, 0x03, 0x00, 0x00,
0xfc, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00,
0x80, 0x07, 0x00, 0x00, 0x3e, 0x04, 0x00, 0x00,
0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
0xd3, 0xf3, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
@ -3506,14 +3723,51 @@ static const unsigned char EMF_PATH_BITS[] =
0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
0x13, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
0x5a, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00
};
static void test_emf_GetPath(void)
{
POINT pts[4] = {{10, 10}, {20, 10}, {10, 20}, {20, 20}};
DWORD counts[2] = {2, 2};
HDC hdcMetafile;
HENHMETAFILE hemf;
BOOL ret;
@ -3523,7 +3777,8 @@ static void test_emf_GetPath(void)
hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
BeginPath(hdcMetafile);
ret = BeginPath(hdcMetafile);
ok(ret, "BeginPath error %d\n", GetLastError());
ret = MoveToEx(hdcMetafile, 50, 50, NULL);
ok( ret, "MoveToEx error %d.\n", GetLastError());
ret = LineTo(hdcMetafile, 50, 150);
@ -3535,10 +3790,17 @@ static void test_emf_GetPath(void)
ret = LineTo(hdcMetafile, 50, 50);
ok( ret, "LineTo error %d.\n", GetLastError());
Rectangle(hdcMetafile, 10, 10, 20, 20);
Arc(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
Chord(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
Pie(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
Ellipse(hdcMetafile, 10, 10, 20, 20);
RoundRect(hdcMetafile, 10, 10, 20, 20, 3, 5);
Polyline(hdcMetafile, pts, 4);
PolyPolyline(hdcMetafile, pts, counts, 2);
EndPath(hdcMetafile);
size = GetPath(hdcMetafile, NULL, NULL, 0);
ok( size == 9, "GetPath returned %d.\n", size);
todo_wine ok( size == 77, "GetPath returned %d.\n", size);
hemf = CloseEnhMetaFile(hdcMetafile);
ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
@ -3552,6 +3814,104 @@ static void test_emf_GetPath(void)
DeleteEnhMetaFile(hemf);
}
static void test_emf_PolyPolyline(void)
{
HDC hdcMetafile;
HENHMETAFILE hemf;
POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
DWORD counts[2];
BOOL ret;
SetLastError(0xdeadbeef);
hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
ret = PolyPolyline(hdcMetafile, NULL, NULL, 0);
ok( !ret, "PolyPolyline\n" );
SetLastError( 0xdeadbeef );
counts[0] = 0;
counts[1] = 1;
ret = PolyPolyline(hdcMetafile, pts, counts, 2);
ok( !ret, "PolyPolyline\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
SetLastError( 0xdeadbeef );
counts[0] = 1;
counts[1] = 1;
ret = PolyPolyline(hdcMetafile, pts, counts, 2);
ok( !ret, "PolyPolyline\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
SetLastError( 0xdeadbeef );
counts[0] = 2;
counts[1] = 1;
ret = PolyPolyline(hdcMetafile, pts, counts, 2);
ok( !ret, "PolyPolyline\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
counts[0] = 2;
counts[1] = 2;
ret = PolyPolyline(hdcMetafile, pts, counts, 2);
ok( ret, "PolyPolyline\n" );
hemf = CloseEnhMetaFile(hdcMetafile);
ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS),
"emf_PolyPolyline", FALSE) != 0)
{
dump_emf_bits(hemf, "emf_PolyPolyline");
dump_emf_records(hemf, "emf_PolyPolyline");
}
DeleteEnhMetaFile(hemf);
}
static void test_emf_GradientFill(void)
{
HDC mf;
HENHMETAFILE hemf;
TRIVERTEX v[] =
{
{ 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 },
{ 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
{ 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
{ 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
{ 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
};
GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } };
BOOL ret;
mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL );
ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
/* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
* means it allocates three mesh indices rather than two per
* rectangle. This results in uninitialised values being written
* to the EMF which is rather difficult to test against.
*
* Note also that the final vertex here is not required, yet it is
* written to the EMF, but is not considered in the bounds
* calculation.
*/
ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
GRADIENT_FILL_TRIANGLE );
ok( ret, "GradientFill\n" );
hemf = CloseEnhMetaFile( mf );
ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() );
if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS),
"emf_GradientFill", FALSE ) != 0)
{
dump_emf_bits( hemf, "emf_GradientFill" );
dump_emf_records( hemf, "emf_GradientFill" );
}
DeleteEnhMetaFile( hemf );
}
START_TEST(metafile)
{
init_function_pointers();
@ -3566,6 +3926,8 @@ START_TEST(metafile)
test_emf_clipping();
test_emf_polybezier();
test_emf_GetPath();
test_emf_PolyPolyline();
test_emf_GradientFill();
/* For win-format metafiles (mfdrv) */
test_mf_SaveDC();
@ -3577,6 +3939,7 @@ START_TEST(metafile)
test_SetMetaFileBits();
test_mf_ExtTextOut_on_path();
test_mf_clipping();
test_mf_GetPath();
/* For metafile conversions */
test_mf_conversions();