예제 #1
0
static void 
xd_set_style (char **s)
{
    unsigned char buf[BUFSIZ];
    agxbuf xbuf;
    char* p;
    int more;

    agxbinit(&xbuf, BUFSIZ, buf);
    while ((p = *s++)) {
	agxbput(&xbuf, p);
	while (*p)
	    p++;
	p++;
	if (*p) {  /* arguments */
	    agxbputc(&xbuf, '(');
            more = 0;
	    while (*p) {
		if (more)
		    agxbputc(&xbuf, ',');
		agxbput(&xbuf, p);
	        while (*p) p++;
		p++;
		more++;
	    }
	    agxbputc(&xbuf, ')');
	}
	xd_str ("S ", agxbuse(&xbuf));
    }
    agxbfree(&xbuf);
}
예제 #2
0
static const char *getTok(const char *args, agxbuf * xb)
{
    char c;
    int more = 1;

    args = skipWS(args);
    if (*args == '\0')
	return 0;

    while (more) {
	c = *args++;
	if (isspace(c))
	    more = 0;
	else if (c == '\0') {
	    more = 0;
	    args--;
	} else if ((c == '"') || (c == '\'')) {
	    args = endQuote(args, xb, c);
	} else if (c == '\\') {
	    c = *args++;
	    if (c == '\0')
		args--;
	    else
		agxbputc(xb, c);
	} else
	    agxbputc(xb, c);
    }
    return args;
}
예제 #3
0
파일: htmllex.c 프로젝트: Chaduke/bah.mod
/* findNext:
 * Return next XML unit. This is either <..>, an HTML 
 * comment <!-- ... -->, or characters up to next <.
 */
static char *findNext(char *s, agxbuf* xb)
{
    char* t = s + 1;
    char c;
    int rc;

    if (*s == '<') {
	if ((*t == '!') && !strncmp(t + 1, "--", 2))
	    t = eatComment(t + 3);
	else
	    while (*t && (*t != '>'))
		t++;
	if (*t != '>') {
	    agerr(AGWARN, "Label closed before end of HTML element\n");
	    state.warn = 1;
	} else
	    t++;
    } else {
	rc = agxbputc(xb, *s);
	while ((c = *t) && (c != '<')) {
	    if ((c == '&') && (*(t+1) != '#')) {
		t = scanEntity(t + 1, xb);
	    }
	    else {
		rc = agxbputc(xb, c);
		t++;
	    }
	}
    }
    return t;
}
static void xdot_style (GVJ_t *job)
{
    unsigned char buf0[BUFSIZ];
    char buf [128]; /* enough to hold a double */
    agxbuf xbuf;
    char* p, **s;
    int more;

    agxbinit(&xbuf, BUFSIZ, buf0);

    /* First, check if penwidth state is correct */
    if (job->obj->penwidth != penwidth[job->obj->emit_state]) {
	penwidth[job->obj->emit_state] = job->obj->penwidth;
	agxbput (&xbuf, "setlinewidth(");
	sprintf (buf, "%.3f", job->obj->penwidth);
	xdot_trim_zeros (buf, 0);
	agxbput(&xbuf, buf);
	agxbputc (&xbuf, ')');
        xdot_str (job, "S ", agxbuse(&xbuf));
    }

    /* now process raw style, if any */
    s = job->obj->rawstyle;
    if (!s)
	return;

    while ((p = *s++)) {
	if (streq(p, "filled") || streq(p, "bold") || streq(p, "setlinewidth")) continue;
        agxbput(&xbuf, p);
        while (*p)
            p++;
        p++;
        if (*p) {  /* arguments */
            agxbputc(&xbuf, '(');
            more = 0;
            while (*p) {
                if (more)
                    agxbputc(&xbuf, ',');
                agxbput(&xbuf, p);
                while (*p) p++;
                p++;
                more++;
            }
            agxbputc(&xbuf, ')');
        }
        xdot_str (job, "S ", agxbuse(&xbuf));
    }

    agxbfree(&xbuf);

}
예제 #5
0
char *gvUsername(void)
{
    char *user = NULL;
#ifndef MSWIN32
    static int first = 1;
    struct passwd *p;
    if (first) {
	agxbinit(&xb, SMALLBUF, userbuf);
	atexit(cleanup);
	first = 0;
    }
    p = (struct passwd *) getpwuid(getuid());
    if (p) {
	agxbputc(&xb, '(');
	agxbput(&xb, p->pw_name);
	agxbput(&xb, ") ");
#ifdef SVR4
	agxbput(&xb, p->pw_comment);
#else
	agxbput(&xb, p->pw_gecos);
#endif
	user = agxbuse(&xb);
    }
#endif
    if (user == NULL)
	user = "******"; //maks
    return user;
}
예제 #6
0
/* clustNode:
 * Generate a special cluster node representing the end node
 * of an edge to the cluster cg. n is a node whose name is the same
 * as the cluster cg. clg is the subgraph of all of
 * the original nodes, which will be deleted later.
 */
