[PATCH 7/7] dwrite: Implement chaining contextual substitution of format 2.

Nikolay Sivov nsivov at codeweavers.com
Fri May 29 11:01:09 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/opentype.c | 128 ++++++++++++++++++++++++++++-------------
 1 file changed, 87 insertions(+), 41 deletions(-)

diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 5114e900df6..f4e9d3305a4 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -3536,6 +3536,13 @@ static BOOL opentype_match_glyph_func(UINT16 glyph, UINT16 glyph_data, const str
     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)
 {
     const struct match_context *mc = data->mc;
@@ -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);
 }
 
+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,
         const struct lookup *lookup, unsigned int subtable_offset)
 {
     struct match_context mc = { .context = context, .mask = lookup->mask };
     const struct dwrite_fonttable *table = &context->table->table;
-    unsigned int i, coverage_index = GLYPH_NOT_COVERED, count, offset;
-    unsigned int backtrack_count, input_count, lookahead_count, lookup_count;
-    const UINT16 *backtrack, *lookahead, *input, *lookup_records;
+    unsigned int coverage_index = GLYPH_NOT_COVERED, count, offset;
     UINT16 glyph, format, coverage;
     BOOL ret = FALSE;
 
@@ -5162,8 +5212,6 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
 
     if (format == 1)
     {
-        const struct ot_gsub_ruleset *ruleset;
-
         coverage = table_read_be_word(table, subtable_offset +
                 FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
 
@@ -5180,51 +5228,48 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
                 rulesets[coverage_index]));
         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;
-        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;
-            }
-        }
+
+        ret = opentype_layout_apply_chain_rule_set(&mc, offset);
     }
     else if (format == 2)
     {
-        coverage = table_read_be_word(table, subtable_offset +
-                FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
+        unsigned int backtrack_classdef, input_classdef, lookahead_classdef, rule_set_idx;
+
+        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);
         if (coverage_index == GLYPH_NOT_COVERED)
             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)
     {
@@ -5262,6 +5307,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
         mc.input_offset = subtable_offset;
         mc.lookahead_offset = subtable_offset;
         mc.match_func = opentype_match_coverage_func;
+
         ret = opentype_layout_apply_gsub_chain_context_lookup(backtrack_count, backtrack, input_count, input + 1,
                 lookahead_count, lookahead, lookup_count, lookup_records, &mc);
     }
-- 
2.26.2




More information about the wine-devel mailing list