00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00032 #define REGULAR 0
00033 #define BOLD 1
00034 #define ITALIC 2
00035
00036
00037 #define P_SOLID 0
00038 #define P_NONE 15
00039 #define P_DOTTED 4
00040 #define P_DASHED 11
00041
00042
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
00055 #if 0
00056
00057 static char *sdarray = "5,2";
00058
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
00065
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
00105
00106
00107
00108
00109
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
00127
00128
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
00147
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
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;
00223 cstk[0].fillcolor = "";
00224 cstk[0].fontfam = DEFAULT_FONTNAME;
00225 cstk[0].fontsz = DEFAULT_FONTSIZE;
00226 cstk[0].fontopt = REGULAR;
00227 cstk[0].pen = P_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));
00300
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
00313
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
00406
00407
00408 Scale = scale * SCALE;
00409 Rot = rot;
00410
00411
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
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
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
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
00700
00701
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
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
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
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
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
00975 return;
00976 }
00977
00978 #if 0
00979
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, 0,
00997 dia_begin_cluster, dia_end_cluster,
00998 0, 0,
00999 0, 0,
01000 dia_begin_node, dia_end_node,
01001 dia_begin_edge, dia_end_edge,
01002 dia_begin_context, dia_end_context,
01003 0, 0,
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,
01009 dia_comment,
01010 dia_usershape
01011 };