示例#1
0
文件: QGVNode.cpp 项目: swallat/qgv
void QGVNode::updateLayout()
{
        prepareGeometryChange();
        qreal width  = ND_width(_node->node()) * (DotDefaultDPI);
        qreal height = ND_height(_node->node()) * (DotDefaultDPI);

        //Node Position (center)
        qreal gheight = QGVCore::graphHeight(_scene->_graph->graph());
        QPointF pos = QGVCore::centerToOrigin(QGVCore::toPoint(ND_coord(_node->node()), gheight), width, height);
        setPos(pos);

        //Node on top
        setZValue(1);

        //Node path
        if (0 == strcmp(ND_shape(_node->node())->name, "record")) {
                this->is_record = true;
                _record_desc = QGVCore::to_record_label((field_t *) ND_shape_info(_node->node()), width, height);
                _bounding_rect = _record_desc.first().first;
        } else {
                this->is_record = false;
                _path = QGVCore::toPath(ND_shape(_node->node())->name, (polygon_t *) ND_shape_info(_node->node()),
                                        width, height);
                _bounding_rect = _path.boundingRect();
        }
        _pen.setWidth(1);

        _brush.setStyle(QGVCore::toBrushStyle(getAttribute("style")));
        _brush.setColor(QGVCore::toColor(getAttribute("fillcolor")));
        _pen.setColor(QGVCore::toColor(getAttribute("color")));

        setToolTip(getAttribute("tooltip"));
}
示例#2
0
void common_init_node(node_t * n)
{
    struct fontinfo fi;
    char *str;
    ND_width(n) =
	late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH);
    ND_height(n) =
	late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEHEIGHT);
    ND_shape(n) =
	bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE), n);
    str = agxget(n, N_label);
    fi.fontsize = late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE);
    fi.fontname = late_nnstring(n, N_fontname, DEFAULT_FONTNAME);
    fi.fontcolor = late_nnstring(n, N_fontcolor, DEFAULT_COLOR);
    ND_label(n) = make_label((void*)n, str,
	        ((aghtmlstr(str) ? LT_HTML : LT_NONE) | ( (shapeOf(n) == SH_RECORD) ? LT_RECD : LT_NONE)),
		fi.fontsize, fi.fontname, fi.fontcolor);
    if (N_xlabel && (str = agxget(n, N_xlabel)) && (str[0])) {
	ND_xlabel(n) = make_label((void*)n, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				fi.fontsize, fi.fontname, fi.fontcolor);
	GD_has_labels(agraphof(n)) |= NODE_XLABEL;
    }

    ND_showboxes(n) = late_int(n, N_showboxes, 0, 0);
    ND_shape(n)->fns->initfn(n);
}
示例#3
0
static void ptest_initNode(node_t * n)
{
    char *str;
    ND_width(n) =
	late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH);
    ND_height(n) =
	late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEWIDTH);
    if (N_label == NULL)
	str = NODENAME_ESC;
    else
	str = agxget(n, N_label->index);
    str = strdup_and_subst(str, NODENAME_ESC, n->name);
    ND_label(n) = make_label(str,
			     late_double(n, N_fontsize, DEFAULT_FONTSIZE,
					 MIN_FONTSIZE), late_nnstring(n,
								      N_fontname,
								      DEFAULT_FONTNAME),
			     late_nnstring(n, N_fontcolor, DEFAULT_COLOR),
			     n->graph);
    ND_shape(n) = bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE));
    ND_shape(n)->initfn(n);	/* ### need to quantize ? */
    ptest_nodesize(n, n->GD_flip(graph));


}
示例#4
0
static void twopi_cleanup_node(node_t * n)
{
    free(ND_alg(n));
    if (ND_shape(n))
	ND_shape(n)->fns->freefn(n);
    free_label(ND_label(n));
    memset(&(n->u), 0, sizeof(Agnodeinfo_t));
}
示例#5
0
void neato_cleanup_node(node_t * n)
{
    if (ND_shape(n)) {
	ND_shape(n)->fns->freefn(n);
    }
    free(ND_pos(n));
    free_label(ND_label(n));
    memset(&(n->u), 0, sizeof(Agnodeinfo_t));
}
示例#6
0
static void 
dot_cleanup_node(node_t * n)
{
    free_list(ND_in(n));
    free_list(ND_out(n));
    free_list(ND_flat_out(n));
    free_list(ND_flat_in(n));
    free_list(ND_other(n));
    free_label(ND_label(n));
    if (ND_shape(n))
	ND_shape(n)->fns->freefn(n);
    memset(&(n->u), 0, sizeof(Agnodeinfo_t));
}
示例#7
0
static void 
dot_cleanup_node(node_t * n)
{
    free_list(ND_in(n));
    free_list(ND_out(n));
    free_list(ND_flat_out(n));
    free_list(ND_flat_in(n));
    free_list(ND_other(n));
    free_label(ND_label(n));
    free_label(ND_xlabel(n));
    if (ND_shape(n))
	ND_shape(n)->fns->freefn(n);
    agdelrec(n, "Agnodeinfo_t");	
}
示例#8
0
static void 
dot_cleanup_node(node_t * n)
{
    free_list(ND_in(n));
    free_list(ND_out(n));
    free_list(ND_flat_out(n));
    free_list(ND_flat_in(n));
    free_list(ND_other(n));
    free_label(ND_label(n));
    if (ND_shape(n))
	ND_shape(n)->fns->freefn(n);
#ifndef WITH_CGRAPH
    memset(&(n->u), 0, sizeof(Agnodeinfo_t));
#else /* WITH_CGRAPH */
	agclean(agraphof(n), AGNODE,"Agnodeinfo_t");	
#endif /* WITH_CGRAPH */
}
示例#9
0
void common_init_node(node_t * n)
{
    char *str;
    int html = 0;

    ND_width(n) =
	late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH);
    ND_height(n) =
	late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEHEIGHT);
    if (N_label == NULL)
	str = NODENAME_ESC;
    else {
	str = agxget(n, N_label->index);
	html = aghtmlstr(str);
    }
    if (html)
	str = strdup(str);
    else
	str = strdup_and_subst_node(str, n);
    ND_label(n) = make_label(html, str,
			     late_double(n, N_fontsize, DEFAULT_FONTSIZE,
					 MIN_FONTSIZE), late_nnstring(n,
								      N_fontname,
								      DEFAULT_FONTNAME),
			     late_nnstring(n, N_fontcolor, DEFAULT_COLOR),
			     n->graph);

