| /* |
| * Copyright © 2011 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): Behdad Esfahbod |
| */ |
| |
| #ifndef FACE_OPTIONS_HH |
| #define FACE_OPTIONS_HH |
| |
| #include "options.hh" |
| |
| struct face_options_t |
| { |
| ~face_options_t () |
| { |
| g_free (font_file); |
| g_free (face_loader); |
| hb_face_destroy (face); |
| } |
| |
| void set_face (hb_face_t *face_) |
| { |
| hb_face_destroy (face); |
| face = hb_face_reference (face_); |
| } |
| |
| void add_options (option_parser_t *parser); |
| |
| void post_parse (GError **error); |
| |
| static struct cache_t |
| { |
| ~cache_t () |
| { |
| g_free (font_path); |
| g_free (face_loader); |
| hb_face_destroy (face); |
| } |
| |
| char *font_path = nullptr; |
| char *face_loader = nullptr; |
| unsigned face_index = (unsigned) -1; |
| hb_face_t *face = nullptr; |
| } cache; |
| |
| char *font_file = nullptr; |
| unsigned face_index = 0; |
| char *face_loader = nullptr; |
| |
| hb_face_t *face = nullptr; |
| }; |
| |
| |
| face_options_t::cache_t face_options_t::cache {}; |
| |
| 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); |
| |
| const char *font_path = font_file; |
| |
| if (0 == strcmp (font_path, "-")) |
| { |
| #if defined(_WIN32) || defined(__CYGWIN__) |
| setmode (fileno (stdin), O_BINARY); |
| font_path = "STDIN"; |
| #else |
| font_path = "/dev/stdin"; |
| #endif |
| } |
| |
| if ((!cache.font_path || 0 != strcmp (cache.font_path, font_path)) || |
| (cache.face_loader != face_loader && |
| (cache.face_loader && face_loader && 0 != strcmp (cache.face_loader, face_loader))) || |
| cache.face_index != face_index) |
| { |
| hb_face_destroy (cache.face); |
| cache.face = hb_face_create_from_file_or_fail_using (font_path, face_index, face_loader); |
| cache.face_index = face_index; |
| |
| g_free ((char *) cache.font_path); |
| g_free ((char *) cache.face_loader); |
| cache.font_path = g_strdup (font_path); |
| cache.face_loader = face_loader ? g_strdup (face_loader) : nullptr; |
| |
| if (!cache.face) |
| { |
| g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, |
| "%s: Failed loading font face", font_path); |
| return_value = RETURN_VALUE_FACE_LOAD_FAILED; |
| return; |
| } |
| } |
| |
| set_face (cache.face); |
| } |
| |
| static G_GNUC_NORETURN gboolean |
| list_face_loaders (const char *name G_GNUC_UNUSED, |
| const char *arg G_GNUC_UNUSED, |
| gpointer data G_GNUC_UNUSED, |
| GError **error G_GNUC_UNUSED) |
| { |
| for (const char **funcs = hb_face_list_loaders (); *funcs; funcs++) |
| g_printf ("%s\n", *funcs); |
| |
| exit(0); |
| } |
| |
| void |
| face_options_t::add_options (option_parser_t *parser) |
| { |
| char *face_loaders_text = nullptr; |
| { |
| const char **supported_face_loaders = hb_face_list_loaders (); |
| GString *s = g_string_new (nullptr); |
| if (unlikely (!supported_face_loaders)) |
| g_string_printf (s, "Set face loader to use (default: none)\n No supported face loaders found"); |
| else |
| { |
| char *supported_str = g_strjoinv ("/", (char **) supported_face_loaders); |
| g_string_printf (s, "Set face loader to use (default: %s)\n Supported face loaders are: %s", |
| supported_face_loaders[0], |
| supported_str); |
| g_free (supported_str); |
| } |
| face_loaders_text = g_string_free (s, FALSE); |
| parser->free_later (face_loaders_text); |
| } |
| |
| GOptionEntry entries[] = |
| { |
| {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"}, |
| {"face-index", 'y', 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"}, |
| {"face-loader", 0, 0, G_OPTION_ARG_STRING, &this->face_loader, face_loaders_text, "loader"}, |
| {"list-face-loaders",0, G_OPTION_FLAG_NO_ARG, |
| G_OPTION_ARG_CALLBACK, (gpointer) &list_face_loaders, "List available face loaders and quit", nullptr}, |
| {nullptr} |
| }; |
| parser->add_group (entries, |
| "face", |
| "Font-face options:", |
| "Options for the font face", |
| this); |
| |
| parser->add_environ("HB_FACE_LOADER=face-loader; Overrides the default face loader."); |
| parser->add_exit_code (RETURN_VALUE_FACE_LOAD_FAILED, "Failed loading font face."); |
| } |
| |
| #endif |