~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to dotneato/common/output.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This software may only be used by you under license from AT&T Corp.
 
3
    ("AT&T").  A copy of AT&T's Source Code Agreement is available at
 
4
    AT&T's Internet website having the URL:
 
5
    <http://www.research.att.com/sw/tools/graphviz/license/source.html>
 
6
    If you received this software without first entering into a license
 
7
    with AT&T, you have an infringing copy of this software and cannot use
 
8
    it without violating AT&T's intellectual property rights.
 
9
*/
 
10
#pragma prototyped
 
11
 
 
12
#include        "render.h"
 
13
 
 
14
#ifdef DMALLOC
 
15
#include "dmalloc.h"
 
16
#endif
 
17
 
 
18
int        Output_lang;
 
19
codegen_t  *CodeGen;
 
20
FILE       *Output_file;
 
21
 
 
22
void dotneato_write(graph_t* g)
 
23
{
 
24
        double  xf, yf;
 
25
        char    *p;
 
26
        int     i;
 
27
 
 
28
        /* margins */
 
29
        if ((p = agget(g,"margin"))) {
 
30
                i = sscanf(p,"%lf,%lf",&xf,&yf);
 
31
                if (i > 0) g->u.drawing->margin.x = g->u.drawing->margin.y = POINTS(xf);
 
32
                if (i > 1) g->u.drawing->margin.y = POINTS(yf);
 
33
        }
 
34
        else {
 
35
                /* set default margins depending on format */
 
36
                switch (Output_lang) {
 
37
                        case GIF:
 
38
                        case PNG:
 
39
                        case JPEG:
 
40
                        case GD:
 
41
                        case GD2:
 
42
                        case ISMAP:
 
43
                        case IMAP:
 
44
                        case VRML:
 
45
                        case SVG:
 
46
                        case SVGZ:
 
47
                                g->u.drawing->margin.x = DEFAULT_EMBED_MARGIN_X;
 
48
                                g->u.drawing->margin.y = DEFAULT_EMBED_MARGIN_Y;
 
49
                                break;
 
50
                        case POSTSCRIPT:
 
51
                        case HPGL:
 
52
                        case PCL:
 
53
                        case MIF:
 
54
                        case METAPOST:
 
55
                        case FIG:
 
56
                        case VTX:
 
57
                        case ATTRIBUTED_DOT:
 
58
                        case PLAIN:             
 
59
                        case PLAIN_EXT:         
 
60
                                g->u.drawing->margin.x = g->u.drawing->margin.y = DEFAULT_MARGIN;
 
61
                                break;
 
62
                        case CANONICAL_DOT:
 
63
                                break;
 
64
                }
 
65
        }
 
66
 
 
67
        switch (Output_lang) {
 
68
                case POSTSCRIPT:
 
69
                case HPGL:
 
70
                case PCL:
 
71
                case MIF:
 
72
                case PIC_format:
 
73
                case GIF:
 
74
                case PNG:
 
75
                case JPEG:
 
76
                case GD:
 
77
                case GD2:
 
78
                case ISMAP:
 
79
                case IMAP:
 
80
                case VRML:
 
81
                case METAPOST:
 
82
                case SVG:
 
83
                case SVGZ:
 
84
                        /* output in breadth first graph walk order */
 
85
                        emit_graph(g,0); break;
 
86
                case FIG:
 
87
                        /* output color definition objects first */
 
88
                        emit_graph(g,EMIT_COLORS); break;
 
89
                case VTX:
 
90
                        /* output sorted, i.e. all nodes then all edges */
 
91
                        emit_graph(g,EMIT_SORTED); break;
 
92
                case ATTRIBUTED_DOT:
 
93
                        attach_attrs(g);
 
94
                        agwrite(g,Output_file); break;
 
95
                case CANONICAL_DOT:
 
96
                        agwrite(g,Output_file); break;
 
97
                case PLAIN:             
 
98
                        attach_attrs(g); write_plain(g,Output_file); break;
 
99
                case PLAIN_EXT:         
 
100
                        attach_attrs(g); write_plain_ext(g,Output_file); break;
 
101
        }
 
102
        fflush(Output_file);
 
103
}
 