static node_t *clustNode(node_t * n, graph_t * cg, agxbuf * xb,
			 graph_t * clg)
{
    node_t *cn;
    static int idx = 0;
    char num[100];

    agxbput(xb, "__");
    sprintf(num, "%d", idx++);
    agxbput(xb, num);
    agxbputc(xb, ':');
    agxbput(xb, cg->name);

    cn = agnode(cg->root, agxbuse(xb));
    SET_CLUST_NODE(cn);
    aginsert(cg, cn);
    aginsert(clg, n);

    /* set attributes */
    N_label = setAttr(cn->graph, cn, "label", "", N_label);
    N_style = setAttr(cn->graph, cn, "style", "invis", N_style);
    N_shape = setAttr(cn->graph, cn, "shape", "box", N_shape);
    /* N_width = setAttr (cn->graph, cn, "width", "0.0001", N_width); */

    return cn;
}
예제 #7
0
static void copyUpper (agxbuf* xb, char* s)
{
    int c;

    while ((c = *s++))
	(void)agxbputc (xb, toupper(c));
}
예제 #8
0
파일: utils.c 프로젝트: jho1965us/graphviz
/* clustNode:
 * Generate a special cluster node representing the end node
 * of an edge to the cluster cg. n is a node whose name is the same
 * as the cluster cg. clg is the subgraph of all of
 * the original nodes, which will be deleted later.
 */
