From 295d67ea7d0ddac5666bd6aa4b647dd9cbf8e8f7 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 2 May 2018 16:12:04 -0700 Subject: [PATCH] [subset] WIP cmap format 4 subsetting. --- src/hb-ot-cmap-table.hh | 104 +++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index f0e70afee..7e9675b3c 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -69,6 +69,48 @@ struct CmapSubtableFormat0 struct CmapSubtableFormat4 { + struct segment_plan + { + HBUINT16 start_code; + HBUINT16 end_code; + bool use_delta; + }; + + bool serialize (hb_serialize_context_t *c, + const hb_subset_plan_t *plan, + const hb_vector_t &segments) + { + // TODO + } + + static inline size_t get_sub_table_size (const hb_vector_t &segments) + { + size_t segment_size = 0; + for (unsigned int i = 0; i < segments.len; i++) + { + // Parallel array entries + segment_size += + 2 // end count + + 2 // start count + + 2 // delta + + 2; // range offset + + if (!segments[i].use_delta) + // Add bytes for the glyph index array entries for this segment. + segment_size += (segments[i].end_code - segments[i].start_code + 1) * 2; + } + + return min_size + + 2 // Padding + + segment_size; + } + + static inline bool create_sub_table_plan (const hb_subset_plan_t *plan, + hb_vector_t *segments) + { + // TODO + } + struct accelerator_t { inline void init (const CmapSubtableFormat4 *subtable) @@ -175,6 +217,8 @@ struct CmapSubtableFormat4 return_trace (16 + 4 * (unsigned int) segCountX2 <= length); } + + protected: HBUINT16 format; /* Format number is set to 4. */ HBUINT16 length; /* This is the length in bytes of the @@ -597,24 +641,29 @@ struct cmap struct subset_plan { subset_plan(void) { - groups.init(); + format4_segments.init(); + format12_groups.init(); } ~subset_plan(void) { - groups.fini(); + format4_segments.fini(); + format12_groups.fini(); } inline size_t final_size() const { return 4 // header - + 8 // 1 EncodingRecord - + CmapSubtableFormat12::get_sub_table_size (this->groups); + + 8 * 2 // 2 EncodingRecord + + CmapSubtableFormat4::get_sub_table_size (this->format4_segments); + + CmapSubtableFormat12::get_sub_table_size (this->format12_groups); } + // Format 4 + hb_vector_t format4_segments; // Format 12 - hb_vector_t groups; + hb_vector_t format12_groups; }; inline bool sanitize (hb_sanitize_context_t *c) const @@ -628,10 +677,14 @@ struct cmap inline bool _create_plan (const hb_subset_plan_t *plan, subset_plan *cmap_plan) const { - return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->groups); + if (unlikely( !CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments))) + return false; + + return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups); } - inline bool _subset (const subset_plan &cmap_subset_plan, + inline bool _subset (const hb_subset_plan_t *plan, + const subset_plan &cmap_subset_plan, size_t dest_sz, void *dest) const { @@ -645,18 +698,37 @@ struct cmap cmap->version.set (0); - if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 1))) return false; + if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 2))) return false; - EncodingRecord &rec = cmap->encodingRecord[0]; - rec.platformID.set (3); // Windows - rec.encodingID.set (10); // Unicode UCS-4 + // TODO(grieger): Convert the below to a for loop + + // Format 4 Encoding Record + EncodingRecord &format4_rec = cmap->encodingRecord[0]; + format4_rec.platformID.set (3); // Windows + format4_rec.encodingID.set (1); // Unicode BMP + + // Format 12 Encoding Record + EncodingRecord &format12_rec = cmap->encodingRecord[1]; + format12_rec.platformID.set (3); // Windows + format12_rec.encodingID.set (10); // Unicode UCS-4 + + // Write out format 4 sub table. + { + CmapSubtable &subtable = format4_rec.subtable.serialize (&c, cmap); + subtable.u.format.set (4); + + CmapSubtableFormat4 &format4 = subtable.u.format4; + if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments))) return false; + } // Write out format 12 sub table. - CmapSubtable &subtable = rec.subtable.serialize (&c, cmap); - subtable.u.format.set (12); + { + CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap); + subtable.u.format.set (12); - CmapSubtableFormat12 &format12 = subtable.u.format12; - if (unlikely (!format12.serialize (&c, cmap_subset_plan.groups))) return false; + CmapSubtableFormat12 &format12 = subtable.u.format12; + if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups))) return false; + } c.end_serialize (); @@ -681,7 +753,7 @@ struct cmap return false; } - if (unlikely (!_subset (cmap_subset_plan, dest_sz, dest))) + if (unlikely (!_subset (plan, cmap_subset_plan, dest_sz, dest))) { DEBUG_MSG(SUBSET, nullptr, "Failed to perform subsetting of cmap."); free (dest);