Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 5 ++++- dlls/dwrite/opentype.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index fa82a8d4376..830c71f0abf 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -564,7 +564,10 @@ struct shaping_feature
#define MAX_SHAPING_STAGE 16
-typedef void (*stage_func)(struct scriptshaping_context *context); +struct shaping_features; + +typedef void (*stage_func)(struct scriptshaping_context *context, + const struct shaping_features *features);
struct shaping_stage { diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index afae1b69d07..125b7353031 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -6070,7 +6070,7 @@ void opentype_layout_apply_gsub_features(struct scriptshaping_context *context, }
if (features->stages[j].func) - features->stages[j].func(context); + features->stages[j].func(context, features); }
/* For every glyph range of [<last>.isClusterStart, <next>.isClusterStart) set corresponding
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/layout.c | 105 +++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 38 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index a24752c9bff..73fe28e222a 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -934,47 +934,57 @@ fatal: return hr; }
-static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular_layout_run *run) +struct shaping_context { + IDWriteTextAnalyzer *analyzer; + 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; +}; + +static void layout_shape_clear_context(struct shaping_context *context) +{ + heap_free(context->glyph_props); + heap_free(context->text_props); +} + +static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct shaping_context *context) +{ + struct regular_layout_run *run = context->run; + unsigned int max_count; HRESULT hr;
- range = get_layout_range_by_pos(layout, run->descr.textPosition); - run->descr.localeName = range->locale; + run->descr.localeName = get_layout_range_by_pos(layout, run->descr.textPosition)->locale; run->clustermap = heap_calloc(run->descr.stringLength, sizeof(*run->clustermap)); + if (!run->clustermap) + return E_OUTOFMEMORY;
max_count = 3 * run->descr.stringLength / 2 + 16; run->glyphs = heap_calloc(max_count, sizeof(*run->glyphs)); - if (!run->clustermap || !run->glyphs) + if (!run->glyphs) return E_OUTOFMEMORY;
- text_props = heap_calloc(run->descr.stringLength, sizeof(*text_props)); - glyph_props = heap_calloc(max_count, sizeof(*glyph_props)); - if (!text_props || !glyph_props) { - heap_free(text_props); - heap_free(glyph_props); + context->text_props = heap_calloc(run->descr.stringLength, sizeof(*context->text_props)); + context->glyph_props = heap_calloc(max_count, sizeof(*context->glyph_props)); + if (!context->text_props || !context->glyph_props) return E_OUTOFMEMORY; - } - - analyzer = get_text_analyzer();
- for (;;) { - hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, run->descr.string, run->descr.stringLength, run->run.fontFace, + for (;;) + { + hr = IDWriteTextAnalyzer_GetGlyphs(context->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) { + NULL, 0, max_count, run->clustermap, context->text_props, run->glyphs, context->glyph_props, &run->glyphcount); + if (hr == E_NOT_SUFFICIENT_BUFFER) + { heap_free(run->glyphs); - heap_free(glyph_props); + heap_free(context->glyph_props);
max_count = run->glyphcount;
run->glyphs = heap_calloc(max_count, sizeof(*run->glyphs)); - glyph_props = heap_calloc(max_count, sizeof(*glyph_props)); - if (!run->glyphs || !glyph_props) { + context->glyph_props = heap_calloc(max_count, sizeof(*context->glyph_props)); + if (!run->glyphs || !context->glyph_props) + { hr = E_OUTOFMEMORY; break; } @@ -985,16 +995,20 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular break; }
- if (FAILED(hr)) { - heap_free(text_props); - heap_free(glyph_props); + if (FAILED(hr)) WARN("%s: shaping failed, hr %#x.\n", debugstr_rundescr(&run->descr), hr); - return hr; - }
run->run.glyphIndices = run->glyphs; run->descr.clusterMap = run->clustermap;
+ return hr; +} + +static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, struct shaping_context *context) +{ + struct regular_layout_run *run = context->run; + HRESULT hr; + run->advances = heap_calloc(run->glyphcount, sizeof(*run->advances)); run->offsets = heap_calloc(run->glyphcount, sizeof(*run->offsets)); if (!run->advances || !run->offsets) @@ -1002,20 +1016,19 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular
/* 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, + hr = IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap, + context->text_props, run->descr.stringLength, run->run.glyphIndices, context->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)) { + hr = IDWriteTextAnalyzer_GetGlyphPlacements(context->analyzer, run->descr.string, run->descr.clusterMap, + context->text_props, run->descr.stringLength, run->run.glyphIndices, context->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); + + 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); @@ -1024,6 +1037,22 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular run->run.glyphAdvances = run->advances; run->run.glyphOffsets = run->offsets;
+ return hr; +} + +static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular_layout_run *run) +{ + struct shaping_context context = { 0 }; + HRESULT hr; + + context.analyzer = get_text_analyzer(); + context.run = run; + + if (SUCCEEDED(hr = layout_shape_get_glyphs(layout, &context))) + hr = layout_shape_get_positions(layout, &context); + + layout_shape_clear_context(&context); + /* 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. */ @@ -1032,7 +1061,7 @@ static HRESULT layout_shape_run(struct dwrite_textlayout *layout, struct regular else run->run.glyphCount = run->glyphcount;
- return S_OK; + return hr; }
static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/layout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c index 73fe28e222a..12a2ce1726c 100644 --- a/dlls/dwrite/layout.c +++ b/dlls/dwrite/layout.c @@ -979,7 +979,7 @@ static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct heap_free(run->glyphs); heap_free(context->glyph_props);
- max_count = run->glyphcount; + max_count *= 2;
run->glyphs = heap_calloc(max_count, sizeof(*run->glyphs)); context->glyph_props = heap_calloc(max_count, sizeof(*context->glyph_props));
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/analyzer.c | 2 ++ dlls/dwrite/tests/analyzer.c | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index 53fb18df4c9..d0d769cb346 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -1188,6 +1188,8 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, context.glyph_infos = heap_calloc(glyph_count, sizeof(*context.glyph_infos)); context.table = &context.cache->gsub;
+ *actual_glyph_count = 0; + scriptprops = &dwritescripts_properties[context.script]; hr = shape_get_glyphs(&context, scriptprops->scripttags); if (SUCCEEDED(hr)) diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c index 6dd251270c7..d4889e5aa63 100644 --- a/dlls/dwrite/tests/analyzer.c +++ b/dlls/dwrite/tests/analyzer.c @@ -1628,11 +1628,13 @@ static void test_GetGlyphs(void) fontface = create_fontface();
maxglyphcount = 1; + actual_count = 1; sa.script = 0; sa.shapes = DWRITE_SCRIPT_SHAPES_DEFAULT; hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, test1W, lstrlenW(test1W), fontface, FALSE, FALSE, &sa, NULL, NULL, NULL, NULL, 0, maxglyphcount, clustermap, props, glyphs1, shapingprops, &actual_count); ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr); + ok(actual_count == 0, "Unexpected count value %u.\n", actual_count);
if (0) { /* NULL fontface - crashes on Windows */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=85661
Your paranoid android.
=== wvistau64 (64 bit report) ===
dwrite: analyzer.c:1637: Test failed: Unexpected count value 2290008.
=== w2008s64 (64 bit report) ===
dwrite: analyzer.c:1637: Test failed: Unexpected count value 2289872.