/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/common/vtxgen.c

Go to the documentation of this file.
00001 /* $Id: vtxgen.c,v 1.13 2006/12/07 22:49:36 erg Exp $ $Revision: 1.13 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 
00018 /*
00019  * vtxgen.c generates graph diagrams in the format for
00020  *  Confluents's Visual Thought
00021  */
00022 
00023 /*
00024  * If this time code is a pain to port, then just comment out the
00025  * next line.  It only provides an optional information field
00026  * in the (header...) block 
00027  */
00028 #define SUPPORT_WRITEDATE
00029 
00030 #include "render.h"
00031 #ifdef SUPPORT_WRITEDATE
00032 #include <time.h>
00033 #endif
00034 
00035 
00036 /* VTX font modifiers */
00037 #define REGULAR 0
00038 #define BOLD    1
00039 #define ITALIC  2
00040 #define UNDERSORE 4
00041 #define STRIKE 8
00042 
00043 /* VTX patterns */
00044 #define P_NONE  0
00045 #define P_SOLID 1
00046 #define P_DOTTED 2
00047 #define P_DASHED 3
00048 
00049 /* VTX bold line constant */
00050 #define WIDTH_NORMAL 1
00051 #define WIDTH_BOLD 3
00052 
00053 /* VTX shape mappings */
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\""}       /* default */
00069 };
00070 
00071 
00072 static point Pages;
00073 static double Scale;
00074 static int Rot;
00075 /* static       box             PB; */
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";  /* font family name */
00100     cstk[0].fontopt = REGULAR;  /* modifier: REGULAR, BOLD or ITALIC */
00101     cstk[0].pen = P_SOLID;      /* pen pattern style, default is 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             /* undo EK's strange coding of straight segments */
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 /* FIX
00192         char    *fw,*fa;
00193 
00194         fw = fa = "Regular";
00195         switch (cp->fontopt) {
00196                 case BOLD: fw = "Bold"; break;
00197                 case ITALIC: fa = "Italic"; break;
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     /* N_pages = pages.x * pages.y; */
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     /* PB = bb; */
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     /* point        sz; */
00254 
00255     Scale = scale;
00256     Rot = rot;
00257     page_number = page.x + page.y * Pages.x + 1;
00258     /* sz = sub_points(PB.UR,PB.LL); */
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         /* its invisible, don't draw */
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 /* FIXME */
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,           /* vtx_end_job */
00633     vtx_begin_graph, 0,         /* vtx_end_graph */
00634     vtx_begin_page, 0,          /* vtx_end_page */
00635     0, /* vtx_begin_layer */ 0, /* vtx_end_layer */
00636     0, /* vtx_begin_cluster */ 0,       /* vtx_end_cluster */
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, /* vtx_begin_anchor */ 0,        /* vtx_end_anchor */
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,                          /* bezier_has_arrows */
00648     vtx_comment,
00649     vtx_usershape
00650 };

Generated on Mon Mar 31 19:03:25 2008 for Graphviz by  doxygen 1.5.1