Nikolay Sivov : dwrite: Use iterator matching for chain substitution.

Alexandre Julliard julliard at winehq.org
Fri May 29 15:22:55 CDT 2020


Module: wine
Branch: master
Commit: a1d1647131b4038485ed20e484df6c8aba1b200a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a1d1647131b4038485ed20e484df6c8aba1b200a

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri May 29 19:01:07 2020 +0300

dwrite: Use iterator matching for chain substitution.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dwrite/opentype.c | 105 +++++++++++++++++++++++++++++++------------------
 1 file changed, 67 insertions(+), 38 deletions(-)

diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 468368bcc0..198da43f2c 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -3474,7 +3474,24 @@ enum iterator_match
     ITER_MAYBE,
 };
 
-typedef BOOL (*p_match_func)(UINT16 glyph, UINT16 glyph_data, const void *match_data);
+struct match_context;
+struct match_data
+{
+    const struct match_context *mc;
+    unsigned int subtable_offset;
+};
+
+typedef BOOL (*p_match_func)(UINT16 glyph, UINT16 glyph_data, const struct match_data *match_data);
+
+struct match_context
+{
+    struct scriptshaping_context *context;
+    unsigned int backtrack_offset;
+    unsigned int input_offset;
+    unsigned int lookahead_offset;
+    p_match_func match_func;
+    unsigned int mask;
+};
 
 struct glyph_iterator
 {
@@ -3485,7 +3502,7 @@ struct glyph_iterator
     unsigned int mask;
     p_match_func match_func;
     const UINT16 *glyph_data;
-    const void *match_data;
+    const struct match_data *match_data;
 };
 
 static void glyph_iterator_init(struct scriptshaping_context *context, unsigned int flags, unsigned int pos,
@@ -3495,7 +3512,7 @@ static void glyph_iterator_init(struct scriptshaping_context *context, unsigned
     iter->flags = flags;
     iter->pos = pos;
     iter->len = len;
-    iter->mask = ~0u; /* TODO: input sequences should be using actual mask */
+    iter->mask = ~0u;
     iter->match_func = NULL;
     iter->match_data = NULL;
     iter->glyph_data = NULL;
@@ -3508,6 +3525,13 @@ struct ot_gdef_mark_glyph_sets
     DWORD offsets[1];
 };
 
+static BOOL opentype_match_coverage_func(UINT16 glyph, UINT16 glyph_data, const struct match_data *data)
+{
+    const struct match_context *mc = data->mc;
+    return opentype_layout_is_glyph_covered(&mc->context->table->table, data->subtable_offset + GET_BE_WORD(glyph_data), glyph)
+            != GLYPH_NOT_COVERED;
+}
+
 static BOOL opentype_layout_mark_set_covers(const struct scriptshaping_cache *cache, unsigned int set_index,
         UINT16 glyph)
 {
@@ -4947,32 +4971,32 @@ static BOOL opentype_layout_apply_gsub_lig_substitution(struct scriptshaping_con
     return FALSE;
 }
 
-#define CHAIN_CONTEXT_MAX_LENGTH 64
+#define GLYPH_CONTEXT_MAX_LENGTH 64
 
-static BOOL opentype_layout_context_match_input(struct scriptshaping_context *context, unsigned int subtable_offset,
-        unsigned int count, const UINT16 *input, unsigned int *end_offset, unsigned int *match_positions)
+static BOOL opentype_layout_context_match_input(const struct match_context *mc, unsigned int count, const UINT16 *input,
+        unsigned int *end_offset, unsigned int *match_positions)
 {
+    struct match_data match_data = { .mc = mc, .subtable_offset = mc->input_offset };
+    struct scriptshaping_context *context = mc->context;
     struct glyph_iterator iter;
     unsigned int i;
-    UINT16 glyph;
 
-    if (count > CHAIN_CONTEXT_MAX_LENGTH)
+    if (count > GLYPH_CONTEXT_MAX_LENGTH)
         return FALSE;
 
     match_positions[0] = context->cur;
 
     glyph_iterator_init(context, 0, context->cur, count - 1, &iter);
+    iter.mask = mc->mask;
+    iter.match_func = mc->match_func;
+    iter.match_data = &match_data;
+    iter.glyph_data = input;
 
     for (i = 1; i < count; ++i)
     {
         if (!glyph_iterator_next(&iter))
             return FALSE;
 
-        /* TODO: this only covers Format3 substitution */
-        glyph = context->u.subst.glyphs[iter.pos];
-        if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(input[i]), glyph) == GLYPH_NOT_COVERED)
-            return FALSE;
-
         match_positions[i] = iter.pos;
     }
 
@@ -4981,23 +5005,23 @@ static BOOL opentype_layout_context_match_input(struct scriptshaping_context *co
     return TRUE;
 }
 
-static BOOL opentype_layout_context_match_backtrack(struct scriptshaping_context *context, unsigned int subtable_offset,
-        unsigned int count, const UINT16 *backtrack, unsigned int *match_start)
+static BOOL opentype_layout_context_match_backtrack(const struct match_context *mc, unsigned int count,
+        const UINT16 *backtrack, unsigned int *match_start)
 {
+    struct match_data match_data = { .mc = mc, .subtable_offset = mc->backtrack_offset };
+    struct scriptshaping_context *context = mc->context;
     struct glyph_iterator iter;
     unsigned int i;
-    UINT16 glyph;
 
     glyph_iterator_init(context, 0, context->cur, count, &iter);
+    iter.match_func = mc->match_func;
+    iter.match_data = &match_data;
+    iter.glyph_data = backtrack;
 
     for (i = 0; i < count; ++i)
     {
         if (!glyph_iterator_prev(&iter))
             return FALSE;
-
-        glyph = context->u.subst.glyphs[iter.pos];
-        if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(backtrack[i]), glyph) == GLYPH_NOT_COVERED)
-            return FALSE;
     }
 
     *match_start = iter.pos;
@@ -5005,23 +5029,23 @@ static BOOL opentype_layout_context_match_backtrack(struct scriptshaping_context
     return TRUE;
 }
 
-static BOOL opentype_layout_context_match_lookahead(struct scriptshaping_context *context, unsigned int subtable_offset,
-        unsigned int count, const UINT16 *lookahead, unsigned int offset, unsigned int *end_index)
+static BOOL opentype_layout_context_match_lookahead(const struct match_context *mc, unsigned int count,
+        const UINT16 *lookahead, unsigned int offset, unsigned int *end_index)
 {
+    struct match_data match_data = { .mc = mc, .subtable_offset = mc->lookahead_offset };
+    struct scriptshaping_context *context = mc->context;
     struct glyph_iterator iter;
     unsigned int i;
-    UINT16 glyph;
 
     glyph_iterator_init(context, 0, context->cur + offset - 1, count, &iter);
+    iter.match_func = mc->match_func;
+    iter.match_data = &match_data;
+    iter.glyph_data = lookahead;
 
     for (i = 0; i < count; ++i)
     {
         if (!glyph_iterator_next(&iter))
             return FALSE;
-
-        glyph = context->u.subst.glyphs[iter.pos];
-        if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(lookahead[i]), glyph) == GLYPH_NOT_COVERED)
-            return FALSE;
     }
 
     *end_index = iter.pos;
@@ -5071,7 +5095,7 @@ static BOOL opentype_layout_context_gsub_apply_lookup(struct scriptshaping_conte
 
         if (delta > 0)
         {
-            if (delta + count > CHAIN_CONTEXT_MAX_LENGTH)
+            if (delta + count > GLYPH_CONTEXT_MAX_LENGTH)
                 break;
         }
         else
@@ -5097,22 +5121,23 @@ static BOOL opentype_layout_context_gsub_apply_lookup(struct scriptshaping_conte
     return TRUE;
 }
 
-static BOOL opentype_layout_apply_gsub_chain_context_lookup(struct scriptshaping_context *context, unsigned int subtable_offset,
-        unsigned int backtrack_count, const UINT16 *backtrack, unsigned int input_count, const UINT16 *input,
-        unsigned int lookahead_count, const UINT16 *lookahead, unsigned int lookup_count, const UINT16 *lookup_records)
+static BOOL opentype_layout_apply_gsub_chain_context_lookup(unsigned int backtrack_count, const UINT16 *backtrack,
+        unsigned int input_count, const UINT16 *input, unsigned int lookahead_count, const UINT16 *lookahead,
+        unsigned int lookup_count, const UINT16 *lookup_records, const struct match_context *mc)
 {
     unsigned int start_index = 0, match_length = 0, end_index = 0;
-    unsigned int match_positions[CHAIN_CONTEXT_MAX_LENGTH];
+    unsigned int match_positions[GLYPH_CONTEXT_MAX_LENGTH];
 
-    return opentype_layout_context_match_input(context, subtable_offset, input_count, input, &match_length, match_positions) &&
-            opentype_layout_context_match_backtrack(context, subtable_offset, backtrack_count, backtrack, &start_index) &&
-            opentype_layout_context_match_lookahead(context, subtable_offset, lookahead_count, lookahead, input_count, &end_index) &&
-            opentype_layout_context_gsub_apply_lookup(context, input_count, match_positions, lookup_count, lookup_records, match_length);
+    return opentype_layout_context_match_input(mc, input_count, input, &match_length, match_positions) &&
+            opentype_layout_context_match_backtrack(mc, backtrack_count, backtrack, &start_index) &&
+            opentype_layout_context_match_lookahead(mc, lookahead_count, lookahead, input_count, &end_index) &&
+            opentype_layout_context_gsub_apply_lookup(mc->context, input_count, match_positions, lookup_count, lookup_records, match_length);
 }
 
 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 coverage_index = GLYPH_NOT_COVERED;
     UINT16 glyph, format, coverage;
@@ -5176,8 +5201,12 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
         if (coverage_index == GLYPH_NOT_COVERED)
             return FALSE;
 
-        ret = opentype_layout_apply_gsub_chain_context_lookup(context, subtable_offset, backtrack_count, backtrack,
-                input_count, input + 1, lookahead_count, lookahead, lookup_count, lookup_records);
+        mc.backtrack_offset = subtable_offset;
+        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);
     }
     else
         WARN("Unknown chaining contextual substitution format %u.\n", format);




More information about the wine-cvs mailing list