From 14dbd5b25492264d3c7ea015ea74fb8f9c3e60c5 Mon Sep 17 00:00:00 2001 From: ellson Date: Sat, 29 Jan 2005 14:16:48 +0000 Subject: [PATCH] some cleanup to gvc and job structs --- cmd/dot/dot.c | 35 +- lib/common/emit.c | 27 +- lib/common/output.c | 1079 ++++++++++++++++++------------------- lib/common/renderprocs.h | 3 - lib/gvc/gvc.h | 4 +- lib/gvc/gvcint.h | 12 +- lib/gvc/gvlayout.c | 8 +- lib/gvc/gvplugin_render.h | 4 +- lib/gvc/gvrender.c | 23 +- tclpkg/tcldot/tcldot.c | 19 +- 10 files changed, 593 insertions(+), 621 deletions(-) diff --git a/cmd/dot/dot.c b/cmd/dot/dot.c index b2c04c2a0..fb161bca2 100644 --- a/cmd/dot/dot.c +++ b/cmd/dot/dot.c @@ -49,14 +49,15 @@ char *Info[] = { BUILDDATE /* Build Date */ }; -static GVC_t *gvc; +static GVC_t *Gvc; +static graph_t * G; #ifndef MSWIN32 static void intr(int s) { - if (gvc->g) - dotneato_write(gvc, gvc->g); - dotneato_terminate(gvc); + if (G) + dotneato_write(Gvc, G); + dotneato_terminate(Gvc); exit(1); } @@ -135,10 +136,10 @@ static graph_t *create_test_graph(void) int main(int argc, char **argv) { - graph_t *g, *prev = NULL; + graph_t *prev = NULL; - gvc = gvNEWcontext(Info, username()); - parse_args(gvc, argc, argv); + Gvc = gvNEWcontext(Info, username()); + parse_args(Gvc, argc, argv); #ifndef MSWIN32 signal(SIGUSR1, toggle); @@ -149,27 +150,27 @@ int main(int argc, char **argv) if (MemTest) { while (1) { /* Create a test graph */ - g = create_test_graph(); + G = create_test_graph(); /* Perform layout and cleanup */ - gvlayout_layout(gvc, g); - gvlayout_cleanup(gvc, g); + gvlayout_layout(Gvc, G); + gvlayout_cleanup(Gvc, G); /* Delete graph */ - agclose(g); + agclose(G); } assert(0); /* should never exit loop */ } else { - while ((g = next_input_graph())) { + while ((G = next_input_graph())) { if (prev) { - gvlayout_cleanup(gvc, prev); + gvlayout_cleanup(Gvc, prev); agclose(prev); } - gvlayout_layout(gvc, g); - dotneato_write(gvc, g); - prev = g; + gvlayout_layout(Gvc, G); + dotneato_write(Gvc, G); + prev = G; } } - dotneato_terminate(gvc); + dotneato_terminate(Gvc); return 1; } diff --git a/lib/common/emit.c b/lib/common/emit.c index ff27fddc2..3e5f3eb59 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -328,11 +328,10 @@ void emit_reset(GVC_t * gvc, graph_t * g) gvrender_reset(gvc); } -static void emit_background(GVC_t * gvc, boxf pageBox) +static void emit_background(GVC_t * gvc, graph_t *g, boxf pageBox) { char *str; point A[4]; - graph_t *g = gvc->g; box PB; if (((str = agget(g, "bgcolor")) != 0) @@ -358,12 +357,9 @@ static void emit_defaults(GVC_t * gvc) /* even if this makes you cringe, at least it's short */ -static void setup_page(GVC_t * gvc) +static void setup_page(GVC_t * gvc, graph_t * g) { gvrender_job_t *job = gvc->job; - point offset; - int rot; - graph_t *g = gvc->g; /* establish current box in graph coordinates */ job->pageBox.LL.x = job->pagesArrayElem.x * job->pageSize.x; @@ -372,16 +368,15 @@ static void setup_page(GVC_t * gvc) job->pageBox.UR.y = job->pageBox.LL.y + job->pageSize.y; /* establish offset to be applied, in graph coordinates */ - if (GD_drawing(g)->landscape == FALSE) - offset = pointof(-job->pageBox.LL.x, -job->pageBox.LL.y); + if (job->rotation == 0) + job->offset = pointof(-job->pageBox.LL.x, -job->pageBox.LL.y); else { - offset.x = (job->pagesArrayElem.y + 1) * job->pageSize.y; - offset.y = -(job->pagesArrayElem.x) * job->pageSize.x; + job->offset.x = (job->pagesArrayElem.y + 1) * job->pageSize.y; + job->offset.y = -(job->pagesArrayElem.x) * job->pageSize.x; } - rot = GD_drawing(g)->landscape ? 90 : 0; - gvrender_begin_page(gvc, job->zoom, rot, offset); - emit_background(gvc, job->pageBox); + gvrender_begin_page(gvc, g); + emit_background(gvc, g, job->pageBox); emit_defaults(gvc); } @@ -932,11 +927,13 @@ void emit_init(GVC_t * gvc, graph_t * g) late_double(g->proto->n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE); + gvc->graphname = g->name; + init_layering(gvc, g); init_job_pagination(gvc, g); - gvrender_begin_job(gvc, Lib, X, Y, Z, x, y, GD_drawing(g)->dpi); + gvrender_begin_job(gvc, g, Lib, X, Y, Z, x, y, GD_drawing(g)->dpi); } void emit_deinit(GVC_t * gvc) @@ -1031,7 +1028,7 @@ void emit_graph(GVC_t * gvc, graph_t * g, int flags) if (gvc->numLayers > 1) gvrender_begin_layer(gvc); for (firstpage(gvc); validpage(gvc); nextpage(gvc)) { - setup_page(gvc); + setup_page(gvc, g); Obj = NONE; if (((s = agget(g, "href")) && s[0]) || ((s = agget(g, "URL")) && s[0])) { diff --git a/lib/common/output.c b/lib/common/output.c index 61e00bb0d..ac63b454f 100644 --- a/lib/common/output.c +++ b/lib/common/output.c @@ -28,14 +28,17 @@ 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; -static void extend_attrs(GVC_t * gvc); - - /* macros for inverting the y coordinate with the bounding box */ +/* macros for inverting the y coordinate with the bounding box */ #define Y(y) (y_invert ? (y_off - (y)) : (y)) #define YF(y) (y_invert ? (yf_off - (y)) : (y)) -static void graph_sets_margin(GVC_t * gvc, graph_t * g) +static void graph_settings(GVC_t * gvc, graph_t * g) { double xf, yf; char *p; @@ -52,224 +55,559 @@ static void graph_sets_margin(GVC_t * gvc, graph_t * g) gvc->graph_sets_margin = TRUE; } } -} -static void graph_sets_pageSize(GVC_t * gvc, graph_t * g) -{ + /* pagesize */ gvc->graph_sets_pageSize = FALSE; P2PF(GD_drawing(g)->page, gvc->pageSize); if ((GD_drawing(g)->page.x > 0) && (GD_drawing(g)->page.y > 0)) { gvc->graph_sets_pageSize = TRUE; } + /* bounding box */ B2BF(GD_bb(g),gvc->bb); + + /* rotation */ + gvc->rotation = GD_drawing(g)->landscape ? 90 : 0; } -/* chkOrder: - * Determine order of output. - * Output usually in breadth first graph walk order - */ -static int chkOrder(graph_t * g) +static void printptf(FILE * f, point pt) { - char *p = agget(g, "outputorder"); - if (p) { - char c = *p; - if ((c == 'n') && !strcmp(p + 1, "odesfirst")) - return EMIT_SORTED; - if ((c == 'e') && !strcmp(p + 1, "dgesfirst")) - return EMIT_EDGE_SORTED; - } - return 0; + fprintf(f, " %.3f %.3f", PS2INCH(pt.x), PS2INCH(Y(pt.y))); } -static int lang_sets_flags(gvrender_job_t * job, graph_t * g) +/* setYInvert: + * Set parameters used to flip coordinate system (y=0 at top). + * Values do not need to be unset, since if y_invert is set, it's + * set for * all graphs during current run, so each will + * reinitialize the values for its bbox. + */ +static void setYInvert(graph_t * g) { - int flags; - - switch (job->output_lang) { - case GVRENDER_PLUGIN: - flags = chkOrder(g) | job->render_features->flags; - break; - case POSTSCRIPT: - flags = chkOrder(g) | GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES; - break; - case ISMAP: case IMAP: case CMAP: case CMAPX: - /* output in breadth first graph walk order, but - * with nodes edges and nested clusters before - * clusters */ - flags = EMIT_CLUSTERS_LAST; - break; - case FIG: - /* output color definition objects first */ - flags = EMIT_COLORS; - break; - case VTX: - /* output sorted, i.e. all nodes then all edges */ - flags = EMIT_SORTED; - break; - case DIA: - /* output in preorder traversal of the graph */ - flags = EMIT_PREORDER; - break; - case EXTENDED_DOT: case ATTRIBUTED_DOT: case CANONICAL_DOT: - case PLAIN: case PLAIN_EXT: - flags = 0; - break; - default: - flags = chkOrder(g); - break; + if (y_invert) { + y_off = GD_bb(g).UR.y + GD_bb(g).LL.y; + yf_off = PS2INCH(y_off); } - return flags; } -void dotneato_write_one(GVC_t * gvc, graph_t * g) +static char *getoutputbuffer(char *str) { - gvrender_job_t *job = gvc->job; - int flags; - - gvc->g = g; -#ifndef DISABLE_CODEGENS - Output_file = job->output_file; - Output_lang = job->output_lang; -#endif - - graph_sets_margin(gvc, g); - graph_sets_pageSize(gvc, g); - flags = lang_sets_flags(job, g); - emit_init(gvc, g); - - if (! (flags & GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES)) - emit_reset(gvc, g); /* FIXME - split into emit_init & page reset */ + static char *rv; + static int len; + int req; - switch (gvc->job->output_lang) { - case GVRENDER_PLUGIN: - gvemit_graph(gvc, g, flags); - 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, flags); - break; - case EXTENDED_DOT: - attach_attrs(g); - extend_attrs(gvc); - 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, gvc->job->output_file); - break; - case PLAIN_EXT: - write_plain_ext(gvc, gvc->job->output_file); - break; - default: - if (gvc->job->output_lang >= QBM_FIRST - && gvc->job->output_lang < QBM_LAST) - emit_graph(gvc, g, flags); - break; + req = MAX(2 * strlen(str) + 2, BUFSIZ); + if (req > len) { + rv = ALLOC(req, rv, char); + len = req; } + return rv; +} -#if 0 - if (gvc->job->output_lang != TK) - fflush(gvc->job->output_file); -#endif -#if 0 - emit_deinit(gvc); -#endif +static char *canonical(char *str) +{ + return agstrcanon(str, getoutputbuffer(str)); } -static FILE *file_select(char *str) +static void writenodeandport(FILE * fp, node_t * node, char *port) { - FILE *rv; - rv = fopen(str, "wb"); - if (rv == NULL) { - perror(str); - exit(1); - } - return rv; + char *name; + if (IS_CLUST_NODE(node)) + name = strchr(node->name, ':') + 1; + else + name = node->name; + fprintf(fp, "%s", canonical(name)); /* slimey i know */ + if (port && *port) + fprintf(fp, ":%s", canonical(port)); } -void dotneato_write(GVC_t * gvc, graph_t * g) +/* FIXME - there must be a proper way to get port info - these are + * supposed to be private to libgraph - from libgraph.h */ +#define TAILX 1 +#define HEADX 2 + +/* _write_plain: + */ +static void _write_plain(GVC_t * gvc, graph_t * g, FILE * f, boolean extend) { - gvrender_job_t *job; + int i, j, splinePoints; + char *tport, *hport; + node_t *n; + edge_t *e; + bezier bz; + point pt; + char *lbl; - 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); +// setup_graph(gvc, g); + setYInvert(g); + pt = GD_bb(g).UR; + fprintf(f, "graph %.3f %.3f %.3f\n", gvc->job->zoom, PS2INCH(pt.x), PS2INCH(pt.y)); + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + if (IS_CLUST_NODE(n)) + continue; + fprintf(f, "node %s ", canonical(n->name)); + printptf(f, ND_coord_i(n)); + if (ND_label(n)->html) /* if html, get original text */ + lbl = agxget(n, N_label->index); + else + lbl = ND_label(n)->text; + if (lbl) + lbl = canonical(lbl); + else + lbl = "\"\""; + fprintf(f, " %.3f %.3f %s %s %s %s %s\n", + ND_width(n), ND_height(n), lbl, + late_nnstring(n, N_style, "solid"), + ND_shape(n)->name, + late_nnstring(n, N_color, DEFAULT_COLOR), + late_nnstring(n, N_fillcolor, DEFAULT_FILL)); + } + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + for (e = agfstout(g, n); e; e = agnxtout(g, e)) { + if (extend && e->attr) { + tport = e->attr[TAILX]; + hport = e->attr[HEADX]; + } else + tport = hport = ""; + if (ED_spl(e)) { + splinePoints = 0; + for (i = 0; i < ED_spl(e)->size; i++) { + bz = ED_spl(e)->list[i]; + splinePoints += bz.size; + } + fprintf(f, "edge "); + writenodeandport(f, e->tail, tport); + fprintf(f, " "); + writenodeandport(f, e->head, hport); + fprintf(f, " %d", splinePoints); + for (i = 0; i < ED_spl(e)->size; i++) { + bz = ED_spl(e)->list[i]; + for (j = 0; j < bz.size; j++) + printptf(f, bz.list[j]); + } } - job->output_lang = gvrender_select(gvc, job->output_langname); - assert(job->output_lang != NO_SUPPORT); /* should have been verified already */ + if (ED_label(e)) { + fprintf(f, " %s", canonical(ED_label(e)->text)); + printptf(f, ED_label(e)->p); + } + fprintf(f, " %s %s\n", late_nnstring(e, E_style, "solid"), + late_nnstring(e, E_color, DEFAULT_COLOR)); } - dotneato_write_one(gvc, g); } + fprintf(f, "stop\n"); } -void dotneato_eof(GVC_t * gvc) +static void write_plain(GVC_t * gvc, graph_t * g, FILE * f) { - gvrender_job_t *job; + _write_plain(gvc, g, f, FALSE); +} - for (job = gvrender_first_job(gvc); job; job = gvrender_next_job(gvc)) { - if (job->output_file) { - emit_eof(gvc); - fclose(job->output_file); - job->output_file = NULL; - } - } +static void write_plain_ext(GVC_t * gvc, graph_t * g, FILE * f) +{ + _write_plain(gvc, g, f, TRUE); } -static void set_record_rects(node_t * n, field_t * f, agxbuf * xb) +static attrsym_t *safe_dcl(graph_t * g, void *obj, char *name, char *def, + attrsym_t * (*fun) (Agraph_t *, char *, char *)) { - int i; - char buf[BUFSIZ]; + attrsym_t *a = agfindattr(obj, name); + if (a == NULL) + a = fun(g, name, def); + return a; +} - if (f->n_flds == 0) { - sprintf(buf, "%d,%d,%d,%d ", - f->b.LL.x + ND_coord_i(n).x, - Y(f->b.LL.y + ND_coord_i(n).y), - f->b.UR.x + ND_coord_i(n).x, - Y(f->b.UR.y + ND_coord_i(n).y)); - agxbput(xb, buf); +static int isInvis(char *style) +{ + char **styles = 0; + char **sp; + char *p; + + if (style[0]) { + styles = parse_style(style); + sp = styles; + while ((p = *sp++)) { + if (streq(p, "invis")) + return 1; + } + } + 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: + * + * _ohdraw_ (optional head-end arrow for edges) + * _ohldraw_ (optional head-end label for edges) + * _otdraw_ (optional tail-end arrow for edges) + * _otldraw_ (optional tail-end label for edges) + * + * that would be generated when an additional option is supplied to + * dot, etc. and + * these would be the arrow/label positions to use if a user want to flip the + * direction of an edge (as sometimes is there want). + */ +static void extend_attrs(GVC_t * gvc, graph_t *g) +{ + int i; + bezier bz = { 0, 0, 0, 0 }; + double scale; + node_t *n; + edge_t *e; + attrsym_t *n_draw = NULL; + attrsym_t *n_l_draw = NULL; + attrsym_t *e_draw = NULL; + attrsym_t *h_draw = NULL; + attrsym_t *t_draw = NULL; + attrsym_t *e_l_draw = NULL; + attrsym_t *hl_draw = NULL; + attrsym_t *tl_draw = NULL; + unsigned char buf[BUFSIZ]; + unsigned char cbuf[BUFSIZ]; + + if (GD_has_labels(g) & GRAPH_LABEL) + g_l_draw = safe_dcl(g, g, "_ldraw_", "", agraphattr); + if (GD_n_cluster(g)) + g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); + + n_draw = safe_dcl(g, g->proto->n, "_draw_", "", agnodeattr); + n_l_draw = safe_dcl(g, g->proto->n, "_ldraw_", "", agnodeattr); + + e_draw = safe_dcl(g, g->proto->e, "_draw_", "", agedgeattr); + if (e_arrows) + h_draw = safe_dcl(g, g->proto->e, "_hdraw_", "", agedgeattr); + if (s_arrows) + t_draw = safe_dcl(g, g->proto->e, "_tdraw_", "", agedgeattr); + if (GD_has_labels(g) & EDGE_LABEL) + e_l_draw = safe_dcl(g, g->proto->e, "_ldraw_", "", agedgeattr); + if (GD_has_labels(g) & HEAD_LABEL) + hl_draw = safe_dcl(g, g->proto->e, "_hldraw_", "", agedgeattr); + if (GD_has_labels(g) & TAIL_LABEL) + tl_draw = safe_dcl(g, g->proto->e, "_tldraw_", "", agedgeattr); + + agxbinit(&outbuf, BUFSIZ, buf); + agxbinit(&charbuf, BUFSIZ, cbuf); + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + if (ND_shape(n) && !isInvis(late_string(n, N_style, ""))) { + ND_shape(n)->fns->codefn(gvc, n); + agxset(n, n_draw->index, agxbuse(&outbuf)); + agxset(n, n_l_draw->index, agxbuse(&charbuf)); + } + if (State < GVSPLINES) + continue; + for (e = agfstout(g, n); e; e = agnxtout(g, e)) { + if (ED_edge_type(e) == IGNORED) + continue; + if (isInvis(late_string(e, E_style, ""))) + continue; + if (ED_spl(e) == NULL) + continue; + + 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 + } + agxset(e, e_draw->index, agxbuse(&outbuf)); + for (i = 0; i < ED_spl(e)->size; i++) { + if (bz.sflag) { + arrow_gen(gvc, bz.sp, bz.list[0], scale, bz.sflag); + agxset(e, t_draw->index, agxbuse(&outbuf)); + } + if (bz.eflag) { + arrow_gen(gvc, bz.ep, bz.list[bz.size - 1], scale, + bz.eflag); + agxset(e, h_draw->index, agxbuse(&outbuf)); + } + } + if (ED_label(e)) { + emit_label(gvc, ED_label(e), (void *) e); + if (mapbool(late_string(e, E_decorate, "false")) + && ED_spl(e)) { + emit_attachment(gvc, ED_label(e), ED_spl(e)); + agxbput(&charbuf, agxbuse(&outbuf)); + } + agxset(e, e_l_draw->index, agxbuse(&charbuf)); + } + if (ED_head_label(e)) { + emit_label(gvc, ED_head_label(e), (void *) e); + agxset(e, hl_draw->index, agxbuse(&charbuf)); + } + if (ED_tail_label(e)) { + emit_label(gvc, ED_tail_label(e), (void *) e); + agxset(e, tl_draw->index, agxbuse(&charbuf)); + } + } + } + if (GD_label(g)) { + emit_label(gvc, GD_label(g), (void *) g); + agxset(g, g_l_draw->index, agxbuse(&charbuf)); + } + emit_clusters(gvc, g, 0); + agxbfree(&outbuf); + agxbfree(&charbuf); +} + +/* chkOrder: + * Determine order of output. + * Output usually in breadth first graph walk order + */ +static int chkOrder(graph_t * g) +{ + char *p = agget(g, "outputorder"); + if (p) { + char c = *p; + if ((c == 'n') && !strcmp(p + 1, "odesfirst")) + return EMIT_SORTED; + if ((c == 'e') && !strcmp(p + 1, "dgesfirst")) + return EMIT_EDGE_SORTED; + } + return 0; +} + +static int lang_sets_flags(gvrender_job_t * job, graph_t * g) +{ + int flags; + + switch (job->output_lang) { + case GVRENDER_PLUGIN: + flags = chkOrder(g) | job->render_features->flags; + break; + case POSTSCRIPT: + flags = chkOrder(g) | GVRENDER_DOES_MULTIGRAPH_OUTPUT_FILES; + break; + case ISMAP: case IMAP: case CMAP: case CMAPX: + /* output in breadth first graph walk order, but + * with nodes edges and nested clusters before + * clusters */ + flags = EMIT_CLUSTERS_LAST; + break; + case FIG: + /* output color definition objects first */ + flags = EMIT_COLORS; + break; + case VTX: + /* output sorted, i.e. all nodes then all edges */ + flags = EMIT_SORTED; + break; + case DIA: + /* output in preorder traversal of the graph */ + flags = EMIT_PREORDER; + break; + case EXTENDED_DOT: case ATTRIBUTED_DOT: case CANONICAL_DOT: + case PLAIN: case PLAIN_EXT: + flags = 0; + break; + default: + flags = chkOrder(g); + break; + } + return flags; +} + +void dotneato_write_one(GVC_t * gvc, graph_t * g) +{ + gvrender_job_t *job = gvc->job; + int flags; + +#ifndef DISABLE_CODEGENS + Output_file = job->output_file; + Output_lang = job->output_lang; +#endif + + graph_settings(gvc, g); + flags = lang_sets_flags(job, g); + emit_init(gvc, g); + + if (! (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, flags); + 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, flags); + 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, flags); + break; } - for (i = 0; i < f->n_flds; i++) - set_record_rects(n, f->fld[i], xb); + +#if 0 + if (gvc->job->output_lang != TK) + fflush(gvc->job->output_file); +#endif +#if 0 + emit_deinit(gvc); +#endif } -static attrsym_t *safe_dcl(graph_t * g, void *obj, char *name, char *def, - attrsym_t * (*fun) (Agraph_t *, char *, char *)) +static FILE *file_select(char *str) { - attrsym_t *a = agfindattr(obj, name); - if (a == NULL) - a = fun(g, name, def); - return a; + FILE *rv; + rv = fopen(str, "wb"); + if (rv == NULL) { + perror(str); + exit(1); + } + return rv; } -/* setYInvert: - * Set parameters used to flip coordinate system (y=0 at top). - * Values do not need to be unset, since if y_invert is set, it's - * set for * all graphs during current run, so each will - * reinitialize the values for its bbox. - */ -static void setYInvert(graph_t * g) +void dotneato_write(GVC_t * gvc, graph_t * g) { - if (y_invert) { - y_off = GD_bb(g).UR.y + GD_bb(g).LL.y; - yf_off = PS2INCH(y_off); + 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); } } +void dotneato_eof(GVC_t * gvc) +{ + gvrender_job_t *job; + + for (job = gvrender_first_job(gvc); job; job = gvrender_next_job(gvc)) { + if (job->output_file) { + emit_eof(gvc); + fclose(job->output_file); + job->output_file = NULL; + } + } +} + +static void set_record_rects(node_t * n, field_t * f, agxbuf * xb) +{ + int i; + char buf[BUFSIZ]; + + if (f->n_flds == 0) { + sprintf(buf, "%d,%d,%d,%d ", + f->b.LL.x + ND_coord_i(n).x, + Y(f->b.LL.y + ND_coord_i(n).y), + f->b.UR.x + ND_coord_i(n).x, + Y(f->b.UR.y + ND_coord_i(n).y)); + agxbput(xb, buf); + } + for (i = 0; i < f->n_flds; i++) + set_record_rects(n, f->fld[i], xb); +} + void attach_attrs(graph_t * g) { int i, j, sides; @@ -387,252 +725,43 @@ void attach_attrs(graph_t * g) } if (ED_head_label(e)) { pt = ED_head_label(e)->p; - sprintf(buf, "%d,%d", pt.x, Y(pt.y)); - agset(e, "head_lp", buf); - } - if (ED_tail_label(e)) { - pt = ED_tail_label(e)->p; - sprintf(buf, "%d,%d", pt.x, Y(pt.y)); - agset(e, "tail_lp", buf); - } - } - } - } - rec_attach_bb(g); - agxbfree(&xb); - - if (HAS_CLUST_EDGE(g)) - undoClusterEdges(g); -} - -void rec_attach_bb(graph_t * g) -{ - int c; - char buf[32]; - point pt; - - sprintf(buf, "%d,%d,%d,%d", GD_bb(g).LL.x, Y(GD_bb(g).LL.y), - GD_bb(g).UR.x, Y(GD_bb(g).UR.y)); - agset(g, "bb", buf); - if (GD_label(g) && GD_label(g)->text[0]) { - pt = GD_label(g)->p; - sprintf(buf, "%d,%d", pt.x, Y(pt.y)); - agset(g, "lp", buf); - } - for (c = 1; c <= GD_n_cluster(g); c++) - rec_attach_bb(GD_clust(g)[c]); -} - -static char *getoutputbuffer(char *str) -{ - static char *rv; - static int len; - int req; - - req = MAX(2 * strlen(str) + 2, BUFSIZ); - if (req > len) { - rv = ALLOC(req, rv, char); - len = req; - } - return rv; -} - - -static char *canonical(char *str) -{ - return agstrcanon(str, getoutputbuffer(str)); -} - -static void writenodeandport(FILE * fp, node_t * node, char *port) -{ - char *name; - if (IS_CLUST_NODE(node)) - name = strchr(node->name, ':') + 1; - else - name = node->name; - fprintf(fp, "%s", canonical(name)); /* slimey i know */ - if (port && *port) - fprintf(fp, ":%s", canonical(port)); -} - -/* FIXME - there must be a proper way to get port info - these are - * supposed to be private to libgraph - from libgraph.h */ -#define TAILX 1 -#define HEADX 2 - -/* _write_plain: - */ -void _write_plain(GVC_t * gvc, FILE * f, boolean extend) -{ - int i, j, splinePoints; - char *tport, *hport; - node_t *n; - edge_t *e; - bezier bz; - point pt; - graph_t *g = gvc->g; - char *lbl; - -// setup_graph(gvc, g); - setYInvert(g); - pt = GD_bb(g).UR; - fprintf(f, "graph %.3f %.3f %.3f\n", gvc->job->zoom, PS2INCH(pt.x), PS2INCH(pt.y)); - for (n = agfstnode(g); n; n = agnxtnode(g, n)) { - if (IS_CLUST_NODE(n)) - continue; - fprintf(f, "node %s ", canonical(n->name)); - printptf(f, ND_coord_i(n)); - if (ND_label(n)->html) /* if html, get original text */ - lbl = agxget(n, N_label->index); - else - lbl = ND_label(n)->text; - if (lbl) - lbl = canonical(lbl); - else - lbl = "\"\""; - fprintf(f, " %.3f %.3f %s %s %s %s %s\n", - ND_width(n), ND_height(n), lbl, - late_nnstring(n, N_style, "solid"), - ND_shape(n)->name, - late_nnstring(n, N_color, DEFAULT_COLOR), - late_nnstring(n, N_fillcolor, DEFAULT_FILL)); - } - for (n = agfstnode(g); n; n = agnxtnode(g, n)) { - for (e = agfstout(g, n); e; e = agnxtout(g, e)) { - if (extend && e->attr) { - tport = e->attr[TAILX]; - hport = e->attr[HEADX]; - } else - tport = hport = ""; - if (ED_spl(e)) { - splinePoints = 0; - for (i = 0; i < ED_spl(e)->size; i++) { - bz = ED_spl(e)->list[i]; - splinePoints += bz.size; - } - fprintf(f, "edge "); - writenodeandport(f, e->tail, tport); - fprintf(f, " "); - writenodeandport(f, e->head, hport); - fprintf(f, " %d", splinePoints); - for (i = 0; i < ED_spl(e)->size; i++) { - bz = ED_spl(e)->list[i]; - for (j = 0; j < bz.size; j++) - printptf(f, bz.list[j]); + sprintf(buf, "%d,%d", pt.x, Y(pt.y)); + agset(e, "head_lp", buf); + } + if (ED_tail_label(e)) { + pt = ED_tail_label(e)->p; + sprintf(buf, "%d,%d", pt.x, Y(pt.y)); + agset(e, "tail_lp", buf); } } - if (ED_label(e)) { - fprintf(f, " %s", canonical(ED_label(e)->text)); - printptf(f, ED_label(e)->p); - } - fprintf(f, " %s %s\n", late_nnstring(e, E_style, "solid"), - late_nnstring(e, E_color, DEFAULT_COLOR)); } } - fprintf(f, "stop\n"); -} - -void write_plain(GVC_t * gvc, FILE * f) -{ - _write_plain(gvc, f, FALSE); -} - -void write_plain_ext(GVC_t * gvc, FILE * f) -{ - _write_plain(gvc, f, TRUE); -} - -void printptf(FILE * f, point pt) -{ - fprintf(f, " %.3f %.3f", PS2INCH(pt.x), PS2INCH(Y(pt.y))); -} - -static agxbuf outbuf; -static agxbuf charbuf; -static attrsym_t *g_draw; -static attrsym_t *g_l_draw; - -#ifndef DISABLE_CODEGENS - -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]; + rec_attach_bb(g); + agxbfree(&xb); - agxbputc(&outbuf, (filled ? 'E' : 'e')); - sprintf(buf, " %d %d %d %d ", p.x, Y(p.y), rx, ry); - agxbput(&outbuf, buf); + if (HAS_CLUST_EDGE(g)) + undoClusterEdges(g); } -static void points(char c, point * A, int n) +void rec_attach_bb(graph_t * g) { - char buf[BUFSIZ]; - int i; - point p; + int c; + char buf[32]; + point pt; - 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); + sprintf(buf, "%d,%d,%d,%d", GD_bb(g).LL.x, Y(GD_bb(g).LL.y), + GD_bb(g).UR.x, Y(GD_bb(g).UR.y)); + agset(g, "bb", buf); + if (GD_label(g) && GD_label(g)->text[0]) { + pt = GD_label(g)->p; + sprintf(buf, "%d,%d", pt.x, Y(pt.y)); + agset(g, "lp", buf); } + for (c = 1; c <= GD_n_cluster(g); c++) + rec_attach_bb(GD_clust(g)[c]); } -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 Agraph_t *cluster_g; - -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)); -} +#ifndef DISABLE_CODEGENS codegen_t XDot_CodeGen = { 0, /* xd_reset */ @@ -656,139 +785,3 @@ codegen_t XDot_CodeGen = { }; #endif - -static int isInvis(char *style) -{ - char **styles = 0; - char **sp; - char *p; - - if (style[0]) { - styles = parse_style(style); - sp = styles; - while ((p = *sp++)) { - if (streq(p, "invis")) - return 1; - } - } - return 0; -} - -/* - * John M. suggests: - * You might want to add four more: - * - * _ohdraw_ (optional head-end arrow for edges) - * _ohldraw_ (optional head-end label for edges) - * _otdraw_ (optional tail-end arrow for edges) - * _otldraw_ (optional tail-end label for edges) - * - * that would be generated when an additional option is supplied to - * dot, etc. and - * these would be the arrow/label positions to use if a user want to flip the - * direction of an edge (as sometimes is there want). - */ -static void extend_attrs(GVC_t * gvc) -{ - int i; - bezier bz = { 0, 0, 0, 0 }; - double scale; - node_t *n; - edge_t *e; - attrsym_t *n_draw = NULL; - attrsym_t *n_l_draw = NULL; - attrsym_t *e_draw = NULL; - attrsym_t *h_draw = NULL; - attrsym_t *t_draw = NULL; - attrsym_t *e_l_draw = NULL; - attrsym_t *hl_draw = NULL; - attrsym_t *tl_draw = NULL; - unsigned char buf[BUFSIZ]; - unsigned char cbuf[BUFSIZ]; - graph_t *g = gvc->g; - - if (GD_has_labels(g) & GRAPH_LABEL) - g_l_draw = safe_dcl(g, g, "_ldraw_", "", agraphattr); - if (GD_n_cluster(g)) - g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); - - n_draw = safe_dcl(g, g->proto->n, "_draw_", "", agnodeattr); - n_l_draw = safe_dcl(g, g->proto->n, "_ldraw_", "", agnodeattr); - - e_draw = safe_dcl(g, g->proto->e, "_draw_", "", agedgeattr); - if (e_arrows) - h_draw = safe_dcl(g, g->proto->e, "_hdraw_", "", agedgeattr); - if (s_arrows) - t_draw = safe_dcl(g, g->proto->e, "_tdraw_", "", agedgeattr); - if (GD_has_labels(g) & EDGE_LABEL) - e_l_draw = safe_dcl(g, g->proto->e, "_ldraw_", "", agedgeattr); - if (GD_has_labels(g) & HEAD_LABEL) - hl_draw = safe_dcl(g, g->proto->e, "_hldraw_", "", agedgeattr); - if (GD_has_labels(g) & TAIL_LABEL) - tl_draw = safe_dcl(g, g->proto->e, "_tldraw_", "", agedgeattr); - - agxbinit(&outbuf, BUFSIZ, buf); - agxbinit(&charbuf, BUFSIZ, cbuf); - for (n = agfstnode(g); n; n = agnxtnode(g, n)) { - if (ND_shape(n) && !isInvis(late_string(n, N_style, ""))) { - ND_shape(n)->fns->codefn(gvc, n); - agxset(n, n_draw->index, agxbuse(&outbuf)); - agxset(n, n_l_draw->index, agxbuse(&charbuf)); - } - if (State < GVSPLINES) - continue; - for (e = agfstout(g, n); e; e = agnxtout(g, e)) { - if (ED_edge_type(e) == IGNORED) - continue; - if (isInvis(late_string(e, E_style, ""))) - continue; - if (ED_spl(e) == NULL) - continue; - - 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 - } - agxset(e, e_draw->index, agxbuse(&outbuf)); - for (i = 0; i < ED_spl(e)->size; i++) { - if (bz.sflag) { - arrow_gen(gvc, bz.sp, bz.list[0], scale, bz.sflag); - agxset(e, t_draw->index, agxbuse(&outbuf)); - } - if (bz.eflag) { - arrow_gen(gvc, bz.ep, bz.list[bz.size - 1], scale, - bz.eflag); - agxset(e, h_draw->index, agxbuse(&outbuf)); - } - } - if (ED_label(e)) { - emit_label(gvc, ED_label(e), (void *) e); - if (mapbool(late_string(e, E_decorate, "false")) - && ED_spl(e)) { - emit_attachment(gvc, ED_label(e), ED_spl(e)); - agxbput(&charbuf, agxbuse(&outbuf)); - } - agxset(e, e_l_draw->index, agxbuse(&charbuf)); - } - if (ED_head_label(e)) { - emit_label(gvc, ED_head_label(e), (void *) e); - agxset(e, hl_draw->index, agxbuse(&charbuf)); - } - if (ED_tail_label(e)) { - emit_label(gvc, ED_tail_label(e), (void *) e); - agxset(e, tl_draw->index, agxbuse(&charbuf)); - } - } - } - if (GD_label(g)) { - emit_label(gvc, GD_label(g), (void *) g); - agxset(g, g_l_draw->index, agxbuse(&charbuf)); - } - emit_clusters(gvc, g, 0); - agxbfree(&outbuf); - agxbfree(&charbuf); -} diff --git a/lib/common/renderprocs.h b/lib/common/renderprocs.h index a6677e682..9bec74e92 100644 --- a/lib/common/renderprocs.h +++ b/lib/common/renderprocs.h @@ -147,7 +147,6 @@ extern "C" { extern void place_graph_label(Agraph_t *); extern void place_portlabel(edge_t * e, boolean head_p); extern point pointof(int, int); - extern void printptf(FILE *, point); extern int processClusterEdges(graph_t * g); extern char *ps_string(char *s); extern void rank(graph_t * g, int balance, int maxiter); @@ -175,8 +174,6 @@ extern "C" { extern void use_library(char *); extern char *username(); extern point user_shape_size(node_t * n, char *shapefile); - extern void write_plain(GVC_t * gvc, FILE *); - extern void write_plain_ext(GVC_t * gvc, FILE *); extern void *zmalloc(size_t); extern void *zrealloc(void *, size_t, size_t, size_t); extern void *gmalloc(size_t); diff --git a/lib/gvc/gvc.h b/lib/gvc/gvc.h index 1f2186310..bff5671e7 100644 --- a/lib/gvc/gvc.h +++ b/lib/gvc/gvc.h @@ -75,12 +75,12 @@ extern "C" { extern int gvrender_select(GVC_t * gvc, char *lang); extern int gvrender_features(GVC_t * gvc); extern void gvrender_reset(GVC_t * gvc); - extern void gvrender_begin_job(GVC_t * gvc, char **lib, double X, double Y, double Z, + extern void gvrender_begin_job(GVC_t * gvc, graph_t *g, char **lib, double X, double Y, double Z, double x, double y, int dpi); extern void gvrender_end_job(GVC_t * gvc); extern void gvrender_begin_graph(GVC_t * gvc, graph_t * g); extern void gvrender_end_graph(GVC_t * gvc); - extern void gvrender_begin_page(GVC_t * gvc, double scale, int rot, point offset); + extern void gvrender_begin_page(GVC_t * gvc, graph_t * g); extern void gvrender_end_page(GVC_t * gvc); extern void gvrender_begin_layer(GVC_t * gvc); extern void gvrender_end_layer(GVC_t * gvc); diff --git a/lib/gvc/gvcint.h b/lib/gvc/gvcint.h index 069c85036..86669227c 100644 --- a/lib/gvc/gvcint.h +++ b/lib/gvc/gvcint.h @@ -87,6 +87,7 @@ extern "C" { int flags; /* emit_graph flags */ pointf margin; /* job-specific margin */ + int rotation; /* job-specific page rotation */ boxf pageBox; /* drawable region in device coords */ /* basically width*height - margins */ @@ -99,18 +100,17 @@ extern "C" { point pagesArrayElem; /* 2D coord of current page - 0,0 based */ int numPages; /* number of pages */ int pageNum; /* current page - 1 based */ + point offset; /* offset for current page */ unsigned int width; /* width in pixels */ unsigned int height; /* height in pixels */ int dpi; /* resolution pixels-per-inch */ - int rot; /* rotation */ double zoom; /* viewport zoom factor */ pointf focus; /* viewport focus in graph units */ #if 0 pointf pointer; /* pointer position in graph units */ #endif boxf clip; /* clip region in graph units */ - point offset; pointf compscale; /* composite device scale incl: scale, zoom, dpi, y_goes_down */ boolean fit_mode, needs_refresh, click, active, has_grown; @@ -157,6 +157,7 @@ extern "C" { char *layout_type; /* string name of layout type */ gvlayout_engine_t *layout_engine; /* current layout engine */ int layout_id; /* internal id of current layout */ + char *graphname; /* name from graph */ char **lib; @@ -165,7 +166,8 @@ extern "C" { pointf pageSize; /* pageSize in graph units, not including margins */ point pb; /* page size - including margins (inches) */ boxf bb; /* graph bb in graph units, not including margins */ - boolean graph_sets_margin, graph_sets_pageSize; + int rotation; /* rotation - 0 = portrait, 90 = landscape */ + boolean graph_sets_margin, graph_sets_pageSize, graph_sets_rotation; /* layers */ char *layerDelims; /* delimiters in layer names */ @@ -174,10 +176,6 @@ extern "C" { int numLayers; /* number of layers */ int layerNum; /* current layer - 1 based*/ - /* gvrender_begin_graph() */ - graph_t *g; - - gvstyle_t styles[MAXNEST]; /* style stack - reused by each job */ int SP; diff --git a/lib/gvc/gvlayout.c b/lib/gvc/gvlayout.c index 9e72b633e..3139d02d7 100644 --- a/lib/gvc/gvlayout.c +++ b/lib/gvc/gvlayout.c @@ -52,18 +52,14 @@ void gvlayout_layout(GVC_t * gvc, graph_t * g) { gvlayout_engine_t *gvle = gvc->layout_engine; - if (gvle && gvle->layout) { - gvc->g = g; + if (gvle && gvle->layout) gvle->layout(g); - } } void gvlayout_cleanup(GVC_t * gvc, graph_t * g) { gvlayout_engine_t *gvle = gvc->layout_engine; - if (gvle && gvle->cleanup) { + if (gvle && gvle->cleanup) gvle->cleanup(g); - gvc->g = NULL; - } } diff --git a/lib/gvc/gvplugin_render.h b/lib/gvc/gvplugin_render.h index 41ae11506..490e51ea1 100644 --- a/lib/gvc/gvplugin_render.h +++ b/lib/gvc/gvplugin_render.h @@ -29,11 +29,11 @@ extern "C" { void (*end_job) (gvrender_job_t * job); void (*begin_graph) (gvrender_job_t * job, char *graphname); void (*end_graph) (gvrender_job_t * job); - void (*begin_page) (gvrender_job_t * job, char *pagename, point pagesArrayElem, int pageNum, int numPages); - void (*end_page) (gvrender_job_t * job, point pagesArrayElem, int pageNum, int numPages); void (*begin_layer) (gvrender_job_t * job, char *layername, int layerNum, int numLayers); void (*end_layer) (gvrender_job_t * job); + void (*begin_page) (gvrender_job_t * job); + void (*end_page) (gvrender_job_t * job); void (*begin_cluster) (gvrender_job_t * job, char *clustername, long id); void (*end_cluster) (gvrender_job_t * job); void (*begin_nodes) (gvrender_job_t * job); diff --git a/lib/gvc/gvrender.c b/lib/gvc/gvrender.c index 14cc01905..fa1b2a9f1 100644 --- a/lib/gvc/gvrender.c +++ b/lib/gvc/gvrender.c @@ -121,7 +121,7 @@ void gvrender_reset(GVC_t * gvc) #endif } -void gvrender_begin_job(GVC_t * gvc, char **lib, double X, double Y, double Z, double x, double y, int dpi) +void gvrender_begin_job(GVC_t * gvc, graph_t *g, char **lib, double X, double Y, double Z, double x, double y, int dpi) { gvrender_job_t *job = gvc->job; gvrender_engine_t *gvre = job->render_engine; @@ -142,6 +142,7 @@ void gvrender_begin_job(GVC_t * gvc, char **lib, double X, double Y, double Z, d job->zoom = Z; /* scaling factor */ job->focus.x = x; /* graph coord of focus - points */ job->focus.y = y; + job->rotation = gvc->rotation; if (gvre) { if (gvre->begin_job) gvre->begin_job(job); @@ -151,7 +152,7 @@ void gvrender_begin_job(GVC_t * gvc, char **lib, double X, double Y, double Z, d codegen_t *cg = job->codegen; if (cg && cg->begin_job && job->pageNum <= 1) - cg->begin_job(gvc->job->output_file, gvc->g, lib, gvc->user, + cg->begin_job(gvc->job->output_file, g, lib, gvc->user, gvc->info, job->pagesArraySize); } #endif @@ -185,7 +186,7 @@ static pointf gvrender_ptf(GVC_t * gvc, pointf p) gvrender_job_t *job = gvc->job; pointf rv; - if (job->rot == 0) { + if (job->rotation == 0) { rv.x = (p.x - job->focus.x) * job->compscale.x + job->width / 2.; rv.y = (p.y - job->focus.y) * job->compscale.y + job->height / 2.; } else { @@ -200,7 +201,7 @@ static pointf gvrender_pt(GVC_t * gvc, point p) gvrender_job_t *job = gvc->job; pointf rv; - if (job->rot == 0) { + if (job->rotation == 0) { rv.x = ((double) p.x - job->focus.x) * job->compscale.x + job->width / 2.; rv.y = ((double) p.y - job->focus.y) * job->compscale.y + job->height / 2.; } else { @@ -237,8 +238,6 @@ void gvrender_begin_graph(GVC_t * gvc, graph_t * g) char *str; double sx, sy; - gvc->g = g; - if (gvre) { job->compscale.x = job->zoom * job->dpi / POINTS_PER_INCH; job->compscale.y = job->compscale.x * @@ -253,7 +252,7 @@ void gvrender_begin_graph(GVC_t * gvc, graph_t * g) /* render specific init */ if (gvre->begin_graph) - gvre->begin_graph(job, g->name); + gvre->begin_graph(job, gvc->graphname); /* background color */ if (((str = agget(g, "bgcolor")) != 0) && str[0]) { @@ -305,22 +304,20 @@ void gvrender_end_graph(GVC_t * gvc) #endif } -void gvrender_begin_page(GVC_t * gvc, double scale, int rot, point offset) +void gvrender_begin_page(GVC_t * gvc, graph_t * g) { gvrender_job_t *job = gvc->job; gvrender_engine_t *gvre = job->render_engine; - job->rot = rot; if (gvre && gvre->begin_page) - gvre->begin_page(job, gvc->g->name, - job->pagesArrayElem, job->pageNum, job->numPages); + gvre->begin_page(job); #ifndef DISABLE_CODEGENS else { codegen_t *cg = job->codegen; if (cg && cg->begin_page) - cg->begin_page(gvc->g, job->pagesArrayElem, job->zoom, rot, offset); + cg->begin_page(g, job->pagesArrayElem, job->zoom, job->rotation, job->offset); } #endif } @@ -331,7 +328,7 @@ void gvrender_end_page(GVC_t * gvc) gvrender_engine_t *gvre = job->render_engine; if (gvre && gvre->end_page) - gvre->end_page(job, job->pagesArrayElem, job->pageNum, job->numPages); + gvre->end_page(job); #ifndef DISABLE_CODEGENS else { codegen_t *cg = job->codegen; diff --git a/tclpkg/tcldot/tcldot.c b/tclpkg/tcldot/tcldot.c index b18dfb51f..4dca31e70 100644 --- a/tclpkg/tcldot/tcldot.c +++ b/tclpkg/tcldot/tcldot.c @@ -1112,7 +1112,7 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp, gvc->job->output_file = (FILE *) & tkgendata; /* make sure that layout is done */ - gvc->g = g = g->root; + g = g->root; if (!GD_drawing(g) || argc > 3) tcldot_layout(g, (argc > 3) ? argv[3] : (char *) NULL); @@ -1139,7 +1139,7 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp, } /* make sure that layout is done */ - gvc->g = g = g->root; + g = g->root; if (!GD_drawing(g) || argc > 4) tcldot_layout(g, (argc > 4) ? argv[4] : (char *) NULL); @@ -1364,9 +1364,6 @@ static int dotnew(ClientData clientData, Tcl_Interp * interp, *gp = g; g->handle = id; - /* link graph to context */ - gvc->g = g; - #ifndef TCLOBJ Tcl_CreateCommand(interp, interp->result, graphcmd, (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL); @@ -1387,9 +1384,9 @@ static int dotnew(ClientData clientData, Tcl_Interp * interp, * it to create the handles and tcl commands for each * graph, subgraph, node, and edge. */ -static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc) +static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc, graph_t * g) { - Agraph_t **gp, *sg, **sgp, *g = gvc->g; + Agraph_t **gp, *sg, **sgp; Agnode_t *n, **np; Agedge_t *e, **ep; char buf[16]; @@ -1595,10 +1592,7 @@ static int dotread(ClientData clientData, Tcl_Interp * interp, * so we make sure that it is initialized to "not done" */ GD_drawing(g) = NULL; - /* link graph to context */ - gvc->g = g; - - return (tcldot_fixup(interp, gvc)); + return (tcldot_fixup(interp, gvc, g)); } static int dotstring(ClientData clientData, Tcl_Interp * interp, @@ -1637,9 +1631,8 @@ static int dotstring(ClientData clientData, Tcl_Interp * interp, /* link graph to context */ gvc = (GVC_t *) clientData; - gvc->g = g; - return (tcldot_fixup(interp, gvc)); + return (tcldot_fixup(interp, gvc, g)); } #if defined(_BLD_tcldot) && defined(_DLL) -- 2.40.0