[PATCH 7/7] d3dx9: Implement ID3DXFont_DrawText().

Sven Baars sbaars at codeweavers.com
Sat Jan 4 05:59:52 CST 2020


Based on a patch by Tony Wasserka.

Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=24754
Signed-off-by: Sven Baars <sbaars at codeweavers.com>
---
 dlls/d3dx9_24/Makefile.in  |   2 +-
 dlls/d3dx9_25/Makefile.in  |   2 +-
 dlls/d3dx9_26/Makefile.in  |   2 +-
 dlls/d3dx9_27/Makefile.in  |   2 +-
 dlls/d3dx9_28/Makefile.in  |   2 +-
 dlls/d3dx9_29/Makefile.in  |   2 +-
 dlls/d3dx9_30/Makefile.in  |   2 +-
 dlls/d3dx9_31/Makefile.in  |   2 +-
 dlls/d3dx9_32/Makefile.in  |   2 +-
 dlls/d3dx9_33/Makefile.in  |   2 +-
 dlls/d3dx9_34/Makefile.in  |   2 +-
 dlls/d3dx9_35/Makefile.in  |   2 +-
 dlls/d3dx9_36/Makefile.in  |   2 +-
 dlls/d3dx9_36/font.c       | 392 ++++++++++++++++++++++++++++++++++++-
 dlls/d3dx9_36/tests/core.c |  45 ++---
 dlls/d3dx9_37/Makefile.in  |   2 +-
 dlls/d3dx9_38/Makefile.in  |   2 +-
 dlls/d3dx9_39/Makefile.in  |   2 +-
 dlls/d3dx9_40/Makefile.in  |   2 +-
 dlls/d3dx9_41/Makefile.in  |   2 +-
 dlls/d3dx9_42/Makefile.in  |   2 +-
 dlls/d3dx9_43/Makefile.in  |   2 +-
 22 files changed, 427 insertions(+), 50 deletions(-)

diff --git a/dlls/d3dx9_24/Makefile.in b/dlls/d3dx9_24/Makefile.in
index faad4c49ac..f80541a9aa 100644
--- a/dlls/d3dx9_24/Makefile.in
+++ b/dlls/d3dx9_24/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=24
 MODULE    = d3dx9_24.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_25/Makefile.in b/dlls/d3dx9_25/Makefile.in
index 292b33db2b..e3144f0d45 100644
--- a/dlls/d3dx9_25/Makefile.in
+++ b/dlls/d3dx9_25/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=25
 MODULE    = d3dx9_25.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_26/Makefile.in b/dlls/d3dx9_26/Makefile.in
index 22bb54a498..1b432afb21 100644
--- a/dlls/d3dx9_26/Makefile.in
+++ b/dlls/d3dx9_26/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=26
 MODULE    = d3dx9_26.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_27/Makefile.in b/dlls/d3dx9_27/Makefile.in
index 4ed104a170..65d8cad9d6 100644
--- a/dlls/d3dx9_27/Makefile.in
+++ b/dlls/d3dx9_27/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=27
 MODULE    = d3dx9_27.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_28/Makefile.in b/dlls/d3dx9_28/Makefile.in
index 94e059ae9d..ff7ba564c1 100644
--- a/dlls/d3dx9_28/Makefile.in
+++ b/dlls/d3dx9_28/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=28
 MODULE    = d3dx9_28.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_29/Makefile.in b/dlls/d3dx9_29/Makefile.in
index 94b39aee37..7e53415c43 100644
--- a/dlls/d3dx9_29/Makefile.in
+++ b/dlls/d3dx9_29/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=29
 MODULE    = d3dx9_29.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_30/Makefile.in b/dlls/d3dx9_30/Makefile.in
index 6beadbc47e..9bc955753f 100644
--- a/dlls/d3dx9_30/Makefile.in
+++ b/dlls/d3dx9_30/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=30
 MODULE    = d3dx9_30.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_31/Makefile.in b/dlls/d3dx9_31/Makefile.in
index b73f32872c..58b72c527c 100644
--- a/dlls/d3dx9_31/Makefile.in
+++ b/dlls/d3dx9_31/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=31
 MODULE    = d3dx9_31.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_32/Makefile.in b/dlls/d3dx9_32/Makefile.in
