[PATCH 5/5] d3dx9: Add a very basic ID3DXFont_DrawText implementation.

Sven Baars sbaars at codeweavers.com
Wed Feb 26 05:09:01 CST 2020


Based on a patch by Tony Wasserka.

Signed-off-by: Sven Baars <sbaars at codeweavers.com>
---
 dlls/d3dx9_36/font.c       | 125 +++++++++++++++++++++++++++++++++++--
 dlls/d3dx9_36/tests/core.c |  59 ++++++++---------
 2 files changed, 146 insertions(+), 38 deletions(-)

diff --git a/dlls/d3dx9_36/font.c b/dlls/d3dx9_36/font.c
index 44bd08a9fb..861d083cf7 100644
--- a/dlls/d3dx9_36/font.c
+++ b/dlls/d3dx9_36/font.c
@@ -462,17 +462,130 @@ 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_a(string), count, wine_dbgstr_rect(rect), format, color);
+
+    if (!string || count == 0)
+        return 0;
+
+    countW = MultiByteToWideChar(CP_ACP, 0, string, count < 0 ? -1 : count, NULL, 0);
+
+    if (countW == 0)
+        return 0;
+
+    wstr = heap_alloc_zero(countW * sizeof(WCHAR));
+    if (!wstr)
+        return 0;
+
+    MultiByteToWideChar(CP_ACP, 0, string, count < 0 ? -1 : count, wstr, countW);
+
+    ret = ID3DXFont_DrawTextW(iface, sprite, wstr, count, 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_w(string), count, wine_dbgstr_rect(rect), format, color);
+
+    if (!string)
+        return 0;
+
+    if (count < 0)
+        count = lstrlenW(string);
+
+    if (count == 0)
+        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;
+        UINT i;
+
+        ZeroMemory(&results, sizeof(GCP_RESULTSW));
+        results.nGlyphs = count;
+
+        results.lpCaretPos = heap_alloc(count * sizeof(INT));
+        if (!results.lpCaretPos)
+            goto cleanup;
+
+        results.lpGlyphs = heap_alloc(count * sizeof(WCHAR));
+        if (!results.lpGlyphs)
+        {
+            heap_free(results.lpCaretPos);
+            goto cleanup;
+        }
+
+        GetCharacterPlacementW(font->hdc, string, count, 0, &results, 0);
+
+        for (i = 0; i < results.nGlyphs; ++i)
+        {
+            LPDIRECT3DTEXTURE9 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 662483b687..c1e0eac0c8 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);
 }
-- 
2.24.0




More information about the wine-devel mailing list