[PATCH 6/6] dwrite: Search more generously for font fallbacks.

Giovanni Mascellani gmascellani at codeweavers.com
Mon Mar 8 03:31:19 CST 2021


Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>
---
 dlls/dwrite/analyzer.c     | 51 ++++++++++++++++++++------------------
 dlls/dwrite/tests/layout.c | 10 --------
 2 files changed, 27 insertions(+), 34 deletions(-)

diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index daa553adbaf..c811caf0a66 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -2066,7 +2066,7 @@ static HRESULT fallback_map_characters(IDWriteFont *font, const WCHAR *text, UIN
         /* stop on first unsupported character */
         exists = FALSE;
         hr = IDWriteFont_HasCharacter(font, text[i], &exists);
-        if (hr == S_OK && exists)
+        if (SUCCEEDED(hr) && exists)
             ++*mapped_length;
         else
             break;
@@ -2084,11 +2084,12 @@ static HRESULT fallback_get_fallback_font(struct dwrite_fontfallback *fallback,
     UINT32 i;
 
     *mapped_font = NULL;
+    *mapped_length = 0;
 
     mapping = find_fallback_mapping(fallback, text[0]);
     if (!mapping) {
         WARN("No mapping range for %#x.\n", text[0]);
-        return E_FAIL;
+        return S_OK;
     }
 
     /* Now let's see what fallback can handle. Pick first font that could be created. */
@@ -2103,19 +2104,18 @@ static HRESULT fallback_get_fallback_font(struct dwrite_fontfallback *fallback,
 
     if (!*mapped_font) {
         WARN("Failed to create fallback font.\n");
-        return E_FAIL;
+        return S_OK;
     }
 
     hr = fallback_map_characters(*mapped_font, text, length, mapped_length);
-    if (FAILED(hr))
-        WARN("Mapping with fallback family %s failed, hr %#x.\n", debugstr_w(mapping->families[i]), hr);
 
     if (!*mapped_length) {
+        WARN("Mapping with fallback family %s failed.\n", debugstr_w(mapping->families[i]));
         IDWriteFont_Release(*mapped_font);
         *mapped_font = NULL;
     }
 
-    return *mapped_length ? S_OK : E_FAIL;
+    return hr;
 }
 
 static HRESULT WINAPI fontfallback_MapCharacters(IDWriteFontFallback1 *iface, IDWriteTextAnalysisSource *source,
@@ -2150,30 +2150,33 @@ static HRESULT WINAPI fontfallback_MapCharacters(IDWriteFontFallback1 *iface, ID
 
     if (basefamily && *basefamily) {
         hr = create_matching_font(basecollection, basefamily, weight, style, stretch, ret_font);
-        if (FAILED(hr))
-            goto done;
 
-        hr = fallback_map_characters(*ret_font, text, length, mapped_length);
+        /* It is not a fatal error for create_matching_font to
+           fail. We still have other fallbacks to try. */
+
+        if (SUCCEEDED(hr)) {
+            hr = fallback_map_characters(*ret_font, text, length, mapped_length);
+            if (FAILED(hr))
+                goto done;
+        }
+    }
+
+    if (!*mapped_length) {
+        if (*ret_font) {
+            IDWriteFont_Release(*ret_font);
+            *ret_font = NULL;
+        }
+
+        hr = fallback_get_fallback_font(fallback, text, length, weight, style, stretch, mapped_length, ret_font);
         if (FAILED(hr))
             goto done;
     }
 
     if (!*mapped_length) {
-        IDWriteFont *mapped_font;
-
-        hr = fallback_get_fallback_font(fallback, text, length, weight, style, stretch, mapped_length, &mapped_font);
-        if (FAILED(hr)) {
-            /* fallback wasn't found, keep base font if any, so we can get at least some visual output */
-            if (*ret_font) {
-                *mapped_length = length;
-                hr = S_OK;
-            }
-        }
-        else {
-            if (*ret_font)
-                IDWriteFont_Release(*ret_font);
-            *ret_font = mapped_font;
-        }
+        /* fallback wasn't found, ask the caller to skip one character
+           and try again; FIXME: skip the appropriate number of
+           characters instead of just one */
+        *mapped_length = 1;
     }
 
 done:
diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c
index 8574af5465f..5a04b19b77c 100644
--- a/dlls/dwrite/tests/layout.c
+++ b/dlls/dwrite/tests/layout.c
@@ -4771,12 +4771,9 @@ if (font) {
     font = NULL;
     hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 0, 4, &fallbackcollection, g_fontNotInCollectionW, DWRITE_FONT_WEIGHT_NORMAL,
         DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale);
-todo_wine {
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(mappedlength == 1, "got %u\n", mappedlength);
-}
     ok(scale == 1.0f, "got %f\n", scale);
-todo_wine
     ok(font != NULL, "got %p\n", font);
 if (font) {
     IDWriteFont_Release(font);
@@ -4789,12 +4786,9 @@ if (font) {
     font = NULL;
     hr = IDWriteFontFallback_MapCharacters(fallback, &analysissource, 1, 1, &fallbackcollection, g_fontNotInCollectionW, DWRITE_FONT_WEIGHT_NORMAL,
         DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, &mappedlength, &font, &scale);
-todo_wine {
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(mappedlength == 1, "got %u\n", mappedlength);
-}
     ok(scale == 1.0f, "got %f\n", scale);
-todo_wine
     ok(font != NULL, "got %p\n", font);
 if (font) {
     IDWriteFont_Release(font);
@@ -5053,21 +5047,17 @@ static void test_fallback(void)
 
     count = 0;
     hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, 4, &count);
-todo_wine {
     ok(hr == S_OK, "Failed to get cluster metrics, hr %#x.\n", hr);
     ok(count == 4, "Unexpected count %u.\n", count);
-}
     for (i = 0, width = 0.0; i < count; i++)
         width += clusters[i].width;
 
     memset(&metrics, 0xcc, sizeof(metrics));
     hr = IDWriteTextLayout_GetMetrics(layout, &metrics);
     ok(hr == S_OK, "Failed to get layout metrics, hr %#x.\n", hr);
-todo_wine {
     ok(metrics.width > 0.0 && metrics.width == width, "Unexpected width %.2f, expected %.2f.\n", metrics.width, width);
     ok(metrics.height > 0.0, "Unexpected height %.2f.\n", metrics.height);
     ok(metrics.lineCount == 1, "Unexpected line count %u.\n", metrics.lineCount);
-}
     IDWriteTextLayout_Release(layout);
     IDWriteTextFormat_Release(format);
 
-- 
2.30.1




More information about the wine-devel mailing list