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