|
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 00015 /* 00016 * vtxgen.c generates graph diagrams in the format for 00017 * Confluents's Visual Thought 00018 */ 00019 00020 /* 00021 * If this time code is a pain to port, then just comment out the 00022 * next line. It only provides an optional information field 00023 * in the (header...) block 00024 */ 00025 #define SUPPORT_WRITEDATE 00026 00027 #include "render.h" 00028 #ifdef SUPPORT_WRITEDATE 00029 #include <time.h> 00030 #endif 00031 00032 00033 /* VTX font modifiers */ 00034 #define REGULAR 0 00035 #define BOLD 1 00036 #define ITALIC 2 00037 #define UNDERSORE 4 00038 #define STRIKE 8 00039 00040 /* VTX patterns */ 00041 #define P_NONE 0 00042 #define P_SOLID 1 00043 #define P_DOTTED 2 00044 #define P_DASHED 3 00045 00046 /* VTX bold line constant */ 00047 #define WIDTH_NORMAL 1 00048 #define WIDTH_BOLD 3 00049 00050 /* VTX shape mappings */ 00051 typedef struct shapemap_s { 00052 char *shape; 00053 char *vtxshape; 00054 } shapemap_t; 00055 00056 static shapemap_t shapemap[] = { 00057 {"box", "\"Rectangle\""}, 00058 {"ellipse", "\"Ellipse\""}, 00059 {"circle", "\"Ellipse\""}, 00060 {"triangle", "\"Triangle\""}, 00061 {"diamond", "\"Diamond\""}, 00062 {"trapezium", "\"Trapezoid\""}, 00063 {"parallelogram", "\"Parallelogram\""}, 00064 {"hexagon", "\"Hexagon\""}, 00065 {NULL, "\"Ellipse\""} /* default */ 00066 }; 00067 00068 00069 static point Pages; 00070 static double Scale; 00071 static int Rot; 00072 /* static box PB; */ 00073 static int onetime = TRUE; 00074 00075 typedef struct context_t { 00076 int color_r, color_g, color_b; 00077 char *fontfam, fontopt, font_was_set; 00078 char pen, fill, penwidth, style_was_set; 00079 double fontsz; 00080 } context_t; 00081 00082 #define MAXNEST 4 00083 static context_t cstk[MAXNEST]; 00084 static int SP; 00085 00086 static void vtx_reset(void) 00087 { 00088 onetime = TRUE; 00089 } 00090 00091 00092 static void init_vtx(void) 00093 { 00094 SP = 0; 00095 cstk[0].color_r = cstk[0].color_g = cstk[0].color_b = 0; 00096 cstk[0].fontfam = "Times"; /* font family name */ 00097 cstk[0].fontopt = REGULAR; /* modifier: REGULAR, BOLD or ITALIC */ 00098 cstk[0].pen = P_SOLID; /* pen pattern style, default is solid */ 00099 cstk[0].fill = P_NONE; 00100 cstk[0].penwidth = WIDTH_NORMAL; 00101 } 00102 00103 static pointf vtx_pt(pointf p) 00104 { 00105 pointf rv; 00106 00107 if (Rot == 0) { 00108 rv.x = p.x; 00109 rv.y = p.y; 00110 } else { 00111 rv.x = p.y; 00112 rv.y = p.x; 00113 } 00114 return rv; 00115 } 00116 00117 static void vtx_ptarray(point * A, int n) 00118 { 00119 int i; 00120 pointf p; 00121 00122 fprintf(Output_file, " (points\n"); 00123 for (i = 0; i < n; i++) { 00124 p.x = (double) A[i].x; 00125 p.y = (double) A[i].y; 00126 p = vtx_pt(p); 00127 fprintf(Output_file, " (%g %g)\n", p.x, p.y); 00128 } 00129 fprintf(Output_file, " )\n"); 00130 } 00131 00132 static void vtx_bzptarray(point * A, int start, int end) 00133 { 00134 pointf p; 00135 int qx = 0, qy = 0; 00136 int i, j, incr = (start > end) ? -1 : 1; 00137 00138 fprintf(Output_file, " (points\n"); 00139 for (i = start, j = 1; i != end; i += incr, j++) { 00140 switch (j % 3) { 00141 case 0: 00142 p.x = (double) A[i].x; 00143 p.y = (double) A[i].y; 00144 p = vtx_pt(p); 00145 fprintf(Output_file, " (%g %g)\n", p.x, p.y); 00146 break; 00147 case 1: 00148 #if 1 00149 qx = A[i].x; 00150 qy = A[i].y; 00151 #else 00152 p.x = (double) A[i].x; 00153 p.y = (double) A[i].y; 00154 p = vtx_pt(p); 00155 fprintf(Output_file, " (%g %g)\n", p.x, p.y); 00156 #endif 00157 break; 00158 case 2: 00159 #if 1 00160 /* undo EK's strange coding of straight segments */ 00161 if (A[i].x == qx && A[i].y == qy) { 00162 if ((A[i - 2].x == qx && A[i - 2].y == qy) 00163 || (A[i + 1].x == qx && A[i + 1].y == qy)) { 00164 p.x = (A[i + 1].x + A[i - 2].x) / 2.0; 00165 p.y = (A[i + 1].y + A[i - 2].y) / 2.0; 00166 } else { 00167 p.x = (double) qx; 00168 p.y = (double) qy; 00169 } 00170 } else { 00171 p.x = (A[i].x + qx) / 2.0; 00172 p.y = (A[i].y + qy) / 2.0; 00173 } 00174 #else 00175 p.x = (double) A[i].x; 00176 p.y = (double) A[i].y; 00177 #endif 00178 p = vtx_pt(p); 00179 fprintf(Output_file, " (%g %g)\n", p.x, p.y); 00180 break; 00181 } 00182 } 00183 fprintf(Output_file, " )\n"); 00184 } 00185 00186 static void vtx_font(context_t * cp) 00187 { 00188 /* FIX 00189 char *fw,*fa; 00190 00191 fw = fa = "Regular"; 00192 switch (cp->fontopt) { 00193 case BOLD: fw = "Bold"; break; 00194 case ITALIC: fa = "Italic"; break; 00195 } 00196 */ 00197 } 00198 00199 static void vtx_comment(char *str) 00200 { 00201 fprintf(Output_file, "; %s\n", str); 00202 } 00203 00204 static void 00205 vtx_begin_job(FILE * ofp, graph_t * g, const char **lib, char *info[], point pages) 00206 { 00207 char *date = ""; 00208 #ifdef SUPPORT_WRITEDATE 00209 time_t when; 00210 struct tm *tm; 00211 size_t date_length = 200; 00212 00213 time(&when); 00214 tm = localtime(&when); 00215 date = N_GNEW(date_length, char); 00216 strftime(date, date_length, "%a %b %e %H:%M:%S %Z %Y", tm); 00217 #endif 00218 00219 Pages = pages; 00220 /* N_pages = pages.x * pages.y; */ 00221 00222 fprintf(Output_file, "; Visual Thought 1.0\n" 00223 "\n" 00224 "(header\n" 00225 " (program \"%s\")\n" 00226 " (version \"%s\")\n" 00227 " (buildDate \"%s\")\n" 00228 " (writeDate \"%s\")\n" 00229 " (documentPath \"\")\n" 00230 ")\n" "\n", info[0], info[1], info[2], date); 00231 00232 free(date); 00233 } 00234 00235 static void vtx_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb) 00236 { 00237 /* PB = bb; */ 00238 if (onetime) { 00239 init_vtx(); 00240 onetime = FALSE; 00241 } 00242 } 00243 00244 static void 00245 vtx_begin_page(graph_t * g, point page, double scale, int rot, 00246 point offset) 00247 { 00248 int page_number; 00249 /* point sz; */ 00250 00251 Scale = scale; 00252 Rot = rot; 00253 page_number = page.x + page.y * Pages.x + 1; 00254 /* sz = sub_points(PB.UR,PB.LL); */ 00255 00256 fprintf(Output_file, "(document\n" 00257 " (palette F)\n" 00258 " (layout\n" 00259 " (page \"Letter\")\n" 00260 " (units \"Inches\")\n" 00261 " (orientation \"portrait\")\n" 00262 " (numberOfPages %d %d)\n" 00263 " (scale %g)\n" 00264 " (margins 18 18 18 18)\n" 00265 " )\n" 00266 ")\n" 00267 "\n" 00268 "(views\n" 00269 " (view\n" 00270 " (location 269 49)\n" 00271 " (size 632 723)\n" 00272 " (zoom %g)\n" 00273 " (documentLocation 0 119)\n" 00274 " (gridSnap T)\n" 00275 " (gridVisibility F)\n" 00276 " (gridSpacing 9)\n" 00277 " (pageBreaks T)\n" 00278 " (toolVisibility T)\n" 00279 " (rulerVisibility T)\n" 00280 " )\n" 00281 ")\n" 00282 "\n", page_number, Pages.x * Pages.y, scale * 100, scale); 00283 } 00284 00285 static void vtx_begin_nodes(void) 00286 { 00287 fprintf(Output_file, "(shapes\n"); 00288 } 00289 00290 static void vtx_end_nodes(void) 00291 { 00292 fprintf(Output_file, ")\n" "\n"); 00293 } 00294 00295 static void vtx_begin_edges(void) 00296 { 00297 fprintf(Output_file, "(connections\n"); 00298 } 00299 00300 static void vtx_end_edges(void) 00301 { 00302 fprintf(Output_file, ")\n" "\n" "(groups\n" ")\n"); 00303 } 00304 00305 static void vtx_begin_node(node_t * n) 00306 { 00307 shapemap_t *p; 00308 00309 for (p = shapemap; p->shape; p++) { 00310 if (streq(ND_shape(n)->name, p->shape)) { 00311 break; 00312 } 00313 } 00314 #ifndef WITH_CGRAPH 00315 fprintf(Output_file, " (shape\n" 00316 " (id %d)\n" 00317 " (layer %d)\n" 00318 " (type %s)\n", AGID(n) + 1, AGID(n), p->vtxshape); 00319 #else 00320 fprintf(Output_file, " (shape\n" 00321 " (id %ld)\n" 00322 " (layer %ld)\n" 00323 " (type %s)\n", AGID(n) + 1, AGID(n), p->vtxshape); 00324 #endif 00325 } 00326 00327 static void vtx_end_node(void) 00328 { 00329 fprintf(Output_file, " )\n"); 00330 } 00331 00332 static void vtx_begin_edge(edge_t * e) 00333 { 00334 #ifndef WITH_CGRAPH 00335 fprintf(Output_file, " (connection\n" 00336 " (id %d)\n" 00337 " (layer %d)\n" 00338 " (rotation 0)\n" 00339 " (textRotation 0)\n" 00340 " (locked F)\n" 00341 " (start %d)\n" 00342 " (end %d)\n", 00343 AGID(e) + 1, AGID(e), AGID(agtail(e)) + 1, AGID(aghead(e)) + 1); 00344 #else 00345 fprintf(Output_file, " (connection\n" 00346 " (id %ld)\n" 00347 " (layer %ld)\n" 00348 " (rotation 0)\n" 00349 " (textRotation 0)\n" 00350 " (locked F)\n" 00351 " (start %ld)\n" 00352 " (end %ld)\n", 00353 AGID(e) + 1, AGID(e), AGID(agtail(e)) + 1, AGID(aghead(e)) + 1); 00354 #endif 00355 } 00356 00357 static void vtx_end_edge(void) 00358 { 00359 fprintf(Output_file, " )\n"); 00360 } 00361 00362 static void vtx_begin_context(void) 00363 { 00364 assert(SP + 1 < MAXNEST); 00365 cstk[SP + 1] = cstk[SP]; 00366 SP++; 00367 } 00368 00369 static void vtx_end_context(void) 00370 { 00371 int psp = SP - 1; 00372 00373 assert(SP > 0); 00374 SP = psp; 00375 } 00376 00377 static void vtx_set_font(char *name, double size) 00378 { 00379 char *p, *q; 00380 context_t *cp; 00381 00382 cp = &(cstk[SP]); 00383 cp->font_was_set = TRUE; 00384 cp->fontsz = size; 00385 p = strdup(name); 00386 if ((q = strchr(p, '-'))) { 00387 *q++ = 0; 00388 if (strcasecmp(q, "italic") == 0) 00389 cp->fontopt = ITALIC; 00390 else if (strcasecmp(q, "bold") == 0) 00391 cp->fontopt = BOLD; 00392 } 00393 cp->fontfam = p; 00394 vtx_font(&cstk[SP]); 00395 } 00396 00397 static void vtx_style(void) 00398 { 00399 context_t *cp; 00400 00401 cp = &(cstk[SP]); 00402 fprintf(Output_file, " (style\n" 00403 " (filled %s)\n" 00404 " (fillColor %d %d %d)\n" 00405 " (stroked T)\n" 00406 " (strokeColor %d %d %d)\n" 00407 " (lineWidth %d)\n" 00408 " (shadowed F)\n" 00409 " (shadowColor 39321 39321 39321)\n" 00410 " )\n", 00411 cp->fill ? "T" : "F", 00412 cp->color_r, cp->color_g, cp->color_b, 00413 cp->color_r, cp->color_g, cp->color_b, cp->penwidth); 00414 } 00415 00416 static void vtx_node_style(void) 00417 { 00418 fprintf(Output_file, " (rotation 0)\n" " (locked F)\n"); 00419 vtx_style(); 00420 fprintf(Output_file, " (flipHorizontal F)\n" 00421 " (flipVertical F)\n"); 00422 } 00423 00424 static void vtx_set_color(char *name) 00425 { 00426 gvcolor_t color; 00427 context_t *cp; 00428 00429 cp = &(cstk[SP]); 00430 colorxlate(name, &color, RGBA_WORD); 00431 cp->color_r = color.u.rrggbbaa[0]; 00432 cp->color_g = color.u.rrggbbaa[1]; 00433 cp->color_b = color.u.rrggbbaa[2]; 00434 } 00435 00436 static void vtx_set_style(char **s) 00437 { 00438 char *line; 00439 context_t *cp; 00440 00441 cp = &(cstk[SP]); 00442 while ((line = *s++)) { 00443 if (streq(line, "solid")) 00444 cp->pen = P_SOLID; 00445 else if (streq(line, "dashed")) 00446 cp->pen = P_DASHED; 00447 else if (streq(line, "dotted")) 00448 cp->pen = P_DOTTED; 00449 else if (streq(line, "invis")) 00450 cp->pen = P_NONE; 00451 else if (streq(line, "bold")) 00452 cp->penwidth = WIDTH_BOLD; 00453 else if (streq(line, "filled")) 00454 cp->fill = P_SOLID; 00455 else if (streq(line, "unfilled")) 00456 cp->fill = P_NONE; 00457 else { 00458 agerr(AGERR, 00459 "vtx_set_style: unsupported style %s - ignoring\n", 00460 line); 00461 } 00462 cp->style_was_set = TRUE; 00463 } 00464 } 00465 00466 static char *vtx_string(char *s) 00467 { 00468 static char *buf = NULL; 00469 static int bufsize = 0; 00470 int pos = 0; 00471 char *p, esc; 00472 00473 if (!buf) { 00474 bufsize = 64; 00475 buf = N_GNEW(bufsize, char); 00476 } 00477 00478 p = buf; 00479 while (*s) { 00480 if (pos > (bufsize - 8)) { 00481 bufsize *= 2; 00482 buf = grealloc(buf, bufsize); 00483 p = buf + pos; 00484 } 00485 esc = 0; 00486 switch (*s) { 00487 case '\t': 00488 esc = 't'; 00489 break; 00490 case '{': 00491 case '}': 00492 case '\\': 00493 esc = *s; 00494 break; 00495 } 00496 if (esc) { 00497 *p++ = '\\'; 00498 *p++ = esc; 00499 pos += 2; 00500 } else { 00501 *p++ = *s; 00502 pos++; 00503 } 00504 s++; 00505 } 00506 *p = '\0'; 00507 return buf; 00508 } 00509 00510 static void vtx_textpara(point p, textpara_t * para) 00511 { 00512 pointf mp; 00513 double fontsz = Scale * cstk[SP].fontsz; 00514 00515 if (cstk[SP].pen == P_NONE) { 00516 /* its invisible, don't draw */ 00517 return; 00518 } 00519 00520 mp.x = (double) p.x; 00521 mp.y = (double) (p.y - fontsz / 2 + 2); 00522 mp = vtx_pt(mp); 00523 if (Obj == EDGE) { 00524 fprintf(Output_file, " (showText T)\n" 00525 " (textDistancePercentage 0.5)\n" 00526 " (textWidth 72)\n" 00527 " (textOffset 0)\n" 00528 " (rtfText{\\rtf1\\ansi\\deff0\n" 00529 "{\\fonttbl{\\f0\\fnil helvetica medium;}}\n" 00530 "{\\colortbl\\red0\\green0\\blue0;}\n" 00531 "\\cf0\\plain\\pard {\\fs%d %s}})\n", 00532 (int) ((fontsz * 2) - 8), vtx_string(para->str)); 00533 } else { 00534 fprintf(Output_file, " (showText T)\n" 00535 " (textVerticalAlignment \"left\")\n" 00536 " (rtfText{\\rtf1\\ansi\\deff0\n" 00537 "{\\fonttbl{\\f0\\fnil helvetica medium;}}\n" 00538 "{\\colortbl\\red0\\green0\\blue0;}\n" 00539 "\\cf0\\plain\\pard {\\fs%d %s}})\n", 00540 (int) ((fontsz * 2) - 8), vtx_string(para->str)); 00541 } 00542 } 00543 00544 static void vtx_bezier(point * A, int n, int arrow_at_start, 00545 int arrow_at_end, int filled) 00546 { 00547 if (arrow_at_start) { 00548 vtx_bzptarray(A, n - 2, 0); 00549 fprintf(Output_file, " (curved T)\n"); 00550 vtx_style(); 00551 fprintf(Output_file, " (drawStartArrowhead %s)\n" 00552 " (drawEndArrowhead %s)\n" 00553 " (startArrowhead \"StandardArrow\")\n" 00554 " (endArrowhead \"StandardArrow\")\n", 00555 arrow_at_end ? "T" : "F", arrow_at_start ? "T" : "F"); 00556 } else { 00557 vtx_bzptarray(A, 1, n - 1); 00558 fprintf(Output_file, " (curved T)\n"); 00559 vtx_style(); 00560 fprintf(Output_file, " (drawStartArrowhead %s)\n" 00561 " (drawEndArrowhead %s)\n" 00562 " (startArrowhead \"StandardArrow\")\n" 00563 " (endArrowhead \"StandardArrow\")\n", 00564 arrow_at_start ? "T" : "F", arrow_at_end ? "T" : "F"); 00565 } 00566 } 00567 00568 static void vtx_polygon(point * A, int n, int filled) 00569 { 00570 int i; 00571 pointf mp, max, min; 00572 00573 mp.x = 0; 00574 mp.y = 0; 00575 max.x = min.x = (double) A[0].x; 00576 max.y = min.y = (double) A[0].y; 00577 for (i = 0; i < n; i++) { 00578 mp.x += (double) A[i].x; 00579 mp.y += (double) A[i].y; 00580 max.x = MAX(max.x, (double) A[i].x); 00581 max.y = MAX(max.y, (double) A[i].y); 00582 min.x = MIN(min.x, (double) A[i].x); 00583 min.y = MIN(min.y, (double) A[i].y); 00584 } 00585 mp.x /= n; 00586 mp.y /= n; 00587 mp = vtx_pt(mp); 00588 max = vtx_pt(max); 00589 min = vtx_pt(min); 00590 fprintf(Output_file, " (location %g %g)\n" 00591 " (size %g %g)\n", 00592 mp.x, mp.y, max.x - min.x, max.y - min.y); 00593 vtx_node_style(); 00594 } 00595 00596 static void vtx_ellipse(point p, int rx, int ry, int filled) 00597 { 00598 pointf mp; 00599 00600 mp.x = (double) p.x; 00601 mp.y = (double) p.y; 00602 mp = vtx_pt(mp); 00603 fprintf(Output_file, " (location %g %g)\n" 00604 " (size %g %g)\n", 00605 mp.x, mp.y, (double) (rx + rx), (double) (ry + ry)); 00606 vtx_node_style(); 00607 } 00608 00609 static void vtx_polyline(point * A, int n) 00610 { 00611 vtx_ptarray(A, n); 00612 fprintf(Output_file, " (curved F)\n"); 00613 vtx_style(); 00614 } 00615 00616 static void vtx_usershape(usershape_t *us, boxf b, point *A, int n, boolean filled) 00617 { 00618 /* FIXME */ 00619 int i; 00620 pointf mp, max, min; 00621 00622 mp.x = 0; 00623 mp.y = 0; 00624 max.x = min.x = (double) A[0].x; 00625 max.y = min.y = (double) A[0].y; 00626 for (i = 0; i < n; i++) { 00627 mp.x += (double) A[i].x; 00628 mp.y += (double) A[i].y; 00629 max.x = MAX(max.x, (double) A[i].x); 00630 max.y = MAX(max.y, (double) A[i].y); 00631 min.x = MIN(min.x, (double) A[i].x); 00632 min.y = MIN(min.y, (double) A[i].y); 00633 } 00634 mp.x /= n; 00635 mp.y /= n; 00636 mp = vtx_pt(mp); 00637 max = vtx_pt(max); 00638 min = vtx_pt(min); 00639 fprintf(Output_file, " (location %g %g)\n" 00640 " (size %g %g)\n", 00641 mp.x, mp.y, max.x - min.x, max.y - min.y); 00642 vtx_node_style(); 00643 } 00644 00645 codegen_t VTX_CodeGen = { 00646 vtx_reset, 00647 vtx_begin_job, 0, /* vtx_end_job */ 00648 vtx_begin_graph, 0, /* vtx_end_graph */ 00649 vtx_begin_page, 0, /* vtx_end_page */ 00650 0, /* vtx_begin_layer */ 0, /* vtx_end_layer */ 00651 0, /* vtx_begin_cluster */ 0, /* vtx_end_cluster */ 00652 vtx_begin_nodes, vtx_end_nodes, 00653 vtx_begin_edges, vtx_end_edges, 00654 vtx_begin_node, vtx_end_node, 00655 vtx_begin_edge, vtx_end_edge, 00656 vtx_begin_context, vtx_end_context, 00657 0, /* vtx_begin_anchor */ 0, /* vtx_end_anchor */ 00658 vtx_set_font, vtx_textpara, 00659 vtx_set_color, vtx_set_color, vtx_set_style, 00660 vtx_ellipse, vtx_polygon, 00661 vtx_bezier, vtx_polyline, 00662 1, /* bezier_has_arrows */ 00663 vtx_comment, 00664 vtx_usershape 00665 };
1.7.5