104
 
 
105
/* Extensible buffer:
 
106
 *  Contents in buf; always null-terminated.
 
107
 */
 
108
typedef struct {
 
109
    char*  buf;   /* start of buffer */
 
110
    char*  ptr;   /* next place to write */
 
111
    char*  eptr;  /* end of buffer */
 
112
    int    dyna;  /* true if buffer is malloc'ed */
 
113
} xbuf;
 
114
 
 
115
/* initXBuf:
 
116
 * Assume if init is non-null, hint = sizeof(init[])
 
117
 */
 
118
static void
 
119
initXBuf (xbuf* xb, unsigned int hint, char* init)
 
120
{
 
121
  if (init) {
 
122
    xb->buf = init;
 
123
    xb->dyna = 0;
 
124
  }
 
125
  else {
 
126
    if (hint == 0) hint = BUFSIZ;
 
127
    xb->dyna = 1;
 
128
    xb->buf = (char*)malloc (hint);
 
129
  }
 
130
  xb->eptr = xb->buf + hint;
 
131
  xb->ptr = xb->buf;
 
132
  *xb->ptr = '\0';
 
133
}
 
134
 
 
135
static void
 
136
resetXBuf (xbuf* xb)
 
137
{
 
138
  xb->ptr = xb->buf;
 
139
  *xb->ptr = '\0';
 
140
}
 
141
 
 
142
/* putXBuf;
 
143
 * Append string s into xb
 
144
 */
 
145
static void
 
146
putXBuf (xbuf* xb, char* s)
 
147
{
 
148
  int    ssz = strlen (s);
 
149
  int    cnt;         /* current no. of characters in buffer */
 
150
  int    size;        /* current buffer size */
 
151
  int    nsize;       /* new buffer size */
 
152
  char*  nbuf;        /* new buffer */
 
153
 
 
154
  if (xb->ptr + ssz >= xb->eptr) {
 
155
    size = xb->eptr - xb->buf;
 
156
    nsize = 2*size;
 
157
    if (size+ssz > nsize) nsize = size+ssz;
 
158
    cnt = xb->ptr - xb->buf;
 
159
    if (xb->dyna) {
 
160
      nbuf = (char*)realloc(xb->buf,nsize);
 
161
      if (!nbuf) {fprintf(stderr,"out of memory\n"); abort();}
 
162
      free (xb->buf);
 
163
    }
 
164
    else {
 
165
      nbuf = (char*)malloc(nsize);
 
166
      if (!nbuf) {fprintf(stderr,"out of memory\n"); abort();}
 
167
      memcpy (nbuf, xb->buf, cnt);
 
168
      xb->dyna = 1;
 
169
    }
 
170
    xb->buf = nbuf;
 
171
    xb->ptr = xb->buf + cnt;
 
172
    xb->eptr = xb->buf + nsize;
 
173
  }
 
174
  memcpy (xb->ptr, s, ssz+1);
 
175
  xb->ptr += ssz;
 
176
}
 
177
 
 
178
static void
 
179
termXBuf (xbuf* xb)
 
180
{
 
181
  if (xb->dyna) free (xb->buf);
 
182
}
 
183
 
 
184
static void
 
185
popXBuf (xbuf* xb)
 
186
{
 
187
  if (xb->ptr > xb->buf) {
 
188
    xb->ptr--;
 
189
    *xb->ptr = '\0';
 
190
  }
 
191
 
 
192
}
 
193
 
 
194
static void 
 
195
set_record_rects (node_t* n, field_t* f, xbuf* xb)
 
196
{
 
197
        int             i;
 
198
    char            buf[BUFSIZ];
 
199
 
 
200
        if (f->n_flds == 0) {
 
201
                sprintf(buf, "%d,%d,%d,%d ",
 
202
                                f->b.LL.x + n->u.coord.x,
 
203
                                f->b.LL.y + n->u.coord.y,
 
204
                                f->b.UR.x + n->u.coord.x,
 
205
                                f->b.UR.y + n->u.coord.y);
 
206
        putXBuf (xb, buf);
 
207
        }
 
208
        for (i = 0; i < f->n_flds; i++)
 
209
                set_record_rects (n, f->fld[i], xb);
 
210
}
 
