diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index e66ba6c84..8a8b3f272 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -536,6 +536,11 @@ hb_subset_preprocess (hb_face_t *source) * Note: if a glyph mapping is set with this function, then the retain gids * setting will be ignored. * + * Note: this will accept and apply non-monotonic mappings, however this + * may result in unsorted Coverage tables. Such fonts may not work for all + * use cases (for example ots will reject such coverage tables). So it's + * recommended, if possible, to supply a monotonic mapping. + * * Since: REPLACEME **/ HB_EXTERN void diff --git a/util/hb-subset.cc b/util/hb-subset.cc index cdab3efde..82ec02b7a 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -742,6 +742,65 @@ parse_instance (const char *name, } #endif +static gboolean +parse_glyph_map (const char *name, + const char *arg, + gpointer data, + GError **error) +{ + // Glyph map has the following format: + // ,,..., + // = : + subset_main_t *subset_main = (subset_main_t *) data; + hb_subset_input_t* input = subset_main->input; + hb_map_t *mapping = hb_map_create (); + hb_set_t *glyphs = hb_subset_input_glyph_set(input); + + char *s = (char *) arg; + char *p; + + while (s && *s) + { + while (*s && strchr (", ", *s)) + s++; + if (!*s) + break; + + errno = 0; + hb_codepoint_t start_code = strtoul (s, &p, 10); + if (s[0] == '-' || errno || s == p) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing glyph map at: '%s'", s); + return false; + } + + if (!p || p[0] != ':') // ranges + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing glyph map at: '%s'", s); + return false; + } + + s = ++p; + hb_codepoint_t end_code = strtoul (s, &p, 10); + if (s[0] == '-' || errno || s == p) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing glyph map at: '%s'", s); + return false; + } + + hb_set_add(glyphs, start_code); + hb_map_set (mapping, start_code, end_code); + + s = p; + } + + hb_subset_input_set_old_to_new_glyph_mapping(input, mapping); + return true; +} + template static gboolean parse_file_for (const char *name, @@ -894,6 +953,7 @@ subset_main_t::add_options () GOptionEntry other_entries[] = { + {"gid-map", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_glyph_map, "Specify a glyph mapping to use, any unmapped gids will be automatically assigned.", "List of pairs old_gid1:new_gid1,old_gid2:new_gid2,..."}, {"name-IDs", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_nameids, "Subset specified nameids. Use --name-IDs-=... to subtract from the current set.", "list of int numbers or *"}, {"name-IDs-", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, (gpointer) &parse_nameids, "Subset specified nameids", "list of int numbers or *"}, {"name-IDs+", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, (gpointer) &parse_nameids, "Subset specified nameids", "list of int numbers or *"},