[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-=sbix"]
|
||||
cli_args.extend (test.get_profile_flags ())
|
||||
print (' '.join (cli_args))
|
||||
ret = subset_cmd (cli_args)
|
||||
|
||||
if ret != "success":
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
if (0 == strcmp (text, "*"))
|
||||
while ((text = get_line (&text_len)))
|
||||
{
|
||||
hb_face_collect_unicodes (face, codepoints);
|
||||
return true;
|
||||
if (0 == strcmp (text, "*"))
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue