[var] Add hb_var_coord_t and parsing routines
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 04d9fb0..25c979c 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -607,7 +607,8 @@
}
-/* hb_feature_t */
+
+/* hb_feature_t and hb_var_coord_t */
static bool
parse_space (const char **pp, const char *end)
@@ -654,6 +655,28 @@
}
static bool
+parse_float (const char **pp, const char *end, float *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;
+ float v;
+
+ errno = 0;
+ v = strtof (p, &pend);
+ 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);
@@ -673,6 +696,8 @@
return true;
}
+/* hb_feature_t */
+
static bool
parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
{
@@ -687,7 +712,7 @@
}
static bool
-parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
+parse_tag (const char **pp, const char *end, hb_tag_t *tag)
{
parse_space (pp, end);
@@ -706,7 +731,7 @@
if (p == *pp || *pp - p > 4)
return false;
- feature->tag = hb_tag_from_string (p, *pp - p);
+ *tag = hb_tag_from_string (p, *pp - p);
if (quote)
{
@@ -759,12 +784,11 @@
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_tag (pp, end, &feature->tag) &&
parse_feature_indices (pp, end, feature) &&
parse_feature_value_postfix (pp, end, feature) &&
parse_space (pp, end) &&
@@ -855,3 +879,63 @@
memcpy (buf, s, len);
buf[len] = '\0';
}
+
+/* hb_var_coord_t */
+
+static bool
+parse_var_coord_value (const char **pp, const char *end, hb_var_coord_t *var_coord)
+{
+ parse_char (pp, end, '='); /* Optional. */
+ return parse_float (pp, end, &var_coord->value);
+}
+
+static bool
+parse_one_var_coord (const char **pp, const char *end, hb_var_coord_t *var_coord)
+{
+ return parse_tag (pp, end, &var_coord->tag) &&
+ parse_var_coord_value (pp, end, var_coord) &&
+ parse_space (pp, end) &&
+ *pp == end;
+}
+
+hb_bool_t
+hb_var_coord_from_string (const char *str, int len,
+ hb_var_coord_t *var_coord)
+{
+ hb_var_coord_t coord;
+
+ if (len < 0)
+ len = strlen (str);
+
+ if (likely (parse_one_var_coord (&str, str + len, &coord)))
+ {
+ if (var_coord)
+ *var_coord = coord;
+ return true;
+ }
+
+ if (var_coord)
+ memset (var_coord, 0, sizeof (*var_coord));
+ return false;
+}
+
+void
+hb_var_coord_to_string (hb_var_coord_t *var_coord,
+ char *buf, unsigned int size)
+{
+ if (unlikely (!size)) return;
+
+ char s[128];
+ unsigned int len = 0;
+ hb_tag_to_string (var_coord->tag, s + len);
+ len += 4;
+ while (len && s[len - 1] == ' ')
+ len--;
+ s[len++] = '=';
+ len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", var_coord->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 dd72a9d..e483fb8 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -362,7 +362,7 @@
typedef void (*hb_destroy_func_t) (void *user_data);
-/* Font features. */
+/* Font features and variations. */
typedef struct hb_feature_t {
hb_tag_t tag;
@@ -379,6 +379,19 @@
hb_feature_to_string (hb_feature_t *feature,
char *buf, unsigned int size);
+typedef struct hb_var_coord_t {
+ hb_tag_t tag;
+ float value;
+} hb_var_coord_t;
+
+HB_EXTERN hb_bool_t
+hb_var_coord_from_string (const char *str, int len,
+ hb_var_coord_t *var_coord);
+
+HB_EXTERN void
+hb_var_coord_to_string (hb_var_coord_t *var_coord,
+ char *buf, unsigned int size);
+
HB_END_DECLS