Sven Baars : d3dx9: Handle newlines in ID3DXFont_DrawText.

Alexandre Julliard julliard at winehq.org
Fri Mar 6 16:38:40 CST 2020


Module: wine
Branch: master
Commit: 330c3f9108191feb6eb888384befb5cb54645233
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=330c3f9108191feb6eb888384befb5cb54645233

Author: Sven Baars <sbaars at codeweavers.com>
Date:   Thu Mar  5 22:39:57 2020 +0100

d3dx9: Handle newlines in ID3DXFont_DrawText.

Signed-off-by: Sven Baars <sbaars at codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3dx9_36/font.c       | 109 +++++++++++++++++++++++++++++++--------------
 dlls/d3dx9_36/tests/core.c |  14 +++---
 2 files changed, 83 insertions(+), 40 deletions(-)

diff --git a/dlls/d3dx9_36/font.c b/dlls/d3dx9_36/font.c
index 8ca35b8c21..71cfddb0d4 100644
--- a/dlls/d3dx9_36/font.c
+++ b/dlls/d3dx9_36/font.c
@@ -509,13 +509,42 @@ static INT WINAPI ID3DXFontImpl_DrawTextA(ID3DXFont *iface, ID3DXSprite *sprite,
     return ret;
 }
 
+static const WCHAR *read_line(HDC hdc, const WCHAR *str, int *count,
+        WCHAR *dest, unsigned int *dest_len, int width)
+{
+    unsigned int i = 0;
+    SIZE size;
+
+    *dest_len = 0;
+    while (*count && str[i] != '\n')
+    {
+        --(*count);
+        if (str[i] != '\r')
+            dest[(*dest_len)++] = str[i];
+        ++i;
+    }
+
+    GetTextExtentExPointW(hdc, dest, *dest_len, width, NULL, NULL, &size);
+
+    if (*count && str[i] == '\n')
+    {
+        --(*count);
+        ++i;
+    }
+
+    if (*count)
+        return str + i;
+    return NULL;
+}
+
 static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite,
         const WCHAR *string, INT count, RECT *rect, DWORD format, D3DCOLOR color)
 {
     struct d3dx_font *font = impl_from_ID3DXFont(iface);
     ID3DXSprite *target = sprite;
+    WCHAR *line;
     RECT textrect = {0};
-    int lh, x, y;
+    int lh, x, y, width;
     int ret = 0;
 
     TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x.\n",
@@ -544,59 +573,71 @@ static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite,
 
     x = textrect.left;
     y = textrect.top;
+    width = textrect.right - textrect.left;
 
     lh = font->metrics.tmHeight;
 
+    line = heap_alloc(count * sizeof(*line));
+    if (!line)
+        return 0;
+
     if (!(format & DT_CALCRECT) && !sprite)
     {
         D3DXCreateSprite(font->device, &target);
         ID3DXSprite_Begin(target, 0);
     }
 
-    if (!(format & DT_CALCRECT))
+    while (string)
     {
-        GCP_RESULTSW results;
-        D3DXVECTOR3 pos;
-        int i;
-
-        memset(&results, 0, sizeof(results));
-        results.nGlyphs = count;
+        unsigned int line_len;
 
-        results.lpCaretPos = heap_alloc(count * sizeof(*results.lpCaretPos));
-        if (!results.lpCaretPos)
-            goto cleanup;
+        string = read_line(font->hdc, string, &count, line, &line_len, width);
 
-        results.lpGlyphs = heap_alloc(count * sizeof(*results.lpGlyphs));
-        if (!results.lpGlyphs)
+        if (!(format & DT_CALCRECT))
         {
-            heap_free(results.lpCaretPos);
-            goto cleanup;
-        }
+            GCP_RESULTSW results;
+            D3DXVECTOR3 pos;
+            unsigned int i;
 
-        GetCharacterPlacementW(font->hdc, string, count, 0, &results, 0);
+            memset(&results, 0, sizeof(results));
+            results.nGlyphs = line_len;
 
-        for (i = 0; i < results.nGlyphs; ++i)
-        {
-            IDirect3DTexture9 *texture;
-            POINT cell_inc;
-            RECT black_box;
+            results.lpCaretPos = heap_alloc(line_len * sizeof(*results.lpCaretPos));
+            if (!results.lpCaretPos)
+                goto cleanup;
 
-            ID3DXFont_GetGlyphData(iface, results.lpGlyphs[i], &texture, &black_box, &cell_inc);
+            results.lpGlyphs = heap_alloc(line_len * sizeof(*results.lpGlyphs));
+            if (!results.lpGlyphs)
+            {
+                heap_free(results.lpCaretPos);
+                goto cleanup;
+            }
 
-            if (!texture)
-                continue;
+            GetCharacterPlacementW(font->hdc, line, line_len, 0, &results, 0);
 
-            pos.x = cell_inc.x + x + results.lpCaretPos[i];
-            pos.y = cell_inc.y + y;
+            for (i = 0; i < results.nGlyphs; ++i)
+            {
+                IDirect3DTexture9 *texture;
+                POINT cell_inc;
+                RECT black_box;
 
-            ID3DXSprite_Draw(target, texture, &black_box, NULL, &pos, color);
-            IDirect3DTexture9_Release(texture);
-        }
+                ID3DXFont_GetGlyphData(iface, results.lpGlyphs[i], &texture, &black_box, &cell_inc);
 
-        heap_free(results.lpCaretPos);
-        heap_free(results.lpGlyphs);
+                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;
     }
-    y += lh;
 
     ret = y - textrect.top;
 
@@ -607,6 +648,8 @@ cleanup:
         ID3DXSprite_Release(target);
     }
 
+    heap_free(line);
+
     return ret;
 }
 
