From 0ff3618c2d841d16cce9ba2d73321048e7ca6a2d Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Fri, 17 May 2019 15:30:01 -0700 Subject: [PATCH] [subset] Use hb_subset_input_t inside of subset_options_t so that input defaults are shared between the library and cli. --- src/hb-subset-input.cc | 42 ++++++---- src/hb-subset-input.hh | 7 +- src/hb-subset-plan.cc | 3 +- src/hb-subset-plan.hh | 1 - src/hb-subset.cc | 23 +----- src/hb-subset.h | 6 -- test/api/test-subset-glyf.c | 8 +- test/fuzzing/hb-subset-fuzzer.cc | 8 +- util/Makefile.am | 5 +- util/Makefile.sources | 1 + util/hb-subset.cc | 9 +-- util/options-subset.cc | 127 +++++++++++++++++++++++++++++++ util/options.cc | 101 ------------------------ util/options.hh | 20 +---- 14 files changed, 182 insertions(+), 179 deletions(-) create mode 100644 util/options-subset.cc diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc index fa5d9b2a7..8bd6058d0 100644 --- a/src/hb-subset-input.cc +++ b/src/hb-subset-input.cc @@ -47,10 +47,37 @@ hb_subset_input_create_or_fail () input->name_ids = hb_set_create (); input->drop_tables = hb_set_create (); input->drop_hints = false; - input->drop_layout = true; input->desubroutinize = false; input->retain_gids = false; + hb_tag_t default_drop_tables[] = { + // Layout disabled by default + HB_TAG ('G', 'S', 'U', 'B'), + HB_TAG ('G', 'P', 'O', 'S'), + HB_TAG ('G', 'D', 'E', 'F'), + + // Copied from fontTools: + HB_TAG ('B', 'A', 'S', 'E'), + HB_TAG ('J', 'S', 'T', 'F'), + HB_TAG ('D', 'S', 'I', 'G'), + HB_TAG ('E', 'B', 'D', 'T'), + HB_TAG ('E', 'B', 'L', 'C'), + HB_TAG ('E', 'B', 'S', 'C'), + HB_TAG ('S', 'V', 'G', ' '), + HB_TAG ('P', 'C', 'L', 'T'), + HB_TAG ('L', 'T', 'S', 'H'), + // Graphite tables + HB_TAG ('F', 'e', 'a', 't'), + HB_TAG ('G', 'l', 'a', 't'), + HB_TAG ('G', 'l', 'o', 'c'), + HB_TAG ('S', 'i', 'l', 'f'), + HB_TAG ('S', 'i', 'l', 'l'), + // Colour + HB_TAG ('s', 'b', 'i', 'x') + }; + + input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables)); + return input; } @@ -138,19 +165,6 @@ hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input) return subset_input->drop_hints; } -HB_EXTERN void -hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input, - hb_bool_t drop_layout) -{ - subset_input->drop_layout = drop_layout; -} - -HB_EXTERN hb_bool_t -hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input) -{ - return subset_input->drop_layout; -} - HB_EXTERN void hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input, hb_bool_t desubroutinize) diff --git a/src/hb-subset-input.hh b/src/hb-subset-input.hh index 35436f850..f6dd4ac31 100644 --- a/src/hb-subset-input.hh +++ b/src/hb-subset-input.hh @@ -43,10 +43,9 @@ struct hb_subset_input_t hb_set_t *name_ids; hb_set_t *drop_tables; - bool drop_hints : 1; - bool drop_layout : 1; - bool desubroutinize : 1; - bool retain_gids : 1; + bool drop_hints; + bool desubroutinize; + bool retain_gids; /* TODO * * features diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index bdcef37cf..5ea51c4ab 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -236,7 +236,6 @@ hb_subset_plan_create (hb_face_t *face, hb_subset_plan_t *plan = hb_object_create (); plan->drop_hints = input->drop_hints; - plan->drop_layout = input->drop_layout; plan->desubroutinize = input->desubroutinize; plan->retain_gids = input->retain_gids; plan->unicodes = hb_set_create (); @@ -255,7 +254,7 @@ hb_subset_plan_create (hb_face_t *face, plan->_glyphset = _populate_gids_to_retain (face, input->unicodes, input->glyphs, - !plan->drop_layout, + !input->drop_tables->has (HB_OT_TAG_GSUB), plan->unicodes, plan->codepoint_to_glyph); diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index 2443d9b43..6f65e773e 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -40,7 +40,6 @@ struct hb_subset_plan_t hb_object_header_t header; bool drop_hints : 1; - bool drop_layout : 1; bool desubroutinize : 1; bool retain_gids : 1; diff --git a/src/hb-subset.cc b/src/hb-subset.cc index ab5e03122..ba81dbc02 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -249,35 +249,14 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag) case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */ return plan->drop_hints; +#ifdef HB_NO_SUBSET_LAYOUT // Drop Layout Tables if requested. case HB_OT_TAG_GDEF: case HB_OT_TAG_GPOS: case HB_OT_TAG_GSUB: -#ifdef HB_NO_SUBSET_LAYOUT return true; #endif - return plan->drop_layout; - // Drop these tables below by default, list pulled - // from fontTools: - case HB_TAG ('B', 'A', 'S', 'E'): - case HB_TAG ('J', 'S', 'T', 'F'): - case HB_TAG ('D', 'S', 'I', 'G'): - case HB_TAG ('E', 'B', 'D', 'T'): - case HB_TAG ('E', 'B', 'L', 'C'): - case HB_TAG ('E', 'B', 'S', 'C'): - case HB_TAG ('S', 'V', 'G', ' '): - case HB_TAG ('P', 'C', 'L', 'T'): - case HB_TAG ('L', 'T', 'S', 'H'): - // Graphite tables: - case HB_TAG ('F', 'e', 'a', 't'): - case HB_TAG ('G', 'l', 'a', 't'): - case HB_TAG ('G', 'l', 'o', 'c'): - case HB_TAG ('S', 'i', 'l', 'f'): - case HB_TAG ('S', 'i', 'l', 'l'): - // Colour - case HB_TAG ('s', 'b', 'i', 'x'): - return true; default: return false; } diff --git a/src/hb-subset.h b/src/hb-subset.h index 67a4c765a..c778896a2 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -66,12 +66,6 @@ hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input, HB_EXTERN hb_bool_t hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input); -HB_EXTERN void -hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input, - hb_bool_t drop_layout); -HB_EXTERN hb_bool_t -hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input); - HB_EXTERN void hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input, hb_bool_t desubroutinize); diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c index dd9833c58..ad2c8e577 100644 --- a/test/api/test-subset-glyf.c +++ b/test/api/test-subset-glyf.c @@ -137,7 +137,9 @@ test_subset_glyf_with_gsub (void) input = hb_subset_test_create_input (codepoints); hb_set_destroy (codepoints); - hb_subset_input_set_drop_layout (input, false); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'S', 'U', 'B')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'P', 'O', 'S')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'D', 'E', 'F')); face_subset = hb_subset_test_create_subset (face_fil, input); @@ -164,7 +166,9 @@ test_subset_glyf_without_gsub (void) input = hb_subset_test_create_input (codepoints); hb_set_destroy (codepoints); - hb_subset_input_set_drop_layout (input, true); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'S', 'U', 'B')); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'P', 'O', 'S')); + hb_set_add (hb_subset_input_drop_tables_set (input), HB_TAG('G', 'D', 'E', 'F')); face_subset = hb_subset_test_create_subset (face_fil, input); diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc index 56ffd2271..42ef0071e 100644 --- a/test/fuzzing/hb-subset-fuzzer.cc +++ b/test/fuzzing/hb-subset-fuzzer.cc @@ -16,10 +16,16 @@ trySubset (hb_face_t *face, { hb_subset_input_t *input = hb_subset_input_create_or_fail (); hb_subset_input_set_drop_hints (input, drop_hints); - hb_subset_input_set_drop_layout (input, drop_layout); hb_subset_input_set_retain_gids (input, retain_gids); hb_set_t *codepoints = hb_subset_input_unicode_set (input); + if (!drop_layout) + { + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'S', 'U', 'B')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'P', 'O', 'S')); + hb_set_del (hb_subset_input_drop_tables_set (input), HB_TAG ('G', 'D', 'E', 'F')); + } + for (int i = 0; i < text_length; i++) { hb_set_add (codepoints, text[i]); diff --git a/util/Makefile.am b/util/Makefile.am index e24a6f3dc..5298e7732 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -50,8 +50,9 @@ bin_PROGRAMS += hb-shape hb_subset_SOURCES = $(HB_SUBSET_CLI_sources) hb_subset_LDADD = \ - $(LDADD) \ - $(top_builddir)/src/libharfbuzz-subset.la + $(top_builddir)/src/libharfbuzz-subset.la \ + $(LDADD) + bin_PROGRAMS += hb-subset hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources) diff --git a/util/Makefile.sources b/util/Makefile.sources index 6c815d26b..bcf85f562 100644 --- a/util/Makefile.sources +++ b/util/Makefile.sources @@ -32,6 +32,7 @@ HB_OT_SHAPE_CLOSURE_sources = \ HB_SUBSET_CLI_sources = \ hb-subset.cc \ options.cc \ + options-subset.cc \ options.hh \ main-font-text.hh \ $(NULL) diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 5ac541a2a..4b7af8e9a 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -43,7 +43,7 @@ struct subset_consumer_t const font_options_t *font_opts) { font = hb_font_reference (font_opts->get_font ()); - input = hb_subset_input_create_or_fail (); + input = hb_subset_input_reference (subset_options.input); } void consume_line (const char *text, @@ -89,13 +89,6 @@ struct subset_consumer_t void finish (const font_options_t *font_opts) { - hb_subset_input_set_drop_layout (input, !subset_options.keep_layout); - 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_set_set (hb_subset_input_drop_tables_set (input), subset_options.drop_tables); - hb_face_t *face = hb_font_get_face (font); hb_face_t *new_face = hb_subset (face, input); diff --git a/util/options-subset.cc b/util/options-subset.cc new file mode 100644 index 000000000..8ce194604 --- /dev/null +++ b/util/options-subset.cc @@ -0,0 +1,127 @@ +/* + * Copyright © 2019 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. + * + * Google Author(s): Garret Rieger + */ + +#include "options.hh" + +#include "hb-subset-input.hh" + +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 = subset_opts->input->name_ids; + + hb_set_clear (name_ids); + + char *s = (char *) arg; + char *p; + + while (s && *s) + { + while (*s && strchr (", ", *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; + } + + return true; +} + +static gboolean +parse_drop_tables (const char *name, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + subset_options_t *subset_opts = (subset_options_t *) data; + hb_set_t *drop_tables = subset_opts->input->drop_tables; + + char last_name_char = name[strlen (name) - 1]; + + if (last_name_char != '+' && last_name_char != '-') + hb_set_clear (drop_tables); + + char *s = strtok((char *) arg, ", "); + while (s) + { + if (strlen (s) > 4) // Table tags are at most 4 bytes. + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing table tag values at: '%s'", s); + return false; + } + + hb_tag_t tag = hb_tag_from_string (s, strlen (s)); + + if (last_name_char != '-') + hb_set_add (drop_tables, tag); + else + hb_set_del (drop_tables, tag); + + s = strtok(NULL, ", "); + } + + return true; +} + +void +subset_options_t::add_options (option_parser_t *parser) +{ + GOptionEntry entries[] = + { + {"no-hinting", 0, 0, G_OPTION_ARG_NONE, &this->input->drop_hints, "Whether to drop hints", nullptr}, + {"retain-gids", 0, 0, G_OPTION_ARG_NONE, &this->input->retain_gids, "If set don't renumber glyph ids in the subset.", nullptr}, + {"desubroutinize", 0, 0, G_OPTION_ARG_NONE, &this->input->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"}, + {"drop-tables", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables, "Drop the specified tables.", "list of string table tags."}, + {"drop-tables+", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables, "Drop the specified tables.", "list of string table tags."}, + {"drop-tables-", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables, "Drop the specified tables.", "list of string table tags."}, + + {nullptr} + }; + parser->add_group (entries, + "subset", + "Subset options:", + "Options subsetting", + this); +} diff --git a/util/options.cc b/util/options.cc index 1d7798bb3..4e6ca57e7 100644 --- a/util/options.cc +++ b/util/options.cc @@ -972,104 +972,3 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t *buffer, serialize_glyphs (buffer, font, output_format, format_flags, gs); 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 (DELIMITERS, *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; -} - -static gboolean -parse_drop_tables (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_clear (subset_opts->drop_tables); - char *s = (char *) arg; - - while (s && *s) - { - while (*s && strchr (", ", *s)) - s++; - if (!*s) - break; - - char *p = s; - while (*p && !strchr (", ", *p)) - p++; - - if ((p - s) > 4) // Table tags are at most 4 bytes. - { - g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, - "Failed parsing table tag values at: '%s'", s); - return false; - } - - hb_tag_t tag = hb_tag_from_string (s, p -s); - hb_set_add (subset_opts->drop_tables, tag); - s = p; - } - - return true; -} - - -void -subset_options_t::add_options (option_parser_t *parser) -{ - GOptionEntry entries[] = - { - {"layout", 0, 0, G_OPTION_ARG_NONE, &this->keep_layout, "Keep OpenType Layout tables", nullptr}, - {"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"}, - {"drop-tables", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_drop_tables, "Drop the specified tables.", "list of string table tags."}, - - {nullptr} - }; - parser->add_group (entries, - "subset", - "Subset options:", - "Options subsetting", - this); -} diff --git a/util/options.hh b/util/options.hh index 3c3d32b5b..83dbe3402 100644 --- a/util/options.hh +++ b/util/options.hh @@ -28,6 +28,7 @@ #define OPTIONS_HH #include "hb.hh" +#include "hb-subset.h" #include #include @@ -673,31 +674,18 @@ struct subset_options_t : option_group_t { subset_options_t (option_parser_t *parser) { - keep_layout = false; - drop_hints = false; - retain_gids = false; - desubroutinize = false; - name_ids = hb_set_create (); - drop_tables = hb_set_create(); - + input = hb_subset_input_create_or_fail (); add_options (parser); } virtual ~subset_options_t () { - hb_set_destroy (name_ids); - hb_set_destroy (drop_tables); + hb_subset_input_destroy (input); } - 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; - hb_set_t *drop_tables; + hb_subset_input_t *input; }; /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */