diff --git a/util/face-options.hh b/util/face-options.hh index 386b9339c..f680e05cd 100644 --- a/util/face-options.hh +++ b/util/face-options.hh @@ -36,6 +36,9 @@ struct face_options_t g_free (font_file); } + void set_face (hb_face_t *face_) + { face = face_; } + void add_options (option_parser_t *parser); void post_parse (GError **error); diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 3817dd5b2..41a61ded6 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -46,8 +46,37 @@ struct subset_main_t : option_parser_t, face_options_t, output_options_t hb_subset_input_destroy (input); } + void parse_face (int argc, const char * const *argv) + { + option_parser_t parser; + face_options_t face_opts; + + face_opts.add_options (&parser); + + GOptionEntry entries[] = + { + {G_OPTION_REMAINING, 0, G_OPTION_FLAG_IN_MAIN, + G_OPTION_ARG_CALLBACK, (gpointer) &collect_face, nullptr, "[FONT-FILE] [TEXT]"}, + {nullptr} + }; + parser.add_main_group (entries, &face_opts); + + g_option_context_set_ignore_unknown_options (parser.context, true); + g_option_context_set_help_enabled (parser.context, false); + + char **args = (char **) g_memdup (argv, argc * sizeof (*argv)); + parser.parse (&argc, &args, true); + g_free (args); + + set_face (face_opts.face); + } + void parse (int argc, char **argv) { + /* Do a preliminary parse to load font-face, such that we can use it + * during main option parsing. */ + parse_face (argc, argv); + add_options (); option_parser_t::parse (&argc, &argv); } @@ -103,6 +132,11 @@ struct subset_main_t : option_parser_t, face_options_t, output_options_t protected: static gboolean + collect_face (const char *name, + const char *arg, + gpointer data, + GError **error); + static gboolean collect_rest (const char *name, const char *arg, gpointer data, @@ -565,6 +599,23 @@ parse_file_for (const char *name, return true; } +gboolean +subset_main_t::collect_face (const char *name, + const char *arg, + gpointer data, + GError **error) +{ + face_options_t *thiz = (face_options_t *) data; + + if (!thiz->font_file) + { + thiz->font_file = g_strdup (arg); + return true; + } + + return true; +} + gboolean subset_main_t::collect_rest (const char *name, const char *arg, diff --git a/util/options.hh b/util/options.hh index b3be16d66..acb341fcb 100644 --- a/util/options.hh +++ b/util/options.hh @@ -126,7 +126,8 @@ struct option_parser_t GOptionGroup *group = g_option_group_new (nullptr, nullptr, nullptr, static_cast(closure), nullptr); g_option_group_add_entries (group, entries); - g_option_group_set_parse_hooks (group, nullptr, post_parse); + /* https://gitlab.gnome.org/GNOME/glib/-/issues/2460 */ + //g_option_group_set_parse_hooks (group, nullptr, post_parse); g_option_context_set_main_group (context, group); } @@ -143,10 +144,10 @@ struct option_parser_t g_ptr_array_add (to_free, p); } - void parse (int *argc, char ***argv); + bool parse (int *argc, char ***argv, bool ignore_error = false); - protected: GOptionContext *context; + protected: GPtrArray *to_free; }; @@ -195,8 +196,8 @@ option_parser_t::add_options () g_option_context_add_main_entries (context, entries, nullptr); } -inline void -option_parser_t::parse (int *argc, char ***argv) +inline bool +option_parser_t::parse (int *argc, char ***argv, bool ignore_error) { setlocale (LC_ALL, ""); @@ -205,12 +206,18 @@ option_parser_t::parse (int *argc, char ***argv) { if (parse_error) { - fail (true, "%s", parse_error->message); - //g_error_free (parse_error); + if (!ignore_error) + fail (true, "%s", parse_error->message); + g_error_free (parse_error); } else - fail (true, "Option parse error"); + { + if (!ignore_error) + fail (true, "Option parse error"); + } + return false; } + return true; }