[PATCH 5/5] dwrite: Use current layout fallback when creating run font faces

Nikolay Sivov nsivov at codeweavers.com
Sun Feb 14 10:05:10 CST 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/analyzer.c       |   2 +-
 dlls/dwrite/dwrite_private.h |   2 +
 dlls/dwrite/layout.c         | 127 ++++++++++++++++++++++++++++++-------------
 3 files changed, 91 insertions(+), 40 deletions(-)

diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index 10ff0a2..66fa29c 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -1745,7 +1745,7 @@ static const struct fallback_mapping *find_fallback_mapping(struct dwrite_fontfa
     return NULL;
 }
 
-static HRESULT create_matching_font(IDWriteFontCollection *collection, const WCHAR *name,
+HRESULT create_matching_font(IDWriteFontCollection *collection, const WCHAR *name,
     DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, IDWriteFont **font)
 {
     IDWriteFontFamily *family;
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 1e4cf59..5a01061 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -145,6 +145,8 @@ extern HRESULT create_colorglyphenum(FLOAT,FLOAT,const DWRITE_GLYPH_RUN*,const D
 extern BOOL lb_is_newline_char(WCHAR) DECLSPEC_HIDDEN;
 extern HRESULT create_system_fontfallback(IDWriteFactory2*,IDWriteFontFallback**) DECLSPEC_HIDDEN;
 extern void    release_system_fontfallback(IDWriteFontFallback*) DECLSPEC_HIDDEN;
+extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
+    IDWriteFont**) DECLSPEC_HIDDEN;
 
 /* Opentype font table functions */
 struct dwrite_font_props {
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index b60f2ce..164ac48 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -696,39 +696,6 @@ static void layout_set_cluster_metrics(struct dwrite_textlayout *layout, const s
 
 #define SCALE_FONT_METRIC(metric, emSize, metrics) ((FLOAT)(metric) * (emSize) / (FLOAT)(metrics)->designUnitsPerEm)
 
-static HRESULT create_fontface_by_pos(struct dwrite_textlayout *layout, struct layout_range *range, IDWriteFontFace **fontface)
-{
-    static DWRITE_GLYPH_RUN_DESCRIPTION descr = { 0 };
-    IDWriteFontFamily *family;
-    BOOL exists = FALSE;
-    IDWriteFont *font;
-    UINT32 index;
-    HRESULT hr;
-
-    *fontface = NULL;
-
-    hr = IDWriteFontCollection_FindFamilyName(range->collection, range->fontfamily, &index, &exists);
-    if (FAILED(hr) || !exists) {
-        WARN("%s: family %s not found in collection %p\n", debugstr_rundescr(&descr), debugstr_w(range->fontfamily), range->collection);
-        return hr;
-    }
-
-    hr = IDWriteFontCollection_GetFontFamily(range->collection, index, &family);
-    if (FAILED(hr))
-        return hr;
-
-    hr = IDWriteFontFamily_GetFirstMatchingFont(family, range->weight, range->stretch, range->style, &font);
-    IDWriteFontFamily_Release(family);
-    if (FAILED(hr)) {
-        WARN("%s: failed to get a matching font\n", debugstr_rundescr(&descr));
-        return hr;
-    }
-
-    hr = IDWriteFont_CreateFontFace(font, fontface);
-    IDWriteFont_Release(font);
-    return hr;
-}
-
 static void layout_get_font_metrics(struct dwrite_textlayout *layout, IDWriteFontFace *fontface, FLOAT emsize,
     DWRITE_FONT_METRICS *fontmetrics)
 {
@@ -749,6 +716,7 @@ static void layout_get_font_height(FLOAT emsize, DWRITE_FONT_METRICS *fontmetric
 
 static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
 {
+    IDWriteFontFallback *fallback;
     IDWriteTextAnalyzer *analyzer;
     struct layout_range *range;
     struct layout_run *r;
@@ -808,6 +776,82 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
             break;
     }
 
+    if (layout->format.fallback) {
+        fallback = layout->format.fallback;
+        IDWriteFontFallback_AddRef(fallback);
+    }
+    else {
+        hr = IDWriteFactory2_GetSystemFontFallback(layout->factory, &fallback);
+        if (FAILED(hr))
+            return hr;
+    }
+
+    /* resolve run fonts */
+    LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
+        struct regular_layout_run *run = &r->u.regular;
+        UINT32 length;
+
+        if (r->kind == LAYOUT_RUN_INLINE)
+            continue;
+
+        range = get_layout_range_by_pos(layout, run->descr.textPosition);
+        length = run->descr.stringLength;
+
+        while (length) {
+            UINT32 mapped_length;
+            IDWriteFont *font;
+            FLOAT scale;
+
+            run = &r->u.regular;
+
+            hr = IDWriteFontFallback_MapCharacters(fallback,
+                (IDWriteTextAnalysisSource*)&layout->IDWriteTextAnalysisSource1_iface,
+                run->descr.textPosition,
+                run->descr.stringLength,
+                range->collection,
+                range->fontfamily,
+                range->weight,
+                range->style,
+                range->stretch,
+                &mapped_length,
+                &font,
+                &scale);
+            if (FAILED(hr)) {
+                WARN("%s: failed to map family %s, collection %p\n", debugstr_rundescr(&run->descr), debugstr_w(range->fontfamily), range->collection);
+                return hr;
+            }
+
+            hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
+            IDWriteFont_Release(font);
+            if (FAILED(hr))
+                return hr;
+            run->run.fontEmSize = range->fontsize * scale;
+
+            if (mapped_length < length) {
+                struct regular_layout_run *nextrun = &r->u.regular;
+                struct layout_run *nextr;
+
+                /* keep mapped part for current run, add another run for the rest */
+                nextr = alloc_layout_run(LAYOUT_RUN_REGULAR);
+                if (!nextr)
+                    return E_OUTOFMEMORY;
+
+                *nextr = *r;
+                nextrun = &nextr->u.regular;
+                nextrun->descr.textPosition = run->descr.textPosition + mapped_length;
+                nextrun->descr.stringLength = run->descr.stringLength - mapped_length;
+                nextrun->descr.string = &layout->str[nextrun->descr.textPosition];
+                run->descr.stringLength = mapped_length;
+                list_add_after(&r->entry, &nextr->entry);
+                r = nextr;
+            }
+
+            length -= mapped_length;
+        }
+    }
+
+    IDWriteFontFallback_Release(fallback);
+
     /* fill run info */
     LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
         DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props = NULL;
@@ -850,11 +894,6 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
         }
 
         range = get_layout_range_by_pos(layout, run->descr.textPosition);
-        hr = create_fontface_by_pos(layout, range, &run->run.fontFace);
-        if (FAILED(hr))
-            continue;
-
-        run->run.fontEmSize = range->fontsize;
         run->descr.localeName = range->locale;
         run->clustermap = heap_alloc(run->descr.stringLength*sizeof(UINT16));
 
@@ -1606,10 +1645,20 @@ static HRESULT layout_set_dummy_line_metrics(struct dwrite_textlayout *layout, U
     DWRITE_LINE_METRICS metrics;
     struct layout_range *range;
     IDWriteFontFace *fontface;
+    IDWriteFont *font;
     HRESULT hr;
 
     range = get_layout_range_by_pos(layout, pos);
-    hr = create_fontface_by_pos(layout, range, &fontface);
+    hr = create_matching_font(range->collection,
+        range->fontfamily,
+        range->weight,
+        range->style,
+        range->stretch,
+        &font);
+    if (FAILED(hr))
+        return hr;
+    hr = IDWriteFont_CreateFontFace(font, &fontface);
+    IDWriteFont_Release(font);
     if (FAILED(hr))
         return hr;
 
-- 
2.7.0




More information about the wine-patches mailing list