pkginclude_HEADERS = gvc.h gvcext.h gvplugin.h gvcjob.h gvcint.h \
gvcommon.h gvplugin_render.h gvplugin_layout.h \
- gvplugin_textlayout.h gvplugin_device.h \
- dot_builtins.c \
- demand_loading.c no_demand_loading.c
+ gvplugin_textlayout.h gvplugin_device.h gvplugin_loadimage.h \
+ dot_builtins.c demand_loading.c no_demand_loading.c
noinst_HEADERS = gvcproc.h
noinst_LTLIBRARIES = libgvc_C.la
pkglib_LTLIBRARIES = libgvc.la libgvc_builtins.la
pkgconfig_DATA = libgvc.pc libgvc_builtins.pc
-libgvc_C_la_SOURCES = gvrender.c gvlayout.c gvdevice.c gvcontext.c gvjobs.c \
+libgvc_C_la_SOURCES = gvrender.c gvlayout.c gvdevice.c gvloadimage.c gvcontext.c gvjobs.c \
gvevent.c gvplugin.c gvconfig.c gvtextlayout.c gvusershape.c gvc.c
libgvc_C_la_LIBADD = $(top_builddir)/lib/common/libcommon_C.la
typedef struct gvrender_engine_s gvrender_engine_t;
typedef struct gvlayout_engine_s gvlayout_engine_t;
typedef struct gvtextlayout_engine_s gvtextlayout_engine_t;
+ typedef struct gvloadimage_engine_s gvloadimage_engine_t;
typedef enum { PEN_NONE, PEN_DASHED, PEN_DOTTED, PEN_SOLID } pen_type;
typedef enum { FILL_NONE, FILL_SOLID } fill_type;
int sz_knowncolors;
color_type_t color_type;
char *device;
+ char *loadimage_target;
} gvrender_features_t;
typedef struct {
char *type;
} gvplugin_active_render_t;
+ typedef struct gvplugin_active_loadimage_t {
+ gvloadimage_engine_t *engine;
+ int id;
+ char *type;
+ } gvplugin_active_loadimage_t;
+
typedef struct gv_argvlist_s {
char **argv;
int argc;
gvplugin_active_render_t render;
gvplugin_active_device_t device;
+ gvplugin_active_loadimage_t loadimage;
gvdevice_callbacks_t *callbacks;
void *surface; /* gd or cairo surface */
extern int gvtextlayout_select(GVC_t * gvc);
extern bool gvtextlayout(GVC_t *gvc, textpara_t *para, char **fontpath);
+/* loadimage */
+ extern void gvloadimage(GVJ_t *job, usershape_t *us, boxf b, bool filled, char *target);
+
/* usershapes */
extern point gvusershape_size(graph_t *g, char *name);
extern usershape_t *gvusershape_find(char *name);
--- /dev/null
+/* $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 *
+**********************************************************/
+
+/*
+ * graphics code generator wrapper
+ *
+ * This library forms the socket for run-time loadable loadimage plugins.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "const.h"
+#include "gvplugin_loadimage.h"
+#include "gvcint.h"
+#include "gvcproc.h"
+
+int gvloadimage_select(GVJ_t * job, char *str)
+{
+ gvplugin_available_t *plugin;
+ gvplugin_installed_t *typeptr;
+
+ plugin = gvplugin_load(job->gvc, API_loadimage, str);
+ if (plugin) {
+ typeptr = plugin->typeptr;
+ job->loadimage.engine = (gvloadimage_engine_t *) (typeptr->engine);
+ job->loadimage.id = typeptr->id;
+ return GVRENDER_PLUGIN;
+ }
+ return NO_SUPPORT;
+}
+
+void gvloadimage(GVJ_t * job, usershape_t *us, boxf b, bool filled, char *target)
+{
+ gvloadimage_engine_t *gvli;
+ char type[SMALLBUF];
+
+ switch (us->type) {
+ case FT_PNG:
+ strcpy(type, "png");
+ break;
+ case FT_JPEG:
+ strcpy(type, "jpeg");
+ break;
+ case FT_GIF:
+ strcpy(type, "gif");
+ break;
+ default:
+ strcpy(type, "");
+ break;
+ }
+ strcat(type, "2");
+ strcat(type, target);
+
+ if (type)
+ gvloadimage_select(job, type);
+
+ if ((gvli = job->loadimage.engine)) {
+ if (gvli->loadimage) {
+ gvli->loadimage(job, us, b, filled);
+ }
+ }
+}
* The enumerated type is defined here. The apis array is
* inititialized in gvplugin.c by redefining ELEM and reinvoking APIS.
*/
-#define APIS ELEM(render) ELEM(layout) ELEM(textlayout) ELEM(device)
+#define APIS ELEM(render) ELEM(layout) ELEM(textlayout) ELEM(device) ELEM(loadimage)
/*
* Define api_t using names based on the plugin names with API_ prefixed.
--- /dev/null
+/* $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 *
+**********************************************************/
+
+#ifndef GVPLUGIN_IMAGELOAD_H
+#define GVPLUGIN_IMAGELOAD_H
+
+#include "types.h"
+#include "gvplugin.h"
+#include "gvcjob.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ struct gvloadimage_engine_s {
+ void (*loadimage) (GVJ_t *job, usershape_t *us, boxf b, bool filled);
+ };
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* GVPLUGIN_IMAGELOAD_H */
af[1].x = pf.x + rx;
af[1].y = pf.y + ry;
- if (! (job->flags & GVRENDER_DOES_TRANSFORM)) {
- af[0] = gvrender_ptf(job, af[0]);
- af[1] = gvrender_ptf(job, af[1]);
- }
+ if (! (job->flags & GVRENDER_DOES_TRANSFORM))
+ gvrender_ptf_A(job, af, af, 2);
gvre->ellipse(job, af, filled);
}
}
void gvrender_polygon(GVJ_t * job, pointf * af, int n, bool filled)
{
- int i;
gvrender_engine_t *gvre = job->render.engine;
if (gvre && gvre->polygon) {
sizeAF = n+10;
AF = grealloc(AF, sizeAF * sizeof(pointf));
}
- for (i = 0; i < n; i++)
- AF[i] = gvrender_ptf(job, af[i]);
+ gvrender_ptf_A(job, af, AF, n);
gvre->polygon(job, AF, n, filled);
}
}
#ifdef WITH_CODEGENS
else {
codegen_t *cg = job->codegen;
+ int i;
if (sizeA < n) {
sizeA = n+10;
if (job->flags & GVRENDER_DOES_TRANSFORM)
gvre->beziercurve(job, af, n, arrow_at_start, arrow_at_end,filled);
else {
- int i;
if (sizeAF < n) {
sizeAF = n+10;
AF = grealloc(AF, sizeAF * sizeof(pointf));
}
- for (i = 0; i < n; i++)
- AF[i] = gvrender_ptf(job, af[i]);
+ gvrender_ptf_A(job, af, AF, n);
gvre->beziercurve(job, AF, n, arrow_at_start, arrow_at_end,filled);
}
}
void gvrender_polylinef(GVJ_t * job, pointf * af, int n)
{
- int i;
gvrender_engine_t *gvre = job->render.engine;
if (gvre && gvre->polyline) {
sizeAF = n+10;
AF = grealloc(AF, sizeAF * sizeof(pointf));
}
- for (i = 0; i < n; i++)
- AF[i] = gvrender_ptf(job, af[i]);
+ gvrender_ptf_A(job, af, AF, n);
gvre->polyline(job, AF, n);
}
}
#ifdef WITH_CODEGENS
else {
codegen_t *cg = job->codegen;
+ int i;
if (sizeA < n) {
sizeA = n+10;
sizeAF = n+10;
AF = grealloc(AF, sizeAF * sizeof(pointf));
}
- for (i = 0; i < n; i++)
- AF[i] = gvrender_ptf(job, a[i]);
+ gvrender_ptf_A(job, a, AF, n);
af = AF;
}
b.UR.y -= (ph - th) / 2.0;
}
- if (gvre && gvre->usershape)
- gvre->usershape(job, us, b, filled);
+ if (gvre) {
+ if (gvre->usershape)
+ gvre->usershape(job, us, b, filled);
+ else if (job->render.features->loadimage_target)
+ gvloadimage(job, us, b, filled, job->render.features->loadimage_target);
+ }
#ifdef WITH_CODEGENS
else {
codegen_t *cg = job->codegen;
NULL, /* knowncolors */
0, /* sizeof knowncolors */
0, /* color_type */
+ NULL, /* device */
+ NULL, /* gvloadimage target for usershapes */
};
static gvrender_features_t mapgen_features = {
NULL, /* knowncolors */
0, /* sizeof knowncolors */
0, /* color_type */
+ NULL, /* device */
+ NULL, /* gvloadimage target for usershapes */
};
gvplugin_installed_t gvrender_core_map_types[] = {
#include "gd.h"
#endif
+/* for CHAR_LATIN1 */
+#include "const.h"
+
/*
* J$: added `pdfmark' URL embedding. PostScript rendered from
* dot files with URL attributes will get active PDF links
cat_preamble(job, job->common->lib);
epsf_define(job->output_file);
}
-#if 0
- // FIXME
isLatin1 = (GD_charset(obj->g) == CHAR_LATIN1);
if (isLatin1 && !setupLatin1) {
fprintf(job->output_file, "setupLatin1\n"); /* as defined in ps header */
setupLatin1 = TRUE;
}
-#endif
/* Set base URL for relative links (for Distiller >= 3.0) */
if (obj->url)
fprintf(job->output_file, "[ {Catalog} << /URI << /Base (%s) >> >>\n"
{
obj_state_t *obj = job->obj;
- if (obj->url_map_p) {
+ if (obj->url) {
fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
obj->url_map_p[0].x, obj->url_map_p[0].y,
obj->url_map_p[1].x, obj->url_map_p[1].y);
{
obj_state_t *obj = job->obj;
- if (obj->url_map_p) {
+ if (obj->url) {
fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
obj->url_map_p[0].x, obj->url_map_p[0].y,
obj->url_map_p[1].x, obj->url_map_p[1].y);
"/ANN pdfmark\n",
ps_string(obj->url, isLatin1));
}
- if (obj->tailurl_map_p) {
+ if (obj->tailurl) {
fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
obj->tailurl_map_p[0].x, obj->tailurl_map_p[0].y,
obj->tailurl_map_p[1].x, obj->tailurl_map_p[1].y);
"/ANN pdfmark\n",
ps_string(obj->tailurl, isLatin1));
}
- if (obj->headurl_map_p) {
+ if (obj->headurl) {
fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
obj->headurl_map_p[0].x, obj->headurl_map_p[0].y,
obj->headurl_map_p[1].x, obj->headurl_map_p[1].y);
"/ANN pdfmark\n",
ps_string(obj->headurl, isLatin1));
}
- if (obj->tailendurl_map_p) {
+ if (obj->tailurl) {
fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
obj->tailendurl_map_p[0].x, obj->tailendurl_map_p[0].y,
obj->tailendurl_map_p[1].x, obj->tailendurl_map_p[1].y);
"/ANN pdfmark\n",
ps_string(obj->tailurl, isLatin1));
}
- if (obj->headendurl_map_p) {
+ if (obj->headurl) {
fprintf(job->output_file, "[ /Rect [ %g %g %g %g ]\n",
obj->headendurl_map_p[0].x, obj->headendurl_map_p[0].y,
obj->headendurl_map_p[1].x, obj->headendurl_map_p[1].y);
fprintf(job->output_file, "%% %s\n", str);
}
-static void ps_freeimage_gd (void *data)
-{
-#ifdef HAVE_LIBGD
- gdImageDestroy((gdImagePtr)data);
-#endif
-}
-
static void ps_freeimage_ps (void *data)
{
#if 0
#endif
}
-#ifdef HAVE_LIBGD
-static void writePSBitmap (GVJ_t *job, gdImagePtr im, boxf b)
-{
- int x, y, px;
-
- fprintf(job->output_file, "gsave\n");
-
- /* this sets the position of the image */
- fprintf(job->output_file, "%g %g translate %% lower-left coordinate\n", b.LL.x, b.LL.y);
-
- /* this sets the rendered size to fit the box */
- fprintf(job->output_file,"%g %g scale\n", b.UR.x - b.LL.x, b.UR.y - b.LL.y);
-
- /* xsize ysize bits-per-sample [matrix] */
- fprintf(job->output_file, "%d %d 8 [%d 0 0 %d 0 %d]\n", im->sx, im->sy,
- im->sx, -(im->sy), im->sy);
-
- fprintf(job->output_file, "{<\n");
- for (y = 0; y < im->sy; y++) {
- for (x = 0; x < im->sx; x++) {
- if (im->trueColor) {
- px = gdImageTrueColorPixel(im, x, y);
- fprintf(job->output_file, "%02x%02x%02x",
- gdTrueColorGetRed(px),
- gdTrueColorGetGreen(px),
- gdTrueColorGetBlue(px));
- }
- else {
- px = gdImagePalettePixel(im, x, y);
- fprintf(job->output_file, "%02x%02x%02x",
- im->red[px],
- im->green[px],
- im->blue[px]);
- }
- }
- fprintf(job->output_file, "\n");
- }
-
- fprintf(job->output_file, ">}\n");
- fprintf(job->output_file, "false 3 colorimage\n");
-
- fprintf(job->output_file, "grestore\n");
-
-}
-#endif
-
-
/* ps_usershape:
* Images for postscript are complicated by the old epsf shape, as
* well as user-defined shapes using postscript code.
static void
psgen_usershape(GVJ_t * job, usershape_t *us, boxf b, bool filled)
{
-#ifdef HAVE_LIBGD
- gdImagePtr gd_img = NULL;
-#endif
#ifdef XXX_PS
int j;
ps_image_t *ps_img = NULL;
}
if (us->data) {
- if (us->datafree == ps_freeimage_gd) {
-#ifdef HAVE_LIBGD
- gd_img = (gdImagePtr)(us->data); /* use cached data */
-#endif
- }
- else if (us->datafree == ps_freeimage_ps) {
+ if (us->datafree == ps_freeimage_ps) {
#ifdef XXX_PS
ps_img = (ps_image_t *)(us->data); /* use cached data */
#endif
}
}
-#ifdef HAVE_LIBGD
-#ifdef XXX_PS
- if (!ps_img && !gd_img) { /* read file into cache */
-#else
- if (!gd_img) { /* read file into cache */
-#endif
-#else
#ifdef XXX_PS
if (!ps_img) { /* read file into cache */
#else
if (false) { /* nothing to do */
-#endif
#endif
fseek(us->f, 0, SEEK_SET);
switch (us->type) {
-#ifdef HAVE_LIBGD
-#ifdef HAVE_GD_PNG
- case FT_PNG:
- gd_img = gdImageCreateFromPng(us->f);
- break;
-#endif
-#ifdef HAVE_GD_GIF
- case FT_GIF:
- gd_img = gdImageCreateFromGif(us->f);
- break;
-#endif
-#ifdef HAVE_GD_JPEG
- case FT_JPEG:
- gd_img = gdImageCreateFromJpeg(us->f);
- break;
-#endif
-#endif
#ifdef XXX_PS
case FT_PS:
case FT_EPS:
default:
break;
}
-#ifdef HAVE_LIBGD
- if (gd_img) {
- us->data = (void*)gd_img;
- us->datafree = ps_freeimage_gd;
- }
-#endif
#ifdef XXX_PS
if (ps_img) {
us->data = (void*)ps_img;
}
#endif
-#ifdef HAVE_LIBGD
- if (gd_img) {
- writePSBitmap (job, gd_img, b);
- return;
- }
-#endif
-
/* some other type of image */
job->common->errorfn("usershape %s is not supported in PostScript output\n", us->name);
}
psgen_bezier,
psgen_polyline,
psgen_comment,
- psgen_usershape
+ 0, /* psgen_usershape */
};
static gvrender_features_t psgen_features = {
NULL, /* knowncolors */
0, /* sizeof knowncolors */
HSV_DOUBLE, /* color_type */
+ NULL, /* device */
+ "ps", /* gvloadimage target for usershapes */
};
gvplugin_installed_t gvrender_core_ps_types[] = {
svggen_knowncolors, /* knowncolors */
sizeof(svggen_knowncolors) / sizeof(char *), /* sizeof knowncolors */
RGBA_BYTE, /* color_type */
+ NULL, /* device */
+ NULL, /* gvloadimage target for usershapes */
};
gvplugin_installed_t gvrender_core_svg_types[] = {
--- /dev/null
+/* $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 <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#ifdef MSWIN32
+#include <io.h>
+#endif
+#endif
+
+#include "gvplugin_loadimage.h"
+
+#ifdef HAVE_LIBGD
+#include "gd.h"
+
+typedef enum {
+ FORMAT_PNG_GD, FORMAT_GIF_GD, FORMAT_JPG_GD, FORMAT_GD_GD, FORMAT_GD2_GD, FORMAT_XPM_GD, FORMAT_WBMP_GD,
+ FORMAT_PNG_PS, FORMAT_GIF_PS, FORMAT_JPG_PS, FORMAT_GD_PS, FORMAT_GD2_PS, FORMAT_XPM_PS, FORMAT_WBMP_PS,
+} format_type;
+
+
+static void gd_freeimage(void *data)
+{
+ gdImageDestroy((gdImagePtr)data);
+}
+
+static gdImagePtr gd_loadimage(GVJ_t * job, usershape_t *us)
+{
+ gdImagePtr im = NULL;
+
+ if (us->data) {
+ if (us->datafree == gd_freeimage)
+ im = (gdImagePtr)(us->data); /* use cached data */
+ else {
+ us->datafree(us->data); /* free incompatible cache data */
+ us->data = NULL;
+ }
+ }
+ if (!im) { /* read file into cache */
+ fseek(us->f, 0, SEEK_SET);
+ switch (us->type) {
+#if 0
+ case FT_GD:
+ im = gdImageCreateFromGd(us->f);
+ break;
+ case FT_GD2:
+ im = gdImageCreateFromGd2(us->f);
+ break;
+#endif
+#ifdef HAVE_GD_PNG
+ case FT_PNG:
+ im = gdImageCreateFromPng(us->f);
+ break;
+#endif
+#ifdef HAVE_GD_GIF
+ case FT_GIF:
+ im = gdImageCreateFromGif(us->f);
+ break;
+#endif
+#ifdef HAVE_GD_JPEG
+ case FT_JPEG:
+ im = gdImageCreateFromJpeg(us->f);
+ break;
+#endif
+#if 0
+#ifdef HAVE_GD_XPM
+ case FT_XPM:
+ im = gdImageCreateFromXpm(us->f);
+ break;
+#endif
+#ifdef HAVE_GD_WBMP
+ case FT_WBMP:
+ im = gdImageCreateFromWbmp(us->f);
+ break;
+#endif
+#endif
+ default:
+ im = NULL;
+ }
+ if (im) {
+ us->data = (void*)im;
+ us->datafree = gd_freeimage;
+ }
+ }
+ return im;
+}
+
+static void gd_loadimage_gd(GVJ_t * job, usershape_t *us, boxf b, bool filled)
+{
+ gdImagePtr im3, im2 = NULL, im = (gdImagePtr) job->surface;
+
+ im2 = gd_loadimage(job, us);
+ if (im2) {
+ if (job->rotation) {
+ im3 = gdImageCreate(im2->sy, im2->sx); /* scratch image for rotation */
+ gdImageCopyRotated(im3, im2, im3->sx / 2., im3->sy / 2.,
+ 0, 0, im2->sx, im2->sy, job->rotation);
+ gdImageCopyResized(im, im3, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
+ ROUND(b.UR.y - b.LL.y), ROUND(b.UR.x - b.LL.x), im3->sx, im3->sy);
+ gdImageDestroy(im3);
+ }
+ else {
+ gdImageCopyResized(im, im2, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
+ ROUND(b.UR.x - b.LL.x), ROUND(b.UR.y - b.LL.y), im2->sx, im2->sy);
+ }
+ }
+}
+
+static void gd_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, bool filled)
+{
+ gdImagePtr im = NULL;
+ FILE *out = job->output_file;
+ int X, Y, x, y, px;
+
+ im = gd_loadimage(job, us);
+ if (im) {
+ X = im->sx;
+ Y = im->sy;
+
+ fprintf(out, "gsave\n");
+
+ /* this sets the position of the image */
+ fprintf(out, "%g %g translate %% lower-left coordinate\n", b.LL.x, b.LL.y);
+
+ /* this sets the rendered size to fit the box */
+ fprintf(out,"%g %g scale\n", b.UR.x - b.LL.x, b.UR.y - b.LL.y);
+
+ /* xsize ysize bits-per-sample [matrix] */
+ fprintf(out, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y);
+
+ fprintf(out, "{<\n");
+ if (im->trueColor) {
+ for (y = 0; y < Y; y++) {
+ for (x = 0; x < X; x++) {
+ px = gdImageTrueColorPixel(im, x, y);
+ fprintf(out, "%02x%02x%02x",
+ gdTrueColorGetRed(px),
+ gdTrueColorGetGreen(px),
+ gdTrueColorGetBlue(px));
+ }
+ }
+ fprintf(out, "\n");
+ }
+ else {
+ for (y = 0; y < Y; y++) {
+ for (x = 0; x < X; x++) {
+ px = gdImagePalettePixel(im, x, y);
+ fprintf(out, "%02x%02x%02x",
+ im->red[px],
+ im->green[px],
+ im->blue[px]);
+ }
+ }
+ fprintf(out, "\n");
+ }
+
+ fprintf(out, ">}\n");
+ fprintf(out, "false 3 colorimage\n");
+
+ fprintf(out, "grestore\n");
+ }
+}
+
+static gvloadimage_engine_t engine = {
+ gd_loadimage_gd
+};
+
+static gvloadimage_engine_t engine_ps = {
+ gd_loadimage_ps
+};
+
+#endif
+
+gvplugin_installed_t gvloadimage_gd_types[] = {
+#ifdef HAVE_LIBGD
+#if 0
+ {FORMAT_GD_GD, "gd2gd", 1, &engine, NULL},
+ {FORMAT_GD2_GD, "gd22gd", 1, &engine, NULL},
+#endif
+#ifdef HAVE_GD_GIF
+ {FORMAT_GIF_GD, "gif2gd", 1, &engine, NULL},
+#endif
+#ifdef HAVE_GD_JPEG
+ {FORMAT_JPG_GD, "jpeg2gd", 1, &engine, NULL},
+#endif
+#ifdef HAVE_GD_PNG
+ {FORMAT_PNG_GD, "png2gd", 1, &engine, NULL},
+#endif
+#if 0
+#ifdef HAVE_GD_WBMP
+ {FORMAT_WBMP_GD, "wbmp2gd", 1, &engine, NULL},
+#endif
+#ifdef HAVE_GD_XPM
+ {FORMAT_XBM_GD, "xbm2gd", 1, &engine, NULL},
+#endif
+#endif
+#if 0
+ {FORMAT_GD_PS, "gd2ps", 1, &engine_ps, NULL},
+ {FORMAT_GD2_PS, "gd22ps", 1, &engine_ps, NULL},
+#endif
+#ifdef HAVE_GD_GIF
+ {FORMAT_GIF_PS, "gif2ps", 1, &engine_ps, NULL},
+#endif
+#ifdef HAVE_GD_JPEG
+ {FORMAT_JPG_PS, "jpeg2ps", 1, &engine_ps, NULL},
+#endif
+#ifdef HAVE_GD_PNG
+ {FORMAT_PNG_PS, "png2ps", 1, &engine_ps, NULL},
+#endif
+#if 0
+#ifdef HAVE_GD_WBMP
+ {FORMAT_WBMP_PS, "wbmp2ps", 1, &engine_ps, NULL},
+#endif
+#ifdef HAVE_GD_XPM
+ {FORMAT_XBM_PS, "xbm2ps", 1, &engine_ps, NULL},
+#endif
+#endif
+#endif
+ {0, NULL, 0, NULL, NULL}
+};
gdImageDestroy(brush);
}
-static void gdgen_freeimage(void *data)
-{
- gdImageDestroy((gdImagePtr)data);
-}
-
-static void
-gdgen_usershape(GVJ_t * job, usershape_t *us, boxf b, bool filled)
-{
- gdImagePtr im3, im2 = NULL, im = (gdImagePtr) job->surface;
-
- if (us->data) {
- if (us->datafree == gdgen_freeimage)
- im2 = (gdImagePtr)(us->data); /* use cached data */
- else {
- us->datafree(us->data); /* free incompatible cache data */
- us->data = NULL;
- }
- }
- if (!im2) { /* read file into cache */
- fseek(us->f, 0, SEEK_SET);
- switch (us->type) {
-#ifdef HAVE_GD_PNG
- case FT_PNG:
- im2 = gdImageCreateFromPng(us->f);
- break;
-#endif
-#ifdef HAVE_GD_GIF
- case FT_GIF:
- im2 = gdImageCreateFromGif(us->f);
- break;
-#endif
-#ifdef HAVE_GD_JPEG
- case FT_JPEG:
- im2 = gdImageCreateFromJpeg(us->f);
- break;
-#endif
- default:
- im2 = NULL;
- }
- if (im2) {
- us->data = (void*)im2;
- us->datafree = gdgen_freeimage;
- }
- }
- if (im2) {
- if (job->rotation) {
- im3 = gdImageCreate(im2->sy, im2->sx); /* scratch image for rotation */
- gdImageCopyRotated(im3, im2, im3->sx / 2., im3->sy / 2.,
- 0, 0, im2->sx, im2->sy, job->rotation);
- gdImageCopyResized(im, im3, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
- ROUND(b.UR.y - b.LL.y), ROUND(b.UR.x - b.LL.x), im3->sx, im3->sy);
- gdImageDestroy(im3);
- }
- else {
- gdImageCopyResized(im, im2, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
- ROUND(b.UR.x - b.LL.x), ROUND(b.UR.y - b.LL.y), im2->sx, im2->sy);
- }
- }
-}
-
static gvrender_engine_t gdgen_engine = {
0, /* gdgen_begin_job */
0, /* gdgen_end_job */
gdgen_bezier,
gdgen_polyline,
0, /* gdgen_comment */
- gdgen_usershape
+ 0 /* gdgen_usershape */ /* provided by gvloadimage */
};
static gvrender_features_t gdgen_features_tc = {
0, /* sizeof knowncolors */
RGBA_BYTE, /* color_type */
NULL, /* device */
+ "gd", /* gvloadimage target for usershapes */
};
static gvrender_features_t gdgen_features = {
0, /* sizeof knowncolors */
RGBA_BYTE, /* color_type */
NULL, /* device */
+ "gd", /* gvloadimage target for usershapes */
};
#endif
--- /dev/null
+/* $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 <stdlib.h>
+
+#include "gvplugin_loadimage.h"
+
+#ifdef HAVE_PANGOCAIRO
+#include <cairo.h>
+
+typedef enum {
+ FORMAT_PNG_CAIRO, FORMAT_PNG_PS,
+} format_type;
+
+static cairo_status_t
+reader (void *closure, unsigned char *data, unsigned int length)
+{
+ if (length == fread(data, 1, length, (FILE *)closure)
+ || feof((FILE *)closure))
+ return CAIRO_STATUS_SUCCESS;
+ return CAIRO_STATUS_READ_ERROR;
+}
+
+static void cairo_freeimage(void *data)
+{
+ cairo_destroy((cairo_t*)data);
+}
+
+static cairo_surface_t* cairo_loadimage(GVJ_t * job, usershape_t *us)
+{
+ cairo_surface_t *surface = NULL; /* source surface */
+
+ if (us->data) {
+ if (us->datafree == cairo_freeimage)
+ surface = (cairo_surface_t*)(us->data); /* use cached data */
+ else {
+ us->datafree(us->data); /* free incompatible cache data */
+ us->data = NULL;
+ }
+ }
+ if (!surface) { /* read file into cache */
+ fseek(us->f, 0, SEEK_SET);
+ switch (us->type) {
+#ifdef CAIRO_HAS_PNG_FUNCTIONS
+ case FT_PNG:
+ surface = cairo_image_surface_create_from_png_stream(reader, us->f);
+ cairo_surface_reference(surface);
+ break;
+#endif
+ default:
+ surface = NULL;
+ }
+ if (surface) {
+ us->data = (void*)surface;
+ us->datafree = cairo_freeimage;
+ }
+ }
+ return surface;
+}
+
+static void pango_loadimage_cairo(GVJ_t * job, usershape_t *us, boxf b, bool filled)
+{
+ cairo_t *cr = (cairo_t *) job->surface; /* target context */
+ cairo_surface_t *surface = NULL; /* source surface */
+
+ surface = cairo_loadimage(job, us);
+ if (surface) {
+ cairo_save(cr);
+ cairo_translate(cr, ROUND(b.LL.x), ROUND(-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_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+ cairo_restore(cr);
+ }
+}
+
+static void pango_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, bool filled)
+{
+ cairo_surface_t *surface = NULL; /* source surface */
+ FILE *out = job->output_file;
+ int X, Y, x, y, stride;
+ unsigned char *data, *ix, alpha, red, green, blue;
+
+ surface = cairo_loadimage(job, us);
+ if (surface && (cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32)) {
+ X = cairo_image_surface_get_width(surface);
+ Y = cairo_image_surface_get_height(surface);
+ stride = cairo_image_surface_get_stride(surface);
+ data = cairo_image_surface_get_data(surface);
+
+ fprintf(out, "gsave\n");
+
+ /* this sets the position of the image */
+ fprintf(out, "%g %g translate %% lower-left coordinate\n", b.LL.x, b.LL.y);
+
+ /* this sets the rendered size to fit the box */
+ fprintf(out,"%g %g scale\n", b.UR.x - b.LL.x, b.UR.y - b.LL.y);
+
+ /* xsize ysize bits-per-sample [matrix] */
+ fprintf(out, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y);
+
+ fprintf(out, "{<\n");
+
+ for (y = 0; y < Y; y++) {
+ ix = data + y * stride;
+ for (x = 0; x < X; x++) {
+ /* FIXME - this code may have endian problems */
+ blue = *ix++;
+ green = *ix++;
+ red = *ix++;
+ alpha = *ix++;
+ fprintf(out, "%02x%02x%02x", red, green, blue);
+ }
+ fprintf(out, "\n");
+ }
+
+ fprintf(out, ">}\n");
+ fprintf(out, "false 3 colorimage\n");
+
+ fprintf(out, "grestore\n");
+ }
+}
+
+static gvloadimage_engine_t engine_cairo = {
+ pango_loadimage_cairo
+};
+
+static gvloadimage_engine_t engine_ps = {
+ pango_loadimage_ps
+};
+#endif
+
+gvplugin_installed_t gvloadimage_pango_types[] = {
+#ifdef HAVE_PANGOCAIRO
+ {FORMAT_PNG_CAIRO, "png2cairo", 1, &engine_cairo, NULL},
+ {FORMAT_PNG_PS, "png2ps", 1, &engine_ps, NULL},
+#endif
+ {0, NULL, 0, NULL, NULL}
+};
extern gvplugin_installed_t gvrender_pango_types;
extern gvplugin_installed_t gvtextlayout_pango_types;
+extern gvplugin_installed_t gvloadimage_pango_types;
static gvplugin_api_t apis[] = {
{API_render, &gvrender_pango_types},
{API_textlayout, &gvtextlayout_pango_types},
+ {API_loadimage, &gvloadimage_pango_types},
{(api_t)0, 0},
};
return CAIRO_STATUS_WRITE_ERROR;
}
-static cairo_status_t
-reader (void *closure, unsigned char *data, unsigned int length)
-{
- if (length == fread(data, 1, length, (FILE *)closure)
- || feof((FILE *)closure))
- return CAIRO_STATUS_SUCCESS;
- return CAIRO_STATUS_READ_ERROR;
-}
-
static void cairogen_begin_page(GVJ_t * job)
{
cairo_t *cr;
cairo_stroke(cr);
}
-static void cairogen_freeimage(void *data)
-{
- cairo_destroy((cairo_t*)data);
-}
-
-static void
-cairogen_usershape(GVJ_t * job, usershape_t *us, boxf b, bool filled)
-{
- cairo_t *cr = (cairo_t *) job->surface; /* target context */
- cairo_surface_t *surface1 = NULL; /* source surface */
-
- if (us->data) {
- if (us->datafree == cairogen_freeimage)
- surface1 = (cairo_surface_t*)(us->data); /* use cached data */
- else {
- us->datafree(us->data); /* free incompatible cache data */
- us->data = NULL;
- }
- }
- if (!surface1) { /* read file into cache */
- fseek(us->f, 0, SEEK_SET);
- switch (us->type) {
-#ifdef CAIRO_HAS_PNG_FUNCTIONS
- case FT_PNG:
- surface1 = cairo_image_surface_create_from_png_stream(reader, us->f);
- cairo_surface_reference(surface1);
- break;
-#endif
- default:
- surface1 = NULL;
- }
- if (surface1) {
- us->data = (void*)surface1;
- us->datafree = cairogen_freeimage;
- }
- }
- if (surface1) {
- cairo_save(cr);
- cairo_translate(cr, ROUND(b.LL.x), ROUND(-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_surface (cr, surface1, 0, 0);
- cairo_paint (cr);
- cairo_restore(cr);
- }
-}
-
static gvrender_engine_t cairogen_engine = {
0, /* cairogen_begin_job */
0, /* cairogen_end_job */
cairogen_bezier,
cairogen_polyline,
0, /* cairogen_comment */
- cairogen_usershape
+ 0 /* cairogen_usershape */ /* provided by gvloadimage */
};
static gvrender_features_t cairogen_features = {
0, /* sizeof knowncolors */
RGBA_DOUBLE, /* color_type */
0, /* device */
+ "cairo", /* gvloadimage target for usershapes */
};
static gvrender_features_t cairogen_features_ps = {
0, /* sizeof knowncolors */
RGBA_DOUBLE, /* color_type */
0, /* device */
+ "cairo", /* gvloadimage target for usershapes */
};
#if 0
0, /* sizeof knowncolors */
RGBA_DOUBLE, /* color_type */
"xlib", /* device */
+ "cairo", /* gvloadimage target for usershapes */
};
static gvrender_features_t cairogen_features_gtk = {
0, /* sizeof knowncolors */
RGBA_DOUBLE, /* color_type */
"gtk", /* device */
+ "cairo", /* gvloadimage target for usershapes */
};
#endif
#endif