#ifdef ENABLE_HTML //maks
    if (html) {
	if (make_html_label(ND_label(n), n) == 1)
	    agerr(AGPREV, "in label of node %s\n", n->name);
    }
#endif

    ND_shape(n) =
	bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE), n);
    ND_showboxes(n) = late_int(n, N_showboxes, 0, 0);
    ND_shape(n)->fns->initfn(n);
}
示例#10
0
文件: vtxgen.c 项目: ekoontz/graphviz
static void vtx_begin_node(node_t * n)
{
    shapemap_t *p;

    for (p = shapemap; p->shape; p++) {
	if (streq(ND_shape(n)->name, p->shape)) {
	    break;
	}
    }
    fprintf(Output_file, "  (shape\n"
	    "    (id %d)\n"
	    "    (layer %d)\n"
	    "    (type %s)\n", n->id + 1, n->id, p->vtxshape);
}
示例#11
0
文件: output.c 项目: emdenrg/graphviz
/* _write_plain:
 */
void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend)
{
    int i, j, splinePoints;
    char *tport, *hport;
    node_t *n;
    edge_t *e;
    bezier bz;
    pointf pt;
    char *lbl;
    char* fillcolor;

#ifdef WITH_CGRAPH
    putstr = g->clos->disc.io->putstr;
#endif
//    setup_graph(job, g);
    setYInvert(g);
    pt = GD_bb(g).UR;
    printdouble(f, "graph ", job->zoom);
    printdouble(f, " ", PS2INCH(pt.x));
    printdouble(f, " ", PS2INCH(pt.y));
    agputc('\n', f);
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (IS_CLUST_NODE(n))
	    continue;
	printstring(f, "node ", agcanonStr(agnameof(n)));
	printpoint(f, ND_coord(n));
	if (ND_label(n)->html)   /* if html, get original text */
#ifndef WITH_CGRAPH
	    lbl = agcanonStr (agxget(n, N_label->index));
#else
	    lbl = agcanonStr (agxget(n, N_label));
#endif
	else
	    lbl = canon(agraphof(n),ND_label(n)->text);
        printdouble(f, " ", ND_width(n));
        printdouble(f, " ", ND_height(n));
        printstring(f, " ", lbl);
	printstring(f, " ", late_nnstring(n, N_style, "solid"));
	printstring(f, " ", ND_shape(n)->name);
	printstring(f, " ", late_nnstring(n, N_color, DEFAULT_COLOR));
	fillcolor = late_nnstring(n, N_fillcolor, "");
        if (fillcolor[0] == '\0')
	    fillcolor = late_nnstring(n, N_color, DEFAULT_FILL);
	printstring(f, " ", fillcolor);
	agputc('\n', f);
    }