index 50bc9d0e26..88cc083bbe 100644
--- a/dlls/d3dx9_32/Makefile.in
+++ b/dlls/d3dx9_32/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=32
 MODULE    = d3dx9_32.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_33/Makefile.in b/dlls/d3dx9_33/Makefile.in
index 7be34e1d4b..f6de942ed8 100644
--- a/dlls/d3dx9_33/Makefile.in
+++ b/dlls/d3dx9_33/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=33
 MODULE    = d3dx9_33.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_34/Makefile.in b/dlls/d3dx9_34/Makefile.in
index 248735a531..5d0bc9b3a4 100644
--- a/dlls/d3dx9_34/Makefile.in
+++ b/dlls/d3dx9_34/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=34
 MODULE    = d3dx9_34.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_35/Makefile.in b/dlls/d3dx9_35/Makefile.in
index 01c809dab2..5eb00327c1 100644
--- a/dlls/d3dx9_35/Makefile.in
+++ b/dlls/d3dx9_35/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=35
 MODULE    = d3dx9_35.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in
index 825e5ddfbc..6a08c41159 100644
--- a/dlls/d3dx9_36/Makefile.in
+++ b/dlls/d3dx9_36/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=36
 MODULE    = d3dx9_36.dll
 IMPORTLIB = d3dx9
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_36/font.c b/dlls/d3dx9_36/font.c
index 1037f49cd5..b91f21b671 100644
--- a/dlls/d3dx9_36/font.c
+++ b/dlls/d3dx9_36/font.c
@@ -20,6 +20,10 @@
 
 #include "d3dx9_private.h"
 
+#include <assert.h>
+
+#include "usp10.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 typedef struct _GLYPH
@@ -513,20 +517,396 @@ static HRESULT WINAPI ID3DXFontImpl_PreloadTextW(ID3DXFont *iface, const WCHAR *
     return D3D_OK;
 }
 
+/************************************************************
+ * ID3DXFont_DrawText
+ *
+ * Renders the specified string to the screen
+ *
+ * PARAMS
+ *   sprite [I]   sprite object used to draw the text
+ *   string [I]   string to be drawn
+ *   count  [I]   length of the string
+ *   rect   [I,O] rect which tells us where to draw the string,
+ *                which can be computed by passing DT_CALCRECT
+ *   format [I]   format of the string
+ *   color  [I]   text color
+ *
+ * RETURNS
+ *   The height of the drawn text
+ *
+ */
 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;
