[subset] subsetting cmap14
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index c4cbd06..7678180 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -676,6 +676,70 @@
}
}
+ DefaultUVS* copy (hb_serialize_context_t *c,
+ const hb_set_t *unicodes) const
+ {
+ DefaultUVS *out = c->start_embed<DefaultUVS> ();
+ if (unlikely (!out)) return nullptr;
+ auto snap = c->snapshot ();
+
+ HBUINT32 len;
+ len = 0;
+ if (unlikely (!c->copy<HBUINT32> (len))) return nullptr;
+ unsigned init_len = c->length ();
+
+ hb_codepoint_t lastCode = HB_MAP_VALUE_INVALID;
+ int count = -1;
+
+ + as_array ()
+ | hb_apply ([&] (const UnicodeValueRange& _)
+ {
+ + hb_range ((unsigned)_.additionalCount + 1)
+ | hb_apply ([&] (const unsigned addcnt)
+ {
+ unsigned curEntry = (unsigned)_.startUnicodeValue + addcnt;
+ if (hb_set_has (unicodes, curEntry))
+ {
+ count += 1;
+ if (lastCode == HB_MAP_VALUE_INVALID)
+ {
+ lastCode = curEntry;
+ } else if (lastCode + count != curEntry)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = lastCode;
+ rec.additionalCount = count - 1;
+ c->copy<UnicodeValueRange> (rec);
+
+ lastCode = curEntry;
+ count = 0;
+ }
+ }
+ })
+ ;
+ })
+ ;
+
+ if (lastCode != HB_MAP_VALUE_INVALID)
+ {
+ UnicodeValueRange rec;
+ rec.startUnicodeValue = lastCode;
+ rec.additionalCount = count;
+ c->copy<UnicodeValueRange> (rec);
+ }
+
+ if (c->length () - init_len == 0)
+ {
+ c->revert (snap);
+ return nullptr;
+ }
+ else
+ {
+ if (unlikely (!c->check_assign (out->len, (c->length () - init_len) / UnicodeValueRange::static_size))) return nullptr;
+ return out;
+ }
+ }
+
public:
DEFINE_SIZE_ARRAY (4, *this);
};
@@ -718,6 +782,41 @@
;
}
+ NonDefaultUVS* copy (hb_serialize_context_t *c,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map) const
+ {
+ NonDefaultUVS *out = c->start_embed<NonDefaultUVS> ();
+ if (unlikely (!out)) return nullptr;
+
+ auto it =
+ + as_array ()
+ | hb_filter ([&] (const UVSMapping& _)
+ {
+ return hb_set_has (unicodes, _.unicodeValue) || hb_set_has (glyphs, _.glyphID);
+ })
+ ;
+
+ if (!it) return nullptr;
+
+ HBUINT32 len;
+ len = it.len ();
+ if (unlikely (!c->copy<HBUINT32> (len))) return nullptr;
+
+ + it
+ | hb_apply ([&] (const UVSMapping& _)
+ {
+ UVSMapping mapping;
+ mapping.unicodeValue = _.unicodeValue;
+ mapping.glyphID = glyph_map->get (_.glyphID);
+ c->copy<UVSMapping> (mapping);
+ })
+ ;
+
+ return out;
+ }
+
public:
DEFINE_SIZE_ARRAY (4, *this);
};
@@ -758,6 +857,52 @@
nonDefaultUVS.sanitize (c, base));
}
+ VariationSelectorRecord* copy (hb_serialize_context_t *c,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map,
+ const void *src_base,
+ const void *dst_base) const
+ {
+ auto snap = c->snapshot ();
+ auto *out = c->embed<VariationSelectorRecord> (*this);
+ if (unlikely (!out)) return nullptr;
+
+ out->defaultUVS = 0;
+ out->nonDefaultUVS = 0;
+
+ bool drop = true;
+
+ if (defaultUVS != 0)
+ {
+ c->push ();
+ if (c->copy (src_base+defaultUVS, unicodes))
+ {
+ c->add_link (out->defaultUVS, c->pop_pack (), dst_base);
+ drop = false;
+ }
+ else c->pop_discard ();
+ }
+
+ if (nonDefaultUVS != 0)
+ {
+ c->push ();
+ if (c->copy (src_base+nonDefaultUVS, unicodes, glyphs, glyph_map))
+ {
+ c->add_link (out->nonDefaultUVS, c->pop_pack (), dst_base);
+ drop = false;
+ }
+ else c->pop_discard ();
+ }
+
+ if (drop)
+ {
+ c->revert (snap);
+ return nullptr;
+ }
+ else return out;
+ }
+
HBUINT24 varSelector; /* Variation selector. */
LOffsetTo<DefaultUVS>
defaultUVS; /* Offset to Default UVS Table. May be 0. */
@@ -788,11 +933,44 @@
record.bsearch (variation_selector).collect_unicodes (out, this);
}
+ void serialize (hb_serialize_context_t *c,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map,
+ const void *src_base)
+ {
+ auto snap = c->snapshot ();
+ unsigned table_initpos = c->length ();
+ const char* init_tail = c->tail;
+
+ if (unlikely (!c->extend_min (*this))) return;
+ this->format = 14;
+
+ const CmapSubtableFormat14 *src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (src_base);
+ + hb_iter (src_tbl->record)
+ | hb_apply ([&] (const VariationSelectorRecord& _)
+ {
+ c->copy (_, unicodes, glyphs, glyph_map, src_base, this);
+ })
+ ;
+
+ if (c->length () - table_initpos == CmapSubtableFormat14::min_size)
+ {
+ c->revert (snap);
+ }
+ else
+ {
+ int tail_len = init_tail - c->tail;
+ c->check_assign (this->length, c->length () - table_initpos + tail_len);
+ c->check_assign (this->record.len, (c->length () - table_initpos - CmapSubtableFormat14::min_size) / VariationSelectorRecord::static_size);
+ }
+ }
+
void closure_glyphs (const hb_set_t *unicodes,
hb_set_t *glyphset) const
{
+ hb_iter (record)
- | hb_filter ([&] (const VariationSelectorRecord& _) { return _.nonDefaultUVS != 0 && hb_set_has (unicodes, _.varSelector); })
+ | hb_filter ([&] (const VariationSelectorRecord& _) { return _.nonDefaultUVS != 0; })
| hb_map (&VariationSelectorRecord::nonDefaultUVS)
| hb_map (hb_add (this))
| hb_apply ([=] (const NonDefaultUVS& _) { _.closure_glyphs (unicodes, glyphset); })
@@ -852,11 +1030,16 @@
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
- unsigned format)
+ unsigned format,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map,
+ const void *src_base)
{
switch (format) {
case 4: u.format4.serialize (c, it); return;
case 12: u.format12.serialize (c, it); return;
+ case 14: u.format14.serialize (c, unicodes, glyphs, glyph_map, src_base); return;
default: return;
}
}
@@ -915,12 +1098,17 @@
template<typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
EncodingRecord* copy (hb_serialize_context_t *c,
- Iterator it,
- unsigned format,
- void *base,
- /* INOUT */ unsigned *objidx) const
+ Iterator it,
+ unsigned format,
+ const void *src_base,
+ const void *dst_base,
+ /* INOUT */ unsigned *objidx,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map) const
{
TRACE_SERIALIZE (this);
+ auto snap = c->snapshot ();
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
out->subtable = 0;
@@ -929,13 +1117,21 @@
{
CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
unsigned origin_length = c->length ();
- cmapsubtable->serialize (c, it, format);
+ cmapsubtable->serialize (c, it, format, unicodes, glyphs, glyph_map, &(src_base+subtable));
if (c->length () - origin_length > 0) *objidx = c->pop_pack ();
else c->pop_discard ();
}
- c->add_link (out->subtable, *objidx, base);
- return_trace (out);
+ if (*objidx == 0)
+ {
+ c->revert (snap);
+ return_trace (nullptr);
+ }
+ else
+ {
+ c->add_link (out->subtable, *objidx, dst_base);
+ return_trace (out);
+ }
}
HBUINT16 platformID; /* Platform ID. */
@@ -950,27 +1146,33 @@
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ template<typename Iterator, typename EncodingRecIter,
+ hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
- Iterator it,
- const EncodingRecord *unicode_bmp,
- const EncodingRecord *unicode_ucs4,
- const EncodingRecord *ms_bmp,
- const EncodingRecord *ms_ucs4)
+ Iterator it,
+ EncodingRecIter encodingrec_iter,
+ const void *src_base,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map)
{
if (unlikely (!c->extend_min ((*this)))) return;
this->version = 0;
- unsigned numTables = (unicode_bmp ? 1 : 0) + (unicode_ucs4 ? 1 : 0) + (ms_bmp ? 1 : 0) + (ms_ucs4 ? 1 : 0);
- if (unlikely (!c->check_assign(this->encodingRecord.len, numTables))) return;
+ unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
- unsigned format4objidx = 0, format12objidx = 0;
- if (unicode_bmp) c->copy (unicode_bmp, it, 4u, this, &format4objidx);
- if (unicode_ucs4) c->copy (unicode_ucs4, it, 12u, this, &format12objidx);
- if (ms_bmp) c->copy (ms_bmp, it, 4u, this, &format4objidx);
- if (ms_ucs4) c->copy (ms_ucs4, it, 12u, this, &format12objidx);
+ + encodingrec_iter
+ | hb_apply ([&] (const EncodingRecord& _)
+ {
+ unsigned format = (src_base+_.subtable).u.format;
+ if (format == 4) c->copy (_, it, 4u, src_base, this, &format4objidx, unicodes, glyphs, glyph_map);
+ else if (format == 12) c->copy (_, it, 12u, src_base, this, &format12objidx, unicodes, glyphs, glyph_map);
+ else if (format == 14) c->copy (_, it, 14u, src_base, this, &format14objidx, unicodes, glyphs, glyph_map);
+ })
+ ;
+
+ c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size);
}
void closure_glyphs (const hb_set_t *unicodes,
@@ -991,12 +1193,45 @@
cmap *cmap_prime = c->serializer->start_embed<cmap> ();
if (unlikely (!c->serializer->check_success (cmap_prime))) return_trace (false);
- const EncodingRecord *unicode_bmp = find_encodingrec (0, 3);
- const EncodingRecord *unicode_ucs4 = find_encodingrec (0, 4);
- const EncodingRecord *ms_bmp = find_encodingrec (3, 1);
- const EncodingRecord *ms_ucs4 = find_encodingrec (3, 10);
- bool has_format12 = find_subtable (12);
+ const EncodingRecord *unicode_bmp= nullptr, *unicode_ucs4 = nullptr, *ms_bmp = nullptr, *ms_ucs4 = nullptr;
+ bool has_format12 = false, has_format14 = false;
+
+ auto encodingrec_iter =
+ + hb_iter (encodingRecord)
+ | hb_filter ([&] (const EncodingRecord& _)
+ {
+ unsigned format = (this + _.subtable).u.format;
+ if (format == 12) has_format12 = true;
+ if (format == 14) has_format14 = true;
+ const EncodingRecord *table = hb_addressof (_);
+ if (_.platformID == 0 && _.encodingID == 3)
+ {
+ unicode_bmp = table;
+ return true;
+ }
+ else if (_.platformID == 0 && _.encodingID == 4)
+ {
+ unicode_ucs4 = table;
+ return true;
+ }
+ else if (_.platformID == 3 && _.encodingID == 1)
+ {
+ ms_bmp = table;
+ return true;
+ }
+ else if (_.platformID == 3 && _.encodingID == 10)
+ {
+ ms_ucs4 = table;
+ return true;
+ }
+ else if (format == 14) return true;
+ else return false;
+ })
+ ;
+
+
+ if (unlikely (!encodingrec_iter.len ())) return_trace (false);
if (unlikely (!unicode_bmp && !ms_bmp)) return_trace (false);
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
@@ -1014,7 +1249,7 @@
})
;
- cmap_prime->serialize (c->serializer, it, unicode_bmp, unicode_ucs4, ms_bmp, ms_ucs4);
+ cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan->unicodes, c->plan->_glyphset, c->plan->glyph_map);
return_trace (true);
}