diff --git a/src/Makefile.sources b/src/Makefile.sources index d8b7b2f7d..bd66473af 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -257,6 +257,7 @@ HB_SUBSET_sources = \ hb-ot-cff1-table.cc \ hb-ot-cff2-table.cc \ hb-ot-color-colrv1-closure.hh \ + hb-ot-post-table-v2subset.hh \ hb-static.cc \ hb-subset-cff-common.cc \ hb-subset-cff-common.hh \ diff --git a/src/hb-ot-post-table-v2subset.hh b/src/hb-ot-post-table-v2subset.hh new file mode 100644 index 000000000..c8ea01126 --- /dev/null +++ b/src/hb-ot-post-table-v2subset.hh @@ -0,0 +1,114 @@ +/* + * Copyright © 2021 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + */ + +#ifndef HB_OT_POST_TABLE_V2SUBSET_HH +#define HB_OT_POST_TABLE_V2SUBSET_HH + +#include "hb-open-type.hh" +#include "hb-ot-post-table.hh" + +/* + * post -- PostScript + * https://docs.microsoft.com/en-us/typography/opentype/spec/post + */ + +namespace OT { +template +HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c, + Iterator it, + const void* _post) const +{ + TRACE_SERIALIZE (this); + auto *out = c->start_embed (this); + if (unlikely (!c->check_success (out))) return_trace (false); + if (!out->glyphNameIndex.serialize (c, + it + | hb_map (hb_second))) + return_trace (false); + + hb_set_t copied_indices; + for (const auto& _ : + it ) + { + unsigned glyph_id = _.first; + unsigned new_index = _.second; + + if (new_index < 258) continue; + if (copied_indices.has (new_index)) continue; + copied_indices.add (new_index); + + hb_bytes_t s = reinterpret_cast (_post)->find_glyph_name (glyph_id); + HBUINT8 *o = c->allocate_size (HBUINT8::static_size * (s.length + 1)); + if (unlikely (!o)) return_trace (false); + if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); + memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length); + } + + return_trace (true); +} + +HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const +{ + TRACE_SUBSET (this); + + const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map; + unsigned num_glyphs = c->plan->num_output_glyphs (); + hb_map_t old_new_index_map, old_gid_new_index_map; + unsigned i = 0; + + for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++) + { + hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid); + unsigned old_index = glyphNameIndex[old_gid]; + + unsigned new_index; + if (old_index <= 257) new_index = old_index; + else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index); + else + { + new_index = 258 + i; + old_new_index_map.set (old_index, new_index); + i++; + } + old_gid_new_index_map.set (old_gid, new_index); + } + + auto index_iter = + + hb_range (num_glyphs) + | hb_map (reverse_glyph_map) + | hb_map_retains_sorting ([&](hb_codepoint_t old_gid) + { + unsigned new_index = old_gid_new_index_map.get (old_gid); + return hb_pair_t (old_gid, new_index); + }) + ; + + post::accelerator_t _post; + _post.init (c->plan->source); + bool ret = serialize (c->serializer, index_iter, &_post); + _post.fini (); + return_trace (ret); +} + +} /* namespace OT */ +#endif /* HB_OT_POST_TABLE_V2SUBSET_HH */ diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index 33d10a931..1184682df 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -55,6 +55,13 @@ struct postV2Tail return_trace (glyphNameIndex.sanitize (c)); } + template + bool serialize (hb_serialize_context_t *c, + Iterator it, + const void* _post) const; + + bool subset (hb_subset_context_t *c) const; + protected: Array16Of glyphNameIndex; /* This is not an offset, but is the * ordinal number of the glyph in 'post' @@ -71,13 +78,18 @@ struct post { static constexpr hb_tag_t tableTag = HB_OT_TAG_post; - void serialize (hb_serialize_context_t *c) const + bool serialize (hb_serialize_context_t *c, bool glyph_names) const { + TRACE_SERIALIZE (this); post *post_prime = c->allocate_min (); - if (unlikely (!post_prime)) return; + if (unlikely (!post_prime)) return_trace (false); memcpy (post_prime, this, post::min_size); - post_prime->version.major = 3; // Version 3 does not have any glyph names. + if (!glyph_names) + return_trace (c->check_assign (post_prime->version.major, 3, + HB_SERIALIZE_ERROR_INT_OVERFLOW)); // Version 3 does not have any glyph names. + + return_trace (true); } bool subset (hb_subset_context_t *c) const @@ -86,13 +98,18 @@ struct post post *post_prime = c->serializer->start_embed (); if (unlikely (!post_prime)) return_trace (false); - serialize (c->serializer); + if (!serialize (c->serializer, c->plan->glyph_names)) + return_trace (false); + + if (c->plan->glyph_names && version.major == 2) + return_trace (v2X.subset (c)); return_trace (true); } struct accelerator_t { + friend struct postV2Tail; void init (hb_face_t *face) { index_to_offset.init (); diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index 2b9e2a6f3..47f1f6a59 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -60,6 +60,7 @@ hb_subset_input_create_or_fail (void) input->name_legacy = false; input->overlaps_flag = false; input->notdef_outline = false; + input->glyph_names = false; input->no_prune_unicode_ranges = false; input->retain_all_layout_features = false; input->passthrough_unrecognized = false; @@ -391,6 +392,8 @@ hb_subset_input_get_flag (hb_subset_input_t *input, return input->passthrough_unrecognized; case HB_SUBSET_FLAG_NOTDEF_OUTLINE: return input->notdef_outline; + case HB_SUBSET_FLAG_GLYPH_NAMES: + return input->glyph_names; case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES: return input->no_prune_unicode_ranges; case HB_SUBSET_FLAG_RETAIN_ALL_FEATURES: @@ -438,6 +441,9 @@ hb_subset_input_set_flag (hb_subset_input_t *input, case HB_SUBSET_FLAG_NOTDEF_OUTLINE: input->notdef_outline = value; break; + case HB_SUBSET_FLAG_GLYPH_NAMES: + input->glyph_names = value; + break; case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES: input->no_prune_unicode_ranges = value; break; diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh index 6f76f999f..ddbd4fba5 100644 --- a/src/hb-subset-input.hh +++ b/src/hb-subset-input.hh @@ -53,6 +53,7 @@ struct hb_subset_input_t hb_bool_t name_legacy; hb_bool_t overlaps_flag; hb_bool_t notdef_outline; + hb_bool_t glyph_names; hb_bool_t no_prune_unicode_ranges; hb_bool_t retain_all_layout_features; hb_bool_t passthrough_unrecognized; diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 5749068de..76b73fedc 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -429,6 +429,7 @@ hb_subset_plan_create (hb_face_t *face, plan->name_legacy = input->name_legacy; plan->overlaps_flag = input->overlaps_flag; plan->notdef_outline = input->notdef_outline; + plan->glyph_names = input->glyph_names; plan->prune_unicode_ranges = !input->no_prune_unicode_ranges; plan->retain_all_layout_features = input->retain_all_layout_features; plan->passthrough_unrecognized = input->passthrough_unrecognized; diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index cd449ba22..9252e706a 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -46,6 +46,7 @@ struct hb_subset_plan_t bool name_legacy : 1; bool overlaps_flag : 1; bool notdef_outline : 1; + bool glyph_names : 1; bool prune_unicode_ranges : 1; bool retain_all_layout_features : 1; bool passthrough_unrecognized : 1; diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 30a3cef9a..369d54ac1 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -42,6 +42,7 @@ #include "hb-ot-color-cpal-table.hh" #include "hb-ot-os2-table.hh" #include "hb-ot-post-table.hh" +#include "hb-ot-post-table-v2subset.hh" #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" #include "hb-ot-vorg-table.hh" diff --git a/src/hb-subset.h b/src/hb-subset.h index 9b7e35492..cf08a5027 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -59,6 +59,8 @@ typedef struct hb_subset_input_t hb_subset_input_t; * Defaults to false. * @HB_SUBSET_FLAG_NOTDEF_OUTLINE: If set the notdef glyph outline will be * retained in the final subset. Defaults to false. + * @HB_SUBSET_FLAG_GLYPH_NAMES: If set the PS glyph names will be retained + * in the final subset. Defaults to false. * @HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in * OS/2 will not be recalculated. * @HB_SUBSET_FLAG_RETAIN_ALL_FEATURES: If set all layout features will be @@ -79,6 +81,7 @@ typedef enum HB_SUBSET_FLAG_SET_OVERLAPS_FLAG, HB_SUBSET_FLAG_PASSTHROUGH_UNRECOGNIZED, HB_SUBSET_FLAG_NOTDEF_OUTLINE, + HB_SUBSET_FLAG_GLYPH_NAMES, HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES, HB_SUBSET_FLAG_RETAIN_ALL_FEATURES, } hb_subset_flag_t; diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61,62,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61,62,63.ttf new file mode 100644 index 000000000..3a0c14989 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61,63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61,63.ttf new file mode 100644 index 000000000..f748fbcf0 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61.ttf new file mode 100644 index 000000000..2f5654909 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.61.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.62.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.62.ttf new file mode 100644 index 000000000..831fa96b6 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.62.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.63.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.63.ttf new file mode 100644 index 000000000..2df55a7ea Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.63.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.retain-all-codepoint.ttf new file mode 100644 index 000000000..d89c501f1 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.glyph-names.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61,62,63.ttf b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61,62,63.ttf new file mode 100644 index 000000000..dbed582fb Binary files /dev/null and b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61,63.ttf b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61,63.ttf new file mode 100644 index 000000000..5913420e3 Binary files /dev/null and b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61,63.ttf differ diff --git a/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61.ttf b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61.ttf new file mode 100644 index 000000000..3635f68be Binary files /dev/null and b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.61.ttf differ diff --git a/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.62.ttf b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.62.ttf new file mode 100644 index 000000000..91fcad84a Binary files /dev/null and b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.62.ttf differ diff --git a/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.63.ttf b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.63.ttf new file mode 100644 index 000000000..737cbdc7e Binary files /dev/null and b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.63.ttf differ diff --git a/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.retain-all-codepoint.ttf b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.retain-all-codepoint.ttf new file mode 100644 index 000000000..9744bc31d Binary files /dev/null and b/test/subset/data/expected/basics/NanumMyeongjo-Regular-subset.glyph-names.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61,62,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61,62,63.ttf new file mode 100644 index 000000000..712674fa2 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61,62,63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61,63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61,63.ttf new file mode 100644 index 000000000..f4b4a0852 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61,63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61.ttf new file mode 100644 index 000000000..60e3c5cbb Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.61.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.62.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.62.ttf new file mode 100644 index 000000000..a2916f82b Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.62.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.63.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.63.ttf new file mode 100644 index 000000000..e3964f8e9 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.63.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.retain-all-codepoint.ttf new file mode 100644 index 000000000..712674fa2 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.glyph-names.retain-all-codepoint.ttf differ diff --git a/test/subset/data/profiles/glyph-names.txt b/test/subset/data/profiles/glyph-names.txt new file mode 100644 index 000000000..57df5afd9 --- /dev/null +++ b/test/subset/data/profiles/glyph-names.txt @@ -0,0 +1 @@ +--glyph-names diff --git a/test/subset/data/tests/basics.tests b/test/subset/data/tests/basics.tests index 2e86e218f..12ac8b0f7 100644 --- a/test/subset/data/tests/basics.tests +++ b/test/subset/data/tests/basics.tests @@ -16,6 +16,7 @@ gids.txt layout-features.txt keep-all-layout-features.txt no-prune-unicode-ranges.txt +glyph-names.txt SUBSETS: abc diff --git a/util/options-subset.cc b/util/options-subset.cc index 2b0314aac..ff2288059 100644 --- a/util/options-subset.cc +++ b/util/options-subset.cc @@ -312,6 +312,7 @@ subset_options_t::add_options (option_parser_t *parser) "Set the overlaps flag on each glyph.", nullptr}, {"notdef-outline", 0, 0, G_OPTION_ARG_NONE, &this->input->notdef_outline, "Keep the outline of \'.notdef\' glyph", nullptr}, {"no-prune-unicode-ranges", 0, 0, G_OPTION_ARG_NONE, &this->input->no_prune_unicode_ranges, "Don't change the 'OS/2 ulUnicodeRange*' bits.", nullptr}, + {"glyph-names", 0, 0, G_OPTION_ARG_NONE, &this->input->glyph_names, "Keep PS glyph names in TT-flavored fonts. ", nullptr}, {nullptr} }; parser->add_group (entries,