[PATCH 3/6] dwrite: Split initial cluster computation by stage

Nikolay Sivov nsivov at codeweavers.com
Tue Aug 22 04:42:11 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/analyzer.c       |   5 +-
 dlls/dwrite/dwrite_private.h |   2 +-
 dlls/dwrite/layout.c         | 374 ++++++++++++++++++++++++-------------------
 dlls/dwrite/main.c           |   6 +-
 4 files changed, 215 insertions(+), 172 deletions(-)

diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index 3d187d4788..b2d6c7a48e 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -1832,10 +1832,9 @@ static const struct IDWriteTextAnalyzer2Vtbl textanalyzervtbl = {
 
 static IDWriteTextAnalyzer2 textanalyzer = { &textanalyzervtbl };
 
-HRESULT get_textanalyzer(IDWriteTextAnalyzer **ret)
+IDWriteTextAnalyzer *get_text_analyzer(void)
 {
-    *ret = (IDWriteTextAnalyzer*)&textanalyzer;
-    return S_OK;
+    return (IDWriteTextAnalyzer *)&textanalyzer;
 }
 
 static HRESULT WINAPI dwritenumbersubstitution_QueryInterface(IDWriteNumberSubstitution *iface, REFIID riid, void **obj)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index a0632b7771..288da2cb43 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -175,7 +175,7 @@ extern HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLoca
 extern void    set_en_localizedstring(IDWriteLocalizedStrings*,const WCHAR*) DECLSPEC_HIDDEN;
 extern HRESULT get_system_fontcollection(IDWriteFactory5*,IDWriteFontCollection1**) DECLSPEC_HIDDEN;
 extern HRESULT get_eudc_fontcollection(IDWriteFactory5*,IDWriteFontCollection1**) DECLSPEC_HIDDEN;
-extern HRESULT get_textanalyzer(IDWriteTextAnalyzer**) DECLSPEC_HIDDEN;
+extern IDWriteTextAnalyzer *get_text_analyzer(void) DECLSPEC_HIDDEN;
 extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN;
 extern HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) DECLSPEC_HIDDEN;
 extern HRESULT create_fontface(const struct fontface_desc*,struct list*,IDWriteFontFace4**) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 76c3ad918b..1acf134bc1 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -746,40 +746,21 @@ static void layout_get_font_height(FLOAT emsize, DWRITE_FONT_METRICS *fontmetric
     *height = SCALE_FONT_METRIC(fontmetrics->ascent + fontmetrics->descent + fontmetrics->lineGap, emsize, fontmetrics);
 }
 
-static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
+static HRESULT layout_itemize(struct dwrite_textlayout *layout)
 {
-    IDWriteFontFallback *fallback;
     IDWriteTextAnalyzer *analyzer;
     struct layout_range *range;
     struct layout_run *r;
-    UINT32 cluster = 0;
-    HRESULT hr;
-
-    free_layout_eruns(layout);
-    free_layout_runs(layout);
-
-    /* Cluster data arrays are allocated once, assuming one text position per cluster. */
-    if (!layout->clustermetrics && layout->len) {
-        layout->clustermetrics = heap_alloc(layout->len*sizeof(*layout->clustermetrics));
-        layout->clusters = heap_alloc(layout->len*sizeof(*layout->clusters));
-        if (!layout->clustermetrics || !layout->clusters) {
-            heap_free(layout->clustermetrics);
-            heap_free(layout->clusters);
-            return E_OUTOFMEMORY;
-        }
-    }
-    layout->cluster_count = 0;
+    HRESULT hr = S_OK;
 
-    hr = get_textanalyzer(&analyzer);
-    if (FAILED(hr))
-        return hr;
+    analyzer = get_text_analyzer();
 
     LIST_FOR_EACH_ENTRY(range, &layout->ranges, struct layout_range, h.entry) {
-        /* we don't care about ranges that don't contain any text */
+        /* We don't care about ranges that don't contain any text. */
         if (range->h.range.startPosition >= layout->len)
             break;
 
-        /* inline objects override actual text in a range */
+        /* Inline objects override actual text in range. */
         if (range->object) {
             hr = layout_update_breakpoints_range(layout, range);
             if (FAILED(hr))
@@ -795,30 +776,49 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
             continue;
         }
 
-        /* initial splitting by script */
-        hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, (IDWriteTextAnalysisSource*)&layout->IDWriteTextAnalysisSource1_iface,
-            range->h.range.startPosition, get_clipped_range_length(layout, range), (IDWriteTextAnalysisSink*)&layout->IDWriteTextAnalysisSink1_iface);
+        /* Initial splitting by script. */
+        hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
+                range->h.range.startPosition, get_clipped_range_length(layout, range),
+                (IDWriteTextAnalysisSink *)&layout->IDWriteTextAnalysisSink1_iface);
         if (FAILED(hr))
             break;
 
