Nikolay Sivov : dwrite: Set per-glyph feature mask.

Alexandre Julliard julliard at winehq.org
Fri May 22 13:51:09 CDT 2020


Module: wine
Branch: master
Commit: 8962f82210b2cdc733ce3eee1c257f846bb54a9c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=8962f82210b2cdc733ce3eee1c257f846bb54a9c

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri May 22 13:58:07 2020 +0300

dwrite: Set per-glyph feature mask.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dwrite/analyzer.c       | 18 ++++++++++++++--
 dlls/dwrite/dwrite_private.h |  6 ++++++
 dlls/dwrite/opentype.c       | 51 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/dwrite/shape.c          |  3 +++
 4 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index 98e1ef4a0d..62258ec441 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -1259,6 +1259,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
     context.user_features.features = features;
     context.user_features.range_lengths = feature_range_lengths;
     context.user_features.range_count = feature_ranges;
+    context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * max_glyph_count);
 
     script = analysis->script > Script_LastId ? Script_Unknown : analysis->script;
     scriptprops = &dwritescripts_properties[script];
@@ -1268,6 +1269,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
                 text_props, glyph_props);
 
 done:
+    heap_free(context.glyph_infos);
     heap_free(string);
 
     return hr;
@@ -1284,6 +1286,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2
     struct scriptshaping_context context;
     struct dwrite_fontface *font_obj;
     unsigned int i, script;
+    HRESULT hr;
 
     TRACE("(%s %p %p %u %p %p %u %p %.2f %d %d %s %s %p %p %u %p %p)\n", debugstr_wn(text, text_len),
         clustermap, props, text_len, glyphs, glyph_props, glyph_count, fontface, emSize, is_sideways,
@@ -1327,8 +1330,13 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2
     context.user_features.features = features;
     context.user_features.range_lengths = feature_range_lengths;
     context.user_features.range_count = feature_ranges;
+    context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count);
+
+    hr = shape_get_positions(&context, scriptprops->scripttags);
 
-    return shape_get_positions(&context, scriptprops->scripttags);
+    heap_free(context.glyph_infos);
+
+    return hr;
 }
 
 static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWriteTextAnalyzer2 *iface,
@@ -1344,6 +1352,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite
     DWRITE_MEASURING_MODE measuring_mode;
     struct dwrite_fontface *font_obj;
     unsigned int i, script;
+    HRESULT hr;
 
     TRACE("(%s %p %p %u %p %p %u %p %.2f %.2f %p %d %d %d %s %s %p %p %u %p %p)\n", debugstr_wn(text, text_len),
         clustermap, props, text_len, glyphs, glyph_props, glyph_count, fontface, emSize, ppdip,
@@ -1389,8 +1398,13 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite
     context.user_features.features = features;
     context.user_features.range_lengths = feature_range_lengths;
     context.user_features.range_count = feature_ranges;
+    context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count);
+
+    hr = shape_get_positions(&context, scriptprops->scripttags);
 
-    return shape_get_positions(&context, scriptprops->scripttags);
+    heap_free(context.glyph_infos);
+
+    return hr;
 }
 
 static HRESULT apply_cluster_spacing(float leading_spacing, float trailing_spacing, float min_advance_width,
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index ef48ec18c4..afa4bce91d 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -461,6 +461,11 @@ struct scriptshaping_cache
     } gdef;
 };
 
+struct shaping_glyph_info
+{
+    unsigned int mask;
+};
+
 struct scriptshaping_context
 {
     struct scriptshaping_cache *cache;
@@ -493,6 +498,7 @@ struct scriptshaping_context
         unsigned int range_count;
     } user_features;
     unsigned int global_mask;
+    struct shaping_glyph_info *glyph_infos;
 
     unsigned int glyph_count;
     float emsize;
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 1cb61027b4..cb1743c5cc 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -4311,6 +4311,53 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex
     }
 }
 
+static int feature_search_compare(const void *a, const void* b)
+{
+    unsigned int tag = *(unsigned int *)a;
+    const struct shaping_feature *feature = b;
+
+    return tag < feature->tag ? -1 : tag > feature->tag ? 1 : 0;
+}
+
+static unsigned int shaping_features_get_mask(const struct shaping_features *features, unsigned int tag, unsigned int *shift)
+{
+    struct shaping_feature *feature;
+
+    feature = bsearch(&tag, features->features, features->count, sizeof(*features->features), feature_search_compare);
+
+    if (!feature || feature->index == 0xffff)
+        return 0;
+
+    *shift = feature->shift;
+    return feature->mask;
+}
+
+static void opentype_layout_set_glyph_masks(struct scriptshaping_context *context, const struct shaping_features *features)
+{
+   const DWRITE_TYPOGRAPHIC_FEATURES **user_features = context->user_features.features;
+   unsigned int f, r, g, start_glyph = 0, mask, shift, value;
+
+   for (g = 0; g < context->glyph_count; ++g)
+       context->glyph_infos[g].mask = context->global_mask;
+
+   /* FIXME: set shaper masks */
+
+   for (r = 0; r < context->user_features.range_count; ++r)
+   {
+       for (f = 0; f < user_features[r]->featureCount; ++f)
+       {
+           mask = shaping_features_get_mask(features, user_features[r]->features[f].nameTag, &shift);
+           if (!mask)
+               continue;
+
+           value = (user_features[r]->features[f].parameter << shift) & mask;
+           for (g = 0; g < context->user_features.range_lengths[r]; ++g)
+               context->glyph_infos[g + start_glyph].mask = (context->glyph_infos[g + start_glyph].mask & ~mask) | value;
+           start_glyph += context->user_features.range_lengths[r];
+       }
+   }
+}
+
 void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index,
         unsigned int language_index, const struct shaping_features *features)
 {
@@ -4319,6 +4366,8 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context,
 
     opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gpos, &lookups);
 
+    opentype_layout_set_glyph_masks(context, features);
+
     for (i = 0; i < lookups.count; ++i)
         opentype_layout_apply_gpos_lookup(context, lookups.lookups[i].index);
 
@@ -4629,6 +4678,8 @@ HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *contex
 
     opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gsub, &lookups);
 
+    opentype_layout_set_glyph_masks(context, features);
+
     for (i = 0; i < lookups.count; ++i)
         opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.lookups[i].index);
 
diff --git a/dlls/dwrite/shape.c b/dlls/dwrite/shape.c
index 0f88ad4821..18afb2212b 100644
--- a/dlls/dwrite/shape.c
+++ b/dlls/dwrite/shape.c
@@ -370,7 +370,10 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i
     if (!context->is_sideways)
     {
         if (context->is_rtl)
+        {
             shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','a'));
+            shape_add_feature_full(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), 0, 1);
+        }
         else
         {
             shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','a'));




More information about the wine-cvs mailing list