46#define strtok_r strtok_s
49#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)
70 if (!((p =
agget(g,
"_background")) && p[0])) {
71 if (!((p =
agget(g,
"_draw_")) && p[0])) {
88 fprintf(stderr,
"%" PRISIZE_T " ops %.2f sec\n", stats.
cnt, et);
160 char *
id,
void *gobj) {
163 bool assigned =
false;
175 if (tooltip && tooltip[0]) {
180 else if (obj->
label) {
215 id =
agget(obj,
"id");
216 if (
id && *
id !=
'\0') {
221 if (obj != root && gid) {
260 bool backslash_seen =
false;
262 while ((c = *
ins++)) {
263 if (backslash_seen) {
276 backslash_seen =
false;
280 backslash_seen =
true;
319 char* url =
agget(gobj,
"href");
320 char* tooltip =
agget(gobj,
"tooltip");
321 char* target =
agget(gobj,
"target");
325 if (lab) lbl = lab->
text;
328 url =
agget(gobj,
"URL");
332 initMapData (job, lbl, url, tooltip, target,
id, gobj);
365 char **pstyle =
NULL;
368 if ((style =
agget(sg,
"style")) != 0 && style[0]) {
374 if (strcmp(p,
"filled") == 0) {
377 }
else if (strcmp(p,
"radial") == 0) {
385 }
else if (strcmp(p,
"striped") == 0) {
392 }
else if (strcmp(p,
"rounded") == 0) {
426 char *p = memchr(
s->data,
';',
s->size);
433 s->size = (size_t)(p -
s->data);
439 v = strtod (p, &endp);
448#define AEQ0(x) (((x) < EPS) && ((x) > -EPS))
466static int parseSegs(
const char *clrs, colorsegs_t *psegs) {
467 colorsegs_t segs = {0};
469 static int doWarn = 1;
478 agwarningf(
"Total size > 1 in \"%s\" color spec ", clrs);
486 if (v > 0)
s.hasFraction =
true;
488 colorsegs_append(&segs,
s);
492 agerrorf(
"Illegal value in \"%s\" color attribute; float expected after ';'\n",
498 colorsegs_free(&segs);
511 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
512 if (colorsegs_get(&segs, i).t <= 0) nseg++;
516 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
522 colorsegs_back(&segs)->t +=
left;
527 while (!colorsegs_is_empty(&segs)) {
528 if (colorsegs_back(&segs)->t > 0)
break;
529 colorsegs_pop_back(&segs);
552 double angle0, angle1;
555 if (rv == 1 || rv == 2)
return rv;
562 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
564 if (
s.color ==
NULL)
break;
565 if (
s.t <= 0)
continue;
568 if (i + 1 == colorsegs_size(&segs))
571 angle1 = angle0 + 2 *
M_PI *
s.t;
580 colorsegs_free(&segs);
602 if (rv == 1 || rv == 2)
return rv;
615 xdelta = (pts[1].
x - pts[0].
x);
616 pts[1].
x = pts[2].
x = pts[0].
x;
620 for (
size_t i = 0; i < colorsegs_size(&segs); ++i) {
622 if (
s.color ==
NULL)
break;
623 if (
s.t <= 0)
continue;
625 if (i + 1 == colorsegs_size(&segs))
626 pts[1].
x = pts[2].
x = lastx;
628 pts[1].
x = pts[2].
x = pts[0].
x + xdelta * (
s.t);
630 pts[0].
x = pts[3].
x = pts[1].
x;
634 colorsegs_free(&segs);
705 char *style, *p, **pp;
711 if (strcmp(p,
"filled") == 0)
726 double deltheta = 2 *
M_PI / (double)np;
729 for (
size_t i = 0; i < np; i++) {
730 ps[i].x = a * cos(theta);
731 ps[i].y = b * sin(theta);
746 double dis1 =
ptToLine2 (cp[0], cp[3], cp[1]);
747 double dis2 =
ptToLine2 (cp[0], cp[3], cp[2]);
748 return dis1 <
HW *
HW && dis2 <
HW *
HW;
756 if (cp[0].x > bb->
UR.
x || cp[0].
x < bb->
LL.
x ||
757 cp[0].
y > bb->
UR.
y || cp[0].
y < bb->
LL.
y ||
758 cp[1].
x > bb->
UR.
x || cp[1].
x < bb->
LL.
x ||
759 cp[1].
y > bb->
UR.
y || cp[1].
y < bb->
LL.
y ||
760 cp[2].
x > bb->
UR.
x || cp[2].
x < bb->
LL.
x ||
761 cp[2].
y > bb->
UR.
y || cp[2].
y < bb->
LL.
y ||
762 cp[3].
x > bb->
UR.
x || cp[3].
x < bb->
LL.
x ||
763 cp[3].
y > bb->
UR.
y || cp[3].
y < bb->
LL.
y) {
769 for (i = 0; i < 4; i++) {
770 if (cp[i].x > bb->
UR.
x)
772 else if (cp[i].x < bb->LL.
x)
774 if (cp[i].y > bb->
UR.
y)
776 else if (cp[i].y < bb->LL.
y)
792 const pointf first = points_get(
ps, start);
793 fprintf(stdout,
"newpath %f %f moveto\n", first.
x, first.
y);
794 for (
size_t i = start + 1; i < start + n; ++i) {
795 const pointf pt = points_get(
ps, i);
796 fprintf(stdout,
"%f %f lineto\n", pt.
x, pt.
y);
798 fprintf (stdout,
"closepath stroke\n");
806#define MARK_FIRST_SEG(L) ((L)->next = (segitem_t*)1)
807#define FIRST_SEG(L) ((L)->next == (segitem_t*)1)
808#define INIT_SEG(P,L) {(L)->next = 0; (L)->p = P;}
825 pbs_size_append(pbs_n, 2 * n);
827 const UNUSED size_t nump = points_size(pbs_p);
828 for (
size_t i = 0; i < n; i++) {
829 points_append(pbs_p, p1[i]);
831 for (
size_t i = 0; i < n; i++) {
832 points_append(pbs_p, p2[n - i - 1]);
834#if defined(DEBUG) && DEBUG == 2
869 double ang, theta, phi;
870 theta = atan2(np.
y - cp.
y,np.
x - cp.
x);
871 phi = atan2(pp.
y - cp.
y,pp.
x - cp.
x);
873 if (ang > 0) ang -= 2*
M_PI;
875 return phi + ang / 2.0;
889 double theta, delx, dely;
902 np.
x = 2*cp.
x - pp.
x;
903 np.
y = 2*cp.
y - pp.
y;
908 pp.
x = 2*cp.
x - np.
x;
909 pp.
y = 2*cp.
y - np.
y;
912 delx = w2*cos(theta);
913 dely = w2*sin(theta);
935 pointf pts[4], pt1[50], pt2[50];
938 const size_t nc = (bp->
size - 1) / 3;
939 for (
size_t j = 0; j < nc; j++) {
940 for (
size_t k = 0; k < 4; k++) {
941 pts[k] = bp->
list[3*j + k];
950 segnext = segp->
next;
953 if (segnext ==
NULL ||
cnt == 50) {
973 const char *
str = sstr;
1000 char *buf_part_p =
NULL, *buf_p =
NULL, *cur, *part_in_p;
1005 part_in_p = spec_copy;
1015 if (n0 >= 0 || n1 >= 0) {
1019 rval =
BETWEEN(n0, layerNum, n1);
1021 }
else if (w0 !=
NULL) {
1023 rval = (n0 == layerNum);
1066 agwarningf(
"The layerselect attribute \"%s\" does not match any layer specifed by the layers attribute - ignored.\n",
p);
1092 agwarningf(
"The character \'%c\' appears in both the layersep and layerlistsep attributes - layerlistsep ignored.\n", *
tok);
1097 layer_names_t layerIDs = {0};
1100 layer_names_append(&layerIDs,
NULL);
1104 layer_names_append(&layerIDs,
tok);
1107 assert(layer_names_size(&layerIDs) - 1 <= INT_MAX);
1108 int ntok = (int)(layer_names_size(&layerIDs) - 1);
1111 if (layer_names_size(&layerIDs) > 1) {
1112 layer_names_append(&layerIDs,
NULL);
1115 layer_names_free(&layerIDs);
1125 char *
p =
agget(g,
"outputorder");
1127 if (!strcmp(
p,
"nodesfirst"))
1129 if (!strcmp(
p,
"edgesfirst"))
1146 if ((
str =
agget(g,
"layers")) != 0) {
1148 if ((
str =
agget(g,
"layerselect")) != 0 && *
str) {
1174 agwarningf(
"layers not supported in %s output\n",
1183 agwarningf(
"layers not supported in %s output\n",
1274 imageSize.
x = fmin(imageSize.
x, pageSize.
x);
1275 imageSize.
y = fmin(imageSize.
y, pageSize.
y);
1280 pageSize.
x = fmax(pageSize.
x, 0);
1282 pageSize.
y = fmax(pageSize.
y, 0);
1285 pageSize.
x = pageSize.
y = 0.;
1288 pageSize.
x = fmax(pageSize.
x, imageSize.
x);
1289 pageSize.
y = fmax(pageSize.
y, imageSize.
y);
1311 if (pageSize.
x > imageSize.
x)
1312 centering.
x = (pageSize.
x - imageSize.
x) / 2;
1313 if (pageSize.
y > imageSize.
y)
1314 centering.
y = (pageSize.
y - imageSize.
y) / 2;
1401 for (
size_t i = 0; i < numpts; i++) {
1402 pts[i].
x = inpts[i].
x;
1403 pts[i].
y = inpts[i].
y;
1412 char** styles =
NULL;
1416 for (
size_t i = 0; i <
xd->cnt; i++) {
1433 "polygon count exceeds gvrender_polygon support");
1472 char *
const clr0 =
p->stops[0].color;
1473 char *
const clr1 =
p->stops[1].color;
1474 const double frac =
p->stops[1].frac;
1475 if (
p->x1 ==
p->x0 &&
p->y1 ==
p->y0) {
1478 angle = (int)(180 * acos((
p->x0 -
p->x1) /
p->r0) /
M_PI);
1485 char *
const clr0 =
p->stops[0].color;
1486 char *
const clr1 =
p->stops[1].color;
1487 const double frac =
p->stops[1].frac;
1488 angle = (int)(180 * atan2(
p->y1 -
p->y0,
p->x1 -
p->x0) /
M_PI);
1495 agwarningf(
"gradient pen colors not yet supported.\n");
1509 agwarningf(
"Images unsupported in \"background\" attribute\n");
1546 char *clrs[2] = {0};
1583 pagesArrayElem =
exch_xy(pagesArrayElem);
1584 pagesArraySize =
exch_xy(pagesArraySize);
1731 bool is_rect =
false;
1747 const size_t sides =
poly->sides < 3 ? 1 :
poly->sides;
1748 const size_t peripheries =
poly->peripheries < 2 ? 1 :
poly->peripheries;
1750 vertices =
poly->vertices;
1753 if ((
s =
agget(n,
"samplepoints")))
1759 nump = (nump_int < 4 || nump_int > 60) ?
DFLT_SAMPLE : (size_t)nump_int;
1763 if (
poly->peripheries == 0 && !filled) {
1772 if (
poly->regular) {
1780 p[1].
x =
coord.
x + vertices[2*peripheries - 1].
x;
1781 p[1].
y =
coord.
y + vertices[2*peripheries - 1].
y;
1785 p =
pEllipse(vertices[2 * peripheries - 1].x,
1786 vertices[2 * peripheries - 1].y, nump);
1787 for (
size_t i = 0; i < nump; i++) {
1795 assert(peripheries >= 1);
1796 size_t offset = (peripheries - 1) *
poly->sides;
1801 if (
poly->sides >= nump) {
1804 for (
size_t i = 0, j = 0; j < nump; i +=
delta, j++) {
1805 p[j].
x =
coord.
x + vertices[i + offset].
x;
1806 p[j].
y =
coord.
y + vertices[i + offset].
y;
1811 for (
size_t i = 0; i < nump; i++) {
1812 p[i].
x =
coord.
x + vertices[i + offset].
x;
1813 p[i].
y =
coord.
y + vertices[i + offset].
y;
1857 char **styles =
NULL;
1877 while ((
p = *sp++)) {
1878 if (
streq(
p,
"invis"))
return;
1894 double x =
p.
x - q.
x, y =
p.
y - q.
y;
1897 d /= sqrt(x * x + y * y +
EPSILON);
1909 double x = q.
x - r.
x, y = q.
y - r.
y;
1915 x =
p.
x -
s.x, y =
p.
y -
s.y;
1939 AF[1] = (
pointf){AF[0].
x - sz.
x, AF[0].
y};
1954 const char *deflt) {
1956 for (
const char *
p = pencolor; *
p;
p++) {
1965 double d =
DIST(pts[0],pts[1]);
1966 d +=
DIST(pts[1],pts[2]);
1967 d +=
DIST(pts[2],pts[3]);
1980 const size_t cnt = (bz->
size - 1) / 3;
1996 for (
size_t i = 0; i <
cnt; i++) {
2004 for (i = 0; i <
cnt; i++) {
2010 left->size = 3*(i+1) + 1;
2015 for (j = 0; j <
left->size; j++)
2018 for (j = 0; j <
right->size; j++)
2034 double arrowsize,
double penwidth) {
2039 char* endcolor =
NULL;
2055 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2059 for (
size_t j = 0; j < colorsegs_size(&segs); ++j) {
2061 if (
s.color ==
NULL)
break;
2062 if (
AEQ0(
s.t))
continue;
2107 colorsegs_free(&segs);
2117static double forfunc (
double curlen,
double totallen,
double initwid)
2119 return (1 - curlen / totallen) * initwid / 2.0;
2122static double revfunc (
double curlen,
double totallen,
double initwid)
2124 return curlen / totallen * initwid / 2.0;
2127static double nonefunc (
double curlen,
double totallen,
double initwid)
2132 return initwid / 2.0;
2135static double bothfunc (
double curlen,
double totallen,
double initwid)
2137 double fr = curlen/totallen;
2138 if (fr <= 0.5)
return fr * initwid;
2139 return (1 - fr) * initwid;
2157 int cnum, numsemi = 0;
2158 char *
color, *pencolor, *fillcolor;
2159 char *headcolor, *tailcolor, *lastcolor;
2160 char *colors =
NULL;
2163 pointf pf0, pf1, pf2 = { 0, 0 }, pf3, *offlist, *tmplist;
2166 bool tapered =
false;
2178 while ((
p = *sp++)) {
2179 if (
streq(
p,
"tapered")) {
2195 if (numsemi && numc) {
2203 fillcolor = pencolor =
color;
2222 if (pencolor !=
color)
2224 if (fillcolor !=
color)
2239 if (fillcolor !=
color)
2254 numc2 = (2 + (double)numc) / 2.0;
2255 for (
size_t i = 0; i < offspl.
size; i++) {
2262 for (j = 0; j < bz.
size - 1; j += 3) {
2264 pf1 = bz.
list[j + 1];
2270 pf2 = bz.
list[j + 2];
2271 pf3 = bz.
list[j + 3];
2272 offlist[j + 1] = offlist[j + 2] =
2275 tmplist[j].x = pf0.
x - numc2 * offlist[j].x;
2276 tmplist[j].y = pf0.
y - numc2 * offlist[j].y;
2277 tmplist[j + 1].x = pf1.
x - numc2 * offlist[j + 1].x;
2278 tmplist[j + 1].y = pf1.
y - numc2 * offlist[j + 1].y;
2279 tmplist[j + 2].x = pf2.
x - numc2 * offlist[j + 2].x;
2280 tmplist[j + 2].y = pf2.
y - numc2 * offlist[j + 2].y;
2284 tmplist[j].x = pf3.x - numc2 * offlist[j].x;
2285 tmplist[j].y = pf3.y - numc2 * offlist[j].y;
2287 lastcolor = headcolor = tailcolor =
color;
2289 for (cnum = 0,
color = strtok(colors,
":");
color;
2290 cnum++,
color = strtok(0,
":")) {
2293 if (
color != lastcolor) {
2301 headcolor = tailcolor =
color;
2304 for (
size_t i = 0; i < tmpspl.
size; i++) {
2307 for (
size_t j = 0; j < tmpspl.
list[i].
size; j++) {
2308 tmplist[j].
x += offlist[j].x;
2309 tmplist[j].y += offlist[j].y;
2315 if (
color != tailcolor) {
2326 if (
color != headcolor) {
2337 for (
size_t i = 0; i < offspl.
size; i++) {
2356 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2376 free(previous_color_scheme);
2405 char *dflt_url =
NULL;
2406 char *dflt_target =
NULL;
2441 obj->
xlabel = tlab->text;
2455 if (((
s =
agget(e,
"href")) &&
s[0]) || ((
s =
agget(e,
"URL")) &&
s[0]))
2457 if (((
s =
agget(e,
"edgehref")) &&
s[0]) ||
2458 ((
s =
agget(e,
"edgeURL")) &&
s[0]))
2462 if (((
s =
agget(e,
"labelhref")) &&
s[0]) ||
2463 ((
s =
agget(e,
"labelURL")) &&
s[0]))
2467 if (((
s =
agget(e,
"tailhref")) &&
s[0]) ||
2468 ((
s =
agget(e,
"tailURL")) &&
s[0])) {
2471 }
else if (dflt_url)
2473 if (((
s =
agget(e,
"headhref")) &&
s[0]) ||
2474 ((
s =
agget(e,
"headURL")) &&
s[0])) {
2477 }
else if (dflt_url)
2482 if ((
s =
agget(e,
"target")) &&
s[0])
2484 if ((
s =
agget(e,
"edgetarget")) &&
s[0]) {
2487 }
else if (dflt_target)
2489 if ((
s =
agget(e,
"labeltarget")) &&
s[0])
2491 else if (dflt_target)
2493 if ((
s =
agget(e,
"tailtarget")) &&
s[0]) {
2496 }
else if (dflt_target)
2498 if ((
s =
agget(e,
"headtarget")) &&
s[0]) {
2501 }
else if (dflt_target)
2506 if (((
s =
agget(e,
"tooltip")) &&
s[0]) ||
2507 ((
s =
agget(e,
"edgetooltip")) &&
s[0])) {
2512 }
else if (obj->
label)
2515 if ((
s =
agget(e,
"labeltooltip")) &&
s[0]) {
2520 }
else if (obj->
label)
2523 if ((
s =
agget(e,
"tailtooltip")) &&
s[0]) {
2531 if ((
s =
agget(e,
"headtooltip")) &&
s[0]) {
2550 const size_t ns = spl->
size;
2552 pbs_size_t pbs_n = {0};
2553 for (
size_t i = 0; i < ns; i++)
2557 for (
size_t i = 0; i < pbs_size_size(&pbs_n); ++i) {
2558 nump += pbs_size_get(&pbs_n, i);
2560 gvrender_ptf_A(job, points_front(&pbs), points_front(&pbs), nump);
2565 obj->
url_map_n = *pbs_size_front(&pbs_n);
2578 char* url,
char* tooltip,
char* target,
char *
id,
splines* spl)
2586 if (lbl ==
NULL || !lbl->
set)
return;
2614 if (url ||
explicit) {
2637 bool explicit_itooltip) {
2642 if (explicit_iurl) url = iurl;
2643 else url = obj->
url;
2644 if (explicit_itooltip) {
2654 if (url ||
explicit) {
2730 char **styles =
NULL;
2758 while ((
p = *sp++)) {
2759 if (
streq(
p,
"invis"))
return;
2783 opbb.
LL.
x = opbb.
UR.
x = inpts->
x;
2784 opbb.
LL.
y = opbb.
UR.
y = inpts->
y;
2785 for (
size_t i = 1; i < numpts; i++) {
2787 if (inpts->
x < opbb.
LL.
x)
2788 opbb.
LL.
x = inpts->
x;
2789 else if (inpts->
x > opbb.
UR.
x)
2790 opbb.
UR.
x = inpts->
x;
2791 if (inpts->
y < opbb.
LL.
y)
2792 opbb.
LL.
y = inpts->
y;
2793 else if (inpts->
y > opbb.
UR.
y)
2794 opbb.
UR.
y = inpts->
y;
2808 switch (span->
just) {
2814 bb.
LL.
x = x - sz.
x / 2.0;
2815 bb.
UR.
x = x + sz.
x / 2.0;
2837 double fontsize = 0.0;
2838 char* fontname =
NULL;
2844 unsigned fontflags = 0;
2849 bb.
LL.
x = bb.
LL.
y = DBL_MAX;
2850 bb.
UR.
x = bb.
UR.
y = -DBL_MAX;
2854 for (
size_t i = 0; i <
xd->cnt; i++) {
2885 tf.
flags = fontflags;
2920 if ((
p =
agget(g,
"margin"))) {
2921 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2932 if ((
p =
agget(g,
"pad"))) {
2933 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2956 if ((
p =
agget(g,
"pagedir")) &&
p[0])
3039 job->
dpi.
x = job->
dpi.
y = DEFAULT_DPI;
3067 if (sz.
x <= 0.001) sz.
x = size.
x;
3068 if (sz.
y <= 0.001) sz.
y = size.
y;
3069 if (size.
x < sz.
x || size.
y < sz.
y
3071 && size.
x > sz.
x && size.
y > sz.
y))
3072 Z = fmin(size.
x / sz.
x, size.
y / sz.
y);
3083 if ((
str =
agget(g,
"viewport"))) {
3085 rv = sscanf(
str,
"%lf,%lf,%lf,\'%[^\']\'", &XY.
x, &XY.
y, &Z, nodename);
3093 rv = sscanf(
str,
"%lf,%lf,%lf,%[^,]%c", &XY.
x, &XY.
y, &Z, nodename,
3102 sscanf(
str,
"%lf,%lf,%lf,%lf,%lf", &XY.
x, &XY.
y, &Z, &xy.
x, &xy.
y);
3129 if (((
str =
agget(sg,
"pencolor")) != 0) &&
str[0])
3131 if (((
str =
agget(sg,
"bgcolor")) != 0) &&
str[0])
3133 if (((
str =
agget(sg,
"fillcolor")) != 0) &&
str[0])
3135 if (((
str =
agget(sg,
"fontcolor")) != 0) &&
str[0])
3149 if (((
str =
agget(g,
"fontcolor")) != 0) &&
str[0])
3156 if (((
str =
agget(n,
"pencolor")) != 0) &&
str[0])
3158 if (((
str =
agget(n,
"fillcolor")) != 0) &&
str[0]) {
3159 if (strchr(
str,
':')) {
3161 for (
str = strtok(colors,
":");
str;
3162 str = strtok(0,
":")) {
3172 if (((
str =
agget(n,
"fontcolor")) != 0) &&
str[0])
3176 if (strchr(
str,
':')) {
3178 for (
str = strtok(colors,
":");
str;
3179 str = strtok(0,
":")) {
3189 if (((
str =
agget(e,
"fontcolor")) != 0) &&
str[0])
3278#define NotFirstPage(j) (((j)->layerNum>1)||((j)->pagesArrayElem.x > 0)||((j)->pagesArrayElem.x > 0))
3293 bool obj_id_needs_restore =
false;
3299 obj_id_needs_restore =
true;
3349 if (obj_id_needs_restore) {
3356 free(previous_color_scheme);
3457 int doPerim, c, filled;
3459 char *
color, *fillcolor, *pencolor, **style, *
s;
3490 fillcolor = pencolor = 0;
3514 fillcolor = pencolor =
color;
3524 if ((filled == 0 || !fillcolor) && (
color =
agget(sg,
"bgcolor")) != 0 &&
color[0]) {
3532 char *clrs[2] = {0};
3557 AF[0] =
GD_bb(sg).LL;
3558 AF[2] =
GD_bb(sg).UR;
3571 AF[0] =
GD_bb(sg).LL;
3572 AF[2] =
GD_bb(sg).UR;
3590 else if (filled != 0) {
3623 free(previous_color_scheme);
3658 const char *start = p;
3675 size_t size = (size_t)(p - start);
3676 return (
token_t){.type = token, .start = start, .size = size};
3691 size_t parse_offsets[
sizeof(parse) /
sizeof(parse[0])];
3693 bool in_parens =
false;
3706 agerrorf(
"nesting not allowed in style: %s\n",
s);
3715 agerrorf(
"unmatched ')' in style: %s\n",
s);
3730 parse_offsets[fun++] =
agxblen(&ps_xb);
3738 agerrorf(
"unmatched '(' in style: %s\n",
s);
3746 for (
size_t i = 0; i < fun; ++i) {
3747 parse[i] = base + parse_offsets[i];
3759 assert(bz.
size > 0);
3760 assert(bz.
size % 3 == 1);
3762 for (
size_t i = 1; i < bz.
size;) {
3768 p.
x = ( p1.
x + p2.
x ) / 2;
3769 p.
y = ( p1.
y + p2.
y ) / 2;
3784 assert(spl->
size > 0);
3787 for (
size_t i = 0; i < spl->
size; i++) {
3857 static char* save_locale;
3864 setlocale (LC_NUMERIC,
"C");
3870 setlocale (LC_NUMERIC, save_locale);
3877#define FINISH() if (Verbose) fprintf(stderr,"gvRenderJobs %s: %.2f secs.\n", agnameof(g), elapsed_sec())
3881 static GVJ_t *prevjob;
3882 GVJ_t *job, *firstjob;
3888 agerrorf(
"Layout was not done. Missing layout plugins? \n");
3981#pragma GCC diagnostic push
3982#pragma GCC diagnostic ignored "-Wcast-qual"
3986#pragma GCC diagnostic pop
4013 colorsegs_t segs = {0};
4019 if (rv || colorsegs_size(&segs) < 2 || colorsegs_front(&segs)->
color ==
NULL) {
4020 colorsegs_free(&segs);
4024 if (colorsegs_size(&segs) > 2)
4025 agwarningf(
"More than 2 colors specified for a gradient - ignoring remaining\n");
4028 if (colorsegs_get(&segs, 1).
color) {
4032 if (colorsegs_front(&segs)->hasFraction)
4033 *frac = colorsegs_front(&segs)->t;
4034 else if (colorsegs_get(&segs, 1).hasFraction)
4035 *frac = 1 - colorsegs_get(&segs, 1).t;
4039 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 void freePara(xdot_op *xop)
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)
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 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)
bool initMapData(GVJ_t *job, char *lbl, char *url, char *tooltip, char *target, char *id, void *gobj)
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 void expandbp(boxf *b, pointf p)
expand box b as needed to enclose point p
static pointf add_pointf(pointf p, pointf q)
static pointf sub_pointf(pointf p, pointf q)
static point exch_xy(point p)
static pointf scale(double c, pointf 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_text(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up text 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?
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