From f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 15 Sep 2011 17:52:00 -0400 Subject: [PATCH] [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. --- util/common.hh | 1 + util/options.hh | 31 ++++++++++++++---- util/view-cairo.cc | 79 +++++++++++++++++++++++++++++++--------------- 3 files changed, 78 insertions(+), 33 deletions(-) diff --git a/util/common.hh b/util/common.hh index 45ac6efe2..015dbf4f1 100644 --- a/util/common.hh +++ b/util/common.hh @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/util/options.hh b/util/options.hh index 404fa7333..48a3ff732 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 b09a1fe30..d747c9fb2 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);