[PATCH 4/7] dwrite: Add matching callback support for iterators.

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


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

diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 05fc38bad3f..468368bcc03 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -3466,12 +3466,26 @@ struct ot_lookup
     unsigned int flags;
 };
 
+enum iterator_match
+{
+    /* First two to fit matching callback result. */
+    ITER_NO = 0,
+    ITER_YES = 1,
+    ITER_MAYBE,
+};
+
+typedef BOOL (*p_match_func)(UINT16 glyph, UINT16 glyph_data, const void *match_data);
+
 struct glyph_iterator
 {
     struct scriptshaping_context *context;
     unsigned int flags;
     unsigned int pos;
     unsigned int len;
+    unsigned int mask;
+    p_match_func match_func;
+    const UINT16 *glyph_data;
+    const void *match_data;
 };
 
 static void glyph_iterator_init(struct scriptshaping_context *context, unsigned int flags, unsigned int pos,
@@ -3481,6 +3495,10 @@ 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->match_func = NULL;
+    iter->match_data = NULL;
+    iter->glyph_data = NULL;
 }
 
 struct ot_gdef_mark_glyph_sets
@@ -3535,21 +3553,48 @@ static BOOL lookup_is_glyph_match(const struct scriptshaping_context *context, u
     return TRUE;
 }
 
-static BOOL glyph_iterator_match(const struct glyph_iterator *iter)
+static enum iterator_match glyph_iterator_may_skip(const struct glyph_iterator *iter)
+{
+    if (!lookup_is_glyph_match(iter->context, iter->pos, iter->flags))
+        return ITER_YES;
+
+    return ITER_NO;
+}
+
+static enum iterator_match glyph_iterator_may_match(const struct glyph_iterator *iter)
 {
-    return lookup_is_glyph_match(iter->context, iter->pos, iter->flags);
+    if (!(iter->mask & iter->context->glyph_infos[iter->pos].mask))
+        return ITER_NO;
+
+    if (iter->match_func)
+        return !!iter->match_func(iter->context->u.buffer.glyphs[iter->pos], *iter->glyph_data, iter->match_data);
+
+    return ITER_MAYBE;
 }
 
 static BOOL glyph_iterator_next(struct glyph_iterator *iter)
 {
+    enum iterator_match skip, match;
+
     while (iter->pos + iter->len < iter->context->glyph_count)
     {
         ++iter->pos;
-        if (glyph_iterator_match(iter))
+
+        skip = glyph_iterator_may_skip(iter);
+        if (skip == ITER_YES)
+            continue;
+
+        match = glyph_iterator_may_match(iter);
+        if (match == ITER_YES || (match == ITER_MAYBE && skip == ITER_NO))
         {
             --iter->len;
+            if (iter->glyph_data)
+                ++iter->glyph_data;
             return TRUE;
         }
+
+        if (skip == ITER_NO)
+            return FALSE;
     }
 
     return FALSE;
@@ -3557,17 +3602,27 @@ static BOOL glyph_iterator_next(struct glyph_iterator *iter)
 
 static BOOL glyph_iterator_prev(struct glyph_iterator *iter)
 {
-    if (!iter->pos)
-        return FALSE;
+    enum iterator_match skip, match;
 
     while (iter->pos > iter->len - 1)
     {
         --iter->pos;
-        if (glyph_iterator_match(iter))
+
+        skip = glyph_iterator_may_skip(iter);
+        if (skip == ITER_YES)
+            continue;
+
+        match = glyph_iterator_may_match(iter);
+        if (match == ITER_YES || (match == ITER_MAYBE && skip == ITER_NO))
         {
             --iter->len;
+            if (iter->glyph_data)
+                ++iter->glyph_data;
             return TRUE;
         }
+
+        if (skip == ITER_NO)
+            return FALSE;
     }
 
     return FALSE;
-- 
2.26.2




More information about the wine-devel mailing list