dwrite: Set per-glyph feature mask.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b8625c7f03
commit
8962f82210
|
@ -1259,6 +1259,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
|
||||||
context.user_features.features = features;
|
context.user_features.features = features;
|
||||||
context.user_features.range_lengths = feature_range_lengths;
|
context.user_features.range_lengths = feature_range_lengths;
|
||||||
context.user_features.range_count = feature_ranges;
|
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;
|
script = analysis->script > Script_LastId ? Script_Unknown : analysis->script;
|
||||||
scriptprops = &dwritescripts_properties[script];
|
scriptprops = &dwritescripts_properties[script];
|
||||||
|
@ -1268,6 +1269,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
|
||||||
text_props, glyph_props);
|
text_props, glyph_props);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
heap_free(context.glyph_infos);
|
||||||
heap_free(string);
|
heap_free(string);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -1284,6 +1286,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2
|
||||||
struct scriptshaping_context context;
|
struct scriptshaping_context context;
|
||||||
struct dwrite_fontface *font_obj;
|
struct dwrite_fontface *font_obj;
|
||||||
unsigned int i, script;
|
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),
|
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,
|
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.features = features;
|
||||||
context.user_features.range_lengths = feature_range_lengths;
|
context.user_features.range_lengths = feature_range_lengths;
|
||||||
context.user_features.range_count = feature_ranges;
|
context.user_features.range_count = feature_ranges;
|
||||||
|
context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count);
|
||||||
|
|
||||||
return shape_get_positions(&context, scriptprops->scripttags);
|
hr = shape_get_positions(&context, scriptprops->scripttags);
|
||||||
|
|
||||||
|
heap_free(context.glyph_infos);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWriteTextAnalyzer2 *iface,
|
static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWriteTextAnalyzer2 *iface,
|
||||||
|
@ -1344,6 +1352,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite
|
||||||
DWRITE_MEASURING_MODE measuring_mode;
|
DWRITE_MEASURING_MODE measuring_mode;
|
||||||
struct dwrite_fontface *font_obj;
|
struct dwrite_fontface *font_obj;
|
||||||
unsigned int i, script;
|
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),
|
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,
|
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.features = features;
|
||||||
context.user_features.range_lengths = feature_range_lengths;
|
context.user_features.range_lengths = feature_range_lengths;
|
||||||
context.user_features.range_count = feature_ranges;
|
context.user_features.range_count = feature_ranges;
|
||||||
|
context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count);
|
||||||
|
|
||||||
return shape_get_positions(&context, scriptprops->scripttags);
|
hr = 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,
|
static HRESULT apply_cluster_spacing(float leading_spacing, float trailing_spacing, float min_advance_width,
|
||||||
|
|
|
@ -461,6 +461,11 @@ struct scriptshaping_cache
|
||||||
} gdef;
|
} gdef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct shaping_glyph_info
|
||||||
|
{
|
||||||
|
unsigned int mask;
|
||||||
|
};
|
||||||
|
|
||||||
struct scriptshaping_context
|
struct scriptshaping_context
|
||||||
{
|
{
|
||||||
struct scriptshaping_cache *cache;
|
struct scriptshaping_cache *cache;
|
||||||
|
@ -493,6 +498,7 @@ struct scriptshaping_context
|
||||||
unsigned int range_count;
|
unsigned int range_count;
|
||||||
} user_features;
|
} user_features;
|
||||||
unsigned int global_mask;
|
unsigned int global_mask;
|
||||||
|
struct shaping_glyph_info *glyph_infos;
|
||||||
|
|
||||||
unsigned int glyph_count;
|
unsigned int glyph_count;
|
||||||
float emsize;
|
float emsize;
|
||||||
|
|
|
@ -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,
|
void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index,
|
||||||
unsigned int language_index, const struct shaping_features *features)
|
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_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)
|
for (i = 0; i < lookups.count; ++i)
|
||||||
opentype_layout_apply_gpos_lookup(context, lookups.lookups[i].index);
|
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_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)
|
for (i = 0; i < lookups.count; ++i)
|
||||||
opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.lookups[i].index);
|
opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.lookups[i].index);
|
||||||
|
|
||||||
|
|
|
@ -370,7 +370,10 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i
|
||||||
if (!context->is_sideways)
|
if (!context->is_sideways)
|
||||||
{
|
{
|
||||||
if (context->is_rtl)
|
if (context->is_rtl)
|
||||||
|
{
|
||||||
shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','a'));
|
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
|
else
|
||||||
{
|
{
|
||||||
shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','a'));
|
shape_add_feature(&features, DWRITE_MAKE_OPENTYPE_TAG('l','t','r','a'));
|
||||||
|
|
Loading…
Reference in New Issue