Move code around
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 3564e43..04d9fb0 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -605,3 +605,253 @@
{
return HB_VERSION_ATLEAST (major, minor, micro);
}
+
+
+/* hb_feature_t */
+
+static bool
+parse_space (const char **pp, const char *end)
+{
+ while (*pp < end && ISSPACE (**pp))
+ (*pp)++;
+ return true;
+}
+
+static bool
+parse_char (const char **pp, const char *end, char c)
+{
+ parse_space (pp, end);
+
+ if (*pp == end || **pp != c)
+ return false;
+
+ (*pp)++;
+ return true;
+}
+
+static bool
+parse_uint (const char **pp, const char *end, unsigned int *pv)
+{
+ char buf[32];
+ unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
+ strncpy (buf, *pp, len);
+ buf[len] = '\0';
+
+ char *p = buf;
+ char *pend = p;
+ unsigned int v;
+
+ /* Intentionally use strtol instead of strtoul, such that
+ * -1 turns into "big number"... */
+ errno = 0;
+ v = strtol (p, &pend, 0);
+ if (errno || p == pend)
+ return false;
+
+ *pv = v;
+ *pp += pend - p;
+ return true;
+}
+
+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, '-'))
+ feature->value = 0;
+ else {
+ parse_char (pp, end, '+');
+ feature->value = 1;
+ }
+
+ return true;
+}
+
+static bool
+parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
+{
+ parse_space (pp, end);
+
+ char quote = 0;
+
+ if (*pp < end && (**pp == '\'' || **pp == '"'))
+ {
+ quote = **pp;
+ (*pp)++;
+ }
+
+ const char *p = *pp;
+ while (*pp < end && ISALNUM(**pp))
+ (*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 bool
+parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
+{
+ parse_space (pp, end);
+
+ bool has_start;
+
+ feature->start = 0;
+ feature->end = (unsigned int) -1;
+
+ if (!parse_char (pp, end, '['))
+ return true;
+
+ has_start = parse_uint (pp, end, &feature->start);
+
+ if (parse_char (pp, end, ':')) {
+ parse_uint (pp, end, &feature->end);
+ } else {
+ if (has_start)
+ feature->end = feature->start + 1;
+ }
+
+ return parse_char (pp, end, ']');
+}
+
+static bool
+parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
+{
+ 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 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) (element-type uint8_t): a string to parse
+ * @len: length of @str, or -1 if string is %NULL terminated
+ * @feature: (out): the #hb_feature_t to initialize with the parsed values
+ *
+ * Parses a string into a #hb_feature_t.
+ *
+ * TODO: document the syntax here.
+ *
+ * Return value:
+ * %true if @str is successfully parsed, %false otherwise.
+ *
+ * Since: 0.9.5
+ **/
+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);
+
+ if (likely (parse_one_feature (&str, str + len, &feat)))
+ {
+ if (feature)
+ *feature = feat;
+ return true;
+ }
+
+ if (feature)
+ memset (feature, 0, sizeof (*feature));
+ return false;
+}
+
+/**
+ * hb_feature_to_string:
+ * @feature: an #hb_feature_t to convert
+ * @buf: (array length=size) (out): output string
+ * @size: the allocated size of @buf
+ *
+ * Converts a #hb_feature_t into a %NULL-terminated string in the format
+ * understood by hb_feature_from_string(). The client in responsible for
+ * allocating big enough size for @buf, 128 bytes is more than enough.
+ *
+ * Since: 0.9.5
+ **/
+void
+hb_feature_to_string (hb_feature_t *feature,
+ char *buf, unsigned int size)
+{
+ if (unlikely (!size)) return;
+
+ char s[128];
+ unsigned int len = 0;
+ if (feature->value == 0)
+ s[len++] = '-';
+ hb_tag_to_string (feature->tag, s + len);
+ len += 4;
+ while (len && s[len - 1] == ' ')
+ len--;
+ if (feature->start != 0 || feature->end != (unsigned int) -1)
+ {
+ s[len++] = '[';
+ if (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, "%u", feature->end));
+ }
+ s[len++] = ']';
+ }
+ if (feature->value > 1)
+ {
+ s[len++] = '=';
+ len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
+ }
+ assert (len < ARRAY_LENGTH (s));
+ len = MIN (len, size - 1);
+ memcpy (buf, s, len);
+ buf[len] = '\0';
+}
diff --git a/src/hb-common.h b/src/hb-common.h
index 2cbee76..dd72a9d 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -362,6 +362,24 @@
typedef void (*hb_destroy_func_t) (void *user_data);
+/* Font features. */
+
+typedef struct hb_feature_t {
+ hb_tag_t tag;
+ uint32_t value;
+ unsigned int start;
+ unsigned int end;
+} hb_feature_t;
+
+HB_EXTERN hb_bool_t
+hb_feature_from_string (const char *str, int len,
+ hb_feature_t *feature);
+
+HB_EXTERN void
+hb_feature_to_string (hb_feature_t *feature,
+ char *buf, unsigned int size);
+
+
HB_END_DECLS
#endif /* HB_COMMON_H */
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index 706f144..f57cad9 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -45,254 +45,6 @@
* contains the output glyphs and their positions.
**/
-static bool
-parse_space (const char **pp, const char *end)
-{
- while (*pp < end && ISSPACE (**pp))
- (*pp)++;
- return true;
-}
-
-static bool
-parse_char (const char **pp, const char *end, char c)
-{
- parse_space (pp, end);
-
- if (*pp == end || **pp != c)
- return false;
-
- (*pp)++;
- return true;
-}
-
-static bool
-parse_uint (const char **pp, const char *end, unsigned int *pv)
-{
- char buf[32];
- unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
- strncpy (buf, *pp, len);
- buf[len] = '\0';
-
- char *p = buf;
- char *pend = p;
- unsigned int v;
-
- /* Intentionally use strtol instead of strtoul, such that
- * -1 turns into "big number"... */
- errno = 0;
- v = strtol (p, &pend, 0);
- if (errno || p == pend)
- return false;
-
- *pv = v;
- *pp += pend - p;
- return true;
-}
-
-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, '-'))
- feature->value = 0;
- else {
- parse_char (pp, end, '+');
- feature->value = 1;
- }
-
- return true;
-}
-
-static bool
-parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
-{
- parse_space (pp, end);
-
- char quote = 0;
-
- if (*pp < end && (**pp == '\'' || **pp == '"'))
- {
- quote = **pp;
- (*pp)++;
- }
-
- const char *p = *pp;
- while (*pp < end && ISALNUM(**pp))
- (*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 bool
-parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
-{
- parse_space (pp, end);
-
- bool has_start;
-
- feature->start = 0;
- feature->end = (unsigned int) -1;
-
- if (!parse_char (pp, end, '['))
- return true;
-
- has_start = parse_uint (pp, end, &feature->start);
-
- if (parse_char (pp, end, ':')) {
- parse_uint (pp, end, &feature->end);
- } else {
- if (has_start)
- feature->end = feature->start + 1;
- }
-
- return parse_char (pp, end, ']');
-}
-
-static bool
-parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
-{
- 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 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) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
- * @feature: (out): the #hb_feature_t to initialize with the parsed values
- *
- * Parses a string into a #hb_feature_t.
- *
- * TODO: document the syntax here.
- *
- * Return value:
- * %true if @str is successfully parsed, %false otherwise.
- *
- * Since: 0.9.5
- **/
-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);
-
- if (likely (parse_one_feature (&str, str + len, &feat)))
- {
- if (feature)
- *feature = feat;
- return true;
- }
-
- if (feature)
- memset (feature, 0, sizeof (*feature));
- return false;
-}
-
-/**
- * hb_feature_to_string:
- * @feature: an #hb_feature_t to convert
- * @buf: (array length=size) (out): output string
- * @size: the allocated size of @buf
- *
- * Converts a #hb_feature_t into a %NULL-terminated string in the format
- * understood by hb_feature_from_string(). The client in responsible for
- * allocating big enough size for @buf, 128 bytes is more than enough.
- *
- * Since: 0.9.5
- **/
-void
-hb_feature_to_string (hb_feature_t *feature,
- char *buf, unsigned int size)
-{
- if (unlikely (!size)) return;
-
- char s[128];
- unsigned int len = 0;
- if (feature->value == 0)
- s[len++] = '-';
- hb_tag_to_string (feature->tag, s + len);
- len += 4;
- while (len && s[len - 1] == ' ')
- len--;
- if (feature->start != 0 || feature->end != (unsigned int) -1)
- {
- s[len++] = '[';
- if (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, "%u", feature->end));
- }
- s[len++] = ']';
- }
- if (feature->value > 1)
- {
- s[len++] = '=';
- len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
- }
- assert (len < ARRAY_LENGTH (s));
- len = MIN (len, size - 1);
- memcpy (buf, s, len);
- buf[len] = '\0';
-}
-
-
static const char **static_shaper_list;
#ifdef HB_USE_ATEXIT
diff --git a/src/hb-shape.h b/src/hb-shape.h
index 53bb845..39507ff 100644
--- a/src/hb-shape.h
+++ b/src/hb-shape.h
@@ -40,22 +40,6 @@
HB_BEGIN_DECLS
-typedef struct hb_feature_t {
- hb_tag_t tag;
- uint32_t value;
- unsigned int start;
- unsigned int end;
-} hb_feature_t;
-
-HB_EXTERN hb_bool_t
-hb_feature_from_string (const char *str, int len,
- hb_feature_t *feature);
-
-HB_EXTERN void
-hb_feature_to_string (hb_feature_t *feature,
- char *buf, unsigned int size);
-
-
HB_EXTERN void
hb_shape (hb_font_t *font,
hb_buffer_t *buffer,