/* make_label: * Assume str is freshly allocated for this instance, so it * can be freed in free_label. */ textlabel_t *make_label(void *obj, char *str, int kind, double fontsize, char *fontname, char *fontcolor) { textlabel_t *rv = NEW(textlabel_t); graph_t *g = NULL, *sg = NULL; node_t *n = NULL; edge_t *e = NULL; char *s; switch (agobjkind(obj)) { case AGRAPH: sg = (graph_t*)obj; g = sg->root; break; case AGNODE: n = (node_t*)obj; g = agroot(agraphof(n)); break; case AGEDGE: e = (edge_t*)obj; g = agroot(agraphof(aghead(e))); break; } rv->fontname = fontname; rv->fontcolor = fontcolor; rv->fontsize = fontsize; rv->charset = GD_charset(g); if (kind & LT_RECD) { rv->text = strdup(str); if (kind & LT_HTML) { rv->html = TRUE; } } else if (kind == LT_HTML) { rv->text = strdup(str); rv->html = TRUE; if (make_html_label(obj, rv)) { switch (agobjkind(obj)) { case AGRAPH: agerr(AGPREV, "in label of graph %s\n",agnameof(sg)); break; case AGNODE: agerr(AGPREV, "in label of node %s\n", agnameof(n)); break; case AGEDGE: agerr(AGPREV, "in label of edge %s %s %s\n", agnameof(agtail(e)), agisdirected(g)?"->":"--", agnameof(aghead(e))); break; } } } else { assert(kind == LT_NONE); /* This call just processes the graph object based escape sequences. The formatting escape * sequences (\n, \l, \r) are processed in make_simple_label. That call also replaces \\ with \. */ rv->text = strdup_and_subst_obj0(str, obj, 0); switch (rv->charset) { case CHAR_LATIN1: s = latin1ToUTF8(rv->text); break; default: /* UTF8 */ s = htmlEntityUTF8(rv->text, g); break; } free(rv->text); rv->text = s; make_simple_label(GD_gvc(g), rv); } return rv; }
/* make_html_label: * Return non-zero if problem parsing HTML. In this case, use object name. */ int make_html_label(void *obj, textlabel_t * lp) { int rv; double wd2, ht2; boxf box; graph_t *g; htmllabel_t *lbl; htmlenv_t env; char *s; env.obj = obj; switch (agobjkind(obj)) { #ifdef WITH_CGRAPH case AGRAPH: #else case AGGRAPH: #endif env.g = ((Agraph_t *) obj)->root; break; case AGNODE: env.g = agraphof(((Agnode_t *) obj)); break; case AGEDGE: env.g = agraphof(aghead (((Agedge_t *) obj))); break; } g = env.g->root; env.finfo.size = lp->fontsize; env.finfo.name = lp->fontname; env.finfo.color = lp->fontcolor; lbl = parseHTML(lp->text, &rv, GD_charset(env.g)); if (!lbl) { /* Parse of label failed; revert to simple text label */ agxbuf xb; unsigned char buf[SMALLBUF]; agxbinit(&xb, SMALLBUF, buf); lp->html = FALSE; lp->text = strdup(nameOf(obj, &xb)); switch (lp->charset) { case CHAR_LATIN1: s = latin1ToUTF8(lp->text); break; default: /* UTF8 */ s = htmlEntityUTF8(lp->text, env.g); break; } free(lp->text); lp->text = s; make_simple_label(g, lp); agxbfree(&xb); return rv; } if (lbl->kind == HTML_TBL) { if (! lbl->u.tbl->data.pencolor && getPenColor(obj)) lbl->u.tbl->data.pencolor = strdup(getPenColor(obj)); rv |= size_html_tbl(g, lbl->u.tbl, NULL, &env); wd2 = (lbl->u.tbl->data.box.UR.x + 1) / 2; ht2 = (lbl->u.tbl->data.box.UR.y + 1) / 2; box = boxfof(-wd2, -ht2, wd2, ht2); pos_html_tbl(lbl->u.tbl, box, BOTTOM | RIGHT | TOP | LEFT); lp->dimen.x = box.UR.x - box.LL.x; lp->dimen.y = box.UR.y - box.LL.y; } else { rv |= size_html_txt(g, lbl->u.txt, &env); wd2 = (lbl->u.txt->box.UR.x + 1) / 2; ht2 = (lbl->u.txt->box.UR.y + 1) / 2; box = boxfof(-wd2, -ht2, wd2, ht2); lbl->u.txt->box = box; lp->dimen.x = box.UR.x - box.LL.x; lp->dimen.y = box.UR.y - box.LL.y; } lp->u.html = lbl; /* If the label is a table, replace label text because this may * be used for the title and alt fields in image maps. */ if (lbl->kind == HTML_TBL) { free (lp->text); lp->text = strdup ("<TABLE>"); } return rv; }