dwrite: Implement mark glyph filtering.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2e79405eec
commit
5c9129723c
|
@ -459,6 +459,8 @@ struct scriptshaping_cache
|
||||||
{
|
{
|
||||||
struct dwrite_fonttable table;
|
struct dwrite_fonttable table;
|
||||||
unsigned int classdef;
|
unsigned int classdef;
|
||||||
|
unsigned int markattachclassdef;
|
||||||
|
unsigned int markglyphsetdef;
|
||||||
} gdef;
|
} gdef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -448,10 +448,11 @@ enum ot_gdef_class
|
||||||
struct gdef_header
|
struct gdef_header
|
||||||
{
|
{
|
||||||
DWORD version;
|
DWORD version;
|
||||||
WORD classdef;
|
UINT16 classdef;
|
||||||
WORD attach_list;
|
UINT16 attach_list;
|
||||||
WORD ligcaret_list;
|
UINT16 ligcaret_list;
|
||||||
WORD markattach_classdef;
|
UINT16 markattach_classdef;
|
||||||
|
UINT16 markglyphsetdef;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ot_gdef_classdef_format1
|
struct ot_gdef_classdef_format1
|
||||||
|
@ -486,12 +487,15 @@ struct gpos_gsub_header
|
||||||
|
|
||||||
enum gsub_gpos_lookup_flags
|
enum gsub_gpos_lookup_flags
|
||||||
{
|
{
|
||||||
LOOKUP_FLAG_RTL = 0x1,
|
LOOKUP_FLAG_RTL = 0x1, /* Only used for GPOS cursive attachments. */
|
||||||
|
|
||||||
LOOKUP_FLAG_IGNORE_BASE = 0x2,
|
LOOKUP_FLAG_IGNORE_BASE = 0x2,
|
||||||
LOOKUP_FLAG_IGNORE_LIGATURES = 0x4,
|
LOOKUP_FLAG_IGNORE_LIGATURES = 0x4,
|
||||||
LOOKUP_FLAG_IGNORE_MARKS = 0x8,
|
LOOKUP_FLAG_IGNORE_MARKS = 0x8,
|
||||||
|
|
||||||
LOOKUP_FLAG_IGNORE_MASK = 0xe,
|
LOOKUP_FLAG_IGNORE_MASK = 0xe,
|
||||||
|
|
||||||
|
LOOKUP_FLAG_USE_MARK_FILTERING_SET = 0x10,
|
||||||
|
LOOKUP_FLAG_MARK_ATTACHMENT_TYPE = 0xff00,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum glyph_prop_flags
|
enum glyph_prop_flags
|
||||||
|
@ -3041,7 +3045,16 @@ void opentype_layout_scriptshaping_cache_init(struct scriptshaping_cache *cache)
|
||||||
&cache->gdef.table.context);
|
&cache->gdef.table.context);
|
||||||
|
|
||||||
if (cache->gdef.table.data)
|
if (cache->gdef.table.data)
|
||||||
|
{
|
||||||
|
unsigned int version = table_read_be_dword(&cache->gdef.table, 0);
|
||||||
|
|
||||||
cache->gdef.classdef = table_read_be_word(&cache->gdef.table, FIELD_OFFSET(struct gdef_header, classdef));
|
cache->gdef.classdef = table_read_be_word(&cache->gdef.table, FIELD_OFFSET(struct gdef_header, classdef));
|
||||||
|
cache->gdef.markattachclassdef = table_read_be_word(&cache->gdef.table,
|
||||||
|
FIELD_OFFSET(struct gdef_header, markattach_classdef));
|
||||||
|
if (version >= 0x00010002)
|
||||||
|
cache->gdef.markglyphsetdef = table_read_be_word(&cache->gdef.table,
|
||||||
|
FIELD_OFFSET(struct gdef_header, markglyphsetdef));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int opentype_layout_find_script(const struct scriptshaping_cache *cache, unsigned int kind, DWORD script,
|
unsigned int opentype_layout_find_script(const struct scriptshaping_cache *cache, unsigned int kind, DWORD script,
|
||||||
|
@ -3188,6 +3201,12 @@ static unsigned int opentype_set_glyph_props(struct scriptshaping_context *conte
|
||||||
break;
|
break;
|
||||||
case GDEF_CLASS_MARK:
|
case GDEF_CLASS_MARK:
|
||||||
props = GLYPH_PROP_MARK;
|
props = GLYPH_PROP_MARK;
|
||||||
|
if (cache->gdef.markattachclassdef)
|
||||||
|
{
|
||||||
|
glyph_class = opentype_layout_get_glyph_class(&cache->gdef.table, cache->gdef.markattachclassdef,
|
||||||
|
context->u.buffer.glyphs[idx]);
|
||||||
|
props |= glyph_class << 8;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
props = 0;
|
props = 0;
|
||||||
|
@ -3200,7 +3219,7 @@ static unsigned int opentype_set_glyph_props(struct scriptshaping_context *conte
|
||||||
|
|
||||||
static void opentype_set_subst_glyph_props(struct scriptshaping_context *context, unsigned int idx)
|
static void opentype_set_subst_glyph_props(struct scriptshaping_context *context, unsigned int idx)
|
||||||
{
|
{
|
||||||
unsigned int glyph_props = opentype_set_glyph_props(context, idx);
|
unsigned int glyph_props = opentype_set_glyph_props(context, idx) & LOOKUP_FLAG_IGNORE_MASK;
|
||||||
context->u.subst.glyph_props[idx].isDiacritic = !!(glyph_props == GLYPH_PROP_MARK);
|
context->u.subst.glyph_props[idx].isDiacritic = !!(glyph_props == GLYPH_PROP_MARK);
|
||||||
context->u.subst.glyph_props[idx].isZeroWidthSpace = !!(glyph_props == GLYPH_PROP_MARK);
|
context->u.subst.glyph_props[idx].isZeroWidthSpace = !!(glyph_props == GLYPH_PROP_MARK);
|
||||||
}
|
}
|
||||||
|
@ -3238,10 +3257,9 @@ static int coverage_compare_format2(const void *g, const void *r)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int opentype_layout_is_glyph_covered(const struct scriptshaping_context *context, unsigned int coverage,
|
static unsigned int opentype_layout_is_glyph_covered(const struct dwrite_fonttable *table, unsigned int coverage,
|
||||||
UINT16 glyph)
|
UINT16 glyph)
|
||||||
{
|
{
|
||||||
const struct dwrite_fonttable *table = &context->table->table;
|
|
||||||
WORD format = table_read_be_word(table, coverage), count;
|
WORD format = table_read_be_word(table, coverage), count;
|
||||||
|
|
||||||
count = table_read_be_word(table, coverage + 2);
|
count = table_read_be_word(table, coverage + 2);
|
||||||
|
@ -3465,19 +3483,61 @@ static void glyph_iterator_init(struct scriptshaping_context *context, unsigned
|
||||||
iter->len = len;
|
iter->len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL lookup_is_glyph_match(unsigned int glyph_props, unsigned int lookup_flags)
|
struct ot_gdef_mark_glyph_sets
|
||||||
{
|
{
|
||||||
if (glyph_props & lookup_flags & LOOKUP_FLAG_IGNORE_MASK)
|
UINT16 format;
|
||||||
|
UINT16 count;
|
||||||
|
DWORD offsets[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
static BOOL opentype_layout_mark_set_covers(const struct scriptshaping_cache *cache, unsigned int set_index,
|
||||||
|
UINT16 glyph)
|
||||||
|
{
|
||||||
|
unsigned int format, offset = cache->gdef.markglyphsetdef, coverage_offset, set_count;
|
||||||
|
|
||||||
|
if (!offset)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* FIXME: match mark properties */
|
format = table_read_be_word(&cache->gdef.table, offset);
|
||||||
|
|
||||||
|
if (format == 1)
|
||||||
|
{
|
||||||
|
set_count = table_read_be_word(&cache->gdef.table, offset + 2);
|
||||||
|
if (!set_count || set_index >= set_count)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
coverage_offset = table_read_be_dword(&cache->gdef.table, offset + 2 + set_index * sizeof(coverage_offset));
|
||||||
|
return opentype_layout_is_glyph_covered(&cache->gdef.table, offset + coverage_offset, glyph) != GLYPH_NOT_COVERED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WARN("Unexpected MarkGlyphSets format %#x.\n", format);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL lookup_is_glyph_match(const struct scriptshaping_context *context, unsigned int idx, unsigned int match_props)
|
||||||
|
{
|
||||||
|
unsigned int glyph_props = context->glyph_infos[idx].props;
|
||||||
|
UINT16 glyph = context->u.buffer.glyphs[idx];
|
||||||
|
|
||||||
|
if (glyph_props & match_props & LOOKUP_FLAG_IGNORE_MASK)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!(glyph_props & GLYPH_PROP_MARK))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (match_props & LOOKUP_FLAG_USE_MARK_FILTERING_SET)
|
||||||
|
return opentype_layout_mark_set_covers(context->cache, match_props >> 16, glyph);
|
||||||
|
|
||||||
|
if (match_props & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE)
|
||||||
|
return (match_props & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE) == (glyph_props & LOOKUP_FLAG_MARK_ATTACHMENT_TYPE);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL glyph_iterator_match(const struct glyph_iterator *iter)
|
static BOOL glyph_iterator_match(const struct glyph_iterator *iter)
|
||||||
{
|
{
|
||||||
return lookup_is_glyph_match(iter->context->glyph_infos[iter->pos].props, iter->flags);
|
return lookup_is_glyph_match(iter->context, iter->pos, iter->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL glyph_iterator_next(struct glyph_iterator *iter)
|
static BOOL glyph_iterator_next(struct glyph_iterator *iter)
|
||||||
|
@ -3527,6 +3587,7 @@ struct lookup
|
||||||
static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_context *context,
|
static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_context *context,
|
||||||
const struct lookup *lookup, unsigned int subtable_offset)
|
const struct lookup *lookup, unsigned int subtable_offset)
|
||||||
{
|
{
|
||||||
|
const struct dwrite_fonttable *table = &context->table->table;
|
||||||
struct scriptshaping_cache *cache = context->cache;
|
struct scriptshaping_cache *cache = context->cache;
|
||||||
UINT16 format, value_format, value_len, coverage, glyph;
|
UINT16 format, value_format, value_len, coverage, glyph;
|
||||||
|
|
||||||
|
@ -3547,7 +3608,7 @@ static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_co
|
||||||
const struct ot_gpos_singlepos_format1 *format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
|
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]));
|
FIELD_OFFSET(struct ot_gpos_singlepos_format1, value[value_len]));
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -3560,7 +3621,7 @@ static BOOL opentype_layout_apply_gpos_single_adjustment(struct scriptshaping_co
|
||||||
const struct ot_gpos_singlepos_format2 *format2 = table_read_ensure(&cache->gpos.table, subtable_offset,
|
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));
|
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, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED || coverage_index >= value_count)
|
if (coverage_index == GLYPH_NOT_COVERED || coverage_index >= value_count)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -3589,6 +3650,7 @@ static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_cont
|
||||||
const struct lookup *lookup, unsigned int subtable_offset)
|
const struct lookup *lookup, unsigned int subtable_offset)
|
||||||
{
|
{
|
||||||
struct scriptshaping_cache *cache = context->cache;
|
struct scriptshaping_cache *cache = context->cache;
|
||||||
|
const struct dwrite_fonttable *table = &cache->gpos.table;
|
||||||
unsigned int first_glyph, second_glyph;
|
unsigned int first_glyph, second_glyph;
|
||||||
struct glyph_iterator iter_pair;
|
struct glyph_iterator iter_pair;
|
||||||
WORD format, coverage;
|
WORD format, coverage;
|
||||||
|
@ -3611,13 +3673,13 @@ static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_cont
|
||||||
second_glyph = iter_pair.pos;
|
second_glyph = iter_pair.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
format = table_read_be_word(&cache->gpos.table, subtable_offset);
|
format = table_read_be_word(table, subtable_offset);
|
||||||
|
|
||||||
coverage = table_read_be_word(&cache->gpos.table, subtable_offset + FIELD_OFFSET(struct ot_gpos_pairpos_format1, coverage));
|
coverage = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_pairpos_format1, coverage));
|
||||||
if (!coverage)
|
if (!coverage)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, context->u.pos.glyphs[first_glyph]);
|
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, context->u.pos.glyphs[first_glyph]);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -3634,14 +3696,12 @@ static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_cont
|
||||||
if (!pairset_count || coverage_index >= pairset_count)
|
if (!pairset_count || coverage_index >= pairset_count)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
|
format1 = table_read_ensure(table, subtable_offset, FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairsets[pairset_count]));
|
||||||
FIELD_OFFSET(struct ot_gpos_pairpos_format1, pairsets[pairset_count]));
|
|
||||||
if (!format1)
|
if (!format1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Ordered paired values. */
|
/* Ordered paired values. */
|
||||||
pairvalue_count = table_read_be_word(&cache->gpos.table, subtable_offset +
|
pairvalue_count = table_read_be_word(table, subtable_offset + GET_BE_WORD(format1->pairsets[coverage_index]));
|
||||||
GET_BE_WORD(format1->pairsets[coverage_index]));
|
|
||||||
if (!pairvalue_count)
|
if (!pairvalue_count)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -3681,28 +3741,25 @@ static BOOL opentype_layout_apply_gpos_pair_adjustment(struct scriptshaping_cont
|
||||||
unsigned int class1, class2;
|
unsigned int class1, class2;
|
||||||
const WCHAR *values;
|
const WCHAR *values;
|
||||||
|
|
||||||
value_format1 = table_read_be_word(&cache->gpos.table, subtable_offset +
|
value_format1 = table_read_be_word(table, subtable_offset +
|
||||||
FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format1)) & 0xff;
|
FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format1)) & 0xff;
|
||||||
value_format2 = table_read_be_word(&cache->gpos.table, subtable_offset +
|
value_format2 = table_read_be_word(table, subtable_offset +
|
||||||
FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format2)) & 0xff;
|
FIELD_OFFSET(struct ot_gpos_pairpos_format2, value_format2)) & 0xff;
|
||||||
|
|
||||||
class1_count = table_read_be_word(&cache->gpos.table, subtable_offset +
|
class1_count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_pairpos_format2, class1_count));
|
||||||
FIELD_OFFSET(struct ot_gpos_pairpos_format2, class1_count));
|
class2_count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_pairpos_format2, class2_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_len1 = dwrite_popcount(value_format1);
|
||||||
value_len2 = dwrite_popcount(value_format2);
|
value_len2 = dwrite_popcount(value_format2);
|
||||||
|
|
||||||
format2 = table_read_ensure(&cache->gpos.table, subtable_offset,
|
format2 = table_read_ensure(table, subtable_offset, FIELD_OFFSET(struct ot_gpos_pairpos_format2,
|
||||||
FIELD_OFFSET(struct ot_gpos_pairpos_format2,
|
|
||||||
values[class1_count * class2_count * (value_len1 + value_len2)]));
|
values[class1_count * class2_count * (value_len1 + value_len2)]));
|
||||||
if (!format2)
|
if (!format2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
class1 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def1),
|
class1 = opentype_layout_get_glyph_class(table, subtable_offset + GET_BE_WORD(format2->class_def1),
|
||||||
context->u.pos.glyphs[first_glyph]);
|
context->u.pos.glyphs[first_glyph]);
|
||||||
class2 = opentype_layout_get_glyph_class(&cache->gpos.table, subtable_offset + GET_BE_WORD(format2->class_def2),
|
class2 = opentype_layout_get_glyph_class(table, subtable_offset + GET_BE_WORD(format2->class_def2),
|
||||||
context->u.pos.glyphs[second_glyph]);
|
context->u.pos.glyphs[second_glyph]);
|
||||||
|
|
||||||
if (!(class1 < class1_count && class2 < class2_count))
|
if (!(class1 < class1_count && class2 < class2_count))
|
||||||
|
@ -3787,12 +3844,13 @@ static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_c
|
||||||
const struct lookup *lookup, unsigned int subtable_offset)
|
const struct lookup *lookup, unsigned int subtable_offset)
|
||||||
{
|
{
|
||||||
struct scriptshaping_cache *cache = context->cache;
|
struct scriptshaping_cache *cache = context->cache;
|
||||||
|
const struct dwrite_fonttable *table = &cache->gpos.table;
|
||||||
WORD format = table_read_be_word(&cache->gpos.table, subtable_offset);
|
WORD format = table_read_be_word(&cache->gpos.table, subtable_offset);
|
||||||
UINT16 glyph = context->u.pos.glyphs[context->cur];
|
UINT16 glyph = context->u.pos.glyphs[context->cur];
|
||||||
|
|
||||||
if (format == 1)
|
if (format == 1)
|
||||||
{
|
{
|
||||||
WORD coverage_offset = table_read_be_word(&cache->gpos.table, subtable_offset +
|
WORD coverage_offset = table_read_be_word(table, subtable_offset +
|
||||||
FIELD_OFFSET(struct ot_gpos_cursive_format1, coverage));
|
FIELD_OFFSET(struct ot_gpos_cursive_format1, coverage));
|
||||||
unsigned int glyph_index, entry_count, entry_anchor, exit_anchor;
|
unsigned int glyph_index, entry_count, entry_anchor, exit_anchor;
|
||||||
float entry_x, entry_y, exit_x, exit_y, delta;
|
float entry_x, entry_y, exit_x, exit_y, delta;
|
||||||
|
@ -3801,14 +3859,13 @@ static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_c
|
||||||
if (!coverage_offset)
|
if (!coverage_offset)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
entry_count = table_read_be_word(&cache->gpos.table, subtable_offset +
|
entry_count = table_read_be_word(table, subtable_offset + FIELD_OFFSET(struct ot_gpos_cursive_format1, count));
|
||||||
FIELD_OFFSET(struct ot_gpos_cursive_format1, count));
|
|
||||||
|
|
||||||
glyph_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage_offset, glyph);
|
glyph_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage_offset, glyph);
|
||||||
if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
|
if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
entry_anchor = table_read_be_word(&cache->gpos.table, subtable_offset +
|
entry_anchor = table_read_be_word(table, subtable_offset +
|
||||||
FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2]));
|
FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2]));
|
||||||
if (!entry_anchor)
|
if (!entry_anchor)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -3817,12 +3874,12 @@ static BOOL opentype_layout_apply_gpos_cursive_attachment(struct scriptshaping_c
|
||||||
if (!glyph_iterator_prev(&prev_iter))
|
if (!glyph_iterator_prev(&prev_iter))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
glyph_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage_offset,
|
glyph_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage_offset,
|
||||||
context->u.pos.glyphs[prev_iter.pos]);
|
context->u.pos.glyphs[prev_iter.pos]);
|
||||||
if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
|
if (glyph_index == GLYPH_NOT_COVERED || glyph_index >= entry_count)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
exit_anchor = table_read_be_word(&cache->gpos.table, subtable_offset +
|
exit_anchor = table_read_be_word(table, subtable_offset +
|
||||||
FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2 + 1]));
|
FIELD_OFFSET(struct ot_gpos_cursive_format1, anchors[glyph_index * 2 + 1]));
|
||||||
if (!exit_anchor)
|
if (!exit_anchor)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -3865,14 +3922,14 @@ static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshap
|
||||||
const struct lookup *lookup, unsigned int subtable_offset)
|
const struct lookup *lookup, unsigned int subtable_offset)
|
||||||
{
|
{
|
||||||
struct scriptshaping_cache *cache = context->cache;
|
struct scriptshaping_cache *cache = context->cache;
|
||||||
|
const struct dwrite_fonttable *table = &cache->gpos.table;
|
||||||
WORD format;
|
WORD format;
|
||||||
|
|
||||||
format = table_read_be_word(&cache->gpos.table, subtable_offset);
|
format = table_read_be_word(table, subtable_offset);
|
||||||
|
|
||||||
if (format == 1)
|
if (format == 1)
|
||||||
{
|
{
|
||||||
const struct ot_gpos_mark_to_base_format1 *format1 = table_read_ensure(&cache->gpos.table, subtable_offset,
|
const struct ot_gpos_mark_to_base_format1 *format1 = table_read_ensure(table, subtable_offset, sizeof(*format1));
|
||||||
sizeof(*format1));
|
|
||||||
unsigned int mark_class_count, count, mark_array_offset, base_array_offset;
|
unsigned int mark_class_count, count, mark_array_offset, base_array_offset;
|
||||||
const struct ot_gpos_mark_array *mark_array;
|
const struct ot_gpos_mark_array *mark_array;
|
||||||
const struct ot_gpos_base_array *base_array;
|
const struct ot_gpos_base_array *base_array;
|
||||||
|
@ -3885,26 +3942,25 @@ static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshap
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
mark_array_offset = subtable_offset + GET_BE_WORD(format1->mark_array);
|
mark_array_offset = subtable_offset + GET_BE_WORD(format1->mark_array);
|
||||||
if (!(count = table_read_be_word(&cache->gpos.table, mark_array_offset)))
|
if (!(count = table_read_be_word(table, mark_array_offset)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
mark_array = table_read_ensure(&cache->gpos.table, mark_array_offset,
|
mark_array = table_read_ensure(table, mark_array_offset, FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
|
||||||
FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
|
|
||||||
if (!mark_array)
|
if (!mark_array)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
base_array_offset = subtable_offset + GET_BE_WORD(format1->base_array);
|
base_array_offset = subtable_offset + GET_BE_WORD(format1->base_array);
|
||||||
if (!(count = table_read_be_word(&cache->gpos.table, base_array_offset)))
|
if (!(count = table_read_be_word(table, base_array_offset)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
base_array = table_read_ensure(&cache->gpos.table, base_array_offset,
|
base_array = table_read_ensure(table, base_array_offset,
|
||||||
FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * GET_BE_WORD(format1->mark_class_count)]));
|
FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * GET_BE_WORD(format1->mark_class_count)]));
|
||||||
if (!base_array)
|
if (!base_array)
|
||||||
return FALSE;
|
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),
|
mark_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark_coverage),
|
||||||
context->u.pos.glyphs[context->cur]);
|
context->u.pos.glyphs[context->cur]);
|
||||||
|
|
||||||
if (mark_index == GLYPH_NOT_COVERED || mark_index >= GET_BE_WORD(mark_array->count))
|
if (mark_index == GLYPH_NOT_COVERED || mark_index >= GET_BE_WORD(mark_array->count))
|
||||||
|
@ -3915,7 +3971,7 @@ static BOOL opentype_layout_apply_gpos_mark_to_base_attachment(struct scriptshap
|
||||||
if (!glyph_iterator_prev(&base_iter))
|
if (!glyph_iterator_prev(&base_iter))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
base_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->base_coverage),
|
base_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->base_coverage),
|
||||||
context->u.pos.glyphs[base_iter.pos]);
|
context->u.pos.glyphs[base_iter.pos]);
|
||||||
if (base_index == GLYPH_NOT_COVERED || base_index >= GET_BE_WORD(base_array->count))
|
if (base_index == GLYPH_NOT_COVERED || base_index >= GET_BE_WORD(base_array->count))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -3945,21 +4001,21 @@ static BOOL opentype_layout_apply_gpos_mark_to_lig_attachment(struct scriptshapi
|
||||||
const struct lookup *lookup, unsigned int subtable_offset)
|
const struct lookup *lookup, unsigned int subtable_offset)
|
||||||
{
|
{
|
||||||
struct scriptshaping_cache *cache = context->cache;
|
struct scriptshaping_cache *cache = context->cache;
|
||||||
|
const struct dwrite_fonttable *table = &cache->gpos.table;
|
||||||
WORD format;
|
WORD format;
|
||||||
|
|
||||||
format = table_read_be_word(&cache->gpos.table, subtable_offset);
|
format = table_read_be_word(&cache->gpos.table, subtable_offset);
|
||||||
|
|
||||||
if (format == 1)
|
if (format == 1)
|
||||||
{
|
{
|
||||||
const struct ot_gpos_mark_to_lig_format1 *format1 = table_read_ensure(&cache->gpos.table,
|
const struct ot_gpos_mark_to_lig_format1 *format1 = table_read_ensure(table, subtable_offset, sizeof(*format1));
|
||||||
subtable_offset, sizeof(*format1));
|
|
||||||
unsigned int mark_index, lig_index;
|
unsigned int mark_index, lig_index;
|
||||||
struct glyph_iterator lig_iter;
|
struct glyph_iterator lig_iter;
|
||||||
|
|
||||||
if (!format1)
|
if (!format1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
mark_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark_coverage),
|
mark_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark_coverage),
|
||||||
context->u.pos.glyphs[context->cur]);
|
context->u.pos.glyphs[context->cur]);
|
||||||
if (mark_index == GLYPH_NOT_COVERED)
|
if (mark_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -3968,7 +4024,7 @@ static BOOL opentype_layout_apply_gpos_mark_to_lig_attachment(struct scriptshapi
|
||||||
if (!glyph_iterator_prev(&lig_iter))
|
if (!glyph_iterator_prev(&lig_iter))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
lig_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->lig_coverage),
|
lig_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->lig_coverage),
|
||||||
context->u.pos.glyphs[lig_iter.pos]);
|
context->u.pos.glyphs[lig_iter.pos]);
|
||||||
if (lig_index == GLYPH_NOT_COVERED)
|
if (lig_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -3985,14 +4041,14 @@ static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshap
|
||||||
const struct lookup *lookup, unsigned int subtable_offset)
|
const struct lookup *lookup, unsigned int subtable_offset)
|
||||||
{
|
{
|
||||||
struct scriptshaping_cache *cache = context->cache;
|
struct scriptshaping_cache *cache = context->cache;
|
||||||
|
const struct dwrite_fonttable *table = &cache->gpos.table;
|
||||||
WORD format;
|
WORD format;
|
||||||
|
|
||||||
format = table_read_be_word(&cache->gpos.table, subtable_offset);
|
format = table_read_be_word(table, subtable_offset);
|
||||||
|
|
||||||
if (format == 1)
|
if (format == 1)
|
||||||
{
|
{
|
||||||
const struct ot_gpos_mark_to_mark_format1 *format1 = table_read_ensure(&cache->gpos.table,
|
const struct ot_gpos_mark_to_mark_format1 *format1 = table_read_ensure(table, subtable_offset, sizeof(*format1));
|
||||||
subtable_offset, sizeof(*format1));
|
|
||||||
unsigned int count, mark1_array_offset, mark2_array_offset, mark_class_count;
|
unsigned int count, mark1_array_offset, mark2_array_offset, mark_class_count;
|
||||||
unsigned int mark1_index, mark2_index, mark2_anchor;
|
unsigned int mark1_index, mark2_index, mark2_anchor;
|
||||||
const struct ot_gpos_mark_array *mark1_array;
|
const struct ot_gpos_mark_array *mark1_array;
|
||||||
|
@ -4003,15 +4059,14 @@ static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshap
|
||||||
if (!format1)
|
if (!format1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
mark1_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark1_coverage),
|
mark1_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark1_coverage),
|
||||||
context->u.pos.glyphs[context->cur]);
|
context->u.pos.glyphs[context->cur]);
|
||||||
|
|
||||||
mark1_array_offset = subtable_offset + GET_BE_WORD(format1->mark1_array);
|
mark1_array_offset = subtable_offset + GET_BE_WORD(format1->mark1_array);
|
||||||
if (!(count = table_read_be_word(&cache->gpos.table, mark1_array_offset)))
|
if (!(count = table_read_be_word(table, mark1_array_offset)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
mark1_array = table_read_ensure(&cache->gpos.table, mark1_array_offset,
|
mark1_array = table_read_ensure(table, mark1_array_offset, FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
|
||||||
FIELD_OFFSET(struct ot_gpos_mark_array, records[count]));
|
|
||||||
if (!mark1_array)
|
if (!mark1_array)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -4031,12 +4086,12 @@ static BOOL opentype_layout_apply_gpos_mark_to_mark_attachment(struct scriptshap
|
||||||
|
|
||||||
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,
|
mark2_array = table_read_ensure(table, mark2_array_offset,
|
||||||
FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * mark_class_count]));
|
FIELD_OFFSET(struct ot_gpos_base_array, offsets[count * mark_class_count]));
|
||||||
if (!mark2_array)
|
if (!mark2_array)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
mark2_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(format1->mark2_coverage),
|
mark2_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(format1->mark2_coverage),
|
||||||
context->u.pos.glyphs[mark_iter.pos]);
|
context->u.pos.glyphs[mark_iter.pos]);
|
||||||
|
|
||||||
if (mark2_index == GLYPH_NOT_COVERED || mark2_index >= count)
|
if (mark2_index == GLYPH_NOT_COVERED || mark2_index >= count)
|
||||||
|
@ -4169,7 +4224,7 @@ static int lookups_sorting_compare(const void *a, const void *b)
|
||||||
static BOOL opentype_layout_init_lookup(const struct ot_gsubgpos_table *table, unsigned short lookup_index, unsigned int mask,
|
static BOOL opentype_layout_init_lookup(const struct ot_gsubgpos_table *table, unsigned short lookup_index, unsigned int mask,
|
||||||
struct lookup *lookup)
|
struct lookup *lookup)
|
||||||
{
|
{
|
||||||
unsigned short subtable_count, lookup_type, flags;
|
unsigned short subtable_count, lookup_type, flags, mark_filtering_set;
|
||||||
const struct ot_lookup_table *lookup_table;
|
const struct ot_lookup_table *lookup_table;
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
|
|
||||||
|
@ -4190,6 +4245,13 @@ static BOOL opentype_layout_init_lookup(const struct ot_gsubgpos_table *table, u
|
||||||
lookup_type = GET_BE_WORD(lookup_table->lookup_type);
|
lookup_type = GET_BE_WORD(lookup_table->lookup_type);
|
||||||
flags = GET_BE_WORD(lookup_table->flags);
|
flags = GET_BE_WORD(lookup_table->flags);
|
||||||
|
|
||||||
|
if (flags & LOOKUP_FLAG_USE_MARK_FILTERING_SET)
|
||||||
|
{
|
||||||
|
mark_filtering_set = table_read_be_word(&table->table, offset +
|
||||||
|
FIELD_OFFSET(struct ot_lookup_table, subtable[subtable_count]));
|
||||||
|
flags |= mark_filtering_set << 16;
|
||||||
|
}
|
||||||
|
|
||||||
lookup->index = lookup_index;
|
lookup->index = lookup_index;
|
||||||
lookup->type = lookup_type;
|
lookup->type = lookup_type;
|
||||||
lookup->flags = flags;
|
lookup->flags = flags;
|
||||||
|
@ -4473,7 +4535,7 @@ void opentype_layout_apply_gpos_features(struct scriptshaping_context *context,
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
|
|
||||||
if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
|
if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
|
||||||
lookup_is_glyph_match(context->glyph_infos[context->cur].props, lookup->flags))
|
lookup_is_glyph_match(context, context->cur, lookup->flags))
|
||||||
{
|
{
|
||||||
ret = opentype_layout_apply_gpos_lookup(context, lookup);
|
ret = opentype_layout_apply_gpos_lookup(context, lookup);
|
||||||
}
|
}
|
||||||
|
@ -4515,7 +4577,7 @@ static BOOL opentype_layout_apply_gsub_single_substitution(struct scriptshaping_
|
||||||
{
|
{
|
||||||
const struct ot_gsub_singlesubst_format1 *format1 = table_read_ensure(gsub, subtable_offset, sizeof(*format1));
|
const struct ot_gsub_singlesubst_format1 *format1 = table_read_ensure(gsub, subtable_offset, sizeof(*format1));
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(gsub, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -4527,7 +4589,7 @@ static BOOL opentype_layout_apply_gsub_single_substitution(struct scriptshaping_
|
||||||
const struct ot_gsub_singlesubst_format2 *format2 = table_read_ensure(gsub, subtable_offset,
|
const struct ot_gsub_singlesubst_format2 *format2 = table_read_ensure(gsub, subtable_offset,
|
||||||
FIELD_OFFSET(struct ot_gsub_singlesubst_format2, count) + count * sizeof(UINT16));
|
FIELD_OFFSET(struct ot_gsub_singlesubst_format2, count) + count * sizeof(UINT16));
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(gsub, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED || coverage_index >= count)
|
if (coverage_index == GLYPH_NOT_COVERED || coverage_index >= count)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -4612,7 +4674,7 @@ static BOOL opentype_layout_apply_gsub_mult_substitution(struct scriptshaping_co
|
||||||
|
|
||||||
if (format == 1)
|
if (format == 1)
|
||||||
{
|
{
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(gsub, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -4719,7 +4781,7 @@ static BOOL opentype_layout_apply_gsub_alt_substitution(struct scriptshaping_con
|
||||||
|
|
||||||
coverage = table_read_be_word(gsub, subtable_offset + FIELD_OFFSET(struct ot_gsub_altsubst_format1, coverage));
|
coverage = table_read_be_word(gsub, subtable_offset + FIELD_OFFSET(struct ot_gsub_altsubst_format1, coverage));
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(gsub, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -4797,7 +4859,7 @@ static BOOL opentype_layout_apply_gsub_lig_substitution(struct scriptshaping_con
|
||||||
|
|
||||||
coverage = table_read_be_word(gsub, subtable_offset + FIELD_OFFSET(struct ot_gsub_ligsubst_format1, coverage));
|
coverage = table_read_be_word(gsub, subtable_offset + FIELD_OFFSET(struct ot_gsub_ligsubst_format1, coverage));
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(gsub, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -4853,7 +4915,7 @@ static BOOL opentype_layout_context_match_input(struct scriptshaping_context *co
|
||||||
|
|
||||||
/* TODO: this only covers Format3 substitution */
|
/* TODO: this only covers Format3 substitution */
|
||||||
glyph = context->u.subst.glyphs[iter.pos];
|
glyph = context->u.subst.glyphs[iter.pos];
|
||||||
if (opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(input[i]), glyph) == GLYPH_NOT_COVERED)
|
if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(input[i]), glyph) == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
match_positions[i] = iter.pos;
|
match_positions[i] = iter.pos;
|
||||||
|
@ -4879,7 +4941,7 @@ static BOOL opentype_layout_context_match_backtrack(struct scriptshaping_context
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
glyph = context->u.subst.glyphs[iter.pos];
|
glyph = context->u.subst.glyphs[iter.pos];
|
||||||
if (opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(backtrack[i]), glyph) == GLYPH_NOT_COVERED)
|
if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(backtrack[i]), glyph) == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4903,7 +4965,7 @@ static BOOL opentype_layout_context_match_lookahead(struct scriptshaping_context
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
glyph = context->u.subst.glyphs[iter.pos];
|
glyph = context->u.subst.glyphs[iter.pos];
|
||||||
if (opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(lookahead[i]), glyph) == GLYPH_NOT_COVERED)
|
if (opentype_layout_is_glyph_covered(&context->table->table, subtable_offset + GET_BE_WORD(lookahead[i]), glyph) == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5010,7 +5072,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
|
||||||
coverage = table_read_be_word(table, subtable_offset +
|
coverage = table_read_be_word(table, subtable_offset +
|
||||||
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
|
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -5021,7 +5083,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
|
||||||
coverage = table_read_be_word(table, subtable_offset +
|
coverage = table_read_be_word(table, subtable_offset +
|
||||||
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
|
FIELD_OFFSET(struct ot_gsub_chaincontext_subst_format1, coverage));
|
||||||
|
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + coverage, glyph);
|
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + coverage, glyph);
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -5054,7 +5116,7 @@ static BOOL opentype_layout_apply_gsub_chain_context_substitution(struct scripts
|
||||||
lookup_records = table_read_ensure(table, offset, lookup_count * 2 * sizeof(*lookup_records));
|
lookup_records = table_read_ensure(table, offset, lookup_count * 2 * sizeof(*lookup_records));
|
||||||
|
|
||||||
if (input)
|
if (input)
|
||||||
coverage_index = opentype_layout_is_glyph_covered(context, subtable_offset + GET_BE_WORD(input[0]), glyph);
|
coverage_index = opentype_layout_is_glyph_covered(table, subtable_offset + GET_BE_WORD(input[0]), glyph);
|
||||||
|
|
||||||
if (coverage_index == GLYPH_NOT_COVERED)
|
if (coverage_index == GLYPH_NOT_COVERED)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -5222,7 +5284,7 @@ void opentype_layout_apply_gsub_features(struct scriptshaping_context *context,
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
|
|
||||||
if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
|
if ((context->glyph_infos[context->cur].mask & lookup->mask) &&
|
||||||
lookup_is_glyph_match(context->glyph_infos[context->cur].props, lookup->flags))
|
lookup_is_glyph_match(context, context->cur, lookup->flags))
|
||||||
{
|
{
|
||||||
ret = opentype_layout_apply_gsub_lookup(context, lookup);
|
ret = opentype_layout_apply_gsub_lookup(context, lookup);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue