45#define strtok_r strtok_s
48#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)
63 if (!((p =
agget(g,
"_background")) && p[0])) {
64 if (!((p =
agget(g,
"_draw_")) && p[0])) {
84 fprintf (stderr,
"%d ops %.2f sec\n", stats.
cnt, et);
88 fprintf (stderr,
"%d ellipses\n", stats.
n_ellipse);
89 fprintf (stderr,
"%d texts\n", stats.
n_text);
171 if (tooltip && tooltip[0]) {
176 else if (obj->
label) {
211 id =
agget(obj,
"id");
212 if (
id && *
id !=
'\0') {
217 if (obj != root && gid) {
256 bool backslash_seen =
false;
258 while ((c = *
ins++)) {
259 if (backslash_seen) {
272 backslash_seen =
false;
276 backslash_seen =
true;
315 char* url =
agget(gobj,
"href");
316 char* tooltip =
agget(gobj,
"tooltip");
317 char* target =
agget(gobj,
"target");
321 if (lab) lbl = lab->
text;
324 url =
agget(gobj,
"URL");
328 initMapData (job, lbl, url, tooltip, target,
id, gobj);
361 char **pstyle =
NULL;
364 if ((style =
agget(sg,
"style")) != 0 && style[0]) {
370 if (strcmp(p,
"filled") == 0) {
373 }
else if (strcmp(p,
"radial") == 0) {
381 }
else if (strcmp(p,
"striped") == 0) {
388 }
else if (strcmp(p,
"rounded") == 0) {
422 char *p = memchr(
s->data,
';',
s->size);
429 s->size = (size_t)(p -
s->data);
435 v = strtod (p, &endp);
444#define AEQ0(x) (((x) < EPS) && ((x) > -EPS))
462static int parseSegs(
const char *clrs, colorsegs_t *psegs) {
463 colorsegs_t segs = {0};
465 static int doWarn = 1;
474 agwarningf(
"Total size > 1 in \"%s\" color spec ", clrs);
482 if (v > 0)
s.hasFraction =
true;
484 colorsegs_append(&segs,
s);
488 agerrorf(
"Illegal value in \"%s\" color attribute; float expected after ';'\n",
494 colorsegs_free(&segs);
507 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
508 if (colorsegs_get(&segs, i).t <= 0) nseg++;
512 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
518 colorsegs_back(&segs)->t +=
left;
523 while (!colorsegs_is_empty(&segs)) {
524 if (colorsegs_back(&segs)->t > 0)
break;
525 colorsegs_pop_back(&segs);
548 double angle0, angle1;
551 if (rv == 1 || rv == 2)
return rv;
558 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
560 if (
s.color ==
NULL)
break;
561 if (
s.t <= 0)
continue;
564 if (i + 1 == colorsegs_size(&segs))
567 angle1 = angle0 + 2 *
M_PI *
s.t;
576 colorsegs_free(&segs);
598 if (rv == 1 || rv == 2)
return rv;
611 xdelta = (pts[1].
x - pts[0].
x);
612 pts[1].
x = pts[2].
x = pts[0].
x;
616 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
618 if (
s.color ==
NULL)
break;
619 if (
s.t <= 0)
continue;
621 if (i + 1 == colorsegs_size(&segs))
622 pts[1].
x = pts[2].
x = lastx;
624 pts[1].
x = pts[2].
x = pts[0].
x + xdelta * (
s.t);
626 pts[0].
x = pts[3].
x = pts[1].
x;
630 colorsegs_free(&segs);
701 char *style, *p, **pp;
707 if (strcmp(p,
"filled") == 0)
722 double deltheta = 2 *
M_PI / (double)np;
725 for (
size_t i = 0; i < np; i++) {
726 ps[i].x = a * cos(theta);
727 ps[i].y = b * sin(theta);
742 double dis1 =
ptToLine2 (cp[0], cp[3], cp[1]);
743 double dis2 =
ptToLine2 (cp[0], cp[3], cp[2]);
744 return dis1 <
HW *
HW && dis2 <
HW *
HW;
752 if (cp[0].x > bb->
UR.
x || cp[0].
x < bb->
LL.
x ||
753 cp[0].
y > bb->
UR.
y || cp[0].
y < bb->
LL.
y ||
754 cp[1].
x > bb->
UR.
x || cp[1].
x < bb->
LL.
x ||
755 cp[1].
y > bb->
UR.
y || cp[1].
y < bb->
LL.
y ||
756 cp[2].
x > bb->
UR.
x || cp[2].
x < bb->
LL.
x ||
757 cp[2].
y > bb->
UR.
y || cp[2].
y < bb->
LL.
y ||
758 cp[3].
x > bb->
UR.
x || cp[3].
x < bb->
LL.
x ||
759 cp[3].
y > bb->
UR.
y || cp[3].
y < bb->
LL.
y) {
765 for (i = 0; i < 4; i++) {
766 if (cp[i].x > bb->
UR.
x)
768 else if (cp[i].x < bb->LL.
x)
770 if (cp[i].y > bb->
UR.
y)
772 else if (cp[i].y < bb->LL.
y)
788 const pointf first = points_get(
ps, start);
789 fprintf(stdout,
"newpath %f %f moveto\n", first.
x, first.
y);
790 for (
size_t i = start + 1; i < start + n; ++i) {
791 const pointf pt = points_get(
ps, i);
792 fprintf(stdout,
"%f %f lineto\n", pt.
x, pt.
y);
794 fprintf (stdout,
"closepath stroke\n");
802#define MARK_FIRST_SEG(L) ((L)->next = (segitem_t*)1)
803#define FIRST_SEG(L) ((L)->next == (segitem_t*)1)
804#define INIT_SEG(P,L) {(L)->next = 0; (L)->p = P;}
821 pbs_size_append(pbs_n, 2 * n);
823 const UNUSED size_t nump = points_size(pbs_p);
824 for (
size_t i = 0; i < n; i++) {
825 points_append(pbs_p, p1[i]);
827 for (
size_t i = 0; i < n; i++) {
828 points_append(pbs_p, p2[n - i - 1]);
830#if defined(DEBUG) && DEBUG == 2
865 double ang, theta, phi;
866 theta = atan2(np.
y - cp.
y,np.
x - cp.
x);
867 phi = atan2(pp.
y - cp.
y,pp.
x - cp.
x);
869 if (ang > 0) ang -= 2*
M_PI;
871 return phi + ang / 2.0;
885 double theta, delx, dely;
898 np.
x = 2*cp.
x - pp.
x;
899 np.
y = 2*cp.
y - pp.
y;
904 pp.
x = 2*cp.
x - np.
x;
905 pp.
y = 2*cp.
y - np.
y;
908 delx = w2*cos(theta);
909 dely = w2*sin(theta);
931 pointf pts[4], pt1[50], pt2[50];
934 const size_t nc = (bp->
size - 1) / 3;
935 for (
size_t j = 0; j < nc; j++) {
936 for (
size_t k = 0; k < 4; k++) {
937 pts[k] = bp->
list[3*j + k];
946 segnext = segp->
next;
949 if (segnext ==
NULL ||
cnt == 50) {
969 const char *
str = sstr;
996 char *buf_part_p =
NULL, *buf_p =
NULL, *cur, *part_in_p;
1001 part_in_p = spec_copy;
1011 if (n0 >= 0 || n1 >= 0) {
1017 rval =
BETWEEN(n0, layerNum, n1);
1019 }
else if (w0 !=
NULL) {
1021 rval = (n0 == layerNum);
1064 agwarningf(
"The layerselect attribute \"%s\" does not match any layer specifed by the layers attribute - ignored.\n",
p);
1090 agwarningf(
"The character \'%c\' appears in both the layersep and layerlistsep attributes - layerlistsep ignored.\n", *
tok);
1095 layer_names_t layerIDs = {0};
1098 layer_names_append(&layerIDs,
NULL);
1102 layer_names_append(&layerIDs,
tok);
1105 assert(layer_names_size(&layerIDs) - 1 <= INT_MAX);
1106 int ntok = (int)(layer_names_size(&layerIDs) - 1);
1109 if (layer_names_size(&layerIDs) > 1) {
1110 layer_names_append(&layerIDs,
NULL);
1113 layer_names_free(&layerIDs);
1123 char *
p =
agget(g,
"outputorder");
1125 if (!strcmp(
p,
"nodesfirst"))
1127 if (!strcmp(
p,
"edgesfirst"))
1144 if ((
str =
agget(g,
"layers")) != 0) {
1146 if ((
str =
agget(g,
"layerselect")) != 0 && *
str) {
1172 agwarningf(
"layers not supported in %s output\n",
1181 agwarningf(
"layers not supported in %s output\n",
1272 imageSize.
x = fmin(imageSize.
x, pageSize.
x);
1273 imageSize.
y = fmin(imageSize.
y, pageSize.
y);
1278 pageSize.
x = fmax(pageSize.
x, 0);
1280 pageSize.
y = fmax(pageSize.
y, 0);
1283 pageSize.
x = pageSize.
y = 0.;
1286 pageSize.
x = fmax(pageSize.
x, imageSize.
x);
1287 pageSize.
y = fmax(pageSize.
y, imageSize.
y);
1309 if (pageSize.
x > imageSize.
x)
1310 centering.
x = (pageSize.
x - imageSize.
x) / 2;
1311 if (pageSize.
y > imageSize.
y)
1312 centering.
y = (pageSize.
y - imageSize.
y) / 2;
1399 for (
size_t i = 0; i < numpts; i++) {
1400 pts[i].
x = inpts[i].
x;
1401 pts[i].
y = inpts[i].
y;
1411 char** styles =
NULL;
1415 for (
size_t i = 0; i <
xd->cnt; i++) {
1432 "polygon count exceeds gvrender_polygon support");
1475 clr0 =
p->stops[0].color;
1476 clr1 =
p->stops[1].color;
1477 frac =
p->stops[1].frac;
1478 if (
p->x1 ==
p->x0 &&
p->y1 ==
p->y0)
1481 angle = (int)(180.0*acos((
p->x0 -
p->x1)/
p->r0)/
M_PI);
1488 clr0 =
p->stops[0].color;
1489 clr1 =
p->stops[1].color;
1490 frac =
p->stops[1].frac;
1491 angle = (int)(180.0*atan2(
p->y1-
p->y0,
p->x1-
p->x0)/
M_PI);
1499 agwarningf(
"gradient pen colors not yet supported.\n");
1513 agwarningf(
"Images unsupported in \"background\" attribute\n");
1550 char *clrs[2] = {0};
1587 pagesArrayElem =
exch_xy(pagesArrayElem);
1588 pagesArraySize =
exch_xy(pagesArraySize);
1735 bool is_rect =
false;
1751 const size_t sides =
poly->sides < 3 ? 1 :
poly->sides;
1752 const size_t peripheries =
poly->peripheries < 2 ? 1 :
poly->peripheries;
1754 vertices =
poly->vertices;
1757 if ((
s =
agget(n,
"samplepoints")))
1763 nump = (nump_int < 4 || nump_int > 60) ?
DFLT_SAMPLE : (size_t)nump_int;
1767 if (
poly->peripheries == 0 && !filled) {
1776 if (
poly->regular) {
1784 p[1].
x =
coord.
x + vertices[2*peripheries - 1].
x;
1785 p[1].
y =
coord.
y + vertices[2*peripheries - 1].
y;
1789 p =
pEllipse(vertices[2 * peripheries - 1].x,
1790 vertices[2 * peripheries - 1].y, nump);
1791 for (
size_t i = 0; i < nump; i++) {
1799 assert(peripheries >= 1);
1800 size_t offset = (peripheries - 1) *
poly->sides;
1805 if (
poly->sides >= nump) {
1808 for (
size_t i = 0, j = 0; j < nump; i +=
delta, j++) {
1815 for (
size_t i = 0; i < nump; i++) {
1861 char **styles =
NULL;
1881 while ((
p = *sp++)) {
1882 if (
streq(
p,
"invis"))
return;
1898 double x =
p.
x - q.
x, y =
p.
y - q.
y;
1901 d /= sqrt(x * x + y * y +
EPSILON);
1913 double x = q.
x - r.
x, y = q.
y - r.
y;
1919 x =
p.
x -
s.x, y =
p.
y -
s.y;
1943 AF[1] = (
pointf){AF[0].
x - sz.
x, AF[0].
y};
1958 const char *deflt) {
1960 for (
const char *
p = pencolor; *
p;
p++) {
1969 double d =
DIST(pts[0],pts[1]);
1970 d +=
DIST(pts[1],pts[2]);
1971 d +=
DIST(pts[2],pts[3]);
1984 const size_t cnt = (bz->
size - 1) / 3;
2000 for (
size_t i = 0; i <
cnt; i++) {
2008 for (i = 0; i <
cnt; i++) {
2014 left->size = 3*(i+1) + 1;
2019 for (j = 0; j <
left->size; j++)
2022 for (j = 0; j <
right->size; j++)
2038 double arrowsize,
double penwidth) {
2043 char* endcolor =
NULL;
2059 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2063 for (
size_t j = 0; j < colorsegs_size(&segs); ++j) {
2065 if (
s.color ==
NULL)
break;
2066 if (
AEQ0(
s.t))
continue;
2111 colorsegs_free(&segs);
2121static double forfunc (
double curlen,
double totallen,
double initwid)
2123 return (1 - curlen / totallen) * initwid / 2.0;
2126static double revfunc (
double curlen,
double totallen,
double initwid)
2128 return curlen / totallen * initwid / 2.0;
2131static double nonefunc (
double curlen,
double totallen,
double initwid)
2136 return initwid / 2.0;
2139static double bothfunc (
double curlen,
double totallen,
double initwid)
2141 double fr = curlen/totallen;
2142 if (fr <= 0.5)
return fr * initwid;
2143 return (1 - fr) * initwid;
2161 int cnum, numsemi = 0;
2162 char *
color, *pencolor, *fillcolor;
2163 char *headcolor, *tailcolor, *lastcolor;
2164 char *colors =
NULL;
2167 pointf pf0, pf1, pf2 = { 0, 0 }, pf3, *offlist, *tmplist;
2170 bool tapered =
false;
2182 while ((
p = *sp++)) {
2183 if (
streq(
p,
"tapered")) {
2199 if (numsemi && numc) {
2207 fillcolor = pencolor =
color;
2226 if (pencolor !=
color)
2228 if (fillcolor !=
color)
2243 if (fillcolor !=
color)
2258 numc2 = (2 + (double)numc) / 2.0;
2259 for (
size_t i = 0; i < offspl.
size; i++) {
2266 for (j = 0; j < bz.
size - 1; j += 3) {
2268 pf1 = bz.
list[j + 1];
2274 pf2 = bz.
list[j + 2];
2275 pf3 = bz.
list[j + 3];
2276 offlist[j + 1] = offlist[j + 2] =
2279 tmplist[j].x = pf0.
x - numc2 * offlist[j].x;
2280 tmplist[j].y = pf0.
y - numc2 * offlist[j].y;
2281 tmplist[j + 1].x = pf1.
x - numc2 * offlist[j + 1].x;
2282 tmplist[j + 1].y = pf1.
y - numc2 * offlist[j + 1].y;
2283 tmplist[j + 2].x = pf2.
x - numc2 * offlist[j + 2].x;
2284 tmplist[j + 2].y = pf2.
y - numc2 * offlist[j + 2].y;
2288 tmplist[j].x = pf3.x - numc2 * offlist[j].x;
2289 tmplist[j].y = pf3.y - numc2 * offlist[j].y;
2291 lastcolor = headcolor = tailcolor =
color;
2293 for (cnum = 0,
color = strtok(colors,
":");
color;
2294 cnum++,
color = strtok(0,
":")) {
2297 if (
color != lastcolor) {
2305 headcolor = tailcolor =
color;
2308 for (
size_t i = 0; i < tmpspl.
size; i++) {
2311 for (
size_t j = 0; j < tmpspl.
list[i].
size; j++) {
2312 tmplist[j].
x += offlist[j].x;
2313 tmplist[j].y += offlist[j].y;
2319 if (
color != tailcolor) {
2330 if (
color != headcolor) {
2341 for (
size_t i = 0; i < offspl.
size; i++) {
2360 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2380 free(previous_color_scheme);
2409 char *dflt_url =
NULL;
2410 char *dflt_target =
NULL;
2445 obj->
xlabel = tlab->text;
2459 if (((
s =
agget(e,
"href")) &&
s[0]) || ((
s =
agget(e,
"URL")) &&
s[0]))
2461 if (((
s =
agget(e,
"edgehref")) &&
s[0]) ||
2462 ((
s =
agget(e,
"edgeURL")) &&
s[0]))
2466 if (((
s =
agget(e,
"labelhref")) &&
s[0]) ||
2467 ((
s =
agget(e,
"labelURL")) &&
s[0]))
2471 if (((
s =
agget(e,
"tailhref")) &&
s[0]) ||
2472 ((
s =
agget(e,
"tailURL")) &&
s[0])) {
2475 }
else if (dflt_url)
2477 if (((
s =
agget(e,
"headhref")) &&
s[0]) ||
2478 ((
s =
agget(e,
"headURL")) &&
s[0])) {
2481 }
else if (dflt_url)
2486 if ((
s =
agget(e,
"target")) &&
s[0])
2488 if ((
s =
agget(e,
"edgetarget")) &&
s[0]) {
2491 }
else if (dflt_target)
2493 if ((
s =
agget(e,
"labeltarget")) &&
s[0])
2495 else if (dflt_target)
2497 if ((
s =
agget(e,
"tailtarget")) &&
s[0]) {
2500 }
else if (dflt_target)
2502 if ((
s =
agget(e,
"headtarget")) &&
s[0]) {
2505 }
else if (dflt_target)
2510 if (((
s =
agget(e,
"tooltip")) &&
s[0]) ||
2511 ((
s =
agget(e,
"edgetooltip")) &&
s[0])) {
2516 }
else if (obj->
label)
2519 if ((
s =
agget(e,
"labeltooltip")) &&
s[0]) {
2524 }
else if (obj->
label)
2527 if ((
s =
agget(e,
"tailtooltip")) &&
s[0]) {
2535 if ((
s =
agget(e,
"headtooltip")) &&
s[0]) {
2554 const size_t ns = spl->
size;
2556 pbs_size_t pbs_n = {0};
2557 for (
size_t i = 0; i < ns; i++)
2561 for (
size_t i = 0; i < pbs_size_size(&pbs_n); ++i) {
2562 nump += pbs_size_get(&pbs_n, i);
2564 gvrender_ptf_A(job, points_front(&pbs), points_front(&pbs), nump);
2569 obj->
url_map_n = *pbs_size_front(&pbs_n);
2582 char* url,
char* tooltip,
char* target,
char *
id,
splines* spl)
2590 if (lbl ==
NULL || !lbl->
set)
return;
2618 if (url ||
explicit) {
2641 bool explicit_itooltip) {
2646 if (explicit_iurl) url = iurl;
2647 else url = obj->
url;
2648 if (explicit_itooltip) {
2658 if (url ||
explicit) {
2734 char **styles =
NULL;
2762 while ((
p = *sp++)) {
2763 if (
streq(
p,
"invis"))
return;
2787 opbb.
LL.
x = opbb.
UR.
x = inpts->
x;
2788 opbb.
LL.
y = opbb.
UR.
y = inpts->
y;
2789 for (
size_t i = 1; i < numpts; i++) {
2791 if (inpts->
x < opbb.
LL.
x)
2792 opbb.
LL.
x = inpts->
x;
2793 else if (inpts->
x > opbb.
UR.
x)
2794 opbb.
UR.
x = inpts->
x;
2795 if (inpts->
y < opbb.
LL.
y)
2796 opbb.
LL.
y = inpts->
y;
2797 else if (inpts->
y > opbb.
UR.
y)
2798 opbb.
UR.
y = inpts->
y;
2812 switch (span->
just) {
2818 bb.
LL.
x = x - sz.
x / 2.0;
2819 bb.
UR.
x = x + sz.
x / 2.0;
2842 double fontsize = 0.0;
2843 char* fontname =
NULL;
2854 bb.
LL.
x = bb.
LL.
y = DBL_MAX;
2855 bb.
UR.
x = bb.
UR.
y = -DBL_MAX;
2859 for (
size_t i = 0; i <
xd->cnt; i++) {
2890 tf.
flags = fontflags;
2925 if ((
p =
agget(g,
"margin"))) {
2926 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2937 if ((
p =
agget(g,
"pad"))) {
2938 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2961 if ((
p =
agget(g,
"pagedir")) &&
p[0])
3044 job->
dpi.
x = job->
dpi.
y = DEFAULT_DPI;
3054 double X,
Y, Z, x, y;
3075 if (sz.
x <= 0.001) sz.
x = size.
x;
3076 if (sz.
y <= 0.001) sz.
y = size.
y;
3077 if (size.
x < sz.
x || size.
y < sz.
y
3079 && size.
x > sz.
x && size.
y > sz.
y))
3080 Z = fmin(size.
x / sz.
x, size.
y / sz.
y);
3084 x = (LL.
x + UR.
x) / 2.;
3085 y = (LL.
y + UR.
y) / 2.;
3093 if ((
str =
agget(g,
"viewport"))) {
3095 rv = sscanf(
str,
"%lf,%lf,%lf,\'%[^\']\'", &
X, &
Y, &Z, nodename);
3105 rv = sscanf(
str,
"%lf,%lf,%lf,%[^,]%c", &
X, &
Y, &Z, nodename, &junk);
3114 rv = sscanf(
str,
"%lf,%lf,%lf,%lf,%lf", &
X, &
Y, &Z, &x, &y);
3143 if (((
str =
agget(sg,
"pencolor")) != 0) &&
str[0])
3145 if (((
str =
agget(sg,
"bgcolor")) != 0) &&
str[0])
3147 if (((
str =
agget(sg,
"fillcolor")) != 0) &&
str[0])
3149 if (((
str =
agget(sg,
"fontcolor")) != 0) &&
str[0])
3163 if (((
str =
agget(g,
"fontcolor")) != 0) &&
str[0])
3170 if (((
str =
agget(n,
"pencolor")) != 0) &&
str[0])
3172 if (((
str =
agget(n,
"fillcolor")) != 0) &&
str[0]) {
3173 if (strchr(
str,
':')) {
3175 for (
str = strtok(colors,
":");
str;
3176 str = strtok(0,
":")) {
3186 if (((
str =
agget(n,
"fontcolor")) != 0) &&
str[0])
3190 if (strchr(
str,
':')) {
3192 for (
str = strtok(colors,
":");
str;
3193 str = strtok(0,
":")) {
3203 if (((
str =
agget(e,
"fontcolor")) != 0) &&
str[0])
3292#define NotFirstPage(j) (((j)->layerNum>1)||((j)->pagesArrayElem.x > 0)||((j)->pagesArrayElem.x > 0))
3368 free(previous_color_scheme);
3469 int doPerim, c, filled;
3471 char *
color, *fillcolor, *pencolor, **style, *
s;
3502 fillcolor = pencolor = 0;
3526 fillcolor = pencolor =
color;
3536 if ((filled == 0 || !fillcolor) && (
color =
agget(sg,
"bgcolor")) != 0 &&
color[0]) {
3544 char *clrs[2] = {0};
3569 AF[0] =
GD_bb(sg).LL;
3570 AF[2] =
GD_bb(sg).UR;
3584 AF[0] =
GD_bb(sg).LL;
3585 AF[2] =
GD_bb(sg).UR;
3604 else if (filled != 0) {
3637 free(previous_color_scheme);
3672 const char *start = p;
3689 size_t size = (size_t)(p - start);
3690 return (
token_t){.type = token, .start = start, .size = size};
3705 size_t parse_offsets[
sizeof(parse) /
sizeof(parse[0])];
3707 bool in_parens =
false;
3720 agerrorf(
"nesting not allowed in style: %s\n",
s);
3729 agerrorf(
"unmatched ')' in style: %s\n",
s);
3744 parse_offsets[fun++] =
agxblen(&ps_xb);
3752 agerrorf(
"unmatched '(' in style: %s\n",
s);
3760 for (
size_t i = 0; i < fun; ++i) {
3761 parse[i] = base + parse_offsets[i];
3773 assert(bz.
size > 0);
3774 assert(bz.
size % 3 == 1);
3776 for (
size_t i = 1; i < bz.
size;) {
3782 p.
x = ( p1.
x + p2.
x ) / 2;
3783 p.
y = ( p1.
y + p2.
y ) / 2;
3798 assert(spl->
size > 0);
3801 for (
size_t i = 0; i < spl->
size; i++) {
3871 static char* save_locale;
3878 setlocale (LC_NUMERIC,
"C");
3884 setlocale (LC_NUMERIC, save_locale);
3891#define FINISH() if (Verbose) fprintf(stderr,"gvRenderJobs %s: %.2f secs.\n", agnameof(g), elapsed_sec())
3895 static GVJ_t *prevjob;
3896 GVJ_t *job, *firstjob;
3902 agerrorf(
"Layout was not done. Missing layout plugins? \n");
4020 colorsegs_t segs = {0};
4026 if (rv || colorsegs_size(&segs) < 2 || colorsegs_front(&segs)->
color ==
NULL) {
4027 colorsegs_free(&segs);
4031 if (colorsegs_size(&segs) > 2)
4032 agwarningf(
"More than 2 colors specified for a gradient - ignoring remaining\n");
4035 if (colorsegs_get(&segs, 1).
color) {
4039 if (colorsegs_front(&segs)->hasFraction)
4040 *frac = colorsegs_front(&segs)->t;
4041 else if (colorsegs_get(&segs, 1).hasFraction)
4042 *frac = 1 - colorsegs_get(&segs, 1).t;
4046 colorsegs_free(&segs);
static agxbuf last
last message
static void agxbfree(agxbuf *xb)
free any malloced resources
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 WUR char * agxbuse(agxbuf *xb)
static size_t agxblen(const agxbuf *xb)
return number of characters currently stored
static int agxbputc(agxbuf *xb, char c)
add character to buffer
Memory allocation wrappers that exit on failure.
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)
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)
int stripedBox(GVJ_t *job, pointf *AF, const char *clrs, int rotate)
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 void map_bspline_poly(points_t *pbs_p, pbs_size_t *pbs_n, size_t n, pointf *p1, pointf *p2)
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 map_output_bspline(points_t *pbs, pbs_size_t *pbs_n, bezier *bp, double w2)
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 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)
bool findStopColor(const char *colorlist, char *clrs[2], double *frac)
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 const char adjust[]
static pointf * pEllipse(double a, double b, size_t np)
static void freeSeg(colorseg_t seg)
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 int multicolor(GVJ_t *job, edge_t *e, char **styles, const char *colors, double arrowsize, double penwidth)
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
static UNUSED void psmapOutput(const points_t *ps, size_t start, size_t n)
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 bool is_natural_number(const char *sstr)
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)
static char * default_pencolor(agxbuf *buf, const char *pencolor, const char *deflt)
void emit_once_reset(void)
void emit_map_rect(GVJ_t *job, boxf b)
static void emit_end_edge(GVJ_t *job)
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)
int wedgedEllipse(GVJ_t *job, pointf *pf, const char *clrs)
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)
static double getSegLen(strview_t *s)
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)
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)
double(* radfunc_t)(double, double, double)
static void init_job_pad(GVJ_t *job)
static double bisect(pointf pp, pointf cp, pointf np)
static int parseSegs(const char *clrs, colorsegs_t *psegs)
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 * G_gradientangle
bool Y_invert
invert y in dot & plain output
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)
textitem scanner parser str
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_WITH_DTOR(name, type, dtor)
#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
a non-owning string reference
state for an in-progress string tokenization
const char * start
Beginning of the token content.
size_t size
Number of bytes in the token content.
Non-owning string references.
static char * strview_str(strview_t source)
make a heap-allocated string from this string view
static strview_t tok_get(const tok_t *t)
get the current token
static tok_t tok(const char *input, const char *separators)
begin tokenization of a new string
static bool tok_end(const tok_t *t)
is this tokenizer exhausted?
static void tok_next(tok_t *t)
advance to the next token in the string being scanned
#define GUI_STATE_SELECTED
#define GUI_STATE_DELETED
#define GUI_STATE_VISITED
abstraction for squashing compiler warnings for unused symbols
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 *)