|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 /* mpgen.c 1999-Feb-23 Jim Hefferon jim@joshua.smcvt.edu 00015 * Adapted from psgen.c. See 1st_read.mp. 00016 */ 00017 #include "render.h" 00018 #ifndef WIN32 00019 #include <unistd.h> 00020 #endif 00021 #include <sys/stat.h> 00022 00023 00024 #define NONE 0 00025 #define NODE 1 00026 #define EDGE 2 00027 #define CLST 3 00028 00029 /* static point Pages; */ 00030 /* static box PB; */ 00031 static int onetime = TRUE; 00032 00033 static const char **U_lib; 00034 00035 typedef struct grcontext_t { 00036 char *color, *font; 00037 double size; 00038 } grcontext_t; 00039 00040 #define STACKSIZE 32 /* essentially infinite? */ 00041 static grcontext_t S[STACKSIZE]; 00042 static int SP = 0; 00043 00044 static void mp_reset(void) 00045 { 00046 onetime = TRUE; 00047 } 00048 00049 /* mp_cat_libfile: 00050 * Write library files onto the given file pointer. 00051 * arglib is an NULL-terminated array of char* 00052 * Each non-trivial entry should be the name of a file to be included. 00053 * stdlib is an NULL-terminated array of char* 00054 * Each of these is a line of a standard library to be included. 00055 * If any item in arglib is the empty string, the stdlib is not used. 00056 * The stdlib is printed first, if used, followed by the user libraries. 00057 * We check that for web-safe file usage. 00058 */ 00059 static void mp_cat_libfile(FILE * ofp, const char **arglib, const char **stdlib) 00060 { 00061 FILE *fp; 00062 const char **s, *bp, *p, *path; 00063 int i; 00064 boolean use_stdlib = TRUE; 00065 00066 /* check for empty string to turn off stdlib */ 00067 if (arglib) { 00068 for (i = 0; use_stdlib && ((p = arglib[i])); i++) { 00069 if (*p == '\0') 00070 use_stdlib = FALSE; 00071 } 00072 } 00073 if (use_stdlib) 00074 for (s = stdlib; *s; s++) { 00075 fputs(*s, ofp); 00076 fputc('\n', ofp); 00077 } 00078 if (arglib) { 00079 for (i = 0; (p = arglib[i]) != 0; i++) { 00080 if (*p == '\0') 00081 continue; /* ignore empty string */ 00082 path = safefile(p); /* make sure filename is okay */ 00083 if (!path) { 00084 agerr(AGWARN, "can't find library file %s\n", p); 00085 } 00086 else if ((fp = fopen(path, "r"))) { 00087 while ((bp = Fgets(fp))) 00088 fputs(bp, ofp); 00089 fputc('\n', ofp); /* append a newline just in case */ 00090 fclose (fp); 00091 } else 00092 agerr(AGWARN, "can't open library file %s\n", path); 00093 } 00094 } 00095 } 00096 00097 static void 00098 mp_begin_job(FILE * ofp, graph_t * g, const char **lib, char *info[], point pages) 00099 { 00100 /* pages and libraries not here (yet?) */ 00101 /* Pages = pages; */ 00102 U_lib = lib; 00103 /* N_pages = pages.x * pages.y; */ 00104 /* Cur_page = 0; */ 00105 00106 fprintf(Output_file, "%%--- graphviz MetaPost input\n"); 00107 fprintf(Output_file, "%% Created by program: %s version %s (%s)\n", 00108 info[0], info[1], info[2]); 00109 fprintf(Output_file, "%% Title: %s\n", agnameof(g)); 00110 fprintf(Output_file, 00111 "%% Put this between beginfig and endfig. See 1st_read.mp.\n"); 00112 fprintf(Output_file, "%% \n"); 00113 } 00114 00115 static void mp_end_job(void) 00116 { 00117 fprintf(Output_file, "%% End of graphviz MetaPost input\n"); 00118 fprintf(Output_file, "%% \n"); 00119 } 00120 00121 static void mp_comment(char *str) 00122 { 00123 fprintf(Output_file, "%% %s\n", str); 00124 } 00125 00126 static void mp_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb) 00127 { 00128 /* PB = bb; */ 00129 static const char *mp_lib[] = {0}; 00130 if (onetime) { 00131 fprintf(Output_file, "%% BoundingBox: %d %d %d %d\n", 00132 bb.LL.x, bb.LL.y, bb.UR.x + 1, bb.UR.y + 1); 00133 mp_cat_libfile(Output_file,U_lib,mp_lib); 00134 onetime = FALSE; 00135 } 00136 } 00137 00138 static void 00139 mp_begin_page(graph_t * g, point page, double scale, int rot, point offset) 00140 { 00141 assert(SP == 0); 00142 S[SP].font = ""; 00143 S[SP].color = "black"; 00144 S[SP].size = 0.0; 00145 } 00146 00147 static void mp_begin_context(void) 00148 { 00149 if (SP == STACKSIZE - 1) 00150 agerr(AGWARN, "mpgen stack overflow\n"); 00151 else { 00152 SP++; 00153 S[SP] = S[SP - 1]; 00154 } 00155 } 00156 00157 static void mp_end_context(void) 00158 { 00159 if (SP == 0) 00160 agerr(AGWARN, "mpgen stack underflow\n"); 00161 else 00162 SP--; 00163 } 00164 00165 static void mp_set_font(char *name, double size) 00166 { 00167 if (strcmp(S[SP].font, name) || (size != S[SP].size)) { 00168 fprintf(Output_file, "%% GV set font: %.2f /%s ignored\n", size, 00169 name); 00170 S[SP].font = name; 00171 S[SP].size = size; 00172 } 00173 } 00174 00175 static void mp_set_color(char *name) 00176 { 00177 static char *op[] = { "graph", "node", "edge", "sethsb" }; 00178 gvcolor_t color; 00179 00180 if (strcmp(name, S[SP].color)) { 00181 colorxlate(name, &color, HSVA_DOUBLE); 00182 fprintf(Output_file, "%% GV set color: %.3f %.3f %.3f %scolor\n", 00183 color.u.HSVA[0], color.u.HSVA[1], color.u.HSVA[2], op[Obj]); 00184 } 00185 S[SP].color = name; 00186 } 00187 00188 static void mp_set_style(char **s) 00189 { 00190 char *line, *p; 00191 00192 while ((p = line = *s++)) { 00193 while (*p) 00194 p++; 00195 p++; 00196 while (*p) { 00197 fprintf(Output_file, "%% GV set style: %s \n", p); 00198 while (*p) 00199 p++; 00200 p++; 00201 } 00202 fprintf(Output_file, "%% GV set style:: %s\n", line); 00203 } 00204 } 00205 00206 static char *mp_string(char *s) 00207 { 00208 static char *buf = NULL; 00209 static int bufsize = 0; 00210 int pos = 0; 00211 char *p; 00212 00213 if (!buf) { 00214 bufsize = 64; 00215 buf = N_GNEW(bufsize, char); 00216 } 00217 00218 p = buf; 00219 while (*s) { 00220 if (pos > (bufsize - 8)) { 00221 bufsize *= 2; 00222 buf = grealloc(buf, bufsize); 00223 p = buf + pos; 00224 } 00225 if ((*s == LPAREN) || (*s == RPAREN)) { 00226 *p++ = '\\'; 00227 pos++; 00228 } 00229 *p++ = *s++; 00230 pos++; 00231 } 00232 *p = '\0'; 00233 return buf; 00234 } 00235 00236 static void mp_textpara(point p, textpara_t * para) 00237 { 00238 fprintf(Output_file, "label(btex %s etex,(%dbp,%dbp)) withcolor %s;\n", 00239 mp_string(para->str), p.x, p.y, S[SP].color); 00240 } 00241 00242 static void 00243 mp_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled) 00244 { 00245 int j; 00246 if (arrow_at_start || arrow_at_end) 00247 agerr(AGERR, "mp_bezier illegal arrow args\n"); 00248 fprintf(Output_file, "draw (%dbp,%dbp) ", A[0].x, A[0].y); 00249 for (j = 1; j < n; j += 3) 00250 fprintf(Output_file, 00251 "\n ..controls (%dbp,%dbp) and (%dbp,%dbp).. (%dbp,%dbp)", 00252 A[j].x, A[j].y, A[j + 1].x, A[j + 1].y, A[j + 2].x, 00253 A[j + 2].y); 00254 fprintf(Output_file, " withcolor %s;\n", S[SP].color); 00255 } 00256 00257 static void mp_polygon(point * A, int n, int filled) 00258 { 00259 int j; 00260 if (filled) { 00261 fprintf(Output_file, " fill (%dbp,%dbp)", A[0].x, A[0].y); 00262 for (j = 1; j < n; j++) 00263 fprintf(Output_file, "\n --(%dbp,%dbp)", A[j].x, A[j].y); 00264 fprintf(Output_file, "\n --cycle withcolor %s;\n", S[SP].color); 00265 } 00266 fprintf(Output_file, "draw (%dbp,%dbp) ", A[0].x, A[0].y); 00267 for (j = 1; j < n; j++) 00268 fprintf(Output_file, "\n --(%dbp,%dbp)", A[j].x, A[j].y); 00269 fprintf(Output_file, "\n --cycle withcolor %s;\n", S[SP].color); 00270 } 00271 00272 static void mp_ellipse(point p, int rx, int ry, int filled) 00273 { 00274 if (filled) 00275 fprintf(Output_file, 00276 " fill fullcircle xscaled %dbp yscaled %dbp shifted (%dbp,%dbp) withcolor %s;\n", 00277 2 * rx, 2 * ry, p.x, p.y, S[SP].color); 00278 fprintf(Output_file, 00279 "draw fullcircle xscaled %dbp yscaled %dbp shifted (%dbp,%dbp);\n", 00280 2 * rx, 2 * ry, p.x, p.y); 00281 } 00282 00283 static void mp_polyline(point * A, int n) 00284 { 00285 int j; 00286 00287 fprintf(Output_file, "draw (%dbp,%dbp) ", A[0].x, A[0].y); 00288 for (j = 1; j < n; j++) 00289 fprintf(Output_file, "\n --(%dbp,%dbp)", A[j].x, A[j].y); 00290 fprintf(Output_file, " withcolor %s;\n", S[SP].color); 00291 } 00292 00293 static void mp_usershape(usershape_t *us, boxf b, point *A, int n, boolean filled) 00294 { 00295 int j; 00296 fprintf(Output_file, "%%GV USER SHAPE [ "); 00297 for (j = 0; j < n; j++) 00298 fprintf(Output_file, "%d %d ", A[j].x, A[j].y); 00299 fprintf(Output_file, "%d %d ", A[0].x, A[0].y); 00300 fprintf(Output_file, "] %d %s %s ignored\n", n, 00301 (filled ? "true" : "false"), us->name); 00302 } 00303 00304 codegen_t MP_CodeGen = { 00305 mp_reset, 00306 mp_begin_job, mp_end_job, 00307 mp_begin_graph, 0, /* mp_end_graph */ 00308 mp_begin_page, 0, /* mp_end_page */ 00309 0, /* mp_begin_layer */ 0, /* mp_end_layer */ 00310 0, /* mp_begin_cluster */ 0, /* mp_end_cluster */ 00311 0, /* mp_begin_nodes */ 0, /* mp_end_nodes */ 00312 0, /* mp_begin_edges */ 0, /* mp_end_edges */ 00313 0, /* mp_begin_node */ 0, /* mp_end_node */ 00314 0, /* mp_begin_edge */ 0, /* mp_end_edge */ 00315 mp_begin_context, mp_end_context, 00316 0, /* mp_begin_anchor */ 0, /* mp_end_anchor */ 00317 mp_set_font, mp_textpara, 00318 mp_set_color, mp_set_color, mp_set_style, 00319 mp_ellipse, mp_polygon, 00320 mp_bezier, mp_polyline, 00321 0, /* bezier_has_arrows */ 00322 mp_comment, 00323 mp_usershape 00324 };
1.7.5