diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-shape.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-shape.cc | 110 |
1 files changed, 83 insertions, 27 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc index c1b752405e..4e22c61862 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc @@ -34,15 +34,15 @@ #include "hb-font-private.hh" -static void +static bool parse_space (const char **pp, const char *end) { - char c; - while (*pp < end && (c = **pp, ISSPACE (c))) + while (*pp < end && ISSPACE (**pp)) (*pp)++; + return true; } -static hb_bool_t +static bool parse_char (const char **pp, const char *end, char c) { parse_space (pp, end); @@ -54,7 +54,7 @@ parse_char (const char **pp, const char *end, char c) return true; } -static hb_bool_t +static bool parse_uint (const char **pp, const char *end, unsigned int *pv) { char buf[32]; @@ -78,7 +78,27 @@ parse_uint (const char **pp, const char *end, unsigned int *pv) return true; } -static hb_bool_t +static bool +parse_bool (const char **pp, const char *end, unsigned int *pv) +{ + parse_space (pp, end); + + const char *p = *pp; + while (*pp < end && ISALPHA(**pp)) + (*pp)++; + + /* CSS allows on/off as aliases 1/0. */ + if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) + *pv = 1; + else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) + *pv = 0; + else + return false; + + return true; +} + +static bool parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) { if (parse_char (pp, end, '-')) @@ -91,32 +111,48 @@ parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feat return true; } -static hb_bool_t +static bool parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) { - const char *p = *pp; - char c; - parse_space (pp, end); -#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9')) - while (*pp < end && (c = **pp, ISALNUM(c))) + char quote = 0; + + if (*pp < end && (**pp == '\'' || **pp == '"')) + { + quote = **pp; + (*pp)++; + } + + const char *p = *pp; + while (*pp < end && ISALNUM(**pp)) (*pp)++; -#undef ISALNUM - if (p == *pp) + if (p == *pp || *pp - p > 4) return false; feature->tag = hb_tag_from_string (p, *pp - p); + + if (quote) + { + /* CSS expects exactly four bytes. And we only allow quotations for + * CSS compatibility. So, enforce the length. */ + if (*pp - p != 4) + return false; + if (*pp == end || **pp != quote) + return false; + (*pp)++; + } + return true; } -static hb_bool_t +static bool parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) { parse_space (pp, end); - hb_bool_t has_start; + bool has_start; feature->start = 0; feature->end = (unsigned int) -1; @@ -136,28 +172,35 @@ parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) return parse_char (pp, end, ']'); } -static hb_bool_t +static bool parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) { - return !parse_char (pp, end, '=') || parse_uint (pp, end, &feature->value); + bool had_equal = parse_char (pp, end, '='); + bool had_value = parse_uint (pp, end, &feature->value) || + parse_bool (pp, end, &feature->value); + /* CSS doesn't use equal-sign between tag and value. + * If there was an equal-sign, then there *must* be a value. + * A value without an eqaul-sign is ok, but not required. */ + return !had_equal || had_value; } -static hb_bool_t +static bool parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) { return parse_feature_value_prefix (pp, end, feature) && parse_feature_tag (pp, end, feature) && parse_feature_indices (pp, end, feature) && parse_feature_value_postfix (pp, end, feature) && + parse_space (pp, end) && *pp == end; } /** * hb_feature_from_string: - * @str: (array length=len): + * @str: (array length=len) (element-type uint8_t): * @len: - * @feature: (out): + * @feature: (out) (optional): * * * @@ -169,10 +212,21 @@ hb_bool_t hb_feature_from_string (const char *str, int len, hb_feature_t *feature) { + hb_feature_t feat; + if (len < 0) len = strlen (str); - return parse_one_feature (&str, str + len, feature); + if (likely (parse_one_feature (&str, str + len, &feat))) + { + if (feature) + *feature = feat; + return true; + } + + if (feature) + memset (feature, 0, sizeof (*feature)); + return false; } /** @@ -203,18 +257,18 @@ hb_feature_to_string (hb_feature_t *feature, { s[len++] = '['; if (feature->start) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start)); + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); if (feature->end != feature->start + 1) { s[len++] = ':'; if (feature->end != (unsigned int) -1) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end)); + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); } s[len++] = ']'; } if (feature->value > 1) { s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value)); + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); } assert (len < ARRAY_LENGTH (s)); len = MIN (len, size - 1); @@ -225,11 +279,13 @@ hb_feature_to_string (hb_feature_t *feature, static const char **static_shaper_list; -static inline +#ifdef HB_USE_ATEXIT +static void free_static_shaper_list (void) { free (static_shaper_list); } +#endif /** * hb_shape_list_shapers: @@ -266,7 +322,7 @@ retry: goto retry; } -#ifdef HAVE_ATEXIT +#ifdef HB_USE_ATEXIT atexit (free_static_shaper_list); /* First person registers atexit() callback. */ #endif } |