Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
gvrender_core_dot.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <stdarg.h>
14#include <stdbool.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include <common/macros.h>
19#include <common/const.h>
20
21#include <gvc/gvplugin_render.h>
22#include <gvc/gvplugin_device.h>
23#include <cgraph/alloc.h>
24#include <cgraph/agxbuf.h>
25#include <cgraph/gv_ctype.h>
26#include <cgraph/prisize_t.h>
27#include <cgraph/streq.h>
28#include <cgraph/unreachable.h>
29#include <common/utils.h>
30#include <gvc/gvc.h>
31#include <gvc/gvio.h>
32#include "core_loadimage_xdot.h"
33
43
44#define XDOTVERSION "1.7"
45
46#define NUMXBUFS (EMIT_HLABEL+1)
47/* There are as many xbufs as there are values of emit_state_t.
48 * However, only the first NUMXBUFS are distinct. Nodes, clusters, and
49 * edges are drawn atomically, so they share the DRAW and LABEL buffers
50 */
57static double penwidth [] = {
58 1, 1, 1, 1,
59 1, 1, 1, 1,
60 1, 1, 1, 1,
61};
62static unsigned int textflags[EMIT_ELABEL+1];
63
79
80static void xdot_str_xbuf (agxbuf* xb, char* pfx, const char* s)
81{
82 agxbprint (xb, "%s%" PRISIZE_T " -%s ", pfx, strlen(s), s);
83}
84
85static void xdot_str (GVJ_t *job, char* pfx, const char* s)
86{
87 emit_state_t emit_state = job->obj->emit_state;
88 xdot_str_xbuf (xbufs[emit_state], pfx, s);
89}
90
91/* xdot_fmt_num:
92 * Convert double to string with space at end.
93 * Trailing zeros are removed and decimal point, if possible.
94 */
95static void xdot_fmt_num(agxbuf *buf, double v) {
96 agxbprint(buf, "%.02f", v);
98 agxbputc(buf, ' ');
99}
100
101static void xdot_point(agxbuf *xb, pointf p)
102{
103 xdot_fmt_num(xb, p.x);
104 xdot_fmt_num(xb, yDir(p.y));
105}
106
107static void xdot_num(agxbuf *xb, double v)
108{
109 xdot_fmt_num(xb, v);
110}
111
112static void xdot_points(GVJ_t *job, char c, pointf *A, size_t n) {
113 emit_state_t emit_state = job->obj->emit_state;
114 agxbprint(xbufs[emit_state], "%c %" PRISIZE_T " ", c, n);
115 for (size_t i = 0; i < n; i++)
116 xdot_point(xbufs[emit_state], A[i]);
117}
118
119static char*
120color2str (unsigned char rgba[4])
121{
122 static char buf [10];
123
124 if (rgba[3] == 0xFF)
125 snprintf(buf, sizeof(buf), "#%02x%02x%02x", rgba[0], rgba[1], rgba[2]);
126 else
127 snprintf(buf, sizeof(buf), "#%02x%02x%02x%02x", rgba[0], rgba[1], rgba[2],
128 rgba[3]);
129 return buf;
130}
131
132static void xdot_pencolor (GVJ_t *job)
133{
134 xdot_str (job, "c ", color2str (job->obj->pencolor.u.rgba));
135}
136
137static void xdot_fillcolor (GVJ_t *job)
138{
139 xdot_str (job, "C ", color2str (job->obj->fillcolor.u.rgba));
140}
141
142static void xdot_style (GVJ_t *job)
143{
144 agxbuf xb = {0};
145 char* p, **s;
146
147 /* First, check if penwidth state is correct */
148 if (job->obj->penwidth != penwidth[job->obj->emit_state]) {
149 penwidth[job->obj->emit_state] = job->obj->penwidth;
150 agxbput (&xb, "setlinewidth(");
151 agxbprint(&xb, "%.3f", job->obj->penwidth);
153 agxbputc(&xb, ')');
154 xdot_str (job, "S ", agxbuse(&xb));
155 }
156
157 /* now process raw style, if any */
158 s = job->obj->rawstyle;
159 if (!s) {
160 agxbfree(&xb);
161 return;
162 }
163
164 while ((p = *s++)) {
165 if (streq(p, "filled") || streq(p, "bold") || streq(p, "setlinewidth")) continue;
166 agxbput(&xb, p);
167 while (*p)
168 p++;
169 p++;
170 if (*p) { /* arguments */
171 agxbputc(&xb, '(');
172 for (const char *separator = ""; *p; separator = ",") {
173 agxbprint(&xb, "%s%s", separator, p);
174 while (*p) p++;
175 p++;
176 }
177 agxbputc(&xb, ')');
178 }
179 xdot_str (job, "S ", agxbuse(&xb));
180 }
181
182 agxbfree(&xb);
183
184}
185
199static void put_escaping_backslashes(Agobj_t* n, Agsym_t *sym, const char *value)
200{
201 agxbuf buf = {0};
202
203 /* print the given string to the buffer, escaping as we go */
204 for (; *value != '\0'; ++value) {
205 if (*value == '\\') {
206 agxbputc(&buf, '\\');
207 }
208 agxbputc(&buf, *value);
209 }
210
211 /* update the node's symbol to the escaped text */
212 agxset(n, sym, agxbuse(&buf));
213
214 /* discard the buffer */
215 agxbfree(&buf);
216}
217
230
260
261static void xdot_end_cluster(GVJ_t * job)
262{
263 Agraph_t* cluster_g = job->obj->u.sg;
264
265 agxset(cluster_g, xd->g_draw, agxbuse(xbufs[EMIT_CDRAW]));
266 if (GD_label(cluster_g))
267 agxset(cluster_g, xd->g_l_draw, agxbuse(xbufs[EMIT_CLABEL]));
268 penwidth[EMIT_CDRAW] = 1;
272}
273
274static unsigned short versionStr2Version(const char *str) {
275 unsigned short us = 0;
276 for (size_t i = 0; str[i] != '\0'; ++i) {
277 if (!gv_isdigit(str[i])) {
278 continue;
279 }
280 unsigned short digit = (unsigned short)(str[i] - '0');
281 if (us > (USHRT_MAX - digit) / 10) {
282 agwarningf("xdot version \"%s\" too long", str);
283 break;
284 }
285 us = (unsigned short)(us * 10 + digit);
286 }
287 return us;
288}
289
290/*
291 * John M. suggests:
292 * You might want to add four more:
293 *
294 * _ohdraw_ (optional head-end arrow for edges)
295 * _ohldraw_ (optional head-end label for edges)
296 * _otdraw_ (optional tail-end arrow for edges)
297 * _otldraw_ (optional tail-end label for edges)
298 *
299 * that would be generated when an additional option is supplied to
300 * dot, etc. and
301 * these would be the arrow/label positions to use if a user want to flip the
302 * direction of an edge (as sometimes is there want).
303 *
304 * N.B. John M. asks:
305 * By the way, I don't know if you ever plan to add other letters for
306 * the xdot spec, but could you reserve "a" and also "A" (for attribute),
307 * "n" and also "N" (for numeric), "w" (for sWitch), "s" (for string)
308 * and "t" (for tooltip) and "x" (for position). We use those letters in
309 * our drawing spec (and also "<" and ">"), so if you start generating
310 * output with them, it could break what we have.
311 */
312static void xdot_begin_graph(graph_t *g, bool s_arrows, bool e_arrows,
313 format_type id) {
314 int i;
315 unsigned short us;
316 char* s;
317
318 xd = gv_alloc(sizeof(xdot_state_t));
319
320 if (id == FORMAT_XDOT14) {
321 xd->version = 14;
322 xd->version_s = "1.4";
323 }
324 else if (id == FORMAT_XDOT12) {
325 xd->version = 12;
326 xd->version_s = "1.2";
327 }
328 else if ((s = agget(g, "xdotversion")) && s[0] && ((us = versionStr2Version(s)) > 10)) {
329 xd->version = us;
330 xd->version_s = s;
331 }
332 else {
335 }
336
337 if (GD_n_cluster(g))
338 xd->g_draw = safe_dcl(g, AGRAPH, "_draw_", "");
339 else
340 xd->g_draw = NULL;
341 if (GD_has_labels(g) & GRAPH_LABEL)
342 xd->g_l_draw = safe_dcl(g, AGRAPH, "_ldraw_", "");
343 else
344 xd->g_l_draw = NULL;
345
346 xd->n_draw = safe_dcl(g, AGNODE, "_draw_", "");
347 xd->n_l_draw = safe_dcl(g, AGNODE, "_ldraw_", "");
348
349 xd->e_draw = safe_dcl(g, AGEDGE, "_draw_", "");
350 if (e_arrows)
351 xd->h_draw = safe_dcl(g, AGEDGE, "_hdraw_", "");
352 else
353 xd->h_draw = NULL;
354 if (s_arrows)
355 xd->t_draw = safe_dcl(g, AGEDGE, "_tdraw_", "");
356 else
357 xd->t_draw = NULL;
359 xd->e_l_draw = safe_dcl(g, AGEDGE, "_ldraw_", "");
360 else
361 xd->e_l_draw = NULL;
362 if (GD_has_labels(g) & HEAD_LABEL)
363 xd->hl_draw = safe_dcl(g, AGEDGE, "_hldraw_", "");
364 else
365 xd->hl_draw = NULL;
366 if (GD_has_labels(g) & TAIL_LABEL)
367 xd->tl_draw = safe_dcl(g, AGEDGE, "_tldraw_", "");
368 else
369 xd->tl_draw = NULL;
370
371 for (i = 0; i < NUMXBUFS; i++)
372 xbuf[i] = (agxbuf){0};
373}
374
375static void dot_begin_graph(GVJ_t *job)
376{
377 graph_t *g = job->obj->u.g;
378
379 switch (job->render.id) {
380 case FORMAT_DOT:
381 attach_attrs(g);
382 break;
383 case FORMAT_CANON:
384 if (HAS_CLUST_EDGE(g))
386 break;
387 case FORMAT_PLAIN:
388 case FORMAT_PLAIN_EXT:
389 break;
390 case FORMAT_XDOT:
391 case FORMAT_XDOT12:
392 case FORMAT_XDOT14: {
393 bool e_arrows; // graph has edges with end arrows
394 bool s_arrows; // graph has edges with start arrows
395 attach_attrs_and_arrows(g, &s_arrows, &e_arrows);
396 xdot_begin_graph(g, s_arrows, e_arrows, job->render.id);
397 break;
398 }
399 default:
400 UNREACHABLE();
401 }
402}
403
404static void xdot_end_graph(graph_t* g)
405{
406 int i;
407
408 if (agxblen(xbufs[EMIT_GDRAW])) {
409 if (!xd->g_draw)
410 xd->g_draw = safe_dcl(g, AGRAPH, "_draw_", "");
412 }
413 if (GD_label(g))
415 agsafeset (g, "xdotversion", xd->version_s, "");
416
417 for (i = 0; i < NUMXBUFS; i++)
418 agxbfree(xbuf+i);
419 free (xd);
420 penwidth[EMIT_GDRAW] = 1;
424}
425
426typedef int (*putstrfn) (void *chan, const char *str);
427typedef int (*flushfn) (void *chan);
428static void dot_end_graph(GVJ_t *job)
429{
430 graph_t *g = job->obj->u.g;
431 Agiodisc_t* io_save;
432 static Agiodisc_t io;
433
434 if (io.afread == NULL) {
436 io.putstr = (putstrfn)gvputs;
437 io.flush = (flushfn)gvflush;
438 }
439
440 io_save = g->clos->disc.io;
441 g->clos->disc.io = &io;
442 switch (job->render.id) {
443 case FORMAT_PLAIN:
444 write_plain(job, g, (FILE*)job, false);
445 break;
446 case FORMAT_PLAIN_EXT:
447 write_plain(job, g, (FILE*)job, true);
448 break;
449 case FORMAT_DOT:
450 case FORMAT_CANON:
451 if (!(job->flags & OUTPUT_NOT_REQUIRED))
452 agwrite(g, job);
453 break;
454 case FORMAT_XDOT:
455 case FORMAT_XDOT12:
456 case FORMAT_XDOT14:
458 if (!(job->flags & OUTPUT_NOT_REQUIRED))
459 agwrite(g, job);
460 break;
461 default:
462 UNREACHABLE();
463 }
464 g->clos->disc.io = io_save;
465}
466
467static const unsigned int flag_masks[] = {0x1F, 0x3F, 0x7F};
468
469static void xdot_textspan(GVJ_t * job, pointf p, textspan_t * span)
470{
471 emit_state_t emit_state = job->obj->emit_state;
472 unsigned flags;
473 int j;
474
475 agxbput(xbufs[emit_state], "F ");
476 xdot_fmt_num(xbufs[emit_state], span->font->size);
477 xdot_str (job, "", span->font->name);
478 xdot_pencolor(job);
479
480 switch (span->just) {
481 case 'l':
482 j = -1;
483 break;
484 case 'r':
485 j = 1;
486 break;
487 default:
488 case 'n':
489 j = 0;
490 break;
491 }
492 if (span->font)
493 flags = span->font->flags;
494 else
495 flags = 0;
496 const size_t flag_masks_size = sizeof(flag_masks) / sizeof(flag_masks[0]);
497 if (xd->version >= 15 && (size_t)xd->version - 15 < flag_masks_size) {
498 unsigned int mask = flag_masks[xd->version-15];
499 unsigned int bits = flags & mask;
500 if (textflags[emit_state] != bits) {
501 agxbprint(xbufs[emit_state], "t %u ", bits);
502 textflags[emit_state] = bits;
503 }
504 }
505
506 p.y += span->yoffset_centerline;
507 agxbput(xbufs[emit_state], "T ");
508 xdot_point(xbufs[emit_state], p);
509 agxbprint(xbufs[emit_state], "%d ", j);
510 xdot_fmt_num(xbufs[emit_state], span->size.x);
511 xdot_str (job, "", span->str);
512}
513
514static void xdot_color_stop(agxbuf *xb, double v, gvcolor_t *clr) {
515 agxbprint(xb, "%.03f", v);
517 agxbputc(xb, ' ');
518 xdot_str_xbuf(xb, "", color2str (clr->u.rgba));
519}
520
521static void xdot_gradient_fillcolor(GVJ_t *job, int filled, pointf *A, size_t n)
522{
523 obj_state_t* obj = job->obj;
524 double angle = obj->gradient_angle * M_PI / 180;
525 pointf G[2],c1,c2;
526
527 if (xd->version < 14) {
528 xdot_fillcolor (job);
529 return;
530 }
531
532 agxbuf xb = {0};
533 if (filled == GRADIENT) {
534 get_gradient_points(A, G, n, angle, 2);
535 agxbputc (&xb, '[');
536 xdot_point (&xb, G[0]);
537 xdot_point (&xb, G[1]);
538 }
539 else {
540 get_gradient_points(A, G, n, 0, 3);
541 // r2 is outer radius
542 double r2 = G[1].y;
543 if (obj->gradient_angle == 0) {
544 c1.x = G[0].x;
545 c1.y = G[0].y;
546 }
547 else {
548 c1.x = G[0].x + (r2/4) * cos(angle);
549 c1.y = G[0].y + (r2/4) * sin(angle);
550 }
551 c2.x = G[0].x;
552 c2.y = G[0].y;
553 double r1 = r2 / 4;
554 agxbputc(&xb, '(');
555 xdot_point (&xb, c1);
556 xdot_num (&xb, r1);
557 xdot_point (&xb, c2);
558 xdot_num (&xb, r2);
559 }
560
561 agxbput(&xb, "2 ");
562 if (obj->gradient_frac > 0) {
563 xdot_color_stop (&xb, obj->gradient_frac, &obj->fillcolor);
564 xdot_color_stop (&xb, obj->gradient_frac, &obj->stopcolor);
565 }
566 else {
567 xdot_color_stop (&xb, 0, &obj->fillcolor);
568 xdot_color_stop (&xb, 1, &obj->stopcolor);
569 }
570 agxbpop(&xb);
571 if (filled == GRADIENT)
572 agxbputc(&xb, ']');
573 else
574 agxbputc(&xb, ')');
575 xdot_str (job, "C ", agxbuse(&xb));
576 agxbfree(&xb);
577}
578
579static void xdot_ellipse(GVJ_t * job, pointf * A, int filled)
580{
581 emit_state_t emit_state = job->obj->emit_state;
582
583 xdot_style (job);
584 xdot_pencolor (job);
585 if (filled) {
586 if ((filled == GRADIENT) || (filled == RGRADIENT)) {
587 xdot_gradient_fillcolor (job, filled, A, 2);
588 }
589 else
590 xdot_fillcolor (job);
591 agxbput(xbufs[emit_state], "E ");
592 }
593 else
594 agxbput(xbufs[emit_state], "e ");
595 xdot_point(xbufs[emit_state], A[0]);
596 xdot_fmt_num(xbufs[emit_state], A[1].x - A[0].x);
597 xdot_fmt_num(xbufs[emit_state], A[1].y - A[0].y);
598}
599
600static void xdot_bezier(GVJ_t *job, pointf *A, size_t n, int filled) {
601 xdot_style (job);
602 xdot_pencolor (job);
603 if (filled) {
604 if ((filled == GRADIENT) || (filled == RGRADIENT)) {
605 xdot_gradient_fillcolor(job, filled, A, n);
606 }
607 else
608 xdot_fillcolor (job);
609 xdot_points(job, 'b', A, n); // NB - 'B' & 'b' are reversed in comparison to the other items
610 }
611 else
612 xdot_points(job, 'B', A, n);
613}
614
615static void xdot_polygon(GVJ_t *job, pointf *A, size_t n, int filled) {
616 xdot_style (job);
617 xdot_pencolor (job);
618 if (filled) {
619 if ((filled == GRADIENT) || (filled == RGRADIENT)) {
620 xdot_gradient_fillcolor(job, filled, A, n);
621 }
622 else
623 xdot_fillcolor (job);
624 xdot_points(job, 'P', A, n);
625 }
626 else
627 xdot_points(job, 'p', A, n);
628}
629
630static void xdot_polyline(GVJ_t *job, pointf *A, size_t n) {
631 xdot_style (job);
632 xdot_pencolor (job);
633 xdot_points(job, 'L', A, n);
634}
635
636void core_loadimage_xdot(GVJ_t * job, usershape_t *us, boxf b, bool filled)
637{
638 (void)filled;
639
640 emit_state_t emit_state = job->obj->emit_state;
641
642 agxbput(xbufs[emit_state], "I ");
643 xdot_point(xbufs[emit_state], b.LL);
644 xdot_fmt_num(xbufs[emit_state], b.UR.x - b.LL.x);
645 xdot_fmt_num(xbufs[emit_state], b.UR.y - b.LL.y);
646 xdot_str (job, "", us->name);
647}
648
650 0, /* dot_begin_job */
651 0, /* dot_end_job */
654 0, /* dot_begin_layer */
655 0, /* dot_end_layer */
656 0, /* dot_begin_page */
657 0, /* dot_end_page */
658 0, /* dot_begin_cluster */
659 0, /* dot_end_cluster */
660 0, /* dot_begin_nodes */
661 0, /* dot_end_nodes */
662 0, /* dot_begin_edges */
663 0, /* dot_end_edges */
664 0, /* dot_begin_node */
665 0, /* dot_end_node */
666 0, /* dot_begin_edge */
667 0, /* dot_end_edge */
668 0, /* dot_begin_anchor */
669 0, /* dot_end_anchor */
670 0, /* dot_begin_label */
671 0, /* dot_end_label */
672 0, /* dot_textspan */
673 0, /* dot_resolve_color */
674 0, /* dot_ellipse */
675 0, /* dot_polygon */
676 0, /* dot_bezier */
677 0, /* dot_polyline */
678 0, /* dot_comment */
679 0, /* dot_library_shape */
680};
681
683 0, /* xdot_begin_job */
684 0, /* xdot_end_job */
687 0, /* xdot_begin_layer */
688 0, /* xdot_end_layer */
689 0, /* xdot_begin_page */
690 0, /* xdot_end_page */
691 0, /* xdot_begin_cluster */
693 0, /* xdot_begin_nodes */
694 0, /* xdot_end_nodes */
695 0, /* xdot_begin_edges */
696 0, /* xdot_end_edges */
697 0, /* xdot_begin_node */
699 0, /* xdot_begin_edge */
701 0, /* xdot_begin_anchor */
702 0, /* xdot_end_anchor */
703 0, /* xdot_begin_label */
704 0, /* xdot_end_label */
706 0, /* xdot_resolve_color */
711 0, /* xdot_comment */
712 0, /* xdot_library_shape */
713};
714
716 GVRENDER_DOES_TRANSFORM, /* not really - uses raw graph coords */ /* flags */
717 0., /* default pad - graph units */
718 NULL, /* knowncolors */
719 0, /* sizeof knowncolors */
720 COLOR_STRING, /* color_type */
721};
722
724 GVRENDER_DOES_TRANSFORM /* not really - uses raw graph coords */
727 | GVRENDER_DOES_TOOLTIPS, /* flags */
728 0., /* default pad - graph units */
729 NULL, /* knowncolors */
730 0, /* sizeof knowncolors */
731 RGBA_BYTE, /* color_type */
732};
733
735 LAYOUT_NOT_REQUIRED, /* flags */
736 {0.,0.}, /* default margin - points */
737 {0.,0.}, /* default height, width - device units */
738 {72.,72.}, /* default dpi */
739};
740
742 0, /* flags */
743 {0.,0.}, /* default margin - points */
744 {0.,0.}, /* default page width, height - points */
745 {72.,72.}, /* default dpi */
746};
747
753
755 {FORMAT_DOT, "dot:dot", 1, NULL, &device_features_dot},
756 {FORMAT_DOT, "gv:dot", 1, NULL, &device_features_dot},
757 {FORMAT_CANON, "canon:dot", 1, NULL, &device_features_canon},
758 {FORMAT_PLAIN, "plain:dot", 1, NULL, &device_features_dot},
759 {FORMAT_PLAIN_EXT, "plain-ext:dot", 1, NULL, &device_features_dot},
760 {FORMAT_XDOT, "xdot:xdot", 1, NULL, &device_features_dot},
761 {FORMAT_XDOT12, "xdot1.2:xdot", 1, NULL, &device_features_dot},
762 {FORMAT_XDOT14, "xdot1.4:xdot", 1, NULL, &device_features_dot},
763 {0, NULL, 0, NULL, NULL}
764};
static int agxbpop(agxbuf *xb)
removes last character added, if any
Definition agxbuf.h:110
static void agxbuf_trim_zeros(agxbuf *xb)
Definition agxbuf.h:336
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:77
static size_t agxbput(agxbuf *xb, const char *s)
append string s into xb
Definition agxbuf.h:249
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:213
static size_t agxblen(const agxbuf *xb)
return number of characters currently stored
Definition agxbuf.h:88
static int agxbputc(agxbuf *xb, char c)
add character to buffer
Definition agxbuf.h:256
static char * agxbuse(agxbuf *xb)
Definition agxbuf.h:286
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
#define M_PI
Definition arith.h:41
@ RGBA_BYTE
Definition color.h:26
@ COLOR_STRING
Definition color.h:27
void undoClusterEdges(graph_t *g)
Definition utils.c:1035
attrsym_t * safe_dcl(graph_t *g, int obj_kind, char *name, char *defaultValue)
Definition utils.c:1070
void get_gradient_points(pointf *A, pointf *G, size_t n, double angle, int flags)
Definition utils.c:1466
#define HEAD_LABEL
Definition const.h:177
#define EDGE_XLABEL
Definition const.h:181
#define GRAPH_LABEL
Definition const.h:179
#define TAIL_LABEL
Definition const.h:178
#define EDGE_LABEL
Definition const.h:176
#define GRADIENT
Definition const.h:232
#define RGRADIENT
Definition const.h:233
#define A(n, t)
Definition expr.h:76
static int flags
Definition gc.c:61
#define G
Definition gdefs.h:7
void free(void *)
node NULL
Definition grammar.y:149
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:481
char * agget(void *obj, char *name)
Definition attr.c:442
int agsafeset(void *obj, char *name, const char *value, const char *def)
ensures the given attribute is declared before setting it locally on an object
Definition attr.c:510
Agiodisc_t AgIoDisc
Definition io.c:39
void agwarningf(const char *fmt,...)
Definition agerror.c:173
#define GD_has_labels(g)
Definition types.h:368
#define GD_n_cluster(g)
Definition types.h:389
int agwrite(Agraph_t *g, void *chan)
Return 0 on success, EOF on failure.
Definition write.c:708
#define GD_label(g)
Definition types.h:374
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
void attach_attrs(graph_t *g)
Definition output.c:383
replacements for ctype.h functions
static bool gv_isdigit(int c)
Definition gv_ctype.h:41
Graphviz context library.
#define GVRENDER_DOES_TOOLTIPS
Definition gvcjob.h:103
#define OUTPUT_NOT_REQUIRED
Definition gvcjob.h:108
#define LAYOUT_NOT_REQUIRED
Definition gvcjob.h:107
emit_state_t
Definition gvcjob.h:173
@ EMIT_CDRAW
Definition gvcjob.h:174
@ EMIT_NDRAW
Definition gvcjob.h:176
@ EMIT_TDRAW
Definition gvcjob.h:174
@ EMIT_HDRAW
Definition gvcjob.h:174
@ EMIT_HLABEL
Definition gvcjob.h:175
@ EMIT_GDRAW
Definition gvcjob.h:174
@ EMIT_NLABEL
Definition gvcjob.h:176
@ EMIT_GLABEL
Definition gvcjob.h:175
@ EMIT_ELABEL
Definition gvcjob.h:176
@ EMIT_EDRAW
Definition gvcjob.h:176
@ EMIT_CLABEL
Definition gvcjob.h:175
@ EMIT_TLABEL
Definition gvcjob.h:175
#define GVRENDER_DOES_MAPS
Definition gvcjob.h:97
#define GVRENDER_DOES_TARGETS
Definition gvcjob.h:104
#define GVRENDER_DOES_TRANSFORM
Definition gvcjob.h:95
int gvflush(GVJ_t *job)
Definition gvdevice.c:300
int gvputs(GVJ_t *job, const char *s)
Definition gvdevice.c:263
format_type
gvplugin_installed_t gvrender_dot_types[]
static void xdot_polygon(GVJ_t *job, pointf *A, size_t n, int filled)
int(* putstrfn)(void *chan, const char *str)
static void dot_end_graph(GVJ_t *job)
static void xdot_style(GVJ_t *job)
gvdevice_features_t device_features_canon
static void xdot_end_cluster(GVJ_t *job)
static void xdot_fmt_num(agxbuf *buf, double v)
static void xdot_end_edge(GVJ_t *job)
void core_loadimage_xdot(GVJ_t *job, usershape_t *us, boxf b, bool filled)
static void xdot_begin_graph(graph_t *g, bool s_arrows, bool e_arrows, format_type id)
static agxbuf * xbufs[]
static void xdot_pencolor(GVJ_t *job)
static void xdot_points(GVJ_t *job, char c, pointf *A, size_t n)
static void dot_begin_graph(GVJ_t *job)
static void xdot_fillcolor(GVJ_t *job)
gvrender_engine_t dot_engine
static void xdot_num(agxbuf *xb, double v)
gvrender_features_t render_features_dot
#define NUMXBUFS
static xdot_state_t * xd
static void xdot_str_xbuf(agxbuf *xb, char *pfx, const char *s)
static unsigned int textflags[EMIT_ELABEL+1]
gvplugin_installed_t gvdevice_dot_types[]
static double penwidth[]
static agxbuf xbuf[NUMXBUFS]
int(* flushfn)(void *chan)
static void xdot_textspan(GVJ_t *job, pointf p, textspan_t *span)
static unsigned short versionStr2Version(const char *str)
static char * color2str(unsigned char rgba[4])
gvdevice_features_t device_features_dot
format_type
@ FORMAT_PLAIN
@ FORMAT_XDOT12
@ FORMAT_DOT
@ FORMAT_XDOT
@ FORMAT_PLAIN_EXT
@ FORMAT_XDOT14
@ FORMAT_CANON
static void xdot_ellipse(GVJ_t *job, pointf *A, int filled)
static void xdot_end_node(GVJ_t *job)
#define XDOTVERSION
static void xdot_str(GVJ_t *job, char *pfx, const char *s)
static const unsigned int flag_masks[]
static void xdot_end_graph(graph_t *g)
static void xdot_bezier(GVJ_t *job, pointf *A, size_t n, int filled)
gvrender_features_t render_features_xdot
gvrender_engine_t xdot_engine
static void put_escaping_backslashes(Agobj_t *n, Agsym_t *sym, const char *value)
static void xdot_gradient_fillcolor(GVJ_t *job, int filled, pointf *A, size_t n)
agxbuf * str
Definition htmlparse.c:97
#define HAS_CLUST_EDGE(g)
Definition macros.h:24
void attach_attrs_and_arrows(graph_t *g, bool *sp, bool *ep)
Definition output.c:229
double yDir(double y)
Definition output.c:28
void write_plain(GVJ_t *job, graph_t *g, FILE *f, bool extend)
Definition output.c:114
#define PRISIZE_T
PRIu64 alike for printing size_t
Definition prisize_t.h:27
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11
Agdisc_t disc
Definition cgraph.h:412
Agiodisc_t * io
Definition cgraph.h:339
Agobj_t base
Definition cgraph.h:269
IO services.
Definition cgraph.h:327
int(* afread)(void *chan, char *buf, int bufsize)
Definition cgraph.h:328
int(* flush)(void *chan)
Definition cgraph.h:330
int(* putstr)(void *chan, const char *str)
Definition cgraph.h:329
Agobj_t base
Definition cgraph.h:260
a generic header of Agraph_s, Agnode_s and Agedge_s
Definition cgraph.h:210
graph or subgraph
Definition cgraph.h:425
Agobj_t base
Definition cgraph.h:426
Agclos_t * clos
shared resources
Definition cgraph.h:435
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:639
obj_state_t * obj
Definition gvcjob.h:269
gvplugin_active_render_t render
Definition gvcjob.h:285
Definition geom.h:41
pointf UR
Definition geom.h:41
pointf LL
Definition geom.h:41
union color_s::@72 u
unsigned char rgba[4]
Definition color.h:34
ingroup plugin_api
Definition gvplugin.h:35
union obj_state_s::@92 u
graph_t * g
Definition gvcjob.h:186
edge_t * e
Definition gvcjob.h:189
gvcolor_t fillcolor
Definition gvcjob.h:194
double gradient_frac
Definition gvcjob.h:196
gvcolor_t stopcolor
Definition gvcjob.h:194
node_t * n
Definition gvcjob.h:188
graph_t * sg
Definition gvcjob.h:187
gvcolor_t pencolor
Definition gvcjob.h:194
char ** rawstyle
Definition gvcjob.h:200
int gradient_angle
Definition gvcjob.h:195
emit_state_t emit_state
Definition gvcjob.h:192
double penwidth
Definition gvcjob.h:199
double x
Definition geom.h:29
double y
Definition geom.h:29
char * name
Definition textspan.h:54
unsigned int flags
Definition textspan.h:58
double size
Definition textspan.h:57
char * str
Definition textspan.h:65
char just
'l' 'n' 'r'
Definition textspan.h:71
pointf size
Definition textspan.h:70
textfont_t * font
Definition textspan.h:66
double yoffset_centerline
Definition textspan.h:69
const char * name
Definition usershape.h:54
attrsym_t * n_l_draw
attrsym_t * t_draw
attrsym_t * g_draw
attrsym_t * g_l_draw
attrsym_t * e_l_draw
attrsym_t * tl_draw
attrsym_t * n_draw
attrsym_t * h_draw
unsigned short version
attrsym_t * e_draw
attrsym_t * hl_draw
Definition grammar.c:93
#define UNREACHABLE()
Definition unreachable.h:30