From 2637a81615c80443911a603cbd161ade525c79f1 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Tue, 2 Apr 2019 13:38:27 -0700 Subject: [PATCH] [subset] subset name table step 2, add implementation for collecting subset elements and serialize method --- src/hb-ot-name-table.hh | 131 +++++++++++++++++++++++++++++++++------- 1 file changed, 109 insertions(+), 22 deletions(-) diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh index bacd5a8e6..a387e6e38 100644 --- a/src/hb-ot-name-table.hh +++ b/src/hb-ot-name-table.hh @@ -95,6 +95,28 @@ struct NameRecord 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::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 { TRACE_SANITIZE (this); @@ -158,59 +180,124 @@ struct name unsigned int get_size () const { 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& name_record_idx_to_retain) const { size_t result = min_size; - result += count * NameRecord::static_size; hb_face_t *face = plan->source; accelerator_t acc; acc.init (face); - for(unsigned int i = 0; iadd(i); - } + if (format == 0 && (unsigned int) nameRecordZ[i].nameID > 25) + continue; + result += acc.get_name (i).get_size (); + name_record_idx_to_retain.push (i); } - acc.fini(); + acc.fini (); + + result += name_record_idx_to_retain.length * NameRecord::static_size; 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& 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 ()->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 (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(); - size_t dest_size = get_subsetted_size(this, plan, name_record_ids_to_retain); + hb_vector_t name_record_idx_to_retain; + + size_t dest_size = get_subsetted_size (this, plan, name_record_idx_to_retain); name *dest = (name *) malloc (dest_size); if(unlikely (!dest)) { - DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for name subset output.", + DEBUG_MSG (SUBSET, nullptr, "Unable to alloc %lu for name subset output.", (unsigned long) dest_size); return false; } - serialize(dest, this, dest_size); - hb_set_destroy(name_record_ids_to_retain); + hb_serialize_context_t c (dest, dest_size); + name *name_prime = c.start_serialize (); + 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, - dest_size, - HB_MEMORY_MODE_READONLY, - dest, - free); + hb_blob_t *name_prime_blob = hb_blob_create ((const char *) dest, + dest_size, + HB_MEMORY_MODE_READONLY, + dest, + free); bool result = plan->add_table (HB_OT_TAG_name, name_prime_blob); hb_blob_destroy (name_prime_blob); return result; } + bool sanitize_records (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this);