src/hb-view.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 150 insertions(+), 38 deletions(-)
New commits: commit fb9ca1bfabde7da0c274e7a1bd12bffaf7949c18 Author: Behdad Esfahbod <[email protected]> Date: Mon Apr 4 14:50:09 2011 -0400 [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 diff --git a/src/hb-view.c b/src/hb-view.c index c4b942f..b82d274 100644 --- a/src/hb-view.c +++ b/src/hb-view.c @@ -171,10 +171,134 @@ parse_opts (int argc, char **argv) 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) { char *p; - unsigned int i; num_features = 0; features = NULL; @@ -188,48 +312,19 @@ static void parse_features (char *s) num_features++; p = strchr (p, ','); if (p) - p++; /* skip the comma */ + p++; } while (p); features = calloc (num_features, sizeof (*features)); /* now do the actual parsing */ p = s; - for (i = 0; i < num_features; i++) { - hb_feature_t *feature = &features[i]; - char *end, *eq, sign; - unsigned int value; - - end = strchr (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; + num_features = 0; + while (*p) { + if (parse_one_feature (&p, &features[num_features])) + num_features++; + else + skip_one_feature (&p); } } commit ccc6745afaa68ce7497a6cd02ce85986d3c863d0 Author: Behdad Esfahbod <[email protected]> Date: Mon Apr 4 14:49:50 2011 -0400 [hb-view] Use cached hb-ft face creation Avoids recreating the face the second time we call draw(). diff --git a/src/hb-view.c b/src/hb-view.c index 0411b56..c4b942f 100644 --- a/src/hb-view.c +++ b/src/hb-view.c @@ -241,7 +241,7 @@ _hb_cr_text_glyphs (cairo_t *cr, { cairo_scaled_font_t *scaled_font = cairo_get_scaled_font (cr); FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font); - hb_face_t *hb_face = hb_ft_face_create (ft_face, NULL); + hb_face_t *hb_face = hb_ft_face_create_cached (ft_face); hb_font_t *hb_font = hb_ft_font_create (ft_face, NULL); hb_buffer_t *hb_buffer; cairo_glyph_t *cairo_glyphs; commit 1b4a2cc095d165dc573e0235f00fbbf2a5d3c2c5 Author: Behdad Esfahbod <[email protected]> Date: Mon Apr 4 14:45:28 2011 -0400 [hb-view] Add --debug Frees all allocated memory before exiting. Useful for valgrind run. diff --git a/src/hb-view.c b/src/hb-view.c index 4305cf3..0411b56 100644 --- a/src/hb-view.c +++ b/src/hb-view.c @@ -58,6 +58,7 @@ static const char *language = NULL; static const char *script = NULL; static hb_feature_t *features = NULL; static unsigned int num_features; +static hb_bool_t debug = FALSE; /* Ugh, global vars. Ugly, but does the job */ static int width = 0; @@ -95,6 +96,7 @@ parse_opts (int argc, char **argv) int option_index = 0, c; static struct option long_options[] = { {"background", 1, 0, 'B'}, + {"debug", 0, &debug, TRUE}, {"features", 1, 0, 'f'}, {"font-size", 1, 0, 's'}, {"foreground", 1, 0, 'F'}, @@ -372,6 +374,7 @@ draw (void) if (p != end) { glyphs = _hb_cr_text_glyphs (cr, p, end - p, &num_glyphs); + cairo_glyph_extents (cr, glyphs, num_glyphs, &extents); y += ceil (font_extents.ascent); @@ -381,6 +384,7 @@ draw (void) cairo_show_glyphs (cr, glyphs, num_glyphs); cairo_restore (cr); y += ceil (font_extents.height - ceil (font_extents.ascent)); + cairo_glyph_free (glyphs); } @@ -419,5 +423,18 @@ main (int argc, char **argv) exit (1); } + if (debug) { + free (features); + + cairo_pattern_destroy (fore_pattern); + cairo_pattern_destroy (back_pattern); + cairo_surface_destroy (surface); + cairo_font_face_destroy (cairo_face); + cairo_debug_reset_static_data (); + + FT_Done_Face (ft_face); + FT_Done_FreeType (ft_library); + } + return 0; }
_______________________________________________ HarfBuzz mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/harfbuzz
