Commit d1ae4a56 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Implement chaining contextual substitution of format 2.

parent 7e798dae
...@@ -3536,6 +3536,13 @@ static BOOL opentype_match_glyph_func(UINT16 glyph, UINT16 glyph_data, const str ...@@ -3536,6 +3536,13 @@ static BOOL opentype_match_glyph_func(UINT16 glyph, UINT16 glyph_data, const str
return glyph == glyph_data; return glyph == glyph_data;
} }
static BOOL opentype_match_class_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
{
const struct match_context *mc = data->mc;
UINT16 glyph_class = opentype_layout_get_glyph_class(&mc->context->table->table, data->subtable_offset, glyph);
return glyph_class == glyph_data;
}
static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data) static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
{ {
const struct match_context *mc = data->mc; const struct match_context *mc = data->mc;
...@@ -5145,14 +5152,57 @@ static BOOL opentype_layout_apply_gsub_chain_context_lookup(unsigned int backtra ...@@ -5145,14 +5152,57 @@ static BOOL opentype_layout_apply_gsub_chain_context_lookup(unsigned int backtra
opentype_layout_context_gsub_apply_lookup(mc->context, input_count, match_positions, lookup_count, lookup_records, match_length); opentype_layout_context_gsub_apply_lookup(mc->context, input_count, match_positions, lookup_count, lookup_records, match_length);
} }
static BOOL opentype_layout_apply_chain_rule_set(const struct match_context *mc, unsigned int offset)
{
unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
const struct dwrite_fonttable *table = &mc->context->table->table;
const UINT16 *backtrack, *lookahead, *input, *lookup_records;
const struct ot_gsub_ruleset *ruleset;
unsigned int i, count;
count = table_read_be_word(table, offset);
ruleset = table_read_ensure(table, offset, count * sizeof(ruleset->offsets));
for (i = 0; i < count; ++i)
{
unsigned int rule_offset = offset + GET_BE_WORD(ruleset->offsets[i]);
backtrack_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
backtrack = table_read_ensure(table, rule_offset, backtrack_count * sizeof(*backtrack));
rule_offset += backtrack_count * sizeof(*backtrack);
input_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
input = table_read_ensure(table, rule_offset, input_count * sizeof(*input));
rule_offset += input_count * sizeof(*input);
lookahead_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
lookahead = table_read_ensure(table, rule_offset, lookahead_count * sizeof(*lookahead));
rule_offset += lookahead_count * sizeof(*lookahead);
lookup_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
lookup_records = table_read_ensure(table, rule_offset, lookup_count * 2 * sizeof(*lookup_records));
/* First applicable rule is used. */
if (opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input, lookahead_count,
lookahead, lookup_count, lookup_records, mc))
{
return TRUE;
}
}
return FALSE;
}
static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scriptshaping_context *context, static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scriptshaping_context *context,
const struct lookup *lookup, unsigned int subtable_offset) const struct lookup *lookup, unsigned int subtable_offset)
{ {
struct match_context mc = { .context = context, .mask = lookup->mask }; struct match_context mc = { .context = context, .mask = lookup->mask };
const struct dwrite_fonttable *table = &context->table->table; const struct dwrite_fonttable *table = &context->table->table;
unsigned int i, coverage_index = GLYPH_NOT_COVERED, count, offset; unsigned int coverage_index = GLYPH_NOT_COVERED, count, offset;
unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
const UINT16 *backtrack, *lookahead, *input, *lookup_records;
UINT16 glyph, format, coverage; UINT16 glyph, format, coverage;
BOOL ret = FALSE; BOOL ret = FALSE;
...@@ -5162,8 +5212,6 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts ...@@ -5162,8 +5212,6 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
if (format == 1) if (format == 1)
{ {
const struct ot_gsub_ruleset *ruleset;
coverage = table_read_be_word(table, subtable_offset + coverage = table_read_be_word(table, subtable_offset +
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage)); FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
...@@ -5180,51 +5228,48 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts ...@@ -5180,51 +5228,48 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
rulesets[coverage_index])); rulesets[coverage_index]));
offset += subtable_offset; offset += subtable_offset;
count = table_read_be_word(table, offset);
ruleset = table_read_ensure(table, offset, count * sizeof(ruleset->offsets));
mc.match_func = opentype_match_glyph_func; mc.match_func = opentype_match_glyph_func;
for (i = 0; i < count; ++i)
{ ret = opentype_layout_apply_chain_rule_set(&mc, offset);
unsigned int rule_offset = offset + GET_BE_WORD(ruleset->offsets[i]);
backtrack_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
backtrack = table_read_ensure(table, rule_offset, backtrack_count * sizeof(*backtrack));
rule_offset += backtrack_count * sizeof(*backtrack);
input_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
input = table_read_ensure(table, rule_offset, input_count * sizeof(*input));
rule_offset += input_count * sizeof(*input);
lookahead_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
lookahead = table_read_ensure(table, rule_offset, lookahead_count * sizeof(*lookahead));
rule_offset += lookahead_count * sizeof(*lookahead);
lookup_count = table_read_be_word(table, rule_offset);
rule_offset += 2;
lookup_records = table_read_ensure(table, rule_offset, lookup_count * 2 * sizeof(*lookup_records));
/* First applicable rule is used. */
if (opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input, lookahead_count,
lookahead, lookup_count, lookup_records, &mc))
{
return TRUE;
}
}
} }
else if (format == 2) else if (format == 2)
{ {
coverage = table_read_be_word(table, subtable_offset + unsigned int backtrack_classdef, input_classdef, lookahead_classdef, rule_set_idx;
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
offset = subtable_offset + 2 /* format */;
coverage = table_read_be_word(table, offset);
offset += 2;
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph); coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
if (coverage_index == GLYPH_NOT_COVERED) if (coverage_index == GLYPH_NOT_COVERED)
return FALSE; return FALSE;
WARN("Chaining contextual substitution (2) is not supported.\n"); backtrack_classdef = table_read_be_word(table, offset) + subtable_offset;
offset += 2;
input_classdef = table_read_be_word(table, offset) + subtable_offset;
offset += 2;
lookahead_classdef = table_read_be_word(table, offset) + subtable_offset;
offset += 2;
count = table_read_be_word(table, offset);
offset+= 2;
rule_set_idx = opentype_layout_get_glyph_class(table, input_classdef, glyph);
if (rule_set_idx >= count)
return FALSE;
offset = table_read_be_word(table, offset + rule_set_idx * 2);
offset += subtable_offset;
mc.backtrack_offset = backtrack_classdef;
mc.input_offset = input_classdef;
mc.lookahead_offset = lookahead_classdef;
mc.match_func = opentype_match_class_func;
ret = opentype_layout_apply_chain_rule_set(&mc, offset);
} }
else if (format == 3) else if (format == 3)
{ {
...@@ -5262,6 +5307,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts ...@@ -5262,6 +5307,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
mc.input_offset = subtable_offset; mc.input_offset = subtable_offset;
mc.lookahead_offset = subtable_offset; mc.lookahead_offset = subtable_offset;
mc.match_func = opentype_match_coverage_func; mc.match_func = opentype_match_coverage_func;
ret = opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input + 1, ret = opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input + 1,
lookahead_count, lookahead, lookup_count, lookup_records, &mc); lookahead_count, lookahead, lookup_count, lookup_records, &mc);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment