[HarfBuzz] harfbuzz-ng: Branch 'master' - 6 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Sep 15 22:12:04 PDT 2011


 configure.ac                 |    2 
 src/hb-ot-shape-normalize.cc |    7 ++-
 util/common.hh               |    6 ++
 util/options.cc              |   65 ++++++++++++++++++++++++++------
 util/options.hh              |   37 ++++++++++++++----
 util/view-cairo.cc           |   87 ++++++++++++++++++++++++++++---------------
 util/view-cairo.hh           |    2 
 7 files changed, 153 insertions(+), 53 deletions(-)

New commits:
commit 7bf6ecd3bfb1ccf5d9ac6fe274efa74b46885fea
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Sep 16 01:11:30 2011 -0400

    Always shape at size=upem
    
    Fixes bug with uniscribe not handling GIGANTIC sizes.

diff --git a/util/options.cc b/util/options.cc
index aab2403..4e75827 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -494,7 +494,7 @@ font_options_t::get_font (void) const
   font = hb_font_create (face);
 
   unsigned int upem = hb_face_get_upem (face);
-  hb_font_set_scale (font, font_size * upem, font_size * upem);
+  hb_font_set_scale (font, upem, upem);
   hb_face_destroy (face);
 
 #if HAVE_FREETYPE
diff --git a/util/view-cairo.cc b/util/view-cairo.cc
index d747c9f..daa202d 100644
--- a/util/view-cairo.cc
+++ b/util/view-cairo.cc
@@ -80,7 +80,7 @@ void
 view_cairo_t::init (const font_options_t *font_opts)
 {
   lines = g_array_new (FALSE, FALSE, sizeof (line_t));
-  upem = hb_face_get_upem (hb_font_get_face (font_opts->get_font ()));
+  scale = double (font_opts->font_size) / hb_face_get_upem (hb_font_get_face (font_opts->get_font ()));
 }
 
 void
@@ -115,8 +115,8 @@ view_cairo_t::consume_line (hb_buffer_t  *buffer,
   for (i = 0; i < (int) l.num_glyphs; i++)
     {
       l.glyphs[i].index = hb_glyph[i].codepoint;
-      l.glyphs[i].x = ( hb_position->x_offset + x) / double (upem);
-      l.glyphs[i].y = (-hb_position->y_offset + y) / double (upem);
+      l.glyphs[i].x = ( hb_position->x_offset + x) * scale;
+      l.glyphs[i].y = (-hb_position->y_offset + y) * scale;
       x +=  hb_position->x_advance;
       y += -hb_position->y_advance;
 
@@ -174,7 +174,7 @@ double
 view_cairo_t::line_width (unsigned int i)
 {
   line_t &line = g_array_index (lines, line_t, i);
-  return line.glyphs[line.num_glyphs].x / double (upem);
+  return line.glyphs[line.num_glyphs].x * scale;
 }
 
 void
diff --git a/util/view-cairo.hh b/util/view-cairo.hh
index 4b09d6f..863039b 100644
--- a/util/view-cairo.hh
+++ b/util/view-cairo.hh
@@ -57,7 +57,7 @@ struct view_cairo_t : output_options_t, view_options_t {
   double line_width (unsigned int i);
 
   GArray *lines;
-  unsigned int upem;
+  double scale;
 };
 
 #endif
commit 674ee58d9bc9f825d769220d77f58513edae4558
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Sep 16 00:54:05 2011 -0400

    Minor

diff --git a/util/options.cc b/util/options.cc
index b1fb4ce..aab2403 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -477,9 +477,7 @@ font_options_t::get_font (void) const
 	  user_data = (void *) font_data;
 	  mm = HB_MEMORY_MODE_WRITABLE;
 	} else {
-	  fail (FALSE, "Failed reading font file `%s': %s",
-		g_filename_display_name (font_file),
-		error->message);
+	  fail (FALSE, "%s", error->message);
 	  //g_error_free (error);
 	}
       }
commit 4451168e5d1ea26560899e9a9733b3a3f1853050
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Sep 16 00:38:19 2011 -0400

    Fix binary stdin/stdout io in Windows
    
    Make --font-file accept "-" to mean stdin, and have it work
    in Windows too!

