Graphviz  2.41.20171026.1811
diagen.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include "config.h"
15 
16 #include "render.h"
17 
18 #include <stdarg.h>
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 #ifdef HAVE_LIBZ
23 #include <zlib.h>
24 #endif
25 
26 /* DIA font modifiers */
27 #define REGULAR 0
28 #define BOLD 1
29 #define ITALIC 2
30 
31 /* DIA patterns */
32 #define P_SOLID 0
33 #define P_NONE 15
34 #define P_DOTTED 4 /* i wasn't sure about this */
35 #define P_DASHED 11 /* or this */
36 
37 /* DIA bold line constant */
38 #define WIDTH_NORMAL 1
39 #define WIDTH_BOLD 3
40 
41 #define DIA_RESOLUTION 1.0
42 #define SCALE (DIA_RESOLUTION/15.0)
43 
44 #define NODE 1
45 #define EDGE 2
46 #define CLST 3
47 
48 
49 /* FIXME - these are not used currently - probably something missing */
50 #if 0
51 /* DIA dash array */
52 static char *sdarray = "5,2";
53 /* DIA dot array */
54 static char *sdotarray = "1,5";
55 static int GraphURL, ClusterURL, NodeURL, EdgeURL;
56 static char *op[] = { "graph", "node", "edge", "graph" };
57 #endif
58 
59 /* static int N_pages; */
60 /* static point Pages; */
61 static double Scale;
62 static pointf Offset;
63 static int Rot;
64 static box PB;
65 static int onetime = TRUE;
66 
67 static node_t *Curnode;
68 static edge_t *Curedge;
69 static graph_t *Curgraph, *Rootgraph;
70 
71 typedef struct context_t {
74  double fontsz;
75 } context_t;
76 
77 #define MAXNEST 4
78 static context_t cstk[MAXNEST];
79 static int SP;
80 
81 #ifdef HAVE_LIBZ
82 static gzFile Zfile;
83 #endif
84 
85 static int dia_fputs(char *s)
86 {
87  int len;
88 
89  len = strlen(s);
90 
91 #ifdef HAVE_LIBZ
92  return gzwrite(Zfile, s, (unsigned) len);
93 #else
94  return 0;
95 #endif
96 }
97 
98 
99 /* dia_printf:
100  * Note that this function is unsafe due to the fixed buffer size.
101  * It should only be used when the caller is sure the input will not
102  * overflow the buffer. In particular, it should be avoided for
103  * input coming from users. Also, if vsnprintf is available, the
104  * code should check for return values to use it safely.
105  */
106 static int dia_printf(const char *format, ...)
107 {
108  char buf[BUFSIZ];
109  va_list argp;
110  int len;
111 
112  va_start(argp, format);
113 #ifdef HAVE_VSNPRINTF
114  (void) vsnprintf(buf, sizeof(buf), format, argp);
115 #else
116  (void) vsprintf(buf, format, argp);
117 #endif
118  va_end(argp);
119  len = strlen(buf);
120 
121  /* some *sprintf (e.g C99 std)
122  don't return the number of
123  bytes actually written */
124 
125 #ifdef HAVE_LIBZ
126  return gzwrite(Zfile, buf, (unsigned) len);
127 #else
128  return 0;
129 #endif
130 }
131 
132 #define SVG_COLORS_P 0
133 
134 static int dia_comparestr(const void *s1, const void *s2)
135 {
136  return strcmp(*(char **) s1, *(char **) s2);
137 }
138 
139 static char *dia_resolve_color(char *name)
140 {
141 /* color names from http://www.w3.org/TR/SVG/types.html */
142 /* NB. List must be LANG_C sorted */
143  static char *svg_known_colors[] = {
144  "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure",
145  "beige", "bisque", "black", "blanchedalmond", "blue",
146  "blueviolet", "brown", "burlywood",
147  "cadetblue", "chartreuse", "chocolate", "coral",
148  "cornflowerblue", "cornsilk", "crimson", "cyan",
149  "darkblue", "darkcyan", "darkgoldenrod", "darkgray",
150  "darkgreen", "darkgrey", "darkkhaki", "darkmagenta",
151  "darkolivegreen", "darkorange", "darkorchid", "darkred",
152  "darksalmon", "darkseagreen", "darkslateblue", "darkslategray",
153  "darkslategrey", "darkturquoise", "darkviolet", "deeppink",
154  "deepskyblue", "dimgray", "dimgrey", "dodgerblue",
155  "firebrick", "floralwhite", "forestgreen", "fuchsia",
156  "gainsboro", "ghostwhite", "gold", "goldenrod", "gray",
157  "green", "greenyellow", "grey",
158  "honeydew", "hotpink", "indianred",
159  "indigo", "ivory", "khaki",
160  "lavender", "lavenderblush", "lawngreen", "lemonchiffon",
161  "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow",
162  "lightgray", "lightgreen", "lightgrey", "lightpink",
163  "lightsalmon", "lightseagreen", "lightskyblue",
164  "lightslategray", "lightslategrey", "lightsteelblue",
165  "lightyellow", "lime", "limegreen", "linen",
166  "magenta", "maroon", "mediumaquamarine", "mediumblue",
167  "mediumorchid", "mediumpurple", "mediumseagreen",
168  "mediumslateblue", "mediumspringgreen", "mediumturquoise",
169  "mediumvioletred", "midnightblue", "mintcream",
170  "mistyrose", "moccasin",
171  "navajowhite", "navy", "oldlace",
172  "olive", "olivedrab", "orange", "orangered", "orchid",
173  "palegoldenrod", "palegreen", "paleturquoise",
174  "palevioletred", "papayawhip", "peachpuff", "peru", "pink",
175  "plum", "powderblue", "purple",
176  "red", "rosybrown", "royalblue",
177  "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell",
178  "sienna", "silver", "skyblue", "slateblue", "slategray",
179  "slategrey", "snow", "springgreen", "steelblue",
180  "tan", "teal", "thistle", "tomato", "turquoise",
181  "violet",
182  "wheat", "white", "whitesmoke",
183  "yellow", "yellowgreen",
184  };
185 
186  static char buf[SMALLBUF];
187  char *tok;
188  gvcolor_t color;
189 
190  tok = canontoken(name);
191  if (!SVG_COLORS_P || (bsearch(&tok, svg_known_colors,
192  sizeof(svg_known_colors) / sizeof(char *),
193  sizeof(char *), dia_comparestr) == NULL)) {
194  /* if tok was not found in known_colors */
195  if (streq(tok, "transparent")) {
196  tok = "none";
197  } else {
198  colorxlate(name, &color, RGBA_BYTE);
199  sprintf(buf, "#%02x%02x%02x",
200  color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
201  tok = buf;
202  }
203  }
204  return tok;
205 }
206 
207 
208 static void dia_reset(void)
209 {
210  onetime = TRUE;
211 }
212 
213 
214 static void init_dia(void)
215 {
216  SP = 0;
217  cstk[0].pencolor = DEFAULT_COLOR; /* DIA pencolor */
218  cstk[0].fillcolor = ""; /* DIA fillcolor */
219  cstk[0].fontfam = DEFAULT_FONTNAME; /* font family name */
220  cstk[0].fontsz = DEFAULT_FONTSIZE; /* font size */
221  cstk[0].fontopt = REGULAR; /* modifier: REGULAR, BOLD or ITALIC */
222  cstk[0].pen = P_SOLID; /* pen pattern style, default is solid */
223  cstk[0].fill = P_NONE;
224  cstk[0].penwidth = WIDTH_NORMAL;
225 }
226 
227 static pointf diapt(point p)
228 {
229  pointf rv;
230 
231  if (Rot == 0) {
232  rv.x = PB.LL.x + p.x * Scale + Offset.x;
233  rv.y = PB.UR.y - 1 - p.y * Scale - Offset.y;
234  } else {
235  rv.x = PB.UR.x - 1 - p.y * Scale - Offset.x;
236  rv.y = PB.UR.y - 1 - p.x * Scale - Offset.y;
237  }
238  return rv;
239 }
240 
241 static pointf diaptf(pointf p)
242 {
243  pointf rv;
244 
245  if (Rot == 0) {
246  rv.x = PB.LL.x + p.x * Scale + Offset.x;
247  rv.y = PB.UR.y - 1 - p.y * Scale - Offset.y;
248  } else {
249  rv.x = PB.UR.x - 1 - p.y * Scale - Offset.x;
250  rv.y = PB.UR.y - 1 - p.x * Scale - Offset.y;
251  }
252  return rv;
253 }
254 
255 static void dia_grstyle(context_t * cp)
256 {
257  if (strcmp(cp->pencolor, DEFAULT_COLOR)) {
258  dia_fputs(" <dia:attribute name=\"border_color\">\n");
259  dia_printf(" <dia:color val=\"%s\"/>\n",
260  dia_resolve_color(cp->pencolor));
261  dia_fputs(" </dia:attribute>\n");
262  }
263  if (cp->penwidth != WIDTH_NORMAL) {
264  dia_fputs(" <dia:attribute name=\"line_width\">\n");
265  dia_printf(" <dia:real val=\"%g\"/>\n",
266  Scale * (cp->penwidth));
267  dia_fputs(" </dia:attribute>\n");
268  }
269  if (cp->pen == P_DASHED) {
270  dia_fputs(" <dia:attribute name=\"line_style\">\n");
271  dia_printf(" <dia:real val=\"%d\"/>\n", 1);
272  dia_fputs(" </dia:attribute>\n");
273 #if 0
274  } else if (cp->pen == P_DOTTED) {
275  dia_printf("stroke-dasharray:%s;", sdotarray);
276 #endif
277  }
278 }
279 
280 static void dia_grstylefill(context_t * cp, int filled)
281 {
282  if (filled) {
283  dia_fputs(" <dia:attribute name=\"inner_color\">\n");
284  dia_printf(" <dia:color val=\"%s\"/>\n",
285  dia_resolve_color(cp->fillcolor));
286  dia_fputs(" </dia:attribute>\n");
287  } else {
288  dia_fputs(" <dia:attribute name=\"show_background\">\n");
289  dia_printf(" <dia:boolean val=\"%s\"/>\n", "true");
290  dia_fputs(" </dia:attribute>\n");
291  }
292 }
293 
294 static void dia_comment(char *str)
295 {
296  dia_fputs("<!-- ");
297  dia_fputs(xml_string(str));
298  dia_fputs(" -->\n");
299 }
300 
301 static void
302 dia_begin_job(FILE * ofp, graph_t * g, const char **lib, char *info[], point pages)
303 {
304 #if HAVE_LIBZ
305  int fd;
306 
307  fd = dup(fileno(Output_file)); /* open dup so can gzclose
308  independent of FILE close */
309  Zfile = gzdopen(fd, "wb");
310  if (!Zfile) {
311  agerr(AGERR, "Error opening compressed output file\n");
312  exit(1);
313  }
314 #else
315  agerr(AGERR,
316  "No support for compressed output. Not compiled with zlib.\n");
317  exit(1);
318 #endif
319 
320 /* Pages = pages; */
321 /* N_pages = pages.x * pages.y; */
322  dia_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
323 
324 }
325 
326 static void dia_end_job(void)
327 {
328 }
329 
330 static void dia_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
331 {
332  Rootgraph = g;
333  PB.LL.x = PB.LL.y = 0;
334  PB.UR.x = (bb.UR.x - bb.LL.x + 2 * GD_drawing(g)->margin.x) * SCALE;
335  PB.UR.y = (bb.UR.y - bb.LL.y + 2 * GD_drawing(g)->margin.y) * SCALE;
336  Offset.x = GD_drawing(g)->margin.x * SCALE;
337  Offset.y = GD_drawing(g)->margin.y * SCALE;
338  if (onetime) {
339  init_dia();
340  onetime = FALSE;
341  }
342  dia_fputs
343  ("<dia:diagram xmlns:dia=\"http://www.lysator.liu.se/~alla/dia/\">\n");
344  dia_fputs(" <dia:diagramdata>\n");
345  dia_fputs(" <dia:attribute name=\"background\">\n");
346  dia_fputs(" <dia:color val=\"#ffffff\"/>\n");
347  dia_fputs(" </dia:attribute>\n");
348  dia_fputs(" <dia:attribute name=\"paper\">\n");
349  dia_fputs(" <dia:composite type=\"paper\">\n");
350  dia_fputs(" <dia:attribute name=\"name\">\n");
351  dia_fputs(" <dia:string>#A4#</dia:string>\n");
352  dia_fputs(" </dia:attribute>\n");
353  dia_fputs(" <dia:attribute name=\"tmargin\">\n");
354  dia_fputs(" <dia:real val=\"2.8222\"/>\n");
355  dia_fputs(" </dia:attribute>\n");
356  dia_fputs(" <dia:attribute name=\"bmargin\">\n");
357  dia_fputs(" <dia:real val=\"2.8222\"/>\n");
358  dia_fputs(" </dia:attribute>\n");
359  dia_fputs(" <dia:attribute name=\"lmargin\">\n");
360  dia_fputs(" <dia:real val=\"2.8222\"/>\n");
361  dia_fputs(" </dia:attribute>\n");
362  dia_fputs(" <dia:attribute name=\"rmargin\">\n");
363  dia_fputs(" <dia:real val=\"2.8222\"/>\n");
364  dia_fputs(" </dia:attribute>\n");
365  dia_fputs(" <dia:attribute name=\"is_portrait\">\n");
366  dia_fputs(" <dia:boolean val=\"true\"/>\n");
367  dia_fputs(" </dia:attribute>\n");
368  dia_fputs(" <dia:attribute name=\"scaling\">\n");
369  dia_fputs(" <dia:real val=\"1\"/>\n");
370  dia_fputs(" </dia:attribute>\n");
371  dia_fputs(" <dia:attribute name=\"fitto\">\n");
372  dia_fputs(" <dia:boolean val=\"false\"/>\n");
373  dia_fputs(" </dia:attribute>\n");
374  dia_fputs(" </dia:composite>\n");
375  dia_fputs(" </dia:attribute>\n");
376  dia_fputs(" <dia:attribute name=\"grid\">\n");
377  dia_fputs(" <dia:composite type=\"grid\">\n");
378  dia_fputs(" <dia:attribute name=\"width_x\">\n");
379  dia_fputs(" <dia:real val=\"1\"/>\n");
380  dia_fputs(" </dia:attribute>\n");
381  dia_fputs(" <dia:attribute name=\"width_y\">\n");
382  dia_fputs(" <dia:real val=\"1\"/>\n");
383  dia_fputs(" </dia:attribute>\n");
384  dia_fputs(" <dia:attribute name=\"visible_x\">\n");
385  dia_fputs(" <dia:int val=\"1\"/>\n");
386  dia_fputs(" </dia:attribute>\n");
387  dia_fputs(" <dia:attribute name=\"visible_y\">\n");
388  dia_fputs(" <dia:int val=\"1\"/>\n");
389  dia_fputs(" </dia:attribute>\n");
390  dia_fputs(" </dia:composite>\n");
391  dia_fputs(" </dia:attribute>\n");
392  dia_fputs(" <dia:attribute name=\"guides\">\n");
393  dia_fputs(" <dia:composite type=\"guides\">\n");
394  dia_fputs(" <dia:attribute name=\"hguides\"/>\n");
395  dia_fputs(" <dia:attribute name=\"vguides\"/>\n");
396  dia_fputs(" </dia:composite>\n");
397  dia_fputs(" </dia:attribute>\n");
398  dia_fputs(" </dia:diagramdata>\n");
399 }
400 
401 static void dia_end_graph(void)
402 {
403  dia_printf("</dia:diagram>\n");
404 #ifdef HAVE_LIBZ
405  gzclose(Zfile);
406 #endif
407 }
408 
409 static void
410 dia_begin_page(graph_t * g, point page, double scale, int rot,
411  point offset)
412 {
413  /* int page_number; */
414  /* point sz; */
415 
416  Scale = scale * SCALE;
417  Rot = rot;
418  /* page_number = page.x + page.y * Pages.x + 1; */
419  /* sz = sub_points(PB.UR,PB.LL); */
420 
421  dia_printf(" <dia:layer name=\"Background\" visible=\"true\">\n");
422 }
423 
424 static void dia_end_page(void)
425 {
426  dia_fputs(" </dia:layer>\n");
427 }
428 
429 static void dia_begin_cluster(graph_t * g)
430 {
431  dia_printf("<dia:group>\n");
432  Curgraph = g;
433 }
434 
435 static void dia_end_cluster(void)
436 {
437  dia_printf("</dia:group>\n");
438 }
439 
440 static void dia_begin_node(node_t * n)
441 {
442  dia_printf("<dia:group>\n");
443  Curnode = n;
444 }
445 
446 static void dia_end_node(void)
447 {
448  dia_printf("</dia:group>\n");
449 }
450 
451 static void dia_begin_edge(edge_t * e)
452 {
453  Curedge = e;
454 }
455 
456 static void dia_end_edge(void)
457 {
458  Curedge = NULL;
459 }
460 
461 static void dia_begin_context(void)
462 {
463  assert(SP + 1 < MAXNEST);
464  cstk[SP + 1] = cstk[SP];
465  SP++;
466 }
467 
468 static void dia_end_context(void)
469 {
470  int psp = SP - 1;
471  assert(SP > 0);
472  /*free(cstk[psp].fontfam); */
473  SP = psp;
474 }
475 
476 static void dia_set_font(char *name, double size)
477 {
478  char *p;
479  context_t *cp;
480 
481  cp = &(cstk[SP]);
482  cp->font_was_set = TRUE;
483  cp->fontsz = size;
484  p = strdup(name);
485  cp->fontfam = p;
486 }
487 
488 static void dia_set_pencolor(char *name)
489 {
490  cstk[SP].pencolor = name;
491 }
492 
493 static void dia_set_fillcolor(char *name)
494 {
495  cstk[SP].fillcolor = name;
496 }
497 
498 static void dia_set_style(char **s)
499 {
500  char *line, *p;
501  context_t *cp;
502 
503  cp = &(cstk[SP]);
504  while ((p = line = *s++)) {
505  if (streq(line, "solid"))
506  cp->pen = P_SOLID;
507  else if (streq(line, "dashed"))
508  cp->pen = P_DASHED;
509  else if (streq(line, "dotted"))
510  cp->pen = P_DOTTED;
511  else if (streq(line, "invis"))
512  cp->pen = P_NONE;
513  else if (streq(line, "bold"))
514  cp->penwidth = WIDTH_BOLD;
515  else if (streq(line, "setlinewidth")) {
516  while (*p)
517  p++;
518  p++;
519  cp->penwidth = atol(p);
520  } else if (streq(line, "filled"))
521  cp->fill = P_SOLID;
522  else if (streq(line, "unfilled"))
523  cp->fill = P_NONE;
524  else {
525  agerr(AGWARN,
526  "dia_set_style: unsupported style %s - ignoring\n",
527  line);
528  }
529  cp->style_was_set = TRUE;
530  }
531  /* if (cp->style_was_set) dia_style(cp); */
532 }
533 
534 static void dia_textpara(point p, textpara_t * para)
535 {
536  int anchor;
537  pointf mp;
538  context_t *cp;
539 
540  cp = &(cstk[SP]);
541  switch (para->just) {
542  case 'l':
543  anchor = 0;
544  break;
545  case 'r':
546  anchor = 2;
547  break;
548  default:
549  case 'n':
550  anchor = 1;
551  break;
552  }
553 
554  mp = diapt(p);
555  dia_printf
556  (" <dia:object type=\"Standard - Text\" version=\"0\" id=\"%s\">\n",
557  "0");
558  dia_fputs(" <dia:attribute name=\"text\">\n");
559  dia_fputs(" <dia:composite type=\"text\">\n");
560  dia_fputs(" <dia:attribute name=\"string\">\n");
561  dia_fputs(" <dia:string>#");
562  dia_fputs(xml_string(para->str));
563  dia_fputs("#</dia:string>\n");
564  dia_fputs(" </dia:attribute>\n");
565  dia_fputs(" <dia:attribute name=\"font\">\n");
566  dia_printf(" <dia:font name=\"%s\"/>\n", cp->fontfam);
567  dia_fputs(" </dia:attribute>\n");
568  dia_fputs(" <dia:attribute name=\"height\">\n");
569  dia_printf(" <dia:real val=\"%g\"/>\n",
570  Scale * (cp->fontsz));
571  dia_fputs(" </dia:attribute>\n");
572  dia_fputs(" <dia:attribute name=\"pos\">\n");
573  dia_printf(" <dia:point val=\"%g,%g\"/>\n", mp.x, mp.y);
574  dia_fputs(" </dia:attribute>\n");
575  dia_fputs(" <dia:attribute name=\"color\">\n");
576  dia_printf(" <dia:color val=\"%s\"/>\n",
577  dia_resolve_color(cp->pencolor));
578  dia_fputs(" </dia:attribute>\n");
579  dia_fputs(" <dia:attribute name=\"alignment\">\n");
580  dia_printf(" <dia:enum val=\"%d\"/>\n", anchor);
581  dia_fputs(" </dia:attribute>\n");
582  dia_fputs(" </dia:composite>\n");
583  dia_fputs(" </dia:attribute>\n");
584  dia_fputs(" <dia:attribute name=\"obj_pos\">\n");
585  dia_printf(" <dia:point val=\"%g,%g\"/>\n", mp.x, mp.y);
586  dia_fputs(" </dia:attribute>\n");
587  dia_fputs(" <dia:attribute name=\"obj_bb\">\n");
588  dia_printf(" <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
589  mp.x - (Scale * (para->width) / 2.), mp.y - 0.4,
590  mp.x + (Scale * (para->width) / 2.), mp.y + 0.4);
591  dia_fputs(" </dia:attribute>\n");
592  dia_fputs(" </dia:object>\n");
593 }
594 
595 static void dia_ellipse(point p, int rx, int ry, int filled)
596 {
597  pointf cp, rp;
598  int nodeId;
599 
600  switch (Obj) {
601  case NODE:
602  nodeId = AGID(Curnode);
603  break;
604  default:
605  nodeId = -1;
606  break;
607  }
608 
609  if (cstk[SP].pen == P_NONE) {
610  /* its invisible, don't draw */
611  return;
612  }
613  cp = diapt(p);
614 
615  if (Rot) {
616  int t;
617  t = rx;
618  rx = ry;
619  ry = t;
620  }
621  rp.x = Scale * rx;
622  rp.y = Scale * ry;
623 
624  dia_printf
625  (" <dia:object type=\"Standard - Ellipse\" version=\"0\" id=\"%d\">\n",
626  nodeId);
627  dia_fputs(" <dia:attribute name=\"elem_corner\">\n");
628  dia_printf(" <dia:point val=\"%g,%g\"/>\n", cp.x - rp.x,
629  cp.y - rp.y);
630  dia_fputs(" </dia:attribute>\n");
631  dia_fputs(" <dia:attribute name=\"elem_width\">\n");
632  dia_printf(" <dia:real val=\"%g\"/>\n", rp.x + rp.x);
633  dia_fputs(" </dia:attribute>\n");
634  dia_fputs(" <dia:attribute name=\"elem_height\">\n");
635  dia_printf(" <dia:real val=\"%g\"/>\n", rp.y + rp.y);
636  dia_fputs(" </dia:attribute>\n");
637  dia_fputs(" <dia:attribute name=\"obj_pos\">\n");
638  dia_printf(" <dia:point val=\"%g,%g\"/>\n", cp.x - rp.x,
639  cp.y - rp.y);
640  dia_fputs(" </dia:attribute>\n");
641  dia_fputs(" <dia:attribute name=\"obj_bb\">\n");
642  dia_printf(" <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
643  cp.x - rp.x - .11, cp.y - rp.y - .11, cp.x + rp.x + .11,
644  cp.y + rp.y + .11);
645  dia_fputs(" </dia:attribute>\n");
646  dia_grstyle(&cstk[SP]);
647  dia_grstylefill(&cstk[SP], filled);
648  dia_fputs(" </dia:object>\n");
649 }
650 
651 
653 {
654  int conn = 0;
655 
656  if (cp.x == p.x) {
657  if (cp.y > p.y)
658  conn = 1;
659  else
660  conn = 6;
661  } else if (cp.y == p.y) {
662  if (cp.x > p.x)
663  conn = 3;
664  else
665  conn = 4;
666  } else if (cp.x < p.x) {
667  if (cp.y < p.y)
668  conn = 7;
669  else
670  conn = 2;
671  } else if (cp.x > p.x) {
672  if (cp.y < p.y)
673  conn = 5;
674  else
675  conn = 0;
676  }
677 
678  return conn;
679 }
680 
681 
683 {
684  int i = 0, j, sides, conn = 0, peripheries, z;
685  double xsize, ysize, mindist2 = 0.0, dist2;
686  polygon_t *poly;
687  pointf P, *vertices;
688  static pointf *A;
689  static int A_size;
690 
691  poly = (polygon_t *) ND_shape_info(n);
692  vertices = poly->vertices;
693  sides = poly->sides;
694  peripheries = poly->peripheries;
695 
696  if (A_size < sides) {
697  A_size = sides + 5;
698  A = ALLOC(A_size, A, pointf);
699  }
700 
701  xsize = (ND_lw(n) + ND_rw(n)) / POINTS(ND_width(n));
702  ysize = (ND_ht(n)) / POINTS(ND_height(n));
703 
704  for (j = 0; j < peripheries; j++) {
705  for (i = 0; i < sides; i++) {
706  P = vertices[i + j * sides];
707  A[i].x = P.x * xsize;
708  A[i].y = P.y * ysize;
709  if (sides > 2) {
710  A[i].x += ND_coord(n).x;
711  A[i].y += ND_coord(n).y;
712  }
713  }
714  }
715 
716  z = 0;
717  while (z < i) {
718  dist2 = DIST2(p, diaptf(A[z]));
719  if (z == 0) {
720  mindist2 = dist2;
721  conn = 0;
722  }
723  if (dist2 < mindist2) {
724  mindist2 = dist2;
725  conn = 2 * z;
726  }
727  z++;
728  }
729 
730  z = 0;
731  while (z < i) {
732  P.x = (diaptf(A[z]).x + diaptf(A[z + 1]).x) / 2;
733  P.y = (diaptf(A[z]).y + diaptf(A[z + 1]).y) / 2;
734  dist2 = DIST2(p, P);
735  if (dist2 < mindist2) {
736  mindist2 = dist2;
737  conn = 2 * z + 1;
738  }
739  z++;
740  }
741 
742  return conn;
743 }
744 
745 
746 static void
747 dia_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled)
748 {
749  int i, conn_h, conn_t;
750  pointf p, firstp = { 0, 0 }, llp = { 0, 0}, urp = { 0, 0};
751  node_t *head, *tail;
752  char *shape_t;
753  pointf cp_h, cp_t;
754 
755  if (cstk[SP].pen == P_NONE) {
756  /* its invisible, don't draw */
757  return;
758  }
759 
760  dia_printf
761  (" <dia:object type=\"Standard - BezierLine\" version=\"0\" id=\"%s\">\n",
762  "00");
763  dia_fputs(" <dia:attribute name=\"bez_points\">\n");
764  for (i = 0; i < n; i++) {
765  p = diapt(A[i]);
766  if (!i)
767  llp = urp = firstp = p;
768  if (p.x < llp.x || p.y < llp.y)
769  llp = p;
770  if (p.x > urp.x || p.y > urp.y)
771  urp = p;
772  dia_printf(" <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
773  }
774  dia_fputs(" </dia:attribute>\n");
775  dia_grstyle(&cstk[SP]);
776  dia_fputs(" <dia:attribute name=\"obj_pos\">\n");
777  dia_printf(" <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
778  dia_fputs(" </dia:attribute>\n");
779  dia_fputs(" <dia:attribute name=\"obj_bb\">\n");
780  dia_printf(" <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
781  llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
782  dia_fputs(" </dia:attribute>\n");
783 
784  if (Curedge) {
785  conn_h = conn_t = -1;
786 
787  head = aghead(Curedge);
788  tail = agtail(Curedge);
789 
790  shape_t = ND_shape(tail)->name;
791 
792  /* arrowheads */
793  if (arrow_at_start) {
794  dia_fputs(" <dia:attribute name=\"start_arrow\">\n");
795  dia_fputs(" <dia:enum val=\"3\"/>\n");
796  dia_fputs(" </dia:attribute>\n");
797  dia_fputs(" <dia:attribute name=\"start_arrow_length\">\n");
798  dia_fputs(" <dia:real val=\"0.8\"/>\n");
799  dia_fputs(" </dia:attribute>\n");
800  dia_fputs
801  (" <dia:attribute name=\"start_arrow_width\">\n");
802  dia_fputs(" <dia:real val=\"0.8\"/>\n");
803  dia_fputs(" </dia:attribute>\n");
804  }
805  if (arrow_at_end) {
806  dia_fputs(" <dia:attribute name=\"end_arrow\">\n");
807  dia_fputs(" <dia:enum val=\"3\"/>\n");
808  dia_fputs(" </dia:attribute>\n");
809  dia_fputs(" <dia:attribute name=\"end_arrow_length\">\n");
810  dia_fputs(" <dia:real val=\"0.8\"/>\n");
811  dia_fputs(" </dia:attribute>\n");
812  dia_fputs
813  (" <dia:attribute name=\"end_arrow_width\">\n");
814  dia_fputs(" <dia:real val=\"0.8\"/>\n");
815  dia_fputs(" </dia:attribute>\n");
816  }
817 
818  dia_fputs(" <dia:attribute name=\"conn_endpoints\">\n");
819  dia_printf(" <dia:point val=\"%g,%g\"/>\n",
820  diapt(A[0]).x, diapt(A[0]).y);
821  dia_printf(" <dia:point val=\"%g,%g\"/>\n",
822  diapt(A[n - 1]).x, diapt(A[n - 1]).y);
823  dia_fputs(" </dia:attribute>\n");
824  dia_fputs(" <dia:connections>\n");
825 
826 /* FIXME !!! - What is this crap! It should just user the arrow vector. */
827  if ((strcmp(shape_t, "ellipse") == 0)
828  || (strcmp(shape_t, "circle") == 0)
829  || (strcmp(shape_t, "doublecircle") == 0)) {
830  cp_h = diaptf(ND_coord(head));
831  if (agisdirected(Rootgraph))
832 
833  conn_h = ellipse_connection(cp_h, diapt(A[n - 1]));
834  else
835  conn_h = ellipse_connection(cp_h, diapt(A[0]));
836  } else if (strcmp(shape_t, "record") == 0) {
837  } else {
838  if (agisdirected(Rootgraph))
839  conn_h = box_connection(head, diapt(A[n - 1]));
840  else
841  conn_h = box_connection(head, diapt(A[0]));
842  }
843 
844  if ((strcmp(shape_t, "ellipse") == 0)
845  || (strcmp(shape_t, "circle") == 0)
846  || (strcmp(shape_t, "doublecircle") == 0)) {
847  cp_t = diaptf(ND_coord(tail));
848  if (agisdirected(Rootgraph))
849  conn_t = ellipse_connection(cp_t, diapt(A[0]));
850  else
851  conn_t = ellipse_connection(cp_t, diapt(A[n - 1]));
852  } else if (strcmp(shape_t, "record") == 0) {
853  } else {
854  if (agisdirected(Rootgraph))
855  conn_t = box_connection(tail, diapt(A[0]));
856  else
857  conn_t = box_connection(tail, diapt(A[n - 1]));
858  }
859 
860  if (arrow_at_start) {
861  dia_printf
862  (" <dia:connection handle=\"0\" to=\"%d\" connection=\"%d\"/>\n",
863  AGID(head), conn_h);
864  dia_printf
865  (" <dia:connection handle=\"%d\" to=\"%d\" connection=\"%d\"/>\n",
866  (n - 1), AGID(tail), conn_t);
867  } else {
868  dia_printf
869  (" <dia:connection handle=\"0\" to=\"%d\" connection=\"%d\"/>\n",
870  AGID(tail), conn_t);
871  dia_printf
872  (" <dia:connection handle=\"%d\" to=\"%d\" connection=\"%d\"/>\n",
873  (n - 1), AGID(head), conn_h);
874  }
875 
876  dia_fputs(" </dia:connections>\n");
877  }
878  dia_fputs(" </dia:object>\n");
879 }
880 
881 
882 
883 static void dia_polygon(point * A, int n, int filled)
884 {
885  int i;
886  pointf p, firstp = { 0, 0 }, llp = {
887  0, 0}, urp = {
888  0, 0};
889 
890  if (cstk[SP].pen == P_NONE) {
891  /* its invisible, don't draw */
892  return;
893  }
894 
895  switch (Obj) {
896  case NODE:
897  dia_printf
898  (" <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%d\">\n",
899  AGID(Curnode));
900  break;
901  case EDGE:
902  return;
903  break;
904  case CLST:
905  dia_printf
906  (" <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%s\">\n",
907  agnameof(Curgraph));
908  break;
909  default:
910  dia_printf
911  (" <dia:object type=\"Standard - Polygon\" version=\"0\" id=\"%s\">\n",
912  "polygon");
913  break;
914  }
915  dia_fputs(" <dia:attribute name=\"poly_points\">\n");
916  for (i = 0; i < n; i++) {
917  p = diapt(A[i]);
918  if (!i)
919  llp = urp = firstp = p;
920  if (p.x < llp.x || p.y < llp.y)
921  llp = p;
922  if (p.x > urp.x || p.y > urp.y)
923  urp = p;
924  dia_printf(" <dia:point val=\"%g,%g\"/>\n", p.x, p.y);
925  }
926  dia_fputs(" </dia:attribute>\n");
927  dia_fputs(" <dia:attribute name=\"obj_pos\">\n");
928  dia_printf(" <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
929  dia_fputs(" </dia:attribute>\n");
930  dia_fputs(" <dia:attribute name=\"obj_bb\">\n");
931  dia_printf(" <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
932  llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
933  dia_fputs(" </dia:attribute>\n");
934  dia_grstyle(&cstk[SP]);
935  dia_grstylefill(&cstk[SP], filled);
936  dia_fputs(" </dia:object>\n");
937 }
938 
939 static void dia_polyline(point * A, int n)
940 {
941  int i;
942  pointf p, firstp = { 0, 0 }, llp = {
943  0, 0}, urp = {
944  0, 0};
945 
946  if (cstk[SP].pen == P_NONE) {
947  /* its invisible, don't draw */
948  return;
949  }
950  dia_printf
951  (" <dia:object type=\"Standard - PolyLine\" version=\"0\" id=\"%s\">\n",
952  "0");
953  dia_fputs(" <dia:attribute name=\"poly_points\">\n");
954  for (i = 0; i < n; i++) {
955  p = diapt(A[i]);
956  if (!i)
957  llp = urp = firstp = p;
958  if (p.x < llp.x || p.y < llp.y)
959  llp = p;
960  if (p.x > urp.x || p.y > urp.y)
961  urp = p;
962  dia_printf("<dia:point val=\"%g,%g\"/>\n", p.x, p.y);
963  }
964  dia_fputs(" </dia:attribute>\n");
965  dia_grstyle(&cstk[SP]);
966  dia_fputs(" <dia:attribute name=\"obj_pos\">\n");
967  dia_printf(" <dia:point val=\"%g,%g\"/>\n", firstp.x, firstp.y);
968  dia_fputs(" </dia:attribute>\n");
969  dia_fputs(" <dia:attribute name=\"obj_bb\">\n");
970  dia_printf(" <dia:rectangle val=\"%g,%g;%g,%g\"/>\n",
971  llp.x - .11, llp.y - .11, urp.x + .11, urp.y + .11);
972  dia_fputs(" </dia:attribute>\n");
973  dia_fputs(" </dia:object>\n");
974 }
975 
976 static void dia_usershape(usershape_t *us, boxf b, point *A, int n, boolean filled)
977 {
978  char *imagefile;
979 
980  if (cstk[SP].pen == P_NONE) {
981  /* its invisible, don't draw */
982  return;
983  }
984 
985 #if 0
986 /* FIXME */
987  imagefile = agget(Curnode, "shapefile");
988 #else
989  imagefile = NULL;
990 #endif
991 
992  if (! imagefile) {
993  dia_polygon(A, n, filled);
994  return;
995  }
996 }
997 
998 codegen_t DIA_CodeGen = {
999  dia_reset,
1000  dia_begin_job, dia_end_job,
1001  dia_begin_graph, dia_end_graph,
1002  dia_begin_page, dia_end_page,
1003  0, /* dia_begin_layer */ 0, /* dia_end_layer */
1004  dia_begin_cluster, dia_end_cluster,
1005  0, /* dia_begin_nodes */ 0, /* dia_end_nodes */
1006  0, /* dia_begin_edges */ 0, /* dia_end_edges */
1007  dia_begin_node, dia_end_node,
1008  dia_begin_edge, dia_end_edge,
1009  dia_begin_context, dia_end_context,
1010  0, /* dia_begin_anchor */ 0, /* dia_end_anchor */
1011  dia_set_font, dia_textpara,
1012  dia_set_pencolor, dia_set_fillcolor, dia_set_style,
1013  dia_ellipse, dia_polygon,
1014  dia_bezier, dia_polyline,
1015  1, /* bezier_has_arrows */
1016  dia_comment,
1017  dia_usershape
1018 };
void s1(graph_t *, node_t *)
Definition: stuff.c:686
codegen_t DIA_CodeGen
Definition: diagen.c:998
#define DEFAULT_FONTNAME
Definition: const.h:70
Definition: cgraph.h:388
union color_s::@10 u
#define head
Definition: dthdr.h:19
char * fillcolor
Definition: diagen.c:72
#define WIDTH_BOLD
Definition: diagen.c:39
#define SMALLBUF
Definition: const.h:17
#define AGID(obj)
Definition: cgraph.h:114
#define P_DASHED
Definition: diagen.c:35
#define ALLOC(size, ptr, type)
Definition: memory.h:41
char fill
Definition: diagen.c:73
#define WIDTH_NORMAL
Definition: diagen.c:38
#define assert(x)
Definition: cghdr.h:47
Definition: geom.h:28
CGRAPH_API int agisdirected(Agraph_t *g)
Definition: graph.c:182
#define EDGE
Definition: diagen.c:45
char * fontfam
Definition: diagen.c:72
Definition: color.h:34
char pen
Definition: diagen.c:73
int agerr(agerrlevel_t level, const char *fmt,...)
Definition: agerror.c:141
#define SCALE
Definition: diagen.c:42
#define ND_shape_info(n)
Definition: types.h:535
point UR
Definition: geom.h:33
int x
Definition: geom.h:26
#define POINTS(a_inches)
Definition: geom.h:67
Definition: cgraph.h:388
char * agget(void *obj, char *name)
Definition: attr.c:428
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
Definition: edge.c:525
struct context_t context_t
double fontsz
Definition: diagen.c:74
int box_connection(node_t *n, pointf p)
Definition: diagen.c:682
#define ND_ht(n)
Definition: types.h:506
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
Definition: edge.c:533
#define ND_shape(n)
Definition: types.h:534
#define DIST2(p, q)
Definition: geom.h:59
double y
Definition: geom.h:28
Definition: gvcint.h:70
char * xml_string(char *s)
Definition: labels.c:485
CGRAPH_API char * agnameof(void *)
Definition: id.c:143
#define SVG_COLORS_P
Definition: diagen.c:132
#define ND_height(n)
Definition: types.h:504
#define MAXNEST
Definition: diagen.c:77
#define DEFAULT_COLOR
Definition: const.h:51
char style_was_set
Definition: diagen.c:73
#define ND_rw(n)
Definition: types.h:531
int sides
Definition: types.h:149
point LL
Definition: geom.h:33
int ellipse_connection(pointf cp, pointf p)
Definition: diagen.c:652
Definition: grammar.c:79
char fontopt
Definition: diagen.c:72
char font_was_set
Definition: diagen.c:72
COORD dist2(Ppoint_t, Ppoint_t)
Definition: visibility.c:213
#define P_SOLID
Definition: diagen.c:32
#define CLST
Definition: diagen.c:46
if(aagss+aagstacksize-1<=aagssp)
Definition: grammar.c:1332
int colorxlate(char *str, gvcolor_t *color, color_type_t target_type)
Definition: colxlate.c:254
char * canontoken(char *str)
Definition: colxlate.c:145
#define ND_width(n)
Definition: types.h:542
#define ND_lw(n)
Definition: types.h:513
#define NULL
Definition: logic.h:39
Definition: geom.h:26
double x
Definition: geom.h:28
#define P_DOTTED
Definition: diagen.c:34
#define ND_coord(n)
Definition: types.h:496
#define streq(s, t)
Definition: cghdr.h:52
GVC_t * gvc
Definition: htmlparse.c:87
char penwidth
Definition: diagen.c:73
#define NODE
Definition: diagen.c:44
int peripheries
Definition: types.h:148
pointf * vertices
Definition: types.h:154
#define DEFAULT_FONTSIZE
Definition: const.h:64
agxbuf * str
Definition: htmlparse.c:85
struct shape_t shape_t
#define GD_drawing(g)
Definition: types.h:356
int y
Definition: geom.h:26
unsigned char rgba[4]
Definition: color.h:38
char * pencolor
Definition: diagen.c:72
Definition: geom.h:35
#define FALSE
Definition: cgraph.h:35
#define P_NONE
Definition: diagen.c:33
Definition: geom.h:33
#define REGULAR
Definition: diagen.c:27
#define TRUE
Definition: cgraph.h:38