[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