diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index 20a84c34f8e..e2fac55383f 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -846,6 +846,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, DWRITE_SHAPING_GLYPH_PROPERTIES* glyph_props, UINT32* actual_glyph_count) { const struct dwritescript_properties *scriptprops; + struct scriptshaping_cache *cache; WCHAR *string; BOOL update_cluster; UINT32 i, g; @@ -925,9 +926,13 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, } *actual_glyph_count = g; + hr = create_scriptshaping_cache(fontface, &cache); + if (FAILED(hr)) + goto done; + scriptprops = &dwritescripts_properties[script]; if (scriptprops->ops && scriptprops->ops->contextual_shaping) { - hr = scriptprops->ops->contextual_shaping(fontface, is_rtl, string, length, max_glyph_count, clustermap, glyph_indices, actual_glyph_count); + hr = scriptprops->ops->contextual_shaping(cache, is_rtl, string, length, max_glyph_count, clustermap, glyph_indices, actual_glyph_count); if (FAILED(hr)) goto done; } @@ -935,11 +940,12 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, /* FIXME: apply default features */ if (scriptprops->ops && scriptprops->ops->set_text_glyphs_props) - hr = scriptprops->ops->set_text_glyphs_props(fontface, string, length, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props); + hr = scriptprops->ops->set_text_glyphs_props(cache, string, length, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props); else - hr = default_shaping_ops.set_text_glyphs_props(fontface, string, length, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props); + hr = default_shaping_ops.set_text_glyphs_props(cache, string, length, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props); done: + release_scriptshaping_cache(cache); heap_free(string); return hr; diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 1624c6b785a..3eb7957be85 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -135,11 +135,15 @@ enum SCRIPT_JUSTIFY SCRIPT_JUSTIFY_ARABIC_SEEN_M }; +struct scriptshaping_cache; +extern HRESULT create_scriptshaping_cache(IDWriteFontFace*,struct scriptshaping_cache**) DECLSPEC_HIDDEN; +extern void release_scriptshaping_cache(struct scriptshaping_cache*) DECLSPEC_HIDDEN; + struct scriptshaping_ops { - HRESULT (*contextual_shaping)(IDWriteFontFace *fontface, BOOL is_rtl, const WCHAR *text, UINT32 len, UINT32 max_glyph_count, + HRESULT (*contextual_shaping)(struct scriptshaping_cache *cache, BOOL is_rtl, const WCHAR *text, UINT32 len, UINT32 max_glyph_count, UINT16 *clustermap, UINT16 *glyph_indices, UINT32* actual_glyph_count); - HRESULT (*set_text_glyphs_props)(IDWriteFontFace *fontface, const WCHAR *text, UINT32 len, UINT16 *clustermap, UINT16 *glyph_indices, + HRESULT (*set_text_glyphs_props)(struct scriptshaping_cache *cache, const WCHAR *text, UINT32 len, UINT16 *clustermap, UINT16 *glyph_indices, UINT32 glyphcount, DWRITE_SHAPING_TEXT_PROPERTIES *text_props, DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props); }; diff --git a/dlls/dwrite/shape.c b/dlls/dwrite/shape.c index fdedb2b6f05..bf098617d2f 100644 --- a/dlls/dwrite/shape.c +++ b/dlls/dwrite/shape.c @@ -26,6 +26,35 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite); +struct scriptshaping_cache +{ + IDWriteFontFace *fontface; +}; + +HRESULT create_scriptshaping_cache(IDWriteFontFace *fontface, struct scriptshaping_cache **cache) +{ + struct scriptshaping_cache *ret; + + ret = heap_alloc(sizeof(*ret)); + if (!ret) + return E_OUTOFMEMORY; + + ret->fontface = fontface; + IDWriteFontFace_AddRef(fontface); + + *cache = ret; + + return S_OK; +} + +void release_scriptshaping_cache(struct scriptshaping_cache *cache) +{ + if (!cache) + return; + IDWriteFontFace_Release(cache->fontface); + heap_free(cache); +} + static void shape_update_clusters_from_glyphprop(UINT32 glyphcount, UINT32 text_len, UINT16 *clustermap, DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props) { UINT32 i; @@ -86,7 +115,7 @@ static INT32 map_glyph_to_text_pos(const UINT16 *clustermap, UINT32 len, UINT16 return k; } -static HRESULT default_set_text_glyphs_props(IDWriteFontFace *fontface, const WCHAR *text, UINT32 len, UINT16 *clustermap, UINT16 *glyph_indices, +static HRESULT default_set_text_glyphs_props(struct scriptshaping_cache *cache, const WCHAR *text, UINT32 len, UINT16 *clustermap, UINT16 *glyph_indices, UINT32 glyphcount, DWRITE_SHAPING_TEXT_PROPERTIES *text_props, DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props) { UINT32 i; @@ -119,13 +148,13 @@ static HRESULT default_set_text_glyphs_props(IDWriteFontFace *fontface, const WC return S_OK; } -static HRESULT latn_set_text_glyphs_props(IDWriteFontFace *fontface, const WCHAR *text, UINT32 len, UINT16 *clustermap, UINT16 *glyph_indices, +static HRESULT latn_set_text_glyphs_props(struct scriptshaping_cache *cache, const WCHAR *text, UINT32 len, UINT16 *clustermap, UINT16 *glyph_indices, UINT32 glyphcount, DWRITE_SHAPING_TEXT_PROPERTIES *text_props, DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props) { HRESULT hr; UINT32 i; - hr = default_set_text_glyphs_props(fontface, text, len, clustermap, glyph_indices, glyphcount, text_props, glyph_props); + hr = default_set_text_glyphs_props(cache, text, len, clustermap, glyph_indices, glyphcount, text_props, glyph_props); for (i = 0; i < glyphcount; i++) if (glyph_props[i].isZeroWidthSpace) diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c index 15f5ab058a2..1add76143e6 100644 --- a/dlls/dwrite/tests/analyzer.c +++ b/dlls/dwrite/tests/analyzer.c @@ -1123,6 +1123,12 @@ static void test_GetGlyphs(void) NULL, NULL, NULL, 0, maxglyphcount, clustermap, props, glyphs1, shapingprops, &actual_count); ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "got 0x%08x\n", hr); +if (0) { + /* NULL fontface - crashes on Windows */ + hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, test1W, lstrlenW(test1W), NULL, FALSE, FALSE, &sa, NULL, + NULL, NULL, NULL, 0, maxglyphcount, clustermap, props, glyphs1, shapingprops, &actual_count); +} + /* invalid script id */ maxglyphcount = 10; actual_count = 0;