[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