Browse code

Second version bump after creating 2.14 release branch.

git-svn-id: https://hedgehog.fhcrc.org/bioconductor/trunk/madman/Rpacks/Rgraphviz@88840 bc3139a8-67e5-0310-9ffc-ced21a209358

d.tenenbaum authored on 11/04/2014 21:21:21
Showing1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,487 @@
1
+/* $Id: output.c,v 1.76 2011/01/25 16:30:48 ellson Exp $ $Revision: 1.76 $ */
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 "render.h"
15
+#include "agxbuf.h"
16
+#include <stdarg.h>
17
+#include <string.h>
18
+
19
+#define YDIR(y) (Y_invert ? (Y_off - (y)) : (y))
20
+#define YFDIR(y) (Y_invert ? (YF_off - (y)) : (y))
21
+
22
+double Y_off;        /* ymin + ymax */
23
+double YF_off;       /* Y_off in inches */
24
+
25
+#ifdef WITH_CGRAPH
26
+static int (*putstr) (void *chan, const char *str);
27
+
28
+static void agputs (const char* s, FILE* fp)
29
+{
30
+    putstr ((void*)fp, s);
31
+}
32
+static void agputc (int c, FILE* fp)
33
+{
34
+    static char buf[2] = {'\0','\0'};
35
+    buf[0] = c;
36
+    putstr ((void*)fp, buf);
37
+}
38
+
39
+#endif
40
+
41
+static void printstring(FILE * f, char *prefix, char *s)
42
+{
43
+    if (prefix) agputs(prefix, f);
44
+    agputs(s, f);
45
+}
46
+
47
+static void printint(FILE * f, char *prefix, int i)
48
+{
49
+    char buf[BUFSIZ];
50
+    
51
+    if (prefix) agputs(prefix, f);
52
+    sprintf(buf, "%d", i);
53
+    agputs(buf, f);
54
+}
55
+
56
+static void printdouble(FILE * f, char *prefix, double v)
57
+{
58
+    char buf[BUFSIZ];
59
+    
60
+    if (prefix) agputs(prefix, f);
61
+    sprintf(buf, "%.5g", v);
62
+    agputs(buf, f);
63
+}
64
+
65
+static void printpoint(FILE * f, pointf p)
66
+{
67
+    printdouble(f, " ", PS2INCH(p.x));
68
+    printdouble(f, " ", PS2INCH(YDIR(p.y)));
69
+}
70
+
71
+/* setYInvert:
72
+ * Set parameters used to flip coordinate system (y=0 at top).
73
+ * Values do not need to be unset, since if Y_invert is set, it's
74
+ * set for * all graphs during current run, so each will 
75
+ * reinitialize the values for its bbox.
76
+ */
77
+static void setYInvert(graph_t * g)
78
+{
79
+    if (Y_invert) {
80
+	Y_off = GD_bb(g).UR.y + GD_bb(g).LL.y;
81
+	YF_off = PS2INCH(Y_off);
82
+    }
83
+}
84
+
85
+/* canon:
86
+ * Canonicalize a string which may not have been allocated using agstrdup.
87
+ */
88
+static char* canon (graph_t *g, char* s)
89
+{
90
+#ifndef WITH_CGRAPH
91
+    char* ns = agstrdup (s);
92
+    char* cs = agcanonStr (ns);
93
+    agstrfree (ns);
94
+#else
95
+    char* ns = agstrdup (g, s);
96
+    char* cs = agcanonStr (ns);
97
+    agstrfree (g, ns);
98
+#endif
99
+    return cs;
100
+}
101
+
102
+static void writenodeandport(FILE * f, node_t * node, char *port)
103
+{
104
+    char *name;
105
+    if (IS_CLUST_NODE(node))
106
+	name = canon (agraphof(node), strchr(agnameof(node), ':') + 1);
107
+    else
108
+	name = agcanonStr (agnameof(node));
109
+    printstring(f, " ", name); /* slimey i know */
110
+    if (port && *port)
111
+	printstring(f, ":", agcanonStr(port));
112
+}
113
+
114
+/* _write_plain:
115
+ */
116
+void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend)
117
+{
118
+    int i, j, splinePoints;
119
+    char *tport, *hport;
120
+    node_t *n;
121
+    edge_t *e;
122
+    bezier bz;
123
+    pointf pt;
124
+    char *lbl;
125
+    char* fillcolor;
126
+
127
+#ifdef WITH_CGRAPH
128
+    putstr = g->clos->disc.io->putstr;
129
+#endif
130
+//    setup_graph(job, g);
131
+    setYInvert(g);
132
+    pt = GD_bb(g).UR;
133
+    printdouble(f, "graph ", job->zoom);
134
+    printdouble(f, " ", PS2INCH(pt.x));
135
+    printdouble(f, " ", PS2INCH(pt.y));
136
+    agputc('\n', f);
137
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
138
+	if (IS_CLUST_NODE(n))
139
+	    continue;
140
+	printstring(f, "node ", agcanonStr(agnameof(n)));
141
+	printpoint(f, ND_coord(n));
142
+	if (ND_label(n)->html)   /* if html, get original text */
143
+#ifndef WITH_CGRAPH
144
+	    lbl = agcanonStr (agxget(n, N_label->index));
145
+#else
146
+	    lbl = agcanonStr (agxget(n, N_label));
147
+#endif
148
+	else
149
+	    lbl = canon(agraphof(n),ND_label(n)->text);
150
+        printdouble(f, " ", ND_width(n));
151
+        printdouble(f, " ", ND_height(n));
152
+        printstring(f, " ", lbl);
153
+	printstring(f, " ", late_nnstring(n, N_style, "solid"));
154
+	printstring(f, " ", ND_shape(n)->name);
155
+	printstring(f, " ", late_nnstring(n, N_color, DEFAULT_COLOR));
156
+	fillcolor = late_nnstring(n, N_fillcolor, "");
157
+        if (fillcolor[0] == '\0')
158
+	    fillcolor = late_nnstring(n, N_color, DEFAULT_FILL);
159
+	printstring(f, " ", fillcolor);
160
+	agputc('\n', f);
161
+    }
162
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
163
+	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
164
+
165
+#ifndef WITH_CGRAPH
166
+/* FIXME - there must be a proper way to get port info - these are 
167
+ * supposed to be private to libgraph - from libgraph.h */
168
+#define TAILX 1
169
+#define HEADX 2
170
+
171
+	    if (extend && e->attr) {
172
+		tport = e->attr[TAILX];
173
+		hport = e->attr[HEADX];
174
+	    }
175
+#else /* WITH_CGRAPH */
176
+	    if (extend) {		//assuming these two attrs have already been created by cgraph
177
+		if (!(tport = agget(e,"tailport")))
178
+		    tport = "";
179
+		if (!(hport = agget(e,"headport")))
180
+		    hport = "";
181
+	    }
182
+#endif /* WITH_CGRAPH */
183
+	    else
184
+		tport = hport = "";
185
+	    if (ED_spl(e)) {
186
+		splinePoints = 0;
187
+		for (i = 0; i < ED_spl(e)->size; i++) {
188
+		    bz = ED_spl(e)->list[i];
189
+		    splinePoints += bz.size;
190
+		}
191
+		printstring(f, NULL, "edge");
192
+		writenodeandport(f, agtail(e), tport);
193
+		writenodeandport(f, aghead(e), hport);
194
+		printint(f, " ", splinePoints);
195
+		for (i = 0; i < ED_spl(e)->size; i++) {
196
+		    bz = ED_spl(e)->list[i];
197
+		    for (j = 0; j < bz.size; j++)
198
+			printpoint(f, bz.list[j]);
199
+		}
200
+	    }
201
+	    if (ED_label(e)) {
202
+		printstring(f, " ", canon(agraphof(agtail(e)),ED_label(e)->text));
203
+		printpoint(f, ED_label(e)->pos);
204
+	    }
205
+	    printstring(f, " ", late_nnstring(e, E_style, "solid"));
206
+	    printstring(f, " ", late_nnstring(e, E_color, DEFAULT_COLOR));
207
+	    agputc('\n', f);
208
+	}
209
+    }
210
+    agputs("stop\n", f);
211
+}
212
+
213
+static void set_record_rects(node_t * n, field_t * f, agxbuf * xb)
214
+{
215
+    int i;
216
+    char buf[BUFSIZ];
217
+
218
+    if (f->n_flds == 0) {
219
+	sprintf(buf, "%.5g,%.5g,%.5g,%.5g ",
220
+		f->b.LL.x + ND_coord(n).x,
221
+		YDIR(f->b.LL.y + ND_coord(n).y),
222
+		f->b.UR.x + ND_coord(n).x,
223
+		YDIR(f->b.UR.y + ND_coord(n).y));
224
+	agxbput(xb, buf);
225
+    }
226
+    for (i = 0; i < f->n_flds; i++)
227
+	set_record_rects(n, f->fld[i], xb);
228
+}
229
+
230
+static void rec_attach_bb(graph_t * g, Agsym_t* bbsym)
231
+{
232
+    int c;
233
+    char buf[BUFSIZ];
234
+    pointf pt;
235
+
236
+    sprintf(buf, "%.5g,%.5g,%.5g,%.5g", GD_bb(g).LL.x, YDIR(GD_bb(g).LL.y),
237
+	    GD_bb(g).UR.x, YDIR(GD_bb(g).UR.y));
238
+#ifndef WITH_CGRAPH
239
+    agxset(g, bbsym->index, buf);
240
+#else
241
+    agxset(g, bbsym, buf);
242
+#endif
243
+    if (GD_label(g) && GD_label(g)->text[0]) {
244
+	pt = GD_label(g)->pos;
245
+	sprintf(buf, "%.5g,%.5g", pt.x, YDIR(pt.y));
246
+	agset(g, "lp", buf);
247
+	pt = GD_label(g)->dimen;
248
+	sprintf(buf, "%.2f", PS2INCH(pt.x));
249
+	agset (g, "lwidth", buf);
250
+	sprintf(buf, "%.2f", PS2INCH(pt.y));
251
+	agset (g, "lheight", buf);
252
+    }
253
+    for (c = 1; c <= GD_n_cluster(g); c++)
254
+	rec_attach_bb(GD_clust(g)[c], bbsym);
255
+}
256
+
257
+void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep)
258
+{
259
+    int e_arrows;		/* graph has edges with end arrows */
260
+    int s_arrows;		/* graph has edges with start arrows */
261
+    int i, j, sides;
262
+    char buf[BUFSIZ];		/* Used only for small strings */
263
+    unsigned char xbuffer[BUFSIZ];	/* Initial buffer for xb */
264
+    agxbuf xb;
265
+    node_t *n;
266
+    edge_t *e;
267
+    pointf ptf;
268
+    int dim3 = (GD_odim(g) >= 3);
269
+    Agsym_t* bbsym;
270
+
271
+    gv_fixLocale (1);
272
+    e_arrows = s_arrows = 0;
273
+    setYInvert(g);
274
+    agxbinit(&xb, BUFSIZ, xbuffer);
275
+#ifndef WITH_CGRAPH
276
+    safe_dcl(g, g->proto->n, "pos", "", agnodeattr);
277
+    safe_dcl(g, g->proto->n, "rects", "", agnodeattr);
278
+    N_width = safe_dcl(g, g->proto->n, "width", "", agnodeattr);
279
+    N_height = safe_dcl(g, g->proto->n, "height", "", agnodeattr);
280
+    safe_dcl(g, g->proto->e, "pos", "", agedgeattr);
281
+    if (GD_has_labels(g) & NODE_XLABEL)
282
+	safe_dcl(g, g->proto->n, "xlp", "", agnodeattr);
283
+    if (GD_has_labels(g) & EDGE_LABEL)
284
+	safe_dcl(g, g->proto->e, "lp", "", agedgeattr);
285
+    if (GD_has_labels(g) & EDGE_XLABEL)
286
+	safe_dcl(g, g->proto->e, "xlp", "", agedgeattr);
287
+    if (GD_has_labels(g) & HEAD_LABEL)
288
+	safe_dcl(g, g->proto->e, "head_lp", "", agedgeattr);
289
+    if (GD_has_labels(g) & TAIL_LABEL)
290
+	safe_dcl(g, g->proto->e, "tail_lp", "", agedgeattr);
291
+    if (GD_label(g)) {
292
+	safe_dcl(g, g, "lp", "", agraphattr);
293
+	safe_dcl(g, g, "lwidth", "", agraphattr);
294
+	safe_dcl(g, g, "lheight", "", agraphattr);
295
+	if (GD_label(g)->text[0]) {
296
+	    ptf = GD_label(g)->pos;
297
+	    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
298
+	    agset(g, "lp", buf);
299
+	    ptf = GD_label(g)->dimen;
300
+	    sprintf(buf, "%.2f", PS2INCH(ptf.x));
301
+	    agset(g, "lwidth", buf);
302
+	    sprintf(buf, "%.2f", PS2INCH(ptf.y));
303
+	    agset(g, "lheight", buf);
304
+	}
305
+    }
306
+    bbsym = safe_dcl(g, g, "bb", "", agraphattr);
307
+#else
308
+    safe_dcl(g, AGNODE, "pos", "");
309
+    safe_dcl(g, AGNODE, "rects", "");
310
+    N_width = safe_dcl(g, AGNODE, "width", "");
311
+    N_height = safe_dcl(g, AGNODE, "height", "");
312
+    safe_dcl(g, AGEDGE, "pos", "");
313
+    if (GD_has_labels(g) & NODE_XLABEL)
314
+	safe_dcl(g, AGNODE, "xlp", "");
315
+    if (GD_has_labels(g) & EDGE_LABEL)
316
+	safe_dcl(g, AGEDGE, "lp", "");
317
+    if (GD_has_labels(g) & EDGE_XLABEL)
318
+	safe_dcl(g, AGEDGE, "xlp", "");
319
+    if (GD_has_labels(g) & HEAD_LABEL)
320
+	safe_dcl(g, AGEDGE, "head_lp", "");
321
+    if (GD_has_labels(g) & TAIL_LABEL)
322
+	safe_dcl(g, AGEDGE, "tail_lp", "");
323
+    if (GD_label(g)) {
324
+	safe_dcl(g, AGRAPH, "lp", "");
325
+	safe_dcl(g, AGRAPH, "lwidth", "");
326
+	safe_dcl(g, AGRAPH, "lheight", "");
327
+	if (GD_label(g)->text[0]) {
328
+	    ptf = GD_label(g)->pos;
329
+	    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
330
+	    agset(g, "lp", buf);
331
+	    ptf = GD_label(g)->dimen;
332
+	    sprintf(buf, "%.2f", PS2INCH(ptf.x));
333
+	    agset(g, "lwidth", buf);
334
+	    sprintf(buf, "%.2f", PS2INCH(ptf.y));
335
+	    agset(g, "lheight", buf);
336
+	}
337
+    }
338
+    bbsym = safe_dcl(g, AGRAPH, "bb", "");
339
+#endif
340
+    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
341
+	if (dim3) {
342
+	    int k;
343
+
344
+	    sprintf(buf, "%.5g,%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y), POINTS_PER_INCH*(ND_pos(n)[2]));
345
+	    agxbput (&xb, buf);
346
+	    for (k = 3; k < GD_odim(g); k++) {
347
+		sprintf(buf, ",%.5g", POINTS_PER_INCH*(ND_pos(n)[k]));
348
+		agxbput (&xb, buf);
349
+	    }
350
+	    agset(n, "pos", agxbuse(&xb));
351
+	} else {
352
+	    sprintf(buf, "%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y));
353
+	    agset(n, "pos", buf);
354
+	}
355
+	sprintf(buf, "%.5g", PS2INCH(ND_ht(n)));
356
+#ifndef WITH_CGRAPH
357
+	agxset(n, N_height->index, buf);
358
+	sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n)));
359
+	agxset(n, N_width->index, buf);
360
+#else
361
+	agxset(n, N_height, buf);
362
+	sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n)));
363
+	agxset(n, N_width, buf);
364
+#endif
365
+	if (ND_xlabel(n)) {
366
+	    ptf = ND_xlabel(n)->pos;
367
+	    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
368
+	    agset(n, "xlp", buf);
369
+	}
370
+	if (strcmp(ND_shape(n)->name, "record") == 0) {
371
+	    set_record_rects(n, ND_shape_info(n), &xb);
372
+	    agxbpop(&xb);	/* get rid of last space */
373
+	    agset(n, "rects", agxbuse(&xb));
374
+	} else {
375
+	    polygon_t *poly;
376
+	    int i;
377
+	    if (N_vertices && isPolygon(n)) {
378
+		poly = (polygon_t *) ND_shape_info(n);
379
+		sides = poly->sides;
380
+		if (sides < 3) {
381
+		    char *p = agget(n, "samplepoints");
382
+		    if (p)
383
+			sides = atoi(p);
384
+		    else
385
+			sides = 8;
386
+		    if (sides < 3)
387
+			sides = 8;
388
+		}
389
+		for (i = 0; i < sides; i++) {
390
+		    if (i > 0)
391
+			agxbputc(&xb, ' ');
392
+		    if (poly->sides >= 3)
393
+			sprintf(buf, "%.5g %.5g",
394
+				PS2INCH(poly->vertices[i].x),
395
+				YFDIR(PS2INCH(poly->vertices[i].y)));
396
+		    else
397
+			sprintf(buf, "%.5g %.5g",
398
+				ND_width(n) / 2.0 * cos(i / (double) sides * M_PI * 2.0),
399
+				YFDIR(ND_height(n) / 2.0 * sin(i / (double) sides * M_PI * 2.0)));
400
+		    agxbput(&xb, buf);
401
+		}
402
+#ifndef WITH_CGRAPH
403
+		agxset(n, N_vertices->index, agxbuse(&xb));
404
+#else /* WITH_CGRAPH */
405
+		agxset(n, N_vertices, agxbuse(&xb));
406
+#endif /* WITH_CGRAPH */
407
+	    }
408
+	}
409
+	if (State >= GVSPLINES) {
410
+	    for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
411
+		if (ED_edge_type(e) == IGNORED)
412
+		    continue;
413
+		if (ED_spl(e) == NULL)
414
+		    continue;	/* reported in postproc */
415
+		for (i = 0; i < ED_spl(e)->size; i++) {
416
+		    if (i > 0)
417
+			agxbputc(&xb, ';');
418
+		    if (ED_spl(e)->list[i].sflag) {
419
+			s_arrows = 1;
420
+			sprintf(buf, "s,%.5g,%.5g ",
421
+				ED_spl(e)->list[i].sp.x,
422
+				YDIR(ED_spl(e)->list[i].sp.y));
423
+			agxbput(&xb, buf);
424
+		    }
425
+		    if (ED_spl(e)->list[i].eflag) {
426
+			e_arrows = 1;
427
+			sprintf(buf, "e,%.5g,%.5g ",
428
+				ED_spl(e)->list[i].ep.x,
429
+				YDIR(ED_spl(e)->list[i].ep.y));
430
+			agxbput(&xb, buf);
431
+		    }
432
+		    for (j = 0; j < ED_spl(e)->list[i].size; j++) {
433
+			if (j > 0)
434
+			    agxbputc(&xb, ' ');
435
+			ptf = ED_spl(e)->list[i].list[j];
436
+			sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
437
+			agxbput(&xb, buf);
438
+		    }
439
+		}
440
+		agset(e, "pos", agxbuse(&xb));
441
+		if (ED_label(e)) {
442
+		    ptf = ED_label(e)->pos;
443
+		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
444
+		    agset(e, "lp", buf);
445
+		}
446
+		if (ED_xlabel(e)) {
447
+		    ptf = ED_xlabel(e)->pos;
448
+		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
449
+		    agset(e, "xlp", buf);
450
+		}
451
+		if (ED_head_label(e)) {
452
+		    ptf = ED_head_label(e)->pos;
453
+		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
454
+		    agset(e, "head_lp", buf);
455
+		}
456
+		if (ED_tail_label(e)) {
457
+		    ptf = ED_tail_label(e)->pos;
458
+		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
459
+		    agset(e, "tail_lp", buf);
460
+		}
461
+	    }
462
+	}
463
+    }
464
+    rec_attach_bb(g, bbsym);
465
+    agxbfree(&xb);
466
+
467
+    if (HAS_CLUST_EDGE(g))
468
+	undoClusterEdges(g);
469
+    
470
+    *sp = s_arrows;
471
+    *ep = e_arrows;
472
+    gv_fixLocale (0);
473
+}
474
+
475
+void attach_attrs(graph_t * g)
476
+{
477
+    int e, s;
478
+    attach_attrs_and_arrows (g, &s, &e);
479
+}
480
+
481
+void output_point(agxbuf *xbuf, pointf p)
482
+{
483
+    char buf[BUFSIZ];
484
+    sprintf(buf, "%d %d ", ROUND(p.x), ROUND(YDIR(p.y)));
485
+    agxbput(xbuf, buf);
486
+}
487
+