Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 3 + dlls/dwrite/opentype.c | 144 ++++++++++++++++++++++++++--------- 2 files changed, 111 insertions(+), 36 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 8b5fefc66bd..3145daba4bb 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -492,6 +492,7 @@ struct scriptshaping_context const unsigned int *range_lengths; unsigned int range_count; } user_features; + unsigned int global_mask;
unsigned int glyph_count; float emsize; @@ -525,6 +526,8 @@ struct shaping_feature unsigned int flags; unsigned int max_value; unsigned int default_value; + unsigned int mask; + unsigned int shift; };
struct shaping_features diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 8904dc546e9..d2a9318da87 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -3210,6 +3210,36 @@ static inline unsigned int dwrite_popcount(unsigned int x) #endif }
+static inline unsigned int dwrite_log2i(unsigned int x) +{ +#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3))) + return __builtin_clz(x) ^ 0x1f; +#else + static const unsigned int l[] = + { + ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + }; + unsigned int i; + + return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x]; +#endif +} + static float opentype_scale_gpos_be_value(WORD value, float emsize, UINT16 upem) { return (short)GET_BE_WORD(value) * emsize / upem; @@ -3333,7 +3363,7 @@ static unsigned int opentype_layout_get_gsub_subtable(const struct scriptshaping return lookup_offset + subtable_offset; }
-struct lookup +struct ot_lookup { unsigned int offset; unsigned int subtable_count; @@ -3406,7 +3436,7 @@ static BOOL glyph_iterator_prev(struct glyph_iterator *iter) }
static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; WORD format, value_format, value_len, coverage; @@ -3469,7 +3499,7 @@ static int gpos_pair_adjustment_compare_format1(const void *g, const void *r) }
static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i, first_glyph, second_glyph; @@ -3676,7 +3706,7 @@ static void opentype_layout_gpos_get_anchor(const struct scriptshaping_context * }
static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3760,7 +3790,7 @@ static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_c }
static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3843,7 +3873,7 @@ static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshap }
static BOOL opentype_layout_apply_gpos_mark_to_lig_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3889,7 +3919,7 @@ static BOOL opentype_layout_apply_gpos_mark_to_lig_attachment(struct scriptshapi }
static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = context->cache; unsigned int i; @@ -3974,13 +4004,13 @@ static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshap }
static BOOL opentype_layout_apply_gpos_contextual_positioning(const struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { return FALSE; }
static BOOL opentype_layout_apply_gpos_chaining_contextual_positioning(const struct scriptshaping_context *context, - struct glyph_iterator *iter, const struct lookup *lookup) + struct glyph_iterator *iter, const struct ot_lookup *lookup) { return FALSE; } @@ -3990,7 +4020,7 @@ static void opentype_layout_apply_gpos_lookup(struct scriptshaping_context *cont struct scriptshaping_cache *cache = context->cache; const struct ot_lookup_table *lookup_table; struct glyph_iterator iter; - struct lookup lookup; + struct ot_lookup lookup; WORD lookup_type;
lookup.offset = table_read_be_word(&cache->gpos.table, cache->gpos.lookup_list + @@ -4081,16 +4111,24 @@ static void opentype_layout_apply_gpos_lookup(struct scriptshaping_context *cont } }
+struct lookup +{ + unsigned short index; + unsigned int mask; +}; + struct lookups { - int *indexes; + struct lookup *lookups; size_t capacity; size_t count; };
-static int lookups_sorting_compare(const void *left, const void *right) +static int lookups_sorting_compare(const void *a, const void *b) { - return *(int *)left - *(int *)right; + const struct lookup *left = (const struct lookup *)a; + const struct lookup *right = (const struct lookup *)b; + return left->index < right->index ? -1 : left->index > right->index ? 1 : 0; };
static void opentype_layout_collect_lookups(struct scriptshaping_context *context, unsigned int script_index, @@ -4099,8 +4137,11 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex { UINT16 table_offset, langsys_offset, script_feature_count, total_feature_count, total_lookup_count; const struct ot_feature_list *feature_list; + struct shaping_feature *feature; + unsigned int i, j, l, next_bit; + unsigned int global_bit_shift = 1; + unsigned int global_bit_mask = 1; UINT16 feature_index; - unsigned int i, j, l;
/* ScriptTable offset. */ table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) + @@ -4133,19 +4174,34 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex if (!feature_list) return;
+ context->global_mask = global_bit_mask; + next_bit = global_bit_shift + 1; for (i = 0; i < features->count; ++i) { + unsigned int bits_needed; BOOL found = FALSE;
+ feature = &features->features[i]; + + feature->index = 0xffff; + + if ((feature->flags & FEATURE_GLOBAL) && feature->max_value == 1) + bits_needed = 0; + else + bits_needed = min(8, dwrite_log2i(feature->max_value)); + + if (!feature->max_value || next_bit + bits_needed > 8 * sizeof (feature->mask)) + continue; + for (j = 0; j < script_feature_count; ++j) { feature_index = table_read_be_word(&table->table, table->script_list + table_offset + langsys_offset + FIELD_OFFSET(struct ot_langsys, feature_index[j])); if (feature_index >= total_feature_count) continue; - if ((found = feature_list->features[feature_index].tag == features->features[i].tag)) + if ((found = feature_list->features[feature_index].tag == feature->tag)) { - features->features[i].index = feature_index; + feature->index = feature_index; break; } } @@ -4154,16 +4210,29 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex { for (j = 0; j < total_feature_count; ++j) { - if ((found = (feature_list->features[j].tag == features->features[i].tag))) + if ((found = (feature_list->features[j].tag == feature->tag))) { - features->features[i].index = j; + feature->index = j; break; } } }
if (!found) - features->features[i].index = 0xffff; + continue; + + if (feature->flags & FEATURE_GLOBAL && feature->max_value == 1) + { + feature->shift = global_bit_shift; + feature->mask = global_bit_mask; + } + else + { + feature->shift = next_bit; + feature->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); + next_bit += bits_needed; + context->global_mask |= (feature->default_value << feature->shift) & feature->mask; + } }
/* Collect lookups for all given features. */ @@ -4171,25 +4240,25 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex { UINT16 feature_offset, lookup_count;
- feature_index = features->features[i].index; + feature = &features->features[i];
/* Feature wasn't found */ - if (feature_index == 0xffff) + if (feature->index == 0xffff) continue;
/* FIXME: skip non-global ones for now. */ - if (!(features->features[i].flags & FEATURE_GLOBAL)) + if (!(feature->flags & FEATURE_GLOBAL)) continue;
- feature_offset = GET_BE_WORD(feature_list->features[feature_index].offset); + feature_offset = GET_BE_WORD(feature_list->features[feature->index].offset);
lookup_count = table_read_be_word(&table->table, table->feature_list + feature_offset + FIELD_OFFSET(struct ot_feature, lookup_count)); if (!lookup_count) continue;
- if (!dwrite_array_reserve((void **)&lookups->indexes, &lookups->capacity, lookups->count + lookup_count, - sizeof(*lookups->indexes))) + if (!dwrite_array_reserve((void **)&lookups->lookups, &lookups->capacity, lookups->count + lookup_count, + sizeof(*lookups->lookups))) { return; } @@ -4202,12 +4271,15 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex if (lookup_index >= total_lookup_count) continue;
- lookups->indexes[lookups->count++] = lookup_index; + j = lookups->count; + lookups->lookups[j].index = lookup_index; + lookups->lookups[j].mask = feature->mask; + lookups->count++; } }
/* Sort lookups. */ - qsort(lookups->indexes, lookups->count, sizeof(*lookups->indexes), lookups_sorting_compare); + qsort(lookups->lookups, lookups->count, sizeof(*lookups->lookups), lookups_sorting_compare); }
void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index, @@ -4221,16 +4293,16 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, for (i = 0; i < lookups.count; ++i) { /* Skip duplicates. */ - if (i && lookups.indexes[i] == lookups.indexes[i - 1]) + if (i && lookups.lookups[i].index == lookups.lookups[i - 1].index) continue;
- opentype_layout_apply_gpos_lookup(context, lookups.indexes[i]); + opentype_layout_apply_gpos_lookup(context, lookups.lookups[i].index); }
- heap_free(lookups.indexes); + heap_free(lookups.lookups); }
-static BOOL opentype_layout_apply_gsub_single_substitution(struct glyph_iterator *iter, const struct lookup *lookup) +static BOOL opentype_layout_apply_gsub_single_substitution(struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = iter->context->cache; UINT16 format, coverage; @@ -4376,7 +4448,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_lookup(struct glyph_iterato opentype_layout_context_gsub_apply_lookup(iter, input_count, lookup_count, lookup_records); }
-static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct glyph_iterator *iter, const struct lookup *lookup) +static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct glyph_iterator *iter, const struct ot_lookup *lookup) { struct scriptshaping_cache *cache = iter->context->cache; UINT16 format, coverage; @@ -4468,7 +4540,7 @@ static void opentype_layout_apply_gsub_lookup(struct scriptshaping_context *cont struct ot_gsubgpos_table *table = &context->cache->gsub; const struct ot_lookup_table *lookup_table; struct glyph_iterator iter; - struct lookup lookup; + struct ot_lookup lookup; WORD lookup_type;
lookup.offset = table_read_be_word(&table->table, table->lookup_list + FIELD_OFFSET(struct ot_lookup_list, lookup[lookup_index])); @@ -4537,13 +4609,13 @@ HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *contex for (i = 0; i < lookups.count; ++i) { /* Skip duplicates. */ - if (i && lookups.indexes[i] == lookups.indexes[i - 1]) + if (i && lookups.lookups[i].index == lookups.lookups[i - 1].index) continue;
- opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.indexes[i]); + opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.lookups[i].index); }
- heap_free(lookups.indexes); + heap_free(lookups.lookups);
return S_OK; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 2 + dlls/dwrite/opentype.c | 117 ++++++++++++++++++++--------------- dlls/dwrite/shape.c | 2 + 3 files changed, 71 insertions(+), 50 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 3145daba4bb..ef48ec18c4a 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -528,6 +528,7 @@ struct shaping_feature unsigned int default_value; unsigned int mask; unsigned int shift; + unsigned int stage; };
struct shaping_features @@ -535,6 +536,7 @@ struct shaping_features struct shaping_feature *features; size_t count; size_t capacity; + unsigned int stage; };
extern void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index d2a9318da87..1cb61027b4e 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -4131,14 +4131,57 @@ static int lookups_sorting_compare(const void *a, const void *b) return left->index < right->index ? -1 : left->index > right->index ? 1 : 0; };
+static void opentype_layout_add_lookups(const struct ot_feature_list *feature_list, UINT16 total_lookup_count, + struct ot_gsubgpos_table *table, struct shaping_feature *feature, struct lookups *lookups) +{ + UINT16 feature_offset, lookup_count; + unsigned int i, j; + + /* Feature wasn't found */ + if (feature->index == 0xffff) + return; + + /* FIXME: skip non-global ones for now. */ + if (!(feature->flags & FEATURE_GLOBAL)) + return; + + feature_offset = GET_BE_WORD(feature_list->features[feature->index].offset); + + lookup_count = table_read_be_word(&table->table, table->feature_list + feature_offset + + FIELD_OFFSET(struct ot_feature, lookup_count)); + if (!lookup_count) + return; + + if (!dwrite_array_reserve((void **)&lookups->lookups, &lookups->capacity, lookups->count + lookup_count, + sizeof(*lookups->lookups))) + { + return; + } + + for (i = 0; i < lookup_count; ++i) + { + UINT16 lookup_index = table_read_be_word(&table->table, table->feature_list + feature_offset + + FIELD_OFFSET(struct ot_feature, lookuplist_index[i])); + + if (lookup_index >= total_lookup_count) + continue; + + j = lookups->count; + lookups->lookups[j].index = lookup_index; + lookups->lookups[j].mask = feature->mask; + lookups->count++; + } +} + static void opentype_layout_collect_lookups(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, const struct shaping_features *features, struct ot_gsubgpos_table *table, struct lookups *lookups) { UINT16 table_offset, langsys_offset, script_feature_count, total_feature_count, total_lookup_count; const struct ot_feature_list *feature_list; + unsigned int last_num_lookups = 0, stage; struct shaping_feature *feature; - unsigned int i, j, l, next_bit; + unsigned int i, j, next_bit; unsigned int global_bit_shift = 1; unsigned int global_bit_mask = 1; UINT16 feature_index; @@ -4235,51 +4278,37 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex } }
- /* Collect lookups for all given features. */ - for (i = 0; i < features->count; ++i) + for (stage = 0; stage <= features->stage; ++stage) { - UINT16 feature_offset, lookup_count; - - feature = &features->features[i]; - - /* Feature wasn't found */ - if (feature->index == 0xffff) - continue; - - /* FIXME: skip non-global ones for now. */ - if (!(feature->flags & FEATURE_GLOBAL)) - continue; - - feature_offset = GET_BE_WORD(feature_list->features[feature->index].offset); - - lookup_count = table_read_be_word(&table->table, table->feature_list + feature_offset + - FIELD_OFFSET(struct ot_feature, lookup_count)); - if (!lookup_count) - continue; - - if (!dwrite_array_reserve((void **)&lookups->lookups, &lookups->capacity, lookups->count + lookup_count, - sizeof(*lookups->lookups))) + for (i = 0; i < features->count; ++i) { - return; + if (features->features[i].stage == stage) + opentype_layout_add_lookups(feature_list, total_lookup_count, table, &features->features[i], lookups); }
- for (l = 0; l < lookup_count; ++l) + /* Sort and merge lookups for current stage. */ + if (last_num_lookups < lookups->count) { - UINT16 lookup_index = table_read_be_word(&table->table, table->feature_list + feature_offset + - FIELD_OFFSET(struct ot_feature, lookuplist_index[l])); + qsort(lookups->lookups + last_num_lookups, lookups->count - last_num_lookups, sizeof(*lookups->lookups), + lookups_sorting_compare);
- if (lookup_index >= total_lookup_count) - continue; - - j = lookups->count; - lookups->lookups[j].index = lookup_index; - lookups->lookups[j].mask = feature->mask; - lookups->count++; + j = last_num_lookups; + for (i = j + 1; i < lookups->count; ++i) + { + if (lookups->lookups[i].index != lookups->lookups[j].index) + { + lookups->lookups[++j] = lookups->lookups[i]; + } + else + { + lookups->lookups[j].mask |= lookups->lookups[i].mask; + } + } + lookups->count = j + 1; } - }
- /* Sort lookups. */ - qsort(lookups->lookups, lookups->count, sizeof(*lookups->lookups), lookups_sorting_compare); + last_num_lookups = lookups->count; + } }
void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, unsigned int script_index, @@ -4291,13 +4320,7 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context, opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gpos, &lookups);
for (i = 0; i < lookups.count; ++i) - { - /* Skip duplicates. */ - if (i && lookups.lookups[i].index == lookups.lookups[i - 1].index) - continue; - opentype_layout_apply_gpos_lookup(context, lookups.lookups[i].index); - }
heap_free(lookups.lookups); } @@ -4607,13 +4630,7 @@ HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *contex opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gsub, &lookups);
for (i = 0; i < lookups.count; ++i) - { - /* Skip duplicates. */ - if (i && lookups.lookups[i].index == lookups.lookups[i - 1].index) - continue; - opentype_layout_apply_gsub_lookup(context, 0, context->glyph_count, lookups.lookups[i].index); - }
heap_free(lookups.lookups);
diff --git a/dlls/dwrite/shape.c b/dlls/dwrite/shape.c index df680373a24..0f88ad48215 100644 --- a/dlls/dwrite/shape.c +++ b/dlls/dwrite/shape.c @@ -213,6 +213,7 @@ static void shape_add_feature_full(struct shaping_features *features, unsigned i features->features[i].flags = flags; features->features[i].max_value = value; features->features[i].default_value = flags & FEATURE_GLOBAL ? value : 0; + features->features[i].stage = features->stage; features->count++; }
@@ -267,6 +268,7 @@ static void shape_merge_features(struct scriptshaping_context *context, struct s features->features[j].flags ^= FEATURE_GLOBAL; features->features[j].max_value = max(features->features[j].max_value, features->features[i].max_value); } + features->features[j].stage = min(features->features[j].stage, features->features[i].stage); } } features->count = j + 1;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- 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 98e1ef4a0dc..62258ec4416 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 ef48ec18c4a..afa4bce91df 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 1cb61027b4e..cb1743c5cca 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 0f88ad48215..18afb2212bd 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'));
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/opentype.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index cb1743c5cca..35b02d55730 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -778,7 +778,7 @@ typedef struct { enum TT_NAME_WINDOWS_ENCODING_ID { TT_NAME_WINDOWS_ENCODING_SYMBOL = 0, - TT_NAME_WINDOWS_ENCODING_UCS2, + TT_NAME_WINDOWS_ENCODING_UNICODE_BMP, TT_NAME_WINDOWS_ENCODING_SJIS, TT_NAME_WINDOWS_ENCODING_PRC, TT_NAME_WINDOWS_ENCODING_BIG5, @@ -787,7 +787,7 @@ enum TT_NAME_WINDOWS_ENCODING_ID TT_NAME_WINDOWS_ENCODING_RESERVED1, TT_NAME_WINDOWS_ENCODING_RESERVED2, TT_NAME_WINDOWS_ENCODING_RESERVED3, - TT_NAME_WINDOWS_ENCODING_UCS4 + TT_NAME_WINDOWS_ENCODING_UNICODE_FULL };
enum TT_NAME_MAC_ENCODING_ID @@ -1972,7 +1972,8 @@ static UINT get_name_record_codepage(enum OPENTYPE_PLATFORM_ID platform, USHORT switch (encoding) { case TT_NAME_WINDOWS_ENCODING_SYMBOL: - case TT_NAME_WINDOWS_ENCODING_UCS2: + case TT_NAME_WINDOWS_ENCODING_UNICODE_BMP: + case TT_NAME_WINDOWS_ENCODING_UNICODE_FULL: break; case TT_NAME_WINDOWS_ENCODING_SJIS: codepage = 932;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/analyzer.c | 96 ++++++------------------------------ dlls/dwrite/bidi.c | 7 --- dlls/dwrite/dwrite_private.h | 7 ++- dlls/dwrite/font.c | 40 ++++++++++----- dlls/dwrite/opentype.c | 67 ++++++++++++++++++++++++- dlls/dwrite/shape.c | 12 ++--- 6 files changed, 119 insertions(+), 110 deletions(-)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index 62258ec4416..85fd10b0b28 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -1059,15 +1059,17 @@ static UINT32 get_opentype_language(const WCHAR *locale) return language; }
-static DWRITE_NUMBER_SUBSTITUTION_METHOD get_number_substitutes(IDWriteNumberSubstitution *substitution, WCHAR *digits) +static void get_number_substitutes(IDWriteNumberSubstitution *substitution, BOOL is_rtl, WCHAR *digits) { struct dwrite_numbersubstitution *numbersubst = unsafe_impl_from_IDWriteNumberSubstitution(substitution); DWRITE_NUMBER_SUBSTITUTION_METHOD method; WCHAR isolang[9]; DWORD lctype;
+ digits[0] = 0; + if (!numbersubst) - return DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE; + return;
lctype = numbersubst->ignore_user_override ? LOCALE_NOUSEROVERRIDE : 0;
@@ -1096,7 +1098,6 @@ static DWRITE_NUMBER_SUBSTITUTION_METHOD get_number_substitutes(IDWriteNumberSub else method = numbersubst->method;
- digits[0] = 0; switch (method) { case DWRITE_NUMBER_SUBSTITUTION_METHOD_NATIONAL: @@ -1125,7 +1126,8 @@ static DWRITE_NUMBER_SUBSTITUTION_METHOD get_number_substitutes(IDWriteNumberSub method = DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE; }
- return method; + if ((method == DWRITE_NUMBER_SUBSTITUTION_METHOD_CONTEXTUAL && !is_rtl) || method == DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE) + digits[0] = 0; }
static void analyzer_dump_user_features(DWRITE_TYPOGRAPHIC_FEATURES const **features, @@ -1153,14 +1155,11 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, 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 scriptshaping_context context = { 0 }; struct dwrite_fontface *font_obj; WCHAR digits[NATIVE_DIGITS_LEN]; - unsigned int i, g, script; - BOOL update_cluster; - WCHAR *string; - HRESULT hr = S_OK; + unsigned int script; + HRESULT hr;
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, @@ -1172,78 +1171,11 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, if (max_glyph_count < length) return E_NOT_SUFFICIENT_BUFFER;
- string = heap_calloc(length, sizeof(*string)); - if (!string) - return E_OUTOFMEMORY; - - method = get_number_substitutes(substitution, digits); + get_number_substitutes(substitution, is_rtl, digits);
/* FIXME: have the shaping engine set this */ memset(text_props, 0, length * sizeof(*text_props));
- for (i = 0; i < length; i++) { - /* FIXME: set to better values */ - glyph_props[i].justification = text[i] == ' ' ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER; - glyph_props[i].isClusterStart = 1; - glyph_props[i].isDiacritic = 0; - glyph_props[i].isZeroWidthSpace = 0; - glyph_props[i].reserved = 0; - - clustermap[i] = i; - - string[i] = text[i]; - switch (method) - { - case DWRITE_NUMBER_SUBSTITUTION_METHOD_CONTEXTUAL: - if (!is_rtl) - break; - /* fallthrough */ - default: - if (string[i] >= '0' && string[i] <= '9') - string[i] = digits[string[i] - '0']; - break; - case DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE: - ; - } - } - - for (; i < max_glyph_count; i++) { - glyph_props[i].justification = SCRIPT_JUSTIFY_NONE; - glyph_props[i].isClusterStart = 0; - glyph_props[i].isDiacritic = 0; - glyph_props[i].isZeroWidthSpace = 0; - glyph_props[i].reserved = 0; - } - - for (i = 0, g = 0, update_cluster = FALSE; i < length; i++) { - UINT32 codepoint; - - if (!update_cluster) { - codepoint = decode_surrogate_pair(string, i, length); - if (!codepoint) - codepoint = is_rtl ? bidi_get_mirrored_char(string[i]) : string[i]; - else - update_cluster = TRUE; - - hr = IDWriteFontFace_GetGlyphIndices(fontface, &codepoint, 1, &glyphs[g]); - if (FAILED(hr)) - goto done; - - g++; - } - else { - INT32 k; - - update_cluster = FALSE; - /* mark surrogate halves with same cluster */ - clustermap[i] = clustermap[i-1]; - /* update following clusters */ - for (k = i + 1; k >= 0 && k < length; k++) - clustermap[k]--; - } - } - *actual_glyph_count = g; - font_obj = unsafe_impl_from_IDWriteFontFace(fontface);
context.cache = fontface_get_shaping_cache(font_obj); @@ -1253,8 +1185,9 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, context.is_sideways = is_sideways; context.u.subst.glyphs = glyphs; context.u.subst.glyph_props = glyph_props; + context.u.subst.clustermap = clustermap; context.u.subst.max_glyph_count = max_glyph_count; - context.glyph_count = g; + context.u.subst.digits = digits; context.language_tag = get_opentype_language(locale); context.user_features.features = features; context.user_features.range_lengths = feature_range_lengths; @@ -1265,12 +1198,13 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface, scriptprops = &dwritescripts_properties[script]; hr = shape_get_glyphs(&context, scriptprops->scripttags); if (SUCCEEDED(hr)) + { + *actual_glyph_count = context.glyph_count; hr = default_shaping_ops.set_text_glyphs_props(&context, clustermap, glyphs, *actual_glyph_count, text_props, glyph_props); + }
-done: heap_free(context.glyph_infos); - heap_free(string);
return hr; } diff --git a/dlls/dwrite/bidi.c b/dlls/dwrite/bidi.c index 0323afb88cd..e2f3385519d 100644 --- a/dlls/dwrite/bidi.c +++ b/dlls/dwrite/bidi.c @@ -158,13 +158,6 @@ static void bidi_classify(const WCHAR *string, UINT8 *chartype, UINT32 count) chartype[i] = get_table_entry( bidi_direction_table, string[i] ); }
-WCHAR bidi_get_mirrored_char(WCHAR ch) -{ - extern const WCHAR wine_mirror_map[] DECLSPEC_HIDDEN; - WCHAR mirror = get_table_entry( wine_mirror_map, ch ); - return mirror ? mirror : ch; -} - /* RESOLVE EXPLICIT */
static inline UINT8 get_greater_even_level(UINT8 level) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index afa4bce91df..4cf1523f470 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -300,6 +300,8 @@ extern void factory_unlock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN; extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN; extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index, IDWriteFontResource **resource) DECLSPEC_HIDDEN; +extern HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints, + UINT32 count, UINT16 *glyphs);
struct dwrite_fontface;
@@ -378,7 +380,6 @@ extern unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp,
/* BiDi helpers */ extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN; -extern WCHAR bidi_get_mirrored_char(WCHAR) DECLSPEC_HIDDEN;
/* FreeType integration */ struct dwrite_glyphbitmap @@ -487,7 +488,9 @@ struct scriptshaping_context { UINT16 *glyphs; DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props; + UINT16 *clustermap; unsigned int max_glyph_count; + const WCHAR *digits; } subst; } u;
@@ -512,6 +515,8 @@ struct shaping_font_ops void (*grab_font_table)(void *context, UINT32 table, const BYTE **data, UINT32 *size, void **data_context); void (*release_font_table)(void *context, void *data_context); UINT16 (*get_font_upem)(void *context); + BOOL (*has_glyph)(void *context, unsigned int codepoint); + UINT16 (*get_glyph)(void *context, unsigned int codepoint); };
extern struct scriptshaping_cache *create_scriptshaping_cache(void *context, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index ee52c3e321c..75d2593e07e 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -272,11 +272,29 @@ static UINT16 dwrite_get_font_upem(void *context) return fontface->metrics.designUnitsPerEm; }
+static BOOL dwrite_has_glyph(void *context, unsigned int codepoint) +{ + struct dwrite_fontface *fontface = context; + UINT16 index = 0; + fontface_get_glyphs(fontface, &codepoint, 1, &index); + return !!index; +} + +static UINT16 dwrite_get_glyph(void *context, unsigned int codepoint) +{ + struct dwrite_fontface *fontface = context; + UINT16 index = 0; + fontface_get_glyphs(fontface, &codepoint, 1, &index); + return index; +} + static const struct shaping_font_ops dwrite_font_ops = { dwrite_grab_font_table, dwrite_release_font_table, dwrite_get_font_upem, + dwrite_has_glyph, + dwrite_get_glyph, };
struct scriptshaping_cache *fontface_get_shaping_cache(struct dwrite_fontface *fontface) @@ -714,17 +732,9 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *ifa return S_OK; }
-static HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints, +HRESULT fontface_get_glyphs(struct dwrite_fontface *fontface, UINT32 const *codepoints, UINT32 count, UINT16 *glyphs) { - if (!glyphs) - return E_INVALIDARG; - - if (!codepoints) { - memset(glyphs, 0, count * sizeof(*glyphs)); - return E_INVALIDARG; - } - freetype_get_glyphs(&fontface->IDWriteFontFace5_iface, fontface->charmap, codepoints, count, glyphs); return S_OK; } @@ -736,6 +746,15 @@ static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace5 *iface, UI
TRACE("%p, %p, %u, %p.\n", iface, codepoints, count, glyphs);
+ if (!glyphs) + return E_INVALIDARG; + + if (!codepoints) + { + memset(glyphs, 0, count * sizeof(*glyphs)); + return E_INVALIDARG; + } + return fontface_get_glyphs(fontface, codepoints, count, glyphs); }
@@ -1390,8 +1409,7 @@ static BOOL WINAPI dwritefontface3_HasCharacter(IDWriteFontFace5 *iface, UINT32 TRACE("%p, %#x.\n", iface, ch);
index = 0; - if (FAILED(fontface_get_glyphs(fontface, &ch, 1, &index))) - return FALSE; + fontface_get_glyphs(fontface, &ch, 1, &index);
return index != 0; } diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 35b02d55730..77ae1e84473 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -4187,6 +4187,9 @@ static void opentype_layout_collect_lookups(struct scriptshaping_context *contex unsigned int global_bit_mask = 1; UINT16 feature_index;
+ if (!table->table.data) + return; + /* ScriptTable offset. */ table_offset = table_read_be_word(&table->table, table->script_list + FIELD_OFFSET(struct ot_script_list, scripts) + script_index * sizeof(struct ot_script_record) + FIELD_OFFSET(struct ot_script_record, script)); @@ -4329,7 +4332,7 @@ static unsigned int shaping_features_get_mask(const struct shaping_features *fea if (!feature || feature->index == 0xffff) return 0;
- *shift = feature->shift; + if (shift) *shift = feature->shift; return feature->mask; }
@@ -4671,6 +4674,67 @@ static void opentype_layout_apply_gsub_lookup(struct scriptshaping_context *cont } }
+static unsigned int unicode_get_mirrored_char(unsigned int codepoint) +{ + extern const WCHAR wine_mirror_map[] DECLSPEC_HIDDEN; + WCHAR mirror; + /* TODO: check if mirroring for higher planes makes sense at all */ + if (codepoint > 0xffff) return codepoint; + mirror = get_table_entry(wine_mirror_map, codepoint); + return mirror ? mirror : codepoint; +} + +static void opentype_get_nominal_glyphs(struct scriptshaping_context *context, const struct shaping_features *features) +{ + unsigned int rtlm_mask = shaping_features_get_mask(features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), NULL); + const struct shaping_font_ops *font = context->cache->font; + UINT16 *clustermap = context->u.subst.clustermap; + const WCHAR *text = context->text; + unsigned int i, g, c, codepoint; + BOOL bmp; + + memset(context->u.subst.glyph_props, 0, context->u.subst.max_glyph_count * sizeof(*context->u.subst.glyph_props)); + + for (i = 0; i < context->length; ++i) + { + g = context->glyph_count; + + if ((bmp = !(IS_HIGH_SURROGATE(text[i]) && (i < context->length - 1) && IS_LOW_SURROGATE(text[i + 1])))) + { + codepoint = text[i]; + } + else + { + codepoint = 0x10000 + ((text[i] - 0xd800) << 10) + (text[i + 1] - 0xdc00); + } + + if (context->is_rtl) + { + c = unicode_get_mirrored_char(codepoint); + if (c != codepoint && font->has_glyph(context->cache->context, c)) + codepoint = c; + else + context->glyph_infos[i].mask |= rtlm_mask; + } + + /* TODO: should this check for glyph availability? */ + if (*context->u.subst.digits && codepoint >= '0' && codepoint <= '9') + codepoint = context->u.subst.digits[codepoint - '0']; + + context->u.subst.glyphs[g] = font->get_glyph(context->cache->context, codepoint); + context->u.subst.glyph_props[g].justification = SCRIPT_JUSTIFY_CHARACTER; + context->u.subst.glyph_props[g].isClusterStart = 1; + context->glyph_count++; + + clustermap[i] = i; + if (!bmp) + { + clustermap[i + 1] = i; + ++i; + } + } +} + HRESULT opentype_layout_apply_gsub_features(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, const struct shaping_features *features) { @@ -4679,6 +4743,7 @@ 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_get_nominal_glyphs(context, features); opentype_layout_set_glyph_masks(context, features);
for (i = 0; i < lookups.count; ++i) diff --git a/dlls/dwrite/shape.c b/dlls/dwrite/shape.c index 18afb2212bd..3d25898cf7a 100644 --- a/dlls/dwrite/shape.c +++ b/dlls/dwrite/shape.c @@ -362,8 +362,7 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i DWRITE_MAKE_OPENTYPE_TAG('l','i','g','a'), DWRITE_MAKE_OPENTYPE_TAG('r','c','l','t'), }; - struct scriptshaping_cache *cache = context->cache; - unsigned int script_index, language_index, script; + unsigned int script_index, language_index; struct shaping_features features = { 0 }; unsigned int i;
@@ -396,13 +395,8 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i shape_merge_features(context, &features);
/* 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); - } - } + 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);