static node_t *clustNode(node_t * n, graph_t * cg, agxbuf * xb,
			 graph_t * clg)
{
    node_t *cn;
    static int idx = 0;
    char num[100];

    agxbput(xb, "__");
    sprintf(num, "%d", idx++);
    agxbput(xb, num);
    agxbputc(xb, ':');
    agxbput(xb, agnameof(cg));

    cn = agnode(agroot(cg), agxbuse(xb), 1);
    agbindrec(cn, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE);

    SET_CLUST_NODE(cn);
	agsubnode(cg,cn,1);
	//aginsert(cg, cn);
	agsubnode(clg,n,1);
	//aginsert(clg, n);

    /* set attributes */
    N_label = setAttr(agraphof(cn), cn, "label", "", N_label);
    N_style = setAttr(agraphof(cn), cn, "style", "invis", N_style);
    N_shape = setAttr(agraphof(cn), cn, "shape", "box", N_shape);
    /* N_width = setAttr (cn->graph, cn, "width", "0.0001", N_width); */

    return cn;
}
예제 #9
0
static void xd_ellipse(point p, int rx, int ry, int filled)
{
    char buf[BUFSIZ];

    agxbputc(xbufs[gvc->emit_state], (filled ? 'E' : 'e'));
    sprintf(buf, " %d %d %d %d ", p.x, YDIR(p.y), rx, ry);
    agxbput(xbufs[gvc->emit_state], buf);
}
static void xdot_str_xbuf (agxbuf* xb, char* pfx, char* s)
{
    char buf[BUFSIZ];

    sprintf (buf, "%s%d -", pfx, (int)strlen(s));
    agxbput(xb, buf);
    agxbput(xb, s);
    agxbputc(xb, ' ');
}
예제 #11
0
static void xd_str (char* pfx, char* s)
{
    char buf[BUFSIZ];

    sprintf (buf, "%s%d -", pfx, (int)strlen(s));
    agxbput(xbufs[gvc->emit_state], buf);
    agxbput(xbufs[gvc->emit_state], s);
    agxbputc(xbufs[gvc->emit_state], ' ');
}
예제 #12
0
/* Construct the list of font faces */
static char *get_avail_faces(int faces, agxbuf* xb)
{
    int i;
    for (i = 0; i < FACELIST_SZ; i++) {
	if (faces & facelist[i].flag) {
	    agxbput (xb, facelist[i].name); 
	    agxbputc(xb, ' ');
	}
    }
    return agxbuse (xb);
}
예제 #13
0
/* Returns the font corresponding to a Graphviz PS font. 
   AvantGarde-Book may return URW Gothic L, book
   Returns NULL if no appropriate font found.
*/
static char *gv_get_font(availfont_t* gv_af_p,
		  PostscriptAlias * ps_alias, agxbuf* xb, agxbuf *xb2)
{
    char *avail_faces;
    int i;

    for (i = 0; i < GV_FONT_LIST_SIZE; i++) {
	/* Searches the array of available system fonts for the one that
	   corresponds to the current Graphviz PS font name. Sets up the
	   font string with the available font name and the installed font 
	   faces that match what are required by the Graphviz PS font.
	 */
	if (gv_af_p[i].faces && strstr(ps_alias->name, gv_af_p[i].gv_ps_fontname)) {
	    agxbput(xb2, gv_af_p[i].fontname);
	    agxbput(xb2, ", ");
	    avail_faces = get_avail_faces(gv_af_p[i].faces, xb);
	    if (ps_alias->weight) {
		if (strcasestr(avail_faces, ps_alias->weight)) {
		    agxbputc(xb2, ' ');
		    copyUpper(xb2, ps_alias->weight);
		}
	    } else if (strcasestr(avail_faces, "REGULAR")) {
		agxbputc(xb2, ' ');
		agxbput(xb2, "REGULAR");
	    } else if (strstr(avail_faces, "ROMAN")) {
		agxbputc(xb2, ' ');
		agxbput(xb2, "ROMAN");
	    }
	    if (ps_alias->stretch) {
		if (strcasestr(avail_faces, ps_alias->stretch)) {
		    agxbputc(xb2, ' ');
		    copyUpper(xb2, ps_alias->stretch);
		}
	    }
	    if (ps_alias->style) {
		if (strcasestr(avail_faces, ps_alias->style)) {
		    agxbputc(xb2, ' ');
		    copyUpper(xb2, ps_alias->style);
		} else if (!strcasecmp(ps_alias->style, "ITALIC")) {
                    /* try to use ITALIC in place of OBLIQUE & visa versa */
		    if (strcasestr(avail_faces, "OBLIQUE")) {
			agxbputc(xb2, ' ');
			agxbput(xb2, "OBLIQUE");
		    }
		} else if (!strcasecmp(ps_alias->style, "OBLIQUE")) {
		    if (strcasestr(avail_faces, "ITALIC")) {
			agxbputc(xb2, ' ');
			agxbput(xb2, "ITALIC");
		    }
		}
	    }
	    return strdup(agxbuse(xb2));
	}
    }
    return NULL;
}
static void xdot_points(GVJ_t *job, char c, pointf * A, int n)
{
    emit_state_t emit_state = job->obj->emit_state;
    char buf[BUFSIZ];
    int i, rc;

    rc = agxbputc(xbufs[emit_state], c);
    sprintf(buf, " %d ", n);
    agxbput(xbufs[emit_state], buf);
    for (i = 0; i < n; i++)
        xdot_point(xbufs[emit_state], A[i]);
}
예제 #15
0
파일: utils.c 프로젝트: jho1965us/graphviz
/* scanEntity:
 * Scan non-numeric entity, convert to &#...; form and store in xbuf.
 * t points to first char after '&'. Return after final semicolon.
 * If unknown, we return t and let libexpat flag the error.
 *     */
