static void intr(int s)
{
if (G)
- dotneato_write(Gvc, G);
+ emit_jobs(Gvc, G);
dotneato_terminate(Gvc);
exit(1);
}
agclose(prev);
}
gvlayout_layout(Gvc, G);
- dotneato_write(Gvc, G);
+ emit_jobs(Gvc, G);
prev = G;
}
}
if !DISABLE_CODEGENS
CODEGENS = diagen.c figgen.c gdgen.c hpglgen.c mapgen.c mifgen.c mpgen.c \
- picgen.c psgen.c svggen.c vrmlgen.c vtxgen.c ps.txt color_names
+ picgen.c psgen.c svggen.c vrmlgen.c vtxgen.c ps.txt xdgen.c color_names
endif
return TRUE;
}
-void emit_reset(GVC_t * gvc, graph_t * g)
+static void emit_reset(GVC_t * gvc, graph_t * g)
{
Agnode_t *n;
* - called just once per output device
* (where emit_graph can be called many times for refresh callbacks)
*/
-void emit_init(GVC_t * gvc, graph_t * g)
+static void emit_init_job(GVC_t * gvc, graph_t * g)
{
init_gvc_from_graph(gvc, g);
gvrender_begin_job(gvc);
}
-void emit_deinit(GVC_t * gvc)
+static void emit_deinit_job(GVC_t * gvc)
{
gvrender_end_job(gvc);
}
gvrender_end_graph(gvc);
}
+/* support for stderr_once */
+/* #include "libgraph.h" to get agstrdup, agstrfree */
+extern char *agstrdup(char *);
+extern void agstrfree(char *);
+
+static void free_string_entry(Dict_t * dict, char *key, Dtdisc_t * disc)
+{
+ agstrfree(key);
+}
+
+static Dict_t *strings;
+static Dtdisc_t stringdict = {
+ 0, /* key - the object itself */
+ 0, /* size - null-terminated string */
+ -1, /* link - allocate separate holder objects */
+ NIL(Dtmake_f),
+ (Dtfree_f) free_string_entry,
+ NIL(Dtcompar_f),
+ NIL(Dthash_f),
+ NIL(Dtmemory_f),
+ NIL(Dtevent_f)
+};
+
+int emit_once(char *str)
+{
+ if (strings == 0)
+ strings = dtopen(&stringdict, Dtoset);
+ if (!dtsearch(strings, str)) {
+ dtinsert(strings, agstrdup(str));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void emit_once_reset()
+{
+ if (strings) {
+ dtclose(strings);
+ strings = 0;
+ }
+}
+
void emit_eof(GVC_t * gvc)
{
if (gvc->job->pageNum > 0) {
- emit_deinit(gvc);
+ emit_deinit_job(gvc);
emit_once_reset();
}
}
}
}
-/* support for stderr_once */
-/* #include "libgraph.h" to get agstrdup, agstrfree */
-extern char *agstrdup(char *);
-extern void agstrfree(char *);
-
-static void free_string_entry(Dict_t * dict, char *key, Dtdisc_t * disc)
+static void emit_job(GVC_t * gvc, graph_t * g)
{
- agstrfree(key);
-}
+ gvrender_job_t *job = gvc->job;
-static Dict_t *strings;
-static Dtdisc_t stringdict = {
- 0, /* key - the object itself */
- 0, /* size - null-terminated string */
- -1, /* link - allocate separate holder objects */
- NIL(Dtmake_f),
- (Dtfree_f) free_string_entry,
- NIL(Dtcompar_f),
- NIL(Dthash_f),
- NIL(Dtmemory_f),
- NIL(Dtevent_f)
-};
+#ifndef DISABLE_CODEGENS
+ Output_file = job->output_file;
+ Output_lang = job->output_lang;
+#endif
-int emit_once(char *str)
+ emit_init_job(gvc, g);
+
+ if (! (job->flags & GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES))
+ emit_reset(gvc, g); /* FIXME - split into emit_init & page reset */
+
+ switch (gvc->job->output_lang) {
+ case GVRENDER_PLUGIN:
+ gvemit_graph(gvc, g);
+ break;
+ case POSTSCRIPT: case PDF: case HPGL: case PCL: case MIF:
+ case PIC_format: case GIF: case PNG: case JPEG: case WBMP:
+ case GD: case memGD: case GD2: case VRML: case METAPOST:
+ case TK: case SVG: case SVGZ: case QPDF: case QEPDF: case ISMAP:
+ case IMAP: case CMAP: case CMAPX: case FIG: case VTX: case DIA:
+ emit_graph(gvc, g);
+ break;
+ case EXTENDED_DOT:
+ write_extended_dot(gvc, g, gvc->job->output_file);
+ break;
+ case ATTRIBUTED_DOT:
+ write_attributed_dot(g, gvc->job->output_file);
+ break;
+ case CANONICAL_DOT:
+ write_canonical_dot(g, gvc->job->output_file);
+ break;
+ case PLAIN:
+ write_plain(gvc, g, gvc->job->output_file);
+ break;
+ case PLAIN_EXT:
+ write_plain_ext(gvc, g, gvc->job->output_file);
+ break;
+ default:
+ if (gvc->job->output_lang >= QBM_FIRST
+ && gvc->job->output_lang < QBM_LAST)
+ emit_graph(gvc, g);
+ break;
+ }
+
+#if 0
+ if (gvc->job->output_lang != TK)
+ fflush(gvc->job->output_file);
+#endif
+#if 0
+ emit_deinit(gvc);
+#endif
+}
+
+static FILE *file_select(char *str)
{
- if (strings == 0)
- strings = dtopen(&stringdict, Dtoset);
- if (!dtsearch(strings, str)) {
- dtinsert(strings, agstrdup(str));
- return TRUE;
+ FILE *rv;
+ rv = fopen(str, "wb");
+ if (rv == NULL) {
+ perror(str);
+ exit(1);
}
- return FALSE;
+ return rv;
}
-void emit_once_reset()
+void emit_jobs (GVC_t * gvc, graph_t * g)
{
- if (strings) {
- dtclose(strings);
- strings = 0;
+ gvrender_job_t *job;
+
+ for (job = gvrender_first_job(gvc); job; job = gvrender_next_job(gvc)) {
+ if (!job->output_file) { /* if not yet opened */
+ if (job->output_filename == NULL) {
+ job->output_file = stdout;
+ } else {
+ job->output_file = file_select(job->output_filename);
+ }
+ job->output_lang = gvrender_select(gvc, job->output_langname);
+ assert(job->output_lang != NO_SUPPORT); /* should have been verified already */
+ }
+ emit_job(gvc, g);
}
}
EXTERN int State; /* last finished phase */
EXTERN double Initial_dist;
EXTERN double Damping;
+ EXTERN int y_invert; /* invert y in bounding box */
+ EXTERN int y_off; /* ymin + ymax */
+ EXTERN double yf_off; /* y_off in inches */
+ EXTERN attrsym_t *g_draw;
+ EXTERN attrsym_t *g_l_draw;
external char *BaseLineStyle[]; /* solid, width = 1 */
EXTERN attrsym_t
int Output_lang;
#endif
-int y_invert; /* invert y in bounding box */
-static int y_off; /* ymin + ymax */
-static double yf_off; /* y_off in inches */
static int e_arrows; /* graph has edges with end arrows */
static int s_arrows; /* graph has edges with start arrows */
-static Agraph_t *cluster_g;
static agxbuf outbuf;
static agxbuf charbuf;
-static attrsym_t *g_draw;
-static attrsym_t *g_l_draw;
/* macros for inverting the y coordinate with the bounding box */
#define Y(y) (y_invert ? (y_off - (y)) : (y))
fprintf(f, "stop\n");
}
-static void write_plain(GVC_t * gvc, graph_t * g, FILE * f)
+void write_plain(GVC_t * gvc, graph_t * g, FILE * f)
{
_write_plain(gvc, g, f, FALSE);
}
-static void write_plain_ext(GVC_t * gvc, graph_t * g, FILE * f)
+void write_plain_ext(GVC_t * gvc, graph_t * g, FILE * f)
{
_write_plain(gvc, g, f, TRUE);
}
return 0;
}
-static void xd_textline(point p, textline_t * line)
-{
- char buf[BUFSIZ];
- int j;
-
- agxbputc(&charbuf, 'T');
- switch (line->just) {
- case 'l':
- j = -1;
- break;
- case 'r':
- j = 1;
- break;
- default:
- case 'n':
- j = 0;
- break;
- }
- sprintf(buf, " %d %d %d %d %d -", p.x, Y(p.y), j,
- (int) line->width, (int) strlen(line->str));
- agxbput(&charbuf, buf);
- agxbput(&charbuf, line->str);
- agxbputc(&charbuf, ' ');
-}
-
-static void xd_ellipse(point p, int rx, int ry, int filled)
-{
- char buf[BUFSIZ];
-
- agxbputc(&outbuf, (filled ? 'E' : 'e'));
- sprintf(buf, " %d %d %d %d ", p.x, Y(p.y), rx, ry);
- agxbput(&outbuf, buf);
-}
-
-static void points(char c, point * A, int n)
-{
- char buf[BUFSIZ];
- int i;
- point p;
-
- agxbputc(&outbuf, c);
- sprintf(buf, " %d ", n);
- agxbput(&outbuf, buf);
- for (i = 0; i < n; i++) {
- p = A[i];
- sprintf(buf, "%d %d ", p.x, Y(p.y));
- agxbput(&outbuf, buf);
- }
-}
-
-static void xd_polygon(point * A, int n, int filled)
-{
- points((filled ? 'P' : 'p'), A, n);
-}
-
-static void
-xd_bezier(point * A, int n, int arrow_at_start, int arrow_at_end)
-{
- points('B', A, n);
-}
-
-static void xd_polyline(point * A, int n)
-{
- points('L', A, n);
-}
-
-static void xd_begin_cluster(Agraph_t * sg)
-{
- cluster_g = sg;
-}
-
-static void xd_end_cluster()
-{
- agxset(cluster_g, g_draw->index, agxbuse(&outbuf));
- if (GD_label(cluster_g))
- agxset(cluster_g, g_l_draw->index, agxbuse(&charbuf));
-}
-
/*
* John M. suggests:
* You might want to add four more:
*/
static void extend_attrs(GVC_t * gvc, graph_t *g)
{
- int i;
+ int i, j;
bezier bz = { 0, 0, 0, 0 };
+ bezierf bzf;
double scale;
node_t *n;
edge_t *e;
scale = late_double(e, E_arrowsz, 1.0, 0.0);
for (i = 0; i < ED_spl(e)->size; i++) {
bz = ED_spl(e)->list[i];
-#ifndef DISABLE_CODEGENS
-/* FIXME - why is this here? */
- xd_bezier(bz.list, bz.size, FALSE, FALSE);
-#endif
+ /* convert points to pointf for gvrender api */
+ bzf.size = bz.size;
+ bzf.list = malloc(sizeof(pointf) * bzf.size);
+ for (j = 0; j < bz.size; j++)
+ P2PF(bz.list[j], bzf.list[j]);
+ gvrender_beziercurve(gvc, bzf.list, bz.size, FALSE, FALSE);
+ free(bzf.list);
}
agxset(e, e_draw->index, agxbuse(&outbuf));
for (i = 0; i < ED_spl(e)->size; i++) {
agxbfree(&charbuf);
}
-void dotneato_write_one(GVC_t * gvc, graph_t * g)
+void write_extended_dot(GVC_t *gvc, graph_t *g, FILE *f)
{
- gvrender_job_t *job = gvc->job;
-
-#ifndef DISABLE_CODEGENS
- Output_file = job->output_file;
- Output_lang = job->output_lang;
-#endif
-
- emit_init(gvc, g);
-
- if (! (job->flags & GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES))
- emit_reset(gvc, g); /* FIXME - split into emit_init & page reset */
-
- switch (gvc->job->output_lang) {
- case GVRENDER_PLUGIN:
- gvemit_graph(gvc, g);
- break;
- case POSTSCRIPT: case PDF: case HPGL: case PCL: case MIF:
- case PIC_format: case GIF: case PNG: case JPEG: case WBMP:
- case GD: case memGD: case GD2: case VRML: case METAPOST:
- case TK: case SVG: case SVGZ: case QPDF: case QEPDF: case ISMAP:
- case IMAP: case CMAP: case CMAPX: case FIG: case VTX: case DIA:
- emit_graph(gvc, g);
- break;
- case EXTENDED_DOT:
attach_attrs(g);
extend_attrs(gvc, g);
- agwrite(g, gvc->job->output_file);
- break;
- case ATTRIBUTED_DOT:
- attach_attrs(g);
- agwrite(g, gvc->job->output_file);
- break;
- case CANONICAL_DOT:
- if (HAS_CLUST_EDGE(g))
- undoClusterEdges(g);
- agwrite(g, gvc->job->output_file);
- break;
- case PLAIN:
- write_plain(gvc, g, gvc->job->output_file);
- break;
- case PLAIN_EXT:
- write_plain_ext(gvc, g, gvc->job->output_file);
- break;
- default:
- if (gvc->job->output_lang >= QBM_FIRST
- && gvc->job->output_lang < QBM_LAST)
- emit_graph(gvc, g);
- break;
- }
-
-#if 0
- if (gvc->job->output_lang != TK)
- fflush(gvc->job->output_file);
-#endif
-#if 0
- emit_deinit(gvc);
-#endif
+ agwrite(g, f);
}
-static FILE *file_select(char *str)
+void write_attributed_dot(graph_t *g, FILE *f)
{
- FILE *rv;
- rv = fopen(str, "wb");
- if (rv == NULL) {
- perror(str);
- exit(1);
- }
- return rv;
+ attach_attrs(g);
+ agwrite(g, f);
}
-void dotneato_write(GVC_t * gvc, graph_t * g)
+void write_canonical_dot(graph_t *g, FILE *f)
{
- gvrender_job_t *job;
-
- for (job = gvrender_first_job(gvc); job; job = gvrender_next_job(gvc)) {
- if (!job->output_file) { /* if not yet opened */
- if (job->output_filename == NULL) {
- job->output_file = stdout;
- } else {
- job->output_file = file_select(job->output_filename);
- }
- job->output_lang = gvrender_select(gvc, job->output_langname);
- assert(job->output_lang != NO_SUPPORT); /* should have been verified already */
- }
- dotneato_write_one(gvc, g);
- }
+ if (HAS_CLUST_EDGE(g))
+ undoClusterEdges(g);
+ agwrite(g, f);
}
void dotneato_eof(GVC_t * gvc)
for (c = 1; c <= GD_n_cluster(g); c++)
rec_attach_bb(GD_clust(g)[c]);
}
-
-#ifndef DISABLE_CODEGENS
-
-codegen_t XDot_CodeGen = {
- 0, /* xd_reset */
- 0, /* xd_begin_job */ 0, /* xd_end_job */
- 0, /* xd_begin_graph */ 0, /* xd_end_graph */
- 0, /* xd_begin_page */ 0, /* xd_end_page */
- 0, /* xd_begin_layer */ 0, /* xd_end_layer */
- xd_begin_cluster, xd_end_cluster,
- 0, /* xd_begin_nodes */ 0, /* xd_end_nodes */
- 0, /* xd_begin_edges */ 0, /* xd_end_edges */
- 0, /* xd_begin_node */ 0, /* xd_node */
- 0, /* xd_begin_edge */ 0, /* xd_edge */
- 0, /* xd_begin_context */ 0, /* xd_context */
- 0, /* xd_begin_anchor */ 0, /* xd_anchor */
- 0, /* xd_set_font */ xd_textline,
- 0, /* xd_set_pencolor */ 0, /* xd_set_fillcolor */ 0, /* xd_set_style */
- xd_ellipse, xd_polygon,
- xd_bezier, xd_polyline,
- 0, /* xd_has_arrows */ 0, /* xd_comment */
- 0, /* xd_textsize */ 0, /* xd_user_shape */ 0 /* xd_usershapesize */
-};
-
-#endif
extern double elapsed_sec(void);
extern void enqueue(queue *, Agnode_t *);
extern void enqueue_neighbors(queue *, Agnode_t *, int);
- extern void emit_init(GVC_t * gvc, graph_t * g);
- extern void emit_deinit(GVC_t * gvc);
extern void emit_attachment(GVC_t * gvc, textlabel_t *, splines *);
extern void emit_clusters(GVC_t * gvc, Agraph_t * g, int flags);
extern void emit_eof(GVC_t * gvc);
extern void emit_graph(GVC_t * gvc, graph_t * g);
extern void emit_label(GVC_t * gvc, textlabel_t *, void *obj);
extern int emit_once(char *message);
- extern void emit_once_reset();
- extern void emit_reset(GVC_t * gvc, graph_t * g);
+ extern void emit_jobs(GVC_t * gvc, graph_t *g);
extern void endpath(path *, Agedge_t *, int, pathend_t *, boolean);
extern void epsf_init(node_t * n);
extern void epsf_free(node_t * n);
extern void use_library(char *);
extern char *username();
extern point user_shape_size(node_t * n, char *shapefile);
+ extern void write_attributed_dot(graph_t *g, FILE *f);
+ extern void write_canonical_dot(graph_t *g, FILE *f);
+ extern void write_extended_dot(GVC_t *gvc, graph_t *g, FILE *f);
+ extern void write_plain(GVC_t * gvc, graph_t * g, FILE * f);
+ extern void write_plain_ext(GVC_t * gvc, graph_t * g, FILE * f);
extern void *zmalloc(size_t);
extern void *zrealloc(void *, size_t, size_t, size_t);
extern void *gmalloc(size_t);
}
emit_label(gvc, ND_label(n), (void *) n);
-
-#if 0
- A[0].x = ROUND(ND_coord_i(n).x - ND_label(n)->dimen.x / 2);
- A[0].y = ROUND(ND_coord_i(n).y - ND_label(n)->dimen.y / 2);
- A[1].x = ROUND(ND_coord_i(n).x - ND_label(n)->dimen.x / 2);
- A[1].y = ROUND(ND_coord_i(n).y + ND_label(n)->dimen.y / 2);
- A[2].x = ROUND(ND_coord_i(n).x + ND_label(n)->dimen.x / 2);
- A[2].y = ROUND(ND_coord_i(n).y + ND_label(n)->dimen.y / 2);
- A[3].x = ROUND(ND_coord_i(n).x + ND_label(n)->dimen.x / 2);
- A[3].y = ROUND(ND_coord_i(n).y - ND_label(n)->dimen.y / 2);
- gvrender_polygon(gvc, A, 4, 0);
-#endif
}
/*=======================end poly======================================*/
--- /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 *
+**********************************************************/
+
+#include "render.h"
+#include "gvc.h"
+#include "agxbuf.h"
+
+/* macros for inverting the y coordinate with the bounding box */
+#define Y(y) (y_invert ? (y_off - (y)) : (y))
+
+static agxbuf charbuf;
+static agxbuf outbuf;
+static Agraph_t *cluster_g;
+
+static void xd_textline(point p, textline_t * line)
+{
+ char buf[BUFSIZ];
+ int j;
+
+ agxbputc(&charbuf, 'T');
+ switch (line->just) {
+ case 'l':
+ j = -1;
+ break;
+ case 'r':
+ j = 1;
+ break;
+ default:
+ case 'n':
+ j = 0;
+ break;
+ }
+ sprintf(buf, " %d %d %d %d %d -", p.x, Y(p.y), j,
+ (int) line->width, (int) strlen(line->str));
+ agxbput(&charbuf, buf);
+ agxbput(&charbuf, line->str);
+ agxbputc(&charbuf, ' ');
+}
+
+static void xd_ellipse(point p, int rx, int ry, int filled)
+{
+ char buf[BUFSIZ];
+
+ agxbputc(&outbuf, (filled ? 'E' : 'e'));
+ sprintf(buf, " %d %d %d %d ", p.x, Y(p.y), rx, ry);
+ agxbput(&outbuf, buf);
+}
+
+static void xd_points(char c, point * A, int n)
+{
+ char buf[BUFSIZ];
+ int i;
+ point p;
+
+ agxbputc(&outbuf, c);
+ sprintf(buf, " %d ", n);
+ agxbput(&outbuf, buf);
+ for (i = 0; i < n; i++) {
+ p = A[i];
+ sprintf(buf, "%d %d ", p.x, Y(p.y));
+ agxbput(&outbuf, buf);
+ }
+}
+
+static void xd_polygon(point * A, int n, int filled)
+{
+ xd_points((filled ? 'P' : 'p'), A, n);
+}
+
+static void
+xd_bezier(point * A, int n, int arrow_at_start, int arrow_at_end)
+{
+ xd_points('B', A, n);
+}
+
+static void xd_polyline(point * A, int n)
+{
+ xd_points('L', A, n);
+}
+
+static void xd_begin_cluster(Agraph_t * sg)
+{
+ cluster_g = sg;
+}
+
+static void xd_end_cluster()
+{
+ agxset(cluster_g, g_draw->index, agxbuse(&outbuf));
+ if (GD_label(cluster_g))
+ agxset(cluster_g, g_l_draw->index, agxbuse(&charbuf));
+}
+
+codegen_t XDot_CodeGen = {
+ 0, /* xd_reset */
+ 0, /* xd_begin_job */ 0, /* xd_end_job */
+ 0, /* xd_begin_graph */ 0, /* xd_end_graph */
+ 0, /* xd_begin_page */ 0, /* xd_end_page */
+ 0, /* xd_begin_layer */ 0, /* xd_end_layer */
+ xd_begin_cluster, xd_end_cluster,
+ 0, /* xd_begin_nodes */ 0, /* xd_end_nodes */
+ 0, /* xd_begin_edges */ 0, /* xd_end_edges */
+ 0, /* xd_begin_node */ 0, /* xd_node */
+ 0, /* xd_begin_edge */ 0, /* xd_edge */
+ 0, /* xd_begin_context */ 0, /* xd_context */
+ 0, /* xd_begin_anchor */ 0, /* xd_anchor */
+ 0, /* xd_set_font */ xd_textline,
+ 0, /* xd_set_pencolor */ 0, /* xd_set_fillcolor */ 0, /* xd_set_style */
+ xd_ellipse, xd_polygon,
+ xd_bezier, xd_polyline,
+ 0, /* xd_has_arrows */ 0, /* xd_comment */
+ 0, /* xd_textsize */ 0, /* xd_user_shape */ 0 /* xd_usershapesize */
+};
tcldot_layout(g, (argc > 3) ? argv[3] : (char *) NULL);
/* render graph TK canvas commands */
- dotneato_write_one(gvc, g);
+ emit_jobs(gvc, g);
gvrender_delete_jobs(gvc);
return TCL_OK;
if (!GD_drawing(g) || argc > 4)
tcldot_layout(g, (argc > 4) ? argv[4] : (char *) NULL);
- dotneato_write_one(gvc, g);
+ emit_jobs(gvc, g);
gvrender_delete_jobs(gvc);
Tcl_AppendResult(interp, argv[2], (char *) NULL);
tcldot_layout(g, (argc > 4) ? argv[4] : (char *) NULL);
}
- dotneato_write_one(gvc, g);
+ emit_jobs(gvc, g);
gvrender_delete_jobs(gvc);
return TCL_OK;