Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/harfbuzz/util/font-options.hh @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/harfbuzz/util/font-options.hh Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,329 @@ +/* + * 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 <hb-ft.h> +#endif +#include <hb-ot.h> + +#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 () + { +#ifndef HB_NO_VAR + free (variations); +#endif + g_free (font_funcs); + hb_font_destroy (font); + } + + void add_options (option_parser_t *parser); + + void post_parse (GError **error); + + hb_bool_t sub_font = false; +#ifndef HB_NO_VAR + hb_variation_t *variations = nullptr; + unsigned int num_variations = 0; +#endif + int x_ppem = 0; + int y_ppem = 0; + double ptem = 0.; + double slant = 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; + + hb_font_t *font = nullptr; +}; + + +static struct supported_font_funcs_t { + char name[4]; + void (*func) (hb_font_t *); +} supported_font_funcs[] = +{ + {"ot", hb_ot_font_set_funcs}, +#ifdef HAVE_FREETYPE + {"ft", hb_ft_font_set_funcs}, +#endif +}; + + +void +font_options_t::post_parse (GError **error) +{ + assert (!font); + 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); + + hb_font_set_synthetic_slant (font, slant); + + 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); + +#ifndef HB_NO_VAR + hb_font_set_variations (font, variations, num_variations); +#endif + + 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); + } + 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 font function implementation `%s'; supported values are: %s; default is %s", + font_funcs, + p, + supported_font_funcs[0].name); + free (p); + return; + } + } + set_font_funcs (font); +#ifdef HAVE_FREETYPE + hb_ft_font_set_load_flags (font, ft_load_flags); +#endif + + if (sub_font) + { + hb_font_t *old_font = font; + font = hb_font_create_sub_font (old_font); + hb_font_set_scale (old_font, scale_x * 2, scale_y * 2); + hb_font_destroy (old_font); + } +} + + +#ifndef HB_NO_VAR +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 = strpbrk (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 = strpbrk (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; +} +#endif + +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-slant", 0, 0, + G_OPTION_ARG_DOUBLE, &this->slant, "Set synthetic slant (default: 0)", "slant ratio; eg. 0.2"}, + {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"}, + {"sub-font", 0, G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_NONE, &this->sub_font, "Create a sub-font (default: false)", "boolean"}, + {"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, + false /* We add below. */); + +#ifndef HB_NO_VAR + 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\""; + + 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 +} + +#endif