diff --git a/dlls/d3dx9_36/tests/core.c b/dlls/d3dx9_36/tests/core.c
index c1e0eac0c8..c6f5beff43 100644
--- a/dlls/d3dx9_36/tests/core.c
+++ b/dlls/d3dx9_36/tests/core.c
@@ -762,19 +762,19 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
     todo_wine ok(height == 96, "Got unexpected height %d.\n", height);
 
     height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, &rect, 0, 0xff00ff);
-    todo_wine ok(height == 24, "Got unexpected height %d.\n", height);
+    ok(height == 24, "Got unexpected height %d.\n", height);
 
     height = ID3DXFont_DrawTextW(font, NULL, L"a\r\na", -1, &rect, 0, 0xff00ff);
-    todo_wine ok(height == 24, "Got unexpected height %d.\n", height);
+    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);
 
     height = ID3DXFont_DrawTextW(font, NULL, L"a\na", -1, &rect, DT_SINGLELINE, 0xff00ff);
-    ok(height == 12, "Got unexpected height %d.\n", height);
+    todo_wine ok(height == 12, "Got unexpected height %d.\n", height);
 
     height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, 0, 0xff00ff);
-    todo_wine ok(height == 24, "Got unexpected height %d.\n", height);
+    ok(height == 24, "Got unexpected height %d.\n", height);
 
     height = ID3DXFont_DrawTextW(font, NULL, L"a\naaaaa aaaa", -1, &rect, DT_WORDBREAK, 0xff00ff);
     todo_wine ok(height == 36, "Got unexpected height %d.\n", height);
@@ -783,7 +783,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
     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);
-    todo_wine ok(height == 72, "Got unexpected height %d.\n", height);
+    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);
     todo_wine ok(height == 0, "Got unexpected height %d.\n", height);
@@ -834,10 +834,10 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
     todo_wine ok(height == 32, "Got unexpected height %d.\n", height);
 
     height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_RIGHT, 0xff00ff);
-    todo_wine ok(height == 24, "Got unexpected height %d.\n", height);
+    ok(height == 24, "Got unexpected height %d.\n", height);
 
     height = ID3DXFont_DrawTextW(font, NULL, L"aaaa\naaaa", -1, &rect, DT_CENTER, 0xff00ff);
-    todo_wine ok(height == 24, "Got unexpected height %d.\n", height);
+    ok(height == 24, "Got unexpected height %d.\n", height);
 
     ID3DXFont_Release(font);
 }




More information about the wine-cvs mailing list