48#define strtok_r strtok_s
51#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)
72 if (!((p =
agget(g,
"_background")) && p[0])) {
73 if (!((p =
agget(g,
"_draw_")) && p[0])) {
90 fprintf(stderr,
"%" PRISIZE_T " ops %.2f sec\n", stats.
cnt, et);
162 char *
id,
void *gobj) {
165 bool assigned =
false;
177 if (tooltip && tooltip[0]) {
182 else if (obj->
label) {
217 id =
agget(obj,
"id");
218 if (
id && *
id !=
'\0') {
223 if (obj != root && gid) {
262 bool backslash_seen =
false;
264 while ((c = *
ins++)) {
265 if (backslash_seen) {
278 backslash_seen =
false;
282 backslash_seen =
true;
321 char* url =
agget(gobj,
"href");
322 char* tooltip =
agget(gobj,
"tooltip");
323 char* target =
agget(gobj,
"target");
327 if (lab) lbl = lab->
text;
330 url =
agget(gobj,
"URL");
334 initMapData (job, lbl, url, tooltip, target,
id, gobj);
367 char **pstyle =
NULL;
370 if ((style =
agget(sg,
"style")) != 0 && style[0]) {
376 if (strcmp(p,
"filled") == 0) {
379 }
else if (strcmp(p,
"radial") == 0) {
387 }
else if (strcmp(p,
"striped") == 0) {
394 }
else if (strcmp(p,
"rounded") == 0) {
428 char *p = memchr(
s->data,
';',
s->size);
435 s->size = (size_t)(p -
s->data);
441 v = strtod (p, &endp);
450#define AEQ0(x) (((x) < EPS) && ((x) > -EPS))
468static int parseSegs(
const char *clrs, colorsegs_t *psegs) {
469 colorsegs_t segs = {.dtor =
freeSeg};
471 static atomic_flag warned;
476 if ((v = getSegLen(&
color)) >= 0) {
479 if (!
AEQ0(
del) && !atomic_flag_test_and_set(&warned)) {
480 agwarningf(
"Total size > 1 in \"%s\" color spec ", clrs);
487 if (v > 0)
s.hasFraction =
true;
492 if (!atomic_flag_test_and_set(&warned)) {
493 agerrorf(
"Illegal value in \"%s\" color attribute; float expected after ';'\n",
511 for (
size_t i = 0; i <
LIST_SIZE(&segs); ++i) {
512 if (
LIST_GET(&segs, i).t <= 0) nseg++;
516 for (
size_t i = 0; i <
LIST_SIZE(&segs); ++i) {
553 double angle0, angle1;
556 if (rv == 1 || rv == 2)
return rv;
563 for (
size_t i = 0; i <
LIST_SIZE(&segs); ++i) {
565 if (
s.color ==
NULL)
break;
566 if (
s.t <= 0)
continue;
572 angle1 = angle0 + 2 *
M_PI *
s.t;
603 if (rv == 1 || rv == 2)
return rv;
616 xdelta = (pts[1].
x - pts[0].
x);
617 pts[1].
x = pts[2].
x = pts[0].
x;
621 for (
size_t i = 0; i <
LIST_SIZE(&segs); ++i) {
623 if (
s.color ==
NULL)
break;
624 if (
s.t <= 0)
continue;
627 pts[1].
x = pts[2].
x = lastx;
629 pts[1].
x = pts[2].
x = pts[0].
x + xdelta * (
s.t);
631 pts[0].
x = pts[3].
x = pts[1].
x;
706 char *style, *p, **pp;
712 if (strcmp(p,
"filled") == 0)
727 double deltheta = 2 *
M_PI / (double)np;
730 for (
size_t i = 0; i < np; i++) {
731 ps[i].x = a * cos(theta);
732 ps[i].y = b * sin(theta);
747 double dis1 =
ptToLine2 (cp[0], cp[3], cp[1]);
748 double dis2 =
ptToLine2 (cp[0], cp[3], cp[2]);
749 return dis1 <
HW *
HW && dis2 <
HW *
HW;
757 if (cp[0].x > bb->
UR.
x || cp[0].
x < bb->
LL.
x ||
758 cp[0].
y > bb->
UR.
y || cp[0].
y < bb->
LL.
y ||
759 cp[1].
x > bb->
UR.
x || cp[1].
x < bb->
LL.
x ||
760 cp[1].
y > bb->
UR.
y || cp[1].
y < bb->
LL.
y ||
761 cp[2].
x > bb->
UR.
x || cp[2].
x < bb->
LL.
x ||
762 cp[2].
y > bb->
UR.
y || cp[2].
y < bb->
LL.
y ||
763 cp[3].
x > bb->
UR.
x || cp[3].
x < bb->
LL.
x ||
764 cp[3].
y > bb->
UR.
y || cp[3].
y < bb->
LL.
y) {
770 for (i = 0; i < 4; i++) {
771 if (cp[i].x > bb->
UR.
x)
773 else if (cp[i].x < bb->LL.
x)
775 if (cp[i].y > bb->
UR.
y)
777 else if (cp[i].y < bb->LL.
y)
792static UNUSED void psmapOutput(
const points_t *
ps,
size_t start,
size_t n) {
794 fprintf(stdout,
"newpath %f %f moveto\n", first.
x, first.
y);
795 for (
size_t i = start + 1; i < start + n; ++i) {
797 fprintf(stdout,
"%f %f lineto\n", pt.
x, pt.
y);
799 fprintf (stdout,
"closepath stroke\n");
807#define MARK_FIRST_SEG(L) ((L)->next = (segitem_t*)1)
808#define FIRST_SEG(L) ((L)->next == (segitem_t*)1)
809#define INIT_SEG(P,L) {(L)->next = 0; (L)->p = P;}
819typedef LIST(
size_t) pbs_size_t;
824static void map_bspline_poly(points_t *pbs_p, pbs_size_t *pbs_n,
size_t n,
829 for (
size_t i = 0; i < n; i++) {
832 for (
size_t i = 0; i < n; i++) {
835#if defined(DEBUG) && DEBUG == 2
836 psmapOutput(pbs_p, nump, 2 * n);
870 double ang, theta, phi;
871 theta = atan2(np.
y - cp.
y,np.
x - cp.
x);
872 phi = atan2(pp.
y - cp.
y,pp.
x - cp.
x);
874 if (ang > 0) ang -= 2*
M_PI;
876 return phi + ang / 2.0;
890 double theta, delx, dely;
903 np.
x = 2*cp.
x - pp.
x;
904 np.
y = 2*cp.
y - pp.
y;
909 pp.
x = 2*cp.
x - np.
x;
910 pp.
y = 2*cp.
y - np.
y;
913 delx = w2*cos(theta);
914 dely = w2*sin(theta);
936 pointf pts[4], pt1[50], pt2[50];
939 const size_t nc = (bp->
size - 1) / 3;
940 for (
size_t j = 0; j < nc; j++) {
941 for (
size_t k = 0; k < 4; k++) {
942 pts[k] = bp->
list[3*j + k];
951 segnext = segp->
next;
954 if (segnext ==
NULL ||
cnt == 50) {
955 map_bspline_poly(pbs, pbs_n,
cnt, pt1, pt2);
974 const char *
str = sstr;
1001 char *buf_part_p =
NULL, *buf_p =
NULL, *cur, *part_in_p;
1006 part_in_p = spec_copy;
1016 if (n0 >= 0 || n1 >= 0) {
1020 rval =
BETWEEN(n0, layerNum, n1);
1022 }
else if (w0 !=
NULL) {
1024 rval = (n0 == layerNum);
1067 agwarningf(
"The layerselect attribute \"%s\" does not match any layer specifed by the layers attribute - ignored.\n",
p);
1091 agwarningf(
"The character \'%c\' appears in both the layersep and layerlistsep attributes - layerlistsep ignored.\n", *
tok);
1096 LIST(
char *) layerIDs = {0};
1106 assert(
LIST_SIZE(&layerIDs) - 1 <= INT_MAX);
1107 int ntok = (int)(
LIST_SIZE(&layerIDs) - 1);
1124 char *
p =
agget(g,
"outputorder");
1126 if (!strcmp(
p,
"nodesfirst"))
1128 if (!strcmp(
p,
"edgesfirst"))
1145 if ((
str =
agget(g,
"layers")) != 0) {
1147 if ((
str =
agget(g,
"layerselect")) != 0 && *
str) {
1173 agwarningf(
"layers not supported in %s output\n",
1182 agwarningf(
"layers not supported in %s output\n",
1273 imageSize.
x = fmin(imageSize.
x, pageSize.
x);
1274 imageSize.
y = fmin(imageSize.
y, pageSize.
y);
1279 pageSize.
x = fmax(pageSize.
x, 0);
1281 pageSize.
y = fmax(pageSize.
y, 0);
1284 pageSize.
x = pageSize.
y = 0.;
1287 pageSize.
x = fmax(pageSize.
x, imageSize.
x);
1288 pageSize.
y = fmax(pageSize.
y, imageSize.
y);
1310 if (pageSize.
x > imageSize.
x)
1311 centering.
x = (pageSize.
x - imageSize.
x) / 2;
1312 if (pageSize.
y > imageSize.
y)
1313 centering.
y = (pageSize.
y - imageSize.
y) / 2;
1400 for (
size_t i = 0; i < numpts; i++) {
1401 pts[i].
x = inpts[i].
x;
1402 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");
1471 char *
const clr0 =
p->stops[0].color;
1472 char *
const clr1 =
p->stops[1].color;
1473 const double frac =
p->stops[1].frac;
1474 if (
p->x1 ==
p->x0 &&
p->y1 ==
p->y0) {
1477 angle = (int)(180 * acos((
p->x0 -
p->x1) /
p->r0) /
M_PI);
1484 char *
const clr0 =
p->stops[0].color;
1485 char *
const clr1 =
p->stops[1].color;
1486 const double frac =
p->stops[1].frac;
1487 angle = (int)(180 * atan2(
p->y1 -
p->y0,
p->x1 -
p->x0) /
M_PI);
1494 agwarningf(
"gradient pen colors not yet supported.\n");
1508 agwarningf(
"Images unsupported in \"background\" attribute\n");
1545 char *clrs[2] = {0};
1582 pagesArrayElem =
exch_xy(pagesArrayElem);
1583 pagesArraySize =
exch_xy(pagesArraySize);
1730 bool is_rect =
false;
1746 const size_t sides =
poly->sides < 3 ? 1 :
poly->sides;
1747 const size_t peripheries =
poly->peripheries < 2 ? 1 :
poly->peripheries;
1749 vertices =
poly->vertices;
1752 if ((
s =
agget(n,
"samplepoints")))
1758 nump = (nump_int < 4 || nump_int > 60) ?
DFLT_SAMPLE : (size_t)nump_int;
1762 if (
poly->peripheries == 0 && !filled) {
1771 if (
poly->regular) {
1779 p[1].
x =
coord.
x + vertices[2*peripheries - 1].
x;
1780 p[1].
y =
coord.
y + vertices[2*peripheries - 1].
y;
1784 p =
pEllipse(vertices[2 * peripheries - 1].x,
1785 vertices[2 * peripheries - 1].y, nump);
1786 for (
size_t i = 0; i < nump; i++) {
1794 assert(peripheries >= 1);
1795 size_t offset = (peripheries - 1) *
poly->sides;
1800 if (
poly->sides >= nump) {
1803 for (
size_t i = 0, j = 0; j < nump; i +=
delta, j++) {
1804 p[j].
x =
coord.
x + vertices[i + offset].
x;
1805 p[j].
y =
coord.
y + vertices[i + offset].
y;
1810 for (
size_t i = 0; i < nump; i++) {
1811 p[i].
x =
coord.
x + vertices[i + offset].
x;
1812 p[i].
y =
coord.
y + vertices[i + offset].
y;
1856 char **styles =
NULL;
1876 while ((
p = *sp++)) {
1877 if (
streq(
p,
"invis"))
return;
1893 double x =
p.
x - q.
x, y =
p.
y - q.
y;
1896 d /= sqrt(x * x + y * y +
EPSILON);
1908 double x = q.
x - r.
x, y = q.
y - r.
y;
1914 x =
p.
x -
s.x, y =
p.
y -
s.y;
1938 AF[1] = (
pointf){AF[0].
x - sz.
x, AF[0].
y};
1953 const char *deflt) {
1955 for (
const char *
p = pencolor; *
p;
p++) {
1964 double d =
DIST(pts[0],pts[1]);
1965 d +=
DIST(pts[1],pts[2]);
1966 d +=
DIST(pts[2],pts[3]);
1979 const size_t cnt = (bz->
size - 1) / 3;
1995 for (
size_t i = 0; i <
cnt; i++) {
2003 for (i = 0; i <
cnt; i++) {
2009 left->size = 3*(i+1) + 1;
2014 for (j = 0; j <
left->size; j++)
2017 for (j = 0; j <
right->size; j++)
2033 double arrowsize,
double penwidth) {
2038 char* endcolor =
NULL;
2054 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2058 for (
size_t j = 0; j <
LIST_SIZE(&segs); ++j) {
2060 if (
s.color ==
NULL)
break;
2061 if (
AEQ0(
s.t))
continue;
2116static double forfunc (
double curlen,
double totallen,
double initwid)
2118 return (1 - curlen / totallen) * initwid / 2.0;
2121static double revfunc (
double curlen,
double totallen,
double initwid)
2123 return curlen / totallen * initwid / 2.0;
2126static double nonefunc (
double curlen,
double totallen,
double initwid)
2131 return initwid / 2.0;
2134static double bothfunc (
double curlen,
double totallen,
double initwid)
2136 double fr = curlen/totallen;
2137 if (fr <= 0.5)
return fr * initwid;
2138 return (1 - fr) * initwid;
2156 int cnum, numsemi = 0;
2157 char *
color, *pencolor, *fillcolor;
2158 char *headcolor, *tailcolor, *lastcolor;
2159 char *colors =
NULL;
2162 pointf pf0, pf1, pf2 = { 0, 0 }, pf3, *offlist, *tmplist;
2165 bool tapered =
false;
2177 while ((
p = *sp++)) {
2178 if (
streq(
p,
"tapered")) {
2194 if (numsemi && numc) {
2202 fillcolor = pencolor =
color;
2221 if (pencolor !=
color)
2223 if (fillcolor !=
color)
2238 if (fillcolor !=
color)
2253 numc2 = (2 + (double)numc) / 2.0;
2254 for (
size_t i = 0; i < offspl.
size; i++) {
2261 for (j = 0; j < bz.
size - 1; j += 3) {
2263 pf1 = bz.
list[j + 1];
2269 pf2 = bz.
list[j + 2];
2270 pf3 = bz.
list[j + 3];
2271 offlist[j + 1] = offlist[j + 2] =
2274 tmplist[j].x = pf0.
x - numc2 * offlist[j].x;
2275 tmplist[j].y = pf0.
y - numc2 * offlist[j].y;
2276 tmplist[j + 1].x = pf1.
x - numc2 * offlist[j + 1].x;
2277 tmplist[j + 1].y = pf1.
y - numc2 * offlist[j + 1].y;
2278 tmplist[j + 2].x = pf2.
x - numc2 * offlist[j + 2].x;
2279 tmplist[j + 2].y = pf2.
y - numc2 * offlist[j + 2].y;
2283 tmplist[j].x = pf3.x - numc2 * offlist[j].x;
2284 tmplist[j].y = pf3.y - numc2 * offlist[j].y;
2286 lastcolor = headcolor = tailcolor =
color;
2288 for (cnum = 0,
color = strtok(colors,
":");
color;
2289 cnum++,
color = strtok(0,
":")) {
2292 if (
color != lastcolor) {
2300 headcolor = tailcolor =
color;
2303 for (
size_t i = 0; i < tmpspl.
size; i++) {
2306 for (
size_t j = 0; j < tmpspl.
list[i].
size; j++) {
2307 tmplist[j].
x += offlist[j].x;
2308 tmplist[j].y += offlist[j].y;
2314 if (
color != tailcolor) {
2325 if (
color != headcolor) {
2336 for (
size_t i = 0; i < offspl.
size; i++) {
2355 for (
size_t i = 0; i <
ED_spl(e)->size; i++) {
2375 free(previous_color_scheme);
2404 char *dflt_url =
NULL;
2405 char *dflt_target =
NULL;
2440 obj->
xlabel = tlab->text;
2454 if (((
s =
agget(e,
"href")) &&
s[0]) || ((
s =
agget(e,
"URL")) &&
s[0]))
2456 if (((
s =
agget(e,
"edgehref")) &&
s[0]) ||
2457 ((
s =
agget(e,
"edgeURL")) &&
s[0]))
2461 if (((
s =
agget(e,
"labelhref")) &&
s[0]) ||
2462 ((
s =
agget(e,
"labelURL")) &&
s[0]))
2466 if (((
s =
agget(e,
"tailhref")) &&
s[0]) ||
2467 ((
s =
agget(e,
"tailURL")) &&
s[0])) {
2470 }
else if (dflt_url)
2472 if (((
s =
agget(e,
"headhref")) &&
s[0]) ||
2473 ((
s =
agget(e,
"headURL")) &&
s[0])) {
2476 }
else if (dflt_url)
2481 if ((
s =
agget(e,
"target")) &&
s[0])
2483 if ((
s =
agget(e,
"edgetarget")) &&
s[0]) {
2486 }
else if (dflt_target)
2488 if ((
s =
agget(e,
"labeltarget")) &&
s[0])
2490 else if (dflt_target)
2492 if ((
s =
agget(e,
"tailtarget")) &&
s[0]) {
2495 }
else if (dflt_target)
2497 if ((
s =
agget(e,
"headtarget")) &&
s[0]) {
2500 }
else if (dflt_target)
2505 if (((
s =
agget(e,
"tooltip")) &&
s[0]) ||
2506 ((
s =
agget(e,
"edgetooltip")) &&
s[0])) {
2511 }
else if (obj->
label)
2514 if ((
s =
agget(e,
"labeltooltip")) &&
s[0]) {
2519 }
else if (obj->
label)
2522 if ((
s =
agget(e,
"tailtooltip")) &&
s[0]) {
2530 if ((
s =
agget(e,
"headtooltip")) &&
s[0]) {
2549 const size_t ns = spl->
size;
2551 pbs_size_t pbs_n = {0};
2552 for (
size_t i = 0; i < ns; i++)
2556 for (
size_t i = 0; i <
LIST_SIZE(&pbs_n); ++i) {
2576 char* url,
char* tooltip,
char* target,
char *
id,
splines* spl)
2584 if (lbl ==
NULL || !lbl->
set)
return;
2612 if (url ||
explicit) {
2635 bool explicit_itooltip) {
2640 if (explicit_iurl) url = iurl;
2641 else url = obj->
url;
2642 if (explicit_itooltip) {
2652 if (url ||
explicit) {
2728 char **styles =
NULL;
2756 while ((
p = *sp++)) {
2757 if (
streq(
p,
"invis"))
return;
2781 opbb.
LL.
x = opbb.
UR.
x = inpts->
x;
2782 opbb.
LL.
y = opbb.
UR.
y = inpts->
y;
2783 for (
size_t i = 1; i < numpts; i++) {
2785 if (inpts->
x < opbb.
LL.
x)
2786 opbb.
LL.
x = inpts->
x;
2787 else if (inpts->
x > opbb.
UR.
x)
2788 opbb.
UR.
x = inpts->
x;
2789 if (inpts->
y < opbb.
LL.
y)
2790 opbb.
LL.
y = inpts->
y;
2791 else if (inpts->
y > opbb.
UR.
y)
2792 opbb.
UR.
y = inpts->
y;
2806 switch (span->
just) {
2812 bb.
LL.
x = x - sz.
x / 2.0;
2813 bb.
UR.
x = x + sz.
x / 2.0;
2835 double fontsize = 0.0;
2836 char* fontname =
NULL;
2842 unsigned fontflags = 0;
2847 bb.
LL.
x = bb.
LL.
y = DBL_MAX;
2848 bb.
UR.
x = bb.
UR.
y = -DBL_MAX;
2852 for (
size_t i = 0; i <
xd->cnt; i++) {
2883 tf.
flags = fontflags;
2918 if ((
p =
agget(g,
"margin"))) {
2919 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2930 if ((
p =
agget(g,
"pad"))) {
2931 i = sscanf(
p,
"%lf,%lf", &xf, &yf);
2954 if ((
p =
agget(g,
"pagedir")) &&
p[0])
3037 job->
dpi.
x = job->
dpi.
y = DEFAULT_DPI;
3065 if (sz.
x <= 0.001) sz.
x = size.
x;
3066 if (sz.
y <= 0.001) sz.
y = size.
y;
3067 if (size.
x < sz.
x || size.
y < sz.
y
3069 && size.
x > sz.
x && size.
y > sz.
y))
3070 Z = fmin(size.
x / sz.
x, size.
y / sz.
y);
3081 if ((
str =
agget(g,
"viewport"))) {
3083 rv = sscanf(
str,
"%lf,%lf,%lf,\'%[^\']\'", &XY.
x, &XY.
y, &Z, nodename);
3091 rv = sscanf(
str,
"%lf,%lf,%lf,%[^,]%c", &XY.
x, &XY.
y, &Z, nodename,
3100 sscanf(
str,
"%lf,%lf,%lf,%lf,%lf", &XY.
x, &XY.
y, &Z, &xy.
x, &xy.
y);
3127 if (((
str =
agget(sg,
"pencolor")) != 0) &&
str[0])
3129 if (((
str =
agget(sg,
"bgcolor")) != 0) &&
str[0])
3131 if (((
str =
agget(sg,
"fillcolor")) != 0) &&
str[0])
3133 if (((
str =
agget(sg,
"fontcolor")) != 0) &&
str[0])
3147 if (((
str =
agget(g,
"fontcolor")) != 0) &&
str[0])
3154 if (((
str =
agget(n,
"pencolor")) != 0) &&
str[0])
3156 if (((
str =
agget(n,
"fillcolor")) != 0) &&
str[0]) {
3157 if (strchr(
str,
':')) {
3159 for (
str = strtok(colors,
":");
str;
3160 str = strtok(0,
":")) {
3170 if (((
str =
agget(n,
"fontcolor")) != 0) &&
str[0])
3174 if (strchr(
str,
':')) {
3176 for (
str = strtok(colors,
":");
str;
3177 str = strtok(0,
":")) {
3187 if (((
str =
agget(e,
"fontcolor")) != 0) &&
str[0])
3276#define NotFirstPage(j) (((j)->layerNum>1)||((j)->pagesArrayElem.x > 0)||((j)->pagesArrayElem.x > 0))
3291 bool obj_id_needs_restore =
false;
3297 obj_id_needs_restore =
true;
3347 if (obj_id_needs_restore) {
3354 free(previous_color_scheme);
3455 int doPerim, c, filled;
3457 char *
color, *fillcolor, *pencolor, **style, *
s;
3488 fillcolor = pencolor = 0;
3512 fillcolor = pencolor =
color;
3522 if ((filled == 0 || !fillcolor) && (
color =
agget(sg,
"bgcolor")) != 0 &&
color[0]) {
3530 char *clrs[2] = {0};
3555 AF[0] =
GD_bb(sg).LL;
3556 AF[2] =
GD_bb(sg).UR;
3569 AF[0] =
GD_bb(sg).LL;
3570 AF[2] =
GD_bb(sg).UR;
3588 else if (filled != 0) {
3621 free(previous_color_scheme);
3656 const char *start = p;
3673 size_t size = (size_t)(p - start);
3674 return (
token_t){.type = token, .start = start, .size = size};
3689 size_t parse_offsets[
sizeof(parse) /
sizeof(parse[0])];
3691 bool in_parens =
false;
3704 agerrorf(
"nesting not allowed in style: %s\n",
s);
3713 agerrorf(
"unmatched ')' in style: %s\n",
s);
3728 parse_offsets[fun++] =
agxblen(&ps_xb);
3736 agerrorf(
"unmatched '(' in style: %s\n",
s);
3744 for (
size_t i = 0; i < fun; ++i) {
3745 parse[i] = base + parse_offsets[i];
3757 assert(bz.
size > 0);
3758 assert(bz.
size % 3 == 1);
3760 for (
size_t i = 1; i < bz.
size;) {
3766 p.
x = ( p1.
x + p2.
x ) / 2;
3767 p.
y = ( p1.
y + p2.
y ) / 2;
3782 assert(spl->
size > 0);
3785 for (
size_t i = 0; i < spl->
size; i++) {
3855 static char* save_locale;
3862 setlocale (LC_NUMERIC,
"C");
3868 setlocale (LC_NUMERIC, save_locale);
3876 GV_DEBUG("gvRenderJobs %s: %.2f secs.", agnameof(g), elapsed_sec())
3880 static GVJ_t *prevjob;
3881 GVJ_t *job, *firstjob;
3887 agerrorf(
"Layout was not done. Missing layout plugins? \n");
3980#pragma GCC diagnostic push
3981#pragma GCC diagnostic ignored "-Wcast-qual"
3985#pragma GCC diagnostic pop
4012 colorsegs_t segs = {.dtor =
freeSeg};
4024 agwarningf(
"More than 2 colors specified for a gradient - ignoring remaining\n");
4033 else if (
LIST_GET(&segs, 1).hasFraction)
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
helpers for verbose/debug printing
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 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
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)
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)
type-generic dynamically expanding list
#define LIST_DETACH(list, datap, sizep)
#define LIST_AT(list, index)
#define LIST_APPEND(list, item)
#define LIST_POP_BACK(list)
#define LIST_IS_EMPTY(list)
#define LIST_GET(list, index)
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