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

Go to the documentation of this file.
00001 /* $Id: diagen.c,v 1.24 2007/09/24 08:22:20 ellson Exp $ $Revision: 1.24 $ */
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 #ifdef HAVE_CONFIG_H
00018 #include "config.h"
00019 #endif
00020 
00021 #include "render.h"
00022 
00023 #include <stdarg.h>
00024 #ifdef HAVE_UNISTD_H
00025 #include <unistd.h>
00026 #endif
00027 #ifdef HAVE_LIBZ
00028 #include <zlib.h>
00029 #endif
00030 
00031 /* DIA font modifiers */
00032 #define REGULAR 0
00033 #define BOLD    1
00034 #define ITALIC  2
00035 
00036 /* DIA patterns */
00037 #define P_SOLID 0
00038 #define P_NONE  15
00039 #define P_DOTTED 4              /* i wasn't sure about this */
00040 #define P_DASHED 11             /* or this */
00041 
00042 /* DIA bold line constant */
00043 #define WIDTH_NORMAL 1
00044 #define WIDTH_BOLD 3
00045 
00046 #define DIA_RESOLUTION 1.0
00047 #define SCALE (DIA_RESOLUTION/15.0)
00048 
00049 #define         NODE            1
00050 #define         EDGE            2
00051 #define         CLST            3
00052 
00053 
00054 /* FIXME - these are not used currently - probably something missing */
00055 #if 0
00056 /* DIA dash array */
00057 static char *sdarray = "5,2";
00058 /* DIA dot array */
00059 static char *sdotarray = "1,5";
00060 static int GraphURL, ClusterURL, NodeURL, EdgeURL;
00061 static char *op[] = { "graph", "node", "edge", "graph" };
00062 #endif
00063 
00064 /* static       int             N_pages; */
00065 /* static       point   Pages; */
00066 static double Scale;
00067 static pointf Offset;
00068 static int Rot;
00069 static box PB;
00070 static int onetime = TRUE;
00071 
00072 static node_t *Curnode;
00073 static edge_t *Curedge;
00074 static graph_t *Curgraph, *Rootgraph;
00075 
00076 typedef struct context_t {
00077     char *pencolor, *fillcolor, *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 #ifdef HAVE_LIBZ
00087 static gzFile Zfile;
00088 #endif
00089 
00090 static int dia_fputs(char *s)
00091 {
00092     int len;
00093 
00094     len = strlen(s);
00095 
00096 #ifdef HAVE_LIBZ
00097     return gzwrite(Zfile, s, (unsigned) len);
00098 #else
00099     return 0;
00100 #endif
00101 }
00102 
00103 
00104 /* dia_printf:
00105  * Note that this function is unsafe due to the fixed buffer size.
00106  * It should only be used when the caller is sure the input will not
00107  * overflow the buffer. In particular, it should be avoided for
00108  * input coming from users. Also, if vsnprintf is available, the
00109  * code should check for return values to use it safely.
00110  */
00111 static int dia_printf(const char *format, ...)
00112 {
00113     char buf[BUFSIZ];
00114     va_list argp;
00115     int len;
00116 
00117     va_start(argp, format);
00118 #ifdef HAVE_VSNPRINTF
00119     (void) vsnprintf(buf, sizeof(buf), format, argp);
00120 #else
00121     (void) vsprintf(buf, format, argp);
00122 #endif
00123     va_end(argp);
00124     len = strlen(buf);
00125 
00126     /* some *sprintf (e.g C99 std)
00127        don't return the number of
00128        bytes actually written */
00129 
00130 #ifdef HAVE_LIBZ
00131     return gzwrite(Zfile, buf, (unsigned) len);
00132 #else
00133     return 0;
00134 #endif
00135 }
00136 
00137 #define SVG_COLORS_P 0
00138 
00139 static int dia_comparestr(const void *s1, const void *s2)
00140 {
00141         return strcmp(*(char **) s1, *(char **) s2);
00142 }
00143 
00144 static char *dia_resolve_color(char *name)
00145 {
00146 /* color names from http://www.w3.org/TR/SVG/types.html */
00147 /* NB.  List must be LANG_C sorted */
00148     static char *svg_known_colors[] = {
00149         "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure",
00150         "beige", "bisque", "black", "blanchedalmond", "blue",
00151         "blueviolet", "brown", "burlywood",
00152         "cadetblue", "chartreuse", "chocolate", "coral",
00153         "cornflowerblue", "cornsilk", "crimson", "cyan",
00154         "darkblue", "darkcyan", "darkgoldenrod", "darkgray",
00155         "darkgreen", "darkgrey", "darkkhaki", "darkmagenta",
00156         "darkolivegreen", "darkorange", "darkorchid", "darkred",
00157         "darksalmon", "darkseagreen", "darkslateblue", "darkslategray",
00158         "darkslategrey", "darkturquoise", "darkviolet", "deeppink",
00159         "deepskyblue", "dimgray", "dimgrey", "dodgerblue",
00160         "firebrick", "floralwhite", "forestgreen", "fuchsia",
00161         "gainsboro", "ghostwhite", "gold", "goldenrod", "gray",
00162         "green", "greenyellow", "grey",
00163         "honeydew", "hotpink", "indianred",
00164         "indigo", "ivory", "khaki",
00165         "lavender", "lavenderblush", "lawngreen", "lemonchiffon",
00166         "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow",
00167         "lightgray", "lightgreen", "lightgrey", "lightpink",
00168         "lightsalmon", "lightseagreen", "lightskyblue",
00169         "lightslategray", "lightslategrey", "lightsteelblue",
00170         "lightyellow", "lime", "limegreen", "linen",
00171         "magenta", "maroon", "mediumaquamarine", "mediumblue",
00172         "mediumorchid", "mediumpurple", "mediumseagreen",
00173         "mediumslateblue", "mediumspringgreen", "mediumturquoise",
00174         "mediumvioletred", "midnightblue", "mintcream",
00175         "mistyrose", "moccasin",
00176         "navajowhite", "navy", "oldlace",
00177         "olive", "olivedrab", "orange", "orangered", "orchid",
00178         "palegoldenrod", "palegreen", "paleturquoise",
00179         "palevioletred", "papayawhip", "peachpuff", "peru", "pink",
00180         "plum", "powderblue", "purple",
00181         "red", "rosybrown", "royalblue",
00182         "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell",
00183         "sienna", "silver", "skyblue", "slateblue", "slategray",
00184         "slategrey", "snow", "springgreen", "steelblue",
00185         "tan", "teal", "thistle", "tomato", "turquoise",
00186         "violet",
00187         "wheat", "white", "whitesmoke",
00188         "yellow", "yellowgreen",
00189     };
00190 
00191     static char buf[SMALLBUF];
00192     char *tok;
00193     gvcolor_t color;
00194 
00195     tok = canontoken(name);
00196     if (!SVG_COLORS_P || (bsearch(&tok, svg_known_colors,
00197                               sizeof(svg_known_colors) / sizeof(char *),
00198                               sizeof(char *), dia_comparestr) == NULL)) {
00199         /* if tok was not found in known_colors */
00200         if (streq(tok, "transparent")) {
00201             tok = "none";
00202         } else {
00203             colorxlate(name, &color, RGBA_BYTE);
00204             sprintf(buf, "#%02x%02x%02x",
00205                     color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
00206             tok = buf;
00207         }
00208     }
00209     return tok;
00210 }
00211 
00212 
00213 static void dia_reset(void)
00214 {
00215     onetime = TRUE;
00216 }
00217 
00218 
00219 static void init_dia(void)
00220 {
00221     SP = 0;
00222     cstk[0].pencolor = DEFAULT_COLOR;   /* DIA pencolor */
00223     cstk[0].fillcolor = "";     /* DIA fillcolor */
00224     cstk[0].fontfam = DEFAULT_FONTNAME; /* font family name */
00225     cstk[0].fontsz = DEFAULT_FONTSIZE;  /* font size */
00226     cstk[0].fontopt = REGULAR;  /* modifier: REGULAR, BOLD or ITALIC */
00227     cstk[0].pen = P_SOLID;      /* pen pattern style, default is solid */
00228     cstk[0].fill = P_NONE;
00229     cstk[0].penwidth = WIDTH_NORMAL;
00230 }
00231 
00232 static pointf diapt(point p)
00233 {
00234     pointf rv;
00235 
00236     if (Rot == 0) {
00237         rv.x = PB.LL.x + p.x * Scale + Offset.x;
00238         rv.y = PB.UR.y - 1 - p.y * Scale - Offset.y;
00239     } else {
00240         rv.x = PB.UR.x - 1 - p.y * Scale - Offset.x;
00241         rv.y = PB.UR.y - 1 - p.x * Scale - Offset.y;
00242     }
00243     return rv;
00244 }
00245 
00246 static void dia_grstyle(context_t * cp)
00247 {
00248     if (cp->pencolor != DEFAULT_COLOR) {
00249         dia_fputs("      <dia:attribute name=\"border_color\">\n");
00250         dia_printf("        <dia:color val=\"%s\"/>\n",
00251                    dia_resolve_color(cp->pencolor));
00252         dia_fputs("      </dia:attribute>\n");
00253     }
00254     if (cp->penwidth != WIDTH_NORMAL) {
00255         dia_fputs("      <dia:attribute name=\"line_width\">\n");
00256         dia_printf("        <dia:real val=\"%g\"/>\n",
00257                    Scale * (cp->penwidth));
00258         dia_fputs("      </dia:attribute>\n");
00259     }
00260     if (cp->pen == P_DASHED) {
00261         dia_fputs("      <dia:attribute name=\"line_style\">\n");
00262         dia_printf("        <dia:real val=\"%d\"/>\n", 1);
00263         dia_fputs("      </dia:attribute>\n");
00264 #if 0
00265     } else if (cp->pen == P_DOTTED) {
00266         dia_printf("stroke-dasharray:%s;", sdotarray);
00267 #endif
00268     }
00269 }
00270 
00271 static void dia_grstylefill(context_t * cp, int filled)
00272 {
00273     if (filled) {
00274         dia_fputs("      <dia:attribute name=\"inner_color\">\n");
00275         dia_printf("        <dia:color val=\"%s\"/>\n",
00276                    dia_resolve_color(cp->fillcolor));
00277         dia_fputs("      </dia:attribute>\n");
00278     } else {
00279         dia_fputs("      <dia:attribute name=\"show_background\">\n");
00280         dia_printf("        <dia:boolean val=\"%s\"/>\n", "true");
00281         dia_fputs("      </dia:attribute>\n");
00282     }
00283 }
00284 
00285 static void dia_comment(char *str)
00286 {
00287     dia_fputs("<!-- ");
00288     dia_fputs(xml_string(str));
00289     dia_fputs(" -->\n");
00290 }
00291 
00292 static void
00293 dia_begin_job(FILE * ofp, graph_t * g, char **lib, char *user,
00294               char *info[], point pages)
00295 {
00296 #if HAVE_LIBZ
00297     int fd;
00298 
00299     fd = dup(fileno(Output_file));      /* open dup so can gzclose 
00300                                            independent of FILE close */
00301     Zfile = gzdopen(fd, "wb");
00302     if (!Zfile) {
00303         agerr(AGERR, "Error opening compressed output file\n");
00304         exit(1);
00305     }
00306 #else
00307     agerr(AGERR,
00308           "No support for compressed output. Not compiled with zlib.\n");
00309     exit(1);
00310 #endif
00311 
00312 /*      Pages = pages; */
00313 /*      N_pages = pages.x * pages.y; */
00314     dia_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00315 
00316 }
00317 
00318 static void dia_end_job(void)
00319 {
00320 }
00321 
00322 static void dia_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
00323 {
00324     Rootgraph = g;
00325     PB.LL.x = PB.LL.y = 0;
00326     PB.UR.x = (bb.UR.x - bb.LL.x + 2 * GD_drawing(g)->margin.x) * SCALE;
00327     PB.UR.y = (bb.UR.y - bb.LL.y + 2 * GD_drawing(g)->margin.y) * SCALE;
00328     Offset.x = GD_drawing(g)->margin.x * SCALE;
00329     Offset.y = GD_drawing(g)->margin.y * SCALE;
00330     if (onetime) {
00331         init_dia();
00332         onetime = FALSE;
00333     }
00334     dia_fputs
00335         ("<dia:diagram xmlns:dia=\"http://www.lysator.liu.se/~alla/dia/\">\n");
00336     dia_fputs("  <dia:diagramdata>\n");
00337     dia_fputs("    <dia:attribute name=\"background\">\n");
00338     dia_fputs("      <dia:color val=\"#ffffff\"/>\n");
00339     dia_fputs("    </dia:attribute>\n");
00340     dia_fputs("    <dia:attribute name=\"paper\">\n");
00341     dia_fputs("      <dia:composite type=\"paper\">\n");
00342     dia_fputs("        <dia:attribute name=\"name\">\n");
00343     dia_fputs("          <dia:string>#A4#</dia:string>\n");
00344     dia_fputs("        </dia:attribute>\n");
00345     dia_fputs("        <dia:attribute name=\"tmargin\">\n");
00346     dia_fputs("          <dia:real val=\"2.8222\"/>\n");
00347     dia_fputs("        </dia:attribute>\n");
00348     dia_fputs("        <dia:attribute name=\"bmargin\">\n");
00349     dia_fputs("          <dia:real val=\"2.8222\"/>\n");
00350     dia_fputs("        </dia:attribute>\n");
00351     dia_fputs("        <dia:attribute name=\"lmargin\">\n");
00352     dia_fputs("          <dia:real val=\"2.8222\"/>\n");
00353     dia_fputs("        </dia:attribute>\n");
00354     dia_fputs("        <dia:attribute name=\"rmargin\">\n");
00355     dia_fputs("          <dia:real val=\"2.8222\"/>\n");
00356     dia_fputs("        </dia:attribute>\n");
00357     dia_fputs("        <dia:attribute name=\"is_portrait\">\n");
00358     dia_fputs("          <dia:boolean val=\"true\"/>\n");
00359     dia_fputs("        </dia:attribute>\n");
00360     dia_fputs("        <dia:attribute name=\"scaling\">\n");
00361     dia_fputs("          <dia:real val=\"1\"/>\n");
00362     dia_fputs("        </dia:attribute>\n");
00363     dia_fputs("        <dia:attribute name=\"fitto\">\n");
00364     dia_fputs("          <dia:boolean val=\"false\"/>\n");
00365     dia_fputs("        </dia:attribute>\n");
00366     dia_fputs("      </dia:composite>\n");
00367     dia_fputs("    </dia:attribute>\n");
00368     dia_fputs("    <dia:attribute name=\"grid\">\n");
00369     dia_fputs("      <dia:composite type=\"grid\">\n");
00370     dia_fputs("        <dia:attribute name=\"width_x\">\n");
00371     dia_fputs("          <dia:real val=\"1\"/>\n");
00372     dia_fputs("        </dia:attribute>\n");
00373     dia_fputs("        <dia:attribute name=\"width_y\">\n");
00374     dia_fputs("          <dia:real val=\"1\"/>\n");
00375     dia_fputs("        </dia:attribute>\n");
00376     dia_fputs("        <dia:attribute name=\"visible_x\">\n");
00377     dia_fputs("          <dia:int val=\"1\"/>\n");
00378     dia_fputs("        </dia:attribute>\n");
00379     dia_fputs("        <dia:attribute name=\"visible_y\">\n");
00380     dia_fputs("          <dia:int val=\"1\"/>\n");
00381     dia_fputs("        </dia:attribute>\n");
00382     dia_fputs("      </dia:composite>\n");
00383     dia_fputs("    </dia:attribute>\n");
00384     dia_fputs("    <dia:attribute name=\"guides\">\n");
00385     dia_fputs("      <dia:composite type=\"guides\">\n");
00386     dia_fputs("        <dia:attribute name=\"hguides\"/>\n");
00387     dia_fputs("        <dia:attribute name=\"vguides\"/>\n");
00388     dia_fputs("      </dia:composite>\n");
00389     dia_fputs("    </dia:attribute>\n");
00390     dia_fputs("  </dia:diagramdata>\n");
00391 }
00392 
00393 static void dia_end_graph(void)
00394 {
00395     dia_printf("</dia:diagram>\n");
00396 #ifdef HAVE_LIBZ
00397     gzclose(Zfile);
00398 #endif
00399 }
00400 
00401 static void
00402 dia_begin_page(graph_t * g, point page, double scale, int rot,
00403                point offset)
00404 {
00405     /* int          page_number; */
00406     /* point        sz; */
00407 
00408     Scale = scale * SCALE;
00409     Rot = rot;
00410     /* page_number =  page.x + page.y * Pages.x + 1; */
00411     /* sz = sub_points(PB.UR,PB.LL); */
00412 
00413     dia_printf("  <dia:layer name=\"Background\" visible=\"true\">\n");
00414 }
00415 
00416 static void dia_end_page(void)
00417 {
00418     dia_fputs("  </dia:layer>\n");
00419 }
00420 
00421 static void dia_begin_cluster(graph_t * g)
00422 {
00423     dia_printf("<dia:group>\n");
00424     Curgraph = g;
00425 }
00426 
00427 static void dia_end_cluster(void)
00428 {
00429     dia_printf("</dia:group>\n");
00430 }
00431 
00432 static void dia_begin_node(node_t * n)
00433 {
00434     dia_printf("<dia:group>\n");
00435     Curnode = n;
00436 }
00437 
00438 static void dia_end_node(void)
00439 {
00440     dia_printf("</dia:group>\n");
00441 }
00442 
00443 static void dia_begin_edge(edge_t * e)
00444 {
00445     Curedge = e;
00446 }
00447 
00448 static void dia_end_edge(void)
00449 {
00450     Curedge = NULL;
00451 }
00452 
00453 static void dia_begin_context(void)
00454 {
00455     assert(SP + 1 < MAXNEST);
00456     cstk[SP + 1] = cstk[SP];
00457     SP++;
00458 }
00459 
00460 static void dia_end_context(void)
00461 {
00462     int psp = SP - 1;
00463     assert(SP > 0);
00464     /*free(cstk[psp].fontfam); */
00465     SP = psp;
00466 }
00467 
00468 static void dia_set_font(char *name, double size)
00469 {
00470     char *p;
00471     context_t *cp;
00472 
00473     cp = &(cstk[SP]);
00474     cp->font_was_set = TRUE;
00475     cp->fontsz = size;
00476     p = strdup(name);
00477     cp->fontfam = p;
00478 }
00479 
00480 static void dia_set_pencolor(char *name)
00481 {
00482     cstk[SP].pencolor = name;
00483 }
00484 
00485 static void dia_set_fillcolor(char *name)
00486 {
00487     cstk[SP].fillcolor = name;
00488 }
00489 
00490 static void dia_set_style(char **s)
00491 {
00492     char *line, *p;
00493     context_t *cp;
00494 
00495     cp = &(cstk[SP]);
00496     while ((p = line = *s++)) {
00497         if (streq(line, "solid"))
00498             cp->pen = P_SOLID;
00499         else if (streq(line, "dashed"))
00500             cp->pen = P_DASHED;
00501         else if (streq(line, "dotted"))
00502             cp->pen = P_DOTTED;
00503         else if (streq(line, "invis"))
00504             cp->pen = P_NONE;
00505         else if (streq(line, "bold"))
00506             cp->penwidth = WIDTH_BOLD;
00507         else if (streq(line, "setlinewidth")) {
00508             while (*p)
00509                 p++;
00510             p++;
00511             cp->penwidth = atol(p);
00512         } else if (streq(line, "filled"))
00513             cp->fill = P_SOLID;
00514         else if (streq(line, "unfilled"))
00515             cp->fill = P_NONE;
00516         else {
00517             agerr(AGWARN,
00518                   "dia_set_style: unsupported style %s - ignoring\n",
00519                   line);
00520         }
00521         cp->style_was_set = TRUE;
00522     }
00523     /* if (cp->style_was_set) dia_style(cp); */
00524 }
00525 
00526 static void dia_textpara(point p, textpara_t * para)
00527 {
00528     int anchor;
00529     pointf mp;
00530     context_t *cp;
00531 
00532     cp = &(cstk[SP]);
00533     switch (para->just) {
00534     case 'l':
00535         anchor = 0;
00536         break;
00537     case 'r':
00538         anchor = 2;
00539         break;
00540     default:
00541     case 'n':
00542         anchor = 1;
00543         break;
00544     }
00545 
00546     mp = diapt(p);
00547     dia_printf
00548         ("    <dia:object type=\"Standard - Text\" version=\"0\" id=\"%s\">\n",
00549          "0");
00550     dia_fputs("      <dia:attribute name=\"text\">\n");
00551     dia_fputs("        <dia:composite type=\"text\">\n");
00552     dia_fputs("          <dia:attribute name=\"string\">\n");
00553     dia_fputs("            <dia:string>#");
00554     dia_fputs(xml_string(para->str));
00555     dia_fputs("#</dia:string>\n");
00556     dia_fputs("          </dia:attribute>\n");
00557     dia_fputs("          <dia:attribute name=\"font\">\n");
00558     dia_printf("            <dia:font name=\"%s\"/>\n", cp->fontfam);
00559     dia_fputs("          </dia:attribute>\n");
00560     dia_fputs("          <dia:attribute name=\"height\">\n");
00561     dia_printf("            <dia:real val=\"%g\"/>\n",
00562                Scale * (cp->fontsz));
00563     dia_fputs("          </dia:attribute>\n");
00564     dia_fputs("          <dia:attribute name=\"pos\">\n");
00565     dia_printf("            <dia:point val=\"%g,%g\"/>\n", mp.x, mp.y);
00566     dia_fputs("          </dia:attribute>\n");
00567     dia_fputs("          <dia:attribute name=\"color\">\n");
00568     dia_printf("            <dia:color val=\"%s\"/>\n",
00569                dia_resolve_color(cp->pencolor));
00570     dia_fputs("          </dia:attribute>\n");
00571     dia_fputs("          <dia:attribute name=\"alignment\">\n");
00572     dia_printf("            <dia:enum val=\"%d\"/>\n", anchor);
00573     dia_fputs("          </dia:attribute>\n");
00574     dia_fputs("        </dia:composite>\n");
00575     dia_fputs("      </dia:attribute>\n");
00576     dia_fputs("      <dia:attribute name=\"obj_pos\">\n");
00577     dia_printf("        <dia:point val=\"%g,%g\"/>\n", mp.x, mp.y);
00578     dia_fputs("      </dia:attribute>\n");
00579     dia_fputs("      <dia:attribute name=\"obj_bb\">\n");
00580     dia_printf("        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00581                mp.x - (Scale * (para->width) / 2.), mp.y - 0.4,
00582                mp.x + (Scale * (para->width) / 2.), mp.y + 0.4);
00583     dia_fputs("      </dia:attribute>\n");
00584     dia_fputs("    </dia:object>\n");
00585 }
00586 
00587 static void dia_ellipse(point p, int rx, int ry, int filled)
00588 {
00589     pointf cp, rp;
00590     int nodeId;
00591 
00592     switch (Obj) {
00593     case NODE:
00594         nodeId = Curnode->id;
00595         break;
00596     default:
00597         nodeId = -1;
00598         break;
00599     }
00600 
00601     if (cstk[SP].pen == P_NONE) {
00602         /* its invisible, don't draw */
00603         return;
00604     }
00605     cp = diapt(p);
00606 
00607     if (Rot) {
00608         int t;
00609         t = rx;
00610         rx = ry;
00611         ry = t;
00612     }
00613     rp.x = Scale * rx;
00614     rp.y = Scale * ry;
00615 
00616     dia_printf
00617         ("    <dia:object type=\"Standard - Ellipse\" version=\"0\" id=\"%d\">\n",
00618          nodeId);
00619     dia_fputs("      <dia:attribute name=\"elem_corner\">\n");
00620     dia_printf("        <dia:point val=\"%g,%g\"/>\n", cp.x - rp.x,
00621                cp.y - rp.y);
00622     dia_fputs("      </dia:attribute>\n");
00623     dia_fputs("      <dia:attribute name=\"elem_width\">\n");
00624     dia_printf("        <dia:real val=\"%g\"/>\n", rp.x + rp.x);
00625     dia_fputs("      </dia:attribute>\n");
00626     dia_fputs("      <dia:attribute name=\"elem_height\">\n");
00627     dia_printf("        <dia:real val=\"%g\"/>\n", rp.y + rp.y);
00628     dia_fputs("      </dia:attribute>\n");
00629     dia_fputs("      <dia:attribute name=\"obj_pos\">\n");
00630     dia_printf("        <dia:point val=\"%g,%g\"/>\n", cp.x - rp.x,
00631                cp.y - rp.y);
00632     dia_fputs("      </dia:attribute>\n");
00633     dia_fputs("      <dia:attribute name=\"obj_bb\">\n");
00634     dia_printf("        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00635                cp.x - rp.x - .11, cp.y - rp.y - .11, cp.x + rp.x + .11,
00636                cp.y + rp.y + .11);
00637     dia_fputs("      </dia:attribute>\n");
00638     dia_grstyle(&cstk[SP]);
00639     dia_grstylefill(&cstk[SP], filled);
00640     dia_fputs("    </dia:object>\n");
00641 }
00642 
00643 
00644 int ellipse_connection(pointf cp, pointf p)
00645 {
00646     int conn = 0;
00647 
00648     if (cp.x == p.x) {
00649         if (cp.y > p.y)
00650             conn = 1;
00651         else
00652             conn = 6;
00653     } else if (cp.y == p.y) {
00654         if (cp.x > p.x)
00655             conn = 3;
00656         else
00657             conn = 4;
00658     } else if (cp.x < p.x) {
00659         if (cp.y < p.y)
00660             conn = 7;
00661         else
00662             conn = 2;
00663     } else if (cp.x > p.x) {
00664         if (cp.y < p.y)
00665             conn = 5;
00666         else
00667             conn = 0;
00668     }
00669 
00670     return conn;
00671 }
00672 
00673 
00674 int box_connection(node_t * n, pointf p)
00675 {
00676     int i = 0, j, sides, conn = 0, peripheries, z;
00677     double xsize, ysize, mindist2 = 0.0, dist2;
00678     polygon_t *poly;
00679     pointf P, *vertices;
00680     static point *A;
00681     static int A_size;
00682 
00683     poly = (polygon_t *) ND_shape_info(n);
00684     vertices = poly->vertices;
00685     sides = poly->sides;
00686     peripheries = poly->peripheries;
00687 
00688     if (A_size < sides) {
00689         A_size = sides + 5;
00690         A = ALLOC(A_size, A, point);
00691     }
00692 
00693     xsize = ((ND_lw_i(n) + ND_rw_i(n)) / POINTS(ND_width(n))) * 16.0;
00694     ysize = ((ND_ht_i(n)) / POINTS(ND_height(n))) * 16.0;
00695 
00696     for (j = 0; j < peripheries; j++) {
00697         for (i = 0; i < sides; i++) {
00698             P = vertices[i + j * sides];
00699 /* simple rounding produces random results around .5 
00700  * this trick should clip off the random part. 
00701  * (note xsize/ysize prescaled by 16.0 above) */
00702             A[i].x = ROUND(P.x * xsize) / 16;
00703             A[i].y = ROUND(P.y * ysize) / 16;
00704             if (sides > 2) {
00705                 A[i].x += ND_coord_i(n).x;
00706                 A[i].y += ND_coord_i(n).y;
00707             }
00708         }
00709     }
00710 
00711     z = 0;
00712     while (z < i) {
00713         dist2 = DIST2(p, diapt(A[z]));
00714         if (z == 0) {
00715             mindist2 = dist2;
00716             conn = 0;
00717         }
00718         if (dist2 < mindist2) {
00719             mindist2 = dist2;
00720             conn = 2 * z;
00721         }
00722         z++;
00723     }
00724 
00725     z = 0;
00726     while (z < i) {
00727         P.x = (diapt(A[z]).x + diapt(A[z + 1]).x) / 2;
00728         P.y = (diapt(A[z]).y + diapt(A[z + 1]).y) / 2;
00729         dist2 = DIST2(p, P);
00730         if (dist2 < mindist2) {
00731             mindist2 = dist2;
00732             conn = 2 * z + 1;
00733         }
00734         z++;
00735     }
00736 
00737     return conn;
00738 }
00739 
00740 
00741 static void
00742 dia_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled)
00743 {
00744     int i, conn_h, conn_t;
00745     pointf p, firstp = { 0, 0 }, llp = {
00746     0, 0}, urp = {
00747     0, 0};
00748     node_t *head, *tail;
00749     char *shape_t;
00750     pointf cp_h, cp_t;
00751 
00752     if (cstk[SP].pen == P_NONE) {
00753         /* its invisible, don't draw */
00754         return;
00755     }
00756 
00757     dia_printf
00758         ("    <dia:object type=\"Standard - BezierLine\" version=\"0\" id=\"%s\">\n",
00759          "00");
00760     dia_fputs("       <dia:attribute name=\"bez_points\">\n");
00761     for (i = 0; i < n; i++) {
00762         p = diapt(A[i]);
00763         if (!i)
00764             llp = urp = firstp = p;
00765         if (p.x < llp.x || p.y < llp.y)
00766             llp = p;
00767         if (p.x > urp.x || p.y > urp.y)
00768             urp = p;
00769         dia_printf("        <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00770     }
00771     dia_fputs("      </dia:attribute>\n");
00772     dia_grstyle(&cstk[SP]);
00773     dia_fputs("      <dia:attribute name=\"obj_pos\">\n");
00774     dia_printf("        <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
00775     dia_fputs("      </dia:attribute>\n");
00776     dia_fputs("      <dia:attribute name=\"obj_bb\">\n");
00777     dia_printf("        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00778                llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
00779     dia_fputs("      </dia:attribute>\n");
00780 
00781     if (Curedge) {
00782         conn_h = conn_t = -1;
00783 
00784         head = Curedge->head;
00785         tail = Curedge->tail;
00786 
00787         shape_t = ND_shape(tail)->name;
00788 
00789         /* arrowheads */
00790         if (arrow_at_start) {
00791             dia_fputs("      <dia:attribute name=\"start_arrow\">\n");
00792             dia_fputs("          <dia:enum val=\"3\"/>\n");
00793             dia_fputs("      </dia:attribute>\n");
00794             dia_fputs("      <dia:attribute name=\"start_arrow_length\">\n");
00795             dia_fputs("         <dia:real val=\"0.8\"/>\n");
00796             dia_fputs("      </dia:attribute>\n");
00797             dia_fputs
00798                 ("               <dia:attribute name=\"start_arrow_width\">\n");
00799             dia_fputs("                 <dia:real val=\"0.8\"/>\n");
00800             dia_fputs("      </dia:attribute>\n");
00801         }
00802         if (arrow_at_end) {
00803             dia_fputs("      <dia:attribute name=\"end_arrow\">\n");
00804             dia_fputs("          <dia:enum val=\"3\"/>\n");
00805             dia_fputs("      </dia:attribute>\n");
00806             dia_fputs("      <dia:attribute name=\"end_arrow_length\">\n");
00807             dia_fputs("         <dia:real val=\"0.8\"/>\n");
00808             dia_fputs("      </dia:attribute>\n");
00809             dia_fputs
00810                 ("               <dia:attribute name=\"end_arrow_width\">\n");
00811             dia_fputs("                 <dia:real val=\"0.8\"/>\n");
00812             dia_fputs("      </dia:attribute>\n");
00813         }
00814     
00815         dia_fputs("      <dia:attribute name=\"conn_endpoints\">\n");
00816         dia_printf("        <dia:point val=\"%g,%g\"/>\n", diapt(A[0]).x,
00817                    diapt(A[0]).y);
00818         dia_printf("        <dia:point val=\"%g,%g\"/>\n", diapt(A[n - 1]).x,
00819                    diapt(A[n - 1]).y);
00820         dia_fputs("      </dia:attribute>\n");
00821         dia_fputs("      <dia:connections>\n");
00822     
00823         if ((strcmp(shape_t, "ellipse") == 0)
00824             || (strcmp(shape_t, "circle") == 0)
00825             || (strcmp(shape_t, "doublecircle") == 0)) {
00826             cp_h = diapt(ND_coord_i(head));
00827             if (AG_IS_DIRECTED(Rootgraph))
00828                 conn_h = ellipse_connection(cp_h, diapt(A[n - 1]));
00829             else
00830                 conn_h = ellipse_connection(cp_h, diapt(A[0]));
00831         } else {
00832             if (AG_IS_DIRECTED(Rootgraph))
00833                 conn_h = box_connection(head, diapt(A[n - 1]));
00834             else
00835                 conn_h = box_connection(head, diapt(A[0]));
00836         }
00837     
00838         if ((strcmp(shape_t, "ellipse") == 0)
00839             || (strcmp(shape_t, "circle") == 0)
00840             || (strcmp(shape_t, "doublecircle") == 0)) {
00841             cp_t = diapt(ND_coord_i(tail));
00842             if (AG_IS_DIRECTED(Rootgraph))
00843                 conn_t = ellipse_connection(cp_t, diapt(A[0]));
00844             else
00845                 conn_t = ellipse_connection(cp_t, diapt(A[n - 1]));
00846         } else {
00847             if (AG_IS_DIRECTED(Rootgraph))
00848                 conn_t = box_connection(tail, diapt(A[0]));
00849             else
00850                 conn_t = box_connection(tail, diapt(A[n - 1]));
00851         }
00852 
00853         if (arrow_at_start) {
00854             dia_printf
00855                 ("        <dia:connection handle=\"0\" to=\"%d\" connection=\"%d\"/>\n",
00856                  head->id, conn_h);
00857             dia_printf
00858                 ("        <dia:connection handle=\"%d\" to=\"%d\" connection=\"%d\"/>\n",
00859                  (n - 1), tail->id, conn_t);
00860         } else {
00861             dia_printf
00862                 ("        <dia:connection handle=\"0\" to=\"%d\" connection=\"%d\"/>\n",
00863                  tail->id, conn_t);
00864             dia_printf
00865                 ("        <dia:connection handle=\"%d\" to=\"%d\" connection=\"%d\"/>\n",
00866                  (n - 1), head->id, conn_h);
00867         }
00868     
00869         dia_fputs("      </dia:connections>\n");
00870     }
00871     dia_fputs("    </dia:object>\n");
00872 }
00873 
00874 
00875 
00876 static void dia_polygon(point * A, int n, int filled)
00877 {
00878     int i;
00879     pointf p, firstp = { 0, 0 }, llp = {
00880     0, 0}, urp = {
00881     0, 0};
00882 
00883     if (cstk[SP].pen == P_NONE) {
00884         /* its invisible, don't draw */
00885         return;
00886     }
00887 
00888     switch (Obj) {
00889     case NODE:
00890         dia_printf
00891             ("    <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%d\">\n",
00892              Curnode->id);
00893         break;
00894     case EDGE:
00895         return;
00896         break;
00897     case CLST:
00898         dia_printf
00899             ("    <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%s\">\n",
00900              Curgraph->name);
00901         break;
00902     default:
00903         dia_printf
00904             ("    <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%s\">\n",
00905              "polygon");
00906         break;
00907     }
00908     dia_fputs("       <dia:attribute name=\"poly_points\">\n");
00909     for (i = 0; i < n; i++) {
00910         p = diapt(A[i]);
00911         if (!i)
00912             llp = urp = firstp = p;
00913         if (p.x < llp.x || p.y < llp.y)
00914             llp = p;
00915         if (p.x > urp.x || p.y > urp.y)
00916             urp = p;
00917         dia_printf("        <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00918     }
00919     dia_fputs("      </dia:attribute>\n");
00920     dia_fputs("      <dia:attribute name=\"obj_pos\">\n");
00921     dia_printf("        <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
00922     dia_fputs("      </dia:attribute>\n");
00923     dia_fputs("      <dia:attribute name=\"obj_bb\">\n");
00924     dia_printf("        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00925                llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
00926     dia_fputs("      </dia:attribute>\n");
00927     dia_grstyle(&cstk[SP]);
00928     dia_grstylefill(&cstk[SP], filled);
00929     dia_fputs("    </dia:object>\n");
00930 }
00931 
00932 static void dia_polyline(point * A, int n)
00933 {
00934     int i;
00935     pointf p, firstp = { 0, 0 }, llp = {
00936     0, 0}, urp = {
00937     0, 0};
00938 
00939     if (cstk[SP].pen == P_NONE) {
00940         /* its invisible, don't draw */
00941         return;
00942     }
00943     dia_printf
00944         ("    <dia:object type=\"Standard - PolyLine\" version=\"0\" id=\"%s\">\n",
00945          "0");
00946     dia_fputs("      <dia:attribute name=\"poly_points\">\n");
00947     for (i = 0; i < n; i++) {
00948         p = diapt(A[i]);
00949         if (!i)
00950             llp = urp = firstp = p;
00951         if (p.x < llp.x || p.y < llp.y)
00952             llp = p;
00953         if (p.x > urp.x || p.y > urp.y)
00954             urp = p;
00955         dia_printf("<dia:point val=\"%g,%g\"/>\n", p.x, p.y);
00956     }
00957     dia_fputs("      </dia:attribute>\n");
00958     dia_grstyle(&cstk[SP]);
00959     dia_fputs("      <dia:attribute name=\"obj_pos\">\n");
00960     dia_printf("        <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
00961     dia_fputs("      </dia:attribute>\n");
00962     dia_fputs("      <dia:attribute name=\"obj_bb\">\n");
00963     dia_printf("        <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
00964                llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
00965     dia_fputs("      </dia:attribute>\n");
00966     dia_fputs("    </dia:object>\n");
00967 }
00968 
00969 static void dia_usershape(usershape_t *us, boxf b, point *A, int n, boolean filled)
00970 {
00971     char *imagefile;
00972 
00973     if (cstk[SP].pen == P_NONE) {
00974         /* its invisible, don't draw */
00975         return;
00976     }
00977 
00978 #if 0
00979 /* FIXME */
00980     imagefile = agget(Curnode, "shapefile");
00981 #else
00982     imagefile = NULL;
00983 #endif
00984 
00985     if (! imagefile) {
00986         dia_polygon(A, n, filled);
00987         return;
00988     }
00989 }
00990 
00991 codegen_t DIA_CodeGen = {
00992     dia_reset,
00993     dia_begin_job, dia_end_job,
00994     dia_begin_graph, dia_end_graph,
00995     dia_begin_page, dia_end_page,
00996     0, /* dia_begin_layer */ 0, /* dia_end_layer */
00997     dia_begin_cluster, dia_end_cluster,
00998     0, /* dia_begin_nodes */ 0, /* dia_end_nodes */
00999     0, /* dia_begin_edges */ 0, /* dia_end_edges */
01000     dia_begin_node, dia_end_node,
01001     dia_begin_edge, dia_end_edge,
01002     dia_begin_context, dia_end_context,
01003     0, /* dia_begin_anchor */ 0,        /* dia_end_anchor */
01004     dia_set_font, dia_textpara,
01005     dia_set_pencolor, dia_set_fillcolor, dia_set_style,
01006     dia_ellipse, dia_polygon,
01007     dia_bezier, dia_polyline,
01008     1,                          /* bezier_has_arrows */
01009     dia_comment,
01010     dia_usershape
01011 };

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