From: ellson Date: Fri, 2 Nov 2007 17:02:07 +0000 (+0000) Subject: a first cut at rendering to in-memory strings for script bindings. X-Git-Tag: LAST_LIBGRAPH~32^2~5098 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f62598ad25b0ac4cbfc6d34a31f5bfc71740e6a0;p=graphviz a first cut at rendering to in-memory strings for script bindings. --- diff --git a/lib/gvc/gvc.c b/lib/gvc/gvc.c index 84b12303a..b46d3f8bd 100644 --- a/lib/gvc/gvc.c +++ b/lib/gvc/gvc.c @@ -149,6 +149,51 @@ int gvRenderFilename(GVC_t *gvc, graph_t *g, char *format, char *filename) return 0; } +/* Render layout in a specified format to a malloc'ed string */ +int gvRenderData(GVC_t *gvc, graph_t *g, char *format, char **result) +{ + int rc; + GVJ_t *job; + + g = g->root; + + /* create a job for the required format */ + rc = gvjobs_output_langname(gvc, format); + job = gvc->job; + if (rc == NO_SUPPORT) { + agerr(AGERR, "Format: \"%s\" not recognized. Use one of:%s\n", + format, gvplugin_list(gvc, API_device, format)); + return -1; + } + + job->output_lang = gvrender_select(job, job->output_langname); + if (!GD_drawing(g) && !(job->flags & LAYOUT_NOT_REQUIRED)) { + fprintf(stderr, "Layout was not done\n"); + return -1; + } + +#define OUTPUT_DATA_INITIAL_ALLOCATION 1000 + + if(!result || !(*result = malloc(OUTPUT_DATA_INITIAL_ALLOCATION))) { + agerr(AGERR, "failure malloc'ing for result string"); + return -1; + } + + **result = '\0'; + job->output_data = *result; + job->output_data_allocated = OUTPUT_DATA_INITIAL_ALLOCATION; + job->output_data_position = 0; + + gvRenderJobs(gvc, g); + gvrender_end_job(job); + gvdevice_finalize(job); + + *result = job->output_data; + gvjobs_delete(gvc); + + return 0; +} + char **gvcInfo(GVC_t* gvc) { return gvc->common.info; } char *gvcUsername(GVC_t* gvc) { return gvc->common.user; } char *gvcVersion(GVC_t* gvc) { return gvc->common.info[1]; } diff --git a/lib/gvc/gvc.h b/lib/gvc/gvc.h index 8ce1547a4..d8103e5fe 100644 --- a/lib/gvc/gvc.h +++ b/lib/gvc/gvc.h @@ -90,6 +90,9 @@ extern int gvRender(GVC_t *gvc, graph_t *g, char *format, FILE *out); /* Render layout in a specified format to an open FILE */ extern int gvRenderFilename(GVC_t *gvc, graph_t *g, char *format, char *filename); +/* Render layout in a specified format to a malloc'ed string */ +extern int gvRenderData(GVC_t *gvc, graph_t *g, char *format, char **result); + /* Render layout according to -T and -o options found by gvParseArgs */ extern int gvRenderJobs(GVC_t *gvc, graph_t *g); diff --git a/lib/gvc/gvcjob.h b/lib/gvc/gvcjob.h index 22a7534ed..7de64ab17 100644 --- a/lib/gvc/gvcjob.h +++ b/lib/gvc/gvcjob.h @@ -237,8 +237,12 @@ extern "C" { char *layout_type; char *output_filename; - char *output_langname; FILE *output_file; + char *output_data; + unsigned int output_data_allocated; + unsigned int output_data_position; + + char *output_langname; int output_lang; gvplugin_active_render_t render; diff --git a/lib/gvc/gvdevice.c b/lib/gvc/gvdevice.c index cee176112..aef5b54aa 100644 --- a/lib/gvc/gvdevice.c +++ b/lib/gvc/gvdevice.c @@ -84,6 +84,18 @@ size_t gvdevice_write (GVJ_t * job, const unsigned char *s, unsigned int len) return gzwrite((gzFile *) (job->output_file), s, len); #endif } + else if (job->output_data) { + if (len > (job->output_data_allocated - (job->output_data_position + 1))) { + job->output_data_allocated = job->output_data_position + len + 1000; + job->output_data = realloc(job->output_data, job->output_data_allocated); + if (!job->output_data) { + fprintf(stderr, "failure realloc'ing for result string\n"); + return 0; + } + } + strcpy(job->output_data + job->output_data_position, s); + job->output_data_position += len; + } else return fwrite(s, sizeof(char), len, job->output_file); } @@ -138,48 +150,48 @@ void gvdevice_initialize(GVJ_t * job) if (gvde && gvde->initialize) { gvde->initialize(job); } - else { - /* if the device has no initialization then it uses file output */ - if (!job->output_file) { /* if not yet opened */ - if (gvc->common.auto_outfile_names) - auto_output_filename(job); - if (job->output_filename) { - job->output_file = fopen(job->output_filename, "w"); - if (job->output_file == NULL) { - perror(job->output_filename); - exit(1); - } + else if (job->output_data) { + } + /* if the device has no initialization then it uses file output */ + else if (!job->output_file) { /* if not yet opened */ + if (gvc->common.auto_outfile_names) + auto_output_filename(job); + if (job->output_filename) { + job->output_file = fopen(job->output_filename, "w"); + if (job->output_file == NULL) { + perror(job->output_filename); + exit(1); } - else - job->output_file = stdout; + } + else + job->output_file = stdout; #ifdef WITH_CODEGENS - Output_file = job->output_file; + Output_file = job->output_file; #endif #ifdef HAVE_SETMODE #ifdef O_BINARY - if (job->flags & GVDEVICE_BINARY_FORMAT) - setmode(fileno(job->output_file), O_BINARY); + if (job->flags & GVDEVICE_BINARY_FORMAT) + setmode(fileno(job->output_file), O_BINARY); #endif #endif - if (job->flags & GVDEVICE_COMPRESSED_FORMAT) { + if (job->flags & GVDEVICE_COMPRESSED_FORMAT) { #if HAVE_LIBZ - int fd; - - /* open dup so can gzclose independent of FILE close */ - fd = dup(fileno(job->output_file)); - job->output_file = (FILE *) (gzdopen(fd, "wb")); - if (!job->output_file) { - (job->common->errorfn) ("Error initializing compression on output file\n"); - exit(1); - } -#else - (job->common->errorfn) ("No libz support.\n"); + int fd; + + /* open dup so can gzclose independent of FILE close */ + fd = dup(fileno(job->output_file)); + job->output_file = (FILE *) (gzdopen(fd, "wb")); + if (!job->output_file) { + (job->common->errorfn) ("Error initializing compression on output file\n"); exit(1); -#endif } +#else + (job->common->errorfn) ("No libz support.\n"); + exit(1); +#endif } } } diff --git a/tclpkg/gv/gv.cpp b/tclpkg/gv/gv.cpp index b5042da32..2c37a6e2c 100644 --- a/tclpkg/gv/gv.cpp +++ b/tclpkg/gv/gv.cpp @@ -862,14 +862,14 @@ void render(Agraph_t *g, char *format, FILE *f) err = gvRender(gvc, g, format, f); } -// FIXME - render to a caller provided memory blob -void render(Agraph_t *g, char *format, void **data) -{ -// FIXME -// -// int err; -// -// err = gvRenderData(gvc, g, format, data); +// render to a data string +char* renderdata(Agraph_t *g, char *format) +{ + int err; + char *data; + + err = gvRenderData(gvc, g, format, &data); + return data; } void write(Agraph_t *g, FILE *f) diff --git a/tclpkg/gv/gv.i b/tclpkg/gv/gv.i index d5e76a956..9fdae98f8 100644 --- a/tclpkg/gv/gv.i +++ b/tclpkg/gv/gv.i @@ -190,7 +190,7 @@ extern void render(Agraph_t *g); extern void render(Agraph_t *g, char *format); extern void render(Agraph_t *g, char *format, char *filename); extern void render(Agraph_t *g, char *format, FILE *f); -extern void render(Agraph_t *g, char *format, void **data); +extern char* renderdata(Agraph_t *g, char *format); /*** Writing graph back to file */ void write(Agraph_t *g, FILE *f);