diff --git a/configure.ac b/configure.ac
index 8245181..e1b6bf8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,7 +53,7 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
 
 # Functions and headers
 AC_CHECK_FUNCS(mprotect sysconf getpagesize mmap)
-AC_CHECK_HEADERS(unistd.h sys/mman.h)
+AC_CHECK_HEADERS(unistd.h sys/mman.h io.h)
 
 # Compiler flags
 AC_CANONICAL_HOST
diff --git a/util/common.hh b/util/common.hh
index 015dbf4..1ce61af 100644
--- a/util/common.hh
+++ b/util/common.hh
@@ -40,6 +40,11 @@
 #include <math.h>
 #include <locale.h>
 #include <errno.h>
+#include <fcntl.h>
+#if HAVE_IO_H
+#include <io.h> /* for _setmode() under Windows */
+#endif
+
 
 #include <hb.h>
 #include <glib.h>
diff --git a/util/options.cc b/util/options.cc
index 561b6aa..b1fb4ce 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -424,23 +424,66 @@ font_options_t::get_font (void) const
 
   /* Create the blob */
   {
-    const char *font_data;
-    unsigned int len;
+    char *font_data;
+    unsigned int len = 0;
     hb_destroy_func_t destroy;
     void *user_data;
     hb_memory_mode_t mm;
 
+    /* This is a hell of a lot of code for just reading a file! */
     if (!font_file)
       fail (TRUE, "No font file set");
 
-    GMappedFile *mf = g_mapped_file_new (font_file, FALSE, NULL);
-    if (!mf)
-      fail (FALSE, "Failed opening font file `%s'", g_filename_display_name (font_file));
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
+    if (0 == strcmp (font_file, "-")) {
+      /* read it */
+      GString *gs = g_string_new (NULL);
+      char buf[BUFSIZ];
+#if HAVE_IO_H
+      _setmode (fileno (stdin), O_BINARY);
+#endif
+      while (!feof (stdin)) {
+	size_t ret = fread (buf, 1, sizeof (buf), stdin);
+	if (ferror (stdin))
+	  fail (FALSE, "Failed reading font from standard input: %s",
+		strerror (errno));
+	g_string_append_len (gs, buf, ret);
+      }
+      len = gs->len;
+      font_data = g_string_free (gs, FALSE);
+      user_data = font_data;
+      destroy = (hb_destroy_func_t) g_free;
+      mm = HB_MEMORY_MODE_WRITABLE;
+    } else {
+      GMappedFile *mf = g_mapped_file_new (font_file, FALSE, NULL);
+      if (mf) {
+	font_data = g_mapped_file_get_contents (mf);
+	len = g_mapped_file_get_length (mf);
+	if (len) {
+	  destroy = (hb_destroy_func_t) g_mapped_file_unref;
+	  user_data = (void *) mf;
+	  mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
+	} else
+	  g_mapped_file_unref (mf);
+      }
+      if (!len) {
+	/* GMappedFile is buggy, it doesn't fail if file isn't regular.
+	 * Try reading.
+	 * https://bugzilla.gnome.org/show_bug.cgi?id=659212 */
+        GError *error = NULL;
+	gsize l;
+	if (g_file_get_contents (font_file, &font_data, &l, &error)) {
+	  len = l;
+	  destroy = (hb_destroy_func_t) g_free;
+	  user_data = (void *) font_data;
+	  mm = HB_MEMORY_MODE_WRITABLE;
+	} else {
+	  fail (FALSE, "Failed reading font file `%s': %s",
+		g_filename_display_name (font_file),
+		error->message);
+	  //g_error_free (error);
+	}
+      }
+    }
 
     blob = hb_blob_create (font_data, len, mm, user_data, destroy);
   }
@@ -476,7 +519,6 @@ text_options_t::get_line (unsigned int *len)
       fail (FALSE, "Failed opening text file `%s'", g_filename_display_name (text_file));
     text = g_mapped_file_get_contents (mf);
     text_len = g_mapped_file_get_length (mf);