211
 
 
212
static attrsym_t *safe_dcl(graph_t *g, void *obj, char *name, char *def,
 
213
        attrsym_t*(*fun)(Agraph_t*, char*, char*))
 
214
{
 
215
        attrsym_t       *a = agfindattr(obj,name);
 
216
        if (a == NULL) a = fun(g,name,def);
 
217
        return a;
 
218
}
 
219
 
 
220
void attach_attrs(graph_t* g)
 
221
{
 
222
        int             i,j,sides;
 
223
        char    buf[BUFSIZ],*p;
 
224
        xbuf    xb;
 
225
        node_t  *n;
 
226
        edge_t  *e;
 
227
        point   pt;
 
228
 
 
229
    initXBuf (&xb, BUFSIZ, buf);
 
230
        safe_dcl(g,g->proto->n,"pos","",agnodeattr);
 
231
        safe_dcl(g,g->proto->n,"rects","",agnodeattr);
 
232
        N_width = safe_dcl(g,g->proto->n,"width","",agnodeattr);
 
233
        N_height = safe_dcl(g,g->proto->n,"height","",agnodeattr);
 
234
        safe_dcl(g,g->proto->e,"pos","",agedgeattr);
 
235
        if (g->u.has_edge_labels) safe_dcl(g,g->proto->e,"lp","",agedgeattr);
 
236
        if (g->u.label) {
 
237
                safe_dcl(g,g,"lp","",agraphattr);
 
238
                pt = g->u.label->p;
 
239
                sprintf(buf,"%d,%d",pt.x,pt.y);
 
240
                agset(g,"lp",buf);
 
241
        }
 
242
        safe_dcl(g,g,"bb","",agraphattr);
 
243
        for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
 
244
                sprintf(buf,"%d,%d",n->u.coord.x,n->u.coord.y);
 
245
                agset(n,"pos",buf);
 
246
                sprintf(buf,"%.2f",PS2INCH(n->u.ht));
 
247
                agxset(n,N_height->index,buf);
 
248
                sprintf(buf,"%.2f",PS2INCH(n->u.lw + n->u.rw));
 
249
                agxset(n,N_width->index,buf);
 
250
                if (strcmp (n->u.shape->name, "record") == 0) {
 
251
            resetXBuf (&xb);
 
252
                        set_record_rects (n, n->u.shape_info, &xb);
 
253
            popXBuf (&xb); /* get rid of last space */
 
254
                        agset(n,"rects",xb.buf);
 
255
                }
 
256
                else {
 
257
                        extern void     poly_init(node_t *);
 
258
                        polygon_t *poly;
 
259
                        int i;
 
260
                        if (N_vertices && (n->u.shape->initfn == poly_init)) {
 
261
                                poly = (polygon_t*) n->u.shape_info;
 
262
                                p = buf; 
 
263
                                sides = poly->sides;
 
264
                                if (sides < 3) {
 
265
                                        char *p = agget(n,"samplepoints");
 
266
                                        if (p) sides = atoi(p);
 
267
                                        else sides = 8;
 
268
                                        if (sides < 3) sides = 8;
 
269
                                }
 
270
                                for (i = 0; i < sides; i++) {
 
271
                                        if (i > 0) {*p++ = ' ';}
 
272
                                        if (poly->sides >= 3)
 
273
                                                sprintf(p,"%.3lf %.3lf",
 
274
                                                        poly->vertices[i].x,poly->vertices[i].y);
 
275
                                        else
 
276
                                                sprintf(p,"%.3lf %.3lf",
 
277
                                                        n->u.width/2.0 * cos(i/(double)sides * PI * 2.0),
 
278
                                                        n->u.height/2.0 * sin(i/(double)sides * PI * 2.0));
 
279
                                        while (*p) p++;
 
280
                                }
 
281
                                agxset(n,N_vertices->index,buf);
 
282
                        }
 
283
                }
 
284
                for (e = agfstout(g,n); e; e = agnxtout(g,e)) {
 
285
                        p = buf;
 
286
if (e->u.spl == NULL)
 
287
        {fprintf(stderr,"lost spline of %s %s\n",e->tail->name,e->head->name); continue;}
 
288
                        for (i = 0; i < e->u.spl->size; i++) {
 
289
                                if (i > 0) *p++ = ';';
 
290
                                if (e->u.spl->list[i].sflag) {
 
291
                                        sprintf (p, "s,%d,%d ",e->u.spl->list[i].sp.x,e->u.spl->list[i].sp.y);
 
292
                                        while (*p) p++;
 
293
                                }
 
294
                                if (e->u.spl->list[i].eflag) {
 
295
                                        sprintf (p, "e,%d,%d ",e->u.spl->list[i].ep.x,e->u.spl->list[i].ep.y);
 
296
                                        while (*p) p++;
 
297
                                }
 
298
                                for (j = 0; j < e->u.spl->list[i].size; j++) {
 
299
                                        if (j > 0) *p++ = ' ';
 
300
                                        pt = e->u.spl->list[i].list[j];
 
301
                                        sprintf(p,"%d,%d",pt.x,pt.y);
 
302
                                        while (*p) p++;
 
303
                                }
 
304
                                *p = '\0';
 
305
                        }
 
306
                        agset(e,"pos",buf);
 
307
                        if (e->u.label) {
 
308
                                pt = e->u.label->p;
 
309
                                sprintf(buf,"%d,%d",pt.x,pt.y);
 
310
                                agset(e,"lp",buf);
 
311
                        }
 
312
                }
 
313
        }
 
