diff --git a/util/Makefile.sources b/util/Makefile.sources index ee8414595..200d3f673 100644 --- a/util/Makefile.sources +++ b/util/Makefile.sources @@ -1,5 +1,7 @@ HB_VIEW_sources = \ ansi-print.hh \ + face-options.hh \ + font-options.hh \ hb-view.cc \ helper-cairo-ansi.hh \ helper-cairo.hh \ @@ -13,6 +15,8 @@ HB_VIEW_sources = \ $(NULL) HB_SHAPE_sources = \ + face-options.hh \ + font-options.hh \ hb-shape.cc \ main-font-text.hh \ options.cc \ @@ -23,6 +27,8 @@ HB_SHAPE_sources = \ $(NULL) HB_OT_SHAPE_CLOSURE_sources = \ + face-options.hh \ + font-options.hh \ hb-ot-shape-closure.cc \ main-font-text.hh \ options.cc \ @@ -30,6 +36,7 @@ HB_OT_SHAPE_CLOSURE_sources = \ $(NULL) HB_SUBSET_CLI_sources = \ + face-options.hh \ hb-subset.cc \ main-font-text.hh \ options.cc \ diff --git a/util/face-options.hh b/util/face-options.hh new file mode 100644 index 000000000..12cfd3023 --- /dev/null +++ b/util/face-options.hh @@ -0,0 +1,135 @@ +/* + * 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 +{ + void add_options (option_parser_t *parser); + + hb_blob_t *get_blob () const; + hb_face_t *get_face () const; + + static struct cache_t + { + ~cache_t () + { + free ((void *) font_path); + hb_blob_destroy (blob); + hb_face_destroy (face); + } + + const char *font_path = nullptr; + hb_blob_t *blob = nullptr; + unsigned face_index = (unsigned) -1; + hb_face_t *face = nullptr; + } cache; + + char *font_file = nullptr; + unsigned face_index = 0; + private: + mutable hb_face_t *face = nullptr; +}; + + +face_options_t::cache_t face_options_t::cache {}; + +hb_blob_t * +face_options_t::get_blob () const +{ + // XXX This does the job for now; will move to post_parse. + return cache.blob; +} + +hb_face_t * +face_options_t::get_face () const +{ + if (face) + return face; + + if (!font_file) + fail (true, "No font file set"); + + 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)) + { + hb_blob_destroy (cache.blob); + cache.blob = hb_blob_create_from_file_or_fail (font_path); + + free ((char *) cache.font_path); + cache.font_path = strdup (font_path); + + if (!cache.blob) + fail (false, "%s: Failed reading file", font_path); + + hb_face_destroy (cache.face); + cache.face = nullptr; + cache.face_index = (unsigned) -1; + } + + if (cache.face_index != face_index) + { + hb_face_destroy (cache.face); + cache.face = hb_face_create (cache.blob, face_index); + cache.face_index = face_index; + } + + face = cache.face; + + return face; +} + +void +face_options_t::add_options (option_parser_t *parser) +{ + GOptionEntry entries[] = + { + {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"}, + {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"}, + {nullptr} + }; + parser->add_group (entries, + "face", + "Font-face options:", + "Options for the font face", + this); +} + +#endif diff --git a/util/font-options.hh b/util/font-options.hh new file mode 100644 index 000000000..108dbd824 --- /dev/null +++ b/util/font-options.hh @@ -0,0 +1,306 @@ +/* + * 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 FONT_OPTIONS_HH +#define FONT_OPTIONS_HH + +#include "face-options.hh" + +#ifdef HAVE_FREETYPE +#include +#endif +#include + +#define FONT_SIZE_UPEM 0x7FFFFFFF +#define FONT_SIZE_NONE 0 + +extern const unsigned DEFAULT_FONT_SIZE; +extern const unsigned SUBPIXEL_BITS; + +struct font_options_t : face_options_t +{ + ~font_options_t () + { + g_free (font_file); + free (variations); + g_free (font_funcs); + hb_font_destroy (font); + } + + void add_options (option_parser_t *parser); + + hb_font_t *get_font () const; + + hb_variation_t *variations = nullptr; + unsigned int num_variations = 0; + int x_ppem = 0; + int y_ppem = 0; + double ptem = 0.; + unsigned int subpixel_bits = SUBPIXEL_BITS; + mutable double font_size_x = DEFAULT_FONT_SIZE; + mutable double font_size_y = DEFAULT_FONT_SIZE; + char *font_funcs = nullptr; + int ft_load_flags = 2; + + private: + mutable hb_font_t *font = nullptr; +}; + + +static struct supported_font_funcs_t { + char name[4]; + void (*func) (hb_font_t *); +} supported_font_funcs[] = +{ +#ifdef HAVE_FREETYPE + {"ft", hb_ft_font_set_funcs}, +#endif + {"ot", hb_ot_font_set_funcs}, +}; + +hb_font_t * +font_options_t::get_font () const +{ + if (font) + return font; + + auto *face = get_face (); + + font = hb_font_create (face); + + if (font_size_x == FONT_SIZE_UPEM) + font_size_x = hb_face_get_upem (face); + if (font_size_y == FONT_SIZE_UPEM) + font_size_y = hb_face_get_upem (face); + + hb_font_set_ppem (font, x_ppem, y_ppem); + hb_font_set_ptem (font, ptem); + + int scale_x = (int) scalbnf (font_size_x, subpixel_bits); + int scale_y = (int) scalbnf (font_size_y, subpixel_bits); + hb_font_set_scale (font, scale_x, scale_y); + + hb_font_set_variations (font, variations, num_variations); + + void (*set_font_funcs) (hb_font_t *) = nullptr; + if (!font_funcs) + { + set_font_funcs = supported_font_funcs[0].func; + } + else + { + for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) + if (0 == g_ascii_strcasecmp (font_funcs, supported_font_funcs[i].name)) + { + set_font_funcs = supported_font_funcs[i].func; + break; + } + if (!set_font_funcs) + { + GString *s = g_string_new (nullptr); + for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) + { + if (i) + g_string_append_c (s, '/'); + g_string_append (s, supported_font_funcs[i].name); + } + char *p = g_string_free (s, FALSE); + fail (false, "Unknown font function implementation `%s'; supported values are: %s; default is %s", + font_funcs, + p, + supported_font_funcs[0].name); + //free (p); + } + } + set_font_funcs (font); +#ifdef HAVE_FREETYPE + hb_ft_font_set_load_flags (font, ft_load_flags); +#endif + + return font; +} + + +static gboolean +parse_variations (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + font_options_t *font_opts = (font_options_t *) data; + char *s = (char *) arg; + char *p; + + font_opts->num_variations = 0; + g_free (font_opts->variations); + font_opts->variations = nullptr; + + if (!*s) + return true; + + /* count the variations first, so we can allocate memory */ + p = s; + do { + font_opts->num_variations++; + p = strchr (p, ','); + if (p) + p++; + } while (p); + + font_opts->variations = (hb_variation_t *) calloc (font_opts->num_variations, sizeof (*font_opts->variations)); + if (!font_opts->variations) + return false; + + /* now do the actual parsing */ + p = s; + font_opts->num_variations = 0; + while (p && *p) { + char *end = strchr (p, ','); + if (hb_variation_from_string (p, end ? end - p : -1, &font_opts->variations[font_opts->num_variations])) + font_opts->num_variations++; + p = end ? end + 1 : nullptr; + } + + return true; +} + +static gboolean +parse_font_size (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + font_options_t *font_opts = (font_options_t *) data; + if (0 == strcmp (arg, "upem")) + { + font_opts->font_size_y = font_opts->font_size_x = FONT_SIZE_UPEM; + return true; + } + switch (sscanf (arg, "%lf%*[ ,]%lf", &font_opts->font_size_x, &font_opts->font_size_y)) { + case 1: font_opts->font_size_y = font_opts->font_size_x; HB_FALLTHROUGH; + case 2: return true; + default: + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "%s argument should be one or two space-separated numbers", + name); + return false; + } +} + +static gboolean +parse_font_ppem (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + font_options_t *font_opts = (font_options_t *) data; + switch (sscanf (arg, "%d%*[ ,]%d", &font_opts->x_ppem, &font_opts->y_ppem)) { + case 1: font_opts->y_ppem = font_opts->x_ppem; HB_FALLTHROUGH; + case 2: return true; + default: + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "%s argument should be one or two space-separated numbers", + name); + return false; + } +} + +void +font_options_t::add_options (option_parser_t *parser) +{ + face_options_t::add_options (parser); + + char *text = nullptr; + + { + static_assert ((ARRAY_LENGTH_CONST (supported_font_funcs) > 0), + "No supported font-funcs found."); + GString *s = g_string_new (nullptr); + g_string_printf (s, "Set font functions implementation to use (default: %s)\n\n Supported font function implementations are: %s", + supported_font_funcs[0].name, + supported_font_funcs[0].name); + for (unsigned int i = 1; i < ARRAY_LENGTH (supported_font_funcs); i++) + { + g_string_append_c (s, '/'); + g_string_append (s, supported_font_funcs[i].name); + } + text = g_string_free (s, FALSE); + parser->free_later (text); + } + + char *font_size_text; + if (DEFAULT_FONT_SIZE == FONT_SIZE_UPEM) + font_size_text = (char *) "Font size (default: upem)"; + else + { + font_size_text = g_strdup_printf ("Font size (default: %d)", DEFAULT_FONT_SIZE); + parser->free_later (font_size_text); + } + + int font_size_flags = DEFAULT_FONT_SIZE == FONT_SIZE_NONE ? G_OPTION_FLAG_HIDDEN : 0; + GOptionEntry entries[] = + { + {"font-size", 0, font_size_flags, + G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 integers or 'upem'"}, + {"font-ppem", 0, font_size_flags, + G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"}, + {"font-ptem", 0, 0, + G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"}, + {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"}, + {"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"}, + {nullptr} + }; + parser->add_group (entries, + "font", + "Font-instance options:", + "Options for the font instance", + this); + + const gchar *variations_help = "Comma-separated list of font variations\n" + "\n" + " Variations are set globally. The format for specifying variation settings\n" + " follows. All valid CSS font-variation-settings values other than 'normal'\n" + " and 'inherited' are also accepted, though, not documented below.\n" + "\n" + " The format is a tag, optionally followed by an equals sign, followed by a\n" + " number. For example:\n" + "\n" + " \"wght=500\"\n" + " \"slnt=-7.5\"\n"; + + GOptionEntry entries2[] = + { + {"variations", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_variations, variations_help, "list"}, + {nullptr} + }; + parser->add_group (entries2, + "variations", + "Variations options:", + "Options for font variations used", + this); +} + +#endif diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc index 97d7e9ed0..c31ef60be 100644 --- a/util/hb-ot-shape-closure.cc +++ b/util/hb-ot-shape-closure.cc @@ -25,6 +25,7 @@ */ #include "shape-options.hh" +#include "font-options.hh" #include "main-font-text.hh" const unsigned DEFAULT_FONT_SIZE = FONT_SIZE_NONE; @@ -112,6 +113,6 @@ struct shape_closure_consumer_t int main (int argc, char **argv) { - main_font_text_t driver; + main_font_text_t driver; return driver.main (argc, argv); } diff --git a/util/hb-shape.cc b/util/hb-shape.cc index 79b0c3520..b9fbc7740 100644 --- a/util/hb-shape.cc +++ b/util/hb-shape.cc @@ -159,7 +159,7 @@ struct output_buffer_t int main (int argc, char **argv) { - using driver_t = main_font_text_t>; + using driver_t = main_font_text_t, font_options_t, text_options_t>; if (argc == 2 && !strcmp (argv[1], "--batch")) { diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 4c63251c6..b48b73277 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -28,12 +28,9 @@ #include #include "subset-options.hh" +#include "face-options.hh" #include "main-font-text.hh" -// XXX Remove eventually -const unsigned DEFAULT_FONT_SIZE = FONT_SIZE_NONE; -const unsigned SUBPIXEL_BITS = 0; - /* * Command line interface to the harfbuzz font subsetter. */ @@ -135,7 +132,7 @@ struct subset_consumer_t : subset_options_t int main (int argc, char **argv) { - using driver_t = main_font_text_t; + using driver_t = main_font_text_t; if (argc == 2 && !strcmp (argv[1], "--batch")) { diff --git a/util/hb-view.cc b/util/hb-view.cc index 471ab4c6a..6e3398e71 100644 --- a/util/hb-view.cc +++ b/util/hb-view.cc @@ -35,6 +35,6 @@ const unsigned SUBPIXEL_BITS = 6; int main (int argc, char **argv) { - main_font_text_t> driver; + main_font_text_t, font_options_t, text_options_t> driver; return driver.main (argc, argv); } diff --git a/util/main-font-text.hh b/util/main-font-text.hh index f3a7feea1..55b676651 100644 --- a/util/main-font-text.hh +++ b/util/main-font-text.hh @@ -46,7 +46,7 @@ locale_to_utf8 (char *s) return t; } -template +template struct main_font_text_t { int diff --git a/util/options.cc b/util/options.cc index 03f16f222..00573cb51 100644 --- a/util/options.cc +++ b/util/options.cc @@ -25,67 +25,6 @@ */ #include "options.hh" - -#ifdef HAVE_FREETYPE -#include -#endif -#include - -static struct supported_font_funcs_t { - char name[4]; - void (*func) (hb_font_t *); -} supported_font_funcs[] = -{ -#ifdef HAVE_FREETYPE - {"ft", hb_ft_font_set_funcs}, -#endif - {"ot", hb_ot_font_set_funcs}, -}; - - -static gboolean -parse_variations (const char *name G_GNUC_UNUSED, - const char *arg, - gpointer data, - GError **error G_GNUC_UNUSED) -{ - font_options_t *font_opts = (font_options_t *) data; - char *s = (char *) arg; - char *p; - - font_opts->num_variations = 0; - g_free (font_opts->variations); - font_opts->variations = nullptr; - - if (!*s) - return true; - - /* count the variations first, so we can allocate memory */ - p = s; - do { - font_opts->num_variations++; - p = strchr (p, ','); - if (p) - p++; - } while (p); - - font_opts->variations = (hb_variation_t *) calloc (font_opts->num_variations, sizeof (*font_opts->variations)); - if (!font_opts->variations) - return false; - - /* now do the actual parsing */ - p = s; - font_opts->num_variations = 0; - while (p && *p) { - char *end = strchr (p, ','); - if (hb_variation_from_string (p, end ? end - p : -1, &font_opts->variations[font_opts->num_variations])) - font_opts->num_variations++; - p = end ? end + 1 : nullptr; - } - - return true; -} - static gboolean parse_text (const char *name G_GNUC_UNUSED, const char *arg, @@ -163,138 +102,6 @@ parse_unicodes (const char *name G_GNUC_UNUSED, return true; } -static gboolean -parse_font_size (const char *name G_GNUC_UNUSED, - const char *arg, - gpointer data, - GError **error G_GNUC_UNUSED) -{ - font_options_t *font_opts = (font_options_t *) data; - if (0 == strcmp (arg, "upem")) - { - font_opts->font_size_y = font_opts->font_size_x = FONT_SIZE_UPEM; - return true; - } - switch (sscanf (arg, "%lf%*[ ,]%lf", &font_opts->font_size_x, &font_opts->font_size_y)) { - case 1: font_opts->font_size_y = font_opts->font_size_x; HB_FALLTHROUGH; - case 2: return true; - default: - g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, - "%s argument should be one or two space-separated numbers", - name); - return false; - } -} - -static gboolean -parse_font_ppem (const char *name G_GNUC_UNUSED, - const char *arg, - gpointer data, - GError **error G_GNUC_UNUSED) -{ - font_options_t *font_opts = (font_options_t *) data; - switch (sscanf (arg, "%d%*[ ,]%d", &font_opts->x_ppem, &font_opts->y_ppem)) { - case 1: font_opts->y_ppem = font_opts->x_ppem; HB_FALLTHROUGH; - case 2: return true; - default: - g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, - "%s argument should be one or two space-separated numbers", - name); - return false; - } -} - -void -face_options_t::add_options (option_parser_t *parser) -{ - GOptionEntry entries[] = - { - {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"}, - {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"}, - {nullptr} - }; - parser->add_group (entries, - "face", - "Font-face options:", - "Options for the font face", - this); -} - -void -font_options_t::add_options (option_parser_t *parser) -{ - face_options_t::add_options (parser); - - char *text = nullptr; - - { - static_assert ((ARRAY_LENGTH_CONST (supported_font_funcs) > 0), - "No supported font-funcs found."); - GString *s = g_string_new (nullptr); - g_string_printf (s, "Set font functions implementation to use (default: %s)\n\n Supported font function implementations are: %s", - supported_font_funcs[0].name, - supported_font_funcs[0].name); - for (unsigned int i = 1; i < ARRAY_LENGTH (supported_font_funcs); i++) - { - g_string_append_c (s, '/'); - g_string_append (s, supported_font_funcs[i].name); - } - text = g_string_free (s, FALSE); - parser->free_later (text); - } - - char *font_size_text; - if (DEFAULT_FONT_SIZE == FONT_SIZE_UPEM) - font_size_text = (char *) "Font size (default: upem)"; - else - { - font_size_text = g_strdup_printf ("Font size (default: %d)", DEFAULT_FONT_SIZE); - parser->free_later (font_size_text); - } - - int font_size_flags = DEFAULT_FONT_SIZE == FONT_SIZE_NONE ? G_OPTION_FLAG_HIDDEN : 0; - GOptionEntry entries[] = - { - {"font-size", 0, font_size_flags, - G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 integers or 'upem'"}, - {"font-ppem", 0, font_size_flags, - G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"}, - {"font-ptem", 0, 0, - G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"}, - {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"}, - {"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"}, - {nullptr} - }; - parser->add_group (entries, - "font", - "Font-instance options:", - "Options for the font instance", - this); - - const gchar *variations_help = "Comma-separated list of font variations\n" - "\n" - " Variations are set globally. The format for specifying variation settings\n" - " follows. All valid CSS font-variation-settings values other than 'normal'\n" - " and 'inherited' are also accepted, though, not documented below.\n" - "\n" - " The format is a tag, optionally followed by an equals sign, followed by a\n" - " number. For example:\n" - "\n" - " \"wght=500\"\n" - " \"slnt=-7.5\"\n"; - - GOptionEntry entries2[] = - { - {"variations", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_variations, variations_help, "list"}, - {nullptr} - }; - parser->add_group (entries2, - "variations", - "Variations options:", - "Options for font variations used", - this); -} - void text_options_t::add_options (option_parser_t *parser) { @@ -321,7 +128,7 @@ output_options_t::add_options (option_parser_t *parser, const char *text; if (!supported_formats) - text = "Set output serialization format"; + text = "Set output format"; else { char *items = g_strjoinv ("/", const_cast (supported_formats)); @@ -343,129 +150,6 @@ output_options_t::add_options (option_parser_t *parser, this); } - -face_options_t::cache_t face_options_t::cache {}; - -hb_blob_t * -face_options_t::get_blob () const -{ - // XXX This does the job for now; will move to post_parse. - return cache.blob; -} - -hb_face_t * -face_options_t::get_face () const -{ - if (face) - return face; - - if (!font_file) - fail (true, "No font file set"); - - 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)) - { - hb_blob_destroy (cache.blob); - cache.blob = hb_blob_create_from_file_or_fail (font_path); - - free ((char *) cache.font_path); - cache.font_path = strdup (font_path); - - if (!cache.blob) - fail (false, "%s: Failed reading file", font_path); - - hb_face_destroy (cache.face); - cache.face = nullptr; - cache.face_index = (unsigned) -1; - } - - if (cache.face_index != face_index) - { - hb_face_destroy (cache.face); - cache.face = hb_face_create (cache.blob, face_index); - cache.face_index = face_index; - } - - face = cache.face; - - return face; -} - - -hb_font_t * -font_options_t::get_font () const -{ - if (font) - return font; - - auto *face = get_face (); - - font = hb_font_create (face); - - if (font_size_x == FONT_SIZE_UPEM) - font_size_x = hb_face_get_upem (face); - if (font_size_y == FONT_SIZE_UPEM) - font_size_y = hb_face_get_upem (face); - - hb_font_set_ppem (font, x_ppem, y_ppem); - hb_font_set_ptem (font, ptem); - - int scale_x = (int) scalbnf (font_size_x, subpixel_bits); - int scale_y = (int) scalbnf (font_size_y, subpixel_bits); - hb_font_set_scale (font, scale_x, scale_y); - - hb_font_set_variations (font, variations, num_variations); - - void (*set_font_funcs) (hb_font_t *) = nullptr; - if (!font_funcs) - { - set_font_funcs = supported_font_funcs[0].func; - } - else - { - for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) - if (0 == g_ascii_strcasecmp (font_funcs, supported_font_funcs[i].name)) - { - set_font_funcs = supported_font_funcs[i].func; - break; - } - if (!set_font_funcs) - { - GString *s = g_string_new (nullptr); - for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++) - { - if (i) - g_string_append_c (s, '/'); - g_string_append (s, supported_font_funcs[i].name); - } - char *p = g_string_free (s, FALSE); - fail (false, "Unknown font function implementation `%s'; supported values are: %s; default is %s", - font_funcs, - p, - supported_font_funcs[0].name); - //free (p); - } - } - set_font_funcs (font); -#ifdef HAVE_FREETYPE - hb_ft_font_set_load_flags (font, ft_load_flags); -#endif - - return font; -} - - const char * text_options_t::get_line (unsigned int *len, int eol) { diff --git a/util/options.hh b/util/options.hh index d35193e75..bec2e5746 100644 --- a/util/options.hh +++ b/util/options.hh @@ -205,69 +205,6 @@ option_parser_t::parse (int *argc, char ***argv) // XXXXXXXXXXXX -#define FONT_SIZE_UPEM 0x7FFFFFFF -#define FONT_SIZE_NONE 0 - -extern const unsigned DEFAULT_FONT_SIZE; -extern const unsigned SUBPIXEL_BITS; - -struct face_options_t -{ - void add_options (option_parser_t *parser); - - hb_blob_t *get_blob () const; - hb_face_t *get_face () const; - - static struct cache_t - { - ~cache_t () - { - free ((void *) font_path); - hb_blob_destroy (blob); - hb_face_destroy (face); - } - - const char *font_path = nullptr; - hb_blob_t *blob = nullptr; - unsigned face_index = (unsigned) -1; - hb_face_t *face = nullptr; - } cache; - - char *font_file = nullptr; - unsigned face_index = 0; - private: - mutable hb_face_t *face = nullptr; -}; - -struct font_options_t : face_options_t -{ - ~font_options_t () - { - g_free (font_file); - free (variations); - g_free (font_funcs); - hb_font_destroy (font); - } - - void add_options (option_parser_t *parser); - - hb_font_t *get_font () const; - - hb_variation_t *variations = nullptr; - unsigned int num_variations = 0; - int x_ppem = 0; - int y_ppem = 0; - double ptem = 0.; - unsigned int subpixel_bits = SUBPIXEL_BITS; - mutable double font_size_x = DEFAULT_FONT_SIZE; - mutable double font_size_y = DEFAULT_FONT_SIZE; - char *font_funcs = nullptr; - int ft_load_flags = 2; - - private: - mutable hb_font_t *font = nullptr; -}; - struct text_options_t { diff --git a/util/shape-consumer.hh b/util/shape-consumer.hh index e6a139c5e..760756432 100644 --- a/util/shape-consumer.hh +++ b/util/shape-consumer.hh @@ -27,6 +27,7 @@ #ifndef HB_SHAPE_CONSUMER_HH #define HB_SHAPE_CONSUMER_HH +#include "font-options.hh" #include "shape-options.hh"