-    printf ("%d\n", text_len);
   }
 
   if (text_len == (unsigned int) -1)
diff --git a/util/options.hh b/util/options.hh
index b213872..623e25a 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -208,7 +208,6 @@ struct text_options_t : option_group_t
   mutable unsigned int text_len;
 };
 
-
 struct output_options_t : option_group_t
 {
   output_options_t (option_parser_t *parser) {
@@ -243,7 +242,14 @@ struct output_options_t : option_group_t
     if (fp)
       return fp;
 
-    fp = output_file ? fopen (output_file, "wb") : stdout;
+    if (output_file)
+      fp = fopen (output_file, "wb");
+    else {
+#if HAVE_IO_H
+      _setmode (fileno (stdout), O_BINARY);
+#endif
+      fp = stdout;
+    }
     if (!fp)
       fail (FALSE, "Cannot open output file `%s': %s",
 	    g_filename_display_name (output_file), strerror (errno));
commit 639b5957d9c7b6d8bef6784e3467ccc055ddeea4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Sep 15 18:09:49 2011 -0400

    Minor

diff --git a/util/options.cc b/util/options.cc
index eb3ce69..561b6aa 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -435,7 +435,7 @@ font_options_t::get_font (void) const
 
     GMappedFile *mf = g_mapped_file_new (font_file, FALSE, NULL);
     if (!mf)
-      fail (FALSE, "Failed opening font file `%s'", font_file);
+      fail (FALSE, "Failed opening font file `%s'", g_filename_display_name (font_file));
     font_data = g_mapped_file_get_contents (mf);
     len = g_mapped_file_get_length (mf);
     destroy = (hb_destroy_func_t) g_mapped_file_unref;
@@ -473,9 +473,10 @@ text_options_t::get_line (unsigned int *len)
 
     GMappedFile *mf = g_mapped_file_new (text_file, FALSE, NULL);
     if (!mf)
-      fail (FALSE, "Failed opening text file `%s'", text_file);
+      fail (FALSE, "Failed opening text file `%s'", g_filename_display_name (text_file));
     text = g_mapped_file_get_contents (mf);
     text_len = g_mapped_file_get_length (mf);
+    printf ("%d\n", text_len);
   }
 
   if (text_len == (unsigned int) -1)
diff --git a/util/options.hh b/util/options.hh
index 48a3ff7..b213872 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -245,8 +245,8 @@ struct output_options_t : option_group_t
 
     fp = output_file ? fopen (output_file, "wb") : stdout;
     if (!fp)
-      fail (FALSE, "Cannot open output file '%s': %s",
-	    output_file, strerror (errno));
+      fail (FALSE, "Cannot open output file `%s': %s",
+	    g_filename_display_name (output_file), strerror (errno));
 
     return fp;
   }
commit f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Sep 15 17:52:00 2011 -0400

    [hb-view] Make print to stdout work in Windows
    
    Apparently there's no equivalent to "/dev/stdout", so write using
    stdio to be able to output to stdout.

diff --git a/util/common.hh b/util/common.hh
index 45ac6ef..015dbf4 100644
--- a/util/common.hh
+++ b/util/common.hh
@@ -39,6 +39,7 @@
 #include <stdio.h>
 #include <math.h>
 #include <locale.h>
+#include <errno.h>
 
 #include <hb.h>
 #include <glib.h>
diff --git a/util/options.hh b/util/options.hh
index 404fa73..48a3ff7 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -215,8 +215,14 @@ struct output_options_t : option_group_t
     output_file = NULL;
     output_format = NULL;
 
+    fp = NULL;
+
     add_options (parser);
   }
+  ~output_options_t (void) {
+    if (fp && fp != stdout)
+      fclose (fp);
+  }
 
   void add_options (option_parser_t *parser);
 
@@ -228,13 +234,21 @@ struct output_options_t : option_group_t
 	  output_format++; /* skip the dot */
     }
 
-      if (!output_file) {
-#if defined(_MSC_VER) || defined(__MINGW32__)
-        output_file = "CON"; /* XXX right? */
-#else
-        output_file = "/dev/stdout";
-#endif
-      }
+    if (output_file && 0 == strcmp (output_file, "-"))
+      output_file = NULL; /* STDOUT */
+  }
+
+  FILE *get_file_handle (void)
+  {
+    if (fp)
+      return fp;
+
+    fp = output_file ? fopen (output_file, "wb") : stdout;
+    if (!fp)
+      fail (FALSE, "Cannot open output file '%s': %s",
+	    output_file, strerror (errno));
+
+    return fp;
   }
 
   virtual void init (const font_options_t *font_opts) = 0;
@@ -243,8 +257,11 @@ struct output_options_t : option_group_t
 			     unsigned int  text_len) = 0;
   virtual void finish (const font_options_t *font_opts) = 0;
 
+  protected:
   const char *output_file;
   const char *output_format;
+
+  mutable FILE *fp;
 };
 
 
diff --git a/util/view-cairo.cc b/util/view-cairo.cc
index b09a1fe..d747c9f 100644
--- a/util/view-cairo.cc
+++ b/util/view-cairo.cc
@@ -39,13 +39,14 @@
 #    define HAS_EPS 1
 
 static cairo_surface_t *
