~ubuntu-branches/ubuntu/precise/graphviz/precise-security

« back to all changes in this revision

Viewing changes to lib/common/diagen.c

  • Committer: Bazaar Package Importer
  • Author(s): David Claughton
  • Date: 2010-03-24 22:45:18 UTC
  • mfrom: (1.2.7 upstream) (6.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100324224518-do441tthbqjaqjzd
Tags: 2.26.3-4
Add patch to fix segfault in circo. Backported from upstream snapshot
release.  Thanks to Francis Russell for his work on this.
(Closes: #575255)

Show diffs side-by-side

added added

removed removed

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