From d9a10d1bc6c70926337384d025ebe3aababadacd Mon Sep 17 00:00:00 2001 From: ellson Date: Sun, 12 Oct 2008 21:40:32 +0000 Subject: [PATCH] Add a gs plugin that uses libgs (ghostscript) to interpret PostScript shapes and images into cairo. --- plugin/gs/Makefile.am | 41 +++++++++ plugin/gs/gvloadimage_gs.c | 176 +++++++++++++++++++++++++++++++++++++ plugin/gs/gvplugin_gs.c | 26 ++++++ 3 files changed, 243 insertions(+) create mode 100644 plugin/gs/Makefile.am create mode 100644 plugin/gs/gvloadimage_gs.c create mode 100644 plugin/gs/gvplugin_gs.c diff --git a/plugin/gs/Makefile.am b/plugin/gs/Makefile.am new file mode 100644 index 000000000..3601fa14e --- /dev/null +++ b/plugin/gs/Makefile.am @@ -0,0 +1,41 @@ +# $Id$ $Revision$ +## Process this file with automake to produce Makefile.in + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/lib/common \ + -I$(top_srcdir)/lib/pathplan \ + -I$(top_srcdir)/lib/gvc \ + -I$(top_srcdir)/lib/graph \ + -I$(top_srcdir)/lib/cdt \ + $(GS_CFLAGS) $(PANGOCAIRO_CFLAGS) + +if WITH_GS +if WITH_PANGOCAIRO +noinst_LTLIBRARIES = libgvplugin_gs_C.la +if WITH_WIN32 +lib_LTLIBRARIES = libgvplugin_gs.la +else +pkglib_LTLIBRARIES = libgvplugin_gs.la +endif +endif +endif + +libgvplugin_gs_C_la_SOURCES = \ + gvplugin_gs.c \ + gvloadimage_gs.c + +libgvplugin_gs_la_LDFLAGS = -version-info $(GVPLUGIN_VERSION_INFO) +libgvplugin_gs_la_SOURCES = $(libgvplugin_gs_C_la_SOURCES) +libgvplugin_gs_la_LIBADD = \ + $(top_builddir)/lib/gvc/libgvc.la $(PANGOCAIRO_LIBS) $(GS_LIBS) + +if WITH_WIN32 +libgvplugin_gs_la_LDFLAGS += -no-undefined +endif + +if WITH_DARWIN9 +libgvplugin_gs_la_LDFLAGS += -Wl,-exported_symbol,_gvplugin_gs_LTX_library +endif + +EXTRA_DIST = Makefile.old diff --git a/plugin/gs/gvloadimage_gs.c b/plugin/gs/gvloadimage_gs.c new file mode 100644 index 000000000..f5ec52cb6 --- /dev/null +++ b/plugin/gs/gvloadimage_gs.c @@ -0,0 +1,176 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gvplugin_loadimage.h" + +#ifdef HAVE_GS +#ifdef HAVE_PANGOCAIRO +#include +#include +#include + +#ifdef WIN32 +#define NUL_FILE "nul" +#else +#define NUL_FILE "/dev/null" +#endif + +typedef enum { + FORMAT_PS_CAIRO, FORMAT_EPS_CAIRO, +} format_type; + +typedef struct gs_s { + cairo_t* cr; + cairo_surface_t* surface; + cairo_pattern_t* pattern; +} gs_t; + +static void gvloadimage_gs_free(usershape_t *us) +{ + gs_t *gs = (gs_t*)us->data; + + cairo_pattern_destroy(gs->pattern); + cairo_surface_destroy(gs->surface); + cairo_destroy(gs->cr); + free(gs); +} + +static void gs_error(const char *str, int rc) +{ + fprintf(stderr, "gs error %s %d\n", str, rc); +} + +static int gs_writer(void *caller_handle, const char *str, int len) +{ + GVJ_t *job = (GVJ_t*)caller_handle; + + if (job->common->verbose) + return fwrite(str, 1, len, stderr); + return len; +} + +static cairo_pattern_t* gvloadimage_gs_load(GVJ_t * job, usershape_t *us) +{ + gs_t *gs = NULL; + void *instance; + int rc, exit_code; + char width_height[20], dpi[10], cairo_context[30]; + char *gs_args[] = { + "-dQUIET", + "-dNOPAUSE", + "-sDEVICE=cairo", + cairo_context, + width_height, + dpi, + }; +#define GS_ARGC sizeof(gs_args)/sizeof(gs_args[0]) + + assert(job); + assert(us); + assert(us->name); + + if (us->data) { + if (us->datafree == gvloadimage_gs_free && ((gs_t*)(us->data))->cr == (cairo_t *)job->context) + gs = (gs_t*)(us->data); /* use cached data */ + else { + us->datafree(us); /* free incompatible cache data */ + us->data = NULL; + } + } + if (!gs) { + cairo_t *cr; /* temp cr for gs */ + + if (!gvusershape_file_access(us)) + return NULL; + + gs = (gs_t *)malloc(sizeof(gs_t)); + if (!gs) + return NULL; + + gs->cr = (cairo_t *)job->context; + gs->surface = cairo_surface_create_similar( + cairo_get_target(gs->cr), + CAIRO_CONTENT_COLOR_ALPHA, + us->x + us->w, + us->y + us->h); + gs->pattern = cairo_pattern_create_for_surface (gs->surface); + + rc = gsapi_new_instance(&instance, (void*)job); + if (rc) { gs_error("gsapi_new_instance", rc); return NULL; } + rc = gsapi_set_stdio(instance, NULL, gs_writer, gs_writer); + if (rc) { gs_error("gsapi_set_stdio", rc); return NULL; } + sprintf(width_height, "-g%dx%d", us->x + us->w, us->y + us->h); + sprintf(dpi, "-r%d", us->dpi); + cr = cairo_create(gs->surface); + sprintf(cairo_context, "-sCairoContext=%p", cr); + rc = gsapi_init_with_args(instance, GS_ARGC, gs_args); + cairo_destroy(cr); + if (rc) { gs_error("gsapi_init_with_args", rc); return NULL; } + + rc = gsapi_run_file(instance, us->name, 0, &exit_code); + if (rc) { gs_error("gsapi_run_file", rc); return NULL; } + + rc = gsapi_exit(instance); + if (rc) { gs_error("gsapi_exit", rc); return NULL; } + + gsapi_delete_instance(instance); + + us->data = (void*)gs; + us->datafree = gvloadimage_gs_free; + + gvusershape_file_release(us); + } + return gs->pattern; +} + +static void gvloadimage_gs_cairo(GVJ_t * job, usershape_t *us, boxf b, boolean filled) +{ + cairo_t *cr = (cairo_t *) job->context; /* target context */ + cairo_pattern_t *pattern = gvloadimage_gs_load(job, us); + + if (pattern) { + cairo_save(cr); + cairo_translate(cr, b.LL.x - us->x, -b.UR.y); + cairo_scale(cr, (b.UR.x - b.LL.x) / us->w, (b.UR.y - b.LL.y) / us->h); + cairo_set_source(cr, pattern); + cairo_paint(cr); + cairo_restore(cr); + } +} + +static gvloadimage_engine_t engine_cairo = { + gvloadimage_gs_cairo +}; +#endif +#endif + +gvplugin_installed_t gvloadimage_gs_types[] = { +#ifdef HAVE_GS +#ifdef HAVE_PANGOCAIRO + {FORMAT_PS_CAIRO, "ps:cairo", 1, &engine_cairo, NULL}, + {FORMAT_EPS_CAIRO, "eps:cairo", 1, &engine_cairo, NULL}, +#endif +#endif + {0, NULL, 0, NULL, NULL} +}; diff --git a/plugin/gs/gvplugin_gs.c b/plugin/gs/gvplugin_gs.c new file mode 100644 index 000000000..3727e6520 --- /dev/null +++ b/plugin/gs/gvplugin_gs.c @@ -0,0 +1,26 @@ +/* $Id$ $Revision$ */ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + +#include "gvplugin.h" + +extern gvplugin_installed_t gvloadimage_gs_types; + +static gvplugin_api_t apis[] = { + {API_loadimage, &gvloadimage_gs_types}, + {(api_t)0, 0}, +}; + +gvplugin_library_t gvplugin_gs_LTX_library = { "gs", apis }; -- 2.40.0