From bd6a500ab095944a234cc93398d005569c5035a3 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Mon, 4 May 2020 11:29:32 +0300 Subject: [PATCH] dwrite: Add helper functions to collect default GSUB features. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/analyzer.c | 19 +++++---- dlls/dwrite/dwrite_private.h | 17 +++++++- dlls/dwrite/opentype.c | 10 +++-- dlls/dwrite/shape.c | 80 +++++++++++++++++++++++++++++++++--- 4 files changed, 108 insertions(+), 18 deletions(-) diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index de8ac2ea3c8..bc5c54f21e7 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -1149,21 +1149,22 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, BOOL is_rtl, DWRITE_SCRIPT_ANALYSIS const* analysis, WCHAR const* locale, IDWriteNumberSubstitution* substitution, DWRITE_TYPOGRAPHIC_FEATURES const** features, UINT32 const* feature_range_lengths, UINT32 feature_ranges, UINT32 max_glyph_count, - UINT16* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* text_props, UINT16* glyph_indices, + UINT16* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* text_props, UINT16 *glyphs, DWRITE_SHAPING_GLYPH_PROPERTIES* glyph_props, UINT32* actual_glyph_count) { + const struct dwritescript_properties *scriptprops; DWRITE_NUMBER_SUBSTITUTION_METHOD method; struct scriptshaping_context context; struct dwrite_fontface *font_obj; WCHAR digits[NATIVE_DIGITS_LEN]; + unsigned int i, g, script; BOOL update_cluster; WCHAR *string; - UINT32 i, g; HRESULT hr = S_OK; TRACE("(%s:%u %p %d %d %s %s %p %p %p %u %u %p %p %p %p %p)\n", debugstr_wn(text, length), length, fontface, is_sideways, is_rtl, debugstr_sa_script(analysis->script), debugstr_w(locale), substitution, - features, feature_range_lengths, feature_ranges, max_glyph_count, clustermap, text_props, glyph_indices, + features, feature_range_lengths, feature_ranges, max_glyph_count, clustermap, text_props, glyphs, glyph_props, actual_glyph_count); analyzer_dump_user_features(features, feature_range_lengths, feature_ranges); @@ -1225,7 +1226,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, else update_cluster = TRUE; - hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyph_indices[g]); + hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyphs[g]); if (FAILED(hr)) goto done; @@ -1250,11 +1251,15 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, context.text = text; context.length = length; context.is_rtl = is_rtl; + context.is_sideways = is_sideways; context.language_tag = get_opentype_language(locale); - /* FIXME: apply default features */ - - hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyph_indices, *actual_glyph_count, text_props, glyph_props); + script = analysis->script > Script_LastId ? Script_Unknown : analysis->script; + scriptprops = &dwritescripts_properties[script]; + hr = shape_get_glyphs(&context, scriptprops->scripttags); + if (SUCCEEDED(hr)) + hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyphs, *actual_glyph_count, + text_props, glyph_props); done: heap_free(string); diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 45161894455..7a8ce1e4996 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -24,6 +24,9 @@ #include "wine/list.h" #include "wine/unicode.h" +#define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B') +#define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S') + static const DWRITE_MATRIX identity = { 1.0f, 0.0f, @@ -466,6 +469,7 @@ struct scriptshaping_context const WCHAR *text; unsigned int length; BOOL is_rtl; + BOOL is_sideways; union { @@ -495,10 +499,16 @@ extern struct scriptshaping_cache *create_scriptshaping_cache(void *context, extern void release_scriptshaping_cache(struct scriptshaping_cache*) DECLSPEC_HIDDEN; extern struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface) DECLSPEC_HIDDEN; +struct shaping_feature +{ + unsigned int tag; +}; + struct shaping_features { - const DWORD *tags; - unsigned int count; + struct shaping_feature *features; + size_t count; + size_t capacity; }; extern void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache) DECLSPEC_HIDDEN; @@ -506,6 +516,8 @@ extern DWORD opentype_layout_find_script(const struct scriptshaping_cache *cache unsigned int *script_index) DECLSPEC_HIDDEN; extern DWORD opentype_layout_find_language(const struct scriptshaping_cache *cache, DWORD kind, DWORD tag, unsigned int script_index, unsigned int *language_index) DECLSPEC_HIDDEN; +extern HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index, + unsigned int language_index, const struct shaping_features *features) DECLSPEC_HIDDEN; extern void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, const struct shaping_features *features) DECLSPEC_HIDDEN; @@ -520,5 +532,6 @@ struct scriptshaping_ops extern const struct scriptshaping_ops default_shaping_ops DECLSPEC_HIDDEN; extern const struct scriptshaping_ops latn_shaping_ops DECLSPEC_HIDDEN; +extern HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned int *scripts) DECLSPEC_HIDDEN; extern HRESULT shape_get_positions(struct scriptshaping_context *context, const DWORD *scripts, const struct shaping_features *features) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index a2af5ce954f..b9db82d661d 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -34,8 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite); #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t') #define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f') #define MS_GDEF_TAG DWRITE_MAKE_OPENTYPE_TAG('G','D','E','F') -#define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S') -#define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B') #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e') #define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f') #define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ') @@ -4107,7 +4105,7 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, if (feature_index >= total_feature_count) continue; - if (feature_list->features[feature_index].tag == features->tags[i]) + if (feature_list->features[feature_index].tag == features->features[i].tag) { WORD feature_offset = GET_BE_WORD(feature_list->features[feature_index].offset); WORD lookup_count; @@ -4152,3 +4150,9 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, heap_free(lookups.indexes); } + +HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index, + unsigned int language_index, const struct shaping_features *features) +{ + return S_OK; +} diff --git a/dlls/dwrite/shape.c b/dlls/dwrite/shape.c index bd53f035138..dd7c45e3e7d 100644 --- a/dlls/dwrite/shape.c +++ b/dlls/dwrite/shape.c @@ -27,8 +27,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite); -#define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S') - struct scriptshaping_cache *create_scriptshaping_cache(void *context, const struct shaping_font_ops *font_ops) { struct scriptshaping_cache *cache; @@ -165,11 +163,11 @@ static HRESULT latn_set_text_glyphs_props(struct scriptshaping_context *context, return hr; } -static const DWORD std_gpos_tags[] = +static struct shaping_feature std_gpos_tags[] = { - DWRITE_FONT_FEATURE_TAG_KERNING, - DWRITE_FONT_FEATURE_TAG_MARK_POSITIONING, - DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING, + { DWRITE_FONT_FEATURE_TAG_KERNING }, + { DWRITE_FONT_FEATURE_TAG_MARK_POSITIONING }, + { DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING }, }; static const struct shaping_features std_gpos_features = @@ -268,3 +266,73 @@ HRESULT shape_get_positions(struct scriptshaping_context *context, const DWORD * return S_OK; } + +static void shape_add_feature(struct shaping_features *features, unsigned int tag) +{ + if (!dwrite_array_reserve((void **)&features->features, &features->capacity, features->count + 1, + sizeof(*features->features))) + return; + + features->features[features->count++].tag = tag; +} + +static unsigned int shape_get_script_lang_index(struct scriptshaping_context *context, const unsigned int *scripts, + unsigned int table, unsigned int *script_index, unsigned int *language_index) +{ + unsigned int script; + + /* Resolve script tag to actually supported script. */ + if ((script = shape_select_script(context->cache, table, scripts, script_index))) + { + unsigned int language = context->language_tag; + + if ((language = shape_select_language(context->cache, table, *script_index, language, language_index))) + return script; + } + + return 0; +} + +HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned int *scripts) +{ + static const unsigned int common_features[] = + { + DWRITE_FONT_FEATURE_TAG_GLYPH_COMPOSITION_DECOMPOSITION, + DWRITE_FONT_FEATURE_TAG_LOCALIZED_FORMS, + DWRITE_FONT_FEATURE_TAG_REQUIRED_LIGATURES, + }; + static const unsigned int horizontal_features[] = + { + DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_ALTERNATES, + DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_LIGATURES, + DWRITE_FONT_FEATURE_TAG_STANDARD_LIGATURES, + DWRITE_MAKE_OPENTYPE_TAG('r','c','l','t'), + }; + struct scriptshaping_cache *cache = context->cache; + unsigned int script_index, language_index, script; + struct shaping_features features = { 0 }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(common_features); ++i) + shape_add_feature(&features, common_features[i]); + + /* Horizontal features */ + if (!context->is_sideways) + { + for (i = 0; i < ARRAY_SIZE(horizontal_features); ++i) + shape_add_feature(&features, horizontal_features[i]); + } + + /* Resolve script tag to actually supported script. */ + if (cache->gsub.table.data) + { + if ((script = shape_get_script_lang_index(context, scripts, MS_GSUB_TAG, &script_index, &language_index))) + { + opentype_layout_apply_gsub_features(context, script_index, language_index, &features); + } + } + + heap_free(features.features); + + return S_OK; +}