From: ellson Date: Fri, 4 Aug 2006 02:47:16 +0000 (+0000) Subject: Convert -Tdot, -Txdot, -Tcanon, -Tplain, -Tplain-ext to a plugin X-Git-Tag: LAST_LIBGRAPH~32^2~6008 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d3760b95bd696ab130c26dd36927ed498f7aae37;p=graphviz Convert -Tdot, -Txdot, -Tcanon, -Tplain, -Tplain-ext to a plugin lib/common/xdgen.c becomes plugin/core/gvrender_core_dot.c Put common code in core plugins into: plugin/core/gvrender_core.c --- diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am index c46bbeee5..f0d41eb51 100644 --- a/lib/common/Makefile.am +++ b/lib/common/Makefile.am @@ -17,7 +17,7 @@ noinst_HEADERS = render.h utils.h memory.h \ noinst_LTLIBRARIES = libcommon_C.la if WITH_CODEGENS -CODEGENS = $(GD_CODEGENS) diagen.c hpglgen.c mifgen.c mpgen.c picgen.c vtxgen.c xdgen.c +CODEGENS = $(GD_CODEGENS) diagen.c hpglgen.c mifgen.c mpgen.c picgen.c vtxgen.c endif diff --git a/lib/common/Makefile.old b/lib/common/Makefile.old index 8b2a99be0..7e0439bba 100644 --- a/lib/common/Makefile.old +++ b/lib/common/Makefile.old @@ -24,8 +24,7 @@ NOINST_HDRS = render.h utils.h memory.h \ NOINST_GENERATED_HDRS = colortbl.h ps.h htmltable.h htmlparse.h htmllex.h GD_CODEGENS = -CODEGENS = $(GD_CODEGENS) diagen.o figgen.o hpglgen.o mifgen.o \ - mpgen.o picgen.o vtxgen.o xdgen.o +CODEGENS = $(GD_CODEGENS) diagen.o hpglgen.o mifgen.o mpgen.o picgen.o vtxgen.o OBJS = arrows.o colxlate.o fontmetrics.o \ args.o memory.o globals.o htmllex.o htmlparse.o htmltable.o input.o \ diff --git a/lib/common/arrows.c b/lib/common/arrows.c index 8d3a00a6f..04c89a70a 100644 --- a/lib/common/arrows.c +++ b/lib/common/arrows.c @@ -512,14 +512,15 @@ boxf arrow_bb(pointf p, pointf u, double scale, int flag) return bb; } -void arrow_newgen(GVJ_t * job, int state, pointf p, pointf u, double scale, int flag) +void arrow_newgen(GVJ_t * job, emit_state_t emit_state, pointf p, pointf u, double scale, int flag) { + obj_state_t *obj = job->obj; double s; int f; - int oldstate; + emit_state_t old_emit_state; - oldstate = job->gvc->emit_state; - job->gvc->emit_state = state; + old_emit_state = obj->emit_state; + obj->emit_state = emit_state; /* Dotted and dashed styles on the arrowhead are ugly (dds) */ /* linewidth needs to be reset */ @@ -547,15 +548,15 @@ void arrow_newgen(GVJ_t * job, int state, pointf p, pointf u, double scale, int gvrender_end_context(job); - job->gvc->emit_state = oldstate; + obj->emit_state = old_emit_state; } /* FIXME emit.c and output.c require wrapper for int point coords */ -void arrow_gen(GVJ_t * job, int state, point p, point u, double scale, int flag) +void arrow_gen(GVJ_t * job, emit_state_t emit_state, point p, point u, double scale, int flag) { pointf P, U; P2PF(p, P); P2PF(u, U); - arrow_newgen(job, state, P, U, scale, flag); + arrow_newgen(job, emit_state, P, U, scale, flag); } diff --git a/lib/common/const.h b/lib/common/const.h index 347c014bc..c0cb40b10 100644 --- a/lib/common/const.h +++ b/lib/common/const.h @@ -130,22 +130,16 @@ #define CLST 3 /* output languages */ -#define ATTRIBUTED_DOT 0 /* default */ #define HPGL 2 /* HP Graphics Language */ #define PCL 3 /* Printer Control Language */ #define MIF 4 /* Adobe FrameMaker */ #define PIC_format 5 /* symbol PIC is used by compilers for Position Independent Code */ -#define PLAIN 6 -#define PLAIN_EXT 7 - #define TK 15 /* TK canvas */ #define VTX 21 /* visual thought */ #define METAPOST 22 #define DIA 24 /* dia drawing tool */ -#define CANONICAL_DOT 27 /* wanted for tcl/tk version */ -#define EXTENDED_DOT 29 /* dot with drawing info */ #define QPDF 30 /* Quartz paged PDF */ #define QEPDF 31 /* Quartz embedded PDF */ @@ -205,26 +199,6 @@ #define RANKDIR_BT 2 #define RANKDIR_RL 3 -/* value specifying emit state */ -#define EMIT_DRAW 0 -#define EMIT_GDRAW EMIT_DRAW -#define EMIT_CDRAW EMIT_DRAW -#define EMIT_NDRAW EMIT_DRAW -#define EMIT_EDRAW EMIT_DRAW - -/* values specifying emit state for arrowheads */ -#define EMIT_TDRAW 1 -#define EMIT_HDRAW 2 - -/* values specifying emit state for labels */ -#define EMIT_LABEL 3 -#define EMIT_GLABEL EMIT_LABEL -#define EMIT_CLABEL EMIT_LABEL -#define EMIT_NLABEL EMIT_LABEL -#define EMIT_ELABEL EMIT_LABEL -#define EMIT_TLABEL 4 -#define EMIT_HLABEL 5 - /* allowed charsets */ #define CHAR_UTF8 0 #define CHAR_LATIN1 1 diff --git a/lib/common/emit.c b/lib/common/emit.c index 04c26e14b..c02659b5a 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -496,10 +496,6 @@ static void init_job_flags(GVJ_t * job, graph_t * g) /* output in preorder traversal of the graph */ job->flags = EMIT_PREORDER; break; - case EXTENDED_DOT: case ATTRIBUTED_DOT: case CANONICAL_DOT: - case PLAIN: case PLAIN_EXT: - job->flags = 0; - break; default: job->flags = chkOrder(g); break; @@ -622,8 +618,14 @@ static void init_job_pagination(GVJ_t * job, graph_t *g) } /* initial window size */ - job->width = (imageSize.x + 2*margin.x) * job->dpi.x / POINTS_PER_INCH; - job->height = (imageSize.y + 2*margin.y) * job->dpi.x / POINTS_PER_INCH; + if (job->rotation) { + job->width = (imageSize.y + 2*margin.y) * job->dpi.x / POINTS_PER_INCH; + job->height = (imageSize.x + 2*margin.x) * job->dpi.x / POINTS_PER_INCH; + } + else { + job->width = (imageSize.x + 2*margin.x) * job->dpi.x / POINTS_PER_INCH; + job->height = (imageSize.y + 2*margin.y) * job->dpi.x / POINTS_PER_INCH; + } /* determine page box including centering */ if (GD_drawing(g)->centered) { @@ -958,9 +960,7 @@ static void emit_begin_node(GVJ_t * job, node_t * n) obj = push_obj_state(job); obj->type = NODE_OBJTYPE; obj->u.n = n; - - obj->oldstate = job->gvc->emit_state; - job->gvc->emit_state = EMIT_NDRAW; + obj->emit_state = EMIT_NDRAW; if (flags & GVRENDER_DOES_Z) { obj->z = late_double(n, N_z, 0.0, -MAXFLOAT); @@ -1119,7 +1119,6 @@ static void emit_end_node(GVJ_t * job) #ifdef WITH_CODEGENS Obj = NONE; #endif - job->gvc->emit_state = job->obj->oldstate; pop_obj_state(job); } @@ -1484,14 +1483,14 @@ void emit_edge_graphics(GVJ_t * job, edge_t * e) } } if (ED_label(e)) { - emit_label(job, EMIT_ELABEL, ED_label(e), (void *) e); + emit_label(job, EMIT_ELABEL, ED_label(e)); if (mapbool(late_string(e, E_decorate, "false")) && ED_spl(e)) emit_attachment(job, ED_label(e), ED_spl(e)); } if (ED_head_label(e)) - emit_label(job, EMIT_HLABEL, ED_head_label(e), (void *) e); /* vladimir */ + emit_label(job, EMIT_HLABEL, ED_head_label(e)); /* vladimir */ if (ED_tail_label(e)) - emit_label(job, EMIT_TLABEL, ED_tail_label(e), (void *) e); /* vladimir */ + emit_label(job, EMIT_TLABEL, ED_tail_label(e)); /* vladimir */ if (saved) gvrender_end_context(job); @@ -1526,9 +1525,7 @@ static void emit_begin_edge(GVJ_t * job, edge_t * e) obj = push_obj_state(job); obj->type = EDGE_OBJTYPE; obj->u.e = e; - - obj->oldstate = job->gvc->emit_state; - job->gvc->emit_state = EMIT_EDRAW; + obj->emit_state = EMIT_EDRAW; if (flags & GVRENDER_DOES_Z) { obj->tail_z= late_double(e->tail, N_z, 0.0, -1000.0); @@ -1711,7 +1708,6 @@ static void emit_end_edge(GVJ_t * job) #ifdef WITH_CODEGENS Obj = NONE; #endif - job->gvc->emit_state = job->obj->oldstate; pop_obj_state(job); } @@ -1815,13 +1811,9 @@ static void init_job_margin(GVJ_t *job) case GVRENDER_PLUGIN: job->margin.x = job->margin.y = job->render.features->default_margin; break; - case HPGL: case PCL: case MIF: case METAPOST: case VTX: case ATTRIBUTED_DOT: - case PLAIN: case PLAIN_EXT: case QPDF: + case HPGL: case PCL: case MIF: case METAPOST: case VTX: case QPDF: job->margin.x = job->margin.y = DEFAULT_PRINT_MARGIN; break; - case CANONICAL_DOT: - job->margin.x = job->margin.y = 0; - break; default: job->margin.x = job->margin.y = DEFAULT_EMBED_MARGIN; break; @@ -1994,7 +1986,7 @@ void emit_view(GVJ_t * job, graph_t * g, int flags) gvc->common.viewNum++; if (GD_label(g)) - emit_label(job, EMIT_GLABEL, GD_label(g), (void *) g); + emit_label(job, EMIT_GLABEL, GD_label(g)); /* when drawing, lay clusters down before nodes and edges */ if (!(flags & EMIT_CLUSTERS_LAST)) emit_clusters(job, g, flags); @@ -2062,9 +2054,7 @@ static void emit_begin_graph(GVJ_t * job, graph_t * g) obj = push_obj_state(job); obj->type = ROOTGRAPH_OBJTYPE; obj->u.g = g; - - obj->oldstate = job->gvc->emit_state; - job->gvc->emit_state = EMIT_GDRAW; + obj->emit_state = EMIT_GDRAW; if ((flags & GVRENDER_DOES_LABELS) && ((lab = GD_label(g)))) { if (lab->html) @@ -2101,7 +2091,6 @@ static void emit_end_graph(GVJ_t * job, graph_t * g) #ifdef WITH_CODEGENS Obj = NONE; #endif - job->gvc->emit_state = job->obj->oldstate; pop_obj_state(job); } @@ -2229,9 +2218,7 @@ static void emit_begin_cluster(GVJ_t * job, Agraph_t * sg) obj = push_obj_state(job); obj->type = CLUSTER_OBJTYPE; obj->u.sg = sg; - - obj->oldstate = job->gvc->emit_state; - job->gvc->emit_state = EMIT_CDRAW; + obj->emit_state = EMIT_CDRAW; if ((flags & GVRENDER_DOES_LABELS) && ((lab = GD_label(sg)))) { if (lab->html) @@ -2289,7 +2276,6 @@ static void emit_end_cluster(GVJ_t * job, Agraph_t * g) #ifdef WITH_CODEGENS Obj = NONE; #endif - job->gvc->emit_state = job->obj->oldstate; pop_obj_state(job); } @@ -2382,7 +2368,7 @@ void emit_clusters(GVJ_t * job, Agraph_t * g, int flags) } } if (GD_label(sg)) - emit_label(job, EMIT_GLABEL, GD_label(sg), (void *) sg); + emit_label(job, EMIT_GLABEL, GD_label(sg)); if (flags & EMIT_PREORDER) { for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) { @@ -2547,27 +2533,8 @@ static void emit_job(GVJ_t * job, graph_t * g) gvrender_begin_job(job); - switch (job->output_lang) { - case EXTENDED_DOT: - write_extended_dot(job, g, job->output_file); - break; - case ATTRIBUTED_DOT: - write_attributed_dot(g, job->output_file); - break; - case CANONICAL_DOT: - write_canonical_dot(g, job->output_file); - break; - case PLAIN: - write_plain(job, g, job->output_file); - break; - case PLAIN_EXT: - write_plain_ext(job, g, job->output_file); - break; - default: - if (! (job->flags & GVRENDER_X11_EVENTS)) - emit_graph(job, g); - break; - } + if (! (job->flags & GVRENDER_X11_EVENTS)) + emit_graph(job, g); /* Flush is necessary because we may be writing to a pipe. */ if (! job->external_surface && job->output_lang != TK) diff --git a/lib/common/htmltable.c b/lib/common/htmltable.c index aa62a0f53..3a0db576a 100644 --- a/lib/common/htmltable.c +++ b/lib/common/htmltable.c @@ -99,48 +99,6 @@ static void popFontInfo(htmlenv_t * env, htmlfont_t * savp) env->finfo.size = savp->size; } -#ifdef OLD -static void -emit_html_txt(GVJ_t * job, htmltxt_t * tp, htmlenv_t * env, void *obj) -{ - double halfwidth_x; - pointf p; - char *fname; - char *fcolor; - double fsize; - - /* make sure that there is something to do */ - if (tp->nparas < 1) - return; - - /* set font attributes */ - if (tp->font) { - if (tp->font->size > 0.0) - fsize = tp->font->size; - else - fsize = env->finfo.size; - if (tp->font->name) - fname = tp->font->name; - else - fname = env->finfo.name; - if (tp->font->color) - fcolor = tp->font->color; - else - fcolor = env->finfo.color; - } else { - fsize = env->finfo.size; - fname = env->finfo.name; - fcolor = env->finfo.color; - } - halfwidth_x = ((double)(tp->box.UR.x - tp->box.LL.x))/2.0; - p.x = env->p.x + ((double)(tp->box.UR.x + tp->box.LL.x))/2.0; - p.y = env->p.y + ((double)(tp->box.UR.y + tp->box.LL.y))/2.0; - - emit_textparas(job, tp->nparas, tp->para, p, - halfwidth_x, fname, fsize, fcolor); -} -#endif - static void emit_htextparas(GVJ_t* job, int nparas, htextpara_t* paras, pointf p, double halfwidth_x, char* fname, double fsize, char* fcolor, box b) @@ -224,7 +182,7 @@ emit_htextparas(GVJ_t* job, int nparas, htextpara_t* paras, pointf p, } static void -emit_html_txt(GVJ_t* job, htmltxt_t* tp, htmlenv_t* env, void* obj) +emit_html_txt(GVJ_t* job, htmltxt_t* tp, htmlenv_t* env) { double halfwidth_x; pointf p; @@ -311,7 +269,7 @@ static void doFill(GVJ_t * job, char *color, box B) gvrender_box(job, BF, 1); } -static void doAnchorStart(GVJ_t * job, htmldata_t * data, void *obj) +static void doAnchorStart(GVJ_t * job, htmldata_t * data) { gvrender_begin_anchor(job, data->href, data->title, data->target); } @@ -322,11 +280,10 @@ static void doAnchorEnd(GVJ_t * job) } /* forward declaration */ -static void emit_html_cell(GVJ_t * job, htmlcell_t * cp, - htmlenv_t * env, void *obj); +static void emit_html_cell(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env); static void -emit_html_tbl(GVJ_t * job, htmltbl_t * tbl, htmlenv_t * env, void *obj) +emit_html_tbl(GVJ_t * job, htmltbl_t * tbl, htmlenv_t * env) { box pts = tbl->data.box; point p = env->p; @@ -344,13 +301,13 @@ emit_html_tbl(GVJ_t * job, htmltbl_t * tbl, htmlenv_t * env, void *obj) /* gvrender_begin_context(job); */ if (tbl->data.href) - doAnchorStart(job, &tbl->data, obj); + doAnchorStart(job, &tbl->data); if (tbl->data.bgcolor) doFill(job, tbl->data.bgcolor, pts); while (*cells) { - emit_html_cell(job, *cells, env, obj); + emit_html_cell(job, *cells, env); cells++; } @@ -366,7 +323,7 @@ emit_html_tbl(GVJ_t * job, htmltbl_t * tbl, htmlenv_t * env, void *obj) } static void -emit_html_img(GVJ_t * job, htmlimg_t * cp, htmlenv_t * env, void *obj) +emit_html_img(GVJ_t * job, htmlimg_t * cp, htmlenv_t * env) { pointf A[4]; box bb = cp->box; @@ -387,7 +344,7 @@ emit_html_img(GVJ_t * job, htmlimg_t * cp, htmlenv_t * env, void *obj) } static void -emit_html_cell(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env, void *obj) +emit_html_cell(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env) { box pts = cp->data.box; point p = env->p; @@ -400,17 +357,17 @@ emit_html_cell(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env, void *obj) /* gvrender_begin_context(); */ if (cp->data.href) - doAnchorStart(job, &cp->data, obj); + doAnchorStart(job, &cp->data); if (cp->data.bgcolor) doFill(job, cp->data.bgcolor, pts); if (cp->child.kind == HTML_TBL) - emit_html_tbl(job, cp->child.u.tbl, env, obj); + emit_html_tbl(job, cp->child.u.tbl, env); else if (cp->child.kind == HTML_IMAGE) - emit_html_img(job, cp->child.u.img, env, obj); + emit_html_img(job, cp->child.u.img, env); else - emit_html_txt(job, cp->child.u.txt, env, obj); + emit_html_txt(job, cp->child.u.txt, env); if (cp->data.border) doBorder(job, cp->data.pencolor, cp->data.border, pts); @@ -424,7 +381,7 @@ emit_html_cell(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env, void *obj) /* emit_html_label: */ void -emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t * tp, void *obj) +emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t * tp) { htmlenv_t env; @@ -443,10 +400,10 @@ emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t * tp, void *obj) gvrender_set_pencolor(job, tbl->data.pencolor); else gvrender_set_pencolor(job, DEFAULT_COLOR); - emit_html_tbl(job, tbl, &env, obj); + emit_html_tbl(job, tbl, &env); gvrender_end_context(job); } else { - emit_html_txt(job, lp->u.txt, &env, obj); + emit_html_txt(job, lp->u.txt, &env); } } @@ -471,25 +428,6 @@ void free_html_data(htmldata_t * dp) free(dp->bgcolor); } -#ifdef OLD -void free_html_text(htmltxt_t * tp) -{ - textpara_t *lp; - - if (!tp) - return; - lp = tp->para; - while (lp->str) { - free(lp->str); - lp++; - } - free(tp->para); - if (tp->font) - free_html_font(tp->font); - free(tp); -} -#endif - void free_html_text(htmltxt_t* t) { htextpara_t *tl; @@ -694,62 +632,6 @@ int html_path(node_t * n, port* p, int side, box * rv, int *k) return 0; } -#ifdef OLD -static int -size_html_txt(graph_t *g, htmltxt_t * txt, htmlenv_t * env) -{ - double xsize = 0.0; - double fsize; - char *fname; - char *news = NULL; - textpara_t *lp = txt->para; - pointf size; - - if (txt->font) { - if (txt->font->size > 0.0) - fsize = txt->font->size; - else - fsize = env->finfo.size; - if (txt->font->name) - fname = txt->font->name; - else - fname = env->finfo.name; - } else { - fsize = env->finfo.size; - fname = env->finfo.name; - } - - while (lp->str) { - switch (agobjkind(env->obj)) { - case AGGRAPH: - news = - strdup_and_subst_graph(lp->str, (Agraph_t *) (env->obj)); - break; - case AGNODE: - news = strdup_and_subst_node(lp->str, (Agnode_t *) (env->obj)); - break; - case AGEDGE: - news = strdup_and_subst_edge(lp->str, (Agedge_t *) (env->obj)); - break; - } - free(lp->str); - lp->str = news; - - size = textsize(g, lp, fname, fsize); - /* no margins are added since the containing node or cell will pad */ - if (dimen.x > xsize) - xsize = size.x; - lp++; - } - txt->box.UR.x = xsize; - if (txt->nparas == 1) - txt->box.UR.y = (int) (size.y); - else - txt->box.UR.y = txt->nparas * (int) (size.y * LINESPACING); - return 0; -} -#endif - static char* substrGFn (char* s, htmlenv_t* env) { @@ -1592,22 +1474,6 @@ void printImage(htmlimg_t *ip, int ind) fprintf(stderr, "img: %s\n", ip->src); } -#ifdef OLD -void printTxt(htmltxt_t * tp, int ind) -{ - int i; - indent(ind); - fprintf(stderr, "txt "); - printBox(tp->box); - fputs("\n", stderr); - for (i = 0; i < tp->nparas; i++) { - indent(ind + 1); - fprintf(stderr, "(%c) \"%s\"\n", tp->para[i].just, - tp->para[i].str); - } -} -#endif - void printTxt(htmltxt_t * txt, int ind) { int i, j; diff --git a/lib/common/htmltable.h b/lib/common/htmltable.h index cad000674..476599beb 100644 --- a/lib/common/htmltable.h +++ b/lib/common/htmltable.h @@ -171,8 +171,7 @@ extern "C" { extern htmllabel_t *parseHTML(char *, int *, int); extern int make_html_label(graph_t *g, textlabel_t * lp, void *obj); - extern void emit_html_label(GVJ_t * job, htmllabel_t * lp, - textlabel_t *, void *obj); + extern void emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t *); extern void free_html_label(htmllabel_t *, int); extern void free_html_data(htmldata_t *); diff --git a/lib/common/labels.c b/lib/common/labels.c index 25ef8b037..b522c6cc5 100644 --- a/lib/common/labels.c +++ b/lib/common/labels.c @@ -216,17 +216,18 @@ emit_textparas(GVJ_t* job, int nparas, textpara_t paras[], pointf p, gvrender_end_context(job); } -void emit_label(GVJ_t * job, int state, textlabel_t * lp, void *obj) +void emit_label(GVJ_t * job, emit_state_t emit_state, textlabel_t * lp) { + obj_state_t *obj = job->obj; double halfwidth_x; pointf p; - int oldstate; + emit_state_t old_emit_state; - oldstate = job->gvc->emit_state; - job->gvc->emit_state = state; + old_emit_state = obj->emit_state; + obj->emit_state = emit_state; if (lp->html) { - emit_html_label(job, lp->u.html, lp, obj); + emit_html_label(job, lp->u.html, lp); return; } @@ -242,7 +243,8 @@ void emit_label(GVJ_t * job, int state, textlabel_t * lp, void *obj) emit_textparas(job, lp->u.txt.nparas, lp->u.txt.para, p, halfwidth_x, lp->fontname, lp->fontsize, lp->fontcolor); - job->gvc->emit_state = oldstate; + + obj->emit_state = old_emit_state; } diff --git a/lib/common/output.c b/lib/common/output.c index 5332bae7d..c85c49287 100644 --- a/lib/common/output.c +++ b/lib/common/output.c @@ -19,6 +19,8 @@ static int e_arrows; /* graph has edges with end arrows */ static int s_arrows; /* graph has edges with start arrows */ +static attrsym_t *g_draw; +static attrsym_t *g_l_draw; static void printptf(FILE * f, point pt) { @@ -58,7 +60,7 @@ static void writenodeandport(FILE * fp, node_t * node, char *port) /* _write_plain: */ -static void _write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend) +void write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend) { int i, j, splinePoints; char *tport, *hport; @@ -127,39 +129,6 @@ static void _write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend) fprintf(f, "stop\n"); } -void write_plain(GVJ_t * job, graph_t * g, FILE * f) -{ - _write_plain(job, g, f, FALSE); -} - -void write_plain_ext(GVJ_t * job, graph_t * g, FILE * f) -{ - _write_plain(job, g, f, TRUE); -} - - -void write_extended_dot(GVJ_t *job, graph_t *g, FILE *f) -{ -#ifdef WITH_CODEGENS - attach_attrs(g); - extend_attrs(job, g, s_arrows, e_arrows); - agwrite(g, f); -#endif -} - -void write_attributed_dot(graph_t *g, FILE *f) -{ - attach_attrs(g); - agwrite(g, f); -} - -void write_canonical_dot(graph_t *g, FILE *f) -{ - if (HAS_CLUST_EDGE(g)) - undoClusterEdges(g); - agwrite(g, f); -} - static void set_record_rects(node_t * n, field_t * f, agxbuf * xb) { int i; @@ -329,3 +298,147 @@ void attach_attrs(graph_t * g) if (HAS_CLUST_EDGE(g)) undoClusterEdges(g); } + +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). + * + * N.B. John M. asks: + * By the way, I don't know if you ever plan to add other letters for + * the xdot spec, but could you reserve "a" and also "A" (for attribute), + * "n" and also "N" (for numeric), "w" (for sWitch), "s" (for string) + * and "t" (for tooltip) and "x" (for position). We use those letters in + * our drawing spec (and also "<" and ">"), so if you start generating + * output with them, it could break what we have. + */ + +#define XDOTVERSION "1.1" + +void extend_attrs(GVJ_t * job, graph_t *g, agxbuf** xbufs) +{ + 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 buf0[BUFSIZ]; + unsigned char buf1[BUFSIZ]; + unsigned char buf2[BUFSIZ]; + unsigned char buf3[BUFSIZ]; + unsigned char buf4[BUFSIZ]; + unsigned char buf5[BUFSIZ]; + + agsafeset (g, "xdotversion", XDOTVERSION, ""); + if (GD_has_labels(g) & GRAPH_LABEL) + g_l_draw = safe_dcl(g, g, "_ldraw_", "", agraphattr); + else + g_l_draw = NULL; + if (GD_n_cluster(g)) + g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); + else + g_draw = NULL; + + 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(xbufs[0], BUFSIZ, buf0); + agxbinit(xbufs[1], BUFSIZ, buf1); + agxbinit(xbufs[2], BUFSIZ, buf2); + agxbinit(xbufs[3], BUFSIZ, buf3); + agxbinit(xbufs[4], BUFSIZ, buf4); + agxbinit(xbufs[5], BUFSIZ, buf5); + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + if (ND_shape(n) && !isInvis(late_string(n, N_style, ""))) { + ND_shape(n)->fns->codefn(job, n); + agxset(n, n_draw->index, agxbuse(xbufs[EMIT_NDRAW])); + agxset(n, n_l_draw->index, agxbuse(xbufs[EMIT_NLABEL])); + } + 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; + + emit_edge_graphics (job, e); + agxset(e, e_draw->index, agxbuse(xbufs[EMIT_EDRAW])); + if (t_draw) agxset(e, t_draw->index, agxbuse(xbufs[EMIT_TDRAW])); + if (h_draw) agxset(e, h_draw->index, agxbuse(xbufs[EMIT_HDRAW])); + if (e_l_draw) agxset(e, e_l_draw->index,agxbuse(xbufs[EMIT_ELABEL])); + if (tl_draw) agxset(e, tl_draw->index, agxbuse(xbufs[EMIT_TLABEL])); + if (hl_draw) agxset(e, hl_draw->index, agxbuse(xbufs[EMIT_HLABEL])); + } + } + + emit_background(job, g); + if (agxblen(xbufs[EMIT_GDRAW])) { + if (!g_draw) + g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); + agxset(g, g_draw->index, agxbuse(xbufs[EMIT_GDRAW])); + } + if (GD_label(g)) { + emit_label(job, EMIT_GLABEL, GD_label(g)); + agxset(g, g_l_draw->index, agxbuse(xbufs[EMIT_GLABEL])); + } + emit_clusters(job, g, 0); + agxbfree(xbufs[0]); + agxbfree(xbufs[1]); + agxbfree(xbufs[2]); + agxbfree(xbufs[3]); + agxbfree(xbufs[4]); + agxbfree(xbufs[5]); +} + +void extend_attrs_glabel(graph_t *sg, agxbuf **xbufs) +{ + agxset(sg, g_draw->index, agxbuse(xbufs[EMIT_CDRAW])); + if (GD_label(sg)) + agxset(sg, g_l_draw->index, agxbuse(xbufs[EMIT_CLABEL])); +} diff --git a/lib/common/render.h b/lib/common/render.h index ec6772d8d..104443e23 100644 --- a/lib/common/render.h +++ b/lib/common/render.h @@ -66,7 +66,7 @@ extern "C" { extern void add_box(path *, box); extern void arrow_flags(Agedge_t * e, int *sflag, int *eflag); extern boxf arrow_bb(pointf p, pointf u, double scale, int flag); - extern void arrow_gen(GVJ_t * job, int state, point p, point u, + extern void arrow_gen(GVJ_t * job, emit_state_t emit_state, point p, point u, double scale, int flag); extern double arrow_length(edge_t * e, int flag); extern int arrowEndClip(edge_t*, point*, int, int , bezier*, int eflag); @@ -97,7 +97,7 @@ extern "C" { extern void emit_clusters(GVJ_t * job, Agraph_t * g, int flags); extern void emit_edge_graphics(GVJ_t * job, edge_t * e); extern void emit_graph(GVJ_t * job, graph_t * g); - extern void emit_label(GVJ_t * job, int state, textlabel_t *, void *obj); + extern void emit_label(GVJ_t * job, emit_state_t emit_state, textlabel_t *); extern int emit_once(char *message); extern void emit_jobs_eof(GVC_t * gvc); extern void emit_textparas(GVJ_t*, int, textpara_t*, pointf, @@ -106,7 +106,6 @@ extern "C" { extern void endpath(path *, Agedge_t *, int, pathend_t *, bool); extern void epsf_init(node_t * n); extern void epsf_free(node_t * n); - extern void extend_attrs(GVJ_t * job, graph_t *g, int s_arrows, int e_arrows); extern shape_desc *find_user_shape(char *); extern void free_line(textpara_t *); extern void free_label(textlabel_t *); @@ -152,8 +151,7 @@ extern "C" { 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(GVJ_t * job, graph_t *g, FILE *f); - extern void write_plain(GVJ_t * job, graph_t * g, FILE * f); - extern void write_plain_ext(GVJ_t * job, graph_t * g, FILE * f); + extern void write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend); #if defined(_BLD_dot) && defined(_DLL) # define extern __EXPORT__ diff --git a/lib/common/shapes.c b/lib/common/shapes.c index 744ed3bfe..bbcc8c227 100644 --- a/lib/common/shapes.c +++ b/lib/common/shapes.c @@ -1311,7 +1311,7 @@ static void poly_gencode(GVJ_t * job, node_t * n) filled = FALSE; } - emit_label(job, EMIT_NLABEL, ND_label(n), (void *) n); + emit_label(job, EMIT_NLABEL, ND_label(n)); } /*=======================end poly======================================*/ @@ -1841,7 +1841,7 @@ static void gen_fields(GVJ_t * job, node_t * n, field_t * f) cx = (f->b.LL.x + f->b.UR.x) / 2.0 + ND_coord_i(n).x; cy = (f->b.LL.y + f->b.UR.y) / 2.0 + ND_coord_i(n).y; f->lp->p = pointof((int) cx, (int) cy); - emit_label(job, EMIT_NLABEL, f->lp, (void *) n); + emit_label(job, EMIT_NLABEL, f->lp); } for (i = 0; i < f->n_flds; i++) { @@ -1981,5 +1981,5 @@ static void epsf_gencode(GVJ_t * job, node_t * n) ND_coord_i(n).y + desc->offset.y, desc->macro_id); ND_label(n)->p = ND_coord_i(n); gvrender_end_context(job); - emit_label(job, EMIT_NLABEL, ND_label(n), (void *) n); + emit_label(job, EMIT_NLABEL, ND_label(n)); } diff --git a/lib/common/xdgen.c b/lib/common/xdgen.c deleted file mode 100644 index 3ccbc0778..000000000 --- a/lib/common/xdgen.c +++ /dev/null @@ -1,338 +0,0 @@ -/* $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 "agxbuf.h" - -#define XDOTVERSION "1.1" - -static GVC_t *gvc; -static agxbuf xbuf0; -static agxbuf xbuf1; -static agxbuf xbuf2; -static agxbuf xbuf3; -static agxbuf xbuf4; -static agxbuf xbuf5; -static agxbuf* xbufs[6] = { - &xbuf0, &xbuf1, - &xbuf2, &xbuf3, - &xbuf4, &xbuf5, -}; -static Agraph_t *cluster_g; -static attrsym_t *g_draw; -static attrsym_t *g_l_draw; - -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). - * - * N.B. John M. asks: - * By the way, I don't know if you ever plan to add other letters for - * the xdot spec, but could you reserve "a" and also "A" (for attribute), - * "n" and also "N" (for numeric), "w" (for sWitch), "s" (for string) - * and "t" (for tooltip) and "x" (for position). We use those letters in - * our drawing spec (and also "<" and ">"), so if you start generating - * output with them, it could break what we have. - */ -void extend_attrs(GVJ_t * job, graph_t *g, int s_arrows, int e_arrows) -{ - 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 buf0[BUFSIZ]; - unsigned char buf1[BUFSIZ]; - unsigned char buf2[BUFSIZ]; - unsigned char buf3[BUFSIZ]; - unsigned char buf4[BUFSIZ]; - unsigned char buf5[BUFSIZ]; - - gvc = job->gvc; - - agsafeset (g, "xdotversion", XDOTVERSION, ""); - if (GD_has_labels(g) & GRAPH_LABEL) - g_l_draw = safe_dcl(g, g, "_ldraw_", "", agraphattr); - else - g_l_draw = NULL; - if (GD_n_cluster(g)) - g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); - else - g_draw = NULL; - - 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(&xbuf0, BUFSIZ, buf0); - agxbinit(&xbuf1, BUFSIZ, buf1); - agxbinit(&xbuf2, BUFSIZ, buf2); - agxbinit(&xbuf3, BUFSIZ, buf3); - agxbinit(&xbuf4, BUFSIZ, buf4); - agxbinit(&xbuf5, BUFSIZ, buf5); - - for (n = agfstnode(g); n; n = agnxtnode(g, n)) { - if (ND_shape(n) && !isInvis(late_string(n, N_style, ""))) { - ND_shape(n)->fns->codefn(job, n); - agxset(n, n_draw->index, agxbuse(xbufs[EMIT_NDRAW])); - agxset(n, n_l_draw->index, agxbuse(xbufs[EMIT_NLABEL])); - } - 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; - - emit_edge_graphics (job, e); - agxset(e, e_draw->index, agxbuse(xbufs[EMIT_EDRAW])); - if (t_draw) agxset(e, t_draw->index, agxbuse(xbufs[EMIT_TDRAW])); - if (h_draw) agxset(e, h_draw->index, agxbuse(xbufs[EMIT_HDRAW])); - if (e_l_draw) agxset(e, e_l_draw->index,agxbuse(xbufs[EMIT_ELABEL])); - if (tl_draw) agxset(e, tl_draw->index, agxbuse(xbufs[EMIT_TLABEL])); - if (hl_draw) agxset(e, hl_draw->index, agxbuse(xbufs[EMIT_HLABEL])); - } - } - - emit_background(job, g); - if (agxblen(xbufs[EMIT_GDRAW])) { - if (!g_draw) - g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); - agxset(g, g_draw->index, agxbuse(xbufs[EMIT_GDRAW])); - } - if (GD_label(g)) { - emit_label(job, EMIT_GLABEL, GD_label(g), (void *) g); - agxset(g, g_l_draw->index, agxbuse(xbufs[EMIT_GLABEL])); - } - emit_clusters(job, g, 0); - agxbfree(&xbuf0); - agxbfree(&xbuf1); - agxbfree(&xbuf2); - agxbfree(&xbuf3); - agxbfree(&xbuf4); - agxbfree(&xbuf5); -} - -static void xd_str (char* pfx, char* s) -{ - char buf[BUFSIZ]; - - sprintf (buf, "%s%d -", pfx, (int)strlen(s)); - agxbput(xbufs[gvc->emit_state], buf); - agxbput(xbufs[gvc->emit_state], s); - agxbputc(xbufs[gvc->emit_state], ' '); -} - -static void xd_textpara(point p, textpara_t * para) -{ - char buf[BUFSIZ]; - int j; - - switch (para->just) { - case 'l': - j = -1; - break; - case 'r': - j = 1; - break; - default: - case 'n': - j = 0; - break; - } - sprintf(buf, "T %d %d %d %d ", p.x, YDIR(p.y), j, (int) para->width); - agxbput(xbufs[gvc->emit_state], buf); - xd_str ("", para->str); -} - -static void xd_ellipse(point p, int rx, int ry, int filled) -{ - char buf[BUFSIZ]; - int rc; - - rc = agxbputc(xbufs[gvc->emit_state], (filled ? 'E' : 'e')); - sprintf(buf, " %d %d %d %d ", p.x, YDIR(p.y), rx, ry); - agxbput(xbufs[gvc->emit_state], buf); -} - -static void xd_points(char c, point * A, int n) -{ - char buf[BUFSIZ]; - int i, rc; - point p; - - rc = agxbputc(xbufs[gvc->emit_state], c); - sprintf(buf, " %d ", n); - agxbput(xbufs[gvc->emit_state], buf); - for (i = 0; i < n; i++) { - p = A[i]; - sprintf(buf, "%d %d ", p.x, YDIR(p.y)); - agxbput(xbufs[gvc->emit_state], 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, int filled) -{ - if (filled) - xd_points('b', A, n); - else - xd_points('B', A, n); -} - -static void xd_polyline(point * A, int n) -{ - xd_points('L', A, n); -} - -static void -xd_set_font (char *fontname, double fontsize) -{ - char buf[BUFSIZ]; - - sprintf(buf, "F %f ", fontsize); - agxbput(xbufs[gvc->emit_state], buf); - xd_str ("", fontname); -} - -static void -xd_set_pencolor (char *name) -{ - xd_str ("c ", name); -} - -static void -xd_set_fillcolor (char *name) -{ - xd_str ("C ", name); -} - -static void -xd_set_style (char **s) -{ - unsigned char buf[BUFSIZ]; - agxbuf xbuf; - char* p; - int more; - - agxbinit(&xbuf, BUFSIZ, buf); - while ((p = *s++)) { - agxbput(&xbuf, p); - while (*p) - p++; - p++; - if (*p) { /* arguments */ - agxbputc(&xbuf, '('); - more = 0; - while (*p) { - if (more) - agxbputc(&xbuf, ','); - agxbput(&xbuf, p); - while (*p) p++; - p++; - more++; - } - agxbputc(&xbuf, ')'); - } - xd_str ("S ", agxbuse(&xbuf)); - } - agxbfree(&xbuf); -} - -static void xd_begin_cluster(Agraph_t * sg) -{ - cluster_g = sg; -} - -static void xd_end_cluster(void) -{ - agxset(cluster_g, g_draw->index, agxbuse(xbufs[EMIT_CDRAW])); - if (GD_label(cluster_g)) - agxset(cluster_g, g_l_draw->index, agxbuse(xbufs[EMIT_CLABEL])); -} - -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_end_node */ - 0, /* xd_begin_edge */ 0, /* xd_end_edge */ - 0, /* xd_begin_context */ 0, /* xd_context */ - 0, /* xd_begin_anchor */ 0, /* xd_anchor */ - xd_set_font, xd_textpara, - xd_set_pencolor, xd_set_fillcolor, xd_set_style, - xd_ellipse, xd_polygon, - xd_bezier, xd_polyline, - 0, /* xd_has_arrows */ - 0, /* xd_comment */ - 0 /* xd_usershape */ -}; diff --git a/lib/gvc/gvc.c b/lib/gvc/gvc.c index d0cac5361..ee758a3d8 100644 --- a/lib/gvc/gvc.c +++ b/lib/gvc/gvc.c @@ -101,7 +101,7 @@ int gvRender(GVC_t *gvc, graph_t *g, char *format, FILE *out) } job->output_lang = gvrender_select(job, job->output_langname); - if (!GD_drawing(g) && job->output_lang != CANONICAL_DOT) { + if (!GD_drawing(g) && !(job->flags & LAYOUT_NOT_REQUIRED)) { fprintf(stderr, "Layout was not done\n"); return -1; } @@ -131,7 +131,7 @@ int gvRenderFilename(GVC_t *gvc, graph_t *g, char *format, char *filename) } job->output_lang = gvrender_select(job, job->output_langname); - if (!GD_drawing(g) && job->output_lang != CANONICAL_DOT) { + if (!GD_drawing(g) && !(job->flags & LAYOUT_NOT_REQUIRED)) { fprintf(stderr, "Layout was not done\n"); return -1; } diff --git a/lib/gvc/gvcint.h b/lib/gvc/gvcint.h index fcdf99837..68ef8bad9 100644 --- a/lib/gvc/gvcint.h +++ b/lib/gvc/gvcint.h @@ -98,7 +98,6 @@ extern "C" { GVJ_t *jobs; /* linked list of jobs */ GVJ_t *job; /* current job */ - int emit_state; /* current emit_state */ graph_t *g; /* current graph */ /* gvrender_begin_job() */ diff --git a/lib/gvc/gvcjob.h b/lib/gvc/gvcjob.h index d9cb9c859..966b977be 100644 --- a/lib/gvc/gvcjob.h +++ b/lib/gvc/gvcjob.h @@ -62,6 +62,7 @@ extern "C" { #define GVRENDER_DOES_TOOLTIPS (1<<19) #define GVRENDER_DOES_TARGETS (1<<20) #define GVRENDER_DOES_Z (1<<21) +#define LAYOUT_NOT_REQUIRED (1<<22) typedef struct { int flags; @@ -128,6 +129,36 @@ extern "C" { typedef enum {MAP_RECTANGLE, MAP_CIRCLE, MAP_POLYGON, } map_shape_t; typedef enum {ROOTGRAPH_OBJTYPE, CLUSTER_OBJTYPE, NODE_OBJTYPE, EDGE_OBJTYPE} obj_type; +#if 0 + typedef enum {EMIT_GDRAW, EMIT_CDRAW, EMIT_NDRAW, EMIT_EDRAW, EMIT_TDRAW, EMIT_HDRAW, + EMIT_GLABEL, EMIT_CLABEL, EMIT_NLABEL, EMIT_ELABEL, EMIT_TLABEL, EMIT_HLABEL} emit_state_t; +#else + +/* FIXME - There are places in the core that rely on there being exactly 6 emit_states ! */ +#define emit_state_t int + +/* value specifying emit state */ +#define EMIT_DRAW 0 +#define EMIT_GDRAW EMIT_DRAW +#define EMIT_CDRAW EMIT_DRAW +#define EMIT_NDRAW EMIT_DRAW +#define EMIT_EDRAW EMIT_DRAW + +/* values specifying emit state for arrowheads */ +#define EMIT_TDRAW 1 +#define EMIT_HDRAW 2 + +/* values specifying emit state for labels */ +#define EMIT_LABEL 3 +#define EMIT_GLABEL EMIT_LABEL +#define EMIT_CLABEL EMIT_LABEL +#define EMIT_NLABEL EMIT_LABEL +#define EMIT_ELABEL EMIT_LABEL +#define EMIT_TLABEL 4 +#define EMIT_HLABEL 5 + +#endif + typedef struct obj_state_s obj_state_t; struct obj_state_s { @@ -141,7 +172,7 @@ extern "C" { edge_t *e; } u; - int oldstate; /* FIXME - used by one of those other state stacks */ + emit_state_t emit_state; gvcolor_t pencolor, fillcolor; pen_type pen; @@ -196,6 +227,7 @@ extern "C" { pointf *headendurl_map_p; }; +typedef enum {COMPRESSION_NONE, COMPRESSION_ZLIB} compression_t; /* Note on units: * points - a physical distance (1/72 inch) unaffected by zoom or dpi. @@ -222,6 +254,8 @@ extern "C" { FILE *output_file; int output_lang; + compression_t compression; + gvplugin_active_render_t render; gvplugin_active_device_t device; gvplugin_active_loadimage_t loadimage; diff --git a/lib/gvc/gvconfig.c b/lib/gvc/gvconfig.c index 2f05ae750..2845984ad 100644 --- a/lib/gvc/gvconfig.c +++ b/lib/gvc/gvconfig.c @@ -46,8 +46,7 @@ extern const bool Demand_Loading; extern codegen_t QPDF_CodeGen, QEPDF_CodeGen, QBM_CodeGen; #endif - extern codegen_t HPGL_CodeGen, MIF_CodeGen, XDot_CodeGen, - MP_CodeGen, PIC_CodeGen, DIA_CodeGen, VTX_CodeGen; + extern codegen_t HPGL_CodeGen, MIF_CodeGen, MP_CodeGen, PIC_CodeGen, DIA_CodeGen, VTX_CodeGen; #endif /* @@ -374,12 +373,6 @@ static codegen_info_t cg[MAX_CODEGENS] = { #ifdef HAVE_LIBZ {&DIA_CodeGen, "dia", DIA}, #endif -#define DUMMY_CodeGen XDot_CodeGen - {&DUMMY_CodeGen, "dot", ATTRIBUTED_DOT}, - {&DUMMY_CodeGen, "canon", CANONICAL_DOT}, - {&DUMMY_CodeGen, "plain", PLAIN}, - {&DUMMY_CodeGen, "plain-ext", PLAIN_EXT}, - {&DUMMY_CodeGen, "xdot", EXTENDED_DOT}, {NULL, NULL, 0} }; diff --git a/lib/gvc/gvjobs.c b/lib/gvc/gvjobs.c index e0f872fdc..5d19bdff2 100644 --- a/lib/gvc/gvjobs.c +++ b/lib/gvc/gvjobs.c @@ -50,15 +50,13 @@ static GVJ_t *output_langname_job; void gvjobs_output_filename(GVC_t * gvc, char *name) { if (!gvc->jobs) { - output_filename_job = gvc->job = gvc->jobs = - zmalloc(sizeof(GVJ_t)); + output_filename_job = gvc->job = gvc->jobs = zmalloc(sizeof(GVJ_t)); } else { if (!output_filename_job) { output_filename_job = gvc->jobs; } else { if (!output_filename_job->next) { - output_filename_job->next = - zmalloc(sizeof(GVJ_t)); + output_filename_job->next = zmalloc(sizeof(GVJ_t)); } output_filename_job = output_filename_job->next; } @@ -71,15 +69,13 @@ void gvjobs_output_filename(GVC_t * gvc, char *name) bool gvjobs_output_langname(GVC_t * gvc, char *name) { if (!gvc->jobs) { - output_langname_job = gvc->job = gvc->jobs = - zmalloc(sizeof(GVJ_t)); + output_langname_job = gvc->job = gvc->jobs = zmalloc(sizeof(GVJ_t)); } else { if (!output_langname_job) { output_langname_job = gvc->jobs; } else { if (!output_langname_job->next) { - output_langname_job->next = - zmalloc(sizeof(GVJ_t)); + output_langname_job->next = zmalloc(sizeof(GVJ_t)); } output_langname_job = output_langname_job->next; } diff --git a/plugin/core/Makefile.am b/plugin/core/Makefile.am index ad125fb33..27ac0b064 100644 --- a/plugin/core/Makefile.am +++ b/plugin/core/Makefile.am @@ -16,9 +16,11 @@ pkglib_LTLIBRARIES = libgvplugin_core.la libgvplugin_core_C_la_SOURCES = \ gvplugin_core.c \ - gvrender_core_svg.c \ - gvrender_core_fig.c \ + gvrender_core.c \ + gvrender_core_dot.c \ gvrender_core_ps.c \ + gvrender_core_fig.c \ + gvrender_core_svg.c \ gvrender_core_map.c \ gvloadimage_core.c diff --git a/plugin/core/gvloadimage_core.c b/plugin/core/gvloadimage_core.c index 0b8ced661..f49a8e195 100644 --- a/plugin/core/gvloadimage_core.c +++ b/plugin/core/gvloadimage_core.c @@ -36,9 +36,8 @@ /* for n->name */ #include "graph.h" -extern void svggen_fputs(GVJ_t * job, char *s); -extern void svggen_printf(GVJ_t * job, const char *format, ...); -extern void figgen_printf(GVJ_t * job, const char *format, ...); +extern void core_fputs(GVJ_t * job, char *s); +extern void core_printf(GVJ_t * job, const char *format, ...); extern void epsf_emit_body(usershape_t *us, FILE *of); extern shape_desc *find_user_shape(char *name); @@ -57,19 +56,19 @@ static void core_loadimage_svg(GVJ_t * job, usershape_t *us, boxf b, bool filled assert(us->name); assert(us->f); - svggen_fputs(job, "name); + core_fputs(job, "name); if (job->rotation) { - svggen_printf (job, "\" width=\"%gpx\" height=\"%gpx\" preserveAspectRatio=\"xMidYMid meet\" x=\"%g\" y=\"%g\"", + core_printf (job, "\" width=\"%gpx\" height=\"%gpx\" preserveAspectRatio=\"xMidYMid meet\" x=\"%g\" y=\"%g\"", b.UR.y - b.LL.y, b.UR.x - b.LL.x, b.LL.x, b.UR.y); - svggen_printf (job, " transform=\"rotate(%d %g %g)\"", + core_printf (job, " transform=\"rotate(%d %g %g)\"", job->rotation, b.LL.x, b.UR.y); } else { - svggen_printf (job, "\" width=\"%gpx\" height=\"%gpx\" preserveAspectRatio=\"xMidYMid meet\" x=\"%g\" y=\"%g\"", + core_printf (job, "\" width=\"%gpx\" height=\"%gpx\" preserveAspectRatio=\"xMidYMid meet\" x=\"%g\" y=\"%g\"", b.UR.x - b.LL.x, b.UR.y - b.LL.y, b.LL.x, b.LL.y); } - svggen_fputs(job, "/>\n"); + core_fputs(job, "/>\n"); } static void core_loadimage_fig(GVJ_t * job, usershape_t *us, boxf bf, bool filled) @@ -101,13 +100,12 @@ static void core_loadimage_fig(GVJ_t * job, usershape_t *us, boxf bf, bool fille BF2B(bf, b); - figgen_printf(job, - "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n %d %s\n", + core_printf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n %d %s\n", object_code, sub_type, line_style, thickness, pen_color, fill_color, depth, pen_style, area_fill, style_val, join_style, cap_style, radius, forward_arrow, backward_arrow, npoints, flipped, us->name); - figgen_printf(job," %d %d %d %d %d %d %d %d %d %d\n", + core_printf(job," %d %d %d %d %d %d %d %d %d %d\n", b.LL.x, b.LL.y, b.LL.x, b.UR.y, b.UR.x, b.UR.y, diff --git a/plugin/core/gvplugin_core.c b/plugin/core/gvplugin_core.c index 3a548fa5c..f5ee99c99 100644 --- a/plugin/core/gvplugin_core.c +++ b/plugin/core/gvplugin_core.c @@ -16,6 +16,7 @@ #include "gvplugin.h" +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 gvrender_core_svg_types; @@ -23,6 +24,7 @@ extern gvplugin_installed_t gvrender_core_map_types; extern gvplugin_installed_t gvloadimage_core_types; static gvplugin_api_t apis[] = { + {API_render, &gvrender_core_dot_types}, {API_render, &gvrender_core_ps_types}, {API_render, &gvrender_core_fig_types}, {API_render, &gvrender_core_svg_types}, diff --git a/plugin/core/gvrender_core.c b/plugin/core/gvrender_core.c new file mode 100644 index 000000000..2494ab865 --- /dev/null +++ b/plugin/core/gvrender_core.c @@ -0,0 +1,126 @@ +/* $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 +#include +#include + +#ifdef HAVE_LIBZ +#include +#endif + +#ifdef WIN32 +#include +#include "compat.h" +#endif + +#include "gvplugin_render.h" + +void core_init_compression(GVJ_t *job, compression_t compression) +{ +#if HAVE_LIBZ + int fd; +#endif + + switch ((job->compression = compression)) { + case COMPRESSION_ZLIB: +#if HAVE_LIBZ + /* open dup so can gzclose independent of FILE close */ + fd = dup(fileno(job->output_file)); +#ifdef HAVE_SETMODE +#ifdef O_BINARY + /* + * Windows will do \n -> \r\n translations on + * stdout unless told otherwise. + */ + setmode(fd, O_BINARY); +#endif +#endif + + job->output_file = (FILE *) (gzdopen(fd, "wb")); + if (!job->output_file) { + (job->common->errorfn) ("Error initializing compression on output file\n"); + exit(1); + } + break; +#else + (job->common->errorfn) ("No libz support.\n"); + exit(1); +#endif + case COMPRESSION_NONE: + break; + } +} + +void core_fini_compression(GVJ_t *job) +{ + switch (job->compression) { + case COMPRESSION_ZLIB: +#ifdef HAVE_LIBZ + gzclose((gzFile *) (job->output_file)); + break; +#else + (job->common->errorfn) ("No libz support\n"); + exit(1); +#endif + case COMPRESSION_NONE: + break; + } +} + +void core_fputs(GVJ_t * job, char *s) +{ + int len; + + len = strlen(s); + switch (job->compression) { + case COMPRESSION_ZLIB: +#ifdef HAVE_LIBZ + gzwrite((gzFile *) (job->output_file), s, (unsigned) len); +#endif + break; + case COMPRESSION_NONE: + fwrite(s, sizeof(char), (unsigned) len, job->output_file); + break; + } +} + +/* core_printf: + * Note that this function is unsafe due to the fixed buffer size. + * It should only be used when the caller is sure the input will not + * overflow the buffer. In particular, it should be avoided for + * input coming from users. Also, if vsnprintf is available, the + * code should check for return values to use it safely. + */ +void core_printf(GVJ_t * job, const char *format, ...) +{ + char buf[BUFSIZ]; + va_list argp; + + va_start(argp, format); +#ifdef HAVE_VSNPRINTF + (void) vsnprintf(buf, sizeof(buf), format, argp); +#else + (void) vsprintf(buf, format, argp); +#endif + va_end(argp); + + core_fputs(job, buf); +} diff --git a/plugin/core/gvrender_core_dot.c b/plugin/core/gvrender_core_dot.c new file mode 100644 index 000000000..82c2cc404 --- /dev/null +++ b/plugin/core/gvrender_core_dot.c @@ -0,0 +1,313 @@ +/* $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 +#include "compat.h" +#endif + +#include +#include +#include + +#include "macros.h" +#include "const.h" + +#include "gvplugin_render.h" +#include "graph.h" +#include "agxbuf.h" +#include "utils.h" + +extern void attach_attrs(graph_t * g); +extern char *xml_string(char *str); +extern void write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend); +extern void extend_attrs(GVJ_t * job, graph_t *g, agxbuf** xbufs); +extern void extend_attrs_glabel(graph_t *sg, agxbuf **xbufs); + +typedef enum { FORMAT_DOT, FORMAT_CANON, FORMAT_PLAIN, FORMAT_PLAIN_EXT, FORMAT_XDOT } format_type; + +static agxbuf xbuf0; +static agxbuf xbuf1; +static agxbuf xbuf2; +static agxbuf xbuf3; +static agxbuf xbuf4; +static agxbuf xbuf5; +static agxbuf* xbufs[6] = { + &xbuf0, &xbuf1, + &xbuf2, &xbuf3, + &xbuf4, &xbuf5, +}; + +static void xdot_str (GVJ_t *job, char* pfx, char* s) +{ + emit_state_t emit_state = job->obj->emit_state; + char buf[BUFSIZ]; + + sprintf (buf, "%s%d -", pfx, (int)strlen(s)); + agxbput(xbufs[emit_state], buf); + agxbput(xbufs[emit_state], s); + agxbputc(xbufs[emit_state], ' '); +} + +static void xdot_points(GVJ_t *job, char c, pointf * A, int n) +{ + emit_state_t emit_state = job->obj->emit_state; + char buf[BUFSIZ]; + int i, rc; + + rc = agxbputc(xbufs[emit_state], c); + sprintf(buf, " %d ", n); + agxbput(xbufs[emit_state], buf); + for (i = 0; i < n; i++) { + sprintf(buf, "%d %d ", ROUND(A[i].x), ROUND(A[i].y)); + agxbput(xbufs[emit_state], buf); + } +} + +static void xdot_set_pencolor (GVJ_t *job, char *name) +{ + xdot_str (job, "c ", name); +} + +static void xdot_set_fillcolor (GVJ_t *job, char *name) +{ + xdot_str (job, "C ", name); +} + +static void xdot_set_style (GVJ_t *job, char **s) +{ + unsigned char buf[BUFSIZ]; + agxbuf xbuf; + char* p; + int more; + + agxbinit(&xbuf, BUFSIZ, buf); + while ((p = *s++)) { + agxbput(&xbuf, p); + while (*p) + p++; + p++; + if (*p) { /* arguments */ + agxbputc(&xbuf, '('); + more = 0; + while (*p) { + if (more) + agxbputc(&xbuf, ','); + agxbput(&xbuf, p); + while (*p) p++; + p++; + more++; + } + agxbputc(&xbuf, ')'); + } + xdot_str (job, "S ", agxbuse(&xbuf)); + } + agxbfree(&xbuf); +} + +static void dot_begin_graph(GVJ_t *job) +{ + graph_t *g = job->obj->u.g; + + switch (job->render.id) { + case FORMAT_DOT: + attach_attrs(g); + break; + case FORMAT_CANON: + if (HAS_CLUST_EDGE(g)) + undoClusterEdges(g); + break; + case FORMAT_PLAIN: + case FORMAT_PLAIN_EXT: + break; + case FORMAT_XDOT: + attach_attrs(g); + } +} + +static void dot_end_graph(GVJ_t *job) +{ + graph_t *g = job->obj->u.g; + + switch (job->render.id) { + case FORMAT_PLAIN: + write_plain(job, g, job->output_file, false); + break; + case FORMAT_PLAIN_EXT: + write_plain(job, g, job->output_file, true); + break; + case FORMAT_DOT: + case FORMAT_CANON: + agwrite(g, job->output_file); + break; + case FORMAT_XDOT: + extend_attrs(job, g, xbufs); + agwrite(g, job->output_file); + break; + } +} + +static void xdot_end_cluster(GVJ_t *job) +{ + extend_attrs_glabel(job->obj->u.sg, xbufs); +} + +static void xdot_textpara(GVJ_t * job, pointf p, textpara_t * para) +{ + emit_state_t emit_state = job->obj->emit_state; + + char buf[BUFSIZ]; + int j; + + switch (para->just) { + case 'l': + j = -1; + break; + case 'r': + j = 1; + break; + default: + case 'n': + j = 0; + break; + } + sprintf(buf, "T %d %d %d %d ", ROUND(p.x), ROUND(p.y), j, (int) para->width); + agxbput(xbufs[emit_state], buf); + xdot_str (job, "", para->str); +} + +static void xdot_ellipse(GVJ_t * job, pointf * A, int filled) +{ + emit_state_t emit_state = job->obj->emit_state; + + char buf[BUFSIZ]; + int rc; + + rc = agxbputc(xbufs[emit_state], (filled ? 'E' : 'e')); + sprintf(buf, " %d %d %d %d ", + ROUND(A[0].x), ROUND(A[0].y), ROUND(A[1].x - A[0].x), ROUND(A[1].y - A[0].y)); + agxbput(xbufs[emit_state], buf); +} + +static void xdot_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, int arrow_at_end, int filled) +{ + xdot_points(job, (filled ? 'B' : 'b'), A, n); +} + +static void xdot_polygon(GVJ_t * job, pointf * A, int n, int filled) +{ + xdot_points(job, (filled ? 'P' : 'p'), A, n); +} + +static void xdot_polyline(GVJ_t * job, pointf * A, int n) +{ + xdot_points(job, 'L', A, n); +} + +gvrender_engine_t dot_engine = { + 0, /* dot_begin_job */ + 0, /* dot_end_job */ + dot_begin_graph, + dot_end_graph, + 0, /* dot_begin_layer */ + 0, /* dot_end_layer */ + 0, /* dot_begin_page */ + 0, /* dot_end_page */ + 0, /* dot_begin_cluster */ + 0, /* dot_end_cluster */ + 0, /* dot_begin_nodes */ + 0, /* dot_end_nodes */ + 0, /* dot_begin_edges */ + 0, /* dot_end_edges */ + 0, /* dot_begin_node */ + 0, /* dot_end_node */ + 0, /* dot_begin_edge */ + 0, /* dot_end_edge */ + 0, /* dot_begin_anchor */ + 0, /* dot_end_anchor */ + 0, /* dot_textpara */ + 0, /* dot_resolve_color */ + 0, /* dot_ellipse */ + 0, /* dot_polygon */ + 0, /* dot_bezier */ + 0, /* dot_polyline */ + 0, /* dot_comment */ +}; + +gvrender_engine_t xdot_engine = { + 0, /* xdot_begin_job */ + 0, /* xdot_end_job */ + dot_begin_graph, + dot_end_graph, + 0, /* xdot_begin_layer */ + 0, /* xdot_end_layer */ + 0, /* xdot_begin_page */ + 0, /* xdot_end_page */ + 0, /* xdot_begin_cluster */ + xdot_end_cluster, + 0, /* xdot_begin_nodes */ + 0, /* xdot_end_nodes */ + 0, /* xdot_begin_edges */ + 0, /* xdot_end_edges */ + 0, /* xdot_begin_node */ + 0, /* xdot_end_node */ + 0, /* xdot_begin_edge */ + 0, /* xdot_end_edge */ + 0, /* xdot_begin_anchor */ + 0, /* xdot_end_anchor */ + xdot_textpara, + 0, /* xdot_resolve_color */ + xdot_ellipse, + xdot_polygon, + xdot_bezier, + xdot_polyline, + 0, /* xdot_comment */ +}; + +gvrender_features_t canon_features = { + LAYOUT_NOT_REQUIRED, /* flags */ + 0., /* default margin - points */ + {72.,72.}, /* default dpi */ + NULL, /* knowncolors */ + 0, /* sizeof knowncolors */ + COLOR_STRING, /* color_type */ + NULL, /* device */ + NULL, /* gvloadimage target for usershapes */ +}; + +gvrender_features_t dot_features = { + 0, /* flags */ + 0., /* default margin - points */ + {72.,72.}, /* default dpi */ + NULL, /* knowncolors */ + 0, /* sizeof knowncolors */ + COLOR_STRING, /* color_type */ + NULL, /* device */ + NULL, /* gvloadimage target for usershapes */ +}; + +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, &dot_features}, + {0, NULL, 0, NULL, NULL} +}; diff --git a/plugin/core/gvrender_core_fig.c b/plugin/core/gvrender_core_fig.c index e5cd635ba..4cd89c840 100644 --- a/plugin/core/gvrender_core_fig.c +++ b/plugin/core/gvrender_core_fig.c @@ -25,6 +25,7 @@ #ifdef WIN32 #include +#include "compat.h" #endif #include "macros.h" @@ -43,36 +44,8 @@ typedef enum { FORMAT_FIG, } format_type; static int Depth; -void figgen_fputs(GVJ_t * job, char *s) -{ - int len; - - len = strlen(s); - fwrite(s, sizeof(char), (unsigned) len, job->output_file); -} - -/* figgen_printf: - * Note that this function is unsafe due to the fixed buffer size. - * It should only be used when the caller is sure the input will not - * overflow the buffer. In particular, it should be avoided for - * input coming from users. Also, if vsnprintf is available, the - * code should check for return values to use it safely. - */ -void figgen_printf(GVJ_t * job, const char *format, ...) -{ - char buf[BUFSIZ]; - va_list argp; - - va_start(argp, format); -#ifdef HAVE_VSNPRINTF - (void) vsnprintf(buf, sizeof(buf), format, argp); -#else - (void) vsprintf(buf, format, argp); -#endif - va_end(argp); - - figgen_fputs(job, buf); -} +extern void core_fputs(GVJ_t * job, char *s); +extern void core_printf(GVJ_t * job, const char *format, ...); static void figptarray(GVJ_t *job, pointf * A, int n, int close) { @@ -81,13 +54,13 @@ static void figptarray(GVJ_t *job, pointf * A, int n, int close) for (i = 0; i < n; i++) { PF2P(A[i],p); - figgen_printf(job, " %d %d", p.x, p.y); + core_printf(job, " %d %d", p.x, p.y); } if (close) { PF2P(A[0],p); - figgen_printf(job, " %d %d", p.x, p.y); + core_printf(job, " %d %d", p.x, p.y); } - figgen_fputs(job, "\n"); + core_fputs(job, "\n"); } static char *fig_string(char *s) @@ -166,7 +139,7 @@ static char *figcolor[] = { "black", "blue", "green", "cyan", "red", "magenta", "yellow", "white", (char *) NULL }; -static void figgen_resolve_color(GVJ_t *job, gvcolor_t * color) +static void fig_resolve_color(GVJ_t *job, gvcolor_t * color) { int object_code = 0; /* always 0 for color */ int i, new; @@ -186,7 +159,7 @@ static void figgen_resolve_color(GVJ_t *job, gvcolor_t * color) color->u.rgba[1], color->u.rgba[2]); if (new) - figgen_printf(job, "%d %d #%02x%02x%02x\n", + core_printf(job, "%d %d #%02x%02x%02x\n", object_code, i, color->u.rgba[0], color->u.rgba[1], @@ -200,7 +173,7 @@ static void figgen_resolve_color(GVJ_t *job, gvcolor_t * color) color->type = COLOR_INDEX; } -static void figgen_line_style(obj_state_t *obj, int *line_style, double *style_val) +static void fig_line_style(obj_state_t *obj, int *line_style, double *style_val) { switch (obj->pen) { case PEN_DASHED: @@ -219,63 +192,63 @@ static void figgen_line_style(obj_state_t *obj, int *line_style, double *style_v } } -static void figgen_comment(GVJ_t *job, char *str) +static void fig_comment(GVJ_t *job, char *str) { - figgen_printf(job, "# %s\n", str); + core_printf(job, "# %s\n", str); } -static void figgen_begin_graph(GVJ_t * job) +static void fig_begin_graph(GVJ_t * job) { obj_state_t *obj = job->obj; - figgen_fputs(job, "#FIG 3.2\n"); - figgen_printf(job, "# Generated by %s version %s (%s)\n", + core_fputs(job, "#FIG 3.2\n"); + core_printf(job, "# Generated by %s version %s (%s)\n", job->common->info[0], job->common->info[1], job->common->info[2]); - figgen_printf(job, "# For: %s\n", job->common->user); - figgen_printf(job, "# Title: %s\n", obj->u.g->name); - figgen_printf(job, "# Pages: %d\n", job->pagesArraySize.x * job->pagesArraySize.y); - figgen_fputs(job, "Portrait\n"); /* orientation */ - figgen_fputs(job, "Center\n"); /* justification */ - figgen_fputs(job, "Inches\n"); /* units */ - figgen_fputs(job, "Letter\n"); /* papersize */ - figgen_fputs(job, "100.00\n"); /* magnification % */ - figgen_fputs(job, "Single\n"); /* multiple-page */ - figgen_fputs(job, "-2\n"); /* transparent color (none) */ - figgen_fputs(job, "1200"); /* resolution */ - figgen_fputs(job, " 2\n"); /* coordinate system (upper left) */ + core_printf(job, "# For: %s\n", job->common->user); + core_printf(job, "# Title: %s\n", obj->u.g->name); + core_printf(job, "# Pages: %d\n", job->pagesArraySize.x * job->pagesArraySize.y); + core_fputs(job, "Portrait\n"); /* orientation */ + core_fputs(job, "Center\n"); /* justification */ + core_fputs(job, "Inches\n"); /* units */ + core_fputs(job, "Letter\n"); /* papersize */ + core_fputs(job, "100.00\n"); /* magnification % */ + core_fputs(job, "Single\n"); /* multiple-page */ + core_fputs(job, "-2\n"); /* transparent color (none) */ + core_fputs(job, "1200"); /* resolution */ + core_fputs(job, " 2\n"); /* coordinate system (upper left) */ } -static void figgen_end_graph(GVJ_t * job) +static void fig_end_graph(GVJ_t * job) { - figgen_fputs(job, "# end of FIG file\n"); + core_fputs(job, "# end of FIG file\n"); } -static void figgen_begin_page(GVJ_t * job) +static void fig_begin_page(GVJ_t * job) { Depth = 2; } -static void figgen_begin_node(GVJ_t * job) +static void fig_begin_node(GVJ_t * job) { Depth = 1; } -static void figgen_end_node(GVJ_t * job) +static void fig_end_node(GVJ_t * job) { Depth = 2; } -static void figgen_begin_edge(GVJ_t * job) +static void fig_begin_edge(GVJ_t * job) { Depth = 0; } -static void figgen_end_edge(GVJ_t * job) +static void fig_end_edge(GVJ_t * job) { Depth = 2; } -static void figgen_textpara(GVJ_t * job, pointf p, textpara_t * para) +static void fig_textpara(GVJ_t * job, pointf p, textpara_t * para) { obj_state_t *obj = job->obj; @@ -307,14 +280,14 @@ static void figgen_textpara(GVJ_t * job, pointf p, textpara_t * para) break; } - figgen_printf(job, + core_printf(job, "%d %d %d %d %d %d %.1f %.4f %d %.1f %.1f %d %d %s\\001\n", object_code, sub_type, color, depth, pen_style, font, font_size, angle, font_flags, height, length, ROUND(p.x), ROUND(p.y), fig_string(para->str)); } -static void figgen_ellipse(GVJ_t * job, pointf * A, int filled) +static void fig_ellipse(GVJ_t * job, pointf * A, int filled) { obj_state_t *obj = job->obj; @@ -333,7 +306,7 @@ static void figgen_ellipse(GVJ_t * job, pointf * A, int filled) int center_x, center_y, radius_x, radius_y; int start_x, start_y, end_x, end_y; - figgen_line_style(obj, &line_style, &style_val); + fig_line_style(obj, &line_style, &style_val); start_x = center_x = ROUND(A[0].x); start_y = center_y = ROUND(A[0].y); @@ -342,7 +315,7 @@ static void figgen_ellipse(GVJ_t * job, pointf * A, int filled) end_x = ROUND(A[1].x); end_y = ROUND(A[1].y); - figgen_printf(job, + core_printf(job, "%d %d %d %d %d %d %d %d %d %.3f %d %.4f %d %d %d %d %d %d %d %d\n", object_code, sub_type, line_style, thickness, pen_color, fill_color, depth, pen_style, area_fill, style_val, direction, @@ -350,7 +323,7 @@ static void figgen_ellipse(GVJ_t * job, pointf * A, int filled) start_y, end_x, end_y); } -static void figgen_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, +static void fig_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, int arrow_at_end, int filled) { obj_state_t *obj = job->obj; @@ -384,7 +357,7 @@ static void figgen_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, 1) * 20 * sizeof(char)); buf = buffer; - figgen_line_style(obj, &line_style, &style_val); + fig_line_style(obj, &line_style, &style_val); if (filled) { sub_type = 5; /* closed X-spline */ @@ -419,7 +392,7 @@ static void figgen_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, } } - figgen_printf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d\n", + core_printf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d\n", object_code, sub_type, line_style, @@ -431,15 +404,15 @@ static void figgen_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, area_fill, style_val, cap_style, forward_arrow, backward_arrow, count); - figgen_printf(job, " %s\n", buffer); /* print points */ + core_printf(job, " %s\n", buffer); /* print points */ free(buffer); for (i = 0; i < count; i++) { - figgen_printf(job, " %d", i % (count - 1) ? 1 : 0); /* -1 on all */ + core_printf(job, " %d", i % (count - 1) ? 1 : 0); /* -1 on all */ } - figgen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void figgen_polygon(GVJ_t * job, pointf * A, int n, int filled) +static void fig_polygon(GVJ_t * job, pointf * A, int n, int filled) { obj_state_t *obj = job->obj; @@ -460,9 +433,9 @@ static void figgen_polygon(GVJ_t * job, pointf * A, int n, int filled) int backward_arrow = 0; int npoints = n + 1; - figgen_line_style(obj, &line_style, &style_val); + fig_line_style(obj, &line_style, &style_val); - figgen_printf(job, + core_printf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n", object_code, sub_type, line_style, thickness, pen_color, fill_color, depth, pen_style, area_fill, style_val, join_style, @@ -470,7 +443,7 @@ static void figgen_polygon(GVJ_t * job, pointf * A, int n, int filled) figptarray(job, A, n, 1); /* closed shape */ } -static void figgen_polyline(GVJ_t * job, pointf * A, int n) +static void fig_polyline(GVJ_t * job, pointf * A, int n) { obj_state_t *obj = job->obj; @@ -491,9 +464,9 @@ static void figgen_polyline(GVJ_t * job, pointf * A, int n) int backward_arrow = 0; int npoints = n; - figgen_line_style(obj, &line_style, &style_val); + fig_line_style(obj, &line_style, &style_val); - figgen_printf(job, + core_printf(job, "%d %d %d %d %d %d %d %d %d %.1f %d %d %d %d %d %d\n", object_code, sub_type, line_style, thickness, pen_color, fill_color, depth, pen_style, area_fill, style_val, join_style, @@ -501,44 +474,44 @@ static void figgen_polyline(GVJ_t * job, pointf * A, int n) figptarray(job, A, n, 0); /* open shape */ } -gvrender_engine_t figgen_engine = { - 0, /* figgen_begin_job */ - 0, /* figgen_end_job */ - figgen_begin_graph, - figgen_end_graph, - 0, /* figgen_begin_layer */ - 0, /* figgen_end_layer */ - figgen_begin_page, - 0, /* figgen_end_page */ - 0, /* figgen_begin_cluster */ - 0, /* figgen_end_cluster */ - 0, /* figgen_begin_nodes */ - 0, /* figgen_end_nodes */ - 0, /* figgen_begin_edges */ - 0, /* figgen_end_edges */ - figgen_begin_node, - figgen_end_node, - figgen_begin_edge, - figgen_end_edge, - 0, /* figgen_begin_anchor */ - 0, /* figgen_end_anchor */ - figgen_textpara, - figgen_resolve_color, - figgen_ellipse, - figgen_polygon, - figgen_bezier, - figgen_polyline, - figgen_comment +gvrender_engine_t fig_engine = { + 0, /* fig_begin_job */ + 0, /* fig_end_job */ + fig_begin_graph, + fig_end_graph, + 0, /* fig_begin_layer */ + 0, /* fig_end_layer */ + fig_begin_page, + 0, /* fig_end_page */ + 0, /* fig_begin_cluster */ + 0, /* fig_end_cluster */ + 0, /* fig_begin_nodes */ + 0, /* fig_end_nodes */ + 0, /* fig_begin_edges */ + 0, /* fig_end_edges */ + fig_begin_node, + fig_end_node, + fig_begin_edge, + fig_end_edge, + 0, /* fig_begin_anchor */ + 0, /* fig_end_anchor */ + fig_textpara, + fig_resolve_color, + fig_ellipse, + fig_polygon, + fig_bezier, + fig_polyline, + fig_comment }; /* NB. List must be LANG_C sorted */ -static char *figgen_knowncolors[] = { +static char *fig_knowncolors[] = { "black", "blue", "cyan", "green", "magenta", "red", "white", "yellow", }; -gvrender_features_t figgen_features = { +gvrender_features_t fig_features = { EMIT_COLORS | GVRENDER_Y_GOES_DOWN, /* flags */ DEFAULT_EMBED_MARGIN, /* default margin - points */ @@ -547,16 +520,16 @@ gvrender_features_t figgen_features = { * It was picked to make .png usershapes the right size on my screen. * It happens to be 1.2 * 1200, but I can't explain the 1.2. * (I was expecting 1.3333 which is 96/72, but thats too big.) - * Also 1200 is hardcoded in figgen_begin_graph() instead of using job->dpi + * Also 1200 is hardcoded in fig_begin_graph() instead of using job->dpi */ - figgen_knowncolors, /* knowncolors */ - sizeof(figgen_knowncolors) / sizeof(char *), /* sizeof knowncolors */ + fig_knowncolors, /* knowncolors */ + sizeof(fig_knowncolors) / sizeof(char *), /* sizeof knowncolors */ RGBA_BYTE, /* color_type */ NULL, /* device */ "fig", /* gvloadimage target for usershapes */ }; gvplugin_installed_t gvrender_core_fig_types[] = { - {FORMAT_FIG, "fig", 1, &figgen_engine, &figgen_features}, + {FORMAT_FIG, "fig", 1, &fig_engine, &fig_features}, {0, NULL, 0, NULL, NULL} }; diff --git a/plugin/core/gvrender_core_map.c b/plugin/core/gvrender_core_map.c index 37942d60e..e9d2769b8 100644 --- a/plugin/core/gvrender_core_map.c +++ b/plugin/core/gvrender_core_map.c @@ -24,13 +24,14 @@ #include "graph.h" extern char *xml_string(char *str); +extern void core_fputs(GVJ_t * job, char *s); +extern void core_printf(GVJ_t * job, const char *format, ...); typedef enum { FORMAT_IMAP, FORMAT_ISMAP, FORMAT_CMAP, FORMAT_CMAPX, } format_type; static void map_output_shape (GVJ_t *job, map_shape_t map_shape, pointf * AF, int nump, char* url, char *tooltip, char *target) { - FILE *out = job->output_file; int i; static point *A; @@ -50,18 +51,18 @@ static void map_output_shape (GVJ_t *job, map_shape_t map_shape, pointf * AF, in switch (map_shape) { case MAP_RECTANGLE: /* Y_GOES_DOWN so need UL to LR */ - fprintf(out, "rect %s %d,%d %d,%d\n", url, + core_printf(job, "rect %s %d,%d %d,%d\n", url, A[0].x, A[1].y, A[1].x, A[0].y); break; case MAP_CIRCLE: - fprintf(out, "circle %s %d,%d,%d\n", url, + core_printf(job, "circle %s %d,%d,%d\n", url, A[0].x, A[0].y, A[1].x-A[0].x); break; case MAP_POLYGON: - fprintf(out, "poly %s", url); + core_printf(job, "poly %s", url); for (i = 0; i < nump; i++) - fprintf(out, " %d,%d", A[i].x, A[i].y); - fprintf(out, "\n"); + core_printf(job, " %d,%d", A[i].x, A[i].y); + core_fputs(job, "\n"); break; default: assert(0); @@ -72,7 +73,7 @@ static void map_output_shape (GVJ_t *job, map_shape_t map_shape, pointf * AF, in switch (map_shape) { case MAP_RECTANGLE: /* Y_GOES_DOWN so need UL to LR */ - fprintf(out, "rectangle (%d,%d) (%d,%d) %s %s\n", + core_printf(job, "rectangle (%d,%d) (%d,%d) %s %s\n", A[0].x, A[1].y, A[1].x, A[0].y, url, tooltip); break; default: @@ -83,24 +84,31 @@ static void map_output_shape (GVJ_t *job, map_shape_t map_shape, pointf * AF, in } else if (job->render.id == FORMAT_CMAP || job->render.id == FORMAT_CMAPX) { switch (map_shape) { case MAP_CIRCLE: - fprintf(out, "render.id == FORMAT_CMAPX) - fprintf(out, "\"/>\n"); + core_fputs(job, "\"/>\n"); else - fprintf(out, "\">\n"); + core_fputs(job, "\">\n"); } } static void map_begin_page(GVJ_t * job) { obj_state_t *obj = job->obj; - char *name = xml_string(obj->u.g->name); + char *s; switch (job->render.id) { case FORMAT_IMAP: - fprintf(job->output_file, "base referer\n"); - if (obj->url && obj->url[0]) - fprintf(job->output_file, "default %s\n", obj->url); + core_fputs(job, "base referer\n"); + if (obj->url && obj->url[0]) { + core_fputs(job, "default "); + core_fputs(job, xml_string(obj->url)); + core_fputs(job, "\n"); + } break; case FORMAT_ISMAP: - if (obj->url && obj->url[0]) - fprintf(job->output_file, "default %s %s\n", obj->url, obj->u.g->name); + if (obj->url && obj->url[0]) { + core_fputs(job, "default "); + core_fputs(job, xml_string(obj->url)); + core_fputs(job, " "); + core_fputs(job, xml_string(obj->u.g->name)); + core_fputs(job, "\n"); + } break; case FORMAT_CMAPX: - fprintf(job->output_file, "\n", name, name); + s = xml_string(obj->u.g->name); + core_fputs(job, "\n"); break; default: break; @@ -172,7 +193,7 @@ static void map_end_page(GVJ_t * job) case FORMAT_CMAPX: map_output_shape(job, obj->url_map_shape, obj->url_map_p,obj->url_map_n, obj->url, obj->tooltip, obj->target); - fprintf(job->output_file, "\n"); + core_fputs(job, "\n"); break; default: break; @@ -183,7 +204,7 @@ static void map_begin_cluster(GVJ_t * job) { obj_state_t *obj = job->obj; - fprintf(job->output_file, "%% %s\n", obj->u.sg->name); + core_printf(job, "%% %s\n", obj->u.sg->name); map_output_shape(job, obj->url_map_shape, obj->url_map_p, obj->url_map_n, obj->url, obj->tooltip, obj->target); diff --git a/plugin/core/gvrender_core_ps.c b/plugin/core/gvrender_core_ps.c index a64e97db6..9c0dabed3 100644 --- a/plugin/core/gvrender_core_ps.c +++ b/plugin/core/gvrender_core_ps.c @@ -24,9 +24,11 @@ #ifdef HAVE_LIBZ #include +#endif + #ifdef WIN32 #include -#endif +#include "compat.h" #endif #include "gvplugin_render.h" diff --git a/plugin/core/gvrender_core_svg.c b/plugin/core/gvrender_core_svg.c index fd7461446..f23ee57dd 100644 --- a/plugin/core/gvrender_core_svg.c +++ b/plugin/core/gvrender_core_svg.c @@ -18,22 +18,10 @@ #include "config.h" #endif -#ifdef WIN32 -#include -#include -#endif - #include #include #include -#ifdef HAVE_LIBZ -#include -#endif -#ifdef WIN32 -#include -#endif - #include "macros.h" #include "const.h" @@ -43,60 +31,24 @@ typedef enum { FORMAT_SVG, FORMAT_SVGZ, } format_type; extern char *xml_string(char *str); +extern void core_init_compression(GVJ_t * job, compression_t compression); +extern void core_fini_compression(GVJ_t * job); +extern void core_fputs(GVJ_t * job, char *s); +extern void core_printf(GVJ_t * job, const char *format, ...); /* SVG dash array */ static char *sdarray = "5,2"; /* SVG dot array */ static char *sdotarray = "1,5"; -void svggen_fputs(GVJ_t * job, char *s) -{ - int len; - - len = strlen(s); - switch (job->render.id) { - case FORMAT_SVGZ: -#ifdef HAVE_LIBZ - gzwrite((gzFile *) (job->output_file), s, (unsigned) len); -#endif - break; - case FORMAT_SVG: - fwrite(s, sizeof(char), (unsigned) len, job->output_file); - break; - } -} - -/* svggen_printf: - * Note that this function is unsafe due to the fixed buffer size. - * It should only be used when the caller is sure the input will not - * overflow the buffer. In particular, it should be avoided for - * input coming from users. Also, if vsnprintf is available, the - * code should check for return values to use it safely. - */ -void svggen_printf(GVJ_t * job, const char *format, ...) -{ - char buf[BUFSIZ]; - va_list argp; - - va_start(argp, format); -#ifdef HAVE_VSNPRINTF - (void) vsnprintf(buf, sizeof(buf), format, argp); -#else - (void) vsprintf(buf, format, argp); -#endif - va_end(argp); - - svggen_fputs(job, buf); -} - -static void svggen_bzptarray(GVJ_t * job, pointf * A, int n) +static void svg_bzptarray(GVJ_t * job, pointf * A, int n) { int i; char c; c = 'M'; /* first point */ for (i = 0; i < n; i++) { - svggen_printf(job, "%c%g,%g", c, A[i].x, -A[i].y); + core_printf(job, "%c%g,%g", c, A[i].x, -A[i].y); if (i == 0) c = 'C'; /* second point */ else @@ -104,17 +56,17 @@ static void svggen_bzptarray(GVJ_t * job, pointf * A, int n) } } -static void svggen_print_color(GVJ_t * job, gvcolor_t color) +static void svg_print_color(GVJ_t * job, gvcolor_t color) { switch (color.type) { case COLOR_STRING: - svggen_fputs(job, color.u.string); + core_fputs(job, color.u.string); break; case RGBA_BYTE: if (color.u.rgba[3] == 0) /* transparent */ - svggen_fputs(job, "none"); + core_fputs(job, "none"); else - svggen_printf(job, "#%02x%02x%02x", + core_printf(job, "#%02x%02x%02x", color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]); break; default: @@ -122,336 +74,297 @@ static void svggen_print_color(GVJ_t * job, gvcolor_t color) } } -static void svggen_grstyle(GVJ_t * job, int filled) +static void svg_grstyle(GVJ_t * job, int filled) { obj_state_t *obj = job->obj; - svggen_fputs(job, " style=\"fill:"); + core_fputs(job, " style=\"fill:"); if (filled) - svggen_print_color(job, obj->fillcolor); + svg_print_color(job, obj->fillcolor); else - svggen_fputs(job, "none"); - svggen_fputs(job, ";stroke:"); - svggen_print_color(job, obj->pencolor); + core_fputs(job, "none"); + core_fputs(job, ";stroke:"); + svg_print_color(job, obj->pencolor); if (obj->penwidth != PENWIDTH_NORMAL) - svggen_printf(job, ";stroke-width:%g", obj->penwidth); + core_printf(job, ";stroke-width:%g", obj->penwidth); if (obj->pen == PEN_DASHED) { - svggen_printf(job, ";stroke-dasharray:%s", sdarray); + core_printf(job, ";stroke-dasharray:%s", sdarray); } else if (obj->pen == PEN_DOTTED) { - svggen_printf(job, ";stroke-dasharray:%s", sdotarray); + core_printf(job, ";stroke-dasharray:%s", sdotarray); } - svggen_fputs(job, ";\""); + core_fputs(job, ";\""); } -static void svggen_comment(GVJ_t * job, char *str) +static void svg_comment(GVJ_t * job, char *str) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void svggen_begin_job(GVJ_t * job) +static void svg_begin_job(GVJ_t * job) { -#if HAVE_LIBZ - int fd; -#endif - switch (job->render.id) { case FORMAT_SVGZ: -#if HAVE_LIBZ - /* open dup so can gzclose independent of FILE close */ - fd = dup(fileno(job->output_file)); -#ifdef HAVE_SETMODE -#ifdef O_BINARY - /* - * Windows will do \n -> \r\n translations on - * stdout unless told otherwise. - */ - setmode(fd, O_BINARY); -#endif -#endif - - job->output_file = (FILE *) (gzdopen(fd, "wb")); - if (!job->output_file) { - (job->common->errorfn) ("Error opening compressed output file\n"); - exit(1); - } + core_init_compression(job, COMPRESSION_ZLIB); break; -#else - (job->common->errorfn) ("No libz support.\n"); - exit(1); -#endif case FORMAT_SVG: + core_init_compression(job, COMPRESSION_NONE); break; } - svggen_fputs(job, - "\n"); - svggen_fputs(job, - "\n"); + core_fputs(job, "\n]"); - - svggen_fputs(job, ">\n\n"); + core_fputs(job, " [\n \n]"); + + core_fputs(job, ">\n\n"); } -static void svggen_begin_graph(GVJ_t * job) +static void svg_begin_graph(GVJ_t * job) { obj_state_t *obj = job->obj; - svggen_fputs(job, "\n", job->pagesArraySize.x * job->pagesArraySize.y); + core_printf(job, " Pages: %d -->\n", job->pagesArraySize.x * job->pagesArraySize.y); - svggen_printf(job, "width, job->height); /* namespace of svg */ - svggen_fputs(job, " xmlns=\"http://www.w3.org/2000/svg\""); + core_fputs(job, " xmlns=\"http://www.w3.org/2000/svg\""); /* namespace of xlink */ - svggen_fputs(job, " xmlns:xlink=\"http://www.w3.org/1999/xlink\""); - svggen_fputs(job, ">\n"); + core_fputs(job, " xmlns:xlink=\"http://www.w3.org/1999/xlink\""); + core_fputs(job, ">\n"); } -static void svggen_end_graph(GVJ_t * job) +static void svg_end_graph(GVJ_t * job) { - svggen_fputs(job, "\n"); - switch (job->render.id) { - case FORMAT_SVGZ: -#ifdef HAVE_LIBZ - gzclose((gzFile *) (job->output_file)); - break; -#else - (job->common->errorfn) ("No libz support\n"); - exit(1); -#endif - case FORMAT_SVG: - break; - } + core_fputs(job, "\n"); + core_fini_compression(job); } -static void svggen_begin_layer(GVJ_t * job, char *layername, int layerNum, int numLayers) +static void svg_begin_layer(GVJ_t * job, char *layername, int layerNum, int numLayers) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void svggen_end_layer(GVJ_t * job) +static void svg_end_layer(GVJ_t * job) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void svggen_begin_page(GVJ_t * job) +static void svg_begin_page(GVJ_t * job) { obj_state_t *obj = job->obj; /* its really just a page of the graph, but its still a graph, * and it is the entire graph if we're not currently paging */ - svggen_printf(job, "common->viewNum); - svggen_printf(job, " transform=\"scale(%g %g) rotate(%d) translate(%g %g)\">\n", + core_printf(job, "common->viewNum); + core_printf(job, " transform=\"scale(%g %g) rotate(%d) translate(%g %g)\">\n", job->scale.x, job->scale.y, -job->rotation, job->translation.x, -job->translation.y); /* default style */ if (obj->u.g->name[0]) { - svggen_fputs(job, ""); - svggen_fputs(job, xml_string(obj->u.g->name)); - svggen_fputs(job, "\n"); + core_fputs(job, ""); + core_fputs(job, xml_string(obj->u.g->name)); + core_fputs(job, "\n"); } } -static void svggen_end_page(GVJ_t * job) +static void svg_end_page(GVJ_t * job) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void svggen_begin_cluster(GVJ_t * job) +static void svg_begin_cluster(GVJ_t * job) { obj_state_t *obj = job->obj; - svggen_printf(job, "", + core_printf(job, "", obj->u.sg->meta_node->id); - svggen_fputs(job, ""); - svggen_fputs(job, xml_string(obj->u.sg->name)); - svggen_fputs(job, "\n"); + core_fputs(job, ""); + core_fputs(job, xml_string(obj->u.sg->name)); + core_fputs(job, "\n"); } -static void svggen_end_cluster(GVJ_t * job) +static void svg_end_cluster(GVJ_t * job) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void svggen_begin_node(GVJ_t * job) +static void svg_begin_node(GVJ_t * job) { obj_state_t *obj = job->obj; - svggen_printf(job, "", obj->u.n->id); - svggen_fputs(job, ""); - svggen_fputs(job, xml_string(obj->u.n->name)); - svggen_fputs(job, "\n"); + core_printf(job, "", obj->u.n->id); + core_fputs(job, ""); + core_fputs(job, xml_string(obj->u.n->name)); + core_fputs(job, "\n"); } -static void svggen_end_node(GVJ_t * job) +static void svg_end_node(GVJ_t * job) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } static void -svggen_begin_edge(GVJ_t * job) +svg_begin_edge(GVJ_t * job) { obj_state_t *obj = job->obj; char *edgeop; - svggen_printf(job, "", obj->u.e->id); + core_printf(job, "", obj->u.e->id); if (obj->u.e->tail->graph->root->kind & AGFLAG_DIRECTED) edgeop = "->"; else edgeop = "--"; - svggen_fputs(job, ""); - svggen_fputs(job, xml_string(obj->u.e->tail->name)); - svggen_fputs(job, edgeop); - /* can't do this in single svggen_printf because + core_fputs(job, "<title>"); + core_fputs(job, xml_string(obj->u.e->tail->name)); + core_fputs(job, edgeop); + /* can't do this in single core_printf because * xml_string's buffer gets reused. */ - svggen_fputs(job, xml_string(obj->u.e->head->name)); - svggen_fputs(job, "\n"); + core_fputs(job, xml_string(obj->u.e->head->name)); + core_fputs(job, "\n"); } -static void svggen_end_edge(GVJ_t * job) +static void svg_end_edge(GVJ_t * job) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } static void -svggen_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target) +svg_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target) { - svggen_fputs(job, "\n"); + core_printf(job, " target=\"%s\"", xml_string(target)); + core_fputs(job, ">\n"); } -static void svggen_end_anchor(GVJ_t * job) +static void svg_end_anchor(GVJ_t * job) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void svggen_textpara(GVJ_t * job, pointf p, textpara_t * para) +static void svg_textpara(GVJ_t * job, pointf p, textpara_t * para) { obj_state_t *obj = job->obj; - svggen_fputs(job, "just) { case 'l': - svggen_fputs(job, " text-anchor=\"start\""); + core_fputs(job, " text-anchor=\"start\""); break; case 'r': - svggen_fputs(job, " text-anchor=\"end\""); + core_fputs(job, " text-anchor=\"end\""); break; default: case 'n': - svggen_fputs(job, " text-anchor=\"middle\""); + core_fputs(job, " text-anchor=\"middle\""); break; } - svggen_printf(job, " x=\"%g\" y=\"%g\"", p.x, -p.y); - svggen_fputs(job, " style=\""); + core_printf(job, " x=\"%g\" y=\"%g\"", p.x, -p.y); + core_fputs(job, " style=\""); if (para->postscript_alias) { - svggen_printf(job, "font-family:%s;", para->postscript_alias->family); + core_printf(job, "font-family:%s;", para->postscript_alias->family); if (para->postscript_alias->weight) - svggen_printf(job, "font-weight:%s;", para->postscript_alias->weight); + core_printf(job, "font-weight:%s;", para->postscript_alias->weight); if (para->postscript_alias->stretch) - svggen_printf(job, "font-stretch:%s;", para->postscript_alias->stretch); + core_printf(job, "font-stretch:%s;", para->postscript_alias->stretch); if (para->postscript_alias->style) - svggen_printf(job, "font-style:%s;", para->postscript_alias->style); + core_printf(job, "font-style:%s;", para->postscript_alias->style); } else { - svggen_printf(job, "font:%s;", para->fontname); + core_printf(job, "font:%s;", para->fontname); } - svggen_printf(job, "font-size:%.2fpx;", para->fontsize); + core_printf(job, "font-size:%.2fpx;", para->fontsize); switch (obj->pencolor.type) { case COLOR_STRING: if (strcasecmp(obj->pencolor.u.string, "black")) - svggen_printf(job, "fill:%s;", obj->pencolor.u.string); + core_printf(job, "fill:%s;", obj->pencolor.u.string); break; case RGBA_BYTE: - svggen_printf(job, "fill:#%02x%02x%02x;", + core_printf(job, "fill:#%02x%02x%02x;", obj->pencolor.u.rgba[0], obj->pencolor.u.rgba[1], obj->pencolor.u.rgba[2]); break; default: assert(0); /* internal error */ } - svggen_fputs(job, "\">"); - svggen_fputs(job, xml_string(para->str)); - svggen_fputs(job, "\n"); + core_fputs(job, "\">"); + core_fputs(job, xml_string(para->str)); + core_fputs(job, "\n"); } -static void svggen_ellipse(GVJ_t * job, pointf * A, int filled) +static void svg_ellipse(GVJ_t * job, pointf * A, int filled) { /* A[] contains 2 points: the center and corner. */ - svggen_fputs(job, "\n"); + core_fputs(job, "/>\n"); } static void -svggen_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, +svg_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, int arrow_at_end, int filled) { - svggen_fputs(job, "\n"); + core_fputs(job, "\n"); } -static void svggen_polygon(GVJ_t * job, pointf * A, int n, int filled) +static void svg_polygon(GVJ_t * job, pointf * A, int n, int filled) { int i; - svggen_fputs(job, "\n"); + core_printf(job, "%g,%g ", A[i].x, -A[i].y); + core_printf(job, "%g,%g", A[0].x, -A[0].y); /* because Adobe SVG is broken */ + core_fputs(job, "\"/>\n"); } -static void svggen_polyline(GVJ_t * job, pointf * A, int n) +static void svg_polyline(GVJ_t * job, pointf * A, int n) { int i; - svggen_fputs(job, "\n"); + core_printf(job, "%g,%g ", A[i].x, -A[i].y); + core_fputs(job, "\"/>\n"); } /* color names from http://www.w3.org/TR/SVG/types.html */ /* NB. List must be LANG_C sorted */ -static char *svggen_knowncolors[] = { +static char *svg_knowncolors[] = { "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "burlywood", @@ -494,37 +407,37 @@ static char *svggen_knowncolors[] = { "yellow", "yellowgreen" }; -gvrender_engine_t svggen_engine = { - svggen_begin_job, - 0, /* svggen_end_job */ - svggen_begin_graph, - svggen_end_graph, - svggen_begin_layer, - svggen_end_layer, - svggen_begin_page, - svggen_end_page, - svggen_begin_cluster, - svggen_end_cluster, - 0, /* svggen_begin_nodes */ - 0, /* svggen_end_nodes */ - 0, /* svggen_begin_edges */ - 0, /* svggen_end_edges */ - svggen_begin_node, - svggen_end_node, - svggen_begin_edge, - svggen_end_edge, - svggen_begin_anchor, - svggen_end_anchor, - svggen_textpara, - 0, /* svggen_resolve_color */ - svggen_ellipse, - svggen_polygon, - svggen_bezier, - svggen_polyline, - svggen_comment, +gvrender_engine_t svg_engine = { + svg_begin_job, + 0, /* svg_end_job */ + svg_begin_graph, + svg_end_graph, + svg_begin_layer, + svg_end_layer, + svg_begin_page, + svg_end_page, + svg_begin_cluster, + svg_end_cluster, + 0, /* svg_begin_nodes */ + 0, /* svg_end_nodes */ + 0, /* svg_begin_edges */ + 0, /* svg_end_edges */ + svg_begin_node, + svg_end_node, + svg_begin_edge, + svg_end_edge, + svg_begin_anchor, + svg_end_anchor, + svg_textpara, + 0, /* svg_resolve_color */ + svg_ellipse, + svg_polygon, + svg_bezier, + svg_polyline, + svg_comment, }; -gvrender_features_t svggen_features = { +gvrender_features_t svg_features = { GVRENDER_DOES_TRUECOLOR | GVRENDER_Y_GOES_DOWN | GVRENDER_DOES_TRANSFORM @@ -534,17 +447,17 @@ gvrender_features_t svggen_features = { | GVRENDER_DOES_TOOLTIPS, /* flags */ DEFAULT_EMBED_MARGIN, /* default margin - points */ {96.,96.}, /* default dpi */ - svggen_knowncolors, /* knowncolors */ - sizeof(svggen_knowncolors) / sizeof(char *), /* sizeof knowncolors */ + svg_knowncolors, /* knowncolors */ + sizeof(svg_knowncolors) / sizeof(char *), /* sizeof knowncolors */ RGBA_BYTE, /* color_type */ NULL, /* device */ "svg", /* gvloadimage target for usershapes */ }; gvplugin_installed_t gvrender_core_svg_types[] = { - {FORMAT_SVG, "svg", 1, &svggen_engine, &svggen_features}, + {FORMAT_SVG, "svg", 1, &svg_engine, &svg_features}, #if HAVE_LIBZ - {FORMAT_SVGZ, "svgz", 1, &svggen_engine, &svggen_features}, + {FORMAT_SVGZ, "svgz", 1, &svg_engine, &svg_features}, #endif {0, NULL, 0, NULL, NULL} }; diff --git a/tclpkg/tcldot/tcldot.c b/tclpkg/tcldot/tcldot.c index 78fadd041..6c1e77f01 100644 --- a/tclpkg/tcldot/tcldot.c +++ b/tclpkg/tcldot/tcldot.c @@ -606,9 +606,9 @@ static void tcldot_layout(GVC_t *gvc, Agraph_t * g, char *engine) static int graphcmd(ClientData clientData, Tcl_Interp * interp, #ifndef TCLOBJ int argc, char *argv[] -#else /* TCLOBJ */ +#else int argc, Tcl_Obj * CONST objv[] -#endif /* TCLOBJ */ +#endif ) { @@ -621,6 +621,7 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp, unsigned long id; ClientData outfp; GVC_t *gvc = (GVC_t *) clientData; + GVJ_t *job = gvc->job; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", @@ -1089,10 +1090,10 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp, (char *) 0); return TCL_ERROR; } - gvc->active_jobs = gvc->job; + gvc->active_jobs = job; - gvc->job->surface = (void *)(&tkgendata); - gvc->job->external_surface = TRUE; + job->surface = (void *)(&tkgendata); + job->external_surface = TRUE; /* make sure that layout is done */ g = g->root; @@ -1121,14 +1122,14 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp, (char *) 0); return TCL_ERROR; } - gvc->active_jobs = gvc->job; + gvc->active_jobs = job; if (! (hdl = tclhandleXlate(GDHandleTable, argv[2]))) { Tcl_AppendResult(interp, "GD Image not found.", (char *) NULL); return TCL_ERROR; } - gvc->job->surface = *hdl; - gvc->job->external_surface = TRUE; + job->surface = *hdl; + job->external_surface = TRUE; /* make sure that layout is done */ g = g->root; @@ -1260,20 +1261,18 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp, "\". Use one of:", s, (char *)NULL); return TCL_ERROR; } - gvc->active_jobs = gvc->job; + gvc->active_jobs = job; /* populate new job struct with output language and output file data */ - gvc->job->output_lang = - gvrender_select(gvc->job, gvc->job->output_langname); + job->output_lang = gvrender_select(job, job->output_langname); if (Tcl_GetOpenFile (interp, argv[2], 1, 1, &outfp) != TCL_OK) return TCL_ERROR; - gvc->job->output_file = (FILE *)outfp; - gvc->job->output_filename = NULL; + job->output_file = (FILE *)outfp; + job->output_filename = NULL; /* make sure that layout is done - unless canonical output */ - if ((!GD_drawing(g) || argc > 4) - && gvc->job->output_lang != CANONICAL_DOT) { + if ((!GD_drawing(g) || argc > 4) && !(job->flags & LAYOUT_NOT_REQUIRED)) { tcldot_layout(gvc, g, (argc > 4) ? argv[4] : (char *) NULL); }