[subset] Subset name table step 3, add --nameids option to guide the
authorQunxin Liu <qxliu@google.com>
Fri, 5 Apr 2019 17:05:55 +0000 (10:05 -0700)
committerGarret Rieger <grieger@google.com>
Fri, 26 Apr 2019 22:24:47 +0000 (15:24 -0700)
selection of which name records to keep in the subset method.

src/hb-ot-name-table.hh
src/hb-subset-input.cc
src/hb-subset-input.hh
src/hb-subset-plan.cc
src/hb-subset-plan.hh
src/hb-subset.h
util/hb-subset.cc
util/options.cc
util/options.hh

index a387e6e..cdb8dba 100644 (file)
@@ -106,12 +106,12 @@ struct NameRecord
       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);
+    this->platformID = origin_namerecord.platformID;
+    this->encodingID = origin_namerecord.encodingID;
+    this->languageID = origin_namerecord.languageID;
+    this->nameID = origin_namerecord.nameID;
+    this->length = origin_namerecord.length;
+    this->offset = *new_offset;
     *new_offset += origin_namerecord.length;
     
     return_trace (true);
@@ -194,6 +194,9 @@ struct name
     {
       if (format == 0 && (unsigned int) nameRecordZ[i].nameID > 25)
         continue;
+      if (!hb_set_is_empty (plan->name_ids) &&
+          !hb_set_has (plan->name_ids, source_name->nameRecordZ[i].nameID))
+        continue;
       result += acc.get_name (i).get_size ();
       name_record_idx_to_retain.push (i);
     }
@@ -214,9 +217,9 @@ struct name
 
     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);
+    this->format = source_name->format;
+    this->count = name_record_idx_to_retain.length;
+    this->stringOffset = min_size + name_record_idx_to_retain.length * NameRecord::static_size;
 
     //write new NameRecord
     unsigned int new_offset = 0;
@@ -253,9 +256,10 @@ struct name
         return_trace (false);
       }
       
-      unsigned int origin_offset = source_name->stringOffset + source_name->nameRecordZ[idx].offset;
-      
-      memcpy (new_pos, source_name + origin_offset, size);
+      const HBUINT8* source_string_pool = (source_name + source_name->stringOffset).arrayZ;
+      unsigned int name_record_offset = source_name->nameRecordZ[idx].offset;
+
+      memcpy (new_pos, source_string_pool + name_record_offset, size);
     }
 
     acc.fini ();
index 4d203b5..b3b27d4 100644 (file)
@@ -44,6 +44,7 @@ hb_subset_input_create_or_fail ()
 
   input->unicodes = hb_set_create ();
   input->glyphs = hb_set_create ();
+  input->name_ids = hb_set_create ();
   input->drop_hints = false;
   input->drop_layout = true;
   input->desubroutinize = false;
@@ -81,6 +82,7 @@ hb_subset_input_destroy (hb_subset_input_t *subset_input)
 
   hb_set_destroy (subset_input->unicodes);
   hb_set_destroy (subset_input->glyphs);
+  hb_set_destroy (subset_input->name_ids);
 
   free (subset_input);
 }
@@ -109,6 +111,12 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
   return subset_input->glyphs;
 }
 
+HB_EXTERN hb_set_t *
+hb_subset_input_nameid_set (hb_subset_input_t *subset_input)
+{
+  return subset_input->name_ids;
+}
+
 HB_EXTERN void
 hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
                                hb_bool_t drop_hints)
index 04d6e12..d01fece 100644 (file)
@@ -40,6 +40,7 @@ struct hb_subset_input_t
 
   hb_set_t *unicodes;
   hb_set_t *glyphs;
+  hb_set_t *name_ids;
 
   bool drop_hints : 1;
   bool drop_layout : 1;
@@ -49,7 +50,7 @@ struct hb_subset_input_t
    *
    * features
    * lookups
-   * nameIDs
+   * name_ids
    * ...
    */
 };
