[util] Move hb-subset away from main-font-text
This commit is contained in:
parent
3147e081da
commit
58bfe40794
|
@ -56,7 +56,6 @@ def run_test (test, should_check_ots):
|
||||||
"--drop-tables+=DSIG",
|
"--drop-tables+=DSIG",
|
||||||
"--drop-tables-=sbix"]
|
"--drop-tables-=sbix"]
|
||||||
cli_args.extend (test.get_profile_flags ())
|
cli_args.extend (test.get_profile_flags ())
|
||||||
print (' '.join (cli_args))
|
|
||||||
ret = subset_cmd (cli_args)
|
ret = subset_cmd (cli_args)
|
||||||
|
|
||||||
if ret != "success":
|
if ret != "success":
|
||||||
|
|
|
@ -69,8 +69,11 @@ void
|
||||||
face_options_t::post_parse (GError **error)
|
face_options_t::post_parse (GError **error)
|
||||||
{
|
{
|
||||||
if (!font_file)
|
if (!font_file)
|
||||||
|
{
|
||||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||||
"No font file set");
|
"No font file set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert (font_file);
|
assert (font_file);
|
||||||
|
|
||||||
|
@ -95,8 +98,11 @@ face_options_t::post_parse (GError **error)
|
||||||
cache.font_path = g_strdup (font_path);
|
cache.font_path = g_strdup (font_path);
|
||||||
|
|
||||||
if (!cache.blob)
|
if (!cache.blob)
|
||||||
|
{
|
||||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||||
"%s: Failed reading file", font_path);
|
"%s: Failed reading file", font_path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
hb_face_destroy (cache.face);
|
hb_face_destroy (cache.face);
|
||||||
cache.face = nullptr;
|
cache.face = nullptr;
|
||||||
|
|
|
@ -95,13 +95,13 @@ struct output_buffer_t : output_options_t
|
||||||
{
|
{
|
||||||
g_string_set_size (gs, 0);
|
g_string_set_size (gs, 0);
|
||||||
format.serialize_buffer_of_text (buffer, line_no, text, text_len, font, gs);
|
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)
|
void error (const char *message)
|
||||||
{
|
{
|
||||||
g_string_set_size (gs, 0);
|
g_string_set_size (gs, 0);
|
||||||
format.serialize_message (line_no, "error", message, gs);
|
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,
|
void consume_glyphs (hb_buffer_t *buffer,
|
||||||
const char *text,
|
const char *text,
|
||||||
|
@ -111,7 +111,7 @@ struct output_buffer_t : output_options_t
|
||||||
g_string_set_size (gs, 0);
|
g_string_set_size (gs, 0);
|
||||||
format.serialize_buffer_of_glyphs (buffer, line_no, text, text_len, font,
|
format.serialize_buffer_of_glyphs (buffer, line_no, text, text_len, font,
|
||||||
serialize_format, serialize_flags, gs);
|
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)
|
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);
|
g_string_append_printf (gs, "trace: %s buffer: ", message);
|
||||||
format.serialize (buffer, font, serialize_format, serialize_flags, gs);
|
format.serialize (buffer, font, serialize_format, serialize_flags, gs);
|
||||||
g_string_append_c (gs, '\n');
|
g_string_append_c (gs, '\n');
|
||||||
fprintf (fp, "%s", gs->str);
|
fprintf (out_fp, "%s", gs->str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,73 +38,37 @@
|
||||||
* Command line interface to the harfbuzz font subsetter.
|
* Command line interface to the harfbuzz font subsetter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct subset_main_t : option_parser_t, face_options_t, text_options_t, subset_options_t, output_options_t
|
||||||
struct subset_consumer_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);
|
add_options ();
|
||||||
output_options_t::add_options (parser);
|
parse (&argc, &argv);
|
||||||
}
|
|
||||||
|
|
||||||
void init (const face_options_t *face_opts)
|
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
|
||||||
{
|
|
||||||
face = hb_face_reference (face_opts->face);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool consume_line (text_options_t &text_opts)
|
|
||||||
{
|
|
||||||
unsigned int text_len;
|
unsigned int text_len;
|
||||||
const char *text;
|
const char *text;
|
||||||
if (!(text = text_opts.get_line (&text_len)))
|
while ((text = 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);
|
|
||||||
if (0 == strcmp (text, "*"))
|
|
||||||
{
|
{
|
||||||
hb_face_collect_unicodes (face, codepoints);
|
if (0 == strcmp (text, "*"))
|
||||||
return true;
|
{
|
||||||
|
hb_face_collect_unicodes (face, codepoints);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*text)
|
||||||
|
{
|
||||||
|
gchar *c = (gchar *)text;
|
||||||
|
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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *c = (gchar *)text;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
hb_face_t *new_face = nullptr;
|
||||||
for (unsigned i = 0; i < num_iterations; i++)
|
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);
|
new_face = hb_subset_or_fail (face, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
failed = !new_face;
|
bool success = new_face;
|
||||||
if (!failed)
|
if (success)
|
||||||
{
|
{
|
||||||
hb_blob_t *result = hb_face_reference_blob (new_face);
|
hb_blob_t *result = hb_face_reference_blob (new_face);
|
||||||
write_file (output_file, result);
|
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 (new_face);
|
||||||
hb_face_destroy (face);
|
|
||||||
|
return success ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
bool
|
||||||
bool failed = false;
|
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
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
using main_t = main_font_text_t<subset_consumer_t, face_options_t, text_options_t>;
|
return batch_main<subset_main_t, true> (argc, argv);
|
||||||
return batch_main<main_t, true> (argc, argv);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,7 +447,7 @@ helper_cairo_create_context (double w, double h,
|
||||||
const char *extension = out_opts->output_format;
|
const char *extension = out_opts->output_format;
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
#if HAVE_ISATTY
|
#if HAVE_ISATTY
|
||||||
if (isatty (fileno (out_opts->fp)))
|
if (isatty (fileno (out_opts->out_fp)))
|
||||||
{
|
{
|
||||||
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -526,7 +526,7 @@ helper_cairo_create_context (double w, double h,
|
||||||
content = CAIRO_CONTENT_COLOR_ALPHA;
|
content = CAIRO_CONTENT_COLOR_ALPHA;
|
||||||
|
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
FILE *f = out_opts->fp;
|
FILE *f = out_opts->out_fp;
|
||||||
if (constructor)
|
if (constructor)
|
||||||
surface = constructor (stdio_write_func, f, w, h);
|
surface = constructor (stdio_write_func, f, w, h);
|
||||||
else if (constructor2)
|
else if (constructor2)
|
||||||
|
|
|
@ -35,8 +35,8 @@ struct output_options_t
|
||||||
{
|
{
|
||||||
g_free (output_file);
|
g_free (output_file);
|
||||||
g_free (output_format);
|
g_free (output_format);
|
||||||
if (fp && fp != stdout)
|
if (out_fp && out_fp != stdout)
|
||||||
fclose (fp);
|
fclose (out_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_options (option_parser_t *parser,
|
void add_options (option_parser_t *parser,
|
||||||
|
@ -48,7 +48,7 @@ struct output_options_t
|
||||||
char *output_format = nullptr;
|
char *output_format = nullptr;
|
||||||
|
|
||||||
bool explicit_output_format = false;
|
bool explicit_output_format = false;
|
||||||
FILE *fp = nullptr;
|
FILE *out_fp = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -71,18 +71,21 @@ output_options_t::post_parse (GError **error)
|
||||||
output_file = nullptr; /* STDOUT */
|
output_file = nullptr; /* STDOUT */
|
||||||
|
|
||||||
if (output_file)
|
if (output_file)
|
||||||
fp = fopen (output_file, "wb");
|
out_fp = fopen (output_file, "wb");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
setmode (fileno (stdout), O_BINARY);
|
setmode (fileno (stdout), O_BINARY);
|
||||||
#endif
|
#endif
|
||||||
fp = stdout;
|
out_fp = stdout;
|
||||||
}
|
}
|
||||||
if (!fp)
|
if (!out_fp)
|
||||||
|
{
|
||||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||||
"Cannot open output file `%s': %s",
|
"Cannot open output file `%s': %s",
|
||||||
g_filename_display_name (output_file), strerror (errno));
|
g_filename_display_name (output_file), strerror (errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -322,15 +322,18 @@ parse_shapers (const char *name G_GNUC_UNUSED,
|
||||||
shape_options_t *shape_opts = (shape_options_t *) data;
|
shape_options_t *shape_opts = (shape_options_t *) data;
|
||||||
char **shapers = g_strsplit (arg, ",", 0);
|
char **shapers = g_strsplit (arg, ",", 0);
|
||||||
|
|
||||||
for (char **shaper = shapers; *shaper; shaper++) {
|
for (char **shaper = shapers; *shaper; shaper++)
|
||||||
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (const char **hb_shaper = hb_shape_list_shapers (); *hb_shaper; hb_shaper++) {
|
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;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found)
|
||||||
|
{
|
||||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
|
||||||
"Unknown or unsupported shaper: %s", *shaper);
|
"Unknown or unsupported shaper: %s", *shaper);
|
||||||
g_strfreev (shapers);
|
g_strfreev (shapers);
|
||||||
|
|
|
@ -40,8 +40,8 @@ struct text_options_t
|
||||||
g_free (text_file);
|
g_free (text_file);
|
||||||
if (gs)
|
if (gs)
|
||||||
g_string_free (gs, true);
|
g_string_free (gs, true);
|
||||||
if (fp && fp != stdin)
|
if (in_fp && in_fp != stdin)
|
||||||
fclose (fp);
|
fclose (in_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_options (option_parser_t *parser);
|
void add_options (option_parser_t *parser);
|
||||||
|
@ -62,11 +62,11 @@ struct text_options_t
|
||||||
if (text_file)
|
if (text_file)
|
||||||
{
|
{
|
||||||
if (0 != strcmp (text_file, "-"))
|
if (0 != strcmp (text_file, "-"))
|
||||||
fp = fopen (text_file, "r");
|
in_fp = fopen (text_file, "r");
|
||||||
else
|
else
|
||||||
fp = stdin;
|
in_fp = stdin;
|
||||||
|
|
||||||
if (!fp)
|
if (!in_fp)
|
||||||
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
|
||||||
"Failed opening text file `%s': %s",
|
"Failed opening text file `%s': %s",
|
||||||
text_file, strerror (errno));
|
text_file, strerror (errno));
|
||||||
|
@ -80,7 +80,7 @@ struct text_options_t
|
||||||
char *text_file = nullptr;
|
char *text_file = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE *fp = nullptr;
|
FILE *in_fp = nullptr;
|
||||||
GString *gs = nullptr;
|
GString *gs = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ text_options_t::get_line (unsigned int *len)
|
||||||
|
|
||||||
g_string_set_size (gs, 0);
|
g_string_set_size (gs, 0);
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
while (fgets (buf, sizeof (buf), fp))
|
while (fgets (buf, sizeof (buf), in_fp))
|
||||||
{
|
{
|
||||||
unsigned bytes = strlen (buf);
|
unsigned bytes = strlen (buf);
|
||||||
if (bytes && buf[bytes - 1] == '\n')
|
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);
|
g_string_append_len (gs, buf, bytes);
|
||||||
}
|
}
|
||||||
if (ferror (fp))
|
if (ferror (in_fp))
|
||||||
fail (false, "Failed reading text: %s", strerror (errno));
|
fail (false, "Failed reading text: %s", strerror (errno));
|
||||||
*len = gs->len;
|
*len = gs->len;
|
||||||
return !*len && feof (fp) ? nullptr : gs->str;
|
return !*len && feof (in_fp) ? nullptr : gs->str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue