[HarfBuzz] harfbuzz-ng: Branch 'master' - 3 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Mon Apr 4 12:35:34 PDT 2011
src/hb-view.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 150 insertions(+), 38 deletions(-)
New commits:
commit fb9ca1bfabde7da0c274e7a1bd12bffaf7949c18
Author: Behdad Esfahbod <behdad at behdad.org>
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 <behdad at behdad.org>
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 <behdad at behdad.org>
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;
}
More information about the HarfBuzz
mailing list