[subset] Add subsetting for GPOS Lookup Type 1: Single Adjustment Positioning Subtable

This commit is contained in:
Qunxin Liu 2019-07-02 16:30:57 -07:00 committed by Garret Rieger
parent 37572882e7
commit 321d5588d4
9 changed files with 166 additions and 4 deletions

View File

@ -236,6 +236,11 @@ struct ValueFormat : HBUINT16
} }
}; };
template<typename Iterator>
static inline void SinglePos_serialize (hb_serialize_context_t *c,
Iterator it,
ValueFormat valFormat);
struct AnchorFormat1 struct AnchorFormat1
{ {
@ -496,11 +501,52 @@ struct SinglePosFormat1
return_trace (true); return_trace (true);
} }
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
ValueFormat valFormat)
{
if (unlikely (!c->extend_min (*this))) return;
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
auto vals = hb_second (*it);
+ vals
| hb_apply ([=] (const Value& _)
{
c->copy (_);
})
;
auto glyphs =
+ it
| hb_map_retains_sorting (hb_first)
;
coverage.serialize (c, this).serialize (c, glyphs);
}
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
// TODO(subset) const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
return_trace (false); const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned length = valueFormat.get_len ();
auto it =
+ hb_iter (this+coverage)
| hb_filter (glyphset)
| hb_map_retains_sorting ([&] (hb_codepoint_t p)
{
return hb_pair (glyph_map[p], values.as_array (length));
})
;
bool ret = bool (it);
SinglePos_serialize (c->serializer, it, valueFormat);
return_trace (ret);
} }
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
@ -552,11 +598,58 @@ struct SinglePosFormat2
return_trace (true); return_trace (true);
} }
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
ValueFormat valFormat)
{
if (unlikely (!c->extend_min (*this))) return;
if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
+ it
| hb_map (hb_second)
| hb_apply ([=] (hb_array_t<const Value> val_iter)
{
+ val_iter
| hb_apply ([=] (const Value& _)
{
c->copy (_);
})
;
})
;
auto glyphs =
+ it
| hb_map_retains_sorting (hb_first)
;
coverage.serialize (c, this).serialize (c, glyphs);
}
bool subset (hb_subset_context_t *c) const bool subset (hb_subset_context_t *c) const
{ {
TRACE_SUBSET (this); TRACE_SUBSET (this);
// TODO(subset) const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
return_trace (false); const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned sub_length = valueFormat.get_len ();
unsigned total_length = (unsigned)valueCount * sub_length;
auto it =
+ hb_zip (this+coverage, hb_range ((unsigned) valueCount))
| hb_filter (glyphset, hb_first)
| hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
{
return hb_pair (glyph_map[_.first], values.as_array (total_length).sub_array (_.second * sub_length, sub_length));
})
;
bool ret = bool (it);
SinglePos_serialize (c->serializer, it, valueFormat);
return_trace (ret);
} }
bool sanitize (hb_sanitize_context_t *c) const bool sanitize (hb_sanitize_context_t *c) const
@ -583,6 +676,55 @@ struct SinglePosFormat2
struct SinglePos struct SinglePos
{ {
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
unsigned get_format (Iterator glyph_val_iter_pairs)
{
unsigned subset_format = 1;
hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
+ glyph_val_iter_pairs
| hb_map (hb_second)
| hb_apply ([&] (hb_array_t<const Value> val_iter)
{
+ hb_zip (val_iter, first_val_iter)
| hb_apply ([&] (const hb_pair_t<Value, Value>& _)
{
if (_.first != _.second)
{
subset_format = 2;
return;
}
})
;
})
;
return subset_format;
}
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator glyph_val_iter_pairs,
ValueFormat valFormat)
{
if (unlikely (!c->extend_min (u.format))) return;
unsigned format = 2;
if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs);
u.format = format;
switch (u.format) {
case 1: u.format1.serialize (c, glyph_val_iter_pairs, valFormat);
return;
case 2: u.format2.serialize (c, glyph_val_iter_pairs, valFormat);
return;
default:return;
}
}
template <typename context_t, typename ...Ts> template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{ {
@ -603,6 +745,13 @@ struct SinglePos
} u; } u;
}; };
template<typename Iterator>
static inline void
SinglePos_serialize (hb_serialize_context_t *c,
Iterator it,
ValueFormat valFormat)
{ c->start_embed<SinglePos> ()->serialize (c, it, valFormat); }
struct PairValueRecord struct PairValueRecord
{ {

View File

@ -13,6 +13,7 @@ EXTRA_DIST += \
expected/japanese \ expected/japanese \
expected/cff-japanese \ expected/cff-japanese \
expected/layout \ expected/layout \
expected/layout.gpos \
fonts \ fonts \
profiles \ profiles \
$(NULL) $(NULL)

View File

@ -5,6 +5,7 @@ TESTS = \
tests/japanese.tests \ tests/japanese.tests \
tests/cff-japanese.tests \ tests/cff-japanese.tests \
tests/layout.tests \ tests/layout.tests \
tests/layout.gpos.tests \
$(NULL) $(NULL)
XFAIL_TESTS = \ XFAIL_TESTS = \

Binary file not shown.

View File

@ -0,0 +1,11 @@
FONTS:
gpos1_2_font.otf
PROFILES:
keep-layout-retain-gids.txt
SUBSETS:
AC
CF
AF
*