示例#12
0
//------------------------------------------------------------------------------
// Name: make_shape
// Desc:
//------------------------------------------------------------------------------
QPainterPath GraphNode::make_shape(node_t *node) const {
	QPainterPath path;

	const QString name = QString::fromUtf8(agnameof(ND_shape(node)));

	// TODO: point, egg, doublecircle, doubleoctagon, tripleoctagon,
	// note, tab, folder, box3d, component, record, plaintext

	// handle all of the "regular" polygons
	if(     name == "invhouse"      ||
			name == "invtrapezium"  ||
			name == "invtriangle"   ||
			name == "box"           ||
			name == "polygon"       ||
			name == "triangle"      ||
			name == "diamond"       ||
			name == "trapezium"     ||
			name == "parallelogram" ||
			name == "house"         ||
			name == "pentagon"      ||
			name == "hexagon"       ||
			name == "septagon"      ||
			name == "octagon"       ||
			name == "rect"          ||
			name == "rectangle"     ||
			name == "Msquare"       || // incomplete
			name == "Mdiamond"         // incomplete
			) {

		make_polygon_helper(node, path);
	} else if(name == "ellipse" || name == "circle" || name == "point" || name == "Mcircle") {
		make_ellipse_helper(node, path);
	} else if(name == "none") {
		// NO-OP
	} else {
		qWarning("unsupported shape %s", qPrintable(name));
	}

	return path;
}
示例#13
0
文件: QGVNode.cpp 项目: aszczesn/qgv
void QGVNode::updateLayout()
{
    prepareGeometryChange();
		qreal width = ND_width(_node->node())*DotDefaultDPI;
		qreal height = ND_height(_node->node())*DotDefaultDPI;

    //Node Position (center)
		qreal gheight = QGVCore::graphHeight(_scene->_graph->graph());
		setPos(QGVCore::centerToOrigin(QGVCore::toPoint(ND_coord(_node->node()), gheight), width, height));

    //Node on top
    setZValue(1);

    //Node path
		_path = QGVCore::toPath(ND_shape(_node->node())->name, (polygon_t*)ND_shape_info(_node->node()), width, height);
    _pen.setWidth(1);

    _brush.setStyle(QGVCore::toBrushStyle(getAttribute("style")));
    _brush.setColor(QGVCore::toColor(getAttribute("fillcolor")));
    _pen.setColor(QGVCore::toColor(getAttribute("color")));

    setToolTip(getAttribute("tooltip"));
}
示例#14
0
文件: poly.c 项目: TidyHuang/vizgems
int makePoly(Poly * pp, Agnode_t * n, float xmargin, float ymargin)
{
    int i;
    int sides;
    Point *verts;
    polygon_t *poly;
    boxf b;

    if (ND_clust(n)) {
	Point b;
	sides = 4;
	b.x = ND_width(n) / 2.0;
	b.y = ND_height(n) / 2.0;
	pp->kind = BOX;
	verts = N_GNEW(sides, Point);
	PUTPT(verts[0], b.x, b.y);
	PUTPT(verts[1], -b.x, b.y);
	PUTPT(verts[2], -b.x, -b.y);
	PUTPT(verts[3], b.x, -b.y);
    } else
	switch (shapeOf(n)) {
	case SH_POLY:
	    poly = (polygon_t *) ND_shape_info(n);
	    sides = poly->sides;
	    if (sides >= 3) {	/* real polygon */
		verts = N_GNEW(sides, Point);
		for (i = 0; i < sides; i++) {
		    verts[i].x = PS2INCH(poly->vertices[i].x);
		    verts[i].y = PS2INCH(poly->vertices[i].y);
		}
	    } else
		verts = genRound(n, &sides, 0, 0);

	    if (streq(ND_shape(n)->name, "box"))
		pp->kind = BOX;
	    else if (streq(ND_shape(n)->name, "polygon")
		     && isBox(verts, sides))
		pp->kind = BOX;
	    else if ((poly->sides < 3) && poly->regular)
		pp->kind = CIRCLE;
	    else
		pp->kind = 0;

	    break;
	case SH_RECORD:
	    sides = 4;
	    verts = N_GNEW(sides, Point);
	    b = ((field_t *) ND_shape_info(n))->b;
	    verts[0] = makeScaledPoint(b.LL.x, b.LL.y);
	    verts[1] = makeScaledPoint(b.UR.x, b.LL.y);
	    verts[2] = makeScaledPoint(b.UR.x, b.UR.y);
	    verts[3] = makeScaledPoint(b.LL.x, b.UR.y);
	    pp->kind = BOX;
	    break;
	case SH_POINT:
	    pp->kind = CIRCLE;
	    verts = genRound(n, &sides, 0, 0);
	    break;
	default:
	    agerr(AGERR, "makePoly: unknown shape type %s\n",
		  ND_shape(n)->name);
	    return 1;
	}

#ifdef OLD
    if (margin != 0.0)
	inflatePts(verts, sides, margin);
#else
    if ((xmargin != 1.0) || (ymargin != 1.0))
	inflatePts(verts, sides, xmargin, ymargin);
#endif

    pp->verts = verts;
    pp->nverts = sides;
    bbox(verts, sides, &pp->origin, &pp->corner);

    if (sides > maxcnt)
	maxcnt = sides;
    return 0;
}
示例#15
0
/* return true if edge has label */
int common_init_edge(edge_t * e)
{
    char *str;
    int r = 0;
    struct fontinfo fi;
    struct fontinfo lfi;
    graph_t *sg = agraphof(agtail(e));

    fi.fontname = NULL;
    lfi.fontname = NULL;
    if (E_label && (str = agxget(e, E_label)) && (str[0])) {
	r = 1;
	initFontEdgeAttr(e, &fi);
	ED_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				fi.fontsize, fi.fontname, fi.fontcolor);
	GD_has_labels(sg) |= EDGE_LABEL;
	ED_label_ontop(e) =
	    mapbool(late_string(e, E_label_float, "false"));
    }

    if (E_xlabel && (str = agxget(e, E_xlabel)) && (str[0])) {
	if (!fi.fontname)
	    initFontEdgeAttr(e, &fi);
	ED_xlabel(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				fi.fontsize, fi.fontname, fi.fontcolor);
	GD_has_labels(sg) |= EDGE_XLABEL;
    }


    /* vladimir */
    if (E_headlabel && (str = agxget(e, E_headlabel)) && (str[0])) {
	initFontLabelEdgeAttr(e, &fi, &lfi);
	ED_head_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				lfi.fontsize, lfi.fontname, lfi.fontcolor);
	GD_has_labels(sg) |= HEAD_LABEL;
    }
    if (E_taillabel && (str = agxget(e, E_taillabel)) && (str[0])) {
	if (!lfi.fontname)
	    initFontLabelEdgeAttr(e, &fi, &lfi);
	ED_tail_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				lfi.fontsize, lfi.fontname, lfi.fontcolor);
	GD_has_labels(sg) |= TAIL_LABEL;
    }
    /* end vladimir */

    /* We still accept ports beginning with colons but this is deprecated 
     * That is, we allow tailport = ":abc" as well as the preferred 
     * tailport = "abc".
     */
    str = agget(e, TAIL_ID);
    /* libgraph always defines tailport/headport; libcgraph doesn't */
    if (!str) str = "";
    if (str && str[0])
	ND_has_port(agtail(e)) = TRUE;
    ED_tail_port(e) = chkPort (ND_shape(agtail(e))->fns->portfn, agtail(e), str);
    if (noClip(e, E_tailclip))
	ED_tail_port(e).clip = FALSE;
    str = agget(e, HEAD_ID);
    /* libgraph always defines tailport/headport; libcgraph doesn't */
    if (!str) str = "";
    if (str && str[0])
	ND_has_port(aghead(e)) = TRUE;
    ED_head_port(e) = chkPort(ND_shape(aghead(e))->fns->portfn, aghead(e), str);
    if (noClip(e, E_headclip))
	ED_head_port(e).clip = FALSE;

    return r;
}
示例#16
0
/* return TRUE if edge has label */
int common_init_edge(edge_t * e)
{
    char *s;
    int html = 0, r = 0;
    struct fontinfo fi;
    struct fontinfo lfi;

    fi.fontname = NULL;
    lfi.fontname = NULL;
    if (E_label && (s = agxget(e, E_label->index)) && (s[0])) {
	r = 1;
	html = aghtmlstr(s);
	if (html)
	    s = strdup(s);
	else
	    s = strdup_and_subst_edge(s, e);
	initFontEdgeAttr(e, &fi);
	ED_label(e) = make_label(html, s,
				 fi.fontsize, fi.fontname, fi.fontcolor,
				 e->tail->graph);
	
#ifdef ENABLE_HTML //maks
	if (html) {
	    if (make_html_label(ED_label(e), e) == 1)
		edgeError(e, "label");
	}
#endif

	GD_has_labels(e->tail->graph) |= EDGE_LABEL;
	ED_label_ontop(e) =
	    mapbool(late_string(e, E_label_float, "false"));
    }


    /* vladimir */
    if (E_headlabel && (s = agxget(e, E_headlabel->index)) && (s[0])) {
	html = aghtmlstr(s);
	if (html)
	    s = strdup(s);
	else
	    s = strdup_and_subst_edge(s, e);
	initFontLabelEdgeAttr(e, &fi, &lfi);
	ED_head_label(e) = make_label(html, s,
				      lfi.fontsize, lfi.fontname,
				      lfi.fontcolor, e->tail->graph);
	
#ifdef ENABLE_HTML //maks
	if (html) {
	    if (make_html_label(ED_head_label(e), e) == 1)
		edgeError(e, "head label");
	}
#endif

	GD_has_labels(e->tail->graph) |= HEAD_LABEL;
    }
    if (E_taillabel && (s = agxget(e, E_taillabel->index)) && (s[0])) {
	html = aghtmlstr(s);
	if (html)
	    s = strdup(s);
	else
	    s = strdup_and_subst_edge(s, e);
	if (!lfi.fontname)
	    initFontLabelEdgeAttr(e, &fi, &lfi);
	ED_tail_label(e) = make_label(html, s,
				      lfi.fontsize, lfi.fontname,
				      lfi.fontcolor, e->tail->graph);

#ifdef ENABLE_HTML //maks
	if (html) {
	    if (make_html_label(ED_tail_label(e), e) == 1)
		edgeError(e, "tail label");
	}
#endif

	GD_has_labels(e->tail->graph) |= TAIL_LABEL;
    }
    /* end vladimir */

    /* We still accept ports beginning with colons but this is deprecated */
    s = agget(e, TAIL_ID);
    if (s[0])
	ND_has_port(e->tail) = TRUE;
    ED_tail_port(e) = chkPort (ND_shape(e->tail)->fns->portfn,e->tail, s);
    if (noClip(e, E_tailclip))
	ED_tail_port(e).clip = FALSE;
    s = agget(e, HEAD_ID);
    if (s[0])
	ND_has_port(e->head) = TRUE;
    ED_head_port(e) = chkPort(ND_shape(e->head)->fns->portfn,e->head, s);
    if (noClip(e, E_headclip))
	ED_head_port(e).clip = FALSE;

    return r;
}
示例#17
0
文件: poly.c 项目: TidyHuang/vizgems
int makeAddPoly(Poly * pp, Agnode_t * n, float xmargin, float ymargin)
{
    int i;
    int sides;
    Point *verts;
    polygon_t *poly;
    boxf b;

    if (ND_clust(n)) {
	Point b;
	sides = 4;
	b.x = ND_width(n) / 2.0 + xmargin;
	b.y = ND_height(n) / 2.0 + ymargin;
	pp->kind = BOX;
	verts = N_GNEW(sides, Point);
	PUTPT(verts[0], b.x, b.y);
	PUTPT(verts[1], -b.x, b.y);
	PUTPT(verts[2], -b.x, -b.y);
	PUTPT(verts[3], b.x, -b.y);
    } else
	switch (shapeOf(n)) {
	case SH_POLY:
	    poly = (polygon_t *) ND_shape_info(n);
	    sides = poly->sides;

	    if (streq(ND_shape(n)->name, "box"))
		pp->kind = BOX;
	    else if (streq(ND_shape(n)->name, "polygon")
		     && isBox(poly->vertices, sides))
		pp->kind = BOX;
	    else if ((poly->sides < 3) && poly->regular)
		pp->kind = CIRCLE;
	    else
		pp->kind = 0;

	    if (sides >= 3) {	/* real polygon */
		verts = N_GNEW(sides, Point);
		if (pp->kind == BOX) {
			/* To do an additive margin, we rely on knowing that
			 * the vertices are CCW starting from the UR
			 */
		    verts[0].x = PS2INCH(poly->vertices[0].x) + xmargin;
		    verts[0].y = PS2INCH(poly->vertices[0].y) + ymargin;
		    verts[1].x = PS2INCH(poly->vertices[1].x) - xmargin;
		    verts[1].y = PS2INCH(poly->vertices[1].y) + ymargin;
		    verts[2].x = PS2INCH(poly->vertices[2].x) - xmargin;
		    verts[2].y = PS2INCH(poly->vertices[2].y) - ymargin;
		    verts[3].x = PS2INCH(poly->vertices[3].x) + xmargin;
		    verts[3].y = PS2INCH(poly->vertices[3].y) - ymargin;
 
		}
		else {
		    for (i = 0; i < sides; i++) {
                        double h = LEN(poly->vertices[i].x,poly->vertices[i].y);
		        verts[i].x = poly->vertices[i].x * (1.0 + xmargin/h);
		        verts[i].y = poly->vertices[i].y * (1.0 + ymargin/h);
		        verts[i].x = PS2INCH(verts[i].x);
		        verts[i].y = PS2INCH(verts[i].y);
		    }
		}
	    } else
		verts = genRound(n, &sides, xmargin, ymargin);
	    break;
	case SH_RECORD:
	    sides = 4;
	    verts = N_GNEW(sides, Point);
	    b = ((field_t *) ND_shape_info(n))->b;
	    verts[0] = makeScaledTransPoint(b.LL.x, b.LL.y, -xmargin, -ymargin);
	    verts[1] = makeScaledTransPoint(b.UR.x, b.LL.y, xmargin, -ymargin);
	    verts[2] = makeScaledTransPoint(b.UR.x, b.UR.y, xmargin, ymargin);
	    verts[3] = makeScaledTransPoint(b.LL.x, b.UR.y, -xmargin, ymargin);
	    pp->kind = BOX;
	    break;
	case SH_POINT:
	    pp->kind = CIRCLE;
	    verts = genRound(n, &sides, xmargin, ymargin);
	    break;
	default:
	    agerr(AGERR, "makeAddPoly: unknown shape type %s\n",
		  ND_shape(n)->name);
	    return 1;
	}

    pp->verts = verts;
    pp->nverts = sides;
    bbox(verts, sides, &pp->origin, &pp->corner);

    if (sides > maxcnt)
	maxcnt = sides;
    return 0;
}
示例#18
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);
}
示例#19
0
/* 
 * John M. suggests:
 * You might want to add four more:
 *
 * _ohdraw_ (optional head-end arrow for edges)
 * _ohldraw_ (optional head-end label for edges)
 * _otdraw_ (optional tail-end arrow for edges)
 * _otldraw_ (optional tail-end label for edges)
 * 
 * that would be generated when an additional option is supplied to 
 * dot, etc. and 
 * these would be the arrow/label positions to use if a user want to flip the 
 * direction of an edge (as sometimes is there want).
 * 
 * N.B. John M. asks:
 *   By the way, I don't know if you ever plan to add other letters for 
 * the xdot spec, but could you reserve "a" and also "A" (for  attribute), 
 * "n" and also "N" (for numeric), "w" (for sWitch),  "s" (for string) 
 * and "t" (for tooltip) and "x" (for position). We use  those letters in 
 * our drawing spec (and also "<" and ">"), so if you  start generating 
 * output with them, it could break what we have. 
 */
void extend_attrs(GVJ_t * job, graph_t *g, int s_arrows, int e_arrows)
{
    node_t *n;
    edge_t *e;
    attrsym_t *n_draw = NULL;
    attrsym_t *n_l_draw = NULL;
    attrsym_t *e_draw = NULL;
    attrsym_t *h_draw = NULL;
    attrsym_t *t_draw = NULL;
    attrsym_t *e_l_draw = NULL;
    attrsym_t *hl_draw = NULL;
    attrsym_t *tl_draw = NULL;
    unsigned char buf0[BUFSIZ];
    unsigned char buf1[BUFSIZ];
    unsigned char buf2[BUFSIZ];
    unsigned char buf3[BUFSIZ];
    unsigned char buf4[BUFSIZ];
    unsigned char buf5[BUFSIZ];

    gvc = job->gvc;

    agsafeset (g, "xdotversion", XDOTVERSION, "");
    if (GD_has_labels(g) & GRAPH_LABEL)
	g_l_draw = safe_dcl(g, g, "_ldraw_", "", agraphattr);
    else
	g_l_draw = NULL;
    if (GD_n_cluster(g))
	g_draw = safe_dcl(g, g, "_draw_", "", agraphattr);
    else
	g_draw = NULL;

    n_draw = safe_dcl(g, g->proto->n, "_draw_", "", agnodeattr);
    n_l_draw = safe_dcl(g, g->proto->n, "_ldraw_", "", agnodeattr);

    e_draw = safe_dcl(g, g->proto->e, "_draw_", "", agedgeattr);
    if (e_arrows)
	h_draw = safe_dcl(g, g->proto->e, "_hdraw_", "", agedgeattr);
    if (s_arrows)
	t_draw = safe_dcl(g, g->proto->e, "_tdraw_", "", agedgeattr);
    if (GD_has_labels(g) & EDGE_LABEL)
	e_l_draw = safe_dcl(g, g->proto->e, "_ldraw_", "", agedgeattr);
    if (GD_has_labels(g) & HEAD_LABEL)
	hl_draw = safe_dcl(g, g->proto->e, "_hldraw_", "", agedgeattr);
    if (GD_has_labels(g) & TAIL_LABEL)
	tl_draw = safe_dcl(g, g->proto->e, "_tldraw_", "", agedgeattr);

    agxbinit(&xbuf0, BUFSIZ, buf0);
    agxbinit(&xbuf1, BUFSIZ, buf1);
    agxbinit(&xbuf2, BUFSIZ, buf2);
    agxbinit(&xbuf3, BUFSIZ, buf3);
    agxbinit(&xbuf4, BUFSIZ, buf4);
    agxbinit(&xbuf5, BUFSIZ, buf5);

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (ND_shape(n) && !isInvis(late_string(n, N_style, ""))) {
	    ND_shape(n)->fns->codefn(job, n);
	    agxset(n, n_draw->index, agxbuse(xbufs[EMIT_NDRAW]));
	    agxset(n, n_l_draw->index, agxbuse(xbufs[EMIT_NLABEL]));
	}
	if (State < GVSPLINES)
	    continue;
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    if (ED_edge_type(e) == IGNORED)
		continue;
	    if (isInvis(late_string(e, E_style, "")))
		continue;
	    if (ED_spl(e) == NULL)
		continue;

	    emit_edge_graphics (job, e);
	    agxset(e, e_draw->index, agxbuse(xbufs[EMIT_EDRAW]));
	    if (t_draw) agxset(e, t_draw->index, agxbuse(xbufs[EMIT_TDRAW]));
	    if (h_draw) agxset(e, h_draw->index, agxbuse(xbufs[EMIT_HDRAW]));
	    if (e_l_draw) agxset(e, e_l_draw->index,agxbuse(xbufs[EMIT_ELABEL]));
	    if (tl_draw) agxset(e, tl_draw->index, agxbuse(xbufs[EMIT_TLABEL]));
	    if (hl_draw) agxset(e, hl_draw->index, agxbuse(xbufs[EMIT_HLABEL]));
	}
    }
  
    emit_background(job, g);
    if (agxblen(xbufs[EMIT_GDRAW])) {
	if (!g_draw)
	    g_draw = safe_dcl(g, g, "_draw_", "", agraphattr);
	agxset(g, g_draw->index, agxbuse(xbufs[EMIT_GDRAW]));
    }
    if (GD_label(g)) {
	emit_label(job, EMIT_GLABEL, GD_label(g), (void *) g);
	agxset(g, g_l_draw->index, agxbuse(xbufs[EMIT_GLABEL]));
    }
    emit_clusters(job, g, 0);
    agxbfree(&xbuf0);
    agxbfree(&xbuf1);
    agxbfree(&xbuf2);
    agxbfree(&xbuf3);
    agxbfree(&xbuf4);
    agxbfree(&xbuf5);
}
示例#20
0
文件: output.c 项目: Chaduke/bah.mod
/* _write_plain:
 */
