[subset] Cache per subtable cmap unicode mappings.
This commit is contained in:
parent
d2a2670e54
commit
7a004a7ac2
|
@ -1474,15 +1474,54 @@ struct EncodingRecord
|
||||||
DEFINE_SIZE_STATIC (8);
|
DEFINE_SIZE_STATIC (8);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cmap;
|
||||||
|
|
||||||
struct SubtableUnicodesCache {
|
struct SubtableUnicodesCache {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
hb_blob_ptr_t<cmap> base_blob;
|
||||||
const char* base;
|
const char* base;
|
||||||
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> cached_unicodes;
|
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> cached_unicodes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
static SubtableUnicodesCache* create (hb_blob_ptr_t<cmap> source_table)
|
||||||
|
{
|
||||||
|
SubtableUnicodesCache* cache =
|
||||||
|
(SubtableUnicodesCache*) hb_malloc (sizeof(SubtableUnicodesCache));
|
||||||
|
new (cache) SubtableUnicodesCache (source_table);
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy (void* value) {
|
||||||
|
if (!value) return;
|
||||||
|
|
||||||
|
SubtableUnicodesCache* cache = (SubtableUnicodesCache*) value;
|
||||||
|
cache->~SubtableUnicodesCache ();
|
||||||
|
hb_free (cache);
|
||||||
|
}
|
||||||
|
|
||||||
SubtableUnicodesCache(const void* cmap_base)
|
SubtableUnicodesCache(const void* cmap_base)
|
||||||
: base ((const char *) cmap_base), cached_unicodes () {}
|
: base_blob(),
|
||||||
|
base ((const char*) cmap_base),
|
||||||
|
cached_unicodes ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
SubtableUnicodesCache(hb_blob_ptr_t<cmap> base_blob_)
|
||||||
|
: base_blob(base_blob_),
|
||||||
|
base ((const char *) base_blob.get()),
|
||||||
|
cached_unicodes ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
~SubtableUnicodesCache()
|
||||||
|
{
|
||||||
|
base_blob.destroy ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool same_base(const void* other)
|
||||||
|
{
|
||||||
|
return other == (const void*) base;
|
||||||
|
}
|
||||||
|
|
||||||
hb_set_t* set_for (const EncodingRecord* record)
|
hb_set_t* set_for (const EncodingRecord* record)
|
||||||
{
|
{
|
||||||
|
@ -1523,13 +1562,30 @@ struct cmap
|
||||||
{
|
{
|
||||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
|
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
|
||||||
|
|
||||||
|
|
||||||
|
static SubtableUnicodesCache* create_filled_cache(hb_blob_ptr_t<cmap> source_table) {
|
||||||
|
const cmap* cmap = source_table.get();
|
||||||
|
auto it =
|
||||||
|
+ hb_iter (cmap->encodingRecord)
|
||||||
|
| hb_filter ([&](const EncodingRecord& _) {
|
||||||
|
return cmap::filter_encoding_records_for_subset (cmap, _);
|
||||||
|
})
|
||||||
|
;
|
||||||
|
|
||||||
|
SubtableUnicodesCache* cache = SubtableUnicodesCache::create(source_table);
|
||||||
|
for (const EncodingRecord& _ : it)
|
||||||
|
cache->set_for(&_); // populate the cache for this encoding record.
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Iterator, typename EncodingRecIter,
|
template<typename Iterator, typename EncodingRecIter,
|
||||||
hb_requires (hb_is_iterator (EncodingRecIter))>
|
hb_requires (hb_is_iterator (EncodingRecIter))>
|
||||||
bool serialize (hb_serialize_context_t *c,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
Iterator it,
|
Iterator it,
|
||||||
EncodingRecIter encodingrec_iter,
|
EncodingRecIter encodingrec_iter,
|
||||||
const void *base,
|
const void *base,
|
||||||
const hb_subset_plan_t *plan,
|
hb_subset_plan_t *plan,
|
||||||
bool drop_format_4 = false)
|
bool drop_format_4 = false)
|
||||||
{
|
{
|
||||||
if (unlikely (!c->extend_min ((*this)))) return false;
|
if (unlikely (!c->extend_min ((*this)))) return false;
|
||||||
|
@ -1538,7 +1594,14 @@ struct cmap
|
||||||
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
|
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
|
||||||
auto snap = c->snapshot ();
|
auto snap = c->snapshot ();
|
||||||
|
|
||||||
SubtableUnicodesCache unicodes_cache (base);
|
SubtableUnicodesCache local_unicodes_cache (base);
|
||||||
|
SubtableUnicodesCache* unicodes_cache = &local_unicodes_cache;
|
||||||
|
|
||||||
|
if (plan->accelerator &&
|
||||||
|
plan->accelerator->cmap_cache &&
|
||||||
|
plan->accelerator->cmap_cache->same_base (base))
|
||||||
|
unicodes_cache = plan->accelerator->cmap_cache;
|
||||||
|
|
||||||
for (const EncodingRecord& _ : encodingrec_iter)
|
for (const EncodingRecord& _ : encodingrec_iter)
|
||||||
{
|
{
|
||||||
if (c->in_error ())
|
if (c->in_error ())
|
||||||
|
@ -1547,7 +1610,7 @@ struct cmap
|
||||||
unsigned format = (base+_.subtable).u.format;
|
unsigned format = (base+_.subtable).u.format;
|
||||||
if (format != 4 && format != 12 && format != 14) continue;
|
if (format != 4 && format != 12 && format != 14) continue;
|
||||||
|
|
||||||
hb_set_t* unicodes_set = unicodes_cache.set_for (&_);
|
hb_set_t* unicodes_set = unicodes_cache->set_for (&_);
|
||||||
|
|
||||||
if (!drop_format_4 && format == 4)
|
if (!drop_format_4 && format == 4)
|
||||||
{
|
{
|
||||||
|
@ -1566,7 +1629,7 @@ struct cmap
|
||||||
|
|
||||||
else if (format == 12)
|
else if (format == 12)
|
||||||
{
|
{
|
||||||
if (_can_drop (_, *unicodes_set, base, unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue;
|
if (_can_drop (_, *unicodes_set, base, *unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue;
|
||||||
c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
|
c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
|
||||||
}
|
}
|
||||||
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
|
||||||
|
@ -1653,17 +1716,9 @@ struct cmap
|
||||||
|
|
||||||
auto encodingrec_iter =
|
auto encodingrec_iter =
|
||||||
+ hb_iter (encodingRecord)
|
+ hb_iter (encodingRecord)
|
||||||
| hb_filter ([&] (const EncodingRecord& _)
|
| hb_filter ([&](const EncodingRecord& _) {
|
||||||
{
|
return cmap::filter_encoding_records_for_subset (this, _);
|
||||||
if ((_.platformID == 0 && _.encodingID == 3) ||
|
})
|
||||||
(_.platformID == 0 && _.encodingID == 4) ||
|
|
||||||
(_.platformID == 3 && _.encodingID == 1) ||
|
|
||||||
(_.platformID == 3 && _.encodingID == 10) ||
|
|
||||||
(this + _.subtable).u.format == 14)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
;
|
;
|
||||||
|
|
||||||
if (unlikely (!encodingrec_iter.len ())) return_trace (false);
|
if (unlikely (!encodingrec_iter.len ())) return_trace (false);
|
||||||
|
@ -1692,7 +1747,11 @@ struct cmap
|
||||||
{ return (_.second != HB_MAP_VALUE_INVALID); })
|
{ return (_.second != HB_MAP_VALUE_INVALID); })
|
||||||
;
|
;
|
||||||
|
|
||||||
return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan));
|
return_trace (cmap_prime->serialize (c->serializer,
|
||||||
|
it,
|
||||||
|
encodingrec_iter,
|
||||||
|
this,
|
||||||
|
c->plan));
|
||||||
}
|
}
|
||||||
|
|
||||||
const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
|
const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
|
||||||
|
@ -1928,6 +1987,19 @@ struct cmap
|
||||||
encodingRecord.sanitize (c, this));
|
encodingRecord.sanitize (c, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static bool filter_encoding_records_for_subset(const cmap* cmap,
|
||||||
|
const EncodingRecord& _)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(_.platformID == 0 && _.encodingID == 3) ||
|
||||||
|
(_.platformID == 0 && _.encodingID == 4) ||
|
||||||
|
(_.platformID == 3 && _.encodingID == 1) ||
|
||||||
|
(_.platformID == 3 && _.encodingID == 10) ||
|
||||||
|
(cmap + _.subtable).u.format == 14;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HBUINT16 version; /* Table version number (0). */
|
HBUINT16 version; /* Table version number (0). */
|
||||||
SortedArray16Of<EncodingRecord>
|
SortedArray16Of<EncodingRecord>
|
||||||
|
|
|
@ -39,6 +39,10 @@ namespace CFF {
|
||||||
struct cff_subset_accelerator_t;
|
struct cff_subset_accelerator_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace OT {
|
||||||
|
struct SubtableUnicodesCache;
|
||||||
|
};
|
||||||
|
|
||||||
struct hb_subset_accelerator_t
|
struct hb_subset_accelerator_t
|
||||||
{
|
{
|
||||||
static hb_user_data_key_t* user_data_key()
|
static hb_user_data_key_t* user_data_key()
|
||||||
|
@ -64,6 +68,9 @@ struct hb_subset_accelerator_t
|
||||||
if (accel->cff_accelerator && accel->destroy_cff_accelerator)
|
if (accel->cff_accelerator && accel->destroy_cff_accelerator)
|
||||||
accel->destroy_cff_accelerator ((void*) accel->cff_accelerator);
|
accel->destroy_cff_accelerator ((void*) accel->cff_accelerator);
|
||||||
|
|
||||||
|
if (accel->cmap_cache && accel->destroy_cmap_cache)
|
||||||
|
accel->destroy_cmap_cache ((void*) accel->cmap_cache);
|
||||||
|
|
||||||
accel->~hb_subset_accelerator_t ();
|
accel->~hb_subset_accelerator_t ();
|
||||||
hb_free (accel);
|
hb_free (accel);
|
||||||
}
|
}
|
||||||
|
@ -71,17 +78,23 @@ struct hb_subset_accelerator_t
|
||||||
hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_,
|
hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_,
|
||||||
const hb_set_t& unicodes_)
|
const hb_set_t& unicodes_)
|
||||||
: unicode_to_gid(unicode_to_gid_), unicodes(unicodes_),
|
: unicode_to_gid(unicode_to_gid_), unicodes(unicodes_),
|
||||||
has_seac(false), cff_accelerator(nullptr), destroy_cff_accelerator(nullptr) {}
|
cmap_cache(nullptr), destroy_cmap_cache(nullptr),
|
||||||
|
has_seac(false), cff_accelerator(nullptr), destroy_cff_accelerator(nullptr)
|
||||||
|
|
||||||
|
{}
|
||||||
|
|
||||||
// Generic
|
// Generic
|
||||||
const hb_map_t unicode_to_gid;
|
const hb_map_t unicode_to_gid;
|
||||||
const hb_set_t unicodes;
|
const hb_set_t unicodes;
|
||||||
|
OT::SubtableUnicodesCache* cmap_cache;
|
||||||
|
hb_destroy_func_t destroy_cmap_cache;
|
||||||
|
|
||||||
// CFF
|
// CFF
|
||||||
bool has_seac;
|
bool has_seac;
|
||||||
CFF::cff_subset_accelerator_t* cff_accelerator;
|
CFF::cff_subset_accelerator_t* cff_accelerator;
|
||||||
hb_destroy_func_t destroy_cff_accelerator;
|
hb_destroy_func_t destroy_cff_accelerator;
|
||||||
|
|
||||||
|
// TODO(garretrieger): see if we can make the cff_accelerator and cmap_cache const
|
||||||
// TODO(garretrieger): cumulative glyf checksum map
|
// TODO(garretrieger): cumulative glyf checksum map
|
||||||
// TODO(garretrieger): sanitized table cache.
|
// TODO(garretrieger): sanitized table cache.
|
||||||
|
|
||||||
|
|
|
@ -514,6 +514,11 @@ static void _attach_accelerator_data (hb_subset_plan_t* plan,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate caches that need access to the final tables.
|
||||||
|
hb_blob_ptr_t<OT::cmap> cmap_ptr (hb_sanitize_context_t ().reference_table<OT::cmap> (face));
|
||||||
|
accel->cmap_cache = OT::cmap::create_filled_cache (cmap_ptr);
|
||||||
|
accel->destroy_cmap_cache = OT::SubtableUnicodesCache::destroy;
|
||||||
|
|
||||||
if (!hb_face_set_user_data(face,
|
if (!hb_face_set_user_data(face,
|
||||||
hb_subset_accelerator_t::user_data_key(),
|
hb_subset_accelerator_t::user_data_key(),
|
||||||
accel,
|
accel,
|
||||||
|
|
Loading…
Reference in New Issue