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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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! */ _______________________________________________ HarfBuzz mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/harfbuzz
