31 #define strtok_r strtok_s
34 #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)
49 if (!((p =
agget(g,
"_background")) && p[0])) {
50 if (!((p =
agget(g,
"_draw_")) && p[0])) {
70 fprintf (stderr,
"%d ops %.2f sec\n", stats.
cnt, et);
74 fprintf (stderr,
"%d ellipses\n", stats.
n_ellipse);
75 fprintf (stderr,
"%d texts\n", stats.
n_text);
81 static char *defaultlinestyle[3] = {
"solid\0",
"setlinewidth\0001\0", 0 };
150 int flags = job->
flags;
163 if (tooltip && tooltip[0]) {
168 else if (obj->
label) {
207 layerPagePrefix (job, xb);
209 id =
agget(obj,
"id");
210 if (
id && (*
id !=
'\0')) {
215 if ((obj != root) && gid) {
239 sprintf (buf,
"%ld", idnum);
254 interpretCRNL (
char* ins)
259 boolean backslash_seen =
FALSE;
261 while ((c = *ins++)) {
262 if (backslash_seen) {
275 backslash_seen =
FALSE;
279 backslash_seen =
TRUE;
298 preprocessTooltip(
char*
s,
void* gobj)
312 return interpretCRNL (news);
319 char* url =
agget(gobj,
"href");
320 char* tooltip =
agget(gobj,
"tooltip");
321 char* target =
agget(gobj,
"target");
328 if (lab) lbl = lab->
text;
331 url =
agget(gobj,
"URL");
334 tooltip = preprocessTooltip (tooltip, gobj);
335 initMapData (job, lbl, url, tooltip, target,
id, gobj);
344 int flags = job->
flags;
361 if (! (flags & GVRENDER_DOES_MAP_RECTANGLE))
366 static char **checkClusterStyle(
graph_t* sg,
int *flagp)
372 if (((style =
agget(sg,
"style")) != 0) && style[0]) {
378 if (strcmp(p,
"filled") == 0) {
381 }
else if (strcmp(p,
"radial") == 0) {
388 }
else if (strcmp(p,
"striped") == 0) {
395 }
else if (strcmp(p,
"rounded") == 0) {
436 static double getSegLen (
char* s)
438 char* p = strchr (s,
';');
446 v = strtod (p, &endp);
455 #define AEQ0(x) (((x) < EPS) && ((x) > -EPS))
477 parseSegs (
char* clrs,
int nseg,
colorsegs_t** psegs)
481 char* colors = strdup (clrs);
485 static int doWarn = 1;
492 for (p = colors; *p; p++) {
493 if (*p ==
':') nseg++;
499 for (color = strtok(colors,
":"); color; color = strtok(0,
":")) {
500 if ((v = getSegLen (color)) >= 0) {
501 double del = v -
left;
503 if (doWarn && !
AEQ0(del)) {
504 agerr (
AGWARN,
"Total size > 1 in \"%s\" color spec ", clrs);
512 if (*color) s[cnum].
color = color;
517 agerr (
AGERR,
"Illegal length value in \"%s\" color attribute ", clrs);
535 for (i = 0; i < cnum; i++) {
536 if (s[i].t == 0) nseg++;
539 double delta = left/nseg;
540 for (i = 0; i < cnum; i++) {
541 if (s[i].t == 0) s[i].
t = delta;
551 for (i = cnum-1; i >= 0; i--) {
552 if (s[i].t > 0)
break;
561 #define THIN_LINE 0.5
582 double angle0, angle1;
584 rv = parseSegs (clrs, 0, &segs);
585 if ((rv == 1) || (rv == 2))
return rv;
586 ctr.
x = (pf[0].
x + pf[1].
x) / 2.;
587 ctr.
y = (pf[0].
y + pf[1].
y) / 2.;
588 semi.
x = pf[1].
x - ctr.
x;
589 semi.
y = pf[1].
y - ctr.
y;
595 if (s->
t == 0)
continue;
598 if (s[1].color ==
NULL)
601 angle1 = angle0 + 2*
M_PI*(s->
t);
635 rv = parseSegs (clrs, 0, &segs);
636 if ((rv == 1) || (rv == 2))
return rv;
649 xdelta = (pts[1].
x - pts[0].
x);
650 pts[1].
x = pts[2].
x = pts[0].
x;
655 if (s->
t == 0)
continue;
658 if (s[1].color ==
NULL)
659 pts[1].
x = pts[2].
x = lastx;
661 pts[1].
x = pts[2].
x = pts[0].
x + xdelta*(s->
t);
663 pts[0].
x = pts[3].
x = pts[1].
x;
674 int flags = job->
flags;
678 if (flags & GVRENDER_DOES_MAP_RECTANGLE) {
690 if (! (flags & GVRENDER_DOES_TRANSFORM))
692 if (! (flags & GVRENDER_DOES_MAP_RECTANGLE))
700 int flags = job->
flags;
704 if (flags & GVRENDER_DOES_MAP_RECTANGLE) {
715 if (! (flags & GVRENDER_DOES_TRANSFORM))
717 if (! (flags & GVRENDER_DOES_MAP_RECTANGLE))
737 static int ifFilled(
node_t * n)
739 char *style, *p, **pp;
745 if (strcmp(p,
"filled") == 0)
759 static pointf *pEllipse(
double a,
double b,
int np)
762 double deltheta = 2 *
M_PI / np;
767 for (i = 0; i < np; i++) {
768 ps[i].
x = a * cos(theta);
769 ps[i].
y = b * sin(theta);
783 static int check_control_points(
pointf *cp)
785 double dis1 =
ptToLine2 (cp[0], cp[3], cp[1]);
786 double dis2 =
ptToLine2 (cp[0], cp[3], cp[2]);
798 if (cp[0].x > bb->
UR.
x || cp[0].
x < bb->
LL.
x ||
799 cp[0].
y > bb->
UR.
y || cp[0].
y < bb->
LL.
y ||
800 cp[1].
x > bb->
UR.
x || cp[1].
x < bb->
LL.
x ||
801 cp[1].
y > bb->
UR.
y || cp[1].
y < bb->
LL.
y ||
802 cp[2].
x > bb->
UR.
x || cp[2].
x < bb->
LL.
x ||
803 cp[2].
y > bb->
UR.
y || cp[2].
y < bb->
LL.
y ||
804 cp[3].
x > bb->
UR.
x || cp[3].
x < bb->
LL.
x ||
805 cp[3].
y > bb->
UR.
y || cp[3].
y < bb->
LL.
y) {
808 if (check_control_points(cp)) {
811 for (i = 0; i < 4; i++) {
812 if (cp[i].x > bb->
UR.
x)
814 else if (cp[i].x < bb->LL.
x)
816 if (cp[i].y > bb->
UR.
y)
818 else if (cp[i].y < bb->LL.
y)
824 Bezier (cp, 3, 0.5, left, right);
832 static void psmapOutput (
pointf* ps,
int n)
835 fprintf (stdout,
"newpath %f %f moveto\n", ps[0].x, ps[0].y);
836 for (i=1; i < n; i++)
837 fprintf (stdout,
"%f %f lineto\n", ps[i].x, ps[i].y);
838 fprintf (stdout,
"closepath stroke\n");
847 #define MARK_FIRST_SEG(L) ((L)->next = (segitem_t*)1)
848 #define FIRST_SEG(L) ((L)->next == (segitem_t*)1)
849 #define INIT_SEG(P,L) {(L)->next = 0; (L)->p = P;}
863 static void map_bspline_poly(
pointf **pbs_p,
int **pbs_n,
int *pbs_poly_n,
int n,
pointf* p1,
pointf* p2)
865 int i = 0, nump = 0, last = 2*n-1;
867 for ( ; i < *pbs_poly_n; i++)
871 *pbs_n =
grealloc(*pbs_n, (*pbs_poly_n) *
sizeof(
int));
875 for (i = 0; i < n; i++) {
876 (*pbs_p)[nump+i] = p1[i];
877 (*pbs_p)[nump+last-i] = p2[i];
880 psmapOutput (*pbs_p + nump, last+1);
897 if (check_control_points(cp)) {
899 lp = appendSeg (cp[3], lp);
902 Bezier (cp, 3, 0.5, left, right);
903 lp = approx_bezier (left, lp);
904 lp = approx_bezier (right, lp);
916 double ang, theta, phi;
917 theta = atan2(np.
y - cp.
y,np.
x - cp.
x);
918 phi = atan2(pp.
y - cp.
y,pp.
x - cp.
x);
920 if (ang > 0) ang -= 2*
M_PI;
922 return (phi + ang/2.0);
937 double theta, delx, dely;
950 np.
x = 2*cp.
x - pp.
x;
951 np.
y = 2*cp.
y - pp.
y;
956 pp.
x = 2*cp.
x - np.
x;
957 pp.
y = 2*cp.
y - np.
y;
959 theta = bisect(pp,cp,np);
960 delx = w2*cos(theta);
961 dely = w2*sin(theta);
978 static void map_output_bspline (
pointf **pbs,
int **pbs_n,
int *pbs_poly_n,
bezier* bp,
double w2)
985 pointf pts[4], pt1[50], pt2[50];
988 nc = (bp->
size - 1)/3;
989 for (j = 0; j < nc; j++) {
990 for (k = 0; k < 4; k++) {
991 pts[k] = bp->
list[3*j + k];
993 segp = approx_bezier (pts, segp);
1000 segnext = segp->
next;
1001 mkSegPts (segprev, segp, segnext, pt1+cnt, pt2+cnt, w2);
1003 if ((segnext ==
NULL) || (cnt == 50)) {
1004 map_bspline_poly (pbs, pbs_n, pbs_poly_n, cnt, pt1, pt2);
1005 pt1[0] = pt1[cnt-1];
1006 pt2[0] = pt2[cnt-1];
1021 static boolean is_natural_number(
char *sstr)
1023 unsigned char *
str = (
unsigned char *) sstr;
1026 if (
NOT(isdigit(*str++)))
1031 static int layer_index(
GVC_t *
gvc,
char *str,
int all)
1036 if (
streq(str,
"all"))
1038 if (is_natural_number(str))
1047 static boolean selectedLayer(
GVC_t *gvc,
int layerNum,
int numLayers,
char *spec)
1052 char *buf_part_p =
NULL, *buf_p =
NULL, *cur, *part_in_p;
1054 boolean rval =
FALSE;
1062 w1 = w0 = strtok_r (cur, gvc->
layerDelims, &buf_p);
1065 switch ((w0 !=
NULL) + (w1 !=
NULL)) {
1070 n0 = layer_index(gvc, w0, layerNum);
1071 rval = (n0 == layerNum);
1074 n0 = layer_index(gvc, w0, 0);
1075 n1 = layer_index(gvc, w1, numLayers);
1076 if ((n0 >= 0) || (n1 >= 0)) {
1082 rval =
BETWEEN(n0, layerNum, n1);
1092 static boolean selectedlayer(
GVJ_t *job,
char *spec)
1113 static int* parse_layerselect(
GVC_t *gvc,
graph_t * g,
char *p)
1118 if (selectedLayer (gvc, i, gvc->
numLayers, p)) {
1127 agerr(
AGWARN,
"The layerselect attribute \"%s\" does not match any layer specifed by the layers attribute - ignored.\n", p);
1142 static int parse_layers(
GVC_t *gvc,
graph_t * g,
char *p)
1155 agerr(
AGWARN,
"The character \'%c\' appears in both the layersep and layerlistsep attributes - layerlistsep ignored.\n", *tok);
1185 static int chkOrder(
graph_t * g)
1187 char *p =
agget(g,
"outputorder");
1190 if ((c ==
'n') && !strcmp(p + 1,
"odesfirst"))
1192 if ((c ==
'e') && !strcmp(p + 1,
"dgesfirst"))
1215 if ((str =
agget(g,
"layers")) != 0) {
1216 gvc->
numLayers = parse_layers(gvc, g, str);
1217 if (((str =
agget(g,
"layerselect")) != 0) && *str) {
1218 gvc->
layerlist = parse_layerselect(gvc, g, str);
1229 static int numPhysicalLayers (
GVJ_t *job)
1239 static void firstlayer(
GVJ_t *job,
int** listp)
1246 agerr(
AGWARN,
"layers not supported in %s output\n",
1256 agerr(
AGWARN,
"layers not supported in %s output\n",
1265 static boolean validlayer(
GVJ_t *job)
1270 static void nextlayer(
GVJ_t *job,
int** listp)
1304 static void init_job_pagination(
GVJ_t * job,
graph_t *g)
1310 pointf centering = {0.0, 0.0};
1313 imageSize = job->
view;
1317 imageSize = exch_xyf(imageSize);
1347 imageSize.
x =
MIN(imageSize.
x, pageSize.
x);
1348 imageSize.
y =
MIN(imageSize.
y, pageSize.
y);
1353 if (pageSize.
x < 0.)
1356 if (pageSize.
y < 0.)
1360 pageSize.
x = pageSize.
y = 0.;
1363 if (pageSize.
x < imageSize.
x)
1364 pageSize.
x = imageSize.
x;
1365 if (pageSize.
y < imageSize.
y)
1366 pageSize.
y = imageSize.
y;
1389 if (pageSize.
x > imageSize.
x)
1390 centering.
x = (pageSize.
x - imageSize.
x) / 2;
1391 if (pageSize.
y > imageSize.
y)
1392 centering.
y = (pageSize.
y - imageSize.
y) / 2;
1397 imageSize = exch_xyf(imageSize);
1398 pageSize = exch_xyf(pageSize);
1399 margin = exch_xyf(margin);
1400 centering = exch_xyf(centering);
1424 static void firstpage(
GVJ_t *job)
1429 static boolean validpage(
GVJ_t *job)
1437 static void nextpage(
GVJ_t *job)
1440 if (validpage(job) ==
FALSE) {
1475 #define INITPTS 1000
1480 int i, sz = *ptsize;
1483 sz =
MAX(2*sz, numpts);
1488 for (i = 0; i < numpts; i++) {
1489 pts[i].
x = inpts[i].
x;
1490 pts[i].
y = inpts[i].
y;
1496 static void emit_xdot (
GVJ_t * job,
xdot* xd)
1507 for (i = 0; i < xd->
cnt; i++) {
1511 if (boxf_overlap(op->
bb, job->
clip)) {
1521 if (boxf_overlap(op->
bb, job->
clip)) {
1528 if (boxf_overlap(op->
bb, job->
clip)) {
1534 if (boxf_overlap(op->
bb, job->
clip)) {
1540 if (boxf_overlap(op->
bb, job->
clip)) {
1564 if ((p->
x1 == p->
x0) && (p->
y1 == p->
y0))
1585 agerr (
AGWARN,
"gradient pen colors not yet supported.\n");
1599 agerr(
AGWARN,
"Images unsupported in \"background\" attribute\n");
1618 if (! ((str =
agget(g,
"bgcolor")) && str[0])) {
1639 int filled, istyle = 0;
1642 checkClusterStyle(g, &istyle);
1662 emit_xdot (job, xd);
1670 pagesArrayElem = exch_xy(pagesArrayElem);
1671 pagesArraySize = exch_xy(pagesArraySize);
1718 fprintf(stderr,
"width=%d height=%d dpi=%g,%g\npad=%g,%g focus=%g,%g view=%g,%g zoom=%g\npageBox=%g,%g,%g,%g pagesArraySize=%d,%d pageSize=%g,%g canvasBox=%g,%g,%g,%g pageOffset=%g,%g\ntranslation=%g,%g clip=%g,%g,%g,%g margin=%g,%g\n",
1729 job->pageOffset.x, job->pageOffset.y,
1744 if (selectedlayer(job, pn))
1752 if ((pe[0] ==
'\0') || selectedlayer(job, pe))
1766 if (selectedlayer(job, pe))
1770 for (cnt = 0; cnt < 2; cnt++) {
1772 if ((pn[0] ==
'\0') || selectedlayer(job, pn))
1778 static boolean clust_in_layer(
GVJ_t *job,
graph_t * sg)
1786 if (selectedlayer(job, pg))
1791 if (node_in_layer(job, sg, n))
1796 static boolean node_in_box(
node_t *n,
boxf b)
1798 return boxf_overlap(
ND_bb(n), b);
1801 static void emit_begin_node(
GVJ_t * job,
node_t * n)
1804 int flags = job->
flags;
1805 int sides, peripheries, i, j, filled = 0, rect = 0, shape, nump = 0;
1823 initObjMapData (job,
ND_label(n), n);
1832 filled = ifFilled(n);
1838 if (isRect(poly) && (poly->
peripheries || filled))
1849 if (poly->
sides < 3)
1852 sides = poly->
sides;
1861 if ((s =
agget(n,
"samplepoints")))
1867 if ((nump < 4) || (nump > 60))
1888 p[1].
x = coord.
x + vertices[2*peripheries - 1].
x;
1889 p[1].
y = coord.
y + vertices[2*peripheries - 1].
y;
1893 p = pEllipse((
double)(vertices[2*peripheries - 1].x),
1894 (
double)(vertices[2*peripheries - 1].y), nump);
1895 for (i = 0; i < nump; i++) {
1903 int offset = (peripheries - 1)*(poly->
sides);
1908 if (poly->
sides >= nump) {
1909 int delta = poly->
sides / nump;
1911 for (i = 0, j = 0; j < nump; i += delta, j++) {
1912 p[j].
x = coord.
x + vertices[i + offset].
x;
1913 p[j].
y = coord.
y + vertices[i + offset].
y;
1918 for (i = 0; i < nump; i++) {
1919 p[i].
x = coord.
x + vertices[i + offset].
x;
1920 p[i].
y = coord.
y + vertices[i + offset].
y;
1933 p[0].
y = coord.
y - (
ND_ht(n) / 2);
1935 p[1].
y = coord.
y + (
ND_ht(n) / 2);
1937 if (! (flags & GVRENDER_DOES_TRANSFORM))
1947 static void emit_end_node(
GVJ_t * job)
1965 && node_in_layer(job,
agraphof(n), n)
1966 && node_in_box(n, job->
clip)
1980 while ((p = *sp++)) {
1981 if (
streq(p,
"invis"))
return;
1985 emit_begin_node(job, n);
1997 double x = p.
x - q.
x, y = p.
y - q.
y;
2000 d /= sqrt(x * x + y * y +
EPSILON);
2012 double x = q.
x - r.
x, y = q.
y - r.
y;
2014 len = sqrt(x * x + y * y);
2018 x = p.
x - s.
x, y = p.
y - s.
y;
2020 len = sqrt(x * x + y * y +
EPSILON);
2033 for (s = (
unsigned char *) (lp->
text); *s; s++) {
2034 if (isspace(*s) ==
FALSE)
2041 AF[0] = pointfof(lp->
pos.
x + sz.
x / 2., lp->
pos.
y - sz.
y / 2.);
2042 AF[1] = pointfof(AF[0].x - sz.
x, AF[0].
y);
2056 static char* default_pencolor(
char *pencolor,
char *deflt)
2064 for (p = pencolor; *
p; p++) {
2068 len = ncol * (strlen(deflt) + 1);
2071 buf = realloc(buf, bufsz);
2083 static double approxLen (
pointf* pts)
2085 double d =
DIST(pts[0],pts[1]);
2086 d +=
DIST(pts[1],pts[2]);
2087 d +=
DIST(pts[2],pts[3]);
2102 int i, j, k, cnt = (bz->
size - 1)/3;
2104 double last, len, sum;
2117 lens =
N_NEW(cnt,
double);
2120 for (i = 0; i < cnt; i++) {
2121 lens[i] = approxLen (pts);
2127 for (i = 0; i < cnt; i++) {
2133 left->
size = 3*(i+1) + 1;
2135 right->
size = 3*(cnt-i) + 1;
2137 for (j = 0; j < left->
size; j++)
2140 for (j = 0; j < right->
size; j++)
2144 r = (len - (sum - last))/last;
2156 static int multicolor (
GVJ_t * job,
edge_t * e,
char** styles,
char* colors,
int num,
double arrowsize,
double penwidth)
2163 char* endcolor =
NULL;
2167 rv = parseSegs (colors, num, &segs);
2179 for (i = 0; i <
ED_spl(e)->size; i++) {
2184 if (
AEQ0(s->
t))
continue;
2187 endcolor = s->
color;
2190 splitBSpline (&bz, s->
t, &bz_l, &bz_r);
2198 else if (
AEQ0(left)) {
2205 splitBSpline (&bz0, (s->
t)/(left+s->
t), &bz_l, &bz_r);
2233 static void free_stroke (
stroke_t* sp)
2243 static double forfunc (
double curlen,
double totallen,
double initwid)
2245 return ((1 - (curlen/totallen))*initwid/2.0);
2248 static double revfunc (
double curlen,
double totallen,
double initwid)
2250 return (((curlen/totallen))*initwid/2.0);
2253 static double nonefunc (
double curlen,
double totallen,
double initwid)
2255 return (initwid/2.0);
2258 static double bothfunc (
double curlen,
double totallen,
double initwid)
2260 double fr = curlen/totallen;
2261 if (fr <= 0.5)
return (fr*initwid);
2262 else return ((1-fr)*initwid);
2270 if (
streq(attr,
"forward"))
return forfunc;
2271 if (
streq(attr,
"back"))
return revfunc;
2272 if (
streq(attr,
"both"))
return bothfunc;
2273 if (
streq(attr,
"none"))
return nonefunc;
2278 static void emit_edge_graphics(
GVJ_t * job,
edge_t * e,
char** styles)
2280 int i, j, cnum, numc = 0, numsemi = 0;
2281 char *color, *pencolor, *fillcolor;
2282 char *headcolor, *tailcolor, *lastcolor;
2283 char *colors =
NULL;
2286 pointf pf0, pf1, pf2 = { 0, 0 }, pf3, *offlist, *tmplist;
2287 double arrowsize, numc2, penwidth=job->
obj->
penwidth;
2289 boolean tapered = 0;
2300 while ((p = *sp++)) {
2301 if (
streq(p,
"tapered")) {
2309 for (p = color; *
p; p++) {
2316 if (numsemi && numc) {
2317 if (
multicolor (job, e, styles, color, numc+1, arrowsize, penwidth)) {
2324 fillcolor = pencolor = color;
2347 if (pencolor != color)
2349 if (fillcolor != color)
2360 stp =
taper (&bz, taperfun (e), penwidth, 0, 0);
2364 if (fillcolor != color)
2379 numc2 = (2 + numc) / 2.0;
2380 for (i = 0; i < offspl.
size; i++) {
2386 for (j = 0; j < bz.
size - 1; j += 3) {
2388 pf1 = bz.
list[j + 1];
2391 offlist[j] = computeoffset_p(pf0, pf1,
SEP);
2393 offlist[j] = computeoffset_p(pf2, pf1,
SEP);
2394 pf2 = bz.
list[j + 2];
2395 pf3 = bz.
list[j + 3];
2396 offlist[j + 1] = offlist[j + 2] =
2397 computeoffset_qr(pf0, pf1, pf2, pf3,
SEP);
2399 tmplist[j].x = pf0.
x - numc2 * offlist[j].x;
2400 tmplist[j].y = pf0.
y - numc2 * offlist[j].y;
2401 tmplist[j + 1].x = pf1.
x - numc2 * offlist[j + 1].x;
2402 tmplist[j + 1].y = pf1.
y - numc2 * offlist[j + 1].y;
2403 tmplist[j + 2].x = pf2.
x - numc2 * offlist[j + 2].x;
2404 tmplist[j + 2].y = pf2.
y - numc2 * offlist[j + 2].y;
2407 offlist[j] = computeoffset_p(pf2, pf3,
SEP);
2408 tmplist[j].x = pf3.x - numc2 * offlist[j].x;
2409 tmplist[j].y = pf3.y - numc2 * offlist[j].y;
2411 lastcolor = headcolor = tailcolor = color;
2412 colors = strdup(color);
2413 for (cnum = 0, color = strtok(colors,
":"); color;
2414 cnum++, color = strtok(0,
":")) {
2417 if (color != lastcolor) {
2418 if (! (
ED_gui_state(e) & (GUI_STATE_ACTIVE | GUI_STATE_SELECTED))) {
2425 headcolor = tailcolor = color;
2428 for (i = 0; i < tmpspl.
size; i++) {
2431 for (j = 0; j < tmpspl.
list[i].
size; j++) {
2432 tmplist[j].
x += offlist[j].x;
2433 tmplist[j].y += offlist[j].y;
2440 if (color != tailcolor) {
2442 if (! (
ED_gui_state(e) & (GUI_STATE_ACTIVE | GUI_STATE_SELECTED))) {
2448 arrowsize, penwidth, bz.
sflag);
2451 if (color != headcolor) {
2453 if (! (
ED_gui_state(e) & (GUI_STATE_ACTIVE | GUI_STATE_SELECTED))) {
2459 arrowsize, penwidth, bz.
eflag);
2462 for (i = 0; i < offspl.
size; i++) {
2469 if (! (
ED_gui_state(e) & (GUI_STATE_ACTIVE | GUI_STATE_SELECTED))) {
2481 for (i = 0; i <
ED_spl(e)->size; i++) {
2489 arrowsize, penwidth, bz.
sflag);
2493 arrowsize, penwidth, bz.
eflag);
2503 static boolean edge_in_box(
edge_t *e,
boxf b)
2509 if (spl && boxf_overlap(spl->
bb, b))
2523 static void emit_begin_edge(
GVJ_t * job,
edge_t * e,
char** styles)
2526 int flags = job->
flags;
2530 int i, nump, *pbs_n =
NULL, pbs_poly_n = 0;
2531 char* dflt_url =
NULL;
2532 char* dflt_target =
NULL;
2552 if (flags & GVRENDER_DOES_Z) {
2568 obj->
xlabel = tlab->text;
2584 if (((s =
agget(e,
"href")) && s[0]) || ((s =
agget(e,
"URL")) && s[0]))
2586 if (((s =
agget(e,
"edgehref")) && s[0]) || ((s =
agget(e,
"edgeURL")) && s[0]))
2589 obj->
url = strdup(dflt_url);
2590 if (((s =
agget(e,
"labelhref")) && s[0]) || ((s =
agget(e,
"labelURL")) && s[0]))
2594 if (((s =
agget(e,
"tailhref")) && s[0]) || ((s =
agget(e,
"tailURL")) && s[0])) {
2599 obj->
tailurl = strdup(dflt_url);
2600 if (((s =
agget(e,
"headhref")) && s[0]) || ((s =
agget(e,
"headURL")) && s[0])) {
2605 obj->
headurl = strdup(dflt_url);
2609 if ((s =
agget(e,
"target")) && s[0])
2611 if ((s =
agget(e,
"edgetarget")) && s[0]) {
2615 else if (dflt_target)
2616 obj->
target = strdup(dflt_target);
2617 if ((s =
agget(e,
"labeltarget")) && s[0])
2619 else if (dflt_target)
2621 if ((s =
agget(e,
"tailtarget")) && s[0]) {
2625 else if (dflt_target)
2627 if ((s =
agget(e,
"headtarget")) && s[0]) {
2631 else if (dflt_target)
2636 if (((s =
agget(e,
"tooltip")) && s[0]) ||
2637 ((s =
agget(e,
"edgetooltip")) && s[0])) {
2638 char* tooltip = preprocessTooltip (s, e);
2643 else if (obj->
label)
2646 if ((s =
agget(e,
"labeltooltip")) && s[0]) {
2647 char* tooltip = preprocessTooltip (s, e);
2652 else if (obj->
label)
2655 if ((s =
agget(e,
"tailtooltip")) && s[0]) {
2656 char* tooltip = preprocessTooltip (s, e);
2664 if ((s =
agget(e,
"headtooltip")) && s[0]) {
2665 char* tooltip = preprocessTooltip (s, e);
2677 if (flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS)) {
2678 if (
ED_spl(e) && (obj->
url || obj->
tooltip) && (flags & GVRENDER_DOES_MAP_POLYGON)) {
2685 for (i = 0; i < ns; i++)
2686 map_output_bspline (&pbs, &pbs_n, &pbs_poly_n, spl->
list+i, w2);
2689 if (! (flags & GVRENDER_DOES_TRANSFORM)) {
2690 for ( nump = 0, i = 0; i < pbs_poly_n; i++)
2709 char* url,
char* tooltip,
char* target,
char *
id,
splines* spl)
2711 int flags = job->
flags;
2716 if ((lbl ==
NULL) || !(lbl->
set))
return;
2718 newid =
N_NEW(strlen(
id) +
sizeof(
"-headlabel"),
char);
2733 sprintf (newid,
"%s-%s",
id, type);
2740 map_label(job, lbl);
2744 if (spl) emit_attachment(job, lbl, spl);
2745 if (url ||
explicit) {
2746 if (flags & EMIT_CLUSTERS_LAST) {
2747 map_label(job, lbl);
2752 if (newid) free (newid);
2769 boolean explicit_iurl,
char* iurl,
2770 boolean explicit_itooltip,
char* itooltip,
2771 boolean explicit_itarget,
char* itarget)
2781 if (explicit_iurl) url = iurl;
2782 else url = obj->
url;
2783 if (explicit_itooltip) {
2802 if (explicit_itarget)
2810 if (url ||
explicit) {
2820 static void emit_end_edge(
GVJ_t * job)
2829 for ( nump = obj->
url_bsplinemap_n[0], i = 1; i < obj->url_bsplinemap_poly_n; i++) {
2922 while ((p = *sp++)) {
2923 if (
streq(p,
"invis"))
return;
2927 emit_begin_edge(job, e, styles);
2928 emit_edge_graphics (job, e, styles);
2933 static char adjust[] = {
'l',
'n',
'r'};
2954 opbb.
LL.
x = opbb.
UR.
x = inpts->
x;
2955 opbb.
LL.
y = opbb.
UR.
y = inpts->
y;
2956 for (i = 1; i < numpts; i++) {
2958 if (inpts->
x < opbb.
LL.
x)
2959 opbb.
LL.
x = inpts->
x;
2960 else if (inpts->
x > opbb.
UR.
x)
2961 opbb.
UR.
x = inpts->
x;
2962 if (inpts->
y < opbb.
LL.
y)
2963 opbb.
LL.
y = inpts->
y;
2964 else if (inpts->
y > opbb.
UR.
y)
2965 opbb.
UR.
y = inpts->
y;
2968 expandBB (bb, opbb.
LL);
2969 expandBB (bb, opbb.
UR);
2974 textBB (
double x,
double y,
textspan_t* span)
2979 switch (span->
just) {
2985 bb.
LL.
x = x - sz.
x / 2.0;
2986 bb.
UR.
x = x + sz.
x / 2.0;
3010 double fontsize = 0.0;
3011 char* fontname =
NULL;
3028 for (i = 0; i < xd->
cnt; i++) {
3039 expandBB (&bb, pts[0]);
3040 expandBB (&bb, pts[1]);
3059 tf.
flags = fontflags;
3064 expandBB (&bb, bb0.
LL);
3065 expandBB (&bb, bb0.
UR);
3094 if ((p =
agget(g,
"margin"))) {
3095 i = sscanf(p,
"%lf,%lf", &xf, &yf);
3106 if ((p =
agget(g,
"pad"))) {
3107 i = sscanf(p,
"%lf,%lf", &xf, &yf);
3130 if ((p =
agget(g,
"pagedir")) && p[0])
3153 static void init_job_pad(
GVJ_t *job)
3172 static void init_job_margin(
GVJ_t *job)
3213 job->
dpi.
x = job->
dpi.
y = (double)(DEFAULT_DPI);
3219 static void init_job_viewport(
GVJ_t * job,
graph_t * g)
3223 double X, Y, Z, x, y;
3244 if (sz.
x == 0) sz.
x = size.
x;
3245 if (sz.
y == 0) sz.
y = size.
y;
3246 if ((size.
x < sz.
x) || (size.
y < sz.
y)
3248 && (size.
x > sz.
x) && (size.
y > sz.
y)))
3249 Z =
MIN(size.
x/sz.
x, size.
y/sz.
y);
3253 x = (LL.
x + UR.
x) / 2.;
3254 y = (LL.
y + UR.
y) / 2.;
3262 if ((str =
agget(g,
"viewport"))) {
3263 nodename = malloc(strlen(str)+1);
3264 junk = malloc(strlen(str)+1);
3265 rv = sscanf(str,
"%lf,%lf,%lf,\'%[^\']\'", &X, &Y, &Z, nodename);
3274 rv = sscanf(str,
"%lf,%lf,%lf,%[^,]%s", &X, &Y, &Z, nodename, junk);
3283 rv = sscanf(str,
"%lf,%lf,%lf,%lf,%lf", &X, &Y, &Z, &x, &y);
3301 fprintf(stderr,
"view=%g,%g, zoom=%g, focus=%g,%g\n",
3308 static void emit_cluster_colors(
GVJ_t * job,
graph_t * g)
3316 emit_cluster_colors(job, sg);
3317 if (((str =
agget(sg,
"color")) != 0) && str[0])
3319 if (((str =
agget(sg,
"pencolor")) != 0) && str[0])
3321 if (((str =
agget(sg,
"bgcolor")) != 0) && str[0])
3323 if (((str =
agget(sg,
"fillcolor")) != 0) && str[0])
3325 if (((str =
agget(sg,
"fontcolor")) != 0) && str[0])
3337 if (((str =
agget(g,
"bgcolor")) != 0) && str[0])
3339 if (((str =
agget(g,
"fontcolor")) != 0) && str[0])
3342 emit_cluster_colors(job, g);
3344 if (((str =
agget(n,
"color")) != 0) && str[0])
3346 if (((str =
agget(n,
"pencolor")) != 0) && str[0])
3348 if (((str =
agget(n,
"fillcolor")) != 0) && str[0]) {
3349 if (strchr(str,
':')) {
3350 colors = strdup(str);
3351 for (str = strtok(colors,
":");
str;
3352 str = strtok(0,
":")) {
3362 if (((str =
agget(n,
"fontcolor")) != 0) && str[0])
3365 if (((str =
agget(e,
"color")) != 0) && str[0]) {
3366 if (strchr(str,
':')) {
3367 colors = strdup(str);
3368 for (str = strtok(colors,
":");
str;
3369 str = strtok(0,
":")) {
3379 if (((str =
agget(e,
"fontcolor")) != 0) && str[0])
3385 static void emit_view(
GVJ_t * job,
graph_t * g,
int flags)
3393 if (!(flags & EMIT_CLUSTERS_LAST))
3421 if (write_node_test(g, n))
3428 if (write_edge_test(g, e))
3438 emit_node(job,
aghead(e));
3444 if (flags & EMIT_CLUSTERS_LAST)
3457 initObjMapData (job,
GD_label(g), g);
3468 #define NotFirstPage(j) (((j)->layerNum>1)||((j)->pagesArrayElem.x > 0)||((j)->pagesArrayElem.x > 0))
3473 int nump = 0, flags = job->
flags;
3486 layerPagePrefix (job, &xb);
3498 if ((flags & (GVRENDER_DOES_MAPS | GVRENDER_DOES_TOOLTIPS))
3500 if (flags & (GVRENDER_DOES_MAP_RECTANGLE | GVRENDER_DOES_MAP_POLYGON)) {
3501 if (flags & GVRENDER_DOES_MAP_RECTANGLE) {
3512 if (! (flags & (GVRENDER_DOES_MAP_RECTANGLE)))
3515 if (! (flags & GVRENDER_DOES_TRANSFORM))
3520 if ((flags & GVRENDER_DOES_LABELS) && ((lab =
GD_label(g))))
3532 emit_background(job, g);
3537 emit_view(job,g,flags);
3549 int flags = job->
flags;
3571 fprintf(stderr,
"focus=%g,%g view=%g,%g\n",
3579 emit_begin_graph(job, g);
3588 for (firstlayer(job,&lp); validlayer(job); nextlayer(job,&lp)) {
3589 if (numPhysicalLayers (job) > 1)
3593 for (firstpage(job); validpage(job); nextpage(job))
3596 if (numPhysicalLayers (job) > 1)
3599 emit_end_graph(job, g);
3603 static void free_string_entry(
Dict_t * dict,
char *key,
Dtdisc_t * disc)
3649 initObjMapData (job,
GD_label(sg), sg);
3662 int doPerim, c, istyle, filled;
3664 char *color, *fillcolor, *pencolor, **style, *s;
3676 if (clust_in_layer(job, sg) ==
FALSE)
3679 if (flags & EMIT_CLUSTERS_LAST)
3681 emit_begin_cluster(job, sg);
3685 if (doAnchor && !(flags & EMIT_CLUSTERS_LAST)) {
3691 if ((style = checkClusterStyle(sg, &istyle))) {
3696 fillcolor = pencolor = 0;
3719 if (((color =
agget(sg,
"color")) != 0) && color[0])
3720 fillcolor = pencolor = color;
3721 if (((color =
agget(sg,
"pencolor")) != 0) && color[0])
3723 if (((color =
agget(sg,
"fillcolor")) != 0) && color[0])
3730 if ((!filled || !fillcolor) && ((color =
agget(sg,
"bgcolor")) != 0) && color[0]) {
3763 AF[0] =
GD_bb(sg).LL;
3764 AF[2] =
GD_bb(sg).UR;
3778 AF[0] =
GD_bb(sg).LL;
3779 AF[2] =
GD_bb(sg).UR;
3809 if (flags & EMIT_CLUSTERS_LAST) {
3816 if (flags & EMIT_PREORDER) {
3823 emit_end_cluster(job, g);
3825 if (!(flags & EMIT_CLUSTERS_LAST))
3830 static boolean is_style_delim(
int c)
3845 static int style_token(
char **s,
agxbuf * xb)
3851 while (*p && (isspace(*p) || (*p ==
',')))
3863 while (!is_style_delim(c = *p)) {
3873 static unsigned char outbuf[
SMALLBUF];
3877 static void cleanup(
void)
3894 static boolean is_first =
TRUE;
3896 boolean in_parens =
FALSE;
3912 while ((c = style_token(&p, &xb)) != 0) {
3916 agerr(
AGERR,
"nesting not allowed in style: %s\n", s);
3917 parse[0] = (
char *) 0;
3925 if (in_parens ==
FALSE) {
3926 agerr(
AGERR,
"unmatched ')' in style: %s\n", s);
3927 parse[0] = (
char *) 0;
3935 if (in_parens ==
FALSE) {
3938 parse[fun] = (
char *) 0;
3951 agerr(
AGERR,
"unmatched '(' in style: %s\n", s);
3952 parse[0] = (
char *) 0;
3956 parse[fun] = (
char *) 0;
3971 for (i = 1; i < bz.
size;) {
3977 p.
x = ( p1.
x + p2.
x ) / 2;
3978 p.
y = ( p1.
y + p2.
y ) / 2;
3988 static void init_splines_bb(
splines *spl)
3997 for (i = 0; i < spl->
size; i++) {
4015 static void init_bb_edge(
edge_t *e)
4021 init_splines_bb(spl);
4049 static void init_bb(
graph_t *g)
4072 static char* save_locale;
4078 save_locale = strdup (setlocale (LC_NUMERIC,
NULL));
4079 setlocale (LC_NUMERIC,
"C");
4085 setlocale (LC_NUMERIC, save_locale);
4092 #define FINISH() if (Verbose) fprintf(stderr,"gvRenderJobs %s: %.2f secs.\n", agnameof(g), elapsed_sec())
4096 static GVJ_t *prevjob;
4097 GVJ_t *job, *firstjob;
4103 agerr (
AGERR,
"Layout was not done. Missing layout plugins? \n");
4110 init_layering(gvc, g);
4148 job->
flags |= EMIT_PREORDER
4152 job->
flags |= chkOrder(g);
4186 init_job_margin(job);
4187 init_job_dpi(job, g);
4188 init_job_viewport(job, g);
4189 init_job_pagination(job, g);
4228 rv = parseSegs (colorlist, 0, &segs);
4236 agerr (
AGWARN,
"More than 2 colors specified for a gradient - ignoring remaining\n");
4238 clrs[0] =
N_GNEW (strlen(colorlist)+1,
char);
4241 clrs[1] = clrs[0] + (strlen(clrs[0])+1);
4248 *frac = segs->
segs[0].
t;
4250 *frac = 1 - segs->
segs[1].
t;
void gvrender_comment(GVJ_t *job, char *str)
void * zmalloc(size_t nbytes)
EXTERN Agsym_t * G_activepencolor
int(* Dtcompar_f)(Dt_t *, void *, void *, Dtdisc_t *)
unsigned int(* Dthash_f)(Dt_t *, void *, Dtdisc_t *)
EXTERN Agsym_t * E_deletedpencolor
CGRAPH_API int agobjkind(void *)
void gvrender_box(GVJ_t *job, boxf BF, int filled)
#define RALLOC(size, ptr, type)
void gvrender_polygon(GVJ_t *job, pointf *af, int n, int filled)
EXTERN Agsym_t * N_comment
int gvrender_begin_job(GVJ_t *job)
CDT_API int dtclose(Dt_t *)
void gvrender_end_edge(GVJ_t *job)
#define GUI_STATE_SELECTED
EXTERN Agsym_t * E_deletedfillcolor
Agsym_t * agattr(Agraph_t *g, int kind, char *name, char *value)
void *(* Dtmake_f)(Dt_t *, void *, Dtdisc_t *)
int statXDot(xdot *x, xdot_stats *sp)
char ** parse_style(char *s)
char * latin1ToUTF8(char *s)
#define DEFAULT_DELETEDFILLCOLOR
void * grealloc(void *ptr, size_t size)
char * htmlEntityUTF8(char *s, graph_t *g)
double(* radfunc_t)(double, double, double)
void gv_fixLocale(int set)
EXTERN Agsym_t * E_visitedfillcolor
char * late_nnstring(void *obj, attrsym_t *attr, char *def)
EXTERN Agsym_t * E_activepencolor
EXTERN Agsym_t * N_fontname
#define GVDEVICE_BINARY_FORMAT
shape_kind shapeOf(node_t *)
#define GVDEVICE_DOES_PAGES
boolean findStopColor(char *colorlist, char *clrs[2], float *frac)
boolean graph_sets_pageSize
CDT_API Dtmethod_t * Dtoset
EXTERN Agsym_t * N_fontsize
#define ALLOC(size, ptr, type)
int initMapData(GVJ_t *job, char *lbl, char *url, char *tooltip, char *target, char *id, void *gobj)
void gvrender_end_page(GVJ_t *job)
gvplugin_active_layout_t layout
#define GUI_STATE_VISITED
#define GVRENDER_DOES_MAP_POLYGON
EXTERN Agsym_t * G_visitedfillcolor
EXTERN Agsym_t * G_visitedpencolor
CGRAPH_API int agisdirected(Agraph_t *g)
size_t agxbput(agxbuf *xb, const char *s)
void(* freefunc_t)(xdot_op *)
void gvrender_set_fillcolor(GVJ_t *job, char *name)
void emit_label(GVJ_t *job, emit_state_t emit_state, textlabel_t *lp)
#define DEFAULT_LAYERLISTSEP
int gvRenderJobs(GVC_t *gvc, graph_t *g)
#define DEFAULT_SELECTEDFILLCOLOR
CGRAPH_API Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
EXTERN Agsym_t * G_deletedfillcolor
int agerr(agerrlevel_t level, const char *fmt,...)
int gvevent_key_binding_size
GVJ_t * gvjobs_first(GVC_t *gvc)
CGRAPH_API int agcontains(Agraph_t *, void *)
CGRAPH_API Agraph_t * agroot(void *obj)
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
void gvrender_begin_node(GVJ_t *job, node_t *n)
void gvrender_end_nodes(GVJ_t *job)
EXTERN Agsym_t * G_peripheries
char * strdup_and_subst_obj(char *str, void *obj)
#define GVRENDER_DOES_MAP_RECTANGLE
#define P2RECT(p, pr, sx, sy)
EXTERN Agsym_t * E_fillcolor
#define GVRENDER_DOES_TRANSFORM
void gvrender_end_layer(GVJ_t *job)
EXTERN Agsym_t * E_selectedfillcolor
CDT_API Dt_t * dtopen(Dtdisc_t *, Dtmethod_t *)
gvplugin_active_device_t device
char * agget(void *obj, char *name)
CGRAPH_API Agraph_t * agraphof(void *obj)
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
#define GVRENDER_Y_GOES_DOWN
#define DEFAULT_DELETEDPENCOLOR
void pop_obj_state(GVJ_t *job)
gvevent_key_binding_t gvevent_key_binding[]
void * init_xdot(Agraph_t *g)
#define GVRENDER_DOES_TARGETS
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
#define GVRENDER_DOES_TOOLTIPS
#define DEFAULT_EMBED_MARGIN
#define DEFAULT_VISITEDFILLCOLOR
EXTERN Agsym_t * E_activefillcolor
gvplugin_active_render_t render
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
gvrender_features_t * features
#define GVDEVICE_DOES_LAYERS
#define DEFAULT_VISITEDPENCOLOR
#define MARK_FIRST_SEG(L)
void emit_map_rect(GVJ_t *job, boxf b)
CGRAPH_API char * agnameof(void *)
void gvrender_begin_anchor(GVJ_t *job, char *href, char *tooltip, char *target, char *id)
int stripedBox(GVJ_t *job, pointf *AF, char *clrs, int rotate)
void gvrender_set_pencolor(GVJ_t *job, char *name)
void rect2poly(pointf *p)
void gvrender_begin_cluster(GVJ_t *job, graph_t *sg)
void update_bb_bz(boxf *bb, pointf *cp)
pointf * url_bsplinemap_p
stroke_t * taper(bezier *, double(*radfunc_t)(double, double, double), double initwid, int linejoin, int linecap)
void *(* Dtmemory_f)(Dt_t *, void *, size_t, Dtdisc_t *)
void free_textspan(textspan_t *tl, int cnt)
EXTERN Agsym_t * G_activefillcolor
gvdevice_callbacks_t gvdevice_callbacks
void agxbinit(agxbuf *xb, unsigned int hint, unsigned char *init)
void gvrender_set_style(GVJ_t *job, char **s)
EXTERN Agsym_t * E_comment
boolean mapBool(char *p, boolean dflt)
void gvrender_begin_page(GVJ_t *job)
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
EXTERN Agsym_t * G_deletedpencolor
int late_int(void *obj, attrsym_t *attr, int def, int low)
void gvrender_begin_edges(GVJ_t *job)
EXTERN Agsym_t * E_visitedpencolor
void gvrender_begin_edge(GVJ_t *job, edge_t *e)
void gvrender_end_graph(GVJ_t *job)
void gvrender_set_gradient_vals(GVJ_t *job, char *stopcolor, int angle, float frac)
EXTERN Agsym_t * G_gradientangle
void emit_clusters(GVJ_t *job, Agraph_t *g, int flags)
void gvrender_set_penwidth(GVJ_t *job, double penwidth)
#define GUI_STATE_DELETED
#define GVRENDER_NO_WHITE_BG
obj_state_t * push_obj_state(GVJ_t *job)
void gvrender_textspan(GVJ_t *job, pointf p, textspan_t *span)
int wedgedEllipse(GVJ_t *job, pointf *pf, char *clrs)
gvevent_key_binding_t * keybindings
xdot * parseXDotF(char *s, drawfunc_t fns[], int sz)
void gvrender_end_edges(GVJ_t *job)
pointf Bezier(pointf *V, int degree, double t, pointf *Left, pointf *Right)
#define DEFAULT_SELECTEDPENCOLOR
boolean graph_sets_margin
#define GVRENDER_DOES_MAPS
CGRAPH_API Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
char * getObjId(GVJ_t *job, void *obj, agxbuf *xb)
#define agfindgraphattr(g, a)
#define DEFAULT_PRINT_MARGIN
EXTERN Agsym_t * E_penwidth
boxf arrow_bb(pointf p, pointf u, double arrowsize, int flag)
double late_double(void *obj, attrsym_t *attr, double def, double low)
pointf * gvrender_ptf_A(GVJ_t *job, pointf *af, pointf *AF, int n)
void round_corners(GVJ_t *job, pointf *AF, int sides, int style, int filled)
EXTERN unsigned char Verbose
void emit_once_reset(void)
#define DEFAULT_ACTIVEPENCOLOR
struct segitem_s segitem_t
void freePath(Ppolyline_t *p)
#define DEFAULT_ACTIVEFILLCOLOR
int url_bsplinemap_poly_n
int explicit_labeltooltip
EXTERN char ** Show_boxes
int(* Dtevent_f)(Dt_t *, int, void *, Dtdisc_t *)
void emit_graph(GVJ_t *job, graph_t *g)
void(* pf)(char *, void *)
void(* Dtfree_f)(Dt_t *, void *, Dtdisc_t *)
pointf textspan_size(GVC_t *gvc, textspan_t *span)
void setColorScheme(char *s)
EXTERN Agsym_t * G_penwidth
#define GVRENDER_DOES_LABELS
void gvrender_ellipse(GVJ_t *job, pointf *AF, int n, int filled)
char * late_string(void *obj, attrsym_t *attr, char *def)
void arrow_gen(GVJ_t *job, emit_state_t emit_state, pointf p, pointf u, double arrowsize, double penwidth, int flag)
void gvrender_beziercurve(GVJ_t *job, pointf *AF, int n, int arrow_at_start, int arrow_at_end, boolean filled)
void gvrender_end_job(GVJ_t *job)
int gvrender_select(GVJ_t *job, const char *lang)
void gvrender_begin_nodes(GVJ_t *job)
char * agxget(void *obj, Agsym_t *sym)
#define EMIT_CLUSTERS_LAST
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
EXTERN Agsym_t * E_decorate
boolean overlap_label(textlabel_t *lp, boxf b)
Ppolyline_t * ellipticWedge(pointf ctr, double xsemi, double ysemi, double angle0, double angle1)
EXTERN Agsym_t * E_arrowsz
map_shape_t url_map_shape
void gvrender_end_cluster(GVJ_t *job, graph_t *g)
#define DEFAULT_GRAPH_PAD
void gvrender_end_anchor(GVJ_t *job)
void gvrender_end_node(GVJ_t *job)
GVJ_t * gvjobs_next(GVC_t *gvc)
pointf dotneato_closest(splines *spl, pointf pt)
EXTERN Agsym_t * E_selectedpencolor
void agxbfree(agxbuf *xb)
gvdevice_callbacks_t * callbacks
const char * output_langname
void gvrender_begin_layer(GVJ_t *job)
#define GVDEVICE_DOES_TRUECOLOR
double ptToLine2(pointf a, pointf b, pointf p)
gvdevice_features_t * features
void gvrender_begin_graph(GVJ_t *job, graph_t *g)
void gvrender_polyline(GVJ_t *job, pointf *AF, int n)
#define GVRENDER_DOES_ARROWS