314
        rec_attach_bb(g);
 
315
    termXBuf (&xb);
 
316
}
 
317
 
 
318
void rec_attach_bb(graph_t* g)
 
319
{
 
320
        int             c;
 
321
        char    buf[32];
 
322
 
 
323
        sprintf(buf,"%d,%d,%d,%d", g->u.bb.LL.x, g->u.bb.LL.y,
 
324
                g->u.bb.UR.x, g->u.bb.UR.y);
 
325
        agset(g,"bb",buf);
 
326
        for (c = 1; c <= g->u.n_cluster; c++) rec_attach_bb(g->u.clust[c]);
 
327
}
 
328
 
 
329
static char *getoutputbuffer(char *str)
 
330
{
 
331
        static char             *rv;
 
332
        static int              len;
 
333
        int                     req;
 
334
 
 
335
        req = MAX(2 * strlen(str) + 2, BUFSIZ);
 
336
        if (req > len) {
 
337
                if (rv) rv = realloc(rv,req);
 
338
                else rv = malloc(req);
 
339
                len = req;
 
340
        }
 
341
        return rv;
 
342
}
 
343
 
 
344
 
 
345
static char *canonical(char *str)
 
346
{
 
347
        return agstrcanon(str,getoutputbuffer(str));
 
348
}
 
349
 
 
350
static void writenodeandport(FILE *fp, char *node, char *port)
 
351
{
 
352
        fprintf(fp,"%s",canonical(node));       /* slimey i know*/
 
353
        if (port && *port) fprintf(fp,"%c%s",port[0],canonical(port+1));
 
354
}
 
355
 
 
356
void write_plain(graph_t* g, FILE* f)
 
357
{
 
358
        int                     i;
 
359
        node_t          *n;
 
360
        edge_t          *e;
 
361
        bezier          bz;
 
362
 
 
363
        setup_graph(g);
 
364
        fprintf(f,"graph %.3f",g->u.drawing->scale); printptf(f,g->u.bb.UR); fprintf(f,"\n");
 
365
        for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
 
366
                fprintf(f,"node %s ",canonical(n->name)); printptf(f,n->u.coord);
 
367
                fprintf(f," %.3f %.3f %s %s %s %s %s\n",
 
368
                        n->u.width,n->u.height,canonical(n->u.label->text),
 
369
                        late_nnstring(n,N_style,"solid"),
 
370
                        n->u.shape->name,
 
371
                        late_nnstring(n,N_color,DEFAULT_COLOR),
 
372
                        late_nnstring(n,N_fillcolor,DEFAULT_FILL));
 
373
        }
 
