[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