[subset] Fix hdmx subsetting when retain gids is enabled.
authorGarret Rieger <grieger@google.com>
Sat, 19 Jan 2019 02:33:21 +0000 (18:33 -0800)
committerGarret Rieger <grieger@google.com>
Tue, 29 Jan 2019 21:19:21 +0000 (13:19 -0800)
src/hb-ot-hdmx-table.hh
src/hb-subset-plan.cc
src/hb-subset-plan.hh

index 95229c5..b1ad3eb 100644 (file)
@@ -57,16 +57,19 @@ struct DeviceRecord
     }
 
     unsigned int len () const
-    { return this->subset_plan->glyphs.length; }
+    { return this->subset_plan->num_glyphs; }
 
-    const HBUINT8* operator [] (unsigned int i) const
+    const HBUINT8* operator [] (unsigned int new_gid) const
     {
-      if (unlikely (i >= len ())) return nullptr;
-      hb_codepoint_t gid = this->subset_plan->glyphs [i];
+      if (unlikely (new_gid >= len ())) return nullptr;
 
-      if (gid >= sizeDeviceRecord - DeviceRecord::min_size)
+      hb_codepoint_t old_gid;
+      if (!this->subset_plan->old_gid_for_new_gid (new_gid, &old_gid))
+        return &Null(HBUINT8);
+
+      if (old_gid >= sizeDeviceRecord - DeviceRecord::min_size)
         return nullptr;
-      return &(this->source_device_record->widthsZ[gid]);
+      return &(this->source_device_record->widthsZ[old_gid]);
     }
   };
 
@@ -140,7 +143,7 @@ struct hdmx
 
     this->version.set (source_hdmx->version);
     this->numRecords.set (source_hdmx->numRecords);
-    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->glyphs.length));
+    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->num_glyphs));
 
     for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
     {
@@ -156,7 +159,7 @@ struct hdmx
 
   static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
   {
-    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->glyphs.length);
+    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->num_glyphs);
   }
 
   bool subset (hb_subset_plan_t *plan) const
index 63498b7..dd00f4d 100644 (file)
@@ -159,13 +159,20 @@ static void
 _create_old_gid_to_new_gid_map (bool                               retain_gids,
                                const hb_vector_t<hb_codepoint_t> &glyphs,
                                 hb_map_t                          *glyph_map, /* OUT */
+                                hb_map_t                          *reverse_glyph_map, /* OUT */
                                 unsigned int                      *num_glyphs /* OUT */)
 {
   for (unsigned int i = 0; i < glyphs.length; i++) {
     if (!retain_gids)
+    {
       glyph_map->set (glyphs[i], i);
+      reverse_glyph_map->set (i, glyphs[i]);
+    }
     else
+    {
       glyph_map->set (glyphs[i], glyphs[i]);
+      reverse_glyph_map->set (glyphs[i], glyphs[i]);
+    }
   }
   if (!retain_gids || glyphs.length == 0)
   {
@@ -202,6 +209,7 @@ hb_subset_plan_create (hb_face_t           *face,
   plan->dest = hb_face_builder_create ();
   plan->codepoint_to_glyph = hb_map_create();
   plan->glyph_map = hb_map_create();
+  plan->reverse_glyph_map = hb_map_create();
   plan->glyphset = _populate_gids_to_retain (face,
                                             input->unicodes,
                                             !plan->drop_layout,
@@ -212,6 +220,7 @@ hb_subset_plan_create (hb_face_t           *face,
   _create_old_gid_to_new_gid_map (input->retain_gids,
                                  plan->glyphs,
                                  plan->glyph_map,
+                                  plan->reverse_glyph_map,
                                   &plan->num_glyphs);
 
   return plan;
@@ -233,6 +242,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
   hb_face_destroy (plan->dest);
   hb_map_destroy (plan->codepoint_to_glyph);
   hb_map_destroy (plan->glyph_map);
+  hb_map_destroy (plan->reverse_glyph_map);
   hb_set_destroy (plan->glyphset);
 
   free (plan);
index b8b2c5d..5a90b7c 100644 (file)
@@ -45,11 +45,14 @@ struct hb_subset_plan_t
   // For each cp that we'd like to retain maps to the corresponding gid.
   hb_set_t *unicodes;
 
+  // The glyph subset
   hb_vector_t<hb_codepoint_t> glyphs;
   hb_set_t *glyphset;
-
   hb_map_t *codepoint_to_glyph;
+
+  // Old -> New glyph id mapping
   hb_map_t *glyph_map;
+  hb_map_t *reverse_glyph_map;
   unsigned int num_glyphs;
 
   // Plan is only good for a specific source/dest so keep them with it
@@ -77,6 +80,17 @@ struct hb_subset_plan_t
     return true;
   }
 
+  bool old_gid_for_new_gid (hb_codepoint_t  new_gid,
+                           hb_codepoint_t *old_gid) const
+  {
+    hb_codepoint_t gid = reverse_glyph_map->get (new_gid);
+    if (gid == HB_MAP_VALUE_INVALID)
+      return false;
+
+    *old_gid = gid;
+    return true;
+  }
+
   bool
   add_table (hb_tag_t tag,
             hb_blob_t *contents)