[subset] GSUB5/GPOS7 Contextual Subst/Pos Subtbale Subsetting support
This commit is contained in:
parent
00aba82a6d
commit
8b5d3ebd96
@ -1144,7 +1144,7 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
|
||||
struct LookupRecord
|
||||
{
|
||||
LookupRecord* copy (hb_serialize_context_t *c,
|
||||
const hb_map_t *lookup_map)
|
||||
const hb_map_t *lookup_map) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->embed (*this);
|
||||
@ -1450,6 +1450,47 @@ struct Rule
|
||||
return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const hb_map_t *input_mapping, /* old->new glyphid or class mapping */
|
||||
const hb_map_t *lookup_map) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->start_embed (this);
|
||||
if (unlikely (!c->extend_min (out))) return_trace (false);
|
||||
|
||||
out->inputCount = inputCount;
|
||||
out->lookupCount = lookupCount;
|
||||
|
||||
const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
|
||||
for (const auto org : input)
|
||||
{
|
||||
HBUINT16 d;
|
||||
d = input_mapping->get (org);
|
||||
c->copy (d);
|
||||
}
|
||||
|
||||
const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
|
||||
(inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
|
||||
for (unsigned i = 0; i < (unsigned) lookupCount; i++)
|
||||
c->copy (lookupRecord[i], lookup_map);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const hb_map_t *lookup_map,
|
||||
const hb_map_t *klass_map = nullptr) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_array_t<const HBUINT16> input = inputZ.as_array ((inputCount ? inputCount - 1 : 0));
|
||||
if (!input.length) return_trace (false);
|
||||
|
||||
const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
|
||||
if (!hb_all (input, mapping)) return_trace (false);
|
||||
return_trace (serialize (c->serializer, mapping, lookup_map));
|
||||
}
|
||||
|
||||
public:
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
@ -1546,6 +1587,36 @@ struct RuleSet
|
||||
;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const hb_map_t *lookup_map,
|
||||
const hb_map_t *klass_map = nullptr) 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);
|
||||
|
||||
for (const OffsetTo<Rule>& _ : rule)
|
||||
{
|
||||
if (!_) continue;
|
||||
auto *o = out->rule.serialize_append (c->serializer);
|
||||
if (unlikely (!o)) continue;
|
||||
|
||||
auto o_snap = c->serializer->snapshot ();
|
||||
if (!o->serialize_subset (c, _, this, lookup_map, klass_map))
|
||||
{
|
||||
out->rule.pop ();
|
||||
c->serializer->revert (o_snap);
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = bool (out->rule);
|
||||
if (!ret) c->serializer->revert (snap);
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
@ -1648,8 +1719,26 @@ struct ContextFormat1
|
||||
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;
|
||||
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ hb_zip (this+coverage, ruleSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (subset_offset_array (c, out->ruleSet, this, lookup_map), 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
|
||||
@ -1774,8 +1863,45 @@ struct ContextFormat2
|
||||
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;
|
||||
if (unlikely (!out->coverage.serialize_subset (c, coverage, this)))
|
||||
return_trace (false);
|
||||
|
||||
hb_map_t klass_map;
|
||||
out->classDef.serialize_subset (c, classDef, this, &klass_map);
|
||||
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
bool ret = true;
|
||||
unsigned non_zero_index = 0, index = 0;
|
||||
for (const hb_pair_t<unsigned, const OffsetTo<RuleSet>&>& _ : + hb_enumerate (ruleSet)
|
||||
| hb_filter (klass_map, hb_first))
|
||||
{
|
||||
auto *o = out->ruleSet.serialize_append (c->serializer);
|
||||
if (unlikely (!o))
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
|
||||
non_zero_index = index;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!ret) return_trace (ret);
|
||||
|
||||
//prune empty trailing ruleSets
|
||||
--index;
|
||||
while (index > non_zero_index)
|
||||
{
|
||||
out->ruleSet.pop ();
|
||||
index--;
|
||||
}
|
||||
|
||||
return_trace (bool (out->ruleSet));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
@ -1886,8 +2012,28 @@ struct ContextFormat3
|
||||
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->glyphCount = glyphCount;
|
||||
out->lookupCount = lookupCount;
|
||||
|
||||
const hb_array_t<const OffsetTo<Coverage>> coverages = coverageZ.as_array (glyphCount);
|
||||
|
||||
for (const OffsetTo<Coverage>& offset : coverages)
|
||||
{
|
||||
auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size);
|
||||
if (unlikely (!o)) return_trace (false);
|
||||
if (!o->serialize_subset (c, offset, this)) return_trace (false);
|
||||
}
|
||||
|
||||
const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
|
||||
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
|
||||
for (unsigned i = 0; i < (unsigned) lookupCount; i++)
|
||||
c->serializer->copy (lookupRecord[i], lookup_map);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -89,7 +89,7 @@ _subset (hb_subset_plan_t *plan)
|
||||
retry:
|
||||
hb_serialize_context_t serializer ((void *) buf, buf_size);
|
||||
serializer.start_serialize<TableType> ();
|
||||
hb_subset_context_t c (source_blob, plan, &serializer);
|
||||
hb_subset_context_t c (source_blob, plan, &serializer, tag);
|
||||
bool needed = table->subset (&c);
|
||||
if (serializer.ran_out_of_room)
|
||||
{
|
||||
|
@ -57,14 +57,17 @@ struct hb_subset_context_t :
|
||||
hb_blob_t *source_blob;
|
||||
hb_subset_plan_t *plan;
|
||||
hb_serialize_context_t *serializer;
|
||||
hb_tag_t table_tag;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_subset_context_t (hb_blob_t *source_blob_,
|
||||
hb_subset_plan_t *plan_,
|
||||
hb_serialize_context_t *serializer_) :
|
||||
source_blob (source_blob_),
|
||||
hb_serialize_context_t *serializer_,
|
||||
hb_tag_t table_tag_) :
|
||||
source_blob (source_blob_),
|
||||
plan (plan_),
|
||||
serializer (serializer_),
|
||||
table_tag (table_tag_),
|
||||
debug_depth (0) {}
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@ EXTRA_DIST += \
|
||||
expected/layout.gsub3 \
|
||||
expected/layout.gsub6 \
|
||||
expected/layout.gdef \
|
||||
expected/layout.context \
|
||||
expected/cmap \
|
||||
expected/cmap14 \
|
||||
expected/sbix \
|
||||
|
@ -21,6 +21,7 @@ DISABLED_TESTS = \
|
||||
tests/layout.gsub3.tests \
|
||||
tests/layout.gsub6.tests \
|
||||
tests/layout.gdef.tests \
|
||||
tests/layout.context.tests \
|
||||
$(NULL)
|
||||
|
||||
XFAIL_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.
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.
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/gpos_context1_multiple_subrules_f1.otf
Normal file
BIN
test/subset/data/fonts/gpos_context1_multiple_subrules_f1.otf
Normal file
Binary file not shown.
BIN
test/subset/data/fonts/gpos_context2_multiple_subrules_f1.otf
Normal file
BIN
test/subset/data/fonts/gpos_context2_multiple_subrules_f1.otf
Normal file
Binary file not shown.
BIN
test/subset/data/fonts/gpos_context3_simple_f1.otf
Normal file
BIN
test/subset/data/fonts/gpos_context3_simple_f1.otf
Normal file
Binary file not shown.
15
test/subset/data/tests/layout.context.tests
Normal file
15
test/subset/data/tests/layout.context.tests
Normal file
@ -0,0 +1,15 @@
|
||||
FONTS:
|
||||
gpos_context1_multiple_subrules_f1.otf
|
||||
gpos_context2_multiple_subrules_f1.otf
|
||||
gpos_context3_simple_f1.otf
|
||||
|
||||
PROFILES:
|
||||
keep-layout.txt
|
||||
keep-layout-retain-gids.txt
|
||||
|
||||
SUBSETS:
|
||||
A
|
||||
AB
|
||||
AC
|
||||
ABC
|
||||
*
|
Loading…
Reference in New Issue
Block a user