42#define strtok_r strtok_s
45#define P2RECT(p, pr, sx, sy) (pr[0].x = p.x - sx, pr[0].y = p.y - sy, pr[1].x = p.x + sx, pr[1].y = p.y + sy)
60 if (!((p =
agget(g,
"_background")) && p[0])) {
61 if (!((p =
agget(g,
"_draw_")) && p[0])) {
81 fprintf (stderr,
"%d ops %.2f sec\n", stats.
cnt, et);
85 fprintf (stderr,
"%d ellipses\n", stats.
n_ellipse);
86 fprintf (stderr,
"%d texts\n", stats.
n_text);
168 if (tooltip && tooltip[0]) {
173 else if (obj->
label) {
208 id =
agget(obj,
"id");
209 if (
id && *
id !=
'\0') {
214 if (obj != root && gid) {
253 bool backslash_seen =
false;
255 while ((c = *
ins++)) {
256 if (backslash_seen) {
269 backslash_seen =
false;
273 backslash_seen =
true;
312 char* url =
agget(gobj,
"href");
313 char* tooltip =
agget(gobj,
"tooltip");
314 char* target =
agget(gobj,
"target");
321 url =
agget(gobj,
"URL");
358 char **pstyle =
NULL;
361 if ((style =
agget(sg,
"style")) != 0 && style[0]) {
367 if (strcmp(p,
"filled") == 0) {
370 }
else if (strcmp(p,
"radial") == 0) {
378 }
else if (strcmp(p,
"striped") == 0) {
385 }
else if (strcmp(p,
"rounded") == 0) {
426 char* p = strchr (
s,
';');
434 v = strtod (p, &endp);
443#define AEQ0(x) (((x) < EPS) && ((x) > -EPS))
470 static int doWarn = 1;
477 for (p = colors; *p; p++) {
478 if (*p ==
':') nseg++;
489 agwarningf(
"Total size > 1 in \"%s\" color spec ", clrs);
496 if (v > 0)
s[cnum].hasFraction =
true;
502 agerrorf(
"Illegal value in \"%s\" color attribute; float expected after ';'\n",
521 for (i = 0; i < cnum; i++) {
522 if (
s[i].t <= 0) nseg++;
526 for (i = 0; i < cnum; i++) {
527 if (
s[i].t <= 0)
s[i].t =
delta;
536 for (i = cnum-1; i >= 0; i--) {
537 if (
s[i].t > 0)
break;
564 double angle0, angle1;
567 if (rv == 1 || rv == 2)
return rv;
575 if (
s->t <= 0)
continue;
581 angle1 = angle0 + 2 *
M_PI *
s->t;
614 if (rv == 1 || rv == 2)
return rv;
627 xdelta = (pts[1].
x - pts[0].
x);
628 pts[1].
x = pts[2].
x = pts[0].
x;
633 if (
s->t <= 0)
continue;
636 pts[1].
x = pts[2].
x = lastx;
638 pts[1].
x = pts[2].
x = pts[0].
x + xdelta*(
s->t);
640 pts[0].
x = pts[3].
x = pts[1].
x;
715 char *style, *p, **pp;
721 if (strcmp(p,
"filled") == 0)
736 double deltheta = 2 *
M_PI / (double)np;
739 for (
size_t i = 0; i < np; i++) {
740 ps[i].x = a * cos(theta);
741 ps[i].y = b * sin(theta);
756 double dis1 =
ptToLine2 (cp[0], cp[3], cp[1]);
757 double dis2 =
ptToLine2 (cp[0], cp[3], cp[2]);
758 return dis1 <
HW *
HW && dis2 <
HW *
HW;
766 if (cp[0].x > bb->
UR.
x || cp[0].
x < bb->
LL.
x ||
767 cp[0].
y > bb->
UR.
y || cp[0].
y < bb->
LL.
y ||
768 cp[1].
x > bb->
UR.
x || cp[1].
x < bb->
LL.
x ||
769 cp[1].
y > bb->
UR.
y || cp[1].
y < bb->
LL.
y ||
770 cp[2].
x > bb->
UR.
x || cp[2].
x < bb->
LL.
x ||
771 cp[2].
y > bb->
UR.
y || cp[2].
y < bb->
LL.
y ||
772 cp[3].
x > bb->
UR.
x || cp[3].
x < bb->
LL.
x ||
773 cp[3].
y > bb->
UR.
y || cp[3].
y < bb->
LL.
y) {
779 for (i = 0; i < 4; i++) {
780 if (cp[i].x > bb->
UR.
x)
782 else if (cp[i].x < bb->LL.
x)
784 if (cp[i].y > bb->
UR.
y)
786 else if (cp[i].y < bb->LL.
y)
799#if defined(DEBUG) && DEBUG == 2
800static void psmapOutput(
pointf*
ps,
size_t n) {
801 fprintf (stdout,
"newpath %f %f moveto\n",
ps[0].x,
ps[0].y);
802 for (
size_t i = 1; i < n; i++)
803 fprintf (stdout,
"%f %f lineto\n",
ps[i].x,
ps[i].y);
804 fprintf (stdout,
"closepath stroke\n");
813#define MARK_FIRST_SEG(L) ((L)->next = (segitem_t*)1)
814#define FIRST_SEG(L) ((L)->next == (segitem_t*)1)
815#define INIT_SEG(P,L) {(L)->next = 0; (L)->p = P;}
830 size_t i = 0, nump = 0,
last = 2 * n - 1;
832 for ( ; i < *pbs_poly_n; i++)
836 *pbs_n =
gv_recalloc(*pbs_n, *pbs_poly_n - 1, *pbs_poly_n,
sizeof(
size_t));
840 for (i = 0; i < n; i++) {
841 (*pbs_p)[nump+i] = p1[i];
842 (*pbs_p)[nump+
last-i] = p2[i];
844#if defined(DEBUG) && DEBUG == 2
845 psmapOutput (*pbs_p + nump,
last+1);
879 double ang, theta, phi;
880 theta = atan2(np.
y - cp.
y,np.
x - cp.
x);
881 phi = atan2(pp.
y - cp.
y,pp.
x - cp.
x);
883 if (ang > 0) ang -= 2*
M_PI;
885 return phi + ang / 2.0;
899 double theta, delx, dely;
912 np.
x = 2*cp.
x - pp.
x;
913 np.
y = 2*cp.
y - pp.
y;
918 pp.
x = 2*cp.
x - np.
x;
919 pp.
y = 2*cp.
y - np.
y;
922 delx = w2*cos(theta);
923 dely = w2*sin(theta);
945 pointf pts[4], pt1[50], pt2[50];
948 const size_t nc = (bp->
size - 1) / 3;
949 for (
size_t j = 0; j < nc; j++) {
950 for (
size_t k = 0; k < 4; k++) {
951 pts[k] = bp->
list[3*j + k];
960 segnext = segp->
next;
963 if (segnext ==
NULL ||
cnt == 50) {
983 const char *
str = sstr;
1010 char *buf_part_p =
NULL, *buf_p =
NULL, *cur, *part_in_p;
1015 part_in_p = spec_copy;
1025 if (n0 >= 0 || n1 >= 0) {
1031 rval =
BETWEEN(n0, layerNum, n1);
1033 }
else if (w0 !=
NULL) {
1035 rval = (n0 == layerNum);
1078 agwarningf(
"The layerselect attribute \"%s\" does not match any layer specifed by the layers attribute - ignored.\n",
p);
1104 agwarningf(
"The character \'%c\' appears in both the layersep and layerlistsep attributes - layerlistsep ignored.\n", *
tok);
1109 layer_names_t layerIDs = {0};
1112 layer_names_append(&layerIDs,
NULL);
1116 layer_names_append(&layerIDs,
tok);
1119 assert(layer_names_size(&layerIDs) - 1 <= INT_MAX);
1120 int ntok = (int)(layer_names_size(&layerIDs) - 1);
1123 if (layer_names_size(&layerIDs) > 1) {
1124 layer_names_append(&layerIDs,
NULL);
1127 layer_names_free(&layerIDs);
1137 char *
p =
agget(g,
"outputorder");
1139 if (!strcmp(
p,
"nodesfirst"))
1141 if (!strcmp(
p,
"edgesfirst"))
1158 if ((
str =
agget(g,
"layers")) != 0) {
1160 if ((
str =
agget(g,
"layerselect")) != 0 && *
str) {
1186 agwarningf(
"layers not supported in %s output\n",
1195 agwarningf(
"layers not supported in %s output\n",
1286 imageSize.
x = fmin(imageSize.
x, pageSize.
x);
1287 imageSize.
y = fmin(imageSize.
y, pageSize.
y);
1292 pageSize.
x = fmax(pageSize.
x, 0);
1294 pageSize.
y = fmax(pageSize.
y, 0);
1297 pageSize.
x = pageSize.
y = 0.;
1300 pageSize.
x = fmax(pageSize.
x, imageSize.
x);
1301 pageSize.
y = fmax(pageSize.
y, imageSize.
y);
1323 if (pageSize.
x > imageSize.
x)
1324 centering.
x = (pageSize.
x - imageSize.
x) / 2;
1325 if (pageSize.
y > imageSize.
y)
1326 centering.
y = (pageSize.
y - imageSize.
y) / 2;
1413 for (
size_t i = 0; i < numpts; i++) {
1414 pts[i].
x = inpts[i].
x;
1415 pts[i].
y = inpts[i].
y;
1425 char** styles =
NULL;
1429 for (
size_t i = 0; i <
xd->cnt; i++) {
1446 "polygon count exceeds gvrender_polygon support");
1489 clr0 =
p->stops[0].color;
1490 clr1 =
p->stops[1].color;
1491 frac =
p->stops[1].frac;
1492 if (
p->x1 ==
p->x0 &&
p->y1 ==
p->y0)
1495 angle = (int)(180.0*acos((
p->x0 -
p->x1)/
p->r0)/
M_PI);
1502 clr0 =
p->stops[0].color;
1503 clr1 =
p->stops[1].color;
1504 frac =
p->stops[1].frac;
1505 angle = (int)(180.0*atan2(
p->y1-
p->y0,
p->x1-
p->x0)/
M_PI);
1513 agwarningf(
"gradient pen colors not yet supported.\n");
1527 agwarningf(
"Images unsupported in \"background\" attribute\n");
1600 pagesArrayElem =
exch_xy(pagesArrayElem);
1601 pagesArraySize =
exch_xy(pagesArraySize);
1748 bool is_rect =
false;
1764 const size_t sides =
poly->sides < 3 ? 1 :
poly->sides;
1765 const size_t peripheries =
poly->peripheries < 2 ? 1 :
poly->peripheries;
1767 vertices =
poly->vertices;
1770 if ((
s =
agget(n,
"samplepoints")))
1776 nump = (nump_int < 4 || nump_int > 60) ?
DFLT_SAMPLE : (size_t)nump_int;
1780 if (
poly->peripheries == 0 && !filled) {
1789 if (
poly->regular) {
1797 p[1].
x =
coord.
x + vertices[2*peripheries - 1].
x;
1798 p[1].
y =
coord.
y + vertices[2*peripheries - 1].
y;
1802 p =
pEllipse(vertices[2 * peripheries - 1].x,
1803 vertices[2 * peripheries - 1].y, nump);
1804 for (
size_t i = 0; i < nump; i++) {
1812 assert(peripheries >= 1);
1813 size_t offset = (peripheries - 1) *
poly->sides;
1818 if (
poly->sides >= nump) {
1821 for (
size_t i = 0, j = 0; j < nump; i +=
delta, j++) {
1828 for (
size_t i = 0; i < nump; i++) {
1874 char **styles =
NULL;
1894 while ((
p = *sp++)) {
1895 if (
streq(
p,
"invis"))
return;
1911 double x =
p.
x - q.
x, y =
p.
y - q.
y;
1914 d /= sqrt(x * x + y * y +
EPSILON);
1926 double x = q.
x - r.
x, y = q.
y - r.
y;
1932 x =
p.
x -
s.x, y =
p.
y -
s.y;
1956 AF[1] = (
pointf){AF[0].
x - sz.
x, AF[0].
y};
1975 for (
p = pencolor; *
p;
p++) {
1988 double d =
DIST(pts[0],pts[1]);
1989 d +=
DIST(pts[1],pts[2]);
1990 d +=
DIST(pts[2],pts[3]);
2003 const size_t cnt = (bz->
size - 1) / 3;
2019 for (
size_t i = 0; i <
cnt; i++) {
2027 for (i = 0; i <
cnt; i++) {
2033 left->size = 3*(i+1) + 1;
2038 for (j = 0; j <
left->size; j++)
2041 for (j = 0; j <
right->size; j++)
2057 size_t num,
double arrowsize,
double penwidth) {
2062 char* endcolor =
NULL;
2078 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2083 if (
AEQ0(
s->t))
continue;
2086 endcolor =
s->color;
2138static double forfunc (
double curlen,
double totallen,
double initwid)
2140 return (1 - curlen / totallen) * initwid / 2.0;
2143static double revfunc (
double curlen,
double totallen,
double initwid)
2145 return curlen / totallen * initwid / 2.0;
2148static double nonefunc (
double curlen,
double totallen,
double initwid)
2153 return initwid / 2.0;
2156static double bothfunc (
double curlen,
double totallen,
double initwid)
2158 double fr = curlen/totallen;
2159 if (fr <= 0.5)
return fr * initwid;
2160 return (1 - fr) * initwid;
2178 int cnum, numsemi = 0;
2179 char *
color, *pencolor, *fillcolor;
2180 char *headcolor, *tailcolor, *lastcolor;
2181 char *colors =
NULL;
2184 pointf pf0, pf1, pf2 = { 0, 0 }, pf3, *offlist, *tmplist;
2187 bool tapered =
false;
2198 while ((
p = *sp++)) {
2199 if (
streq(
p,
"tapered")) {
2215 if (numsemi && numc) {
2223 fillcolor = pencolor =
color;
2246 if (pencolor !=
color)
2248 if (fillcolor !=
color)
2263 if (fillcolor !=
color)
2278 numc2 = (2 + (double)numc) / 2.0;
2279 for (
size_t i = 0; i < offspl.
size; i++) {
2286 for (j = 0; j < bz.
size - 1; j += 3) {
2288 pf1 = bz.
list[j + 1];
2294 pf2 = bz.
list[j + 2];
2295 pf3 = bz.
list[j + 3];
2296 offlist[j + 1] = offlist[j + 2] =
2299 tmplist[j].x = pf0.
x - numc2 * offlist[j].x;
2300 tmplist[j].y = pf0.
y - numc2 * offlist[j].y;
2301 tmplist[j + 1].x = pf1.
x - numc2 * offlist[j + 1].x;
2302 tmplist[j + 1].y = pf1.
y - numc2 * offlist[j + 1].y;
2303 tmplist[j + 2].x = pf2.
x - numc2 * offlist[j + 2].x;
2304 tmplist[j + 2].y = pf2.
y - numc2 * offlist[j + 2].y;
2308 tmplist[j].x = pf3.x - numc2 * offlist[j].x;
2309 tmplist[j].y = pf3.y - numc2 * offlist[j].y;
2311 lastcolor = headcolor = tailcolor =
color;
2313 for (cnum = 0,
color = strtok(colors,
":");
color;
2314 cnum++,
color = strtok(0,
":")) {
2317 if (
color != lastcolor) {
2325 headcolor = tailcolor =
color;
2328 for (
size_t i = 0; i < tmpspl.
size; i++) {
2331 for (
size_t j = 0; j < tmpspl.
list[i].
size; j++) {
2332 tmplist[j].
x += offlist[j].x;
2333 tmplist[j].y += offlist[j].y;
2339 if (
color != tailcolor) {
2350 if (
color != headcolor) {
2361 for (
size_t i = 0; i < offspl.
size; i++) {
2380 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2400 free(previous_color_scheme);
2429 size_t *pbs_n =
NULL, pbs_poly_n = 0;
2430 char *dflt_url =
NULL;
2431 char *dflt_target =
NULL;
2466 obj->
xlabel = tlab->text;
2480 if (((
s =
agget(e,
"href")) &&
s[0]) || ((
s =
agget(e,
"URL")) &&
s[0]))
2482 if (((
s =
agget(e,
"edgehref")) &&
s[0]) ||
2483 ((
s =
agget(e,
"edgeURL")) &&
s[0]))
2487 if (((
s =
agget(e,
"labelhref")) &&
s[0]) ||
2488 ((
s =
agget(e,
"labelURL")) &&
s[0]))
2492 if (((
s =
agget(e,
"tailhref")) &&
s[0]) ||
2493 ((
s =
agget(e,
"tailURL")) &&
s[0])) {
2496 }
else if (dflt_url)
2498 if (((
s =
agget(e,
"headhref")) &&
s[0]) ||
2499 ((
s =
agget(e,
"headURL")) &&
s[0])) {
2502 }
else if (dflt_url)
2507 if ((
s =
agget(e,
"target")) &&
s[0])
2509 if ((
s =
agget(e,
"edgetarget")) &&
s[0]) {
2512 }
else if (dflt_target)
2514 if ((
s =
agget(e,
"labeltarget")) &&
s[0])
2516 else if (dflt_target)
2518 if ((
s =
agget(e,
"tailtarget")) &&
s[0]) {
2521 }
else if (dflt_target)
2523 if ((
s =
agget(e,
"headtarget")) &&
s[0]) {
2526 }
else if (dflt_target)
2531 if (((
s =
agget(e,
"tooltip")) &&
s[0]) ||
2532 ((
s =
agget(e,
"edgetooltip")) &&
s[0])) {
2537 }
else if (obj->
label)
2540 if ((
s =
agget(e,
"labeltooltip")) &&
s[0]) {
2545 }
else if (obj->
label)
2548 if ((
s =
agget(e,
"tailtooltip")) &&
s[0]) {
2556 if ((
s =
agget(e,
"headtooltip")) &&
s[0]) {
2575 const size_t ns = spl->
size;
2576 for (
size_t i = 0; i < ns; i++)
2582 for (
size_t i = 0; i < pbs_poly_n; i++) {
2601 char* url,
char* tooltip,
char* target,
char *
id,
splines* spl)
2637 if (url ||
explicit) {
2660 bool explicit_itooltip) {
2665 if (explicit_iurl) url = iurl;
2666 else url = obj->
url;
2667 if (explicit_itooltip) {
2677 if (url ||
explicit) {
2753 char **styles =
NULL;
2781 while ((
p = *sp++)) {
2782 if (
streq(
p,
"invis"))
return;
2806 opbb.
LL.
x = opbb.
UR.
x = inpts->
x;
2807 opbb.
LL.
y = opbb.
UR.
y = inpts->
y;
2808 for (
size_t i = 1; i < numpts; i++) {
2810 if (inpts->
x < opbb.
LL.
x)
2811 opbb.
LL.
x = inpts->
x;
2812 else if (inpts->
x > opbb.
UR.
x)
2813 opbb.
UR.
x = inpts->
x;
2814 if (inpts->
y < opbb.
LL.
y)
2815 opbb.
LL.
y = inpts->
y;
2816 else if (inpts->
y > opbb.
UR.
y)
2817 opbb.
UR.
y = inpts->
y;
2831 switch (span->
just) {
2837 bb.
LL.
x = x - sz.
x / 2.0;
2838 bb.
UR.
x = x + sz.
x / 2.0;
2861 double fontsize = 0.0;
2862 char* fontname =
NULL;
2873 bb.
LL.
x = bb.
LL.
y = DBL_MAX;
2874 bb.
UR.
x = bb.
UR.
y = -DBL_MAX;
2878 for (
size_t i = 0; i <
xd->cnt; i++) {
2909 tf.
flags = fontflags;
2944 if ((
p =
agget(g,
"margin"))) {
2945 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2956 if ((
p =
agget(g,
"pad"))) {
2957 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2980 if ((
p =
agget(g,
"pagedir")) &&
p[0])
3063 job->
dpi.
x = job->
dpi.
y = (double)DEFAULT_DPI;
3073 double X,
Y, Z, x, y;
3094 if (sz.
x <= 0.001) sz.
x = size.
x;
3095 if (sz.
y <= 0.001) sz.
y = size.
y;
3096 if (size.
x < sz.
x || size.
y < sz.
y
3098 && size.
x > sz.
x && size.
y > sz.
y))
3099 Z = fmin(size.
x / sz.
x, size.
y / sz.
y);
3103 x = (LL.
x + UR.
x) / 2.;
3104 y = (LL.
y + UR.
y) / 2.;
3112 if ((
str =
agget(g,
"viewport"))) {
3114 rv = sscanf(
str,
"%lf,%lf,%lf,\'%[^\']\'", &
X, &
Y, &Z, nodename);
3124 rv = sscanf(
str,
"%lf,%lf,%lf,%[^,]%c", &
X, &
Y, &Z, nodename, &junk);
3133 rv = sscanf(
str,
"%lf,%lf,%lf,%lf,%lf", &
X, &
Y, &Z, &x, &y);
3162 if (((
str =
agget(sg,
"pencolor")) != 0) &&
str[0])
3164 if (((
str =
agget(sg,
"bgcolor")) != 0) &&
str[0])
3166 if (((
str =
agget(sg,
"fillcolor")) != 0) &&
str[0])
3168 if (((
str =
agget(sg,
"fontcolor")) != 0) &&
str[0])
3182 if (((
str =
agget(g,
"fontcolor")) != 0) &&
str[0])
3189 if (((
str =
agget(n,
"pencolor")) != 0) &&
str[0])
3191 if (((
str =
agget(n,
"fillcolor")) != 0) &&
str[0]) {
3192 if (strchr(
str,
':')) {
3194 for (
str = strtok(colors,
":");
str;
3195 str = strtok(0,
":")) {
3205 if (((
str =
agget(n,
"fontcolor")) != 0) &&
str[0])
3209 if (strchr(
str,
':')) {
3211 for (
str = strtok(colors,
":");
str;
3212 str = strtok(0,
":")) {
3222 if (((
str =
agget(e,
"fontcolor")) != 0) &&
str[0])
3311#define NotFirstPage(j) (((j)->layerNum>1)||((j)->pagesArrayElem.x > 0)||((j)->pagesArrayElem.x > 0))
3387 free(previous_color_scheme);
3488 int doPerim, c, filled;
3490 char *
color, *fillcolor, *pencolor, **style, *
s;
3522 fillcolor = pencolor = 0;
3546 fillcolor = pencolor =
color;
3556 if ((filled == 0 || !fillcolor) && (
color =
agget(sg,
"bgcolor")) != 0 &&
color[0]) {
3589 AF[0] =
GD_bb(sg).LL;
3590 AF[2] =
GD_bb(sg).UR;
3604 AF[0] =
GD_bb(sg).LL;
3605 AF[2] =
GD_bb(sg).UR;
3624 else if (filled != 0) {
3656 free(previous_color_scheme);
3691 const char *start = p;
3708 size_t size = (size_t)(p - start);
3709 return (
token_t){.type = token, .start = start, .size = size};
3724 size_t parse_offsets[
sizeof(parse) /
sizeof(parse[0])];
3726 bool in_parens =
false;
3739 agerrorf(
"nesting not allowed in style: %s\n",
s);
3748 agerrorf(
"unmatched ')' in style: %s\n",
s);
3763 parse_offsets[fun++] =
agxblen(&ps_xb);
3771 agerrorf(
"unmatched '(' in style: %s\n",
s);
3779 for (
size_t i = 0; i < fun; ++i) {
3780 parse[i] = base + parse_offsets[i];
3792 assert(bz.
size > 0);
3793 assert(bz.
size % 3 == 1);
3795 for (
size_t i = 1; i < bz.
size;) {
3801 p.
x = ( p1.
x + p2.
x ) / 2;
3802 p.
y = ( p1.
y + p2.
y ) / 2;
3817 assert(spl->
size > 0);
3820 for (
size_t i = 0; i < spl->
size; i++) {
3890 static char* save_locale;
3897 setlocale (LC_NUMERIC,
"C");
3903 setlocale (LC_NUMERIC, save_locale);
3910#define FINISH() if (Verbose) fprintf(stderr,"gvRenderJobs %s: %.2f secs.\n", agnameof(g), elapsed_sec())
3914 static GVJ_t *prevjob;
3915 GVJ_t *job, *firstjob;
3921 agerrorf(
"Layout was not done. Missing layout plugins? \n");
4050 agwarningf(
"More than 2 colors specified for a gradient - ignoring remaining\n");
4052 clrs[0] =
gv_calloc(strlen(colorlist) + 1,
sizeof(
char));
4055 clrs[1] = clrs[0] + (strlen(clrs[0])+1);
4062 *frac = segs.
segs[0].
t;
4064 *frac = 1 - segs.
segs[1].
t;
static agxbuf last
last message
static void agxbfree(agxbuf *xb)
free any malloced resources
static size_t agxbput(agxbuf *xb, const char *s)
append string s into xb
static size_t agxbput_n(agxbuf *xb, const char *s, size_t ssz)
append string s of length ssz into xb
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static size_t agxblen(const agxbuf *xb)
return number of characters currently stored
static int agxbputc(agxbuf *xb, char c)
add character to buffer
static char * agxbuse(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
static char * gv_strdup(const char *original)
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
boxf arrow_bb(pointf p, pointf u, double arrowsize)
void arrow_gen(GVJ_t *job, emit_state_t emit_state, pointf p, pointf u, double arrowsize, double penwidth, uint32_t flag)
CDT_API int dtclose(Dt_t *)
CDT_API Dtmethod_t * Dtoset
ordered set (self-adjusting tree)
CDT_API Dt_t * dtopen(Dtdisc_t *, Dtmethod_t *)
COLORPROCS_API char * setColorScheme(const char *s)
pointf Bezier(pointf *V, double t, pointf *Left, pointf *Right)
char * late_nnstring(void *obj, attrsym_t *attr, char *defaultValue)
bool mapbool(const char *p)
char * late_string(void *obj, attrsym_t *attr, char *defaultValue)
int late_int(void *obj, attrsym_t *attr, int defaultValue, int minimum)
bool overlap_label(textlabel_t *lp, boxf b)
double late_double(void *obj, attrsym_t *attr, double defaultValue, double minimum)
pointf dotneato_closest(splines *spl, pointf pt)
char * latin1ToUTF8(char *s)
Converts string from Latin1 encoding to utf8. Also translates HTML entities.
char * htmlEntityUTF8(char *s, graph_t *g)
#define DEFAULT_SELECTEDFILLCOLOR
#define DEFAULT_LAYERLISTSEP
#define DEFAULT_EMBED_MARGIN
#define DEFAULT_ACTIVEFILLCOLOR
#define DEFAULT_PRINT_MARGIN
#define DEFAULT_DELETEDFILLCOLOR
#define DEFAULT_SELECTEDPENCOLOR
#define DEFAULT_VISITEDFILLCOLOR
#define DEFAULT_DELETEDPENCOLOR
#define DEFAULT_GRAPH_PAD
#define DEFAULT_VISITEDPENCOLOR
#define DEFAULT_ACTIVEPENCOLOR
static void ins(Dict_t *d, Dtlink_t **set, Agedge_t *e)
static void del(Dict_t *d, Dtlink_t **set, Agedge_t *e)
Ppolyline_t * ellipticWedge(pointf ctr, double xsemi, double ysemi, double angle0, double angle1)
bool emit_once(char *str)
int wedgedEllipse(GVJ_t *job, pointf *pf, char *clrs)
static bool node_in_box(node_t *n, boxf b)
static bool write_edge_test(Agraph_t *g, Agedge_t *e)
static void free_stroke(stroke_t sp)
static void map_point(GVJ_t *job, pointf pf)
static radfunc_t taperfun(edge_t *e)
static void emit_xdot(GVJ_t *job, xdot *xd)
static void emit_end_graph(GVJ_t *job)
static void emit_end_cluster(GVJ_t *job)
static int * parse_layerselect(GVC_t *gvc, char *p)
static void emit_edge_graphics(GVJ_t *job, edge_t *e, char **styles)
void emit_clusters(GVJ_t *job, Agraph_t *g, int flags)
static void emit_cluster_colors(GVJ_t *job, graph_t *g)
static double revfunc(double curlen, double totallen, double initwid)
static void nodeIntersect(GVJ_t *job, pointf p, bool explicit_iurl, char *iurl, bool explicit_itooltip)
static char * defaultlinestyle[3]
static void init_splines_bb(splines *spl)
static bool selectedLayer(GVC_t *gvc, int layerNum, int numLayers, char *spec)
void gv_fixLocale(int set)
static segitem_t * approx_bezier(pointf *cp, segitem_t *lp)
static void nextlayer(GVJ_t *job, int **listp)
static void layerPagePrefix(GVJ_t *job, agxbuf *xb)
static void init_bb(graph_t *g)
static void emit_end_node(GVJ_t *job)
static pointf computeoffset_qr(pointf p, pointf q, pointf r, pointf s, double d)
struct segitem_s segitem_t
static bool edge_in_layer(GVJ_t *job, edge_t *e)
static double forfunc(double curlen, double totallen, double initwid)
static char ** checkClusterStyle(graph_t *sg, graphviz_polygon_style_t *flagp)
static bool isFilled(node_t *n)
static void emit_background(GVJ_t *job, graph_t *g)
static void init_bb_edge(edge_t *e)
int initMapData(GVJ_t *job, char *lbl, char *url, char *tooltip, char *target, char *id, void *gobj)
static char * preprocessTooltip(char *s, void *gobj)
static int multicolor(GVJ_t *job, edge_t *e, char **styles, char *colors, size_t num, double arrowsize, double penwidth)
static int parse_layers(GVC_t *gvc, graph_t *g, char *p)
static char * interpretCRNL(char *ins)
static boxf bezier_bb(bezier bz)
static bool is_style_delim(int c)
static void expandBB(boxf *bb, pointf p)
static bool clust_in_layer(GVJ_t *job, graph_t *sg)
static bool isRect(polygon_t *p)
static void emit_edge(GVJ_t *job, edge_t *e)
static pointf * pEllipse(double a, double b, size_t np)
static Dtdisc_t stringdict
static void init_bb_node(graph_t *g, node_t *n)
static double bothfunc(double curlen, double totallen, double initwid)
static void emit_view(GVJ_t *job, graph_t *g, int flags)
static boxf textBB(double x, double y, textspan_t *span)
static void emit_begin_node(GVJ_t *job, node_t *n)
static double approxLen(pointf *pts)
static int numPhysicalLayers(GVJ_t *job)
Return number of physical layers to be emitted.
static void init_job_dpi(GVJ_t *job, graph_t *g)
static void map_label(GVJ_t *job, textlabel_t *lab)
static bool node_in_layer(GVJ_t *job, graph_t *g, node_t *n)
static void firstpage(GVJ_t *job)
static void splitBSpline(bezier *bz, double t, bezier *left, bezier *right)
static char * saved_color_scheme
void * init_xdot(Agraph_t *g)
static void emit_edge_label(GVJ_t *job, textlabel_t *lbl, emit_state_t lkind, int explicit, char *url, char *tooltip, char *target, char *id, splines *spl)
static void mkSegPts(segitem_t *prv, segitem_t *cur, segitem_t *nxt, pointf *p1, pointf *p2, double w2)
static void initObjMapData(GVJ_t *job, textlabel_t *lab, void *gobj)
static void init_job_margin(GVJ_t *job)
static void freePara(exdot_op *op)
static bool validpage(GVJ_t *job)
static int chkOrder(graph_t *g)
static void init_job_viewport(GVJ_t *job, graph_t *g)
static void emit_colors(GVJ_t *job, graph_t *g)
static void emit_begin_cluster(GVJ_t *job, Agraph_t *sg)
static void setup_page(GVJ_t *job)
static int layer_index(GVC_t *gvc, char *str, int all)
static bool validlayer(GVJ_t *job)
static void init_gvc(GVC_t *gvc, graph_t *g)
static int parseSegs(char *clrs, size_t nseg, colorsegs_t *psegs)
static bool is_natural_number(const char *sstr)
int stripedBox(GVJ_t *job, pointf *AF, char *clrs, int rotate)
obj_state_t * push_obj_state(GVJ_t *job)
static void emit_attachment(GVJ_t *job, textlabel_t *lp, splines *spl)
static void emit_page(GVJ_t *job, graph_t *g)
gvevent_key_binding_t gvevent_key_binding[]
char ** parse_style(char *s)
static void firstlayer(GVJ_t *job, int **listp)
void emit_once_reset(void)
static void map_output_bspline(pointf **pbs, size_t **pbs_n, size_t *pbs_poly_n, bezier *bp, double w2)
void emit_map_rect(GVJ_t *job, boxf b)
static void emit_end_edge(GVJ_t *job)
static void freeSegs(colorsegs_t *segs)
static void init_layering(GVC_t *gvc, graph_t *g)
static void init_job_pagination(GVJ_t *job, graph_t *g)
static double nonefunc(double curlen, double totallen, double initwid)
static boxf ptsBB(xdot_point *inpts, size_t numpts, boxf *bb)
void pop_obj_state(GVJ_t *job)
static void nextpage(GVJ_t *job)
static pointf * copyPts(xdot_point *inpts, size_t numpts)
static point pagecode(GVJ_t *job, char c)
#define MARK_FIRST_SEG(L)
static bool edge_in_box(edge_t *e, boxf b)
gvdevice_callbacks_t gvdevice_callbacks
char * getObjId(GVJ_t *job, void *obj, agxbuf *xb)
Use id of root graph if any, plus kind and internal id of object.
void update_bb_bz(boxf *bb, pointf *cp)
static void map_bspline_poly(pointf **pbs_p, size_t **pbs_n, size_t *pbs_poly_n, size_t n, pointf *p1, pointf *p2)
const size_t gvevent_key_binding_size
static void emit_begin_edge(GVJ_t *job, edge_t *e, char **styles)
static token_t style_token(char **s)
static bool check_control_points(pointf *cp)
static void emit_begin_graph(GVJ_t *job, graph_t *g)
static bool selectedlayer(GVJ_t *job, char *spec)
static segitem_t * appendSeg(pointf p, segitem_t *lp)
static bool write_node_test(Agraph_t *g, Agnode_t *n)
static void emit_node(GVJ_t *job, node_t *n)
#define P2RECT(p, pr, sx, sy)
void emit_graph(GVJ_t *job, graph_t *g)
static char * default_pencolor(char *pencolor, char *deflt)
bool findStopColor(char *colorlist, char *clrs[2], double *frac)
double(* radfunc_t)(double, double, double)
static double getSegLen(char *s)
static void init_job_pad(GVJ_t *job)
static double bisect(pointf pp, pointf cp, pointf np)
static pointf computeoffset_p(pointf p, pointf q, double d)
#define X(prefix, name, str, type, subtype,...)
void rect2poly(pointf *p)
double ptToLine2(pointf a, pointf b, pointf p)
geometric functions (e.g. on points and boxes)
static pointf mid_pointf(pointf p, pointf q)
static pointf sub_pointf(pointf p, pointf q)
static point exch_xy(point p)
static pointf exch_xyf(pointf p)
static bool boxf_overlap(boxf b0, boxf b1)
Agsym_t * E_visitedpencolor
Agsym_t * G_deletedpencolor
Agsym_t * G_deletedfillcolor
Agsym_t * E_deletedfillcolor
Agsym_t * G_activepencolor
Agsym_t * G_activefillcolor
Agsym_t * E_activefillcolor
Agsym_t * G_visitedfillcolor
Agsym_t * E_selectedpencolor
Agsym_t * E_selectedfillcolor
Agsym_t * E_deletedpencolor
Agsym_t * E_activepencolor
Agsym_t * G_gradientangle
Agsym_t * E_visitedfillcolor
bool Y_invert
invert y in dot & plain output
Agsym_t * G_visitedpencolor
static double len(glCompPoint p)
static int cnt(Dict_t *d, Dtlink_t **set)
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
char * agget(void *obj, char *name)
char * agxget(void *obj, Agsym_t *sym)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
void agwarningf(const char *fmt,...)
void agerrorf(const char *fmt,...)
int agerr(agerrlevel_t level, const char *fmt,...)
#define agfindgraphattr(g, a)
int agisdirected(Agraph_t *g)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
Agraph_t * agraphof(void *obj)
char * agnameof(void *)
returns a string descriptor for the object.
int agcontains(Agraph_t *, void *obj)
returns non-zero if obj is a member of (sub)graph
Agraph_t * agroot(void *obj)
int gvRenderJobs(GVC_t *gvc, graph_t *g)
replacements for ctype.h functions
static bool gv_isdigit(int c)
static bool gv_isspace(int c)
Arithmetic helper functions.
static bool is_exactly_zero(double v)
is a value precisely 0.0?
swig_ptr_object_handlers offset
Graphviz context library.
#define EMIT_CLUSTERS_LAST
#define GVRENDER_DOES_TOOLTIPS
#define GVRENDER_DOES_LABELS
#define GVRENDER_NO_WHITE_BG
#define GVDEVICE_DOES_PAGES
#define GVDEVICE_DOES_LAYERS
#define GVDEVICE_DOES_TRUECOLOR
#define GVRENDER_DOES_MAPS
#define GVRENDER_DOES_TARGETS
#define GVRENDER_DOES_TRANSFORM
#define GVRENDER_Y_GOES_DOWN
#define GVRENDER_DOES_MAP_POLYGON
#define GVRENDER_DOES_MAP_RECTANGLE
static void color(Agraph_t *g)
void gvrender_end_nodes(GVJ_t *job)
void gvrender_begin_nodes(GVJ_t *job)
void gvrender_end_job(GVJ_t *job)
void gvrender_beziercurve(GVJ_t *job, pointf *AF, size_t n, int filled)
void gvrender_comment(GVJ_t *job, char *str)
void gvrender_end_graph(GVJ_t *job)
void gvrender_set_style(GVJ_t *job, char **s)
void gvrender_set_fillcolor(GVJ_t *job, char *name)
void gvrender_polyline(GVJ_t *job, pointf *AF, size_t n)
void gvrender_begin_edges(GVJ_t *job)
pointf * gvrender_ptf_A(GVJ_t *job, pointf *af, pointf *AF, size_t n)
void gvrender_polygon(GVJ_t *job, pointf *af, size_t n, int filled)
void gvrender_end_edges(GVJ_t *job)
void gvrender_begin_graph(GVJ_t *job)
void gvrender_end_page(GVJ_t *job)
void gvrender_end_layer(GVJ_t *job)
void gvrender_box(GVJ_t *job, boxf BF, int filled)
void gvrender_begin_cluster(GVJ_t *job)
void gvrender_set_gradient_vals(GVJ_t *job, char *stopcolor, int angle, double frac)
void gvrender_ellipse(GVJ_t *job, pointf *AF, int filled)
void gvrender_end_edge(GVJ_t *job)
void gvrender_begin_anchor(GVJ_t *job, char *href, char *tooltip, char *target, char *id)
void gvrender_end_anchor(GVJ_t *job)
void gvrender_begin_layer(GVJ_t *job)
void gvrender_begin_page(GVJ_t *job)
void gvrender_begin_edge(GVJ_t *job)
GVJ_t * gvjobs_first(GVC_t *gvc)
void gvrender_textspan(GVJ_t *job, pointf p, textspan_t *span)
void gvrender_begin_node(GVJ_t *job)
int gvrender_begin_job(GVJ_t *job)
void gvrender_end_cluster(GVJ_t *job)
GVJ_t * gvjobs_next(GVC_t *gvc)
void gvrender_set_penwidth(GVJ_t *job, double penwidth)
int gvrender_select(GVJ_t *job, const char *lang)
void gvrender_end_node(GVJ_t *job)
void gvrender_set_pencolor(GVJ_t *job, char *name)
char * strdup_and_subst_obj(char *str, void *obj)
void free_textspan(textspan_t *tl, size_t cnt)
void emit_label(GVJ_t *job, emit_state_t emit_state, textlabel_t *lp)
#define DEFINE_LIST(name, type)
static void add_point(int *n, int igrp, double **x, int *nmax, double point[], int **groups)
void freePath(Ppolyline_t *p)
void round_corners(GVJ_t *job, pointf *AF, size_t sides, graphviz_polygon_style_t style, int filled)
Handle some special graphical cases, such as rounding the shape, adding diagonals at corners,...
pointf textspan_size(GVC_t *gvc, textspan_t *span)
Estimates size of a textspan, in points.
shape_kind shapeOf(node_t *)
stroke_t taper(bezier *, double(*radfunc_t)(double, double, double), double initwid)
static void rotate(int n, int dim, double *x, double angle)
static bool streq(const char *a, const char *b)
are a and b equal?
Agraph_t * root
subgraphs - ancestors
const char ** show_boxes
emit code for correct box coordinates
int viewNum
rendering state
gvplugin_active_layout_t layout
gvdevice_callbacks_t * callbacks
gvplugin_active_device_t device
gvevent_key_binding_t * keybindings
gvplugin_active_render_t render
const char * output_langname
double t
segment size >= 0
gvdevice_features_t * features
gvrender_features_t * features
unsigned explicit_tailtarget
unsigned explicit_edgetarget
size_t url_bsplinemap_poly_n
unsigned explicit_tooltip
size_t * url_bsplinemap_n
unsigned explicit_labeltooltip
map_shape_t url_map_shape
unsigned explicit_tailurl
pointf * url_bsplinemap_p
unsigned explicit_tailtooltip
unsigned explicit_headurl
unsigned explicit_headtarget
unsigned explicit_headtooltip
unsigned labeledgealigned
size_t sides
number of sides
size_t nvertices
number of points in the stroke
const char * start
Beginning of the token content.
size_t size
Number of bytes in the token content.
static tok_t tok(const char *input, const char *separators)
begin tokenization of a new string
#define GUI_STATE_SELECTED
#define GUI_STATE_DELETED
#define GUI_STATE_VISITED
int(* pf)(void *, char *,...)
int statXDot(xdot *x, xdot_stats *sp)
xdot * parseXDotF(char *s, drawfunc_t fns[], size_t sz)
parsing and deparsing of xdot operations
void(* freefunc_t)(xdot_op *)