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