From 316a8d0ae11ae1a9654bc731d2c9dc23febc7a2d Mon Sep 17 00:00:00 2001 From: Sven Baars Date: Tue, 3 Mar 2020 09:38:28 +0100 Subject: [PATCH] d3dx9: Add a very basic ID3DXFont_DrawText implementation. Based on a patch by Tony Wasserka. Signed-off-by: Sven Baars Signed-off-by: Matteo Bruni Signed-off-by: Alexandre Julliard --- dlls/d3dx9_36/font.c | 128 +++++++++++++++++++++++++++++++++++-- dlls/d3dx9_36/tests/core.c | 59 ++++++++--------- 2 files changed, 149 insertions(+), 38 deletions(-) diff --git a/dlls/d3dx9_36/font.c b/dlls/d3dx9_36/font.c index 81ba1e4fa0f..8ca35b8c217 100644 --- a/dlls/d3dx9_36/font.c +++ b/dlls/d3dx9_36/font.c @@ -481,17 +481,133 @@ static HRESULT WINAPI ID3DXFontImpl_PreloadTextW(ID3DXFont *iface, const WCHAR * static INT WINAPI ID3DXFontImpl_DrawTextA(ID3DXFont *iface, ID3DXSprite *sprite, const char *string, INT count, RECT *rect, DWORD format, D3DCOLOR color) { - FIXME("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x stub!\n", - iface, sprite, debugstr_a(string), count, wine_dbgstr_rect(rect), format, color); - return 1; + int ret, countW; + WCHAR *wstr; + + TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x.\n", + iface, sprite, debugstr_an(string, count), count, wine_dbgstr_rect(rect), format, color); + + if (!string || !count) + return 0; + + countW = MultiByteToWideChar(CP_ACP, 0, string, count < 0 ? -1 : count, NULL, 0); + + if (!countW) + return 0; + + wstr = heap_alloc_zero(countW * sizeof(*wstr)); + if (!wstr) + return 0; + + MultiByteToWideChar(CP_ACP, 0, string, count < 0 ? -1 : count, wstr, countW); + + ret = ID3DXFont_DrawTextW(iface, sprite, wstr, count < 0 ? countW - 1 : countW, + rect, format, color); + + heap_free(wstr); + + return ret; } static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite, const WCHAR *string, INT count, RECT *rect, DWORD format, D3DCOLOR color) { - FIXME("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x stub!\n", - iface, sprite, debugstr_w(string), count, wine_dbgstr_rect(rect), format, color); - return 1; + struct d3dx_font *font = impl_from_ID3DXFont(iface); + ID3DXSprite *target = sprite; + RECT textrect = {0}; + int lh, x, y; + int ret = 0; + + TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x.\n", + iface, sprite, debugstr_wn(string, count), count, wine_dbgstr_rect(rect), format, color); + + if (!string) + return 0; + + if (count < 0) + count = lstrlenW(string); + + if (!count) + return 0; + + if (!rect) + { + y = ID3DXFont_DrawTextW(iface, NULL, string, count, &textrect, format | DT_CALCRECT, 0); + + if (format & DT_CALCRECT) + return y; + } + else + { + textrect = *rect; + } + + x = textrect.left; + y = textrect.top; + + lh = font->metrics.tmHeight; + + if (!(format & DT_CALCRECT) && !sprite) + { + D3DXCreateSprite(font->device, &target); + ID3DXSprite_Begin(target, 0); + } + + if (!(format & DT_CALCRECT)) + { + GCP_RESULTSW results; + D3DXVECTOR3 pos; + int i; + + memset(&results, 0, sizeof(results)); + results.nGlyphs = count; + + results.lpCaretPos = heap_alloc(count * sizeof(*results.lpCaretPos)); + if (!results.lpCaretPos) + goto cleanup; + + results.lpGlyphs = heap_alloc(count * sizeof(*results.lpGlyphs)); + if (!results.lpGlyphs) + { + heap_free(results.lpCaretPos); + goto cleanup; + } + + GetCharacterPlacementW(font->hdc, string, count, 0, &results, 0); + + for (i = 0; i < results.nGlyphs; ++i) + { + IDirect3DTexture9 *texture; + POINT cell_inc; + RECT black_box; + + ID3DXFont_GetGlyphData(iface, results.lpGlyphs[i], &texture, &black_box, &cell_inc); + + if (!texture) + continue; + + pos.x = cell_inc.x + x + results.lpCaretPos[i]; + pos.y = cell_inc.y + y; + + ID3DXSprite_Draw(target, texture, &black_box, NULL, &pos, color); + IDirect3DTexture9_Release(texture); + } + + heap_free(results.lpCaretPos); + heap_free(results.lpGlyphs); + } + y += lh; + + ret = y - textrect.top; + +cleanup: + if (target != sprite) + { + ID3DXSprite_End(target); + ID3DXSprite_Release(target); + } + + return ret; } static HRESULT WINAPI ID3DXFontImpl_OnLostDevice(ID3DXFont *iface) diff --git a/dlls/d3dx9_36/tests/core.c b/dlls/d3dx9_36/tests/core.c index 662483b687a..c1e0eac0c8f 100644 --- a/dlls/d3dx9_36/tests/core.c +++ b/dlls/d3dx9_36/tests/core.c @@ -652,8 +652,6 @@ static void test_ID3DXFont(IDirect3DDevice9 *device) hr = ID3DXSprite_Begin(sprite, D3DXSPRITE_ALPHABLEND); ok (hr == D3D_OK, "Test %d: got unexpected hr %#x.\n", i, hr); - todo_wine - { height = ID3DXFont_DrawTextW(font, sprite, testW, -1, &rect, DT_TOP, 0xffffffff); ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_TOP, 0xffffffff); @@ -662,12 +660,11 @@ static void test_ID3DXFont(IDirect3DDevice9 *device) ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_LEFT | DT_NOCLIP, 0xffffffff); ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); - } SetRectEmpty(&rect); height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_LEFT | DT_CALCRECT, 0xffffffff); - todo_wine ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); + ok(height == tests[i].font_height, "Test %d: got unexpected height %u.\n", i, height); ok(!rect.left, "Test %d: got unexpected rect left %d.\n", i, rect.left); ok(!rect.top, "Test %d: got unexpected rect top %d.\n", i, rect.top); todo_wine ok(rect.right, "Test %d: got unexpected rect right %d.\n", i, rect.right); @@ -687,7 +684,6 @@ static void test_ID3DXFont(IDirect3DDevice9 *device) DEFAULT_QUALITY, DEFAULT_PITCH, "Tahoma", &font); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); - todo_wine { SetRect(&rect, 10, 10, 200, 200); height = ID3DXFont_DrawTextA(font, NULL, "test", -2, &rect, 0, 0xFF00FF); @@ -723,10 +719,10 @@ static void test_ID3DXFont(IDirect3DDevice9 *device) SetRect(&rect, 10, 10, 50, 50); height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 60, "Got unexpected height %d.\n", height); + todo_wine ok(height == 60, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextA(font, NULL, long_text, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff); - ok(height == 96, "Got unexpected height %d.\n", height); + todo_wine ok(height == 96, "Got unexpected height %d.\n", height); SetRect(&rect, 10, 10, 200, 200); @@ -760,16 +756,16 @@ static void test_ID3DXFont(IDirect3DDevice9 *device) SetRect(&rect, 10, 10, 50, 50); height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 60, "Got unexpected height %d.\n", height); + todo_wine ok(height == 60, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, long_textW, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xff00ff); - ok(height == 96, "Got unexpected height %d.\n", height); + todo_wine ok(height == 96, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, &rect, 0, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a\r\na", -1, &rect, 0, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a\ra", -1, &rect, 0, 0xff00ff); ok(height == 12, "Got unexpected height %d.\n", height); @@ -778,71 +774,70 @@ static void test_ID3DXFont(IDirect3DDevice9 *device) ok(height == 12, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, 0, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 36, "Got unexpected height %d.\n", height); + todo_wine ok(height == 36, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"1\n2\n3\n4\n5\n6", -1, &rect, 0, 0xff00ff); - ok(height == 48, "Got unexpected height %d.\n", height); + todo_wine ok(height == 48, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"1\n2\n3\n4\n5\n6", -1, &rect, DT_NOCLIP, 0xff00ff); - ok(height == 72, "Got unexpected height %d.\n", height); + todo_wine ok(height == 72, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\t", -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 0, "Got unexpected height %d.\n", height); + todo_wine ok(height == 0, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\ta", -1, &rect, DT_WORDBREAK, 0xff00ff); ok(height == 12, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"\taaaaaaaaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"\taaaaaaaaaa", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); - ok(height == 36, "Got unexpected height %d.\n", height); + todo_wine ok(height == 36, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"\taaa\taaa\taaa", -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"\taaa\taaa\taaa", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); - ok(height == 48, "Got unexpected height %d.\n", height); + todo_wine ok(height == 48, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"\t\t\t\t\t\t\t\t\t\t", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); - ok(height == 60, "Got unexpected height %d.\n", height); + todo_wine ok(height == 60, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a\ta", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); ok(height == 12, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a\ta\ta", -1, &rect, DT_EXPANDTABS | DT_WORDBREAK, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaaaaaaaaaaaaaaaaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 36, "Got unexpected height %d.\n", height); + todo_wine ok(height == 36, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"a a", -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 36, "Got unexpected height %d.\n", height); + todo_wine ok(height == 36, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK, 0xff00ff); - ok(height == 36, "Got unexpected height %d.\n", height); + todo_wine ok(height == 36, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_RIGHT, 0xff00ff); - ok(height == 36, "Got unexpected height %d.\n", height); + todo_wine ok(height == 36, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaa aaaa", -1, &rect, DT_WORDBREAK | DT_RIGHT, 0xff00ff); - ok(height == 36, "Got unexpected height %d.\n", height); + todo_wine ok(height == 36, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_BOTTOM, 0xff00ff); - ok(height == 40, "Got unexpected height %d.\n", height); + todo_wine ok(height == 40, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_VCENTER, 0xff00ff); - ok(height == 32, "Got unexpected height %d.\n", height); + todo_wine ok(height == 32, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER, 0xff00ff); - ok(height == 24, "Got unexpected height %d.\n", height); - } + todo_wine ok(height == 24, "Got unexpected height %d.\n", height); ID3DXFont_Release(font); }