From e711e305c8d59b9e381e9bf7aa7fd7f85d5008b7 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 4 May 2023 18:47:55 +0000 Subject: [PATCH 01/11] [subset] Add new subsetting API method to receive a user specified glyph mapping. --- src/hb-subset-input.cc | 16 ++++++++++++++++ src/hb-subset-input.hh | 1 + src/hb-subset.h | 5 +++++ 3 files changed, 22 insertions(+) diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 5f001ac25..66feef1b1 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -520,6 +520,22 @@ hb_subset_preprocess (hb_face_t *source) return new_source; } +HB_EXTERN hb_bool_t +hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, + const hb_map_t* mapping) +{ + hb_set_t new_gids; + for (auto gid : mapping->values()) + { + // Mapping cannot map multiple old gids to the same new gid. + if (new_gids.has(gid)) return false; + new_gids.add(gid); + } + + input->glyph_map = *mapping; + return true; +} + #ifdef HB_EXPERIMENTAL_API /** * hb_subset_input_override_name_table: diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh index 1550e8b2c..1970f795b 100644 --- a/src/hb-subset-input.hh +++ b/src/hb-subset-input.hh @@ -119,6 +119,7 @@ struct hb_subset_input_t bool force_long_loca = false; hb_hashmap_t axes_location; + hb_map_t glyph_map; #ifdef HB_EXPERIMENTAL_API hb_hashmap_t name_table_overrides; #endif diff --git a/src/hb-subset.h b/src/hb-subset.h index 41d958705..84f4e76ba 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -172,6 +172,11 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, hb_tag_t axis_tag, float axis_value); +HB_EXTERN hb_bool_t +hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, + const hb_map_t* mapping); + + #ifdef HB_EXPERIMENTAL_API HB_EXTERN hb_bool_t hb_subset_input_override_name_table (hb_subset_input_t *input, From 6826634714de899f5f000a6897deb43825c8ba78 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 4 May 2023 19:18:54 +0000 Subject: [PATCH 02/11] [subset] apply the user supplied glyph map. --- src/hb-subset-input.cc | 18 ++++++++++++++++++ src/hb-subset-plan.cc | 31 ++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 66feef1b1..9334f18c1 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -520,6 +520,24 @@ hb_subset_preprocess (hb_face_t *source) return new_source; } +/** + * hb_subset_input_set_old_to_new_glyph_mapping: + * @input: a #hb_subset_input_t object. + * @mapping: a mapping from original glyphs to new ids. + * + * Provide a mapping from glyph ids in the original font to the desired + * new glyph ids. The mappings must be unique, that is no two original + * glyph ids can be mapped to the same new id. + * + * Any glyphs that are retained in the subset which are not specified + * in this mapping will be assigned glyph ids after the highest glyph + * id in the mapping. + * + * Note: if a glyph mapping is set with this function, then the retain gids + * setting will be ignored. + * + * Since: REPLACEME + **/ HB_EXTERN hb_bool_t hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, const hb_map_t* mapping) diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index a1705c047..cff19a78b 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -771,6 +771,7 @@ static void _create_old_gid_to_new_gid_map (const hb_face_t *face, bool retain_gids, const hb_set_t *all_gids_to_retain, + const hb_map_t *requested_glyph_map, hb_map_t *glyph_map, /* OUT */ hb_map_t *reverse_glyph_map, /* OUT */ unsigned int *num_glyphs /* OUT */) @@ -779,7 +780,34 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, reverse_glyph_map->resize (pop); glyph_map->resize (pop); - if (!retain_gids) + if (requested_glyph_map) + { + hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID; + hb_set_t remaining; + for (auto old_gid : all_gids_to_retain->iter ()) + { + hb_codepoint_t* new_gid; + if (!requested_glyph_map->has (old_gid, &new_gid)) + { + remaining.add(old_gid); + continue; + } + + if (*new_gid > max_glyph || max_glyph == HB_SET_VALUE_INVALID) + max_glyph = *new_gid; + reverse_glyph_map->set (*new_gid, old_gid); + } + + // Anything that wasn't mapped by the requested mapping should + // be placed after the requested mapping. + for (auto old_gid : remaining) + { + reverse_glyph_map->set(++max_glyph, old_gid); + } + + *num_glyphs = max_glyph + 1; + } + else if (!retain_gids) { + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0) | hb_sink (reverse_glyph_map) @@ -1011,6 +1039,7 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, _create_old_gid_to_new_gid_map (face, input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, &_glyphset, + &input->glyph_map, glyph_map, reverse_glyph_map, &_num_output_glyphs); From e14020b27ac71f44a46374ebdce9e0ac46160118 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 4 May 2023 19:24:01 +0000 Subject: [PATCH 03/11] [subset] remove return value from mapping setting function. --- src/hb-subset-input.cc | 5 ++--- src/hb-subset.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 9334f18c1..e66ba6c84 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -538,7 +538,7 @@ hb_subset_preprocess (hb_face_t *source) * * Since: REPLACEME **/ -HB_EXTERN hb_bool_t +HB_EXTERN void hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, const hb_map_t* mapping) { @@ -546,12 +546,11 @@ hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, for (auto gid : mapping->values()) { // Mapping cannot map multiple old gids to the same new gid. - if (new_gids.has(gid)) return false; + if (new_gids.has(gid)) return; new_gids.add(gid); } input->glyph_map = *mapping; - return true; } #ifdef HB_EXPERIMENTAL_API diff --git a/src/hb-subset.h b/src/hb-subset.h index 84f4e76ba..a79012802 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -172,7 +172,7 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, hb_tag_t axis_tag, float axis_value); -HB_EXTERN hb_bool_t +HB_EXTERN void hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, const hb_map_t* mapping); From 779e8297fa53f95db2efe1d0e9e734951e0e33ab Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 4 May 2023 19:31:23 +0000 Subject: [PATCH 04/11] [subset] fix requested_glyph_map presence check. --- src/hb-subset-plan.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index cff19a78b..f018814e7 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -780,7 +780,7 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, reverse_glyph_map->resize (pop); glyph_map->resize (pop); - if (requested_glyph_map) + if (*requested_glyph_map) { hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID; hb_set_t remaining; From 98e73192f4aac0419d275857993359676bd94f94 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 4 May 2023 22:20:06 +0000 Subject: [PATCH 05/11] [subset] Add command line flag to provide a gid mapping. --- src/hb-subset-input.cc | 5 ++++ util/hb-subset.cc | 60 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) 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 *"}, From 77a815542588a257f44c9310961797717e435f64 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 4 May 2023 23:01:56 +0000 Subject: [PATCH 06/11] [subset] Add some basic tests for a provided glyph map. --- src/hb-subset-input.cc | 9 +++------ src/hb-subset-plan.cc | 10 ++++++++-- ...o-Regular.glyph_map_roboto.41,43,61,66,69.ttf | Bin 0 -> 3996 bytes ...yph_map_roboto_retain_gids.41,43,61,66,69.ttf | Bin 0 -> 7936 bytes test/subset/data/profiles/glyph_map_roboto.txt | 2 ++ .../profiles/glyph_map_roboto_retain_gids.txt | 4 ++++ test/subset/data/tests/glyph_map.tests | 9 +++++++++ test/subset/generate-expected-outputs.py | 4 +++- 8 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 test/subset/data/expected/glyph_map/Roboto-Regular.glyph_map_roboto.41,43,61,66,69.ttf create mode 100644 test/subset/data/expected/glyph_map/Roboto-Regular.glyph_map_roboto_retain_gids.41,43,61,66,69.ttf create mode 100644 test/subset/data/profiles/glyph_map_roboto.txt create mode 100644 test/subset/data/profiles/glyph_map_roboto_retain_gids.txt create mode 100644 test/subset/data/tests/glyph_map.tests diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 8a8b3f272..49fe7df21 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -547,13 +547,10 @@ HB_EXTERN void hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, const hb_map_t* mapping) { - hb_set_t new_gids; - for (auto gid : mapping->values()) - { + hb_set_t new_gids(mapping->values()); + if (new_gids.get_population() != mapping->get_population()) // Mapping cannot map multiple old gids to the same new gid. - if (new_gids.has(gid)) return; - new_gids.add(gid); - } + return; input->glyph_map = *mapping; } diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index f018814e7..1e152d3e0 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -782,10 +782,16 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, if (*requested_glyph_map) { - hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID; + + hb_codepoint_t max_glyph = 0; hb_set_t remaining; for (auto old_gid : all_gids_to_retain->iter ()) { + if (old_gid == 0) { + reverse_glyph_map->set(0, 0); + continue; + } + hb_codepoint_t* new_gid; if (!requested_glyph_map->has (old_gid, &new_gid)) { @@ -793,7 +799,7 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, continue; } - if (*new_gid > max_glyph || max_glyph == HB_SET_VALUE_INVALID) + if (*new_gid > max_glyph) max_glyph = *new_gid; reverse_glyph_map->set (*new_gid, old_gid); } diff --git a/test/subset/data/expected/glyph_map/Roboto-Regular.glyph_map_roboto.41,43,61,66,69.ttf b/test/subset/data/expected/glyph_map/Roboto-Regular.glyph_map_roboto.41,43,61,66,69.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a4c82662f9f3fb69871adfceb5351fbb4bdff580 GIT binary patch literal 3996 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 HAI Date: Thu, 4 May 2023 23:04:35 +0000 Subject: [PATCH 07/11] [subset] Add new glyph map method to docs. --- docs/harfbuzz-sections.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index d187f7001..ce35281a5 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -874,9 +874,9 @@ hb_subset_input_set_flags hb_subset_input_get_flags hb_subset_input_unicode_set hb_subset_input_glyph_set -hb_subset_input_set hb_subset_input_pin_axis_location hb_subset_input_pin_axis_to_default +hb_subset_input_set_old_to_new_glyph_mapping hb_subset_or_fail hb_subset_plan_create_or_fail hb_subset_plan_reference From 3021b2dbe2a18724f345f881eba7299a8bf00499 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 5 May 2023 05:57:05 +0000 Subject: [PATCH 08/11] [subset] change glyph mapping api to return a mutable map. Maintains consistency with our other set based api methods. --- docs/harfbuzz-sections.txt | 2 +- src/hb-subset-input.cc | 27 +++++++++++---------------- src/hb-subset-plan.cc | 35 +++++++++++++++++++++++++++-------- src/hb-subset.h | 6 ++---- util/hb-subset.cc | 4 +--- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index ce35281a5..9a740c6f1 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -874,9 +874,9 @@ hb_subset_input_set_flags hb_subset_input_get_flags hb_subset_input_unicode_set hb_subset_input_glyph_set +hb_subset_input_old_to_new_glyph_mapping hb_subset_input_pin_axis_location hb_subset_input_pin_axis_to_default -hb_subset_input_set_old_to_new_glyph_mapping hb_subset_or_fail hb_subset_plan_create_or_fail hb_subset_plan_reference diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 49fe7df21..4eba5e221 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -525,34 +525,29 @@ hb_subset_preprocess (hb_face_t *source) * @input: a #hb_subset_input_t object. * @mapping: a mapping from original glyphs to new ids. * - * Provide a mapping from glyph ids in the original font to the desired - * new glyph ids. The mappings must be unique, that is no two original - * glyph ids can be mapped to the same new id. + * Returns a map which specifies an explicit mapping from old to new glyph + * id's in the produced subset. The caller should populate the map as desired. + * If this map is left empty then glyph ids will be automatically mapped to new + * values by the subsetter. If populated, the mapping must be unique, that + * is no two original glyph ids can be mapped to the same new id. + * Additionally, if a mapping is provided then the retain gids option cannot + * be enabled. * * Any glyphs that are retained in the subset which are not specified * in this mapping will be assigned glyph ids after the highest glyph * id in the mapping. * - * 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 + * use cases (for example ots will reject unsorted coverage tables). So it's * recommended, if possible, to supply a monotonic mapping. * * Since: REPLACEME **/ -HB_EXTERN void -hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, - const hb_map_t* mapping) +HB_EXTERN hb_map_t* +hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input) { - hb_set_t new_gids(mapping->values()); - if (new_gids.get_population() != mapping->get_population()) - // Mapping cannot map multiple old gids to the same new gid. - return; - - input->glyph_map = *mapping; + return &input->glyph_map; } #ifdef HB_EXPERIMENTAL_API diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 1e152d3e0..111ff7253 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -767,7 +767,7 @@ _create_glyph_map_gsub (const hb_set_t* glyph_set_gsub, ; } -static void +static bool _create_old_gid_to_new_gid_map (const hb_face_t *face, bool retain_gids, const hb_set_t *all_gids_to_retain, @@ -782,6 +782,20 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, if (*requested_glyph_map) { + hb_set_t new_gids(requested_glyph_map->values()); + if (new_gids.get_population() != requested_glyph_map->get_population()) + { + DEBUG_MSG (SUBSET, nullptr, "The provided custom glyph mapping is not unique."); + return false; + } + + if (retain_gids) + { + DEBUG_MSG (SUBSET, nullptr, + "HB_SUBSET_FLAGS_RETAIN_GIDS cannot be set if " + "a custom glyph mapping has been provided."); + return false; + } hb_codepoint_t max_glyph = 0; hb_set_t remaining; @@ -839,6 +853,8 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, | hb_map (&hb_pair_t::reverse) | hb_sink (glyph_map) ; + + return true; } #ifndef HB_NO_VAR @@ -1042,13 +1058,16 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face, if (unlikely (in_error ())) return; - _create_old_gid_to_new_gid_map (face, - input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, - &_glyphset, - &input->glyph_map, - glyph_map, - reverse_glyph_map, - &_num_output_glyphs); + if (!check_success(_create_old_gid_to_new_gid_map( + face, + input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS, + &_glyphset, + &input->glyph_map, + glyph_map, + reverse_glyph_map, + &_num_output_glyphs))) { + return; + } _create_glyph_map_gsub ( &_glyphset_gsub, diff --git a/src/hb-subset.h b/src/hb-subset.h index a79012802..078dc5abd 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -172,10 +172,8 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, hb_tag_t axis_tag, float axis_value); -HB_EXTERN void -hb_subset_input_set_old_to_new_glyph_mapping (hb_subset_input_t *input, - const hb_map_t* mapping); - +HB_EXTERN hb_map_t* +hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input); #ifdef HB_EXPERIMENTAL_API HB_EXTERN hb_bool_t diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 82ec02b7a..599c7dc4e 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -753,7 +753,6 @@ parse_glyph_map (const char *name, // = : 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; @@ -792,12 +791,11 @@ parse_glyph_map (const char *name, } hb_set_add(glyphs, start_code); - hb_map_set (mapping, start_code, end_code); + hb_map_set (hb_subset_input_old_to_new_glyph_mapping (input), start_code, end_code); s = p; } - hb_subset_input_set_old_to_new_glyph_mapping(input, mapping); return true; } From 374a9a9f5eefd40822c48707bd2126df3505b595 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 5 May 2023 05:58:15 +0000 Subject: [PATCH 09/11] [subset] restore accidentally removed function doc. --- docs/harfbuzz-sections.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 9a740c6f1..dff9bac69 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -874,6 +874,7 @@ hb_subset_input_set_flags hb_subset_input_get_flags hb_subset_input_unicode_set hb_subset_input_glyph_set +hb_subset_input_set hb_subset_input_old_to_new_glyph_mapping hb_subset_input_pin_axis_location hb_subset_input_pin_axis_to_default From d339298f371902e9a09ca7e0708893a15a739f0c Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 5 May 2023 06:00:30 +0000 Subject: [PATCH 10/11] [subset] fix hb_subset_input_old_to_new_gid_mapping method comment. --- src/hb-subset-input.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 4eba5e221..ba74d9294 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -521,14 +521,13 @@ hb_subset_preprocess (hb_face_t *source) } /** - * hb_subset_input_set_old_to_new_glyph_mapping: + * hb_subset_input_old_to_new_glyph_mapping: * @input: a #hb_subset_input_t object. - * @mapping: a mapping from original glyphs to new ids. * - * Returns a map which specifies an explicit mapping from old to new glyph + * Returns a map which can be used to provide an explicit mapping from old to new glyph * id's in the produced subset. The caller should populate the map as desired. * If this map is left empty then glyph ids will be automatically mapped to new - * values by the subsetter. If populated, the mapping must be unique, that + * values by the subsetter. If populated, the mapping must be unique. That * is no two original glyph ids can be mapped to the same new id. * Additionally, if a mapping is provided then the retain gids option cannot * be enabled. @@ -542,6 +541,8 @@ hb_subset_preprocess (hb_face_t *source) * use cases (for example ots will reject unsorted coverage tables). So it's * recommended, if possible, to supply a monotonic mapping. * + * Return value: (transfer none): pointer to the #hb_map_t of the custom glyphs ID map. + * * Since: REPLACEME **/ HB_EXTERN hb_map_t* From 8eb9f31263746a8942fd5dbab90094930ac104bd Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 5 May 2023 15:56:50 +0000 Subject: [PATCH 11/11] [subset] s/Since/XSince/. --- src/hb-subset-input.cc | 2 +- src/hb-subset.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index ba74d9294..0b2de43ee 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -543,7 +543,7 @@ hb_subset_preprocess (hb_face_t *source) * * Return value: (transfer none): pointer to the #hb_map_t of the custom glyphs ID map. * - * Since: REPLACEME + * XSince: REPLACEME **/ HB_EXTERN hb_map_t* hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input) diff --git a/src/hb-subset.h b/src/hb-subset.h index 078dc5abd..6368ff93f 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -154,6 +154,9 @@ hb_subset_input_glyph_set (hb_subset_input_t *input); HB_EXTERN hb_set_t * hb_subset_input_set (hb_subset_input_t *input, hb_subset_sets_t set_type); +HB_EXTERN hb_map_t* +hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input); + HB_EXTERN hb_subset_flags_t hb_subset_input_get_flags (hb_subset_input_t *input); @@ -172,9 +175,6 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input, hb_tag_t axis_tag, float axis_value); -HB_EXTERN hb_map_t* -hb_subset_input_old_to_new_glyph_mapping (hb_subset_input_t *input); - #ifdef HB_EXPERIMENTAL_API HB_EXTERN hb_bool_t hb_subset_input_override_name_table (hb_subset_input_t *input,