+    WCHAR *wstr;
+    INT ret;
+
+    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)
+        return 0;
+
+    if (count < 0)
+        count = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0) - 1;
+
+    if (count == 0)
+        return 0;
+
+    wstr = heap_alloc_zero(count * sizeof(WCHAR));
+    if (!wstr)
+        return 0;
+
+    MultiByteToWideChar(CP_ACP, 0, string, -1, wstr, count);
+
+    ret = ID3DXFont_DrawTextW(iface, sprite, wstr, count, rect, format, color);
+
+    heap_free(wstr);
+
+    return ret;
+}
+
+/* DrawText helpers copied from user32 */
+#define TAB     9
+#define LF     10
+#define CR     13
+#define SPACE  32
+static void TEXT_WordBreak(HDC hdc, WCHAR *str, unsigned int max_str,
+                           unsigned int *len_str,
+                           int width, int format, unsigned int chars_fit,
+                           unsigned int *chars_used, SIZE *size)
+{
+    WCHAR *p;
+    BOOL word_fits;
+    SCRIPT_LOGATTR *sla;
+    SCRIPT_ANALYSIS sa;
+    int i;
+
+    assert(format & DT_WORDBREAK);
+    assert(chars_fit < *len_str);
+
+    sla = heap_alloc(sizeof(SCRIPT_LOGATTR) * *len_str);
+
+    memset(&sa, 0, sizeof(SCRIPT_ANALYSIS));
+    sa.eScript = SCRIPT_UNDEFINED;
+
+    ScriptBreak(str, *len_str, &sa, sla);
+
+    /* Work back from the last character that did fit to either a space or the
+     * last character of a word, whichever is met first.
+     */
+    p = str + chars_fit; /* The character that doesn't fit */
+    i = chars_fit;
+    word_fits = TRUE;
+    if (!chars_fit)
+        word_fits = FALSE;
+    else if (sla[i].fSoftBreak) /* chars_fit < *len_str so this is valid */
+    {
+        /* the word just fitted */
+        p--;
+    }
+    else
+    {
+        while (i > 0 && !sla[(--i)+1].fSoftBreak) p--;
+        p--;
+        word_fits = (i != 0 || sla[i+1].fSoftBreak);
+    }
+
+    /* If there was one. */
+    if (word_fits)
+    {
+        BOOL next_is_space;
+        /* break the line before/after that character */
+        if (!(format & (DT_RIGHT | DT_CENTER)) || *p != SPACE)
+            p++;
+        next_is_space = (p - str) < *len_str && *p == SPACE;
+        *len_str = p - str;
+        /* and if the next character is a space then discard it. */
+        *chars_used = *len_str;
+        if (next_is_space)
+            (*chars_used)++;
+    }
+    /* Suppose there was none. */
+    else
+    {
+        /* discard any trailing space. */
+        const WCHAR *e = str + *len_str;
+        p = str + chars_fit;
+        while (p < e && *p != SPACE)
+            p++;
+        *chars_used = p - str;
+        if (p < e) /* i.e. loop failed because *p == SPACE */
+            (*chars_used)++;
+        *len_str = p - str;
+    }
+    /* Remeasure the string */
+    GetTextExtentExPointW(hdc, str, *len_str, 0, NULL, NULL, size);
+    heap_free(sla);
+}
+
+static const WCHAR *TEXT_NextLineW(HDC hdc, const WCHAR *str, int *count,
+                                   WCHAR *dest, int *len, int width, DWORD format,
+                                   SIZE *retsize, int last_line, int tabwidth)
+{
+    int i = 0, j = 0;
+    int plen = 0;
+    SIZE size;
+    int maxl = *len;
+    int seg_i, seg_count, seg_j;
+    int max_seg_width;
+    int num_fit;
+    BOOL word_broken, line_fits;
+    unsigned int j_in_seg;
+
+    /* For each text segment in the line */
+
+    retsize->cy = 0;
+    while (*count)
+    {
+
+        /* Skip any leading tabs */
+
+        if (str[i] == TAB && (format & DT_EXPANDTABS))
+        {
+            plen = ((plen/tabwidth)+1)*tabwidth;
+            (*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
+            while (*count && str[i] == TAB)
+            {
+                plen += tabwidth;
+                (*count)--; if (j < maxl) dest[j++] = str[i++]; else i++;
+            }
+        }
+
+
+        /* Now copy as far as the next tab or cr/lf or eos */
+
+        seg_i = i;
+        seg_count = *count;
+        seg_j = j;
+
+        while (*count && (str[i] != TAB || !(format & DT_EXPANDTABS)) && ((str[i] != CR && str[i] != LF) || (format & DT_SINGLELINE)))
+        {
+            (*count)--;
+            if (j < maxl) dest[j++] = str[i];
+            i++;
+        }
+
+        /* Measure the whole text segment and possibly WordBreak */
+
+        j_in_seg = j - seg_j;
+        max_seg_width = width - plen;
+        GetTextExtentExPointW(hdc, dest + seg_j, j_in_seg, max_seg_width, &num_fit, NULL, &size);
+
+        /* The Microsoft handling of various combinations of formats is weird.
+         * The following may very easily be incorrect if several formats are
+         * combined, and may differ between versions (to say nothing of the
+         * several bugs in the Microsoft versions).
+         */
+        word_broken = FALSE;
+        line_fits = (num_fit >= j_in_seg);
+        if (!line_fits && (format & DT_WORDBREAK))
+        {
+            const WCHAR *s;
+            unsigned int chars_used;
+            TEXT_WordBreak(hdc, dest+seg_j, maxl-seg_j, &j_in_seg,
+                           max_seg_width, format, num_fit, &chars_used, &size);
+            line_fits = (size.cx <= max_seg_width);
+            /* and correct the counts */
+            *count = seg_count - chars_used;
+            s = str + seg_i + chars_used;
+            i = s - str;
+            word_broken = TRUE;
+        }
+
+        j = seg_j + j_in_seg;
+
+        plen += size.cx;
+        if (size.cy > retsize->cy)
+            retsize->cy = size.cy;
+
+        if (word_broken)
+            break;
+        else if (!*count)
+            break;
+        else if (str[i] == CR || str[i] == LF)
+        {
+            (*count)--, i++;
+            if (*count && (str[i] == CR || str[i] == LF) && str[i] != str[i-1])
+            {
+                (*count)--, i++;
+            }
+            break;
+        }
+        /* else it was a Tab and we go around again */
+    }
+
+    retsize->cx = plen;
+    *len = j;
+    if (*count)
+        return (&str[i]);
+    else
+        return NULL;
 }
 
+#define MAX_BUFFER 1024
 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 *This = impl_from_ID3DXFont(iface);
+    ID3DXSprite *target = sprite;
+
+    const WCHAR *strPtr;
+    WCHAR line[MAX_BUFFER];
+    int lh;
+    TEXTMETRICW tm;
+    int x, y;
+    int width;
+    int max_width = 0;
+    int last_line;
+    int tabwidth = 0;
+    RECT textrect = {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 (format & DT_SINGLELINE)
+        format &= ~DT_WORDBREAK;
+    if (format & DT_CALCRECT)
+        format |= DT_NOCLIP;
+
+    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;
+    width = textrect.right - textrect.left;
+    strPtr = string;
+
+    ID3DXFont_GetTextMetricsW(iface, &tm);
+    lh = tm.tmHeight;
+
+    if (format & DT_EXPANDTABS)
+        tabwidth = tm.tmAveCharWidth * 8;
+
+    if (!(format & DT_CALCRECT) && !sprite)
+    {
+        D3DXCreateSprite(This->device, &target);
+        ID3DXSprite_Begin(target, 0);
+    }
+
+    do {
+        SIZE size;
+        int len = ARRAY_SIZE(line);
+
+        last_line = !(format & DT_NOCLIP) && (y + lh > textrect.bottom);
+        strPtr = TEXT_NextLineW(This->hdc, strPtr, &count, line, &len, width, format, &size, last_line, tabwidth);
+
+        if (format & DT_CENTER)
+            x = (textrect.left + textrect.right - size.cx) / 2;
+        else if (format & DT_RIGHT)
+            x = textrect.right - size.cx;
+
+        if (format & DT_SINGLELINE)
+        {
+            if (format & DT_VCENTER)
+                y = textrect.top + (textrect.bottom - textrect.top) / 2 - size.cy / 2;
+            else if (format & DT_BOTTOM)
+                y = textrect.bottom - size.cy;
+        }
+
+        if (!(format & DT_CALCRECT))
+        {
+            int xseg = x;
+            const WCHAR *str = line;
+
+            while (len)
+            {
+                int len_seg;
+                GCP_RESULTSW results;
+                D3DXVECTOR3 pos;
+                UINT i;
+
+                if ((format & DT_EXPANDTABS))
+                {
+                    const WCHAR *p;
+                    p = str; while (p < str+len && *p != TAB) p++;
+                    len_seg = p - str;
+                    if (len_seg != len && !GetTextExtentPointW(This->hdc, str, len_seg, &size))
+                        return 0;
+                }
+                else
+                    len_seg = len;
+
+                ZeroMemory(&results, sizeof(GCP_RESULTSW));
+                results.lpCaretPos = heap_alloc(len_seg * sizeof(INT));
+                results.lpGlyphs = heap_alloc(len_seg * sizeof(WORD));
+                results.nGlyphs = len_seg;
+
+                GetCharacterPlacementW(This->hdc, str, len_seg, 0, &results, 0);
+
+                for (i = 0; i < results.nGlyphs; i++)
+                {
+                    LPDIRECT3DTEXTURE9 tex;
+                    RECT bbox;
+                    POINT cinc;
+
+                    ID3DXFont_GetGlyphData(iface, results.lpGlyphs[i], &tex, &bbox, &cinc);
+
+                    if (!tex)
+                        continue;
+
+                    pos.x = results.lpCaretPos[i] + cinc.x + xseg;
+                    pos.y = cinc.y + y;
+
+                    ID3DXSprite_Draw(target, tex, &bbox, NULL, &pos, color);
+                    IDirect3DTexture9_Release(tex);
+                }
+
+                len -= len_seg;
+                str += len_seg;
+                if (len)
+                {
+                    assert((format & DT_EXPANDTABS) && *str == TAB);
+                    len--; str++;
+                    xseg += ((size.cx/tabwidth)+1)*tabwidth;
+                }
+            }
+        }
+        else if (size.cx > max_width)
+            max_width = size.cx;
+
+        y += lh;
+    } while (strPtr && !last_line);
+
+    textrect.right = textrect.left + max_width;
+    textrect.bottom = y;
+
+    if ((format & DT_CALCRECT) && rect)
+        *rect = textrect;
+
+    if (target != sprite)
+    {
+        ID3DXSprite_End(target);
+        ID3DXSprite_Release(target);
+    }
+
+    return y - textrect.top;
 }
 
 static HRESULT WINAPI ID3DXFontImpl_OnLostDevice(ID3DXFont *iface)
diff --git a/dlls/d3dx9_36/tests/core.c b/dlls/d3dx9_36/tests/core.c
index 8a0f164259..c2c83952fb 100644
--- a/dlls/d3dx9_36/tests/core.c
+++ b/dlls/d3dx9_36/tests/core.c
@@ -320,20 +320,21 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
         unsigned int expected_height;
         unsigned int expected_size;
         unsigned int expected_levels;
+        BOOL todo;
     }
     tests[] =
     {
-        {   2,   2,  32,  2 },
-        {   4,   4,  64,  3 },
-        {   6,   6, 128,  4 },
-        {   8,   8, 128,  4 },
-        {  10,  10, 256,  5 },
-        {  12,  12, 256,  5 },
-        {  72,  72, 256,  8 },
-        { 256, 255, 256,  9 },
-        { 257, 255, 256,  9 },
-        { 258, 258, 512, 10 },
-        { 512, 512, 512, 10 },
+        {   2,   2,  32,  2, FALSE},
+        {   4,   4,  64,  3, TRUE},
+        {   6,   6, 128,  4, FALSE},
+        {   8,   8, 128,  4, TRUE},
+        {  10,  10, 256,  5, FALSE},
+        {  12,  12, 256,  5, FALSE},
+        {  72,  72, 256,  8, FALSE},
+        { 256, 255, 256,  9, TRUE},
+        { 257, 255, 256,  9, TRUE},
+        { 258, 258, 512, 10, FALSE},
+        { 512, 512, 512, 10, FALSE},
     };
     const unsigned int size = ARRAY_SIZE(testW);
     D3DXFONT_DESCA desc;
