[subset] GPOS Lookup Type 2: PairPos

This commit is contained in:
Qunxin Liu 2019-09-17 11:10:08 -07:00 committed by Garret Rieger
parent e766783152
commit 1f0a9d9be9
18 changed files with 139 additions and 6 deletions

View File

@ -558,7 +558,7 @@ struct SinglePosFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_set_t &glyphset = *c->plan->glyphset ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
@ -647,7 +647,7 @@ struct SinglePosFormat2
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
const hb_set_t &glyphset = *c->plan->glyphset ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned sub_length = valueFormat.get_len ();
@ -761,6 +761,18 @@ struct PairValueRecord
{
friend struct PairSet;
bool serialize (hb_serialize_context_t *c,
unsigned size,
const hb_map_t &glyph_map) const
{
TRACE_SERIALIZE (this);
auto *out = c->start_embed (*this);
if (unlikely (!c->extend_min (out))) return_trace (false);
out->secondGlyph = glyph_map[secondGlyph];
return_trace (c->copy (values, size));
}
protected:
HBGlyphID secondGlyph; /* GlyphID of second glyph in the
* pair--first glyph is listed in the
@ -846,6 +858,37 @@ struct PairSet
return_trace (false);
}
bool subset (hb_subset_context_t *c,
const ValueFormat valueFormats[2]) const
{
TRACE_SUBSET (this);
auto snap = c->serializer->snapshot ();
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->len = 0;
const hb_set_t &glyphset = *c->plan->glyphset ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
unsigned len1 = valueFormats[0].get_size ();
unsigned len2 = valueFormats[1].get_size ();
unsigned record_size = HBUINT16::static_size + len1 + len2;
const PairValueRecord *record = &firstPairValueRecord;
unsigned count = len, num = 0;
for (unsigned i = 0; i < count; i++)
{
if (!glyphset.has (record->secondGlyph)) continue;
if (record->serialize (c->serializer, record_size, glyph_map)) num++;
record = &StructAtOffset<const PairValueRecord> (record, record_size);
}
out->len = num;
if (!num) c->serializer->revert (snap);
return_trace (num);
}
struct sanitize_closure_t
{
const void *base;
@ -919,8 +962,43 @@ struct PairPosFormat1
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
// TODO(subset)
return_trace (false);
const hb_set_t &glyphset = *c->plan->glyphset ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
out->valueFormat[0] = valueFormat[0];
out->valueFormat[1] = valueFormat[1];
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ hb_zip (this+coverage, pairSet)
| hb_filter (glyphset, hb_first)
| hb_filter ([this, c, out] (const OffsetTo<PairSet>& _)
{
auto *o = out->pairSet.serialize_append (c->serializer);
if (unlikely (!o)) return false;
auto snap = c->serializer->snapshot ();
bool ret = o->serialize_subset (c, _, this, out, valueFormat);
if (!ret)
{
out->pairSet.pop ();
c->serializer->revert (snap);
}
return ret;
},
hb_second)
| hb_map (hb_first)
| hb_map (glyph_map)
| hb_sink (new_coverage)
;
out->coverage.serialize (c->serializer, out)
.serialize (c->serializer, new_coverage.iter ());
return_trace (bool (new_coverage));
}
bool sanitize (hb_sanitize_context_t *c) const
@ -1011,8 +1089,49 @@ struct PairPosFormat2
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
// TODO(subset)
return_trace (false);
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
out->format = format;
out->valueFormat1 = valueFormat1;
out->valueFormat2 = valueFormat2;
hb_map_t klass1_map;
out->classDef1.serialize_subset (c, classDef1, this, out, &klass1_map);
out->class1Count = klass1_map.get_population ();
hb_map_t klass2_map;
out->classDef2.serialize_subset (c, classDef2, this, out, &klass2_map);
out->class2Count = klass2_map.get_population ();
unsigned record_len = valueFormat1.get_len () + valueFormat2.get_len ();
+ hb_range ((unsigned) class1Count)
| hb_filter (klass1_map)
| hb_apply ([&] (const unsigned class1_idx)
{
+ hb_range ((unsigned) class2Count)
| hb_filter (klass2_map)
| hb_apply ([&] (const unsigned class2_idx)
{
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_len;
for (unsigned i = 0; i < record_len; i++)
c->serializer->copy (values[idx+i]);
})
;
})
;
const hb_set_t &glyphset = *c->plan->glyphset ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto it =
+ hb_iter (this+coverage)
| hb_filter (glyphset)
| hb_map_retains_sorting (glyph_map)
;
out->coverage.serialize (c->serializer, out).serialize (c->serializer, it);
return_trace (out->class1Count && out->class2Count && bool (it));
}
bool sanitize (hb_sanitize_context_t *c) const

View File

@ -14,6 +14,7 @@ EXTRA_DIST += \
expected/cff-japanese \
expected/layout \
expected/layout.gpos \
expected/layout.gpos2 \
expected/layout.gpos3 \
expected/layout.gsub6 \
expected/cmap14 \

View File

@ -6,6 +6,7 @@ TESTS = \
tests/cff-japanese.tests \
tests/layout.tests \
tests/layout.gpos.tests \
tests/layout.gpos2.tests \
tests/layout.gpos3.tests \
tests/layout.gsub6.tests \
tests/cmap14.tests \

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,12 @@
FONTS:
gpos2_1_font7.otf
gpos2_2_font5.otf
PROFILES:
keep-layout.txt
keep-layout-retain-gids.txt
SUBSETS:
!#
!#%
*