Module: wine Branch: master Commit: 8962f82210b2cdc733ce3eee1c257f846bb54a9c URL: https://source.winehq.org/git/wine.git/?a=commit;h=8962f82210b2cdc733ce3eee1...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Fri May 22 13:58:07 2020 +0300
dwrite: Set per-glyph feature mask.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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'));