[subset] GPOS Lookup Type 2: PairPos
This commit is contained in:
parent
e766783152
commit
1f0a9d9be9
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
test/subset/data/fonts/gpos2_1_font7.otf
Normal file
BIN
test/subset/data/fonts/gpos2_1_font7.otf
Normal file
Binary file not shown.
BIN
test/subset/data/fonts/gpos2_2_font5.otf
Normal file
BIN
test/subset/data/fonts/gpos2_2_font5.otf
Normal file
Binary file not shown.
12
test/subset/data/tests/layout.gpos2.tests
Normal file
12
test/subset/data/tests/layout.gpos2.tests
Normal file
@ -0,0 +1,12 @@
|
||||
FONTS:
|
||||
gpos2_1_font7.otf
|
||||
gpos2_2_font5.otf
|
||||
|
||||
PROFILES:
|
||||
keep-layout.txt
|
||||
keep-layout-retain-gids.txt
|
||||
|
||||
SUBSETS:
|
||||
!#
|
||||
!#%
|
||||
*
|
Loading…
Reference in New Issue
Block a user