index 6e32ed7..fe636b1 100644 (file)
@@ -205,12 +205,13 @@ hb_subset_plan_create (hb_face_t           *face,
   plan->drop_layout = input->drop_layout;
   plan->desubroutinize = input->desubroutinize;
   plan->retain_gids = input->retain_gids;
-  plan->unicodes = hb_set_create();
+  plan->unicodes = hb_set_create ();
+  plan->name_ids = hb_set_reference (input->name_ids);
   plan->source = hb_face_reference (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->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,
                                               input->glyphs,
@@ -239,6 +240,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
   if (!hb_object_destroy (plan)) return;
 
   hb_set_destroy (plan->unicodes);
+  hb_set_destroy (plan->name_ids);
   hb_face_destroy (plan->source);
   hb_face_destroy (plan->dest);
   hb_map_destroy (plan->codepoint_to_glyph);
index afaeff4..abbab5e 100644 (file)
@@ -47,6 +47,9 @@ struct hb_subset_plan_t
   // For each cp that we'd like to retain maps to the corresponding gid.
   hb_set_t *unicodes;
 
+  //name_ids we would like to retain
+  hb_set_t *name_ids;
+
   // The glyph subset
   hb_map_t *codepoint_to_glyph;
 
index 657709e..5034506 100644 (file)
@@ -54,6 +54,9 @@ hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
 HB_EXTERN hb_set_t *
 hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
 
+HB_EXTERN hb_set_t *
+hb_subset_input_nameid_set (hb_subset_input_t *subset_input);
+
 HB_EXTERN void
 hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
                                hb_bool_t drop_hints);
index 33e584b..682ca4c 100644 (file)
@@ -93,6 +93,7 @@ struct subset_consumer_t
     hb_subset_input_set_drop_hints (input, subset_options.drop_hints);
     hb_subset_input_set_retain_gids (input, subset_options.retain_gids);
     hb_subset_input_set_desubroutinize (input, subset_options.desubroutinize);
+    hb_set_set (hb_subset_input_nameid_set (input), subset_options.name_ids);
 
     hb_face_t *face = hb_font_get_face (font);
 
index c5a4f0f..a9b3fc7 100644 (file)
@@ -971,6 +971,49 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t  *buffer,
   g_string_append_c (gs, '\n');
 }
 
+static gboolean
+parse_nameids (const char *name G_GNUC_UNUSED,
+               const char *arg,
+               gpointer    data,
+               GError    **error G_GNUC_UNUSED)
+{
+  subset_options_t *subset_opts = (subset_options_t *) data;
+
+  hb_set_t *name_ids = hb_set_create ();
+  char *s = (char *) arg;
+  char *p;
+
+  while (s && *s)
+  {
+    while (*s && strchr ("<+>{},;&#\\xXuUnNiI\n\t\v\f\r ", *s))
+      s++;
+    if (!*s)
+      break;
+
+    errno = 0;
+    hb_codepoint_t u = strtoul (s, &p, 10);
+    if (errno || s == p)
+    {
+      hb_set_destroy (name_ids);
+      g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+                   "Failed parsing nameID values at: '%s'", s);
+      return false;
+    }
+
+    hb_set_add (name_ids, u);
+
+    s = p;
+  }
+
+  hb_set_t *prev = subset_opts->name_ids;
+  subset_opts->name_ids = hb_set_reference (name_ids);
+  hb_set_destroy (prev);
+  hb_set_destroy (name_ids);
+
+  return true;
+}
+
+
 void
 subset_options_t::add_options (option_parser_t *parser)
 {
@@ -980,6 +1023,7 @@ subset_options_t::add_options (option_parser_t *parser)
     {"no-hinting", 0, 0, G_OPTION_ARG_NONE,  &this->drop_hints,   "Whether to drop hints",   nullptr},
     {"retain-gids", 0, 0, G_OPTION_ARG_NONE,  &this->retain_gids,   "If set don't renumber glyph ids in the subset.",   nullptr},
     {"desubroutinize", 0, 0, G_OPTION_ARG_NONE,  &this->desubroutinize,   "Remove CFF/CFF2 use of subroutines",   nullptr},
+    {"name-IDs", 0, 0, G_OPTION_ARG_CALLBACK,  (gpointer) &parse_nameids,  "Subset specified nameids", "list of int numbers"},
 
     {nullptr}
   };
@@ -989,3 +1033,4 @@ subset_options_t::add_options (option_parser_t *parser)
          "Options subsetting",
          this);
 }
+
index 84139f5..2691e22 100644 (file)
@@ -677,16 +677,24 @@ struct subset_options_t : option_group_t
     drop_hints = false;
     retain_gids = false;
     desubroutinize = false;
+    name_ids = hb_set_create ();
 
     add_options (parser);
   }
 
+  virtual ~subset_options_t ()
+  {
+    hb_set_destroy (name_ids);
+  }
+
+
   void add_options (option_parser_t *parser);
 
   hb_bool_t keep_layout;
   hb_bool_t drop_hints;
   hb_bool_t retain_gids;
   hb_bool_t desubroutinize;
+  hb_set_t *name_ids;
 };
 
 /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */