| Index: third_party/harfbuzz-ng/src/hb-shape.cc
|
| diff --git a/third_party/harfbuzz-ng/src/hb-shape.cc b/third_party/harfbuzz-ng/src/hb-shape.cc
|
| index c1b752405e1fdc55b8b4515b7e218e130ff90736..74747f88b89f7cf719c3a391eb895684156035d5 100644
|
| --- a/third_party/harfbuzz-ng/src/hb-shape.cc
|
| +++ b/third_party/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,20 +172,27 @@ 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;
|
| }
|
|
|
| @@ -157,7 +200,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
|
| * hb_feature_from_string:
|
| * @str: (array length=len):
|
| * @len:
|
| - * @feature: (out):
|
| + * @feature: (out) (allow-none):
|
| *
|
| *
|
| *
|
| @@ -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);
|
| @@ -266,7 +320,7 @@ retry:
|
| goto retry;
|
| }
|
|
|
| -#ifdef HAVE_ATEXIT
|
| +#ifdef HB_USE_ATEXIT
|
| atexit (free_static_shaper_list); /* First person registers atexit() callback. */
|
| #endif
|
| }
|
|
|