-        /* this splits it further */
-        hr = IDWriteTextAnalyzer_AnalyzeBidi(analyzer, (IDWriteTextAnalysisSource*)&layout->IDWriteTextAnalysisSource1_iface,
-            range->h.range.startPosition, get_clipped_range_length(layout, range), (IDWriteTextAnalysisSink*)&layout->IDWriteTextAnalysisSink1_iface);
+        /* Splitting further by bidi levels. */
+        hr = IDWriteTextAnalyzer_AnalyzeBidi(analyzer, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
+                range->h.range.startPosition, get_clipped_range_length(layout, range),
+                (IDWriteTextAnalysisSink *)&layout->IDWriteTextAnalysisSink1_iface);
         if (FAILED(hr))
             break;
     }
 
+    return hr;
+}
+
+static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
+{
+    IDWriteFontCollection *sys_collection;
+    IDWriteFontFallback *fallback = NULL;
+    struct layout_range *range;
+    struct layout_run *r;
+    HRESULT hr;
+
+    if (FAILED(hr = IDWriteFactory5_GetSystemFontCollection(layout->factory, FALSE,
+            (IDWriteFontCollection1 **)&sys_collection, FALSE))) {
+        WARN("Failed to get system collection, hr %#x.\n", hr);
+        return hr;
+    }
+
     if (layout->format.fallback) {
         fallback = layout->format.fallback;
         IDWriteFontFallback_AddRef(fallback);
     }
     else {
-        hr = IDWriteFactory5_GetSystemFontFallback(layout->factory, &fallback);
-        if (FAILED(hr))
-            return hr;
+        if (FAILED(hr = IDWriteFactory5_GetSystemFontFallback(layout->factory, &fallback))) {
+            WARN("Failed to get system fallback, hr %#x.\n", hr);
+            goto fatal;
+        }
     }
 
-    /* resolve run fonts */
     LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
         struct regular_layout_run *run = &r->u.regular;
         IDWriteFont *font;
@@ -832,28 +832,21 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
         if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL) {
             IDWriteFontCollection *collection;
 
-            if (range->collection) {
-                collection = range->collection;
-                IDWriteFontCollection_AddRef(collection);
-            }
-            else
-                IDWriteFactory5_GetSystemFontCollection(layout->factory, FALSE, (IDWriteFontCollection1 **)&collection, FALSE);
-
-            hr = create_matching_font(collection, range->fontfamily, range->weight,
-                range->style, range->stretch, &font);
+            collection = range->collection ? range->collection : sys_collection;
 
-            IDWriteFontCollection_Release(collection);
-
-            if (FAILED(hr)) {
-                WARN("%s: failed to create a font for non visual run, %s, collection %p\n", debugstr_rundescr(&run->descr),
-                    debugstr_w(range->fontfamily), range->collection);
-                return hr;
+            if (FAILED(hr = create_matching_font(collection, range->fontfamily, range->weight, range->style,
+                    range->stretch, &font))) {
+                WARN("%s: failed to create matching font for non visual run, family %s, collection %p\n",
+                        debugstr_rundescr(&run->descr), debugstr_w(range->fontfamily), range->collection);
+                break;
             }
 
             hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
             IDWriteFont_Release(font);
-            if (FAILED(hr))
-                return hr;
+            if (FAILED(hr)) {
+                WARN("Failed to create font face, hr %#x.\n", hr);
+                break;
+            }
 
             run->run.fontEmSize = range->fontsize;
             continue;
@@ -868,7 +861,7 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
             run = &r->u.regular;
 
             hr = IDWriteFontFallback_MapCharacters(fallback,
-                (IDWriteTextAnalysisSource*)&layout->IDWriteTextAnalysisSource1_iface,
+                (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
                 run->descr.textPosition,
                 run->descr.stringLength,
                 range->collection,
@@ -880,14 +873,18 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
                 &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;
+                WARN("%s: failed to map family %s, collection %p, hr %#x.\n", debugstr_rundescr(&run->descr),
+                        debugstr_w(range->fontfamily), range->collection, hr);
+                goto fatal;
             }
 
             hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
             IDWriteFont_Release(font);
-            if (FAILED(hr))
-                return hr;
+            if (FAILED(hr)) {
+                WARN("Failed to create font face, hr %#x.\n", hr);
+                goto fatal;
+            }
+
             run->run.fontEmSize = range->fontsize * scale;
 
             if (mapped_length < length) {
@@ -896,8 +893,10 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
 
                 /* keep mapped part for current run, add another run for the rest */
                 nextr = alloc_layout_run(LAYOUT_RUN_REGULAR, 0);
-                if (!nextr)
-                    return E_OUTOFMEMORY;
+                if (!nextr) {
+                    hr = E_OUTOFMEMORY;
+                    goto fatal;
+                }
 
                 *nextr = *r;
                 nextr->start_position = run->descr.textPosition + mapped_length;
@@ -914,15 +913,150 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
         }
     }
 
-    IDWriteFontFallback_Release(fallback);
+fatal:
+    IDWriteFontCollection_Release(sys_collection);
+    if (fallback)
+        IDWriteFontFallback_Release(fallback);
+
+    return hr;
+}
+
+static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular_layout_run *run)
+{
+    DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props;
+    DWRITE_SHAPING_TEXT_PROPERTIES *text_props;
+    IDWriteTextAnalyzer *analyzer;
+    struct layout_range *range;
+    UINT32 max_count;
+    HRESULT hr;
+
+    range = get_layout_range_by_pos(layout, run->descr.textPosition);
+    run->descr.localeName = range->locale;
+    run->clustermap = heap_alloc(run->descr.stringLength * sizeof(*run->clustermap));
+
+    max_count = 3 * run->descr.stringLength / 2 + 16;
+    run->glyphs = heap_alloc(max_count * sizeof(*run->glyphs));
+    if (!run->clustermap || !run->glyphs)
+        return E_OUTOFMEMORY;
+
+    text_props = heap_alloc(run->descr.stringLength * sizeof(*text_props));
+    glyph_props = heap_alloc(max_count * sizeof(*glyph_props));
+    if (!text_props || !glyph_props) {
+        heap_free(text_props);
+        heap_free(glyph_props);
+        return E_OUTOFMEMORY;
+    }
+
+    analyzer = get_text_analyzer();
+
+    for (;;) {
+        hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace,
+                run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL /* FIXME */, NULL,
+                NULL, 0, max_count, run->clustermap, text_props, run->glyphs, glyph_props, &run->glyphcount);
+        if (hr == E_NOT_SUFFICIENT_BUFFER) {
+            heap_free(run->glyphs);
+            heap_free(glyph_props);
+
+            max_count = run->glyphcount;
+
+            run->glyphs = heap_alloc(max_count * sizeof(*run->glyphs));
+            glyph_props = heap_alloc(max_count * sizeof(*glyph_props));
+            if (!run->glyphs || !glyph_props) {
+                hr = E_OUTOFMEMORY;
+                break;
+            }
+
+            continue;
+        }
+
+        break;
+    }
+
+    if (FAILED(hr)) {
+        heap_free(text_props);
+        heap_free(glyph_props);
+        WARN("%s: shaping failed, hr %#x.\n", debugstr_rundescr(&run->descr), hr);
+        return hr;
+    }
+
+    run->run.glyphIndices = run->glyphs;
+    run->descr.clusterMap = run->clustermap;
+
+    run->advances = heap_alloc(run->glyphcount * sizeof(*run->advances));
+    run->offsets = heap_alloc(run->glyphcount * sizeof(*run->offsets));
+    if (!run->advances || !run->offsets)
+        return E_OUTOFMEMORY;
+
+    /* Get advances and offsets. */
+    if (is_layout_gdi_compatible(layout))
+        hr = IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap,
+                text_props, run->descr.stringLength, run->run.glyphIndices, glyph_props, run->glyphcount,
+                run->run.fontFace, run->run.fontEmSize, layout->ppdip, &layout->transform,
+                layout->measuringmode == DWRITE_MEASURING_MODE_GDI_NATURAL, run->run.isSideways, run->run.bidiLevel & 1,
+                &run->sa, run->descr.localeName, NULL, NULL, 0, run->advances, run->offsets);
+    else
+        hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap, text_props,
+                run->descr.stringLength, run->run.glyphIndices, glyph_props, run->glyphcount, run->run.fontFace,
+                run->run.fontEmSize, run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
+                NULL, NULL, 0, run->advances, run->offsets);
+
+    heap_free(text_props);
+    heap_free(glyph_props);
+    if (FAILED(hr)) {
+        memset(run->advances, 0, run->glyphcount * sizeof(*run->advances));
+        memset(run->offsets, 0, run->glyphcount * sizeof(*run->offsets));
+        WARN("%s: failed to get glyph placement info, hr %#x.\n", debugstr_rundescr(&run->descr), hr);
+    }
+
+    run->run.glyphAdvances = run->advances;
+    run->run.glyphOffsets = run->offsets;
+
+    /* Special treatment for runs that don't produce visual output, shaping code adds normal glyphs for them,
+       with valid cluster map and potentially with non-zero advances; layout code exposes those as zero
+       width clusters. */
+    if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL)
+        run->run.glyphCount = 0;
+    else
+        run->run.glyphCount = run->glyphcount;
+
+    return S_OK;
+}
+
+static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
+{
+    struct layout_run *r;
+    UINT32 cluster = 0;
+    HRESULT hr;
+
+    free_layout_eruns(layout);
+    free_layout_runs(layout);
+
+    /* Cluster data arrays are allocated once, assuming one text position per cluster. */
+    if (!layout->clustermetrics && layout->len) {
+        layout->clustermetrics = heap_alloc(layout->len*sizeof(*layout->clustermetrics));
+        layout->clusters = heap_alloc(layout->len*sizeof(*layout->clusters));
+        if (!layout->clustermetrics || !layout->clusters) {
+            heap_free(layout->clustermetrics);
+            heap_free(layout->clusters);
+            return E_OUTOFMEMORY;
+        }
+    }
+    layout->cluster_count = 0;
+
+    if (FAILED(hr = layout_itemize(layout))) {
+        WARN("Itemization failed, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (FAILED(hr = layout_resolve_fonts(layout))) {
+        WARN("Failed to resolve layout fonts, hr %#x.\n", hr);
+        return hr;
+    }
 
     /* fill run info */
     LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
-        DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props = NULL;
-        DWRITE_SHAPING_TEXT_PROPERTIES *text_props = NULL;
         struct regular_layout_run *run = &r->u.regular;
         DWRITE_FONT_METRICS fontmetrics = { 0 };
-        UINT32 max_count;
 
         /* we need to do very little in case of inline objects */
         if (r->kind == LAYOUT_RUN_INLINE) {
@@ -957,104 +1091,14 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
             continue;
         }
 
-        range = get_layout_range_by_pos(layout, run->descr.textPosition);
-        run->descr.localeName = range->locale;
-        run->clustermap = heap_alloc(run->descr.stringLength*sizeof(UINT16));
-
-        max_count = 3*run->descr.stringLength/2 + 16;
-        run->glyphs = heap_alloc(max_count*sizeof(UINT16));
-        if (!run->clustermap || !run->glyphs)
-            goto memerr;
-
-        text_props = heap_alloc(run->descr.stringLength*sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
-        glyph_props = heap_alloc(max_count*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
-        if (!text_props || !glyph_props)
-            goto memerr;
-
-        while (1) {
-            hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, run->descr.string, run->descr.stringLength,
-                run->run.fontFace, run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
-                NULL /* FIXME */, NULL, NULL, 0, max_count, run->clustermap, text_props, run->glyphs, glyph_props,
-                &run->glyphcount);
-            if (hr == E_NOT_SUFFICIENT_BUFFER) {
-                heap_free(run->glyphs);
-                heap_free(glyph_props);
-
-                max_count = run->glyphcount;
-
-                run->glyphs = heap_alloc(max_count*sizeof(UINT16));
-                glyph_props = heap_alloc(max_count*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
-                if (!run->glyphs || !glyph_props)
-                    goto memerr;
-
-                continue;
-            }
-
-            break;
-        }
-
-        if (FAILED(hr)) {
-            heap_free(text_props);
-            heap_free(glyph_props);
-            WARN("%s: shaping failed 0x%08x\n", debugstr_rundescr(&run->descr), hr);
-            continue;
-        }
-
-        run->run.glyphIndices = run->glyphs;
-        run->descr.clusterMap = run->clustermap;
-
-        run->advances = heap_alloc(run->glyphcount*sizeof(FLOAT));
-        run->offsets = heap_alloc(run->glyphcount*sizeof(DWRITE_GLYPH_OFFSET));
-        if (!run->advances || !run->offsets)
-            goto memerr;
-
-        /* now set advances and offsets */
-        if (is_layout_gdi_compatible(layout))
-            hr = IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap,
-                text_props, run->descr.stringLength, run->run.glyphIndices, glyph_props, run->glyphcount,
-                run->run.fontFace, run->run.fontEmSize, layout->ppdip, &layout->transform,
-                layout->measuringmode == DWRITE_MEASURING_MODE_GDI_NATURAL, run->run.isSideways,
-                run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL, NULL, 0, run->advances, run->offsets);
-        else
-            hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap, text_props,
-                run->descr.stringLength, run->run.glyphIndices, glyph_props, run->glyphcount, run->run.fontFace,
-                run->run.fontEmSize, run->run.isSideways, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
-                NULL, NULL, 0, run->advances, run->offsets);
-
-        heap_free(text_props);
-        heap_free(glyph_props);
-        if (FAILED(hr))
-            WARN("%s: failed to get glyph placement info, 0x%08x\n", debugstr_rundescr(&run->descr), hr);
-
-        run->run.glyphAdvances = run->advances;
-        run->run.glyphOffsets = run->offsets;
-
-        /* Special treatment for runs that don't produce visual output, shaping code adds normal glyphs for them,
-           with valid cluster map and potentially with non-zero advances; layout code exposes those as zero width clusters. */
-        if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL)
-            run->run.glyphCount = 0;
-        else
-            run->run.glyphCount = run->glyphcount;
+        if (FAILED(hr = layout_shape_run(layout, run)))
+            WARN("%s: shaping failed, hr %#x.\n", debugstr_rundescr(&run->descr), hr);
 
         /* baseline derived from font metrics */
         layout_get_font_metrics(layout, run->run.fontFace, run->run.fontEmSize, &fontmetrics);
         layout_get_font_height(run->run.fontEmSize, &fontmetrics, &r->baseline, &r->height);
 
         layout_set_cluster_metrics(layout, r, &cluster);
-        continue;
-
-    memerr:
-        heap_free(text_props);
-        heap_free(glyph_props);
-        heap_free(run->clustermap);
-        heap_free(run->glyphs);
-        heap_free(run->advances);
-        heap_free(run->offsets);
-        run->advances = NULL;
-        run->offsets = NULL;
-        run->clustermap = run->glyphs = NULL;
-        hr = E_OUTOFMEMORY;
-        break;
     }
 
     if (hr == S_OK) {
@@ -1063,7 +1107,6 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
             layout->clustermetrics[cluster-1].canWrapLineAfter = 1;
     }
 
