Mercurial > hgrepos > Python2 > PyMuPDF
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * Copyright © 2011 Google, Inc. | |
| 3 * | |
| 4 * This is part of HarfBuzz, a text shaping library. | |
| 5 * | |
| 6 * Permission is hereby granted, without written agreement and without | |
| 7 * license or royalty fees, to use, copy, modify, and distribute this | |
| 8 * software and its documentation for any purpose, provided that the | |
| 9 * above copyright notice and the following two paragraphs appear in | |
| 10 * all copies of this software. | |
| 11 * | |
| 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | |
| 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | |
| 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | |
| 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | |
| 16 * DAMAGE. | |
| 17 * | |
| 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | |
| 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | |
| 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | |
| 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
| 23 * | |
| 24 * Google Author(s): Behdad Esfahbod | |
| 25 */ | |
| 26 | |
| 27 #ifndef TEXT_OPTIONS_HH | |
| 28 #define TEXT_OPTIONS_HH | |
| 29 | |
| 30 #include "options.hh" | |
| 31 | |
| 32 struct text_options_t | |
| 33 { | |
| 34 text_options_t () | |
| 35 : gs (g_string_new (nullptr)) | |
| 36 {} | |
| 37 ~text_options_t () | |
| 38 { | |
| 39 g_free (text); | |
| 40 g_free (text_file); | |
| 41 if (gs) | |
| 42 g_string_free (gs, true); | |
| 43 if (in_fp && in_fp != stdin) | |
| 44 fclose (in_fp); | |
| 45 } | |
| 46 | |
| 47 void add_options (option_parser_t *parser); | |
| 48 | |
| 49 void post_parse (GError **error G_GNUC_UNUSED) | |
| 50 { | |
| 51 if (!text && !text_file) | |
| 52 text_file = g_strdup ("-"); | |
| 53 | |
| 54 if (text && text_file) | |
| 55 { | |
| 56 g_set_error (error, | |
| 57 G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 58 "Only one of text and text-file can be set"); | |
| 59 return; | |
| 60 } | |
| 61 | |
| 62 if (text_file) | |
| 63 { | |
| 64 if (0 != strcmp (text_file, "-")) | |
| 65 in_fp = fopen (text_file, "r"); | |
| 66 else | |
| 67 in_fp = stdin; | |
| 68 | |
| 69 if (!in_fp) | |
| 70 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, | |
| 71 "Failed opening text file `%s': %s", | |
| 72 text_file, strerror (errno)); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 const char *get_line (unsigned int *len); | |
| 77 | |
| 78 int text_len = -1; | |
| 79 char *text = nullptr; | |
| 80 char *text_file = nullptr; | |
| 81 | |
| 82 private: | |
| 83 FILE *in_fp = nullptr; | |
| 84 GString *gs = nullptr; | |
| 85 char *line = nullptr; | |
| 86 unsigned line_len = UINT_MAX; | |
| 87 hb_bool_t single_par = false; | |
| 88 }; | |
| 89 | |
| 90 struct shape_text_options_t : text_options_t | |
| 91 { | |
| 92 ~shape_text_options_t () | |
| 93 { | |
| 94 g_free (text_before); | |
| 95 g_free (text_after); | |
| 96 } | |
| 97 | |
| 98 void add_options (option_parser_t *parser); | |
| 99 | |
| 100 char *text_before = nullptr; | |
| 101 char *text_after = nullptr; | |
| 102 }; | |
| 103 | |
| 104 | |
| 105 static gboolean | |
| 106 parse_text (const char *name G_GNUC_UNUSED, | |
| 107 const char *arg, | |
| 108 gpointer data, | |
| 109 GError **error G_GNUC_UNUSED) | |
| 110 { | |
| 111 text_options_t *text_opts = (text_options_t *) data; | |
| 112 | |
| 113 if (text_opts->text) | |
| 114 { | |
| 115 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 116 "Either --text or --unicodes can be provided but not both"); | |
| 117 return false; | |
| 118 } | |
| 119 | |
| 120 text_opts->text_len = -1; | |
| 121 text_opts->text = g_strdup (arg); | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 static bool | |
| 126 encode_unicodes (const char *unicodes, | |
| 127 GString *gs, | |
| 128 GError **error) | |
| 129 { | |
| 130 #define DELIMITERS "<+-|>{},;&#\\xXuUnNiI\n\t\v\f\r " | |
| 131 | |
| 132 char *s = (char *) unicodes; | |
| 133 char *p; | |
| 134 | |
| 135 while (s && *s) | |
| 136 { | |
| 137 while (*s && strchr (DELIMITERS, *s)) | |
| 138 s++; | |
| 139 if (!*s) | |
| 140 break; | |
| 141 | |
| 142 errno = 0; | |
| 143 hb_codepoint_t u = strtoul (s, &p, 16); | |
| 144 if (errno || s == p) | |
| 145 { | |
| 146 g_string_free (gs, TRUE); | |
| 147 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 148 "Failed parsing Unicode value at: '%s'", s); | |
| 149 return false; | |
| 150 } | |
| 151 | |
| 152 g_string_append_unichar (gs, u); | |
| 153 | |
| 154 s = p; | |
| 155 } | |
| 156 | |
| 157 #undef DELIMITERS | |
| 158 | |
| 159 return true; | |
| 160 } | |
| 161 | |
| 162 static gboolean | |
| 163 parse_unicodes (const char *name G_GNUC_UNUSED, | |
| 164 const char *arg, | |
| 165 gpointer data, | |
| 166 GError **error G_GNUC_UNUSED) | |
| 167 { | |
| 168 text_options_t *text_opts = (text_options_t *) data; | |
| 169 | |
| 170 if (text_opts->text) | |
| 171 { | |
| 172 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 173 "Either --text or --unicodes can be provided but not both"); | |
| 174 return false; | |
| 175 } | |
| 176 | |
| 177 GString *gs = g_string_new (nullptr); | |
| 178 if (0 == strcmp (arg, "*")) | |
| 179 g_string_append_c (gs, '*'); | |
| 180 else | |
| 181 if (!encode_unicodes (arg, gs, error)) | |
| 182 return false; | |
| 183 | |
| 184 text_opts->text_len = gs->len; | |
| 185 text_opts->text = g_string_free (gs, FALSE); | |
| 186 return true; | |
| 187 } | |
| 188 | |
| 189 static gboolean | |
| 190 parse_text_before (const char *name G_GNUC_UNUSED, | |
| 191 const char *arg, | |
| 192 gpointer data, | |
| 193 GError **error) | |
| 194 { | |
| 195 auto *opts = (shape_text_options_t *) data; | |
| 196 | |
| 197 if (opts->text_before) | |
| 198 { | |
| 199 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 200 "Either --text-before or --unicodes-before can be provided but not both"); | |
| 201 return false; | |
| 202 } | |
| 203 | |
| 204 opts->text_before = g_strdup (arg); | |
| 205 fprintf(stderr, "%s\n", opts->text_before); | |
| 206 return true; | |
| 207 } | |
| 208 | |
| 209 static gboolean | |
| 210 parse_unicodes_before (const char *name G_GNUC_UNUSED, | |
| 211 const char *arg, | |
| 212 gpointer data, | |
| 213 GError **error) | |
| 214 { | |
| 215 auto *opts = (shape_text_options_t *) data; | |
| 216 | |
| 217 if (opts->text_before) | |
| 218 { | |
| 219 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 220 "Either --text-before or --unicodes-before can be provided but not both"); | |
| 221 return false; | |
| 222 } | |
| 223 | |
| 224 GString *gs = g_string_new (nullptr); | |
| 225 if (!encode_unicodes (arg, gs, error)) | |
| 226 return false; | |
| 227 | |
| 228 opts->text_before = g_string_free (gs, FALSE); | |
| 229 return true; | |
| 230 } | |
| 231 | |
| 232 static gboolean | |
| 233 parse_text_after (const char *name G_GNUC_UNUSED, | |
| 234 const char *arg, | |
| 235 gpointer data, | |
| 236 GError **error) | |
| 237 { | |
| 238 auto *opts = (shape_text_options_t *) data; | |
| 239 | |
| 240 if (opts->text_after) | |
| 241 { | |
| 242 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 243 "Either --text-after or --unicodes-after can be provided but not both"); | |
| 244 return false; | |
| 245 } | |
| 246 | |
| 247 opts->text_after = g_strdup (arg); | |
| 248 return true; | |
| 249 } | |
| 250 | |
| 251 static gboolean | |
| 252 parse_unicodes_after (const char *name G_GNUC_UNUSED, | |
| 253 const char *arg, | |
| 254 gpointer data, | |
| 255 GError **error) | |
| 256 { | |
| 257 auto *opts = (shape_text_options_t *) data; | |
| 258 | |
| 259 if (opts->text_after) | |
| 260 { | |
| 261 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, | |
| 262 "Either --text-after or --unicodes-after can be provided but not both"); | |
| 263 return false; | |
| 264 } | |
| 265 | |
| 266 GString *gs = g_string_new (nullptr); | |
| 267 if (!encode_unicodes (arg, gs, error)) | |
| 268 return false; | |
| 269 | |
| 270 opts->text_after = g_string_free (gs, FALSE); | |
| 271 return true; | |
| 272 } | |
| 273 | |
| 274 const char * | |
| 275 text_options_t::get_line (unsigned int *len) | |
| 276 { | |
| 277 if (text) | |
| 278 { | |
| 279 if (!line) | |
| 280 { | |
| 281 line = text; | |
| 282 line_len = text_len; | |
| 283 } | |
| 284 if (line_len == UINT_MAX) | |
| 285 line_len = strlen (line); | |
| 286 | |
| 287 if (!line_len) | |
| 288 { | |
| 289 *len = 0; | |
| 290 return nullptr; | |
| 291 } | |
| 292 | |
| 293 const char *ret = line; | |
| 294 const char *p = single_par ? nullptr : (const char *) memchr (line, '\n', line_len); | |
| 295 unsigned int ret_len; | |
| 296 if (!p) | |
| 297 { | |
| 298 ret_len = line_len; | |
| 299 line += ret_len; | |
| 300 line_len = 0; | |
| 301 } | |
| 302 else | |
| 303 { | |
| 304 ret_len = p - ret; | |
| 305 line += ret_len + 1; | |
| 306 line_len -= ret_len + 1; | |
| 307 } | |
| 308 | |
| 309 *len = ret_len; | |
| 310 return ret; | |
| 311 } | |
| 312 | |
| 313 g_string_set_size (gs, 0); | |
| 314 char buf[BUFSIZ]; | |
| 315 while (fgets (buf, sizeof (buf), in_fp)) | |
| 316 { | |
| 317 unsigned bytes = strlen (buf); | |
| 318 if (!single_par && bytes && buf[bytes - 1] == '\n') | |
| 319 { | |
| 320 bytes--; | |
| 321 g_string_append_len (gs, buf, bytes); | |
| 322 break; | |
| 323 } | |
| 324 g_string_append_len (gs, buf, bytes); | |
| 325 } | |
| 326 if (ferror (in_fp)) | |
| 327 fail (false, "Failed reading text: %s", strerror (errno)); | |
| 328 *len = gs->len; | |
| 329 return !*len && feof (in_fp) ? nullptr : gs->str; | |
| 330 } | |
| 331 | |
| 332 void | |
| 333 text_options_t::add_options (option_parser_t *parser) | |
| 334 { | |
| 335 GOptionEntry entries[] = | |
| 336 { | |
| 337 {"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Set input text", "string"}, | |
| 338 {"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name", "filename"}, | |
| 339 {"unicodes", 'u', 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Set input Unicode codepoints", "list of hex numbers"}, | |
| 340 {"single-par", 0, 0, G_OPTION_ARG_NONE, &this->single_par, "Treat text as single paragraph", nullptr}, | |
| 341 {nullptr} | |
| 342 }; | |
| 343 parser->add_group (entries, | |
| 344 "text", | |
| 345 "Text options:\n\nIf no text is provided, standard input is used for input.\n", | |
| 346 "Options for the input text", | |
| 347 this); | |
| 348 } | |
| 349 | |
| 350 void | |
| 351 shape_text_options_t::add_options (option_parser_t *parser) | |
| 352 { | |
| 353 text_options_t::add_options (parser); | |
| 354 | |
| 355 GOptionEntry entries[] = | |
| 356 { | |
| 357 {"text-before", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text_before, "Set text context before each line", "string"}, | |
| 358 {"text-after", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text_after, "Set text context after each line", "string"}, | |
| 359 {"unicodes-before", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes_before, "Set Unicode codepoints context before each line", "list of hex numbers"}, | |
| 360 {"unicodes-after", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes_after, "Set Unicode codepoints context after each line", "list of hex numbers"}, | |
| 361 {nullptr} | |
| 362 }; | |
| 363 parser->add_group (entries, | |
| 364 "text-context", | |
| 365 "Textual context options:", | |
| 366 "Options for the input context text", | |
| 367 this); | |
| 368 } | |
| 369 | |
| 370 #endif |