-_cairo_eps_surface_create (const char *filename,
-			   double      width,
-			   double      height)
+_cairo_eps_surface_create_for_stream (cairo_write_func_t  write_func,
+				      void               *closure,
+				      double              width,
+				      double              height)
 {
   cairo_surface_t *surface;
 
-  surface = cairo_ps_surface_create (filename, width, height);
+  surface = cairo_ps_surface_create_for_stream (write_func, closure, width, height);
   cairo_ps_surface_set_eps (surface, TRUE);
 
   return surface;
@@ -223,7 +224,8 @@ view_cairo_t::create_scaled_font (const font_options_t *font_opts)
 struct finalize_closure_t {
   void (*callback)(finalize_closure_t *);
   cairo_surface_t *surface;
-  const char *filename;
+  cairo_write_func_t write_func;
+  void *closure;
 };
 static cairo_user_data_key_t finalize_closure_key;
 
@@ -233,17 +235,20 @@ static void
 finalize_png (finalize_closure_t *closure)
 {
   cairo_status_t status;
-  status = cairo_surface_write_to_png (closure->surface, closure->filename);
+  status = cairo_surface_write_to_png_stream (closure->surface,
+					      closure->write_func,
+					      closure->closure);
   if (status != CAIRO_STATUS_SUCCESS)
-    fail (FALSE, "Failed to write output to `%s': %s",
-	  closure->filename, cairo_status_to_string (status));
+    fail (FALSE, "Failed to write output: %s",
+	  cairo_status_to_string (status));
 }
 
 static cairo_surface_t *
-_cairo_png_surface_create (const char *filename,
-			   double width,
-			   double height,
-			   cairo_content_t content)
+_cairo_png_surface_create_for_stream (cairo_write_func_t write_func,
+				      void *closure,
+				      double width,
+				      double height,
+				      cairo_content_t content)
 {
   cairo_surface_t *surface;
   int w = ceil (width);
@@ -266,12 +271,13 @@ _cairo_png_surface_create (const char *filename,
     fail (FALSE, "Failed to create cairo surface: %s",
 	  cairo_status_to_string (status));
 
-  finalize_closure_t *closure = g_new0 (finalize_closure_t, 1);
-  closure->callback = finalize_png;
-  closure->surface = surface;
-  closure->filename = filename;
+  finalize_closure_t *png_closure = g_new0 (finalize_closure_t, 1);
+  png_closure->callback = finalize_png;
+  png_closure->surface = surface;
+  png_closure->write_func = write_func;
+  png_closure->closure = closure;
 
-  if (cairo_surface_set_user_data (surface, &finalize_closure_key, (void *) closure, (cairo_destroy_func_t) g_free))
+  if (cairo_surface_set_user_data (surface, &finalize_closure_key, (void *) png_closure, (cairo_destroy_func_t) g_free))
     g_free ((void *) closure);
 
   return surface;
@@ -304,13 +310,33 @@ view_cairo_t::render (const font_options_t *font_opts)
   cairo_destroy (cr);
 }
 
+static cairo_status_t
+stdio_write_func (void                *closure,
+		  const unsigned char *data,
+		  unsigned int         size)
+{
+  FILE *fp = (FILE *) closure;
+
+  while (size) {
+    size_t ret = fwrite (data, 1, size, fp);
+    size -= ret;
+    data += ret;
+    if (size && ferror (fp))
+      fail (FALSE, "Failed to write output: %s", strerror (errno));
+  }
+
+  return CAIRO_STATUS_SUCCESS;
+}
+
 cairo_t *
 view_cairo_t::create_context (double w, double h)
 {
-  cairo_surface_t *(*constructor) (const char *filename,
+  cairo_surface_t *(*constructor) (cairo_write_func_t write_func,
+				   void *closure,
 				   double width,
 				   double height) = NULL;
-  cairo_surface_t *(*constructor2) (const char *filename,
+  cairo_surface_t *(*constructor2) (cairo_write_func_t write_func,
+				    void *closure,
 				    double width,
 				    double height,
 				    cairo_content_t content) = NULL;
@@ -322,22 +348,22 @@ view_cairo_t::create_context (double w, double h)
     ;
   #ifdef CAIRO_HAS_PNG_FUNCTIONS
     else if (0 == strcasecmp (extension, "png"))
-      constructor2 = _cairo_png_surface_create;
+      constructor2 = _cairo_png_surface_create_for_stream;
   #endif
   #ifdef CAIRO_HAS_SVG_SURFACE
     else if (0 == strcasecmp (extension, "svg"))
-      constructor = cairo_svg_surface_create;
+      constructor = cairo_svg_surface_create_for_stream;
   #endif
   #ifdef CAIRO_HAS_PDF_SURFACE
     else if (0 == strcasecmp (extension, "pdf"))
-      constructor = cairo_pdf_surface_create;
+      constructor = cairo_pdf_surface_create_for_stream;
   #endif
   #ifdef CAIRO_HAS_PS_SURFACE
     else if (0 == strcasecmp (extension, "ps"))
-      constructor = cairo_ps_surface_create;
+      constructor = cairo_ps_surface_create_for_stream;
    #ifdef HAS_EPS
     else if (0 == strcasecmp (extension, "eps"))
-      constructor = _cairo_eps_surface_create;
+      constructor = _cairo_eps_surface_create_for_stream;
    #endif
   #endif
 
@@ -357,10 +383,11 @@ view_cairo_t::create_context (double w, double h)
     content = CAIRO_CONTENT_COLOR_ALPHA;
 
   cairo_surface_t *surface;
+  FILE *f = get_file_handle ();
   if (constructor)
-    surface = constructor (output_file, w, h);
+    surface = constructor (stdio_write_func, f, w, h);
   else if (constructor2)
-    surface = constructor2 (output_file, w, h, content);
+    surface = constructor2 (stdio_write_func, f, w, h, content);
   else
     fail (FALSE, "Unknown output format `%s'", extension);
 
commit 36b10f58cc70ce9570d17b30616f9cb27423e03b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Sep 15 16:29:51 2011 -0400

    Minor

diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 9b42d71..eb0fb43 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -194,10 +194,13 @@ _hb_ot_shape_normalize (hb_ot_shape_context_t *c)
   /* Technically speaking, two characters with ccc=0 may combine.  But all
    * those cases are in languages that the indic module handles (which expects
    * decomposed), or in Hangul jamo, which again, we want decomposed anyway.
-   * So we don't bother combining across cluster boundaries.
+   * So we don't bother combining across cluster boundaries.  This is a huge
+   * performance saver if the compose() callback is slow.
    *
    * TODO: Am I right about Hangul?  If I am, we should add a Hangul module
-   * that requests decomposed. */
+   * that requests decomposed.  If for Hangul we end up wanting composed, we
+   * can do that in the Hangul module.
+   */
 
   if (!has_multichar_clusters)
     return; /* Done! */



More information about the HarfBuzz mailing list