[PATCH 2/5] dwrite: Keep track of shaping stage feature applies to.

Nikolay Sivov nsivov at codeweavers.com
Fri May 22 05:58:06 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at 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;
-- 
2.26.2




More information about the wine-devel mailing list