[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