void write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend)
{
    int i, j, splinePoints;
    char *tport, *hport;
    node_t *n;
    edge_t *e;
    bezier bz;
    point pt;
    char *lbl;

//    setup_graph(job, g);
    setYInvert(g);
    pt = GD_bb(g).UR;
    fprintf(f, "graph %.3f %.3f %.3f\n", job->zoom, PS2INCH(pt.x), PS2INCH(pt.y));
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (IS_CLUST_NODE(n))
	    continue;
	fprintf(f, "node %s ", agcanonical(n->name));
	printptf(f, ND_coord_i(n));
	if (ND_label(n)->html)   /* if html, get original text */
	    lbl = agxget(n, N_label->index);
	else
	    lbl = ND_label(n)->text;
	if (lbl)
	    lbl = agcanonical(lbl);
	else
	    lbl = "\"\"";
	fprintf(f, " %.3f %.3f %s %s %s %s %s\n",
		ND_width(n), ND_height(n), lbl,
		late_nnstring(n, N_style, "solid"),
		ND_shape(n)->name,
		late_nnstring(n, N_color, DEFAULT_COLOR),
		late_nnstring(n, N_fillcolor, DEFAULT_FILL));
    }
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    if (extend && e->attr) {
		tport = e->attr[TAILX];
		hport = e->attr[HEADX];
	    } else
		tport = hport = "";
	    if (ED_spl(e)) {
		splinePoints = 0;
		for (i = 0; i < ED_spl(e)->size; i++) {
		    bz = ED_spl(e)->list[i];
		    splinePoints += bz.size;
		}
		fprintf(f, "edge ");
		writenodeandport(f, e->tail, tport);
		fprintf(f, " ");
		writenodeandport(f, e->head, hport);
		fprintf(f, " %d", splinePoints);
		for (i = 0; i < ED_spl(e)->size; i++) {
		    bz = ED_spl(e)->list[i];
		    for (j = 0; j < bz.size; j++)
			printptf(f, bz.list[j]);
		}
	    }
	    if (ED_label(e)) {
		fprintf(f, " %s", agcanonical(ED_label(e)->text));
		printptf(f, ED_label(e)->p);
	    }
	    fprintf(f, " %s %s\n", late_nnstring(e, E_style, "solid"),
		    late_nnstring(e, E_color, DEFAULT_COLOR));
	}
    }
    fprintf(f, "stop\n");
}
示例#21
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;
}
示例#22
0
/* _write_plain:
 */
