[util] Move hb-subset away from main-font-text

This commit is contained in:
Behdad Esfahbod 2021-08-11 19:48:28 -06:00
parent 3147e081da
commit 58bfe40794
8 changed files with 129 additions and 92 deletions

View File

@ -56,7 +56,6 @@ def run_test (test, should_check_ots):
"--drop-tables+=DSIG",
"--drop-tables-=sbix"]
cli_args.extend (test.get_profile_flags ())
print (' '.join (cli_args))
ret = subset_cmd (cli_args)
if ret != "success":

View File

@ -69,8 +69,11 @@ void
face_options_t::post_parse (GError **error)
{
if (!font_file)
{
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
"No font file set");
return;
}
assert (font_file);
@ -95,8 +98,11 @@ face_options_t::post_parse (GError **error)
cache.font_path = g_strdup (font_path);
if (!cache.blob)
{
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
"%s: Failed reading file", font_path);
return;
}
hb_face_destroy (cache.face);
cache.face = nullptr;

View File

@ -95,13 +95,13 @@ struct output_buffer_t : output_options_t
{
g_string_set_size (gs, 0);
format.serialize_buffer_of_text (buffer, line_no, text, text_len, font, gs);
fprintf (fp, "%s", gs->str);
fprintf (out_fp, "%s", gs->str);
}
void error (const char *message)
{
g_string_set_size (gs, 0);
format.serialize_message (line_no, "error", message, gs);
fprintf (fp, "%s", gs->str);
fprintf (out_fp, "%s", gs->str);
}
void consume_glyphs (hb_buffer_t *buffer,
const char *text,
@ -111,7 +111,7 @@ struct output_buffer_t : output_options_t
g_string_set_size (gs, 0);
format.serialize_buffer_of_glyphs (buffer, line_no, text, text_len, font,
serialize_format, serialize_flags, gs);
fprintf (fp, "%s", gs->str);
fprintf (out_fp, "%s", gs->str);
}
void finish (hb_buffer_t *buffer, const font_options_t *font_opts)
{
@ -143,7 +143,7 @@ struct output_buffer_t : output_options_t
g_string_append_printf (gs, "trace: %s buffer: ", message);
format.serialize (buffer, font, serialize_format, serialize_flags, gs);
g_string_append_c (gs, '\n');
fprintf (fp, "%s", gs->str);
fprintf (out_fp, "%s", gs->str);
}

View File

@ -38,73 +38,37 @@
* Command line interface to the harfbuzz font subsetter.
*/
struct subset_consumer_t : subset_options_t, output_options_t
struct subset_main_t : option_parser_t, face_options_t, text_options_t, subset_options_t, output_options_t
{
void add_options (option_parser_t *parser)
int operator () (int argc, char **argv)
{
subset_options_t::add_options (parser);
output_options_t::add_options (parser);
}
add_options ();
parse (&argc, &argv);
void init (const face_options_t *face_opts)
{
face = hb_face_reference (face_opts->face);
}
bool consume_line (text_options_t &text_opts)
{
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
unsigned int text_len;
const char *text;
if (!(text = text_opts.get_line (&text_len)))
return false;
// TODO does this only get called with at least 1 codepoint?
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
while ((text = get_line (&text_len)))
{
if (0 == strcmp (text, "*"))
{
hb_face_collect_unicodes (face, codepoints);
return true;
continue;
}
if (*text)
{
gchar *c = (gchar *)text;
do {
do
{
gunichar cp = g_utf8_get_char(c);
hb_codepoint_t hb_cp = cp;
hb_set_add (codepoints, hb_cp);
} while ((c = g_utf8_find_next_char(c, text + text_len)));
return true;
}
while ((c = g_utf8_find_next_char(c, text + text_len)));
}
}
hb_bool_t
write_file (const char *output_file, hb_blob_t *blob) {
unsigned int size;
const char* data = hb_blob_get_data (blob, &size);
if (!output_file)
fail (true, "No output file was specified");
FILE *fp = fopen(output_file, "wb");
if (!fp)
fail (false, "Cannot open output file `%s': %s",
g_filename_display_name (output_file), strerror (errno));
while (size) {
size_t ret = fwrite (data, 1, size, fp);
size -= ret;
data += ret;
if (size && ferror (fp))
fail (false, "Failed to write output: %s", strerror (errno));
}
fclose (fp);
return true;
}
void finish (const face_options_t *face_opts)
{
hb_face_t *new_face = nullptr;
for (unsigned i = 0; i < num_iterations; i++)
{
@ -112,8 +76,8 @@ struct subset_consumer_t : subset_options_t, output_options_t
new_face = hb_subset_or_fail (face, input);
}
failed = !new_face;
if (!failed)
bool success = new_face;
if (success)
{
hb_blob_t *result = hb_face_reference_blob (new_face);
write_file (output_file, result);
@ -121,18 +85,80 @@ struct subset_consumer_t : subset_options_t, output_options_t
}
hb_face_destroy (new_face);
hb_face_destroy (face);
return success ? 0 : 1;
}
public:
bool failed = false;
bool
write_file (const char *output_file, hb_blob_t *blob)
{
if (!output_file)
fail (true, "No output file was specified");
hb_face_t *face = nullptr;
unsigned int size;
const char* data = hb_blob_get_data (blob, &size);
while (size)
{
size_t ret = fwrite (data, 1, size, out_fp);
size -= ret;
data += ret;
if (size && ferror (out_fp))
fail (false, "Failed to write output: %s", strerror (errno));
}
return true;
}
protected:
void add_options ()
{
face_options_t::add_options (this);
text_options_t::add_options (this);
subset_options_t::add_options (this);
output_options_t::add_options (this);
GOptionEntry entries[] =
{
{G_OPTION_REMAINING, 0, G_OPTION_FLAG_IN_MAIN,
G_OPTION_ARG_CALLBACK, (gpointer) &collect_rest, nullptr, "[FONT-FILE] [TEXT]"},
{nullptr}
};
add_main_group (entries, this);
option_parser_t::add_options ();
}
private:
static gboolean
collect_rest (const char *name G_GNUC_UNUSED,
const char *arg,
gpointer data,
GError **error)
{
subset_main_t *thiz = (subset_main_t *) data;
if (!thiz->font_file)
{
thiz->font_file = g_strdup (arg);
return true;
}
if (!thiz->text && !thiz->text_file)
{
thiz->text = g_strdup (arg);
return true;
}
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
"Too many arguments on the command line");
return false;
}
};
int
main (int argc, char **argv)
{
using main_t = main_font_text_t<subset_consumer_t, face_options_t, text_options_t>;
return batch_main<main_t, true> (argc, argv);
return batch_main<subset_main_t, true> (argc, argv);
}

View File

@ -447,7 +447,7 @@ helper_cairo_create_context (double w, double h,
const char *extension = out_opts->output_format;
if (!extension) {
#if HAVE_ISATTY
if (isatty (fileno (out_opts->fp)))
if (isatty (fileno (out_opts->out_fp)))
{
#ifdef CAIRO_HAS_PNG_FUNCTIONS
const char *name;
@ -526,7 +526,7 @@ helper_cairo_create_context (double w, double h,
content = CAIRO_CONTENT_COLOR_ALPHA;
cairo_surface_t *surface;
FILE *f = out_opts->fp;
FILE *f = out_opts->out_fp;
if (constructor)
surface = constructor (stdio_write_func, f, w, h);
else if (constructor2)

View File

@ -35,8 +35,8 @@ struct output_options_t
{
g_free (output_file);
g_free (output_format);
if (fp && fp != stdout)
fclose (fp);
if (out_fp && out_fp != stdout)
fclose (out_fp);
}
void add_options (option_parser_t *parser,
@ -48,7 +48,7 @@ struct output_options_t
char *output_format = nullptr;
bool explicit_output_format = false;
FILE *fp = nullptr;
FILE *out_fp = nullptr;
};
void
@ -71,18 +71,21 @@ output_options_t::post_parse (GError **error)
output_file = nullptr; /* STDOUT */
if (output_file)
fp = fopen (output_file, "wb");
out_fp = fopen (output_file, "wb");
else
{
#if defined(_WIN32) || defined(__CYGWIN__)
setmode (fileno (stdout), O_BINARY);
#endif
fp = stdout;
out_fp = stdout;
}
if (!fp)
if (!out_fp)
{
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
"Cannot open output file `%s': %s",
g_filename_display_name (output_file), strerror (errno));
return;
}
}
void

View File

@ -322,15 +322,18 @@ parse_shapers (const char *name G_GNUC_UNUSED,
shape_options_t *shape_opts = (shape_options_t *) data;
char **shapers = g_strsplit (arg, ",", 0);
for (char **shaper = shapers; *shaper; shaper++) {
for (char **shaper = shapers; *shaper; shaper++)
{
bool found = false;
for (const char **hb_shaper = hb_shape_list_shapers (); *hb_shaper; hb_shaper++) {
if (strcmp (*shaper, *hb_shaper) == 0) {
if (strcmp (*shaper, *hb_shaper) == 0)
{
found = true;
break;
}
}
if (!found) {
if (!found)
{
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Unknown or unsupported shaper: %s", *shaper);
g_strfreev (shapers);

View File

@ -40,8 +40,8 @@ struct text_options_t
g_free (text_file);
if (gs)
g_string_free (gs, true);
if (fp && fp != stdin)
fclose (fp);
if (in_fp && in_fp != stdin)
fclose (in_fp);
}
void add_options (option_parser_t *parser);
@ -62,11 +62,11 @@ struct text_options_t
if (text_file)
{
if (0 != strcmp (text_file, "-"))
fp = fopen (text_file, "r");
in_fp = fopen (text_file, "r");
else
fp = stdin;
in_fp = stdin;
if (!fp)
if (!in_fp)
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
"Failed opening text file `%s': %s",
text_file, strerror (errno));
@ -80,7 +80,7 @@ struct text_options_t
char *text_file = nullptr;
private:
FILE *fp = nullptr;
FILE *in_fp = nullptr;
GString *gs = nullptr;
};
@ -197,7 +197,7 @@ text_options_t::get_line (unsigned int *len)
g_string_set_size (gs, 0);
char buf[BUFSIZ];
while (fgets (buf, sizeof (buf), fp))
while (fgets (buf, sizeof (buf), in_fp))
{
unsigned bytes = strlen (buf);
if (bytes && buf[bytes - 1] == '\n')
@ -208,10 +208,10 @@ text_options_t::get_line (unsigned int *len)
}
g_string_append_len (gs, buf, bytes);
}
if (ferror (fp))
if (ferror (in_fp))
fail (false, "Failed reading text: %s", strerror (errno));
*len = gs->len;
return !*len && feof (fp) ? nullptr : gs->str;
return !*len && feof (in_fp) ? nullptr : gs->str;
}
void