char* scanEntity (char* t, agxbuf* xb)
{
    char*  endp = strchr (t, ';');
    struct entities_s key, *res;
    int    len;
    char   buf[MAXENTLEN+1];

    agxbputc(xb, '&');
    if (!endp) return t;
    if (((len = endp-t) > MAXENTLEN) || (len < 2)) return t;
    strncpy (buf, t, len);
    buf[len] = '\0';
    key.name =  buf;
    res = bsearch(&key, entities, NR_OF_ENTITIES,
        sizeof(entities[0]), comp_entities);
    if (!res) return t;
    sprintf (buf, "%d", res->value);
    agxbputc(xb, '#');
    agxbput(xb, buf);
    agxbputc(xb, ';');
    return (endp+1);
}
예제 #16
0
/* stoj:
 * Convert dot string to a valid json string embedded in double quotes.
 */
static char* stoj (char* ins, state_t* sp)
{
    char* s;
    char* input;
    static agxbuf xb;
    unsigned char c;

    if (sp->isLatin)
	input = latin1ToUTF8 (ins);
    else
	input = ins;

    if (xb.buf == NULL)
	agxbinit(&xb, BUFSIZ, NULL);
    for (s = input; (c = *s); s++) {
	switch (c) {
	case '"' :
	    agxbput(&xb, "\\\"");
	    break;
	case '\\' :
	    agxbput(&xb, "\\\\");
	    break;
	case '/' :
	    agxbput(&xb, "\\/");
	    break;
	case '\b' :
	    agxbput(&xb, "\\b");
	    break;
	case '\f' :
	    agxbput(&xb, "\\f");
	    break;
	case '\n' :
	    agxbput(&xb, "\\n");
	    break;
	case '\r' :
	    agxbput(&xb, "\\r");
	    break;
	case '\t' :
	    agxbput(&xb, "\\t");
	    break;
	default :
	    agxbputc(&xb, c);
	    break;
	}
    }
    s = agxbuse(&xb);

    if (sp->isLatin)
	free (input);
    return s;
}
예제 #17
0
static const char *endQuote(const char *args, agxbuf * xb, char endc)
{
    int more = 1;
    char c;

    while (more) {
	c = *args++;
	if (c == endc)
	    more = 0;
	else if (c == '\0') {
	    more = 0;
	    args--;
	} else if (c == '\\') {
	    c = *args++;
	    if (c == '\0')
		args--;
	    else
		agxbputc(xb, c);
	} else
	    agxbputc(xb, c);
    }
    return args;
}
예제 #18
0
static void xd_points(char c, point * A, int n)
{
    char buf[BUFSIZ];
    int i;
    point p;

    agxbputc(xbufs[gvc->emit_state], c);
    sprintf(buf, " %d ", n);
    agxbput(xbufs[gvc->emit_state], buf);
    for (i = 0; i < n; i++) {
	p = A[i];
	sprintf(buf, "%d %d ", p.x, YDIR(p.y));
	agxbput(xbufs[gvc->emit_state], buf);
    }
}
예제 #19
0
/* latin1ToUTF8:
 * Converts string from Latin1 encoding to utf8
 * Also translates HTML entities.
 *
 */
char*
latin1ToUTF8 (char* s)
{
    char*  ns;
    agxbuf xb;
    unsigned char buf[BUFSIZ];
    unsigned int  v;
    
    agxbinit(&xb, BUFSIZ, buf);

    /* Values are either a byte (<= 256) or come from htmlEntity, whose
     * values are all less than 0x07FF, so we need at most 3 bytes.
     */
    while ((v = *(unsigned char*)s++)) {
	if (v == '&') {
	    v = htmlEntity (&s);
	    if (!v) v = '&';
        }
	if (v < 0x7F) agxbputc(&xb, v);
	else if (v < 0x07FF) {
	    agxbputc(&xb, (v >> 6) | 0xC0);
	    agxbputc(&xb, (v & 0x3F) | 0x80);
	}
	else {
예제 #20
0
파일: htmllex.c 프로젝트: Chaduke/bah.mod
/* characterData:
 * Generate T_string token. Do this only when immediately in
 * <TD>..</TD> or <HTML>..</HTML>, i.e., when inCell is true.
 * Strip out formatting characters but keep spaces.
 * Distinguish between all whitespace vs. strings with non-whitespace
 * characters.
 */
static void characterData(void *user, const char *s, int length)
{
    int i, rc, cnt = 0;
    unsigned char c;

    if (state.inCell) {
	for (i = length; i; i--) {
	    c = *s++;
	    if (c >= ' ') {
		cnt++;
		rc = agxbputc(state.xb, c);
	    }
	}
	if (cnt) state.tok = T_string;
    }
}
예제 #21
0
파일: utils.c 프로젝트: jho1965us/graphviz
static unsigned char
cvtAndAppend (unsigned char c, agxbuf* xb)
{
    char buf[2];
    char* s;
    char* p;
    int len;

    buf[0] = c;
    buf[1] = '\0';

    p = s = latin1ToUTF8 (buf);
    len = strlen(s);
    while (len-- > 1)
	agxbputc(xb, *p++);
    c = *p;
    free (s);
    return c;
}
예제 #22
0
void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep)
{
    int e_arrows;		/* graph has edges with end arrows */
    int s_arrows;		/* graph has edges with start arrows */
    int i, j, sides;
    char buf[BUFSIZ];		/* Used only for small strings */
    unsigned char xbuffer[BUFSIZ];	/* Initial buffer for xb */
    agxbuf xb;
    node_t *n;
    edge_t *e;
    pointf ptf;
    int dim3 = (GD_odim(g) >= 3);
    Agsym_t* bbsym;

    gv_fixLocale (1);
    e_arrows = s_arrows = 0;
    setYInvert(g);
    agxbinit(&xb, BUFSIZ, xbuffer);
    safe_dcl(g, AGNODE, "pos", "");
    safe_dcl(g, AGNODE, "rects", "");
    N_width = safe_dcl(g, AGNODE, "width", "");
    N_height = safe_dcl(g, AGNODE, "height", "");
    safe_dcl(g, AGEDGE, "pos", "");
    if (GD_has_labels(g) & NODE_XLABEL)
	safe_dcl(g, AGNODE, "xlp", "");
    if (GD_has_labels(g) & EDGE_LABEL)
	safe_dcl(g, AGEDGE, "lp", "");
    if (GD_has_labels(g) & EDGE_XLABEL)
	safe_dcl(g, AGEDGE, "xlp", "");
    if (GD_has_labels(g) & HEAD_LABEL)
	safe_dcl(g, AGEDGE, "head_lp", "");
    if (GD_has_labels(g) & TAIL_LABEL)
	safe_dcl(g, AGEDGE, "tail_lp", "");
    if (GD_label(g)) {
	safe_dcl(g, AGRAPH, "lp", "");
	safe_dcl(g, AGRAPH, "lwidth", "");
	safe_dcl(g, AGRAPH, "lheight", "");
	if (GD_label(g)->text[0]) {
	    ptf = GD_label(g)->pos;
	    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
	    agset(g, "lp", buf);
	    ptf = GD_label(g)->dimen;
	    sprintf(buf, "%.2f", PS2INCH(ptf.x));
	    agset(g, "lwidth", buf);
	    sprintf(buf, "%.2f", PS2INCH(ptf.y));
	    agset(g, "lheight", buf);
	}
    }
    bbsym = safe_dcl(g, AGRAPH, "bb", "");
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (dim3) {
	    int k;

	    sprintf(buf, "%.5g,%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y), POINTS_PER_INCH*(ND_pos(n)[2]));
	    agxbput (&xb, buf);
	    for (k = 3; k < GD_odim(g); k++) {
		sprintf(buf, ",%.5g", POINTS_PER_INCH*(ND_pos(n)[k]));
		agxbput (&xb, buf);
	    }
	    agset(n, "pos", agxbuse(&xb));
	} else {
	    sprintf(buf, "%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y));
	    agset(n, "pos", buf);
	}
	sprintf(buf, "%.5g", PS2INCH(ND_ht(n)));
	agxset(n, N_height, buf);
	sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n)));
	agxset(n, N_width, buf);
	if (ND_xlabel(n) && ND_xlabel(n)->set) {
	    ptf = ND_xlabel(n)->pos;
	    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
	    agset(n, "xlp", buf);
	}
	if (strcmp(ND_shape(n)->name, "record") == 0) {
	    set_record_rects(n, ND_shape_info(n), &xb);
	    agxbpop(&xb);	/* get rid of last space */
	    agset(n, "rects", agxbuse(&xb));
	} else {
	    polygon_t *poly;
	    int i;
	    if (N_vertices && isPolygon(n)) {
		poly = (polygon_t *) ND_shape_info(n);
		sides = poly->sides;
		if (sides < 3) {
		    char *p = agget(n, "samplepoints");
		    if (p)
			sides = atoi(p);
		    else
			sides = 8;
		    if (sides < 3)
			sides = 8;
		}
		for (i = 0; i < sides; i++) {
		    if (i > 0)
			agxbputc(&xb, ' ');
		    if (poly->sides >= 3)
			sprintf(buf, "%.5g %.5g",
				PS2INCH(poly->vertices[i].x),
				YFDIR(PS2INCH(poly->vertices[i].y)));
		    else
			sprintf(buf, "%.5g %.5g",
				ND_width(n) / 2.0 * cos(i / (double) sides * M_PI * 2.0),
				YFDIR(ND_height(n) / 2.0 * sin(i / (double) sides * M_PI * 2.0)));
		    agxbput(&xb, buf);
		}
		agxset(n, N_vertices, agxbuse(&xb));
	    }
	}
	if (State >= GVSPLINES) {
	    for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
		if (ED_edge_type(e) == IGNORED)
		    continue;
		if (ED_spl(e) == NULL)
		    continue;	/* reported in postproc */
		for (i = 0; i < ED_spl(e)->size; i++) {
		    if (i > 0)
			agxbputc(&xb, ';');
		    if (ED_spl(e)->list[i].sflag) {
			s_arrows = 1;
			sprintf(buf, "s,%.5g,%.5g ",
				ED_spl(e)->list[i].sp.x,
				YDIR(ED_spl(e)->list[i].sp.y));
			agxbput(&xb, buf);
		    }
		    if (ED_spl(e)->list[i].eflag) {
			e_arrows = 1;
			sprintf(buf, "e,%.5g,%.5g ",
				ED_spl(e)->list[i].ep.x,
				YDIR(ED_spl(e)->list[i].ep.y));
			agxbput(&xb, buf);
		    }
		    for (j = 0; j < ED_spl(e)->list[i].size; j++) {
			if (j > 0)
			    agxbputc(&xb, ' ');
			ptf = ED_spl(e)->list[i].list[j];
			sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
			agxbput(&xb, buf);
		    }
		}
		agset(e, "pos", agxbuse(&xb));
		if (ED_label(e)) {
		    ptf = ED_label(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "lp", buf);
		}
		if (ED_xlabel(e) && ED_xlabel(e)->set) {
		    ptf = ED_xlabel(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "xlp", buf);
		}
		if (ED_head_label(e)) {
		    ptf = ED_head_label(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "head_lp", buf);
		}
		if (ED_tail_label(e)) {
		    ptf = ED_tail_label(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "tail_lp", buf);
		}
	    }
	}
    }
    rec_attach_bb(g, bbsym);
    agxbfree(&xb);

    if (HAS_CLUST_EDGE(g))
	undoClusterEdges(g);
    
    *sp = s_arrows;
    *ep = e_arrows;
    gv_fixLocale (0);
}
예제 #23
0
파일: output.c 프로젝트: Chaduke/bah.mod
void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep)
{
    int e_arrows;		/* graph has edges with end arrows */
    int s_arrows;		/* graph has edges with start arrows */
    int i, j, sides;
    char buf[BUFSIZ];		/* Used only for small strings */
    unsigned char xbuffer[BUFSIZ];	/* Initial buffer for xb */
    agxbuf xb;
    node_t *n;
    edge_t *e;
    point pt;

    e_arrows = s_arrows = 0;
    setYInvert(g);
    agxbinit(&xb, BUFSIZ, xbuffer);
    safe_dcl(g, g->proto->n, "pos", "", agnodeattr);
    safe_dcl(g, g->proto->n, "rects", "", agnodeattr);
    N_width = safe_dcl(g, g->proto->n, "width", "", agnodeattr);
    N_height = safe_dcl(g, g->proto->n, "height", "", agnodeattr);
    safe_dcl(g, g->proto->e, "pos", "", agedgeattr);
    if (GD_has_labels(g) & EDGE_LABEL)
	safe_dcl(g, g->proto->e, "lp", "", agedgeattr);
    if (GD_has_labels(g) & HEAD_LABEL)
	safe_dcl(g, g->proto->e, "head_lp", "", agedgeattr);
    if (GD_has_labels(g) & TAIL_LABEL)
	safe_dcl(g, g->proto->e, "tail_lp", "", agedgeattr);
    if (GD_label(g)) {
	safe_dcl(g, g, "lp", "", agraphattr);
	if (GD_label(g)->text[0]) {
	    pt = GD_label(g)->p;
	    sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
	    agset(g, "lp", buf);
	}
    }
    safe_dcl(g, g, "bb", "", agraphattr);
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	sprintf(buf, "%d,%d", ND_coord_i(n).x, YDIR(ND_coord_i(n).y));
	agset(n, "pos", buf);
	sprintf(buf, "%.2f", PS2INCH(ND_ht_i(n)));
	agxset(n, N_height->index, buf);
	sprintf(buf, "%.2f", PS2INCH(ND_lw_i(n) + ND_rw_i(n)));
	agxset(n, N_width->index, buf);
	if (strcmp(ND_shape(n)->name, "record") == 0) {
	    set_record_rects(n, ND_shape_info(n), &xb);
	    agxbpop(&xb);	/* get rid of last space */
	    agset(n, "rects", agxbuse(&xb));
	} else {
	    polygon_t *poly;
	    int i;
	    if (N_vertices && isPolygon(n)) {
		poly = (polygon_t *) ND_shape_info(n);
		sides = poly->sides;
		if (sides < 3) {
		    char *p = agget(n, "samplepoints");
		    if (p)
			sides = atoi(p);
		    else
			sides = 8;
		    if (sides < 3)
			sides = 8;
		}
		for (i = 0; i < sides; i++) {
		    if (i > 0)
			agxbputc(&xb, ' ');
		    if (poly->sides >= 3)
			sprintf(buf, "%.3f %.3f",
				PS2INCH(poly->vertices[i].x),
				YFDIR(PS2INCH(poly->vertices[i].y)));
		    else
			sprintf(buf, "%.3f %.3f",
				ND_width(n) / 2.0 * cos(i /
							(double) sides *
							PI * 2.0),
				YFDIR(ND_height(n) / 2.0 *
				   sin(i / (double) sides * PI * 2.0)));
		    agxbput(&xb, buf);
		}
		agxset(n, N_vertices->index, agxbuse(&xb));
	    }
	}
	if (State >= GVSPLINES) {
	    for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
		if (ED_edge_type(e) == IGNORED)
		    continue;
		if (ED_spl(e) == NULL)
		    continue;	/* reported in postproc */
		for (i = 0; i < ED_spl(e)->size; i++) {
		    if (i > 0)
			agxbputc(&xb, ';');
		    if (ED_spl(e)->list[i].sflag) {
			s_arrows = 1;
			sprintf(buf, "s,%d,%d ",
				ED_spl(e)->list[i].sp.x,
				YDIR(ED_spl(e)->list[i].sp.y));
			agxbput(&xb, buf);
		    }
		    if (ED_spl(e)->list[i].eflag) {
			e_arrows = 1;
			sprintf(buf, "e,%d,%d ",
				ED_spl(e)->list[i].ep.x,
				YDIR(ED_spl(e)->list[i].ep.y));
			agxbput(&xb, buf);
		    }
		    for (j = 0; j < ED_spl(e)->list[i].size; j++) {
			if (j > 0)
			    agxbputc(&xb, ' ');
			pt = ED_spl(e)->list[i].list[j];
			sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
			agxbput(&xb, buf);
		    }
		}
		agset(e, "pos", agxbuse(&xb));
		if (ED_label(e)) {
		    pt = ED_label(e)->p;
		    sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
		    agset(e, "lp", buf);
		}
		if (ED_head_label(e)) {
		    pt = ED_head_label(e)->p;
		    sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
		    agset(e, "head_lp", buf);
		}
		if (ED_tail_label(e)) {
		    pt = ED_tail_label(e)->p;
		    sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
		    agset(e, "tail_lp", buf);
		}
	    }
	}
    }
    rec_attach_bb(g);
    agxbfree(&xb);

    if (HAS_CLUST_EDGE(g))
	undoClusterEdges(g);
    
    *sp = s_arrows;
    *ep = e_arrows;
}
static void xdot_gradient_fillcolor (GVJ_t* job, int filled, pointf* A, int n)
{
    unsigned char buf0[BUFSIZ];
    agxbuf xbuf;
    obj_state_t* obj = job->obj;
    float angle = obj->gradient_angle * M_PI / 180;
    float r1,r2;
    pointf G[2],c1,c2;

    if (xd->version < 14) {
	xdot_fillcolor (job);
	return;
    }

    agxbinit(&xbuf, BUFSIZ, buf0);
    if (filled == GRADIENT) {
	get_gradient_points(A, G, n, angle, 2);
	agxbputc (&xbuf, '[');
	xdot_point (&xbuf, G[0]);
	xdot_point (&xbuf, G[1]);
    }
    else {
	get_gradient_points(A, G, n, 0, 3);
	  //r1 is inner radius, r2 is outer radius
	r1 = G[1].x;
	r2 = G[1].y;
	if (angle == 0) {
	    c1.x = G[0].x;
	    c1.y = G[0].y;
	}
	else {
	    c1.x = G[0].x +  (r2/4) * cos(angle);
	    c1.y = G[0].y +  (r2/4) * sin(angle);
	}
	c2.x = G[0].x;
	c2.y = G[0].y;
	r1 = r2/4;
	agxbputc(&xbuf, '(');
	xdot_point (&xbuf, c1);
	xdot_num (&xbuf, r1);
	xdot_point (&xbuf, c2);
	xdot_num (&xbuf, r2);
    }
    
    agxbput(&xbuf, "2 ");
    if (obj->gradient_frac > 0) {
	xdot_color_stop (&xbuf, obj->gradient_frac, &obj->fillcolor);
	xdot_color_stop (&xbuf, obj->gradient_frac, &obj->stopcolor);
    }
    else {
	xdot_color_stop (&xbuf, 0, &obj->fillcolor);
	xdot_color_stop (&xbuf, 1, &obj->stopcolor);
    }
    agxbpop(&xbuf);
    if (filled == GRADIENT)
	agxbputc(&xbuf, ']');
    else
	agxbputc(&xbuf, ')');
    xdot_str (job, "C ", agxbuse(&xbuf));
    agxbfree(&xbuf);
}