[subset] subset name table step 2, add implementation for collecting subset

elements and serialize method
This commit is contained in:
Qunxin Liu 2019-04-02 13:38:27 -07:00 committed by Garret Rieger
parent 408c1daeb4
commit 2637a81615
1 changed files with 109 additions and 22 deletions

View File

@ -95,6 +95,28 @@ struct NameRecord
return UNSUPPORTED; return UNSUPPORTED;
} }
bool serialize (hb_serialize_context_t *c, const NameRecord& origin_namerecord, unsigned int *new_offset)
{
TRACE_SERIALIZE (this);
if (unlikely (!c->allocate_size<NameRecord> (NameRecord::static_size)))
{
DEBUG_MSG (SUBSET, nullptr, "Couldn't allocate enough space for NameRecord: %d.",
NameRecord::static_size);
return_trace (false);
}
this->platformID.set (origin_namerecord.platformID);
this->encodingID.set (origin_namerecord.encodingID);
this->languageID.set (origin_namerecord.languageID);
this->nameID.set (origin_namerecord.nameID);
this->length.set (origin_namerecord.length);
this->offset.set (*new_offset);
*new_offset += origin_namerecord.length;
return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c, const void *base) const bool sanitize (hb_sanitize_context_t *c, const void *base) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
@ -158,10 +180,11 @@ struct name
unsigned int get_size () const unsigned int get_size () const
{ return min_size + count * nameRecordZ.item_size; } { return min_size + count * nameRecordZ.item_size; }
size_t get_subsetted_size(const name *source_name, hb_subset_plan_t *plan, hb_set_t *name_record_ids_to_retain) const size_t get_subsetted_size (const name *source_name,
const hb_subset_plan_t *plan,
hb_vector_t<unsigned int>& name_record_idx_to_retain) const
{ {
size_t result = min_size; size_t result = min_size;
result += count * NameRecord::static_size;
hb_face_t *face = plan->source; hb_face_t *face = plan->source;
accelerator_t acc; accelerator_t acc;
@ -169,27 +192,82 @@ struct name
for(unsigned int i = 0; i < count; i++) for(unsigned int i = 0; i < count; i++)
{ {
if (format == 0 && (unsigned int) nameRecordZ[i].nameID > 25)
continue;
result += acc.get_name (i).get_size (); result += acc.get_name (i).get_size ();
if(format == 0 && (unsigned int)nameRecordZ[i].nameID <=25) name_record_idx_to_retain.push (i);
{
name_record_ids_to_retain->add(i);
}
} }
acc.fini (); acc.fini ();
result += name_record_idx_to_retain.length * NameRecord::static_size;
return result; return result;
} }
void serialize(void *dest, const void *source, size_t dest_size) const bool serialize (hb_serialize_context_t *c,
const name *source_name,
const hb_subset_plan_t *plan,
const hb_vector_t<unsigned int>& name_record_idx_to_retain)
{ {
memcpy(dest, source, dest_size); TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min ((*this)))) return_trace (false);
this->format.set (source_name->format);
this->count.set (name_record_idx_to_retain.length);
this->stringOffset.set (min_size + name_record_idx_to_retain.length * NameRecord::static_size);
//write new NameRecord
unsigned int new_offset = 0;
for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++)
{
unsigned int idx = name_record_idx_to_retain[i];
if (unlikely (idx >= source_name->count))
{
DEBUG_MSG (SUBSET, nullptr, "Invalid index: %d.", idx);
return_trace (false);
}
const NameRecord &namerec = source_name->nameRecordZ[idx];
if (!c->start_embed<NameRecord> ()->serialize (c, namerec, &new_offset))
return_trace (false);
}
hb_face_t *face = plan->source;
accelerator_t acc;
acc.init (face);
for (unsigned int i = 0; i < name_record_idx_to_retain.length; i++)
{
unsigned int idx = name_record_idx_to_retain[i];
unsigned int size = acc.get_name (idx).get_size ();
char *new_pos = c->allocate_size<char> (size);
if (unlikely (new_pos == nullptr))
{
acc.fini ();
DEBUG_MSG (SUBSET, nullptr, "Couldn't allocate enough space for Name string: %d.",
size);
return_trace (false);
}
unsigned int origin_offset = source_name->stringOffset + source_name->nameRecordZ[idx].offset;
memcpy (new_pos, source_name + origin_offset, size);
}
acc.fini ();
return_trace (true);
} }
bool subset (hb_subset_plan_t *plan) const bool subset (hb_subset_plan_t *plan) const
{ {
hb_set_t *name_record_ids_to_retain = hb_set_create(); hb_vector_t<unsigned int> name_record_idx_to_retain;
size_t dest_size = get_subsetted_size(this, plan, name_record_ids_to_retain);
size_t dest_size = get_subsetted_size (this, plan, name_record_idx_to_retain);
name *dest = (name *) malloc (dest_size); name *dest = (name *) malloc (dest_size);
if(unlikely (!dest)) if(unlikely (!dest))
{ {
@ -198,8 +276,16 @@ struct name
return false; return false;
} }
serialize(dest, this, dest_size); hb_serialize_context_t c (dest, dest_size);
hb_set_destroy(name_record_ids_to_retain); name *name_prime = c.start_serialize<name> ();
if (!name_prime || !name_prime->serialize (&c, this, plan, name_record_idx_to_retain))
{
free (dest);
DEBUG_MSG (SUBSET, nullptr, "Failed to serialize write new name.");
c.end_serialize ();
return false;
}
c.end_serialize ();
hb_blob_t *name_prime_blob = hb_blob_create ((const char *) dest, hb_blob_t *name_prime_blob = hb_blob_create ((const char *) dest,
dest_size, dest_size,
@ -211,6 +297,7 @@ struct name
return result; return result;
} }
bool sanitize_records (hb_sanitize_context_t *c) const bool sanitize_records (hb_sanitize_context_t *c) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);