[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.
This commit is contained in:
Behdad Esfahbod 2011-09-15 17:52:00 -04:00
parent 36b10f58cc
commit f7e2ef74f8
3 changed files with 78 additions and 33 deletions

View File

@ -39,6 +39,7 @@
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include <locale.h> #include <locale.h>
#include <errno.h>
#include <hb.h> #include <hb.h>
#include <glib.h> #include <glib.h>

View File

@ -215,8 +215,14 @@ struct output_options_t : option_group_t
output_file = NULL; output_file = NULL;
output_format = NULL; output_format = NULL;
fp = NULL;
add_options (parser); add_options (parser);
} }
~output_options_t (void) {
if (fp && fp != stdout)
fclose (fp);
}
void add_options (option_parser_t *parser); void add_options (option_parser_t *parser);
@ -228,13 +234,21 @@ struct output_options_t : option_group_t
output_format++; /* skip the dot */ output_format++; /* skip the dot */
} }
if (!output_file) { if (output_file && 0 == strcmp (output_file, "-"))
#if defined(_MSC_VER) || defined(__MINGW32__) output_file = NULL; /* STDOUT */
output_file = "CON"; /* XXX right? */ }
#else
output_file = "/dev/stdout"; FILE *get_file_handle (void)
#endif {
} 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; 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; unsigned int text_len) = 0;
virtual void finish (const font_options_t *font_opts) = 0; virtual void finish (const font_options_t *font_opts) = 0;
protected:
const char *output_file; const char *output_file;
const char *output_format; const char *output_format;
mutable FILE *fp;
}; };

View File

@ -39,13 +39,14 @@
# define HAS_EPS 1 # define HAS_EPS 1
static cairo_surface_t * static cairo_surface_t *
_cairo_eps_surface_create (const char *filename, _cairo_eps_surface_create_for_stream (cairo_write_func_t write_func,
double width, void *closure,
double height) double width,
double height)
{ {
cairo_surface_t *surface; 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); cairo_ps_surface_set_eps (surface, TRUE);
return surface; return surface;
@ -223,7 +224,8 @@ view_cairo_t::create_scaled_font (const font_options_t *font_opts)
struct finalize_closure_t { struct finalize_closure_t {
void (*callback)(finalize_closure_t *); void (*callback)(finalize_closure_t *);
cairo_surface_t *surface; cairo_surface_t *surface;
const char *filename; cairo_write_func_t write_func;
void *closure;
}; };
static cairo_user_data_key_t finalize_closure_key; static cairo_user_data_key_t finalize_closure_key;
@ -233,17 +235,20 @@ static void
finalize_png (finalize_closure_t *closure) finalize_png (finalize_closure_t *closure)
{ {
cairo_status_t status; 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) if (status != CAIRO_STATUS_SUCCESS)
fail (FALSE, "Failed to write output to `%s': %s", fail (FALSE, "Failed to write output: %s",
closure->filename, cairo_status_to_string (status)); cairo_status_to_string (status));
} }
static cairo_surface_t * static cairo_surface_t *
_cairo_png_surface_create (const char *filename, _cairo_png_surface_create_for_stream (cairo_write_func_t write_func,
double width, void *closure,
double height, double width,
cairo_content_t content) double height,
cairo_content_t content)
{ {
cairo_surface_t *surface; cairo_surface_t *surface;
int w = ceil (width); int w = ceil (width);
@ -266,12 +271,13 @@ _cairo_png_surface_create (const char *filename,
fail (FALSE, "Failed to create cairo surface: %s", fail (FALSE, "Failed to create cairo surface: %s",
cairo_status_to_string (status)); cairo_status_to_string (status));
finalize_closure_t *closure = g_new0 (finalize_closure_t, 1); finalize_closure_t *png_closure = g_new0 (finalize_closure_t, 1);
closure->callback = finalize_png; png_closure->callback = finalize_png;
closure->surface = surface; png_closure->surface = surface;
closure->filename = filename; 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); g_free ((void *) closure);
return surface; return surface;
@ -304,13 +310,33 @@ view_cairo_t::render (const font_options_t *font_opts)
cairo_destroy (cr); 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 * cairo_t *
view_cairo_t::create_context (double w, double h) 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 width,
double height) = NULL; 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 width,
double height, double height,
cairo_content_t content) = NULL; cairo_content_t content) = NULL;
@ -322,22 +348,22 @@ view_cairo_t::create_context (double w, double h)
; ;
#ifdef CAIRO_HAS_PNG_FUNCTIONS #ifdef CAIRO_HAS_PNG_FUNCTIONS
else if (0 == strcasecmp (extension, "png")) else if (0 == strcasecmp (extension, "png"))
constructor2 = _cairo_png_surface_create; constructor2 = _cairo_png_surface_create_for_stream;
#endif #endif
#ifdef CAIRO_HAS_SVG_SURFACE #ifdef CAIRO_HAS_SVG_SURFACE
else if (0 == strcasecmp (extension, "svg")) else if (0 == strcasecmp (extension, "svg"))
constructor = cairo_svg_surface_create; constructor = cairo_svg_surface_create_for_stream;
#endif #endif
#ifdef CAIRO_HAS_PDF_SURFACE #ifdef CAIRO_HAS_PDF_SURFACE
else if (0 == strcasecmp (extension, "pdf")) else if (0 == strcasecmp (extension, "pdf"))
constructor = cairo_pdf_surface_create; constructor = cairo_pdf_surface_create_for_stream;
#endif #endif
#ifdef CAIRO_HAS_PS_SURFACE #ifdef CAIRO_HAS_PS_SURFACE
else if (0 == strcasecmp (extension, "ps")) else if (0 == strcasecmp (extension, "ps"))
constructor = cairo_ps_surface_create; constructor = cairo_ps_surface_create_for_stream;
#ifdef HAS_EPS #ifdef HAS_EPS
else if (0 == strcasecmp (extension, "eps")) else if (0 == strcasecmp (extension, "eps"))
constructor = _cairo_eps_surface_create; constructor = _cairo_eps_surface_create_for_stream;
#endif #endif
#endif #endif
@ -357,10 +383,11 @@ view_cairo_t::create_context (double w, double h)
content = CAIRO_CONTENT_COLOR_ALPHA; content = CAIRO_CONTENT_COLOR_ALPHA;
cairo_surface_t *surface; cairo_surface_t *surface;
FILE *f = get_file_handle ();
if (constructor) if (constructor)
surface = constructor (output_file, w, h); surface = constructor (stdio_write_func, f, w, h);
else if (constructor2) else if (constructor2)
surface = constructor2 (output_file, w, h, content); surface = constructor2 (stdio_write_func, f, w, h, content);
else else
fail (FALSE, "Unknown output format `%s'", extension); fail (FALSE, "Unknown output format `%s'", extension);