[subset] support option --glyph-names

This commit is contained in:
Qunxin Liu 2021-07-20 20:05:35 -07:00
parent b235511ed8
commit 71b5509c19
30 changed files with 152 additions and 4 deletions

View File

@ -257,6 +257,7 @@ HB_SUBSET_sources = \
hb-ot-cff1-table.cc \ hb-ot-cff1-table.cc \
hb-ot-cff2-table.cc \ hb-ot-cff2-table.cc \
hb-ot-color-colrv1-closure.hh \ hb-ot-color-colrv1-closure.hh \
hb-ot-post-table-v2subset.hh \
hb-static.cc \ hb-static.cc \
hb-subset-cff-common.cc \ hb-subset-cff-common.cc \
hb-subset-cff-common.hh \ hb-subset-cff-common.hh \

View File

@ -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<typename Iterator>
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<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
HBUINT8 *o = c->allocate_size<HBUINT8> (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<unsigned, unsigned> (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 */

View File

@ -55,6 +55,13 @@ struct postV2Tail
return_trace (glyphNameIndex.sanitize (c)); return_trace (glyphNameIndex.sanitize (c));
} }
template<typename Iterator>
bool serialize (hb_serialize_context_t *c,
Iterator it,
const void* _post) const;
bool subset (hb_subset_context_t *c) const;
protected: protected:
Array16Of<HBUINT16> glyphNameIndex; /* This is not an offset, but is the Array16Of<HBUINT16> glyphNameIndex; /* This is not an offset, but is the
* ordinal number of the glyph in 'post' * ordinal number of the glyph in 'post'
@ -71,13 +78,18 @@ struct post
{ {
static constexpr hb_tag_t tableTag = HB_OT_TAG_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<post> (); post *post_prime = c->allocate_min<post> ();
if (unlikely (!post_prime)) return; if (unlikely (!post_prime)) return_trace (false);
memcpy (post_prime, this, post::min_size); 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 bool subset (hb_subset_context_t *c) const
@ -86,13 +98,18 @@ struct post
post *post_prime = c->serializer->start_embed<post> (); post *post_prime = c->serializer->start_embed<post> ();
if (unlikely (!post_prime)) return_trace (false); 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); return_trace (true);
} }
struct accelerator_t struct accelerator_t
{ {
friend struct postV2Tail;
void init (hb_face_t *face) void init (hb_face_t *face)
{ {
index_to_offset.init (); index_to_offset.init ();

View File

@ -57,6 +57,7 @@ hb_subset_input_create_or_fail ()
input->name_legacy = false; input->name_legacy = false;
input->overlaps_flag = false; input->overlaps_flag = false;
input->notdef_outline = false; input->notdef_outline = false;
input->glyph_names = false;
input->no_prune_unicode_ranges = false; input->no_prune_unicode_ranges = false;
input->retain_all_layout_features = false; input->retain_all_layout_features = false;
input->passthrough_unrecognized = false; input->passthrough_unrecognized = false;
@ -375,6 +376,8 @@ hb_subset_input_get_flag (hb_subset_input_t *input,
return input->passthrough_unrecognized; return input->passthrough_unrecognized;
case HB_SUBSET_FLAG_NOTDEF_OUTLINE: case HB_SUBSET_FLAG_NOTDEF_OUTLINE:
return input->notdef_outline; return input->notdef_outline;
case HB_SUBSET_FLAG_GLYPH_NAMES:
return input->glyph_names;
case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES: case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES:
return input->no_prune_unicode_ranges; return input->no_prune_unicode_ranges;
default: default:
@ -420,6 +423,9 @@ hb_subset_input_set_flag (hb_subset_input_t *input,
case HB_SUBSET_FLAG_NOTDEF_OUTLINE: case HB_SUBSET_FLAG_NOTDEF_OUTLINE:
input->notdef_outline = value; input->notdef_outline = value;
break; break;
case HB_SUBSET_FLAG_GLYPH_NAMES:
input->glyph_names = value;
break;
case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES: case HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES:
input->no_prune_unicode_ranges = value; input->no_prune_unicode_ranges = value;
break; break;

View File

@ -53,6 +53,7 @@ struct hb_subset_input_t
hb_bool_t name_legacy; hb_bool_t name_legacy;
hb_bool_t overlaps_flag; hb_bool_t overlaps_flag;
hb_bool_t notdef_outline; hb_bool_t notdef_outline;
hb_bool_t glyph_names;
hb_bool_t no_prune_unicode_ranges; hb_bool_t no_prune_unicode_ranges;
hb_bool_t retain_all_layout_features; hb_bool_t retain_all_layout_features;
hb_bool_t passthrough_unrecognized; hb_bool_t passthrough_unrecognized;

View File

@ -428,6 +428,7 @@ hb_subset_plan_create (hb_face_t *face,
plan->name_legacy = input->name_legacy; plan->name_legacy = input->name_legacy;
plan->overlaps_flag = input->overlaps_flag; plan->overlaps_flag = input->overlaps_flag;
plan->notdef_outline = input->notdef_outline; plan->notdef_outline = input->notdef_outline;
plan->glyph_names = input->glyph_names;
plan->prune_unicode_ranges = !input->no_prune_unicode_ranges; plan->prune_unicode_ranges = !input->no_prune_unicode_ranges;
plan->retain_all_layout_features = input->retain_all_layout_features; plan->retain_all_layout_features = input->retain_all_layout_features;
plan->passthrough_unrecognized = input->passthrough_unrecognized; plan->passthrough_unrecognized = input->passthrough_unrecognized;

View File

@ -46,6 +46,7 @@ struct hb_subset_plan_t
bool name_legacy : 1; bool name_legacy : 1;
bool overlaps_flag : 1; bool overlaps_flag : 1;
bool notdef_outline : 1; bool notdef_outline : 1;
bool glyph_names : 1;
bool prune_unicode_ranges : 1; bool prune_unicode_ranges : 1;
bool retain_all_layout_features : 1; bool retain_all_layout_features : 1;
bool passthrough_unrecognized : 1; bool passthrough_unrecognized : 1;

View File

@ -42,6 +42,7 @@
#include "hb-ot-color-cpal-table.hh" #include "hb-ot-color-cpal-table.hh"
#include "hb-ot-os2-table.hh" #include "hb-ot-os2-table.hh"
#include "hb-ot-post-table.hh" #include "hb-ot-post-table.hh"
#include "hb-ot-post-table-v2subset.hh"
#include "hb-ot-cff1-table.hh" #include "hb-ot-cff1-table.hh"
#include "hb-ot-cff2-table.hh" #include "hb-ot-cff2-table.hh"
#include "hb-ot-vorg-table.hh" #include "hb-ot-vorg-table.hh"

View File

@ -59,6 +59,8 @@ typedef struct hb_subset_input_t hb_subset_input_t;
* Defaults to false. * Defaults to false.
* @HB_SUBSET_FLAG_NOTDEF_OUTLINE: If set the notdef glyph outline will be * @HB_SUBSET_FLAG_NOTDEF_OUTLINE: If set the notdef glyph outline will be
* retained in the final subset. Defaults to false. * 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 * @HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
* OS/2 will not be recalculated. * OS/2 will not be recalculated.
* *
@ -75,6 +77,7 @@ typedef enum
HB_SUBSET_FLAG_SET_OVERLAPS_FLAG, HB_SUBSET_FLAG_SET_OVERLAPS_FLAG,
HB_SUBSET_FLAG_PASSTHROUGH_UNRECOGNIZED, HB_SUBSET_FLAG_PASSTHROUGH_UNRECOGNIZED,
HB_SUBSET_FLAG_NOTDEF_OUTLINE, HB_SUBSET_FLAG_NOTDEF_OUTLINE,
HB_SUBSET_FLAG_GLYPH_NAMES,
HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES, HB_SUBSET_FLAG_NO_PRUNE_UNICODE_RANGES,
} hb_subset_flag_t; } hb_subset_flag_t;

View File

@ -0,0 +1 @@
--glyph-names

View File

@ -16,6 +16,7 @@ gids.txt
layout-features.txt layout-features.txt
keep-all-layout-features.txt keep-all-layout-features.txt
no-prune-unicode-ranges.txt no-prune-unicode-ranges.txt
glyph-names.txt
SUBSETS: SUBSETS:
abc abc

View File

@ -312,6 +312,7 @@ subset_options_t::add_options (option_parser_t *parser)
"Set the overlaps flag on each glyph.", nullptr}, "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}, {"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}, {"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} {nullptr}
}; };
parser->add_group (entries, parser->add_group (entries,