[PATCH 2/5] dwrite: Use GPOS handlers for subtables, not whole lookups.
Nikolay Sivov
nsivov at codeweavers.com
Thu May 28 06:54:26 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/dwrite/opentype.c | 885 +++++++++++++++++++----------------------
1 file changed, 410 insertions(+), 475 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 18bffc3fa2e..88861863034 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -3402,23 +3402,7 @@ static void opentype_layout_apply_gpos_value(struct scriptshaping_context *conte
}
}
-static unsigned int opentype_layout_get_gpos_subtable(const struct scriptshaping_cache *cache,
- unsigned int lookup_offset, unsigned int subtable)
-{
- WORD lookup_type = table_read_be_word(&cache->gpos.table, lookup_offset);
- unsigned int subtable_offset = table_read_be_word(&cache->gpos.table, lookup_offset +
- FIELD_OFFSET(struct ot_lookup_table, subtable[subtable]));
- if (lookup_type == GPOS_LOOKUP_EXTENSION_POSITION)
- {
- const struct ot_gsubgpos_extension_format1 *format1 = table_read_ensure(&cache->gpos.table,
- lookup_offset + subtable_offset, sizeof(*format1));
- subtable_offset += GET_BE_DWORD(format1->extension_offset);
- }
-
- return lookup_offset + subtable_offset;
-}
-
-static unsigned int opentype_layout_get_gsub_subtable(const struct scriptshaping_context *context,
+static unsigned int opentype_layout_get_gsubgpos_subtable(const struct scriptshaping_context *context,
unsigned int lookup_offset, unsigned int subtable)
{
unsigned int subtable_offset = table_read_be_word(&context->table->table, lookup_offset +
@@ -3499,60 +3483,69 @@ static BOOL glyph_iterator_prev(struct glyph_iterator *iter)
return FALSE;
}
+struct lookup
+{
+ unsigned short index;
+ unsigned short type;
+ unsigned short flags;
+ unsigned short subtable_count;
+
+ unsigned int mask;
+ unsigned int offset;
+};
+
static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
struct scriptshaping_cache *cache = context->cache;
- WORD format, value_format, value_len, coverage;
- unsigned int i;
+ UINT16 format, value_format, value_len, coverage, glyph;
- for (i = 0; i < lookup->subtable_count; ++i)
- {
- unsigned int subtable_offset = opentype_layout_get_gpos_subtable(cache, lookup->offset, i);
- unsigned int coverage_index;
+ unsigned int coverage_index;
- format = table_read_be_word(&cache->gpos.table, subtable_offset);
+ format = table_read_be_word(&cache->gpos.table, subtable_offset);
- coverage = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_singlepos_format1, coverage));
- value_format = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_singlepos_format1, value_format));
- value_len = dwrite_popcount(value_format);
+ coverage = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_singlepos_format1, coverage));
+ value_format = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_singlepos_format1, value_format));
+ value_len = dwrite_popcount(value_format);
- if (format == 1)
- {
- const struct ot_gpos_singlepos_format1 *format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
- FIELD_OFFSET(struct ot_gpos_singlepos_format1, value[value_len]));
+ glyph = context->u.pos.glyphs[context->cur];
- coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage,
- context->u.pos.glyphs[iter->pos]);
- if (coverage_index == GLYPH_NOT_COVERED)
- continue;
+ if (format == 1)
+ {
+ const struct ot_gpos_singlepos_format1 *format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
+ FIELD_OFFSET(struct ot_gpos_singlepos_format1, value[value_len]));
- opentype_layout_apply_gpos_value(context, subtable_offset, value_format, format1->value, iter->pos);
- break;
- }
- else if (format == 2)
- {
- WORD value_count = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_singlepos_format2, value_count));
- const struct ot_gpos_singlepos_format2 *format2 = table_read_ensure(&cache->gpos.table, subtable_offset,
- FIELD_OFFSET(struct ot_gpos_singlepos_format2, values) + value_count * value_len * sizeof(WORD));
-
- coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage,
- context->u.pos.glyphs[iter->pos]);
- if (coverage_index == GLYPH_NOT_COVERED || coverage_index >= value_count)
- continue;
+ coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
+ if (coverage_index == GLYPH_NOT_COVERED)
+ return FALSE;
- opentype_layout_apply_gpos_value(context, subtable_offset, value_format,
- &format2->values[coverage_index * value_len], iter->pos);
- break;
- }
- else
- WARN("Unknown single adjustment format %u.\n", format);
+ opentype_layout_apply_gpos_value(context, subtable_offset, value_format, format1->value, context->cur);
}
+ else if (format == 2)
+ {
+ WORD value_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_singlepos_format2, value_count));
+ const struct ot_gpos_singlepos_format2 *format2 = table_read_ensure(&cache->gpos.table, subtable_offset,
+ FIELD_OFFSET(struct ot_gpos_singlepos_format2, values) + value_count * value_len * sizeof(WORD));
- return FALSE;
+ coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
+ if (coverage_index == GLYPH_NOT_COVERED || coverage_index >= value_count)
+ return FALSE;
+
+ opentype_layout_apply_gpos_value(context, subtable_offset, value_format, &format2->values[coverage_index * value_len],
+ context->cur);
+ }
+ else
+ {
+ WARN("Unknown single adjustment format %u.\n", format);
+ return FALSE;
+ }
+
+ context->cur++;
+
+ return TRUE;
}
static int gpos_pair_adjustment_compare_format1(const void *g, const void *r)
@@ -3563,153 +3556,144 @@ static int gpos_pair_adjustment_compare_format1(const void *g, const void *r)
}
static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
struct scriptshaping_cache *cache = context->cache;
- unsigned int i, first_glyph, second_glyph;
+ unsigned int first_glyph, second_glyph;
struct glyph_iterator iter_pair;
WORD format, coverage;
- glyph_iterator_init(context, iter->flags, iter->pos, 1, &iter_pair);
+ WORD value_format1, value_format2, value_len1, value_len2;
+ unsigned int coverage_index;
+
+ glyph_iterator_init(context, lookup->flags, context->cur, 1, &iter_pair);
if (!glyph_iterator_next(&iter_pair))
return FALSE;
if (context->is_rtl)
{
first_glyph = iter_pair.pos;
- second_glyph = iter->pos;
+ second_glyph = context->cur;
}
else
{
- first_glyph = iter->pos;
+ first_glyph = context->cur;
second_glyph = iter_pair.pos;
}
- for (i = 0; i < lookup->subtable_count; ++i)
- {
- unsigned int subtable_offset = opentype_layout_get_gpos_subtable(cache, lookup->offset, i);
- WORD value_format1, value_format2, value_len1, value_len2;
- unsigned int coverage_index;
-
- format = table_read_be_word(&cache->gpos.table, subtable_offset);
-
- coverage = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_pairpos_format1, coverage));
- if (!coverage)
- continue;
+ format = table_read_be_word(&cache->gpos.table, subtable_offset);
- coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage,
- context->u.pos.glyphs[first_glyph]);
- if (coverage_index == GLYPH_NOT_COVERED)
- continue;
+ coverage = table_read_be_word(&cache->gpos.table, subtable_offset + FIELD_OFFSET(struct ot_gpos_pairpos_format1, coverage));
+ if (!coverage)
+ return FALSE;
- if (format == 1)
- {
- const struct ot_gpos_pairpos_format1 *format1;
- WORD pairset_count = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairset_count));
- unsigned int pairvalue_len, pairset_offset;
- const struct ot_gpos_pairset *pairset;
- const WORD *pairvalue;
- WORD pairvalue_count;
-
- if (!pairset_count || coverage_index >= pairset_count)
- continue;
+ coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, context->u.pos.glyphs[first_glyph]);
+ if (coverage_index == GLYPH_NOT_COVERED)
+ return FALSE;
- format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
- FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairsets[pairset_count]));
- if (!format1)
- continue;
+ if (format == 1)
+ {
+ const struct ot_gpos_pairpos_format1 *format1;
+ WORD pairset_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairset_count));
+ unsigned int pairvalue_len, pairset_offset;
+ const struct ot_gpos_pairset *pairset;
+ const WORD *pairvalue;
+ WORD pairvalue_count;
+
+ if (!pairset_count || coverage_index >= pairset_count)
+ return FALSE;
- /* Ordered paired values. */
- pairvalue_count = table_read_be_word(&cache->gpos.table, subtable_offset +
- GET_BE_WORD(format1->pairsets[coverage_index]));
- if (!pairvalue_count)
- continue;
+ format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
+ FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairsets[pairset_count]));
+ if (!format1)
+ return FALSE;
- /* Structure length is variable, but does not change across the subtable. */
- value_format1 = GET_BE_WORD(format1->value_format1) & 0xff;
- value_format2 = GET_BE_WORD(format1->value_format2) & 0xff;
+ /* Ordered paired values. */
+ pairvalue_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ GET_BE_WORD(format1->pairsets[coverage_index]));
+ if (!pairvalue_count)
+ return FALSE;
- value_len1 = dwrite_popcount(value_format1);
- value_len2 = dwrite_popcount(value_format2);
- pairvalue_len = FIELD_OFFSET(struct ot_gpos_pairvalue, data) + value_len1 * sizeof(WORD) +
- value_len2 * sizeof(WORD);
+ /* Structure length is variable, but does not change across the subtable. */
+ value_format1 = GET_BE_WORD(format1->value_format1) & 0xff;
+ value_format2 = GET_BE_WORD(format1->value_format2) & 0xff;
- pairset_offset = subtable_offset + GET_BE_WORD(format1->pairsets[coverage_index]);
- pairset = table_read_ensure(&cache->gpos.table, subtable_offset + pairset_offset,
- pairvalue_len * pairvalue_count);
- if (!pairset)
- continue;
+ value_len1 = dwrite_popcount(value_format1);
+ value_len2 = dwrite_popcount(value_format2);
+ pairvalue_len = FIELD_OFFSET(struct ot_gpos_pairvalue, data) + value_len1 * sizeof(WORD) +
+ value_len2 * sizeof(WORD);
- pairvalue = bsearch(&context->u.pos.glyphs[second_glyph], pairset->pairvalues, pairvalue_count,
- pairvalue_len, gpos_pair_adjustment_compare_format1);
- if (!pairvalue)
- continue;
+ pairset_offset = subtable_offset + GET_BE_WORD(format1->pairsets[coverage_index]);
+ pairset = table_read_ensure(&cache->gpos.table, subtable_offset + pairset_offset,
+ pairvalue_len * pairvalue_count);
+ if (!pairset)
+ return FALSE;
- pairvalue += 1; /* Skip SecondGlyph. */
- opentype_layout_apply_gpos_value(context, pairset_offset, value_format1, pairvalue, first_glyph);
- opentype_layout_apply_gpos_value(context, pairset_offset, value_format2, pairvalue + value_len1,
- second_glyph);
+ pairvalue = bsearch(&context->u.pos.glyphs[second_glyph], pairset->pairvalues, pairvalue_count,
+ pairvalue_len, gpos_pair_adjustment_compare_format1);
+ if (!pairvalue)
+ return FALSE;
- iter->pos = iter_pair.pos;
- if (value_len2)
- iter->pos++;
+ pairvalue += 1; /* Skip SecondGlyph. */
+ opentype_layout_apply_gpos_value(context, pairset_offset, value_format1, pairvalue, first_glyph);
+ opentype_layout_apply_gpos_value(context, pairset_offset, value_format2, pairvalue + value_len1,
+ second_glyph);
- return TRUE;
- }
- else if (format == 2)
- {
- const struct ot_gpos_pairpos_format2 *format2;
- WORD class1_count, class2_count;
- unsigned int class1, class2;
-
- value_format1 = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format1)) & 0xff;
- value_format2 = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format2)) & 0xff;
-
- class1_count = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_pairpos_format2, class1_count));
- class2_count = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_pairpos_format2, class2_count));
-
- value_len1 = dwrite_popcount(value_format1);
- value_len2 = dwrite_popcount(value_format2);
-
- format2 = table_read_ensure(&cache->gpos.table, subtable_offset,
- FIELD_OFFSET(struct ot_gpos_pairpos_format2,
- values[class1_count * class2_count * (value_len1 + value_len2)]));
- if (!format2)
- continue;
+ context->cur = iter_pair.pos;
+ if (value_len2)
+ context->cur++;
+ }
+ else if (format == 2)
+ {
+ const struct ot_gpos_pairpos_format2 *format2;
+ WORD class1_count, class2_count;
+ unsigned int class1, class2;
+ const WCHAR *values;
+
+ value_format1 = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format1)) & 0xff;
+ value_format2 = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format2)) & 0xff;
+
+ class1_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, class1_count));
+ class2_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2, class2_count));
+
+ value_len1 = dwrite_popcount(value_format1);
+ value_len2 = dwrite_popcount(value_format2);
+
+ format2 = table_read_ensure(&cache->gpos.table, subtable_offset,
+ FIELD_OFFSET(struct ot_gpos_pairpos_format2,
+ values[class1_count * class2_count * (value_len1 + value_len2)]));
+ if (!format2)
+ return FALSE;
- class1 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def1),
- context->u.pos.glyphs[first_glyph]);
- class2 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def2),
- context->u.pos.glyphs[second_glyph]);
+ class1 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def1),
+ context->u.pos.glyphs[first_glyph]);
+ class2 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def2),
+ context->u.pos.glyphs[second_glyph]);
- if (class1 < class1_count && class2 < class2_count)
- {
- const WCHAR *values = &format2->values[(class1 * class2_count + class2) * (value_len1 + value_len2)];
- opentype_layout_apply_gpos_value(context, subtable_offset, value_format1, values, first_glyph);
- opentype_layout_apply_gpos_value(context, subtable_offset, value_format2, values + value_len1,
- second_glyph);
+ if (!(class1 < class1_count && class2 < class2_count))
+ return FALSE;
- iter->pos = iter_pair.pos;
- if (value_len2)
- iter->pos++;
+ values = &format2->values[(class1 * class2_count + class2) * (value_len1 + value_len2)];
+ opentype_layout_apply_gpos_value(context, subtable_offset, value_format1, values, first_glyph);
+ opentype_layout_apply_gpos_value(context, subtable_offset, value_format2, values + value_len1,
+ second_glyph);
- return TRUE;
- }
- }
- else
- {
- WARN("Unknown pair adjustment format %u.\n", format);
- continue;
- }
+ context->cur = iter_pair.pos;
+ if (value_len2)
+ context->cur++;
+ }
+ else
+ {
+ WARN("Unknown pair adjustment format %u.\n", format);
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
static void opentype_layout_gpos_get_anchor(const struct scriptshaping_context *context, unsigned int anchor_offset,
@@ -3770,421 +3754,373 @@ static void opentype_layout_gpos_get_anchor(const struct scriptshaping_context *
}
static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
struct scriptshaping_cache *cache = context->cache;
- unsigned int i;
+ WORD format = table_read_be_word(&cache->gpos.table, subtable_offset);
+ UINT16 glyph = context->u.pos.glyphs[context->cur];
- for (i = 0; i < lookup->subtable_count; ++i)
+ if (format == 1)
{
- unsigned int subtable_offset = opentype_layout_get_gpos_subtable(cache, lookup->offset, i);
- WORD format;
-
- format = table_read_be_word(&cache->gpos.table, subtable_offset);
-
- if (format == 1)
- {
- WORD coverage_offset = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_cursive_format1, coverage));
- unsigned int glyph_index, entry_count, entry_anchor, exit_anchor;
- float entry_x, entry_y, exit_x, exit_y, delta;
- struct glyph_iterator prev_iter;
-
- if (!coverage_offset)
- continue;
+ WORD coverage_offset = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_cursive_format1, coverage));
+ unsigned int glyph_index, entry_count, entry_anchor, exit_anchor;
+ float entry_x, entry_y, exit_x, exit_y, delta;
+ struct glyph_iterator prev_iter;
- entry_count = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_cursive_format1, count));
-
- glyph_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage_offset,
- context->u.pos.glyphs[iter->pos]);
- if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
- continue;
+ if (!coverage_offset)
+ return FALSE;
- entry_anchor = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2]));
- if (!entry_anchor)
- continue;
+ entry_count = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_cursive_format1, count));
- glyph_iterator_init(context, iter->flags, iter->pos, 1, &prev_iter);
- if (!glyph_iterator_prev(&prev_iter))
- continue;
+ glyph_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage_offset, glyph);
+ if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
+ return FALSE;
- glyph_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage_offset,
- context->u.pos.glyphs[prev_iter.pos]);
- if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
- continue;
+ entry_anchor = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2]));
+ if (!entry_anchor)
+ return FALSE;
- exit_anchor = table_read_be_word(&cache->gpos.table, subtable_offset +
- FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2 + 1]));
- if (!exit_anchor)
- continue;
+ glyph_iterator_init(context, lookup->flags, context->cur, 1, &prev_iter);
+ if (!glyph_iterator_prev(&prev_iter))
+ return FALSE;
- opentype_layout_gpos_get_anchor(context, subtable_offset + exit_anchor, prev_iter.pos, &exit_x, &exit_y);
- opentype_layout_gpos_get_anchor(context, subtable_offset + entry_anchor, iter->pos, &entry_x, &entry_y);
+ glyph_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage_offset,
+ context->u.pos.glyphs[prev_iter.pos]);
+ if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
+ return FALSE;
- if (context->is_rtl)
- {
- delta = exit_x + context->offsets[prev_iter.pos].advanceOffset;
- context->advances[prev_iter.pos] -= delta;
- context->advances[iter->pos] = entry_x + context->offsets[iter->pos].advanceOffset;
- context->offsets[prev_iter.pos].advanceOffset -= delta;
- }
- else
- {
- delta = entry_x + context->offsets[iter->pos].advanceOffset;
- context->advances[prev_iter.pos] = exit_x + context->offsets[prev_iter.pos].advanceOffset;
- context->advances[iter->pos] -= delta;
- context->offsets[iter->pos].advanceOffset -= delta;
- }
+ exit_anchor = table_read_be_word(&cache->gpos.table, subtable_offset +
+ FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2 + 1]));
+ if (!exit_anchor)
+ return FALSE;
- if (lookup->flags & LOOKUP_FLAG_RTL)
- context->offsets[prev_iter.pos].ascenderOffset = entry_y - exit_y;
- else
- context->offsets[iter->pos].ascenderOffset = exit_y - entry_y;
+ opentype_layout_gpos_get_anchor(context, subtable_offset + exit_anchor, prev_iter.pos, &exit_x, &exit_y);
+ opentype_layout_gpos_get_anchor(context, subtable_offset + entry_anchor, context->cur, &entry_x, &entry_y);
- break;
+ if (context->is_rtl)
+ {
+ delta = exit_x + context->offsets[prev_iter.pos].advanceOffset;
+ context->advances[prev_iter.pos] -= delta;
+ context->advances[context->cur] = entry_x + context->offsets[context->cur].advanceOffset;
+ context->offsets[prev_iter.pos].advanceOffset -= delta;
+ }
+ else
+ {
+ delta = entry_x + context->offsets[context->cur].advanceOffset;
+ context->advances[prev_iter.pos] = exit_x + context->offsets[prev_iter.pos].advanceOffset;
+ context->advances[context->cur] -= delta;
+ context->offsets[context->cur].advanceOffset -= delta;
}
+
+ if (lookup->flags & LOOKUP_FLAG_RTL)
+ context->offsets[prev_iter.pos].ascenderOffset = entry_y - exit_y;
else
- WARN("Unknown cursive attachment format %u.\n", format);
+ context->offsets[context->cur].ascenderOffset = exit_y - entry_y;
+ context->cur++;
+ }
+ else
+ {
+ WARN("Unknown cursive attachment format %u.\n", format);
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
struct scriptshaping_cache *cache = context->cache;
- unsigned int i;
WORD format;
- for (i = 0; i < lookup->subtable_count; ++i)
- {
- unsigned int subtable_offset = opentype_layout_get_gpos_subtable(cache, lookup->offset, i);
-
- format = table_read_be_word(&cache->gpos.table, subtable_offset);
+ format = table_read_be_word(&cache->gpos.table, subtable_offset);
- if (format == 1)
- {
- const struct ot_gpos_mark_to_base_format1 *format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
- sizeof(*format1));
- unsigned int mark_class_count, count, mark_array_offset, base_array_offset;
- const struct ot_gpos_mark_array *mark_array;
- const struct ot_gpos_base_array *base_array;
- float mark_x, mark_y, base_x, base_y;
- unsigned int base_index, mark_index;
- struct glyph_iterator base_iter;
- unsigned int base_anchor;
-
- if (!format1)
- continue;
+ if (format == 1)
+ {
+ const struct ot_gpos_mark_to_base_format1 *format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
+ sizeof(*format1));
+ unsigned int mark_class_count, count, mark_array_offset, base_array_offset;
+ const struct ot_gpos_mark_array *mark_array;
+ const struct ot_gpos_base_array *base_array;
+ float mark_x, mark_y, base_x, base_y;
+ unsigned int base_index, mark_index;
+ struct glyph_iterator base_iter;
+ unsigned int base_anchor;
+
+ if (!format1)
+ return FALSE;
- mark_array_offset = subtable_offset + GET_BE_WORD(format1->mark_array);
- if (!(count = table_read_be_word(&cache->gpos.table, mark_array_offset)))
- continue;
+ mark_array_offset = subtable_offset + GET_BE_WORD(format1->mark_array);
+ if (!(count = table_read_be_word(&cache->gpos.table, mark_array_offset)))
+ return FALSE;
- mark_array = table_read_ensure(&cache->gpos.table, mark_array_offset,
- FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
- if (!mark_array)
- continue;
+ mark_array = table_read_ensure(&cache->gpos.table, mark_array_offset,
+ FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
+ if (!mark_array)
+ return FALSE;
- base_array_offset = subtable_offset + GET_BE_WORD(format1->base_array);
- if (!(count = table_read_be_word(&cache->gpos.table, base_array_offset)))
- continue;
+ base_array_offset = subtable_offset + GET_BE_WORD(format1->base_array);
+ if (!(count = table_read_be_word(&cache->gpos.table, base_array_offset)))
+ return FALSE;
- base_array = table_read_ensure(&cache->gpos.table, base_array_offset,
- FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * GET_BE_WORD(format1->mark_class_count)]));
- if (!base_array)
- continue;
+ base_array = table_read_ensure(&cache->gpos.table, base_array_offset,
+ FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * GET_BE_WORD(format1->mark_class_count)]));
+ if (!base_array)
+ return FALSE;
- mark_class_count = GET_BE_WORD(format1->mark_class_count);
+ mark_class_count = GET_BE_WORD(format1->mark_class_count);
- mark_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark_coverage),
- context->u.pos.glyphs[iter->pos]);
+ mark_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark_coverage),
+ context->u.pos.glyphs[context->cur]);
- if (mark_index == GLYPH_NOT_COVERED || mark_index >= GET_BE_WORD(mark_array->count))
- continue;
+ if (mark_index == GLYPH_NOT_COVERED || mark_index >= GET_BE_WORD(mark_array->count))
+ return FALSE;
- /* Look back for first base glyph. */
- glyph_iterator_init(context, LOOKUP_FLAG_IGNORE_MARKS, iter->pos, 1, &base_iter);
- if (!glyph_iterator_prev(&base_iter))
- continue;
+ /* Look back for first base glyph. */
+ glyph_iterator_init(context, LOOKUP_FLAG_IGNORE_MARKS, context->cur, 1, &base_iter);
+ if (!glyph_iterator_prev(&base_iter))
+ return FALSE;
- base_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->base_coverage),
- context->u.pos.glyphs[base_iter.pos]);
- if (base_index == GLYPH_NOT_COVERED || base_index >= GET_BE_WORD(base_array->count))
- continue;
+ base_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->base_coverage),
+ context->u.pos.glyphs[base_iter.pos]);
+ if (base_index == GLYPH_NOT_COVERED || base_index >= GET_BE_WORD(base_array->count))
+ return FALSE;
- base_anchor = GET_BE_WORD(base_array->offsets[base_index * mark_class_count +
- GET_BE_WORD(mark_array->records[mark_index].mark_class)]);
+ base_anchor = GET_BE_WORD(base_array->offsets[base_index * mark_class_count +
+ GET_BE_WORD(mark_array->records[mark_index].mark_class)]);
- opentype_layout_gpos_get_anchor(context, mark_array_offset +
- GET_BE_WORD(mark_array->records[mark_index].mark_anchor), iter->pos, &mark_x, &mark_y);
- opentype_layout_gpos_get_anchor(context, base_array_offset + base_anchor, base_iter.pos, &base_x, &base_y);
+ opentype_layout_gpos_get_anchor(context, mark_array_offset +
+ GET_BE_WORD(mark_array->records[mark_index].mark_anchor), context->cur, &mark_x, &mark_y);
+ opentype_layout_gpos_get_anchor(context, base_array_offset + base_anchor, base_iter.pos, &base_x, &base_y);
- context->offsets[iter->pos].advanceOffset = (context->is_rtl ? -1.0f : 1.0f) * (base_x - mark_x);
- context->offsets[iter->pos].ascenderOffset = base_y - mark_y;
+ context->offsets[context->cur].advanceOffset = (context->is_rtl ? -1.0f : 1.0f) * (base_x - mark_x);
+ context->offsets[context->cur].ascenderOffset = base_y - mark_y;
- break;
- }
- else
- WARN("Unknown mark-to-base format %u.\n", format);
+ context->cur++;
+ }
+ else
+ {
+ WARN("Unknown mark-to-base format %u.\n", format);
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
static BOOL opentype_layout_apply_gpos_mark_to_lig_attachment(struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
struct scriptshaping_cache *cache = context->cache;
- unsigned int i;
WORD format;
- for (i = 0; i < lookup->subtable_count; ++i)
- {
- unsigned int subtable_offset = opentype_layout_get_gpos_subtable(cache, lookup->offset, i);
+ format = table_read_be_word(&cache->gpos.table, subtable_offset);
- format = table_read_be_word(&cache->gpos.table, subtable_offset);
-
- if (format == 1)
- {
- const struct ot_gpos_mark_to_lig_format1 *format1 = table_read_ensure(&cache->gpos.table,
- subtable_offset, sizeof(*format1));
- unsigned int mark_index, lig_index;
- struct glyph_iterator lig_iter;
+ if (format == 1)
+ {
+ const struct ot_gpos_mark_to_lig_format1 *format1 = table_read_ensure(&cache->gpos.table,
+ subtable_offset, sizeof(*format1));
+ unsigned int mark_index, lig_index;
+ struct glyph_iterator lig_iter;
- if (!format1)
- continue;
+ if (!format1)
+ return FALSE;
- mark_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark_coverage),
- context->u.pos.glyphs[iter->pos]);
- if (mark_index == GLYPH_NOT_COVERED)
- continue;
+ mark_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark_coverage),
+ context->u.pos.glyphs[context->cur]);
+ if (mark_index == GLYPH_NOT_COVERED)
+ return FALSE;
- glyph_iterator_init(context, LOOKUP_FLAG_IGNORE_MARKS, iter->pos, 1, &lig_iter);
- if (!glyph_iterator_prev(&lig_iter))
- continue;
+ glyph_iterator_init(context, LOOKUP_FLAG_IGNORE_MARKS, context->cur, 1, &lig_iter);
+ if (!glyph_iterator_prev(&lig_iter))
+ return FALSE;
- lig_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->lig_coverage),
- context->u.pos.glyphs[lig_iter.pos]);
- if (lig_index == GLYPH_NOT_COVERED)
- continue;
+ lig_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->lig_coverage),
+ context->u.pos.glyphs[lig_iter.pos]);
+ if (lig_index == GLYPH_NOT_COVERED)
+ return FALSE;
- FIXME("Unimplemented.\n");
- }
- else
- WARN("Unknown mark-to-ligature format %u.\n", format);
+ FIXME("Unimplemented.\n");
}
+ else
+ WARN("Unknown mark-to-ligature format %u.\n", format);
return FALSE;
}
static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
struct scriptshaping_cache *cache = context->cache;
- unsigned int i;
WORD format;
- for (i = 0; i < lookup->subtable_count; ++i)
- {
- unsigned int subtable_offset = opentype_layout_get_gpos_subtable(cache, lookup->offset, i);
-
- format = table_read_be_word(&cache->gpos.table, subtable_offset);
+ format = table_read_be_word(&cache->gpos.table, subtable_offset);
- if (format == 1)
- {
- const struct ot_gpos_mark_to_mark_format1 *format1 = table_read_ensure(&cache->gpos.table,
- subtable_offset, sizeof(*format1));
- unsigned int count, mark1_array_offset, mark2_array_offset, mark_class_count;
- unsigned int mark1_index, mark2_index, mark2_anchor;
- const struct ot_gpos_mark_array *mark1_array;
- const struct ot_gpos_base_array *mark2_array;
- float mark1_x, mark1_y, mark2_x, mark2_y;
- struct glyph_iterator mark_iter;
-
- if (!format1)
- continue;
+ if (format == 1)
+ {
+ const struct ot_gpos_mark_to_mark_format1 *format1 = table_read_ensure(&cache->gpos.table,
+ subtable_offset, sizeof(*format1));
+ unsigned int count, mark1_array_offset, mark2_array_offset, mark_class_count;
+ unsigned int mark1_index, mark2_index, mark2_anchor;
+ const struct ot_gpos_mark_array *mark1_array;
+ const struct ot_gpos_base_array *mark2_array;
+ float mark1_x, mark1_y, mark2_x, mark2_y;
+ struct glyph_iterator mark_iter;
+
+ if (!format1)
+ return FALSE;
- mark1_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark1_coverage),
- context->u.pos.glyphs[iter->pos]);
+ mark1_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark1_coverage),
+ context->u.pos.glyphs[context->cur]);
- mark1_array_offset = subtable_offset + GET_BE_WORD(format1->mark1_array);
- if (!(count = table_read_be_word(&cache->gpos.table, mark1_array_offset)))
- continue;
+ mark1_array_offset = subtable_offset + GET_BE_WORD(format1->mark1_array);
+ if (!(count = table_read_be_word(&cache->gpos.table, mark1_array_offset)))
+ return FALSE;
- mark1_array = table_read_ensure(&cache->gpos.table, mark1_array_offset,
- FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
- if (!mark1_array)
- continue;
+ mark1_array = table_read_ensure(&cache->gpos.table, mark1_array_offset,
+ FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
+ if (!mark1_array)
+ return FALSE;
- if (mark1_index == GLYPH_NOT_COVERED || mark1_index >= count)
- continue;
+ if (mark1_index == GLYPH_NOT_COVERED || mark1_index >= count)
+ return FALSE;
- glyph_iterator_init(context, lookup->flags & ~LOOKUP_FLAG_IGNORE_MASK, iter->pos, 1, &mark_iter);
- if (!glyph_iterator_prev(&mark_iter))
- continue;
+ glyph_iterator_init(context, lookup->flags & ~LOOKUP_FLAG_IGNORE_MASK, context->cur, 1, &mark_iter);
+ if (!glyph_iterator_prev(&mark_iter))
+ return FALSE;
- if (!context->u.pos.glyph_props[mark_iter.pos].isDiacritic)
- continue;
+ if (!context->u.pos.glyph_props[mark_iter.pos].isDiacritic)
+ return FALSE;
- mark2_array_offset = subtable_offset + GET_BE_WORD(format1->mark2_array);
- if (!(count = table_read_be_word(&cache->gpos.table, mark2_array_offset)))
- continue;
+ mark2_array_offset = subtable_offset + GET_BE_WORD(format1->mark2_array);
+ if (!(count = table_read_be_word(&cache->gpos.table, mark2_array_offset)))
+ return FALSE;
- mark_class_count = GET_BE_WORD(format1->mark_class_count);
+ mark_class_count = GET_BE_WORD(format1->mark_class_count);
- mark2_array = table_read_ensure(&cache->gpos.table, mark2_array_offset,
- FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * mark_class_count]));
- if (!mark2_array)
- continue;
+ mark2_array = table_read_ensure(&cache->gpos.table, mark2_array_offset,
+ FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * mark_class_count]));
+ if (!mark2_array)
+ return FALSE;
- mark2_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark2_coverage),
- context->u.pos.glyphs[mark_iter.pos]);
+ mark2_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark2_coverage),
+ context->u.pos.glyphs[mark_iter.pos]);
- if (mark2_index == GLYPH_NOT_COVERED || mark2_index >= count)
- continue;
+ if (mark2_index == GLYPH_NOT_COVERED || mark2_index >= count)
+ return FALSE;
- mark2_anchor = GET_BE_WORD(mark2_array->offsets[mark2_index * mark_class_count +
- GET_BE_WORD(mark1_array->records[mark1_index].mark_class)]);
- opentype_layout_gpos_get_anchor(context, mark1_array_offset +
- GET_BE_WORD(mark1_array->records[mark1_index].mark_anchor), iter->pos, &mark1_x, &mark1_y);
- opentype_layout_gpos_get_anchor(context, mark2_array_offset + mark2_anchor, mark_iter.pos,
- &mark2_x, &mark2_y);
+ mark2_anchor = GET_BE_WORD(mark2_array->offsets[mark2_index * mark_class_count +
+ GET_BE_WORD(mark1_array->records[mark1_index].mark_class)]);
+ opentype_layout_gpos_get_anchor(context, mark1_array_offset +
+ GET_BE_WORD(mark1_array->records[mark1_index].mark_anchor), context->cur, &mark1_x, &mark1_y);
+ opentype_layout_gpos_get_anchor(context, mark2_array_offset + mark2_anchor, mark_iter.pos,
+ &mark2_x, &mark2_y);
- context->offsets[iter->pos].advanceOffset = mark2_x - mark1_x;
- context->offsets[iter->pos].ascenderOffset = mark2_y - mark1_y;
+ context->offsets[context->cur].advanceOffset = mark2_x - mark1_x;
+ context->offsets[context->cur].ascenderOffset = mark2_y - mark1_y;
- break;
- }
- else
- WARN("Unknown mark-to-mark format %u.\n", format);
+ context->cur++;
+ }
+ else
+ {
+ WARN("Unknown mark-to-mark format %u.\n", format);
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
static BOOL opentype_layout_apply_gpos_contextual_positioning(const struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
return FALSE;
}
static BOOL opentype_layout_apply_gpos_chaining_contextual_positioning(const struct scriptshaping_context *context,
- struct glyph_iterator *iter, const struct ot_lookup *lookup)
+ const struct lookup *lookup, unsigned int subtable_offset)
{
return FALSE;
}
-static void opentype_layout_apply_gpos_lookup(struct scriptshaping_context *context, int lookup_index)
+static unsigned int opentype_layout_adjust_extension_subtable(struct scriptshaping_context *context,
+ unsigned int *subtable_offset)
{
- struct scriptshaping_cache *cache = context->cache;
- const struct ot_lookup_table *lookup_table;
- struct glyph_iterator iter;
- struct ot_lookup lookup;
- WORD lookup_type;
-
- lookup.offset = table_read_be_word(&cache->gpos.table, cache->gpos.lookup_list +
- FIELD_OFFSET(struct ot_lookup_list, lookup[lookup_index]));
- if (!lookup.offset)
- return;
-
- lookup.offset += cache->gpos.lookup_list;
-
- if (!(lookup_table = table_read_ensure(&cache->gpos.table, lookup.offset, sizeof(*lookup_table))))
- return;
+ const struct ot_gsubgpos_extension_format1 *format1;
- lookup.subtable_count = GET_BE_WORD(lookup_table->subtable_count);
- if (!lookup.subtable_count)
- return;
+ if (!(format1 = table_read_ensure(&context->table->table, *subtable_offset, sizeof(*format1))))
+ return 0;
- lookup_type = GET_BE_WORD(lookup_table->lookup_type);
- if (lookup_type == GPOS_LOOKUP_EXTENSION_POSITION)
+ if (GET_BE_WORD(format1->format) != 1)
{
- const struct ot_gsubgpos_extension_format1 *extension = table_read_ensure(&cache->gpos.table,
- lookup.offset + GET_BE_WORD(lookup_table->subtable[0]), sizeof(*extension));
- WORD format;
-
- if (!extension)
- return;
+ WARN("Unexpected extension table format %#x.\n", format1->format);
+ return 0;
+ }
- format = GET_BE_WORD(extension->format);
- if (format != 1)
- {
- WARN("Unexpected extension table format %u.\n", format);
- return;
- }
+ *subtable_offset = *subtable_offset + GET_BE_DWORD(format1->extension_offset);
- lookup_type = GET_BE_WORD(extension->lookup_type);
- }
- lookup.flags = GET_BE_WORD(lookup_table->flags);
+ return GET_BE_WORD(format1->lookup_type);
+}
- glyph_iterator_init(context, lookup.flags, 0, context->glyph_count, &iter);
+static BOOL opentype_layout_apply_gpos_lookup(struct scriptshaping_context *context, const struct lookup *lookup)
+{
+ unsigned int i, lookup_type;
+ BOOL ret = FALSE;
- while (iter.pos < context->glyph_count)
+ for (i = 0; i < lookup->subtable_count; ++i)
{
- BOOL ret;
+ unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup->offset, i);
- if (!glyph_iterator_match(&iter))
+ if (lookup->type == GPOS_LOOKUP_EXTENSION_POSITION)
{
- ++iter.pos;
- continue;
+ lookup_type = opentype_layout_adjust_extension_subtable(context, &subtable_offset);
+ if (!lookup_type)
+ continue;
}
+ else
+ lookup_type = lookup->type;
switch (lookup_type)
{
case GPOS_LOOKUP_SINGLE_ADJUSTMENT:
- ret = opentype_layout_apply_gpos_single_adjustment(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_single_adjustment(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_PAIR_ADJUSTMENT:
- ret = opentype_layout_apply_gpos_pair_adjustment(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_pair_adjustment(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_CURSIVE_ATTACHMENT:
- ret = opentype_layout_apply_gpos_cursive_attachment(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_cursive_attachment(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_MARK_TO_BASE_ATTACHMENT:
- ret = opentype_layout_apply_gpos_mark_to_base_attachment(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_mark_to_base_attachment(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_MARK_TO_LIGATURE_ATTACHMENT:
- ret = opentype_layout_apply_gpos_mark_to_lig_attachment(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_mark_to_lig_attachment(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_MARK_TO_MARK_ATTACHMENT:
- ret = opentype_layout_apply_gpos_mark_to_mark_attachment(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_mark_to_mark_attachment(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_CONTEXTUAL_POSITION:
- ret = opentype_layout_apply_gpos_contextual_positioning(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_contextual_positioning(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_CONTEXTUAL_CHAINING_POSITION:
- ret = opentype_layout_apply_gpos_chaining_contextual_positioning(context, &iter, &lookup);
+ ret = opentype_layout_apply_gpos_chaining_contextual_positioning(context, lookup, subtable_offset);
break;
case GPOS_LOOKUP_EXTENSION_POSITION:
WARN("Recursive extension lookup.\n");
- ret = FALSE;
break;
default:
WARN("Unknown lookup type %u.\n", lookup_type);
- return;
}
- /* Some lookups update position after making changes. */
- if (!ret)
- ++iter.pos;
+ if (ret)
+ break;
}
-}
-
-struct lookup
-{
- unsigned short index;
- unsigned short type;
- unsigned short flags;
- unsigned short subtable_count;
- unsigned int mask;
- unsigned int offset;
-};
+ return ret;
+}
struct lookups
{
@@ -4489,6 +4425,7 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context,
{
struct lookups lookups = { 0 };
unsigned int i;
+ BOOL ret;
opentype_layout_collect_lookups(context, script_index, language_index, features, &context->cache->gpos, &lookups);
@@ -4497,7 +4434,24 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context,
opentype_layout_set_glyph_masks(context, features);
for (i = 0; i < lookups.count; ++i)
- opentype_layout_apply_gpos_lookup(context, lookups.lookups[i].index);
+ {
+ const struct lookup *lookup = &lookups.lookups[i];
+
+ context->cur = 0;
+ while (context->cur < context->glyph_count)
+ {
+ ret = FALSE;
+
+ if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
+ lookup_is_glyph_match(context->glyph_infos[context->cur].props, lookup->flags))
+ {
+ ret = opentype_layout_apply_gpos_lookup(context, lookup);
+ }
+
+ if (!ret)
+ context->cur++;
+ }
+ }
heap_free(lookups.lookups);
}
@@ -4845,25 +4799,6 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
return ret;
}
-static unsigned int opentype_layout_adjust_extension_subtable(struct scriptshaping_context *context,
- unsigned int *subtable_offset)
-{
- const struct ot_gsubgpos_extension_format1 *format1;
-
- if (!(format1 = table_read_ensure(&context->table->table, *subtable_offset, sizeof(*format1))))
- return 0;
-
- if (GET_BE_WORD(format1->format) != 1)
- {
- WARN("Unexpected extension table format %#x.\n", format1->format);
- return 0;
- }
-
- *subtable_offset = *subtable_offset + GET_BE_DWORD(format1->extension_offset);
-
- return GET_BE_WORD(format1->lookup_type);
-}
-
static BOOL opentype_layout_apply_gsub_lookup(struct scriptshaping_context *context, const struct lookup *lookup)
{
unsigned int i, lookup_type;
@@ -4871,7 +4806,7 @@ static BOOL opentype_layout_apply_gsub_lookup(struct scriptshaping_context *cont
for (i = 0; i < lookup->subtable_count; ++i)
{
- unsigned int subtable_offset = opentype_layout_get_gsub_subtable(context, lookup->offset, i);
+ unsigned int subtable_offset = opentype_layout_get_gsubgpos_subtable(context, lookup->offset, i);
if (lookup->type == GSUB_LOOKUP_EXTENSION_SUBST)
{
--
2.26.2
More information about the wine-devel
mailing list