Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/harfbuzz/util/text-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/text-options.hh Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,370 @@ +/* + * 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 TEXT_OPTIONS_HH +#define TEXT_OPTIONS_HH + +#include "options.hh" + +struct text_options_t +{ + text_options_t () + : gs (g_string_new (nullptr)) + {} + ~text_options_t () + { + g_free (text); + g_free (text_file); + if (gs) + g_string_free (gs, true); + if (in_fp && in_fp != stdin) + fclose (in_fp); + } + + void add_options (option_parser_t *parser); + + void post_parse (GError **error G_GNUC_UNUSED) + { + if (!text && !text_file) + text_file = g_strdup ("-"); + + if (text && text_file) + { + g_set_error (error, + G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Only one of text and text-file can be set"); + return; + } + + if (text_file) + { + if (0 != strcmp (text_file, "-")) + in_fp = fopen (text_file, "r"); + else + in_fp = stdin; + + if (!in_fp) + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, + "Failed opening text file `%s': %s", + text_file, strerror (errno)); + } + } + + const char *get_line (unsigned int *len); + + int text_len = -1; + char *text = nullptr; + char *text_file = nullptr; + + private: + FILE *in_fp = nullptr; + GString *gs = nullptr; + char *line = nullptr; + unsigned line_len = UINT_MAX; + hb_bool_t single_par = false; +}; + +struct shape_text_options_t : text_options_t +{ + ~shape_text_options_t () + { + g_free (text_before); + g_free (text_after); + } + + void add_options (option_parser_t *parser); + + char *text_before = nullptr; + char *text_after = nullptr; +}; + + +static gboolean +parse_text (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + text_options_t *text_opts = (text_options_t *) data; + + if (text_opts->text) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text or --unicodes can be provided but not both"); + return false; + } + + text_opts->text_len = -1; + text_opts->text = g_strdup (arg); + return true; +} + +static bool +encode_unicodes (const char *unicodes, + GString *gs, + GError **error) +{ +#define DELIMITERS "<+-|>{},;&#\\xXuUnNiI\n\t\v\f\r " + + char *s = (char *) unicodes; + char *p; + + while (s && *s) + { + while (*s && strchr (DELIMITERS, *s)) + s++; + if (!*s) + break; + + errno = 0; + hb_codepoint_t u = strtoul (s, &p, 16); + if (errno || s == p) + { + g_string_free (gs, TRUE); + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing Unicode value at: '%s'", s); + return false; + } + + g_string_append_unichar (gs, u); + + s = p; + } + +#undef DELIMITERS + + return true; +} + +static gboolean +parse_unicodes (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + text_options_t *text_opts = (text_options_t *) data; + + if (text_opts->text) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text or --unicodes can be provided but not both"); + return false; + } + + GString *gs = g_string_new (nullptr); + if (0 == strcmp (arg, "*")) + g_string_append_c (gs, '*'); + else + if (!encode_unicodes (arg, gs, error)) + return false; + + text_opts->text_len = gs->len; + text_opts->text = g_string_free (gs, FALSE); + return true; +} + +static gboolean +parse_text_before (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error) +{ + auto *opts = (shape_text_options_t *) data; + + if (opts->text_before) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text-before or --unicodes-before can be provided but not both"); + return false; + } + + opts->text_before = g_strdup (arg); + fprintf(stderr, "%s\n", opts->text_before); + return true; +} + +static gboolean +parse_unicodes_before (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error) +{ + auto *opts = (shape_text_options_t *) data; + + if (opts->text_before) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text-before or --unicodes-before can be provided but not both"); + return false; + } + + GString *gs = g_string_new (nullptr); + if (!encode_unicodes (arg, gs, error)) + return false; + + opts->text_before = g_string_free (gs, FALSE); + return true; +} + +static gboolean +parse_text_after (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error) +{ + auto *opts = (shape_text_options_t *) data; + + if (opts->text_after) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text-after or --unicodes-after can be provided but not both"); + return false; + } + + opts->text_after = g_strdup (arg); + return true; +} + +static gboolean +parse_unicodes_after (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error) +{ + auto *opts = (shape_text_options_t *) data; + + if (opts->text_after) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Either --text-after or --unicodes-after can be provided but not both"); + return false; + } + + GString *gs = g_string_new (nullptr); + if (!encode_unicodes (arg, gs, error)) + return false; + + opts->text_after = g_string_free (gs, FALSE); + return true; +} + +const char * +text_options_t::get_line (unsigned int *len) +{ + if (text) + { + if (!line) + { + line = text; + line_len = text_len; + } + if (line_len == UINT_MAX) + line_len = strlen (line); + + if (!line_len) + { + *len = 0; + return nullptr; + } + + const char *ret = line; + const char *p = single_par ? nullptr : (const char *) memchr (line, '\n', line_len); + unsigned int ret_len; + if (!p) + { + ret_len = line_len; + line += ret_len; + line_len = 0; + } + else + { + ret_len = p - ret; + line += ret_len + 1; + line_len -= ret_len + 1; + } + + *len = ret_len; + return ret; + } + + g_string_set_size (gs, 0); + char buf[BUFSIZ]; + while (fgets (buf, sizeof (buf), in_fp)) + { + unsigned bytes = strlen (buf); + if (!single_par && bytes && buf[bytes - 1] == '\n') + { + bytes--; + g_string_append_len (gs, buf, bytes); + break; + } + g_string_append_len (gs, buf, bytes); + } + if (ferror (in_fp)) + fail (false, "Failed reading text: %s", strerror (errno)); + *len = gs->len; + return !*len && feof (in_fp) ? nullptr : gs->str; +} + +void +text_options_t::add_options (option_parser_t *parser) +{ + GOptionEntry entries[] = + { + {"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Set input text", "string"}, + {"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name", "filename"}, + {"unicodes", 'u', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Set input Unicode codepoints", "list of hex numbers"}, + {"single-par", 0, 0, G_OPTION_ARG_NONE, &this->single_par, "Treat text as single paragraph", nullptr}, + {nullptr} + }; + parser->add_group (entries, + "text", + "Text options:\n\nIf no text is provided, standard input is used for input.\n", + "Options for the input text", + this); +} + +void +shape_text_options_t::add_options (option_parser_t *parser) +{ + text_options_t::add_options (parser); + + GOptionEntry entries[] = + { + {"text-before", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text_before, "Set text context before each line", "string"}, + {"text-after", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text_after, "Set text context after each line", "string"}, + {"unicodes-before", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes_before, "Set Unicode codepoints context before each line", "list of hex numbers"}, + {"unicodes-after", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes_after, "Set Unicode codepoints context after each line", "list of hex numbers"}, + {nullptr} + }; + parser->add_group (entries, + "text-context", + "Textual context options:", + "Options for the input context text", + this); +} + +#endif