void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend)
{
    int i, j, splinePoints;
    char *tport, *hport;
    node_t *n;
    edge_t *e;
    bezier bz;
    pointf pt;
    char *lbl;
    char* fillcolor;

    putstr = g->clos->disc.io->putstr;
//    setup_graph(job, g);
    setYInvert(g);
    pt = GD_bb(g).UR;
    printdouble(f, "graph ", job->zoom);
    printdouble(f, " ", PS2INCH(pt.x));
    printdouble(f, " ", PS2INCH(pt.y));
    agputc('\n', f);
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (IS_CLUST_NODE(n))
	    continue;
	printstring(f, "node ", agcanonStr(agnameof(n)));
	printpoint(f, ND_coord(n));
	if (ND_label(n)->html)   /* if html, get original text */
	    lbl = agcanonStr (agxget(n, N_label));
	else
	    lbl = canon(agraphof(n),ND_label(n)->text);
        printdouble(f, " ", ND_width(n));
        printdouble(f, " ", ND_height(n));
        printstring(f, " ", lbl);
	printstring(f, " ", late_nnstring(n, N_style, "solid"));
	printstring(f, " ", ND_shape(n)->name);
	printstring(f, " ", late_nnstring(n, N_color, DEFAULT_COLOR));
	fillcolor = late_nnstring(n, N_fillcolor, "");
        if (fillcolor[0] == '\0')
	    fillcolor = late_nnstring(n, N_color, DEFAULT_FILL);
	printstring(f, " ", fillcolor);
	agputc('\n', f);
    }
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {

	    if (extend) {		//assuming these two attrs have already been created by cgraph
		if (!(tport = agget(e,"tailport")))
		    tport = "";
		if (!(hport = agget(e,"headport")))
		    hport = "";
	    }
	    else
		tport = hport = "";
	    if (ED_spl(e)) {
		splinePoints = 0;
		for (i = 0; i < ED_spl(e)->size; i++) {
		    bz = ED_spl(e)->list[i];
		    splinePoints += bz.size;
		}
		printstring(f, NULL, "edge");
		writenodeandport(f, agtail(e), tport);
		writenodeandport(f, aghead(e), hport);
		printint(f, " ", splinePoints);
		for (i = 0; i < ED_spl(e)->size; i++) {
		    bz = ED_spl(e)->list[i];
		    for (j = 0; j < bz.size; j++)
			printpoint(f, bz.list[j]);
		}
	    }
	    if (ED_label(e)) {
		printstring(f, " ", canon(agraphof(agtail(e)),ED_label(e)->text));
		printpoint(f, ED_label(e)->pos);
	    }
	    printstring(f, " ", late_nnstring(e, E_style, "solid"));
	    printstring(f, " ", late_nnstring(e, E_color, DEFAULT_COLOR));
	    agputc('\n', f);
	}
    }
    agputs("stop\n", f);
}