diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index 3d187d4788a..b2d6c7a48eb 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 a0632b7771a..288da2cb43b 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 76c3ad918bb..1acf134bc11 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -746,11 +746,284 @@ 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; + HRESULT hr = S_OK; + + 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. */ + if (range->h.range.startPosition >= layout->len) + break; + + /* Inline objects override actual text in range. */ + if (range->object) { + hr = layout_update_breakpoints_range(layout, range); + if (FAILED(hr)) + return hr; + + r = alloc_layout_run(LAYOUT_RUN_INLINE, range->h.range.startPosition); + if (!r) + return E_OUTOFMEMORY; + + r->u.object.object = range->object; + r->u.object.length = get_clipped_range_length(layout, range); + list_add_tail(&layout->runs, &r->entry); + 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); + if (FAILED(hr)) + break; + + /* 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 { + if (FAILED(hr = IDWriteFactory5_GetSystemFontFallback(layout->factory, &fallback))) { + WARN("Failed to get system fallback, hr %#x.\n", hr); + goto fatal; + } + } + + LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) { + struct regular_layout_run *run = &r->u.regular; + IDWriteFont *font; + UINT32 length; + + if (r->kind == LAYOUT_RUN_INLINE) + continue; + + range = get_layout_range_by_pos(layout, run->descr.textPosition); + + if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL) { + IDWriteFontCollection *collection; + + collection = range->collection ? range->collection : sys_collection; + + 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)) { + WARN("Failed to create font face, hr %#x.\n", hr); + break; + } + + run->run.fontEmSize = range->fontsize; + continue; + } + + length = run->descr.stringLength; + + while (length) { + UINT32 mapped_length; + 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, 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)) { + WARN("Failed to create font face, hr %#x.\n", hr); + goto fatal; + } + + run->run.fontEmSize = range->fontsize * scale; + + if (mapped_length < length) { + struct regular_layout_run *nextrun; + struct layout_run *nextr; + + /* keep mapped part for current run, add another run for the rest */ + nextr = alloc_layout_run(LAYOUT_RUN_REGULAR, 0); + if (!nextr) { + hr = E_OUTOFMEMORY; + goto fatal; + } + + *nextr = *r; + nextr->start_position = run->descr.textPosition + mapped_length; + nextrun = &nextr->u.regular; + nextrun->descr.textPosition = nextr->start_position; + 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; + } + } + +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; @@ -770,159 +1043,20 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout) } layout->cluster_count = 0; - hr = get_textanalyzer(&analyzer); - if (FAILED(hr)) + if (FAILED(hr = layout_itemize(layout))) { + WARN("Itemization failed, hr %#x.\n", hr); return hr; - - LIST_FOR_EACH_ENTRY(range, &layout->ranges, struct layout_range, h.entry) { - /* 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 */ - if (range->object) { - hr = layout_update_breakpoints_range(layout, range); - if (FAILED(hr)) - return hr; - - r = alloc_layout_run(LAYOUT_RUN_INLINE, range->h.range.startPosition); - if (!r) - return E_OUTOFMEMORY; - - r->u.object.object = range->object; - r->u.object.length = get_clipped_range_length(layout, range); - list_add_tail(&layout->runs, &r->entry); - 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); - 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); - if (FAILED(hr)) - break; } - if (layout->format.fallback) { - fallback = layout->format.fallback; - IDWriteFontFallback_AddRef(fallback); + if (FAILED(hr = layout_resolve_fonts(layout))) { + WARN("Failed to resolve layout fonts, hr %#x.\n", hr); + return hr; } - else { - hr = IDWriteFactory5_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; - IDWriteFont *font; - UINT32 length; - - if (r->kind == LAYOUT_RUN_INLINE) - continue; - - range = get_layout_range_by_pos(layout, run->descr.textPosition); - - 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); - - 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; - } - - hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace); - IDWriteFont_Release(font); - if (FAILED(hr)) - return hr; - - run->run.fontEmSize = range->fontsize; - continue; - } - - length = run->descr.stringLength; - - while (length) { - UINT32 mapped_length; - 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; - struct layout_run *nextr; - - /* 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; - - *nextr = *r; - nextr->start_position = run->descr.textPosition + mapped_length; - nextrun = &nextr->u.regular; - nextrun->descr.textPosition = nextr->start_position; - 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; - 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 ace14b29049..a13b9fdef6d 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,