[PATCH 3/6] dwrite: Add helper functions to collect default GSUB features.

Nikolay Sivov nsivov at codeweavers.com
Mon May 4 03:29:32 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 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 de8ac2ea3c..bc5c54f21e 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 4516189445..7a8ce1e499 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 a2af5ce954..b9db82d661 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 bd53f03513..dd7c45e3e7 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;
+}
-- 
2.26.2




More information about the wine-devel mailing list