/* This software may only be used by you under license from AT&T Corp. ("AT&T"). A copy of AT&T's Source Code Agreement is available at AT&T's Internet website having the URL: If you received this software without first entering into a license with AT&T, you have an infringing copy of this software and cannot use it without violating AT&T's intellectual property rights. */ #pragma prototyped #include "render.h" #include "utils.h" #define NONE 0 #define NODE 1 #define EDGE 2 #define CLST 3 /* MIF font modifiers */ #define REGULAR 0 #define BOLD 1 #define ITALIC 2 /* MIF patterns */ #define P_SOLID 0 #define P_NONE 15 #define P_DOTTED 4 /* i wasn't sure about this */ #define P_DASHED 11 /* or this */ /* MIF bold line constant */ #define WIDTH_NORMAL 1 #define WIDTH_BOLD 3 static int N_pages; /* static point Pages; */ static double Scale; static int Rot; static box PB; static int onetime = TRUE; typedef struct context_t { char color_ix,*fontfam,fontopt,font_was_set; char pen,fill,penwidth,style_was_set; double fontsz; } context_t; #define MAXNEST 4 static context_t cstk[MAXNEST]; static int SP; static char *FillStr = ""; static char *NoFillStr = ""; static void mif_reset(void) { onetime = TRUE; } static void init_mif(void) { SP = 0; cstk[0].color_ix = 0; /* MIF color index 0-7 */ cstk[0].fontfam = "Times"; /* font family name */ cstk[0].fontopt = REGULAR; /* modifier: REGULAR, BOLD or ITALIC */ cstk[0].pen = P_SOLID; /* pen pattern style, default is solid */ cstk[0].fill = P_NONE; cstk[0].penwidth = WIDTH_NORMAL; } static pointf mifpt(pointf p) { pointf tmp,rv; tmp.x = p.x * Scale; tmp.y = Scale * p.y; if (Rot == 0) { rv.x = tmp.x; rv.y = PB.UR.y - PB.LL.y - tmp.y; } else {rv.x = PB.UR.x - PB.LL.x - tmp.y; rv.y = tmp.x; } return rv; } static void mifptarray(point* A, int n) { int i; pointf p; fprintf(Output_file," \n",n); for (i = 0; i < n; i++) { p.x = A[i].x; p.y = A[i].y; p = mifpt(p); fprintf(Output_file," \n",p.x,p.y); } } static void mif_font(context_t* cp) { char *fw,*fa; fw = fa = "Regular"; switch (cp->fontopt) { case BOLD: fw = "Bold"; break; case ITALIC: fa = "Italic"; break; } fprintf(Output_file," >\n",cp->fontfam,Scale*cp->fontsz,fw,fa); } static void mif_color(int i) { static char *mifcolor[]= { "black","white","red","green","blue","cyan", "magenta","yellow","comment", "aquamarine","plum","peru","pink","mediumpurple","grey", "lightgrey","lightskyblue","lightcoral","yellowgreen", (char*)0}; if (i <= 8) fprintf(Output_file,"\n",i); if (i > 8) fprintf(Output_file, "\n", mifcolor[i]); } static void mif_style(context_t* cp) { fprintf(Output_file," \n", cp->pen,cp->fill,cp->penwidth); } static void mif_comment(void* obj, attrsym_t* sym) { char *str; str = late_string(obj,sym,""); if (str[0]) fprintf(Output_file,"# %s\n",str); } static void mif_begin_job(FILE *ofp, graph_t *g, char **lib, char *user, char *info[], point pages) { /* Pages = pages; */ N_pages = pages.x * pages.y; fprintf(Output_file," # Generated by %s version %s (%s)\n", info[0],info[1],info[2]); fprintf(Output_file,"# For: %s\n",user); fprintf(Output_file,"# Title: %s\n",g->name); fprintf(Output_file,"# Pages: %d\n",N_pages); fprintf(Output_file,"\n"); fprintf(Output_file, "\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " \n"); fprintf(Output_file, " > # end of Color\n"); fprintf(Output_file, "> # end of ColorCatalog\n"); } static void mif_end_job(void) { fprintf(Output_file,"# end of MIFFile\n"); } static void mif_begin_graph(graph_t* g, box bb, point pb) { PB = bb; if (onetime) { fprintf(Output_file,"\n", PB.LL.x,PB.UR.y,PB.UR.x - PB.LL.x, PB.UR.y - PB.LL.y); init_mif(); mif_comment(g,agfindattr(g,"comment")); onetime = FALSE; } } static void mif_end_graph(void) { } static void mif_begin_page(graph_t *g, point page, double scale, int rot, point offset) { /* int page_number; */ /* point sz; */ Scale = scale; Rot = rot; /* page_number = page.x + page.y * Pages.x + 1; */ /* sz = sub_points(PB.UR,PB.LL); */ fprintf(Output_file," >\n",14*Scale); } static void mif_end_page(void) { } static void mif_begin_cluster(graph_t* g) { } static void mif_end_cluster (void) { } static void mif_begin_nodes(void) { } static void mif_end_nodes(void) { } static void mif_begin_edges(void) { } static void mif_end_edges(void) { } static void mif_begin_node(node_t* n) { fprintf(Output_file,"# %s\n",n->name); mif_comment(n,N_comment); } static void mif_end_node (void) { } static void mif_begin_edge (edge_t* e) { fprintf(Output_file,"# %s -> %s\n",e->tail->name,e->head->name); mif_comment(e,E_comment); } static void mif_end_edge (void) { } static void mif_begin_context(void) { assert(SP + 1 < MAXNEST); cstk[SP+1] = cstk[SP]; SP++; } static void mif_end_context(void) { int c, psp = SP - 1; assert(SP > 0); if (cstk[SP].color_ix != (c = cstk[psp].color_ix)) mif_color(c); if (cstk[SP].font_was_set) mif_font(&(cstk[psp])); if (cstk[SP].style_was_set) mif_style(&(cstk[psp])); /*free(cstk[psp].fontfam);*/ SP = psp; } static void mif_set_font(char* name, double size) { char *p,*q; context_t *cp; cp = &(cstk[SP]); cp->font_was_set = TRUE; cp->fontsz = size; p = strdup(name); if ((q = strchr(p,'-'))) { *q++ = 0; if (strcasecmp(q,"italic") == 0) cp->fontopt = ITALIC; else if (strcasecmp(q,"bold") == 0) cp->fontopt = BOLD; } cp->fontfam = p; mif_font(&cstk[SP]); } static void mif_set_color(char* name) { int i; char *tok; static char *mifcolor[]= { "black","white","red","green","blue","cyan", "magenta","yellow","comment", "aquamarine","plum","peru","pink","mediumpurple","grey", "lightgrey", "lightskyblue","lightcoral","yellowgreen", (char*)0}; tok = canontoken(name); for (i = 0; mifcolor[i]; i++) { if (strcasecmp(mifcolor[i],tok) == 0) { cstk[SP].color_ix = i; mif_color(i); return; } } agerr(AGERR, "color %s not supported in MIF\n",name); } static void mif_set_style(char** s) { char *line; context_t *cp; cp = &(cstk[SP]); while ((line = *s++)) { if (streq(line,"solid")) cp->pen = P_SOLID; else if (streq(line,"dashed")) cp->pen = P_DASHED; else if (streq(line,"dotted")) cp->pen = P_DOTTED; else if (streq(line,"invis")) cp->pen = P_NONE; else if (streq(line,"bold")) cp->penwidth = WIDTH_BOLD; else if (streq(line,"filled")) cp->fill = P_SOLID; else if (streq(line,"unfilled")) cp->fill = P_NONE; else { agerr(AGERR, "mif_set_style: unsupported style %s - ignoring\n", line); } cp->style_was_set = TRUE; } if (cp->style_was_set) mif_style(cp); } static char * mif_string(char *s) { static char *buf = NULL; static int bufsize = 0; int pos = 0; char *p, esc; if (!buf) { bufsize = 64; buf = N_GNEW(bufsize,char); } p = buf; while (*s) { if (pos > (bufsize-8)) { bufsize *= 2; buf = grealloc(buf,bufsize); p = buf + pos; } esc = 0; switch (*s) { case '\t': esc = 't'; break; case '>': case '\'': case '`': case '\\': esc = *s; break; } if (esc) { *p++ = '\\'; *p++ = esc; pos += 2; } else { *p++ = *s; pos++; } s++; } *p = '\0'; return buf; } static void mif_textline(point p, textline_t *line) { pointf mp; char *str = line->str; char *anchor; mp.x = p.x; mp.y = p.y - cstk[SP].fontsz/2 + 2; switch(line->just) { case 'l': anchor="Left"; break; case 'r': anchor="Right"; break; default: case 'n': anchor="Center"; break; } mp = mifpt(mp); fprintf(Output_file, " ", Rot,mp.x,mp.y,anchor); fprintf(Output_file," >\n",mif_string(str)); } static void mif_bezier(point* A, int n, int arrow_at_start, int arrow_at_end) { fprintf(Output_file," \n"); mifptarray(A,n); fprintf(Output_file,">\n"); } static void mif_polygon(point *A, int n, int filled) { fprintf(Output_file,"\n"); } static void mif_ellipse(point p, int rx, int ry, int filled) { pointf tl,mp; tl.x = p.x - rx; tl.y = p.y + ry; if (Rot) {int t; t = rx; rx = ry; ry = t;} mp = mifpt(tl); fprintf(Output_file,">\n", filled?FillStr:NoFillStr, mp.x,mp.y,Scale*(rx + rx),Scale*(ry + ry)); } static void mif_polyline(point* A, int n) { fprintf(Output_file,"\n"); mifptarray(A,n); fprintf(Output_file,">\n"); } static void mif_user_shape(char *name, point *A, int n, int filled) { static boolean onetime = TRUE; if (onetime) { agerr(AGERR, "custom shapes not available with this driver\n"); onetime = FALSE; } } codegen_t MIF_CodeGen = { mif_reset, mif_begin_job, mif_end_job, mif_begin_graph, mif_end_graph, mif_begin_page, mif_end_page, mif_begin_cluster, mif_end_cluster, mif_begin_nodes, mif_end_nodes, mif_begin_edges, mif_end_edges, mif_begin_node, mif_end_node, mif_begin_edge, mif_end_edge, mif_begin_context, mif_end_context, mif_set_font, mif_textline, mif_set_color, mif_set_color, mif_set_style, mif_ellipse, mif_polygon, mif_bezier, mif_polyline, 0 /* mif_arrowhead */, mif_user_shape, 0 /* mif_comment */, 0 /* mif_textsize */ };