[hb-view] Rewrite --features parsing, with range support
The --features parsing handles errors now. More importantly, it allos limiting individual features to specific byte ranges. The format is Python-esque. Here is how it all works: Syntax: Value: Start: End: Setting value: "kern" 1 0 ∞ # Turn feature on "+kern" 1 0 ∞ # Turn feature off "-kern" 0 0 ∞ # Turn feature off "kern=0" 0 0 ∞ # Turn feature off "kern=1" 1 0 ∞ # Turn feature on "kern=2" 2 0 ∞ # Choose 2nd alternate Setting index: "kern[]" 1 0 ∞ # Turn feature on "kern[:]" 1 0 ∞ # Turn feature on "kern[5:]" 1 5 ∞ # Turn feature on, partial "kern[:5]" 1 0 5 # Turn feature on, partial "kern[3:5]" 1 3 5 # Turn feature on, range "kern[3]" 1 3 3+1 # Turn feature on, single char Mixing it all: "kern[3:5]=0" 1 3 5 # Turn feature off for range
This commit is contained in:
parent
ccc6745afa
commit
fb9ca1bfab
169
src/hb-view.c
169
src/hb-view.c
|
@ -171,10 +171,134 @@ parse_opts (int argc, char **argv)
|
||||||
text = argv[optind++];
|
text = argv[optind++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_space (char **pp)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v')
|
||||||
|
while (c = **pp, ISSPACE (c))
|
||||||
|
(*pp)++;
|
||||||
|
#undef ISSPACE
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
parse_char (char **pp, char c)
|
||||||
|
{
|
||||||
|
parse_space (pp);
|
||||||
|
|
||||||
|
if (**pp != c)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
(*pp)++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
parse_uint (char **pp, unsigned int *pv)
|
||||||
|
{
|
||||||
|
char *p = *pp;
|
||||||
|
unsigned int v;
|
||||||
|
|
||||||
|
v = strtol (p, pp, 0);
|
||||||
|
|
||||||
|
if (p == *pp)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*pv = v;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
parse_feature_value_prefix (char **pp, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
if (parse_char (pp, '-'))
|
||||||
|
feature->value = 0;
|
||||||
|
else {
|
||||||
|
parse_char (pp, '+');
|
||||||
|
feature->value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
parse_feature_tag (char **pp, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
char *p = *pp, c;
|
||||||
|
|
||||||
|
parse_space (pp);
|
||||||
|
|
||||||
|
#define ISALPHA(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z'))
|
||||||
|
while (c = **pp, ISALPHA(c))
|
||||||
|
(*pp)++;
|
||||||
|
#undef ISALPHA
|
||||||
|
|
||||||
|
if (p == *pp)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
**pp = '\0';
|
||||||
|
feature->tag = hb_tag_from_string (p);
|
||||||
|
**pp = c;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
parse_feature_indices (char **pp, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
hb_bool_t has_start;
|
||||||
|
|
||||||
|
feature->start = 0;
|
||||||
|
feature->end = (unsigned int) -1;
|
||||||
|
|
||||||
|
if (!parse_char (pp, '['))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
has_start = parse_uint (pp, &feature->start);
|
||||||
|
|
||||||
|
if (parse_char (pp, ':')) {
|
||||||
|
parse_uint (pp, &feature->end);
|
||||||
|
} else {
|
||||||
|
if (has_start)
|
||||||
|
feature->end = feature->start + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parse_char (pp, ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
parse_feature_value_postfix (char **pp, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
return !parse_char (pp, '=') || parse_uint (pp, &feature->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
parse_one_feature (char **pp, hb_feature_t *feature)
|
||||||
|
{
|
||||||
|
return parse_feature_value_prefix (pp, feature) &&
|
||||||
|
parse_feature_tag (pp, feature) &&
|
||||||
|
parse_feature_indices (pp, feature) &&
|
||||||
|
parse_feature_value_postfix (pp, feature) &&
|
||||||
|
(parse_char (pp, ',') || **pp == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
skip_one_feature (char **pp)
|
||||||
|
{
|
||||||
|
char *e;
|
||||||
|
e = strchr (*pp, ',');
|
||||||
|
if (e)
|
||||||
|
*pp = e + 1;
|
||||||
|
else
|
||||||
|
*pp = *pp + strlen (*pp);
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_features (char *s)
|
static void parse_features (char *s)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
num_features = 0;
|
num_features = 0;
|
||||||
features = NULL;
|
features = NULL;
|
||||||
|
@ -188,48 +312,19 @@ static void parse_features (char *s)
|
||||||
num_features++;
|
num_features++;
|
||||||
p = strchr (p, ',');
|
p = strchr (p, ',');
|
||||||
if (p)
|
if (p)
|
||||||
p++; /* skip the comma */
|
p++;
|
||||||
} while (p);
|
} while (p);
|
||||||
|
|
||||||
features = calloc (num_features, sizeof (*features));
|
features = calloc (num_features, sizeof (*features));
|
||||||
|
|
||||||
/* now do the actual parsing */
|
/* now do the actual parsing */
|
||||||
p = s;
|
p = s;
|
||||||
for (i = 0; i < num_features; i++) {
|
num_features = 0;
|
||||||
hb_feature_t *feature = &features[i];
|
while (*p) {
|
||||||
char *end, *eq, sign;
|
if (parse_one_feature (&p, &features[num_features]))
|
||||||
unsigned int value;
|
num_features++;
|
||||||
|
else
|
||||||
end = strchr (p, ',');
|
skip_one_feature (&p);
|
||||||
if (!end)
|
|
||||||
end = p + strlen (p);
|
|
||||||
|
|
||||||
*end = '\0'; /* isolate it */
|
|
||||||
|
|
||||||
while (*p == ' ')
|
|
||||||
p++;
|
|
||||||
|
|
||||||
sign = *p;
|
|
||||||
if (sign == '-' || sign == '+')
|
|
||||||
p++;
|
|
||||||
|
|
||||||
value = 1;
|
|
||||||
eq = strchr (p, '=');
|
|
||||||
if (eq) {
|
|
||||||
*eq = '\0';
|
|
||||||
value = atoi (eq + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* let a '-' sign override '=' */
|
|
||||||
if (sign == '-')
|
|
||||||
value = 0;
|
|
||||||
|
|
||||||
feature->tag = hb_tag_from_string (p);
|
|
||||||
feature->value = value;
|
|
||||||
feature->start = 0;
|
|
||||||
feature->end = (unsigned int) -1;
|
|
||||||
|
|
||||||
p = end + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue