/* 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 /* * vtxgen.c generates graph diagrams in the format for * Confluents's Visual Thought */ /* * If this time code is a pain to port, then just comment out the * next line. It only provides an optional information field * in the (header...) block */ #define SUPPORT_WRITEDATE #ifdef SUPPORT_WRITEDATE #include #endif #include "render.h" #include "utils.h" /* VTX font modifiers */ #define REGULAR 0 #define BOLD 1 #define ITALIC 2 #define UNDERSORE 4 #define STRIKE 8 /* VTX patterns */ #define P_NONE 0 #define P_SOLID 1 #define P_DOTTED 2 #define P_DASHED 3 /* VTX bold line constant */ #define WIDTH_NORMAL 1 #define WIDTH_BOLD 3 /* VTX shape mappings */ typedef struct shapemap_s { char *shape; char *vtxshape; } shapemap_t; static shapemap_t shapemap[] = { {"box", "\"Rectangle\""}, {"ellipse", "\"Ellipse\""}, {"circle", "\"Ellipse\""}, {"triangle", "\"Triangle\""}, {"diamond", "\"Diamond\""}, {"trapezium", "\"Trapezoid\""}, {"parallelogram", "\"Parallelogram\""}, {"hexagon", "\"Hexagon\""}, {NULL,"\"Ellipse\""} /* default */ }; static point Pages; static double Scale; static int Rot; /* static box PB; */ static int onetime = TRUE; typedef struct context_t { int color_r,color_g,color_b; char *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 void vtx_reset(void) { onetime = TRUE; } static void init_vtx(void) { SP = 0; cstk[0].color_r = cstk[0].color_g = cstk[0].color_b = 0; 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 vtx_pt(pointf p) { pointf rv; if (Rot == 0) { rv.x = p.x; rv.y = p.y; } else { rv.x = p.y; rv.y = p.x; } return rv; } static void vtx_ptarray(point* A, int n) { int i; pointf p; fprintf(Output_file," (points\n"); for (i = 0; i < n; i++) { p.x = (double)A[i].x; p.y = (double)A[i].y; p = vtx_pt(p); fprintf(Output_file," (%g %g)\n",p.x,p.y); } fprintf(Output_file," )\n"); } static void vtx_bzptarray(point* A, int start, int end) { pointf p; int qx=0, qy=0; int i,j,incr=(start>end)?-1:1; fprintf(Output_file," (points\n"); for (i = start, j=1; i != end; i += incr, j++) { switch (j % 3) { case 0: p.x = (double)A[i].x; p.y = (double)A[i].y; p = vtx_pt(p); fprintf(Output_file," (%g %g)\n",p.x,p.y); break; case 1: #if 1 qx = A[i].x; qy = A[i].y; #else p.x = (double)A[i].x; p.y = (double)A[i].y; p = vtx_pt(p); fprintf(Output_file," (%g %g)\n",p.x,p.y); #endif break; case 2: #if 1 /* undo EK's strange coding of straight segments */ if (A[i].x == qx && A[i].y == qy) { if ((A[i-2].x == qx && A[i-2].y == qy) || (A[i+1].x == qx && A[i+1].y == qy)) { p.x = (A[i+1].x + A[i-2].x)/2.0; p.y = (A[i+1].y + A[i-2].y)/2.0; } else { p.x = (double)qx; p.y = (double)qy; } } else { p.x = (A[i].x + qx)/2.0; p.y = (A[i].y + qy)/2.0; } #else p.x = (double)A[i].x; p.y = (double)A[i].y; #endif p = vtx_pt(p); fprintf(Output_file," (%g %g)\n",p.x,p.y); break; } } fprintf(Output_file," )\n"); } static void vtx_font(context_t* cp) { /* FIX char *fw,*fa; fw = fa = "Regular"; switch (cp->fontopt) { case BOLD: fw = "Bold"; break; case ITALIC: fa = "Italic"; break; } */ } static void vtx_comment(void* obj, attrsym_t* sym) { char *str; str = late_string(obj,sym,""); if (str[0]) fprintf(Output_file,"; %s\n",str); } static void vtx_begin_job(FILE *ofp, graph_t *g, char **lib, char *user, char *info[], point pages) { char *date = ""; #ifdef SUPPORT_WRITEDATE time_t when; struct tm *tm; size_t date_length = 200; time(&when); tm = localtime(&when); date = N_GNEW(date_length,char); strftime(date, date_length, "%a %b %e %H:%M:%S %Z %Y", tm); #endif Pages = pages; /* N_pages = pages.x * pages.y; */ fprintf(Output_file,"; Visual Thought 1.0\n" "\n" "(header\n" " (program \"%s\")\n" " (version \"%s\")\n" " (buildDate \"%s\")\n" " (writeDate \"%s\")\n" " (documentPath \"\")\n" ")\n" "\n", info[0],info[1],info[2],date); free (date); } static void vtx_end_job(void) { } static void vtx_begin_graph(graph_t* g, box bb, point pb) { /* PB = bb; */ if (onetime) { init_vtx(); vtx_comment(g,agfindattr(g,"comment")); onetime = FALSE; } } static void vtx_end_graph(void) { } static void vtx_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,"(document\n" " (palette F)\n" " (layout\n" " (page \"Letter\")\n" " (units \"Inches\")\n" " (orientation \"portrait\")\n" " (numberOfPages %d %d)\n" " (scale %g)\n" " (margins 18 18 18 18)\n" " )\n" ")\n" "\n" "(views\n" " (view\n" " (location 269 49)\n" " (size 632 723)\n" " (zoom %g)\n" " (documentLocation 0 119)\n" " (gridSnap T)\n" " (gridVisibility F)\n" " (gridSpacing 9)\n" " (pageBreaks T)\n" " (toolVisibility T)\n" " (rulerVisibility T)\n" " )\n" ")\n" "\n", page_number, Pages.x*Pages.y, scale*100, scale); } static void vtx_end_page(void) { } static void vtx_begin_cluster(graph_t* g) { } static void vtx_end_cluster (void) { } static void vtx_begin_nodes(void) { fprintf(Output_file,"(shapes\n"); } static void vtx_end_nodes(void) { fprintf(Output_file,")\n" "\n"); } static void vtx_begin_edges(void) { fprintf(Output_file,"(connections\n"); } static void vtx_end_edges(void) { fprintf(Output_file,")\n" "\n" "(groups\n" ")\n"); } static void vtx_begin_node(node_t* n) { shapemap_t *p; for (p = shapemap; p->shape; p++) { if (streq(ND_shape(n)->name,p->shape)) { break; } } fprintf(Output_file," (shape\n" " (id %d)\n" " (layer %d)\n" " (type %s)\n", n->id + 1, n->id, p->vtxshape); } static void vtx_end_node (void) { fprintf(Output_file," )\n"); } static void vtx_begin_edge (edge_t* e) { fprintf(Output_file," (connection\n" " (id %d)\n" " (layer %d)\n" " (rotation 0)\n" " (textRotation 0)\n" " (locked F)\n" " (start %d)\n" " (end %d)\n", e->id + 1, e->id, e->tail->id + 1, e->head->id + 1); } static void vtx_end_edge (void) { fprintf(Output_file," )\n"); } static void vtx_begin_context(void) { assert(SP + 1 < MAXNEST); cstk[SP+1] = cstk[SP]; SP++; } static void vtx_end_context(void) { int psp = SP - 1; assert(SP > 0); SP = psp; } static void vtx_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; vtx_font(&cstk[SP]); } static void vtx_style() { context_t *cp; cp = &(cstk[SP]); fprintf(Output_file," (style\n" " (filled %s)\n" " (fillColor %d %d %d)\n" " (stroked T)\n" " (strokeColor %d %d %d)\n" " (lineWidth %d)\n" " (shadowed F)\n" " (shadowColor 39321 39321 39321)\n" " )\n", cp->fill?"T":"F", cp->color_r, cp->color_g, cp->color_b, cp->color_r, cp->color_g, cp->color_b, cp->penwidth); } static void vtx_node_style() { fprintf(Output_file," (rotation 0)\n" " (locked F)\n"); vtx_style(); fprintf(Output_file," (flipHorizontal F)\n" " (flipVertical F)\n"); } static void vtx_set_color(char* name) { color_t color; context_t *cp; cp = &(cstk[SP]); colorxlate(name,&color,RGBA_WORD); cp->color_r=color.u.rrggbbaa[0]; cp->color_g=color.u.rrggbbaa[1]; cp->color_b=color.u.rrggbbaa[2]; } static void vtx_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, "vtx_set_style: unsupported style %s - ignoring\n", line); } cp->style_was_set = TRUE; } } static char * vtx_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 '\\': esc = *s; break; } if (esc) { *p++ = '\\'; *p++ = esc; pos += 2; } else { *p++ = *s; pos++; } s++; } *p = '\0'; return buf; } static void vtx_textline(point p, textline_t *line) { pointf mp; double fontsz = Scale * cstk[SP].fontsz; if( cstk[SP].pen == P_NONE ) { /* its invisible, don't draw */ return; } mp.x = (double)p.x; mp.y = (double)(p.y - fontsz/2 + 2); mp = vtx_pt(mp); if (Obj == EDGE) { fprintf(Output_file," (showText T)\n" " (textDistancePercentage 0.5)\n" " (textWidth 72)\n" " (textOffset 0)\n" " (rtfText{\\rtf1\\ansi\\deff0\n" "{\\fonttbl{\\f0\\fnil helvetica medium;}}\n" "{\\colortbl\\red0\\green0\\blue0;}\n" "\\cf0\\plain\\pard {\\fs%d %s}})\n", (int)((fontsz*2)-8), vtx_string(line->str)); } else { fprintf(Output_file," (showText T)\n" " (textVerticalAlignment \"left\")\n" " (rtfText{\\rtf1\\ansi\\deff0\n" "{\\fonttbl{\\f0\\fnil helvetica medium;}}\n" "{\\colortbl\\red0\\green0\\blue0;}\n" "\\cf0\\plain\\pard {\\fs%d %s}})\n", (int)((fontsz*2)-8), vtx_string(line->str)); } } static void vtx_bezier(point* A, int n, int arrow_at_start, int arrow_at_end) { if (arrow_at_start) { vtx_bzptarray(A,n-2,0); fprintf(Output_file," (curved T)\n"); vtx_style(); fprintf(Output_file," (drawStartArrowhead %s)\n" " (drawEndArrowhead %s)\n" " (startArrowhead \"StandardArrow\")\n" " (endArrowhead \"StandardArrow\")\n", arrow_at_end?"T":"F", arrow_at_start?"T":"F"); } else { vtx_bzptarray(A,1,n-1); fprintf(Output_file," (curved T)\n"); vtx_style(); fprintf(Output_file," (drawStartArrowhead %s)\n" " (drawEndArrowhead %s)\n" " (startArrowhead \"StandardArrow\")\n" " (endArrowhead \"StandardArrow\")\n", arrow_at_start?"T":"F", arrow_at_end?"T":"F"); } } static void vtx_polygon(point *A, int n, int filled) { int i; pointf mp, max, min; mp.x = 0; mp.y = 0; max.x = min.x = (double)A[0].x; max.y = min.y = (double)A[0].y; for (i=0; i