@@ -659,26 +660,24 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
         hr = ID3DXSprite_Begin(sprite, D3DXSPRITE_ALPHABLEND);
         ok (hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
 
-        todo_wine {
         height = ID3DXFont_DrawTextW(font, sprite, testW, -1, &rect, DT_TOP, 0xffffffff);
-        ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
+        todo_wine_if(tests[i].todo) ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
         height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_TOP, 0xffffffff);
-        ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
+        todo_wine_if(tests[i].todo) ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
         height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_RIGHT, 0xffffffff);
-        ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
+        todo_wine_if(tests[i].todo) ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
         height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_LEFT | DT_NOCLIP,
                 0xffffffff);
-        ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
-        }
+        todo_wine_if(tests[i].todo) ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
 
         SetRectEmpty(&rect);
         height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect,
                 DT_LEFT | DT_CALCRECT, 0xffffffff);
-        todo_wine ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
+        todo_wine_if(tests[i].todo) ok(height == tests[i].expected_height, "Got unexpected height %u.\n", height);
         ok(!rect.left, "Got unexpected rect left %d.\n", rect.left);
         ok(!rect.top, "Got unexpected rect top %d.\n", rect.top);
-        todo_wine ok(rect.right, "Got unexpected rect right %d.\n", rect.right);
-        todo_wine ok(rect.bottom == tests[i].expected_height, "Got unexpected rect bottom %d.\n", rect.bottom);
+        ok(rect.right, "Got unexpected rect right %d.\n", rect.right);
+        todo_wine_if(tests[i].todo) ok(rect.bottom == tests[i].expected_height, "Got unexpected rect bottom %d.\n", rect.bottom);
 
         hr = ID3DXSprite_End(sprite);
         ok (hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
@@ -694,7 +693,6 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
         RECT rect;
         int height;
 
-        todo_wine {
         SetRect(&rect, 10, 10, 200, 200);
 
         height = ID3DXFont_DrawTextA(font, NULL, "test", -2, &rect, 0, 0xFF00FF);
@@ -730,7 +728,7 @@ static void test_ID3DXFont(IDirect3DDevice9 *device)
         SetRect(&rect, 10, 10, 50, 50);
 
         height = ID3DXFont_DrawTextA(font, NULL, longText, -1, &rect, DT_WORDBREAK, 0xFF00FF);
-        ok(height == 60, "DrawTextA returned %d, expected 60.\n", height);
+        todo_wine ok(height == 60, "DrawTextA returned %d, expected 60.\n", height);
 
         height = ID3DXFont_DrawTextA(font, NULL, longText, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xFF00FF);
         ok(height == 96, "DrawTextA returned %d, expected 96.\n", height);
@@ -772,11 +770,10 @@ if (0) { /* Causes a lockup on Windows 7+ */
         SetRect(&rect, 10, 10, 50, 50);
 
         height = ID3DXFont_DrawTextW(font, NULL, longTextW, -1, &rect, DT_WORDBREAK, 0xFF00FF);
-        ok(height == 60, "DrawTextW returned %d, expected 60.\n", height);
+        todo_wine ok(height == 60, "DrawTextW returned %d, expected 60.\n", height);
 
         height = ID3DXFont_DrawTextW(font, NULL, longTextW, -1, &rect, DT_WORDBREAK | DT_NOCLIP, 0xFF00FF);
         ok(height == 96, "DrawTextW returned %d, expected 96.\n", height);
-        }
 
         ID3DXFont_Release(font);
     }
diff --git a/dlls/d3dx9_37/Makefile.in b/dlls/d3dx9_37/Makefile.in
index a0896df82e..b9dda315f2 100644
--- a/dlls/d3dx9_37/Makefile.in
+++ b/dlls/d3dx9_37/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=37
 MODULE    = d3dx9_37.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_38/Makefile.in b/dlls/d3dx9_38/Makefile.in
index 24bbc3f0cf..adeb4f245a 100644
--- a/dlls/d3dx9_38/Makefile.in
+++ b/dlls/d3dx9_38/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=38
 MODULE    = d3dx9_38.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_39/Makefile.in b/dlls/d3dx9_39/Makefile.in
index a3f7626f33..0e210488f6 100644
--- a/dlls/d3dx9_39/Makefile.in
+++ b/dlls/d3dx9_39/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=39
 MODULE    = d3dx9_39.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_40/Makefile.in b/dlls/d3dx9_40/Makefile.in
index fbbcb0c04e..05349e4b40 100644
--- a/dlls/d3dx9_40/Makefile.in
+++ b/dlls/d3dx9_40/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=40
 MODULE    = d3dx9_40.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_41/Makefile.in b/dlls/d3dx9_41/Makefile.in
index 9b44213117..587e94b7d1 100644
--- a/dlls/d3dx9_41/Makefile.in
+++ b/dlls/d3dx9_41/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=41
 MODULE    = d3dx9_41.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_42/Makefile.in b/dlls/d3dx9_42/Makefile.in
index f725e87471..bb837c4e39 100644
--- a/dlls/d3dx9_42/Makefile.in
+++ b/dlls/d3dx9_42/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=42
 MODULE    = d3dx9_42.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/d3dx9_43/Makefile.in b/dlls/d3dx9_43/Makefile.in
index dbebc51ad0..0701cde7b7 100644
--- a/dlls/d3dx9_43/Makefile.in
+++ b/dlls/d3dx9_43/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DD3DX_SDK_VERSION=43
 MODULE    = d3dx9_43.dll
 IMPORTS   = d3d9 d3dcompiler dxguid d3dxof ole32 gdi32 user32 ucrtbase
 PARENTSRC = ../d3dx9_36
-DELAYIMPORTS = windowscodecs
+DELAYIMPORTS = windowscodecs usp10
 
 EXTRADLLFLAGS = -mno-cygwin
 
-- 
2.24.0




More information about the wine-devel mailing list