374
        for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
 
375
                for (e = agfstout(g,n); e; e = agnxtout(g,e)) {
 
376
                        bz = e->u.spl->list[0];
 
377
                        fprintf(f,"edge ");
 
378
                        writenodeandport(f,e->tail->name,"");
 
379
                        fprintf(f," ");
 
380
                        writenodeandport(f,e->head->name,"");
 
381
                        fprintf(f," %d",bz.size);
 
382
                        for (i = 0; i < bz.size; i++) printptf(f,bz.list[i]);
 
383
                        if (e->u.label) {
 
384
                                fprintf(f," %s",canonical(e->u.label->text));
 
385
                                printptf(f,e->u.label->p);
 
386
                        }
 
387
                        fprintf(f," %s %s\n",late_nnstring(e,E_style,"solid"),
 
388
                                late_nnstring(e,E_color,DEFAULT_COLOR));
 
389
                }
 
390
        }
 
391
        fprintf(f,"stop\n");
 
392
}
 
393
 
 
394
/* FIXME - there must be a proper way to get port info - these are 
 
395
 * supposed to be private to libgraph - from libgraph.h */
 
396
#define TAILX 1
 
397
#define HEADX 1
 
398
 
 
399
void write_plain_ext(graph_t* g, FILE* f)
 
400
{
 
401
        int                     i;
 
402
        node_t          *n;
 
403
        edge_t          *e;
 
404
        bezier          bz;
 
405
        char            *tport, *hport;
 
406
 
 
407
        setup_graph(g);
 
408
        fprintf(f,"graph %.3f",g->u.drawing->scale); printptf(f,g->u.bb.UR); fprintf(f,"\n");
 
409
        for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
 
410
                fprintf(f,"node %s ",canonical(n->name)); printptf(f,n->u.coord);
 
411
                fprintf(f," %.3f %.3f %s %s %s %s %s\n",
 
412
                        n->u.width,n->u.height,canonical(n->u.label->text),
 
413
                        late_nnstring(n,N_style,"solid"),
 
414
                        n->u.shape->name,
 
415
                        late_nnstring(n,N_color,DEFAULT_COLOR),
 
416
                        late_nnstring(n,N_fillcolor,DEFAULT_FILL));
 
417
        }
 
418
        for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
 
419
                for (e = agfstout(g,n); e; e = agnxtout(g,e)) {
 
420
                        bz = e->u.spl->list[0];
 
421
                        if (e->attr) {tport = e->attr[TAILX]; hport = e->attr[HEADX];}
 
422
                        else tport = hport = "";
 
423
                        fprintf(f,"edge ");
 
424
                        writenodeandport(f,e->tail->name,tport);
 
425
                        fprintf(f," ");
 
426
                        writenodeandport(f,e->head->name,hport);
 
427
                        fprintf(f," %d",bz.size);
 
428
                        for (i = 0; i < bz.size; i++) printptf(f,bz.list[i]);
 
429
                        if (e->u.label) {
 
430
                                fprintf(f," %s",canonical(e->u.label->text));
 
431
                                printptf(f,e->u.label->p);
 
432
                        }
 
433
                        fprintf(f," %s %s\n",late_nnstring(e,E_style,"solid"),
 
434
                                late_nnstring(e,E_color,DEFAULT_COLOR));
 
435
                }
 
436
        }
 
437
        fprintf(f,"stop\n");
 
438
}
 
439
 
 
440
void printptf(FILE* f, point pt)
 
441
{
 
442
        fprintf(f," %.3f %.3f",PS2INCH(pt.x),PS2INCH(pt.y));
 
443
}
 
444
 
 
445
int codegen_bezier_has_arrows(void)
 
446
{
 
447
        return CodeGen && 
 
448
      CodeGen->bezier_has_arrows
 
449
      /* (CodeGen->arrowhead == 0)) */;
 
450
}