summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-shape.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-shape.cc')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-shape.cc110
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
}