[subset] WIP cmap format 4 subsetting.
authorGarret Rieger <grieger@google.com>
Wed, 2 May 2018 23:12:04 +0000 (16:12 -0700)
committerGarret Rieger <grieger@google.com>
Fri, 4 May 2018 18:20:03 +0000 (11:20 -0700)
src/hb-ot-cmap-table.hh

index f0e70af..7e9675b 100644 (file)
@@ -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<segment_plan> &segments)
+  {
+    // TODO
+  }
+
+  static inline size_t get_sub_table_size (const hb_vector_t<segment_plan> &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<segment_plan> *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<CmapSubtableFormat4::segment_plan> format4_segments;
     // Format 12
-    hb_vector_t<CmapSubtableLongGroup> groups;
+    hb_vector_t<CmapSubtableLongGroup> 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;
+
+    // TODO(grieger): Convert the below to a for loop
 
-    EncodingRecord &rec = cmap->encodingRecord[0];
-    rec.platformID.set (3); // Windows
-    rec.encodingID.set (10); // Unicode UCS-4
+    // 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);