[subset] Use hb_subset_input_t inside of subset_options_t so that input defaults are shared between the library and cli.

This commit is contained in:
Garret Rieger 2019-05-17 15:30:01 -07:00
parent 67064294a0
commit 0ff3618c2d
14 changed files with 182 additions and 179 deletions

View File

@ -47,10 +47,37 @@ hb_subset_input_create_or_fail ()
input->name_ids = hb_set_create (); input->name_ids = hb_set_create ();
input->drop_tables = hb_set_create (); input->drop_tables = hb_set_create ();
input->drop_hints = false; input->drop_hints = false;
input->drop_layout = true;
input->desubroutinize = false; input->desubroutinize = false;
input->retain_gids = 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; return input;
} }
@ -138,19 +165,6 @@ hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input)
return subset_input->drop_hints; 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_EXTERN void
hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input, hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
hb_bool_t desubroutinize) hb_bool_t desubroutinize)

View File

@ -43,10 +43,9 @@ struct hb_subset_input_t
hb_set_t *name_ids; hb_set_t *name_ids;
hb_set_t *drop_tables; hb_set_t *drop_tables;
bool drop_hints : 1; bool drop_hints;
bool drop_layout : 1; bool desubroutinize;
bool desubroutinize : 1; bool retain_gids;
bool retain_gids : 1;
/* TODO /* TODO
* *
* features * features

View File

@ -236,7 +236,6 @@ hb_subset_plan_create (hb_face_t *face,
hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> (); hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
plan->drop_hints = input->drop_hints; plan->drop_hints = input->drop_hints;
plan->drop_layout = input->drop_layout;
plan->desubroutinize = input->desubroutinize; plan->desubroutinize = input->desubroutinize;
plan->retain_gids = input->retain_gids; plan->retain_gids = input->retain_gids;
plan->unicodes = hb_set_create (); plan->unicodes = hb_set_create ();
@ -255,7 +254,7 @@ hb_subset_plan_create (hb_face_t *face,
plan->_glyphset = _populate_gids_to_retain (face, plan->_glyphset = _populate_gids_to_retain (face,
input->unicodes, input->unicodes,
input->glyphs, input->glyphs,
!plan->drop_layout, !input->drop_tables->has (HB_OT_TAG_GSUB),
plan->unicodes, plan->unicodes,
plan->codepoint_to_glyph); plan->codepoint_to_glyph);

View File

@ -40,7 +40,6 @@ struct hb_subset_plan_t
hb_object_header_t header; hb_object_header_t header;
bool drop_hints : 1; bool drop_hints : 1;
bool drop_layout : 1;
bool desubroutinize : 1; bool desubroutinize : 1;
bool retain_gids : 1; bool retain_gids : 1;

View File

@ -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 */ case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
return plan->drop_hints; return plan->drop_hints;
#ifdef HB_NO_SUBSET_LAYOUT
// Drop Layout Tables if requested. // Drop Layout Tables if requested.
case HB_OT_TAG_GDEF: case HB_OT_TAG_GDEF:
case HB_OT_TAG_GPOS: case HB_OT_TAG_GPOS:
case HB_OT_TAG_GSUB: case HB_OT_TAG_GSUB:
#ifdef HB_NO_SUBSET_LAYOUT
return true; return true;
#endif #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: default:
return false; return false;
} }

View File

@ -66,12 +66,6 @@ hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
HB_EXTERN hb_bool_t HB_EXTERN hb_bool_t
hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input); 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_EXTERN void
hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input, hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
hb_bool_t desubroutinize); hb_bool_t desubroutinize);

View File

@ -137,7 +137,9 @@ test_subset_glyf_with_gsub (void)
input = hb_subset_test_create_input (codepoints); input = hb_subset_test_create_input (codepoints);
hb_set_destroy (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); 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); input = hb_subset_test_create_input (codepoints);
hb_set_destroy (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); face_subset = hb_subset_test_create_subset (face_fil, input);

View File

@ -16,10 +16,16 @@ trySubset (hb_face_t *face,
{ {
hb_subset_input_t *input = hb_subset_input_create_or_fail (); 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_hints (input, drop_hints);
hb_subset_input_set_drop_layout (input, drop_layout);
hb_subset_input_set_retain_gids (input, retain_gids); hb_subset_input_set_retain_gids (input, retain_gids);
hb_set_t *codepoints = hb_subset_input_unicode_set (input); 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++) for (int i = 0; i < text_length; i++)
{ {
hb_set_add (codepoints, text[i]); hb_set_add (codepoints, text[i]);

View File

@ -50,8 +50,9 @@ bin_PROGRAMS += hb-shape
hb_subset_SOURCES = $(HB_SUBSET_CLI_sources) hb_subset_SOURCES = $(HB_SUBSET_CLI_sources)
hb_subset_LDADD = \ hb_subset_LDADD = \
$(LDADD) \ $(top_builddir)/src/libharfbuzz-subset.la \
$(top_builddir)/src/libharfbuzz-subset.la $(LDADD)
bin_PROGRAMS += hb-subset bin_PROGRAMS += hb-subset
hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources) hb_ot_shape_closure_SOURCES = $(HB_OT_SHAPE_CLOSURE_sources)

View File

@ -32,6 +32,7 @@ HB_OT_SHAPE_CLOSURE_sources = \
HB_SUBSET_CLI_sources = \ HB_SUBSET_CLI_sources = \
hb-subset.cc \ hb-subset.cc \
options.cc \ options.cc \
options-subset.cc \
options.hh \ options.hh \
main-font-text.hh \ main-font-text.hh \
$(NULL) $(NULL)

View File

@ -43,7 +43,7 @@ struct subset_consumer_t
const font_options_t *font_opts) const font_options_t *font_opts)
{ {
font = hb_font_reference (font_opts->get_font ()); 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, void consume_line (const char *text,
@ -89,13 +89,6 @@ struct subset_consumer_t
void finish (const font_options_t *font_opts) 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 *face = hb_font_get_face (font);
hb_face_t *new_face = hb_subset (face, input); hb_face_t *new_face = hb_subset (face, input);

127
util/options-subset.cc Normal file
View File

@ -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);
}

View File

@ -972,104 +972,3 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t *buffer,
serialize_glyphs (buffer, font, output_format, format_flags, gs); serialize_glyphs (buffer, font, output_format, format_flags, gs);
g_string_append_c (gs, '\n'); 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);
}

View File

@ -28,6 +28,7 @@
#define OPTIONS_HH #define OPTIONS_HH
#include "hb.hh" #include "hb.hh"
#include "hb-subset.h"
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
@ -673,31 +674,18 @@ struct subset_options_t : option_group_t
{ {
subset_options_t (option_parser_t *parser) subset_options_t (option_parser_t *parser)
{ {
keep_layout = false; input = hb_subset_input_create_or_fail ();
drop_hints = false;
retain_gids = false;
desubroutinize = false;
name_ids = hb_set_create ();
drop_tables = hb_set_create();
add_options (parser); add_options (parser);
} }
virtual ~subset_options_t () virtual ~subset_options_t ()
{ {
hb_set_destroy (name_ids); hb_subset_input_destroy (input);
hb_set_destroy (drop_tables);
} }
void add_options (option_parser_t *parser); void add_options (option_parser_t *parser);
hb_bool_t keep_layout; hb_subset_input_t *input;
hb_bool_t drop_hints;
hb_bool_t retain_gids;
hb_bool_t desubroutinize;
hb_set_t *name_ids;
hb_set_t *drop_tables;
}; };
/* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */ /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */