/* load a plugin of type=str
- where str can optionally contain a ":packagename" modifier */
+ the str can optionally contain one or more ":dependencies"
+
+ examples:
+ png
+ png:cairo
+ fully qualified:
+ png:cairo:cairo
+ png:cairo:gd
+ png:gd:gd
+
+*/
gvplugin_available_t *gvplugin_load(GVC_t * gvc, api_t api, char *str)
{
gvplugin_available_t **pnext, *rv;
gvplugin_library_t *library;
gvplugin_api_t *apis;
gvplugin_installed_t *types;
- char *s, *p;
+#define TYPBUFSIZ 64
+ char reqtyp[TYPBUFSIZ], typ[TYPBUFSIZ];
+ char *reqdep, *dep = NULL, *reqpkg;
int i;
-
+ api_t apidep;
/* check for valid apis[] index */
if (api < 0)
return NULL;
- /* does str have a :packagename modifier? */
- s = strdup(str);
- p = strchr(s, ':');
- if (p)
- *p++ = '\0';
+ if (api == API_device) /* api dependencies - FIXME - find better way to code these *s */
- /* point to the beginning of the linked list of plugins for this api */
- pnext = &(gvc->apis[api]);
+ apidep = API_render;
+ else
+ apidep = api;
- while (*pnext) {
- if (strcmp(s, (*pnext)->typestr) == 0) {
- if (p) {
- if (strcmp(p, (*pnext)->packagename) == 0)
- break;
- }
- else
- break;
- }
- pnext = &((*pnext)->next);
+ strncpy(reqtyp, str, TYPBUFSIZ-1);
+ reqdep = strchr(reqtyp, ':');
+ if (reqdep) {
+ *reqdep++ = '\0';
+ reqpkg = strchr(reqdep, ':');
+ if (reqpkg)
+ *reqpkg++ = '\0';
+ }
+ else
+ reqpkg = NULL;
+
+ /* iterate the linked list of plugins for this api */
+ for (pnext = &(gvc->apis[api]); *pnext; pnext = &((*pnext)->next)) {
+ strncpy(typ, (*pnext)->typestr, TYPBUFSIZ-1);
+ dep = strchr(typ, ':');
+ if (dep)
+ *dep++ = '\0';
+ if (! typ || ! reqtyp || strcmp(typ, reqtyp))
+ continue; /* types empty or mismatched */
+ if (dep && reqdep && strcmp(dep, reqdep))
+ continue; /* dependencies not empty, but mismatched */
+ if (! reqpkg)
+ break; /* found with no packagename constraints */
+ if (strcmp(reqpkg, (*pnext)->packagename) == 0)
+ break; /* found with required matching packagname */
}
rv = *pnext;
- if ((*pnext) && (*pnext)->typeptr == NULL) {
- rv = NULL;
- library = gvplugin_library_load(gvc, (*pnext)->path);
+ if (rv && rv->typeptr == NULL) {
+ library = gvplugin_library_load(gvc, rv->path);
if (library) {
/* Now activate the library with real type ptrs */
apis->api,
types[i].type,
library->packagename,
- (*pnext)->path,
+ rv->path,
&types[i]);
}
}
-
- /* Now search again for the specific plugin type */
- pnext = &(gvc->apis[api]);
- while (*pnext) {
- if (strcmp(s, (*pnext)->typestr) == 0) {
- if (p) {
- if (strcmp(p, (*pnext)->packagename) == 0)
- break;
- }
- else
- break;
- }
- pnext = &((*pnext)->next);
- }
- rv = *pnext;
+ if (gvc->common.verbose >= 1)
+ fprintf(stderr, "Activated plugin library: %s\n",
+ rv->path ? rv->path : "<builtin>");
}
}
- free(s);
- /* one last check for succesfull load */
- if ((*pnext) && (*pnext)->typeptr == NULL)
+ if (dep && (apidep != api)) /* load dependency if needed */
+ if (! (gvplugin_load(gvc, apidep, dep)))
+ rv = NULL;
+
+ /* one last check for successfull load */
+ if (rv && rv->typeptr == NULL)
rv = NULL;
- gvc->api[api] = rv;
if (rv && gvc->common.verbose >= 1)
- fprintf(stderr, "Using plugin: %s %s %s\n",
+ fprintf(stderr, "Using %s: %s:%s\n",
api_names[api],
rv->typestr,
- rv->path ? rv->path : "<builtin>" );
+ rv->packagename
+ );
+ gvc->api[api] = rv;
return rv;
}
/* assemble a string list of available plugins */
const char *gvplugin_list(GVC_t * gvc, api_t api, char *str)
{
- gvplugin_available_t **pnext, **plugin, **pprev;
+ gvplugin_available_t **pnext, **plugin;
const char *buf = NULL;
- char *s, *p, *typestr_last;
+ char *s, *p, *q, *typestr_last;
boolean new = TRUE;
/* check for valid apis[] index */
if (p) { /* if str contains a ':', and if we find a match for the type,
then just list the alternative paths for the plugin */
- pnext = plugin;
- pprev = NULL;
- while (*pnext) {
- /* list only the matching type, and only once*/
- if (strcasecmp(s, (*pnext)->typestr) == 0
- && !(pprev
- && strcasecmp(s, (*pprev)->typestr) == 0
- && strcasecmp((*pprev)->packagename, (*pnext)->packagename) == 0)) {
+ for (pnext = plugin; *pnext; pnext = &((*pnext)->next)) {
+ q = strdup((*pnext)->typestr);
+ if ((p = strchr(q, ':')))
+ *p++ = '\0';
+ /* list only the matching type */
+ if (strcasecmp(s, q) == 0) {
/* list each member of the matching type as "type:path" */
append_buf(' ', (*pnext)->typestr, new);
buf = append_buf(':', (*pnext)->packagename, FALSE);
new = FALSE;
}
- pprev = pnext;
- pnext = &((*pnext)->next);
+ free(q);
}
}
+ free(s);
if (new) { /* if the type was not found, or if str without ':',
then just list available types */
- pnext = plugin;
typestr_last = NULL;
- while (*pnext) {
+ for (pnext = plugin; *pnext; pnext = &((*pnext)->next)) {
/* list only one instance of type */
- if (!typestr_last
- || strcasecmp(typestr_last, (*pnext)->typestr) != 0) {
+ q = strdup((*pnext)->typestr);
+ if ((p = strchr(q, ':')))
+ *p++ = '\0';
+ if (!typestr_last || strcasecmp(typestr_last, q) != 0) {
/* list it as "type" i.e. w/o ":path" */
- buf = append_buf(' ', (*pnext)->typestr, new);
+ buf = append_buf(' ', q, new);
new = FALSE;
}
- typestr_last = (*pnext)->typestr;
- pnext = &((*pnext)->next);
+ if(!typestr_last)
+ free(typestr_last);
+ typestr_last = q;
}
+ if(!typestr_last)
+ free(typestr_last);
}
- free(s);
if (!buf)
buf = "";
return buf;
* 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) ELEM(loadimage) ELEM(formatter)
+#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.
struct gvdevice_engine_s {
void (*initialize) (GVJ_t * firstjob);
+ void (*format) (GVJ_t * firstjob, unsigned int width, unsigned int height, unsigned char *data);
void (*finalize) (GVJ_t * firstjob);
};
GVC_t *gvc = job->gvc;
gvplugin_available_t *plugin;
gvplugin_installed_t *typeptr;
- char *device, *formatter, *p, buf[40];
#ifdef WITH_CODEGENS
codegen_info_t *cg_info;
#endif
- plugin = gvplugin_load(gvc, API_render, str);
+ gvplugin_load(gvc, API_device, str);
+
+ plugin = gvc->api[API_device];
if (plugin) {
#ifdef WITH_CODEGENS
if (strcmp(plugin->packagename, "cg") == 0) {
cg_info = (codegen_info_t *) (plugin->typeptr);
job->codegen = cg_info->cg;
job->render.engine = NULL;
- job->device.engine = NULL;
return cg_info->id;
- } else {
+ }
#endif
- typeptr = plugin->typeptr;
- job->render.engine = (gvrender_engine_t *) (typeptr->engine);
- job->render.features = (gvrender_features_t *) (typeptr->features);
- job->render.id = typeptr->id;
-
- formatter = job->render.features->formatter;
- if (formatter) {
- strcpy(buf, formatter);
- strcat(buf, "2");
- strcat(buf, str);
- if ((p=strchr(buf, ':')))
- *p = '\0';
- formatter = buf;
- plugin = gvplugin_load(gvc, API_formatter, formatter);
- if (! plugin) {
- job->formatter.engine = NULL;
- return NO_SUPPORT; /* FIXME - should differentiate no device from no renderer */
- }
- typeptr = plugin->typeptr;
- job->formatter.engine = (gvformatter_engine_t *) (typeptr->engine);
- job->formatter.features = (gvformatter_features_t *) (typeptr->features);
- job->formatter.id = typeptr->id;
- }
- else {
- job->formatter.engine = NULL;
- }
-
- device = job->render.features->device;
- if (device) {
- plugin = gvplugin_load(gvc, API_device, device);
- if (! plugin) {
- job->device.engine = NULL;
- return NO_SUPPORT; /* FIXME - should differentiate no device from no renderer */
- }
- typeptr = plugin->typeptr;
- job->device.engine = (gvdevice_engine_t *) (typeptr->engine);
- job->device.features = (gvdevice_features_t *) (typeptr->features);
- job->device.id = typeptr->id;
- }
- else {
- job->device.engine = NULL;
- }
+ typeptr = plugin->typeptr;
+ job->device.engine = (gvdevice_engine_t *) (typeptr->engine);
+ job->device.features = (gvdevice_features_t *) (typeptr->features);
+ job->device.id = typeptr->id;
+ }
+ else
+ return NO_SUPPORT; /* FIXME - should differentiate problem */
+
+ plugin = gvc->api[API_render];
+ if (plugin) {
+ typeptr = plugin->typeptr;
+ job->render.engine = (gvrender_engine_t *) (typeptr->engine);
- return GVRENDER_PLUGIN;
-#ifdef WITH_CODEGENS
+ if (job->device.engine) {
+ job->render.features = (gvrender_features_t *) (typeptr->features);
+ job->render.id = typeptr->id;
}
-#endif
+ else {
+ /* a null device engine indicates that the renderer provides
+ the id and features */
+ job->render.features = (gvrender_features_t *) (job->device.features);
+ job->render.id = job->device.id;
+ }
+ return GVRENDER_PLUGIN;
}
- return NO_SUPPORT;
+ job->render.engine = NULL;
+ return NO_SUPPORT; /* FIXME - should differentiate problem */
}
int gvrender_features(GVJ_t * job)
#include "gvplugin.h"
+extern gvplugin_installed_t gvdevice_core_dot_types;
+extern gvplugin_installed_t gvdevice_core_ps_types;
+extern gvplugin_installed_t gvdevice_core_fig_types;
+extern gvplugin_installed_t gvdevice_core_svg_types;
+extern gvplugin_installed_t gvdevice_core_vml_types;
+extern gvplugin_installed_t gvdevice_core_map_types;
extern gvplugin_installed_t gvrender_core_dot_types;
extern gvplugin_installed_t gvrender_core_ps_types;
extern gvplugin_installed_t gvrender_core_fig_types;
extern gvplugin_installed_t gvloadimage_core_types;
static gvplugin_api_t apis[] = {
+ {API_device, &gvdevice_core_dot_types},
+ {API_device, &gvdevice_core_ps_types},
+ {API_device, &gvdevice_core_fig_types},
+ {API_device, &gvdevice_core_svg_types},
+ {API_device, &gvdevice_core_vml_types},
+ {API_device, &gvdevice_core_map_types},
{API_render, &gvrender_core_dot_types},
{API_render, &gvrender_core_ps_types},
{API_render, &gvrender_core_fig_types},
#define GNEW(t) (t*)malloc(sizeof(t))
-typedef enum { FORMAT_DOT, FORMAT_CANON, FORMAT_PLAIN, FORMAT_PLAIN_EXT, FORMAT_XDOT } format_type;
+typedef enum {
+ FORMAT_DOT,
+ FORMAT_CANON,
+ FORMAT_PLAIN,
+ FORMAT_PLAIN_EXT,
+ FORMAT_XDOT
+} format_type;
+
#define XDOTVERSION "1.2"
NULL, /* knowncolors */
0, /* sizeof knowncolors */
COLOR_STRING, /* color_type */
- NULL, /* device */
NULL, /* imageloader for usershapes */
- NULL, /* formatter */
};
gvrender_features_t dot_features = {
NULL, /* knowncolors */
0, /* sizeof knowncolors */
COLOR_STRING, /* color_type */
- NULL, /* device */
NULL, /* imageloader for usershapes */
- NULL, /* formatter */
};
gvrender_features_t xdot_features = {
NULL, /* knowncolors */
0, /* sizeof knowncolors */
COLOR_STRING, /* color_type */
- NULL, /* device */
"xdot", /* imageloader for usershapes */
- NULL, /* formatter */
};
gvplugin_installed_t gvrender_core_dot_types[] = {
- {FORMAT_DOT, "dot", 1, &dot_engine, &dot_features},
- {FORMAT_CANON, "canon", 1, &dot_engine, &canon_features},
- {FORMAT_PLAIN, "plain", 1, &dot_engine, &dot_features},
- {FORMAT_PLAIN_EXT, "plain-ext", 1, &dot_engine, &dot_features},
- {FORMAT_XDOT, "xdot", 1, &xdot_engine, &xdot_features},
+ {FORMAT_DOT, "core_dot", 1, &dot_engine, NULL},
+ {FORMAT_XDOT, "core_xdot", 1, &xdot_engine, NULL},
+ {0, NULL, 0, NULL, NULL}
+};
+
+gvplugin_installed_t gvdevice_core_dot_types[] = {
+ {FORMAT_DOT, "dot:core_dot", 1, NULL, &dot_features},
+ {FORMAT_CANON, "canon:core_dot", 1, NULL, &canon_features},
+ {FORMAT_PLAIN, "plain:core_dot", 1, NULL, &dot_features},
+ {FORMAT_PLAIN_EXT, "plain-ext:core_dot", 1, NULL, &dot_features},
+ {FORMAT_XDOT, "xdot:core_xdot", 1, NULL, &xdot_features},
{0, NULL, 0, NULL, NULL}
};
fig_knowncolors, /* knowncolors */
sizeof(fig_knowncolors) / sizeof(char *), /* sizeof knowncolors */
RGBA_BYTE, /* color_type */
- NULL, /* device */
"fig", /* imageloader for usershapes */
- NULL, /* formatter */
};
gvplugin_installed_t gvrender_core_fig_types[] = {
- {FORMAT_FIG, "fig", 1, &fig_engine, &fig_features},
+ {FORMAT_FIG, "core_fig", 1, &fig_engine, NULL},
+ {0, NULL, 0, NULL, NULL}
+};
+
+gvplugin_installed_t gvdevice_core_fig_types[] = {
+ {FORMAT_FIG, "fig:core_fig", 1, NULL, &fig_features},
{0, NULL, 0, NULL, NULL}
};
NULL, /* knowncolors */
0, /* sizeof knowncolors */
0, /* color_type */
- NULL, /* device */
NULL, /* imageloader for usershapes */
- NULL, /* formatter */
};
static gvrender_features_t map_features_nopoly = {
NULL, /* knowncolors */
0, /* sizeof knowncolors */
0, /* color_type */
- NULL, /* device */
NULL, /* imageloader target for usershapes */
- NULL, /* formatter */
};
gvplugin_installed_t gvrender_core_map_types[] = {
- {FORMAT_ISMAP, "ismap", 1, &map_engine, &map_features_nopoly},
- {FORMAT_CMAP, "cmap", 1, &map_engine, &map_features},
- {FORMAT_IMAP, "imap", 1, &map_engine, &map_features},
- {FORMAT_CMAPX, "cmapx", 1, &map_engine, &map_features},
- {FORMAT_IMAP, "imap_np", 1, &map_engine, &map_features_nopoly},
- {FORMAT_CMAPX, "cmapx_np", 1, &map_engine, &map_features_nopoly},
+ {FORMAT_ISMAP, "core_map", 1, &map_engine, NULL},
+ {0, NULL, 0, NULL, NULL}
+};
+
+gvplugin_installed_t gvdevice_core_map_types[] = {
+ {FORMAT_ISMAP, "ismap:core_map", 1, NULL, &map_features_nopoly},
+ {FORMAT_CMAP, "cmap:core_map", 1, NULL, &map_features},
+ {FORMAT_IMAP, "imap:core_map", 1, NULL, &map_features},
+ {FORMAT_CMAPX, "cmapx:core_map", 1, NULL, &map_features},
+ {FORMAT_IMAP, "imap_np:core_map", 1, NULL, &map_features_nopoly},
+ {FORMAT_CMAPX, "cmapx_np:core_map", 1, NULL, &map_features_nopoly},
{0, NULL, 0, NULL, NULL}
};
NULL, /* knowncolors */
0, /* sizeof knowncolors */
HSVA_DOUBLE, /* color_type */
- NULL, /* device */
"ps", /* imageloader for usershapes */
- NULL, /* formatter */
};
gvplugin_installed_t gvrender_core_ps_types[] = {
- {FORMAT_PS, "ps", 1, &psgen_engine, &psgen_features},
- {FORMAT_PS2, "ps2", 1, &psgen_engine, &psgen_features},
+ {FORMAT_PS, "core_ps", 1, &psgen_engine, NULL},
+ {0, NULL, 0, NULL, NULL}
+};
+
+gvplugin_installed_t gvdevice_core_ps_types[] = {
+ {FORMAT_PS, "ps:core_ps", 1, NULL, &psgen_features},
+ {FORMAT_PS2, "ps2:core_ps", 1, NULL, &psgen_features},
{0, NULL, 0, NULL, NULL}
};
svg_knowncolors, /* knowncolors */
sizeof(svg_knowncolors) / sizeof(char *), /* sizeof knowncolors */
RGBA_BYTE, /* color_type */
- NULL, /* device */
"svg", /* imageloader for usershapes */
- NULL, /* formatter */
};
gvplugin_installed_t gvrender_core_svg_types[] = {
- {FORMAT_SVG, "svg", 1, &svg_engine, &svg_features},
+ {FORMAT_SVG, "core_svg", 1, &svg_engine, NULL},
+ {0, NULL, 0, NULL, NULL}
+};
+
+gvplugin_installed_t gvdevice_core_svg_types[] = {
+ {FORMAT_SVG, "svg:core_svg", 1, NULL, &svg_features},
#if HAVE_LIBZ
- {FORMAT_SVGZ, "svgz", 1, &svg_engine, &svg_features},
+ {FORMAT_SVGZ, "svgz:core_svg", 1, NULL, &svg_features},
#endif
{0, NULL, 0, NULL, NULL}
};
vml_knowncolors, /* knowncolors */
sizeof(vml_knowncolors) / sizeof(char *), /* sizeof knowncolors */
RGBA_BYTE, /* color_type */
- NULL, /* device */
"vml", /* imageloader for usershapes */
- NULL, /* formatter */
};
gvplugin_installed_t gvrender_core_vml_types[] = {
- {FORMAT_VML, "vml", 1, &vml_engine, &vml_features},
+ {FORMAT_VML, "core_vml", 1, &vml_engine, NULL},
+ {0, NULL, 0, NULL, NULL}
+};
+
+gvplugin_installed_t gvdevice_core_vml_types[] = {
+ {FORMAT_VML, "vml:core_vml", 1, NULL, &vml_features},
#if HAVE_LIBZ
- {FORMAT_VMLZ, "vmlz", 1, &vml_engine, &vml_features},
+ {FORMAT_VMLZ, "vmlz:core_vml", 1, NULL, &vml_features},
#endif
{0, NULL, 0, NULL, NULL}
};
libgvplugin_devil_C_la_SOURCES = \
gvplugin_devil.c \
- gvformatter_devil.c
+ gvdevice_devil.c
libgvplugin_devil_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined
libgvplugin_devil_la_SOURCES = $(libgvplugin_devil_C_la_SOURCES)
--- /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
+
+#ifdef WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif
+#include "gvplugin_device.h"
+#include <IL/il.h>
+#include <IL/ilu.h>
+
+static void
+Y_inv ( unsigned int width, unsigned int height, unsigned char *data)
+{
+ unsigned int x, y, rowsize, i;
+ unsigned char tmp, *data2;
+
+#define STRIDE 4
+
+ rowsize = width * STRIDE;
+ data2 = data + (height-1) * rowsize;
+ for (y = 0; y < height/2; y++) {
+ for (x = 0; x < width; x++) {
+ for (i = 0; i < STRIDE; i++) {
+ tmp = *data;
+ *data++ = *data2;
+ *data2++ = tmp;
+ }
+ }
+ data2 -= 2*rowsize;
+ }
+}
+
+static void devil_format(GVJ_t * job, unsigned int width, unsigned int height, unsigned char *data)
+{
+ ILuint ImgId;
+ ILenum Error;
+ ILboolean rc;
+
+#ifdef HAVE_SETMODE
+#ifdef O_BINARY
+ /*
+ * Windows will do \n -> \r\n translations on stdout
+ * unless told otherwise.
+ */
+ setmode(fileno(job->output_file), O_BINARY);
+#endif
+#endif
+
+ // Check if the shared lib's version matches the executable's version.
+ if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION ||
+ iluGetInteger(ILU_VERSION_NUM) < ILU_VERSION) {
+ fprintf(stderr, "DevIL version is different...exiting!\n");
+ }
+
+ // Initialize DevIL.
+ ilInit();
+
+ // Generate the main image name to use.
+ ilGenImages(1, &ImgId);
+
+ // Bind this image name.
+ ilBindImage(ImgId);
+
+ Y_inv ( width, height, data );
+
+ rc = ilTexImage( width, height,
+ 1, // Depth
+ 4, // Bpp
+ IL_BGRA, // Format
+ IL_UNSIGNED_BYTE,// Type
+ data);
+
+#if 1
+ ilSaveF(job->device.id, job->output_file);
+#endif
+
+#if 0
+ ilEnable(IL_FILE_OVERWRITE);
+ ilSaveImage("test-devil.bmp");
+#endif
+
+ // We're done with the image, so let's delete it.
+ ilDeleteImages(1, &ImgId);
+
+ // Simple Error detection loop that displays the Error to the user in a human-readable form.
+ while ((Error = ilGetError())) {
+ fprintf(stderr, "Error: %s\n", iluErrorString(Error));
+ }
+}
+
+static gvdevice_engine_t devil_engine = {
+ NULL,
+ devil_format,
+ NULL,
+};
+
+static gvdevice_features_t devil_features = {
+ 0, /* flags */
+};
+
+gvplugin_installed_t gvdevice_devil_types[] = {
+ {IL_BMP, "bmp:cairo", -1, &devil_engine, &devil_features},
+// {IL_GIF, "gif:cairo", -1, &devil_engine, &devil_features},
+ {IL_JPG, "jpg:cairo", -1, &devil_engine, &devil_features},
+ {IL_JPG, "jpe:cairo", -1, &devil_engine, &devil_features},
+ {IL_JPG, "jpeg:cairo", -1, &devil_engine, &devil_features},
+ {IL_PNG, "png:cairo", -1, &devil_engine, &devil_features},
+ {IL_TIF, "tif:cairo", -1, &devil_engine, &devil_features},
+ {IL_TIF, "tiff:cairo", -1, &devil_engine, &devil_features},
+ {IL_TGA, "tga:cairo", -1, &devil_engine, &devil_features},
+ {0, NULL, 0, NULL, NULL}
+};