-    IDWriteTextAnalyzer_Release(analyzer);
     return hr;
 }
 
@@ -1077,25 +1120,22 @@ static HRESULT layout_compute(struct dwrite_textlayout *layout)
     /* nominal breakpoints are evaluated only once, because string never changes */
     if (!layout->nominal_breakpoints) {
         IDWriteTextAnalyzer *analyzer;
-        HRESULT hr;
 
-        layout->nominal_breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
+        layout->nominal_breakpoints = heap_alloc(layout->len * sizeof(*layout->nominal_breakpoints));
         if (!layout->nominal_breakpoints)
             return E_OUTOFMEMORY;
 
-        hr = get_textanalyzer(&analyzer);
-        if (FAILED(hr))
-            return hr;
+        analyzer = get_text_analyzer();
 
-        hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, (IDWriteTextAnalysisSource*)&layout->IDWriteTextAnalysisSource1_iface,
-            0, layout->len, (IDWriteTextAnalysisSink*)&layout->IDWriteTextAnalysisSink1_iface);
-        IDWriteTextAnalyzer_Release(analyzer);
-    }
-    if (layout->actual_breakpoints) {
-        heap_free(layout->actual_breakpoints);
-        layout->actual_breakpoints = NULL;
+        if (FAILED(hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer,
+                (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
+                0, layout->len, (IDWriteTextAnalysisSink *)&layout->IDWriteTextAnalysisSink1_iface)))
+            WARN("Line breakpoints analysis failed, hr %#x.\n", hr);
     }
 
+    heap_free(layout->actual_breakpoints);
+    layout->actual_breakpoints = NULL;
+
     hr = layout_compute_runs(layout);
 
     if (TRACE_ON(dwrite)) {
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index ace14b2904..a13b9fdef6 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1192,8 +1192,12 @@ static HRESULT WINAPI dwritefactory_CreateEllipsisTrimmingSign(IDWriteFactory5 *
 static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory5 *iface, IDWriteTextAnalyzer **analyzer)
 {
     struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
+
     TRACE("(%p)->(%p)\n", This, analyzer);
-    return get_textanalyzer(analyzer);
+
+    *analyzer = get_text_analyzer();
+
+    return S_OK;
 }
 
 static HRESULT WINAPI dwritefactory_CreateNumberSubstitution(IDWriteFactory5 *iface,
-- 
2.14.1




More information about the wine-patches mailing list