diff --git a/util/face-options.hh b/util/face-options.hh index 9c8d40f2c..6781c60ec 100644 --- a/util/face-options.hh +++ b/util/face-options.hh @@ -29,10 +29,18 @@ #include "options.hh" +#ifdef HAVE_FREETYPE +#include +#endif +#ifdef HAVE_CORETEXT +#include +#endif + struct face_options_t { ~face_options_t () { + g_free (face_loader); g_free (font_file); } @@ -58,6 +66,7 @@ struct face_options_t char *font_file = nullptr; unsigned face_index = 0; + char *face_loader = nullptr; hb_face_t *face = nullptr; }; @@ -65,6 +74,20 @@ struct face_options_t face_options_t::cache_t face_options_t::cache {}; +static struct supported_face_loaders_t { + char name[9]; + hb_face_t * (*func) (const char *font_file, unsigned face_index); +} supported_face_loaders[] = +{ + {"ot", hb_face_create_from_file_or_fail}, +#ifdef HAVE_FREETYPE + {"ft", hb_ft_face_create_from_file_or_fail}, +#endif +#ifdef HAVE_CORETEXT + {"coretext", hb_coretext_face_create_from_file_or_fail}, +#endif +}; + void face_options_t::post_parse (GError **error) { @@ -89,13 +112,46 @@ face_options_t::post_parse (GError **error) #endif } + hb_face_t * (*face_load) (const char *file_name, unsigned face_index) = nullptr; + if (!face_loader) + { + face_load = supported_face_loaders[0].func; + } + else + { + for (unsigned int i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + if (0 == g_ascii_strcasecmp (face_loader, supported_face_loaders[i].name)) + { + face_load = supported_face_loaders[i].func; + break; + } + if (!face_load) + { + GString *s = g_string_new (nullptr); + for (unsigned int i = 0; i < ARRAY_LENGTH (supported_face_loaders); i++) + { + if (i) + g_string_append_c (s, '/'); + g_string_append (s, supported_face_loaders[i].name); + } + g_string_append_c (s, '\n'); + char *p = g_string_free (s, FALSE); + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Unknown face loader `%s'; supported values are: %s; default is %s", + face_loader, + p, + supported_face_loaders[0].name); + free (p); + return; + } + } + if (!cache.font_path || 0 != strcmp (cache.font_path, font_path) || cache.face_index != face_index) { hb_face_destroy (cache.face); - cache.face = hb_face_create_from_file_or_fail (font_path, - face_index); + cache.face = face_load (font_path, face_index); cache.face_index = face_index; free ((char *) cache.font_path); @@ -115,10 +171,28 @@ face_options_t::post_parse (GError **error) void face_options_t::add_options (option_parser_t *parser) { + char *face_loaders_text = nullptr; + { + static_assert ((ARRAY_LENGTH_CONST (supported_face_loaders) > 0), + "No supported face-loaders found."); + GString *s = g_string_new (nullptr); + g_string_printf (s, "Set face loader to use (default: %s)\n\n Supported face loaders are: %s", + supported_face_loaders[0].name, + supported_face_loaders[0].name); + for (unsigned int i = 1; i < ARRAY_LENGTH (supported_face_loaders); i++) + { + g_string_append_c (s, '/'); + g_string_append (s, supported_face_loaders[i].name); + } + 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"}, {nullptr} }; parser->add_group (entries,