[subset] Add subsetting for GPOS Lookup Type 1: Single Adjustment Positioning Subtable
This commit is contained in:
parent
37572882e7
commit
321d5588d4
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,11 @@
|
||||||
|
FONTS:
|
||||||
|
gpos1_2_font.otf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
keep-layout-retain-gids.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
AC
|
||||||
|
CF
|
||||||
|
AF
|
||||||
|
*
|
Loading…
Reference in New Issue