return rv;
}
+static int cell_halignfn(htmldata_t * p, char *v)
+{
+ int rv = 0;
+ char c = toupper(*v);
+ if ((c == 'L') && !strcasecmp(v + 1, "EFT"))
+ p->flags |= HALIGN_LEFT;
+ else if ((c == 'R') && !strcasecmp(v + 1, "IGHT"))
+ p->flags |= HALIGN_RIGHT;
+ else if ((c == 'T') && !strcasecmp(v + 1, "EXT"))
+ p->flags |= HALIGN_TEXT;
+ else if ((c != 'C') || strcasecmp(v + 1, "ENTER"))
+ rv = 1;
+ if (rv)
+ agerr(AGWARN, "Illegal value %s for ALIGN in TD - ignored\n", v);
+ return rv;
+}
+
+static int balignfn(htmldata_t * p, char *v)
+{
+ int rv = 0;
+ char c = toupper(*v);
+ if ((c == 'L') && !strcasecmp(v + 1, "EFT"))
+ p->flags |= BALIGN_LEFT;
+ else if ((c == 'R') && !strcasecmp(v + 1, "IGHT"))
+ p->flags |= BALIGN_RIGHT;
+ else if ((c != 'C') || strcasecmp(v + 1, "ENTER"))
+ rv = 1;
+ if (rv)
+ agerr(AGWARN, "Illegal value %s for BALIGN in TD - ignored\n", v);
+ return rv;
+}
+
static int heightfn(htmldata_t * p, char *v)
{
long u;
*p = 'r';
else if ((c == 'L') || !strcasecmp(v + 1, "EFT"))
*p = 'l';
- else if ((c != 'C') && strcasecmp(v + 1, "ENTER")) {
+ else if ((c == 'C') || strcasecmp(v + 1, "ENTER"))
+ *p = 'n';
+ else {
agerr(AGWARN, "Illegal value %s for ALIGN - ignored\n", v);
rv = 1;
}
};
static attr_item cell_items[] = {
- {"align", (attrFn) halignfn},
+ {"align", (attrFn) cell_halignfn},
+ {"balign", (attrFn) balignfn},
{"bgcolor", (attrFn) bgcolorfn},
{"border", (attrFn) borderfn},
{"cellpadding", (attrFn) cellpaddingfn},
static void mkBR(char **atts)
{
- htmllval.i = 'n';
+ htmllval.i = UNSET_ALIGN;
doAttrs(&htmllval.i, br_items, sizeof(br_items) / ISIZE, atts, "<BR>");
}
static void characterData(void *user, const char *s, int length)
{
int i;
+ int cnt = 0;
unsigned char c;
if (state.inCell) {
for (i = length; i; i--) {
c = *s++;
if (c >= ' ') {
+ cnt++;
agxbputc(state.xb, c);
}
}
- state.tok = T_string;
+ if (cnt) state.tok = T_string;
}
}
#endif
extern int yyparse(void);
+typedef struct sfont_t {
+ htmlfont_t *cfont;
+ struct sfont_t *pfont;
+} sfont_t;
+
static struct {
htmllabel_t* lbl; /* Generated label */
htmltbl_t* tblstack; /* Stack of tables maintained during parsing */
+#ifdef OLD
Dt_t* lines; /* Dictionary for lines of text */
+#endif
+ Dt_t* fitemList; /* Dictionary for font text items */
+ Dt_t* flineList;
agxbuf* str; /* Buffer for text */
+ sfont_t* fontstack;
} HTMLstate;
/* free_ritem:
free (p);
}
-/* free_ritem:
- * Free cell item after cell has been copies into final table.
- * Only the pitem is freed.
+/* free_item:
+ * Generic Dt free. Only frees container, assuming contents
+ * have been copied elsewhere.
*/
static void
-free_item(Dt_t* d, pitem* p,Dtdisc_t* ds)
+free_item(Dt_t* d, void* p,Dtdisc_t* ds)
{
free (p);
}
NIL(Dtevent_f)
};
+#ifdef OLD
typedef struct {
Dtlink_t link;
const char* s; /* line of text */
char c; /* alignment of text */
} sitem;
+#endif
+
+typedef struct {
+ Dtlink_t link;
+ textitem_t ti;
+} fitem;
+
+typedef struct {
+ Dtlink_t link;
+ htextline_t lp;
+} fline;
+#ifdef OLD
static void
-free_sitem(Dt_t* d,sitem* p,Dtdisc_t* ds)
+free_sitem(Dt_t* d, sitem* p,Dtdisc_t* ds)
{
free (p);
}
+#endif
+
+static void
+free_fitem(Dt_t* d, fitem* p, Dtdisc_t* ds)
+{
+ if (p->ti.str)
+ free (p->ti.str);
+ if (p->ti.font)
+ free_html_font (p->ti.font);
+ free (p);
+}
+
+static void
+free_fline(Dt_t* d, fline* p, Dtdisc_t* ds)
+{
+ textitem_t* ti;
+
+ if (p->lp.nitems) {
+ int i;
+ ti = p->lp.items;
+ for (i = 0; i < p->lp.nitems; i++) {
+ if (ti->str) free (ti->str);
+ if (ti->font) free_html_font (ti->font);
+ ti++;
+ }
+ free (p->lp.items);
+ }
+ free (p);
+}
+#ifdef OLD
static Dtdisc_t strDisc = {
offsetof(sitem,s),
sizeof(char*),
NIL(Dtmemory_f),
NIL(Dtevent_f)
};
+#endif
+
+static Dtdisc_t fstrDisc = {
+ 0,
+ 0,
+ offsetof(fitem,link),
+ NIL(Dtmake_f),
+ (Dtfree_f)free_item,
+ NIL(Dtcompar_f),
+ NIL(Dthash_f),
+ NIL(Dtmemory_f),
+ NIL(Dtevent_f)
+};
+
+static Dtdisc_t flineDisc = {
+ 0,
+ 0,
+ offsetof(fline,link),
+ NIL(Dtmake_f),
+ (Dtfree_f)free_item,
+ NIL(Dtcompar_f),
+ NIL(Dthash_f),
+ NIL(Dtmemory_f),
+ NIL(Dtevent_f)
+};
+
+#ifdef OLD
static void
appendStrList(const char* p,int v)
{
sp->c = v;
dtinsert (HTMLstate.lines, sp);
}
+#endif
+/* dupFont:
+ */
+static htmlfont_t *
+dupFont (htmlfont_t *f)
+{
+ if (f) f->cnt++;
+ return f;
+}
+
+/* appendFItemList:
+ * Append a new fitem to the list.
+ */
+static void
+appendFItemList (agxbuf *ag)
+{
+ fitem *fi = NEW(fitem);
+
+ fi->ti.str = strdup(agxbuse(ag));
+ fi->ti.font = dupFont (HTMLstate.fontstack->cfont);
+ dtinsert(HTMLstate.fitemList, fi);
+}
+
+/* appendFLineList:
+ */
+static void
+appendFLineList (int v)
+{
+ int cnt;
+ fline *ln = NEW(fline);
+ fitem *fi;
+ Dt_t *ilist = HTMLstate.fitemList;
+
+ cnt = dtsize(ilist);
+ ln->lp.nitems = cnt;
+ ln->lp.just = v;
+ if (cnt) {
+ int i = 0;
+ ln->lp.items = N_NEW(cnt, textitem_t);
+
+ fi = (fitem*)dtflatten(ilist);
+ for (; fi; fi = (fitem*)dtlink(fitemList,(Dtlink_t*)fi)) {
+ ln->lp.items[i] = fi->ti;
+ i++;
+ }
+ }
+
+ dtclear(ilist);
+
+ dtinsert(HTMLstate.flineList, ln);
+}
+
+#ifdef OLD
/* mkText:
* Construct htmltxt_t from list of lines in HTMLstate.lines.
* lastl is a last, odd line with no <BR>, so we use n by default.
}
if (lastl) {
lp->str = strdup(lastl);
- lp->just = 'n';
+ lp->just = '\0';
}
if (lines) dtclear (lines);
return tp;
}
+#endif
+
+static htmltxt_t*
+mkText()
+{
+ int cnt;
+ Dt_t * iline = HTMLstate.flineList;
+ fline *fl ;
+ htmltxt_t *hft = NEW(htmltxt_t);
+
+ if (dtsize (HTMLstate.fitemList))
+ appendFLineList (UNSET_ALIGN);
+
+ cnt = dtsize(iline);
+ hft->nlines = cnt;
+
+ if (cnt) {
+ int i = 0;
+ hft->lines = N_NEW(cnt,htextline_t);
+ for(fl=(fline *)dtfirst(iline); fl; fl=(fline *)dtnext(iline,fl)) {
+ hft->lines[i] = fl->lp;
+ i++;
+ }
+ }
+
+ dtclear(iline);
+
+ return hft;
+}
/* addRow:
* Add new cell row to current table.
Dt_t* dp = dtopen(&cellDisc, Dtqueue);
htmltbl_t* tbl = HTMLstate.tblstack;
pitem* sp = NEW(pitem);
-
sp->u.rp = dp;
dtinsert (tbl->u.p.rows, sp);
}
htmltbl_t* tbl = HTMLstate.tblstack;
pitem* rp = (pitem*)dtlast (tbl->u.p.rows);
Dt_t* row = rp->u.rp;
-
sp->u.cp = cp;
dtinsert (row, sp);
cp->child.kind = kind;
- if (kind == HTML_TEXT)
- cp->child.u.txt = (htmltxt_t*)obj;
+
+ if(kind == HTML_TEXT)
+ cp->child.u.txt = (htmltxt_t*)obj;
else if (kind == HTML_IMAGE)
cp->child.u.img = (htmlimg_t*)obj;
else
cp->child.u.tbl = (htmltbl_t*)obj;
}
+#ifdef OLD
/* setFont:
* Copy in font attributes. fp has the new attributes.
* curf corresponds to the current font info of the object.
return fp;
}
-
/* fontText:
* Attach font information to text.
*/
{
cp->font = setFont (fp, cp->font);
}
+#endif
/* mkLabel:
* Create label, given body and type.
lp->u.txt = (htmltxt_t*)obj;
else
lp->u.tbl = (htmltbl_t*)obj;
-
return lp;
}
+/* freeFontstack:
+ * Free all stack items but the last, which is
+ * put on artificially during in parseHTML.
+ */
+static void
+freeFontstack()
+{
+ sfont_t* s;
+ sfont_t* next;
+
+ for (s = HTMLstate.fontstack; (next = s->pfont); s = next) {
+ free_html_font (s->cfont);
+ free(s);
+ }
+}
+
/* cleanup:
* Called on error. Frees resources allocated during parsing.
* This includes a label, plus a walk down the stack of
tp = next;
}
cellDisc.freef = (Dtfree_f)free_item;
+
+ fstrDisc.freef = (Dtfree_f)free_fitem;
+ dtclear (HTMLstate.fitemList);
+ fstrDisc.freef = (Dtfree_f)free_item;
+
+ flineDisc.freef = (Dtfree_f)free_fline;
+ dtclear (HTMLstate.flineList);
+ flineDisc.freef = (Dtfree_f)free_item;
+
+ freeFontstack();
}
/* nonSpace:
return 0;
}
+/* pushFont:
+ * Fonts are allocated in the lexer.
+ */
+static void
+pushFont (htmlfont_t *f)
+{
+ sfont_t *ft = NEW(sfont_t);
+ htmlfont_t* curfont = HTMLstate.fontstack->cfont;
+
+ if (curfont) {
+ if (!f->color && curfont->color)
+ f->color = strdup(curfont->color);
+ if ((f->size < 0.0) && (curfont->size >= 0.0))
+ f->size = curfont->size;
+ if (!f->name && curfont->name)
+ f->name = strdup(curfont->name);
+ }
+
+ ft->cfont = dupFont (f);
+ ft->pfont = HTMLstate.fontstack;
+ HTMLstate.fontstack = ft;
+}
+
+/* popFont:
+ */
+static void
+popFont ()
+{
+ sfont_t* curfont = HTMLstate.fontstack;
+ sfont_t* prevfont = curfont->pfont;
+
+ free_html_font (curfont->cfont);
+ free (curfont);
+ HTMLstate.fontstack = prevfont;
+}
+
%}
%union {
%token <cell> T_cell
%token <font> T_font
-%type <txt> text fonttext
+%type <txt> fonttext
%type <i> br
%type <tbl> table fonttable
%type <img> image
%start html
-
+
%%
-html : T_html fonttext { HTMLstate.lbl = mkLabel($2,HTML_TEXT); } T_end_html
- | T_html fonttable { HTMLstate.lbl = mkLabel($2,HTML_TBL); } T_end_html
+html : T_html fonttext T_end_html { HTMLstate.lbl = mkLabel($2,HTML_TEXT); }
+ | T_html fonttable T_end_html { HTMLstate.lbl = mkLabel($2,HTML_TBL); }
| error { cleanup(); YYABORT; }
;
-fonttext : text { $$ = $1; }
- | T_font text T_end_font { fontText($1,$2); $$ = $2; }
- ;
+fonttext : text { $$ = mkText(); }
+ ;
-text : lines
- { $$ = mkText (NULL); }
- | lines string
- { $$ = mkText (agxbuse(HTMLstate.str)); }
- | string
- { $$ = mkText (agxbuse(HTMLstate.str)); }
- | /* empty */
- { $$ = mkText (NULL); }
+text : text textitem
+ | textitem
;
-lines : string br
- { appendStrList (agxbuse(HTMLstate.str),$2); }
- | lines string br
- { appendStrList (agxbuse(HTMLstate.str), $3); }
+textitem : string { appendFItemList(HTMLstate.str);}
+ | br {appendFLineList($1);}
+ | sfont text nfont
+ ;
+
+sfont : T_font { pushFont ($1); }
+ ;
+
+nfont : T_end_font { popFont (); }
;
br : T_br T_end_br { $$ = $1; }
$2->u.p.prev = HTMLstate.tblstack;
$2->u.p.rows = dtopen(&rowDisc, Dtqueue);
HTMLstate.tblstack = $2;
+ $2->font = dupFont (HTMLstate.fontstack->cfont);
$$ = $2;
}
rows T_end_table opt_space {
;
fonttable : table { $$ = $1; }
- | T_font table T_end_font { fontTable($1,$2); $$ = $2; }
+ | sfont table nfont { $$=$2; }
;
opt_space : string
| T_IMG { $$ = $1; }
;
-
%%
+#ifdef OLD
htmllabel_t*
simpleHTML (char* txt)
{
htmllabel_t* l = mkLabel(tobj,HTML_TEXT);
return l;
}
+#endif
/* parseHTML:
* Return parsed label or NULL if failure.
unsigned char buf[SMALLBUF];
agxbuf str;
htmllabel_t* l;
+ sfont_t dfltf;
+ dfltf.cfont = NULL;
+ dfltf.pfont = NULL;
+ HTMLstate.fontstack = &dfltf;
HTMLstate.tblstack = 0;
HTMLstate.lbl = 0;
- HTMLstate.lines = dtopen(&strDisc, Dtqueue);
+ HTMLstate.fitemList = dtopen(&fstrDisc, Dtqueue);
+ HTMLstate.flineList = dtopen(&flineDisc, Dtqueue);
+
agxbinit (&str, SMALLBUF, buf);
HTMLstate.str = &str;
l = HTMLstate.lbl;
}
- dtclose (HTMLstate.lines);
- HTMLstate.lines = NULL;
+ dtclose (HTMLstate.fitemList);
+ dtclose (HTMLstate.flineList);
+
+ HTMLstate.fitemList = NULL;
+ HTMLstate.flineList = NULL;
+ HTMLstate.fontstack = NULL;
+
agxbfree (&str);
return l;
env->finfo.size = savp->size;
}
+#ifdef OLD
static void
emit_html_txt(GVJ_t * job, htmltxt_t * tp, htmlenv_t * env, void *obj)
{
/* make sure that there is something to do */
if (tp->nlines < 1)
- return;
+ return;
+
+ /* set font attributes */
+ if (tp->font) {
+ if (tp->font->size > 0.0)
+ fsize = tp->font->size;
+ else
+ fsize = env->finfo.size;
+ if (tp->font->name)
+ fname = tp->font->name;
+ else
+ fname = env->finfo.name;
+ if (tp->font->color)
+ fcolor = tp->font->color;
+ else
+ fcolor = env->finfo.color;
+ } else {
+ fsize = env->finfo.size;
+ fname = env->finfo.name;
+ fcolor = env->finfo.color;
+ }
+ halfwidth_x = ((double)(tp->box.UR.x - tp->box.LL.x))/2.0;
+ p.x = env->p.x + ((double)(tp->box.UR.x + tp->box.LL.x))/2.0;
+ p.y = env->p.y + ((double)(tp->box.UR.y + tp->box.LL.y))/2.0;
+
+ emit_textlines(job, tp->nlines, tp->line, p,
+ halfwidth_x, fname, fsize, fcolor);
+ }
+#endif
- /* set font attributes */
- if (tp->font) {
- if (tp->font->size > 0.0)
- fsize = tp->font->size;
- else
- fsize = env->finfo.size;
- if (tp->font->name)
- fname = tp->font->name;
- else
- fname = env->finfo.name;
- if (tp->font->color)
- fcolor = tp->font->color;
- else
- fcolor = env->finfo.color;
- } else {
- fsize = env->finfo.size;
- fname = env->finfo.name;
- fcolor = env->finfo.color;
+static void
+emit_htextlines(GVJ_t* job, int nlines, htextline_t* lines, pointf p,
+ double halfwidth_x, char* fname, double fsize, char* fcolor, box b)
+{
+ int i,j;
+ double tmp, center_x, left_x, right_x, fsize_;
+ double offset=0.0;
+ char *fname_ , *fcolor_;
+ textline_t tl;
+ pointf p_;
+ textitem_t* ti;
+
+ center_x = p.x;
+ left_x = center_x - halfwidth_x;
+ right_x = center_x + halfwidth_x;
+
+ gvrender_begin_context(job);
+ for(i=0; i<nlines; i++) {
+ switch (lines[i].just) {
+ case 'l':
+ p_.x = left_x;
+ p.x = left_x;
+ break;
+ case 'r':
+ p_.x = right_x;
+ p.x = right_x;
+ break;
+ default:
+ case 'n':
+ p_.x = center_x;
+ p.x = center_x;
+ break;
+ }
+
+ if (i == 0) {
+ p_.y = p.y + (double)(b.UR.y-b.LL.y)/2 - lines[i].lfsize;
+ tmp = ROUND(p_.y); /* align with interger points */
+ p_.y = (double)tmp;
+ }
+
+ ti = lines[i].items;
+ for(j=0; j<lines[i].nitems; j++) {
+ if (ti->font && (ti->font->size > 0))
+ fsize_ = ti->font->size;
+ else
+ fsize_ = fsize;
+ if (ti->font && ti->font->name)
+ fname_ = ti->font->name;
+ else
+ fname_ = fname;
+ if (ti->font && ti->font->color)
+ fcolor_ = ti->font->color;
+ else
+ fcolor_ = fcolor;
+
+ gvrender_set_pencolor(job, fcolor_);
+ gvrender_set_font(job, fname_, fsize_);
+
+ tl.str = ti->str;
+ tl.xshow = ti->xshow;
+ tl.width = lines[i].size;
+ tl.just = lines[i].just;
+
+ gvrender_textline(job, p_, &tl);
+ offset += ti->size;
+ p_.x = p.x + offset;
+ ti++;
+ }
+ /* position for next line */
+ if(i != nlines-1)
+ p_.y -= lines[i+1].lfsize * LINESPACING;
+ offset = 0.0;
}
- halfwidth_x = ((double)(tp->box.UR.x - tp->box.LL.x))/2.0;
- p.x = env->p.x + ((double)(tp->box.UR.x + tp->box.LL.x))/2.0;
- p.y = env->p.y + ((double)(tp->box.UR.y + tp->box.LL.y))/2.0;
+ gvrender_end_context(job);
+}
- emit_textlines(job, tp->nlines, tp->line, p,
- halfwidth_x, fname, fsize, fcolor);
+static void
+emit_html_txt(GVJ_t* job, htmltxt_t* tp, htmlenv_t* env, void* obj)
+{
+ double halfwidth_x;
+ pointf p;
+ char *fname;
+ char *fcolor;
+ double fsize;
+
+ /* make sure that there is something to do */
+ if (tp->nlines < 1)
+ return;
+
+ fsize = env->finfo.size;
+ fname = env->finfo.name;
+ fcolor = env->finfo.color;
+
+ halfwidth_x = ((double) (tp->box.UR.x - tp->box.LL.x)) / 2.0;
+ p.x = env->p.x + ((double) (tp->box.UR.x + tp->box.LL.x)) / 2.0;
+ p.y = env->p.y + ((double) (tp->box.UR.y + tp->box.LL.y)) / 2.0;
+
+ emit_htextlines(job, tp->nlines, tp->lines, p, halfwidth_x, fname,
+ fsize, fcolor, tp->box);
}
static void doSide(GVJ_t * job, point p, int wd, int ht)
}
}
-static void free_html_font(htmlfont_t * fp)
+void free_html_font(htmlfont_t * fp)
{
- if (fp->name)
- free(fp->name);
- if (fp->color)
- free(fp->color);
- free(fp);
+ fp->cnt--;
+ if (fp->cnt == 0) {
+ if (fp->name)
+ free(fp->name);
+ if (fp->color)
+ free(fp->color);
+ free(fp);
+ }
}
void free_html_data(htmldata_t * dp)
free(dp->bgcolor);
}
+#ifdef OLD
void free_html_text(htmltxt_t * tp)
{
textline_t *lp;
free_html_font(tp->font);
free(tp);
}
+#endif
+
+void free_html_text(htmltxt_t* t)
+{
+ htextline_t *tl;
+ textitem_t *ti;
+ int i, j;
+
+ if (!t) return;
+
+ tl = t->lines;
+ for (i = 0; i < t->nlines; i++) {
+ ti = tl->items;
+ for (j = 0; j < tl->nitems; j++) {
+ if (ti->str) free (ti->str);
+ if (ti->xshow) free (ti->xshow);
+ if (ti->font) free_html_font(ti->font);
+ ti++;
+ }
+ tl++;
+ }
+ free(tl->items);
+ free(t->lines);
+ free(t);
+}
void free_html_img(htmlimg_t * ip)
{
return 0;
}
+#ifdef OLD
static int
size_html_txt(htmltxt_t * txt, htmlenv_t * env)
{
txt->box.UR.y = txt->nlines * (int) (fsize * LINESPACING);
return 0;
}
+#endif
+
+static char*
+substrGFn (char* s, htmlenv_t* env)
+{
+ return strdup_and_subst_graph(s, (Agraph_t *) (env->obj));
+}
+
+static char*
+substrNFn (char* s, htmlenv_t* env)
+{
+ return strdup_and_subst_node(s, (Agnode_t *) (env->obj));
+}
+
+static char*
+substrEFn (char* s, htmlenv_t* env)
+{
+ return strdup_and_subst_edge(s, (Agedge_t *) (env->obj));
+}
+
+static int
+size_html_txt(htmltxt_t* ftxt, htmlenv_t* env)
+{
+ double xsize = 0.0, ysize = 0.0;
+ double fsize, lsize = 0.0;
+ int i, j, w = 0, width = 0;
+ char *fname;
+ textline_t lp;
+ char* (*substrFn) (char*, htmlenv_t* env);
+
+ switch (agobjkind(env->obj)) {
+ case AGGRAPH:
+ substrFn = substrGFn;
+ break;
+ case AGNODE:
+ substrFn = substrNFn;
+ break;
+ case AGEDGE:
+ substrFn = substrEFn;
+ break;
+ }
+
+ for (i = 0; i < ftxt->nlines; i++) {
+ for (j = 0; j < ftxt->lines[i].nitems; j++) {
+ lp.str = substrFn (ftxt->lines[i].items[j].str, env);
+ if (ftxt->lines[i].items[j].font) {
+ if (ftxt->lines[i].items[j].font->size > 0)
+ fsize = ftxt->lines[i].items[j].font->size;
+ else
+ fsize = env->finfo.size;
+ if (ftxt->lines[i].items[j].font->name)
+ fname = ftxt->lines[i].items[j].font->name;
+ else
+ fname = env->finfo.name;
+ } else {
+ fsize = env->finfo.size;
+ fname = env->finfo.name;
+ }
+ w = textwidth(&lp, fname, fsize);
+ free (ftxt->lines[i].items[j].str);
+ ftxt->lines[i].items[j].str = lp.str;
+ ftxt->lines[i].items[j].size = (double) w;
+ ftxt->lines[i].items[j].xshow = lp.xshow;
+ width += w;
+ ftxt->lines[i].size = (double) width;
+ if (fsize > lsize)
+ lsize = fsize;
+ }
+ ftxt->lines[i].lfsize = lsize;
+ if (width > xsize)
+ xsize = width;
+ ysize += lsize * LINESPACING;
+ width = w = 0;
+ lsize = 0;
+ }
+ ftxt->box.UR.x = xsize;
+ ftxt->box.UR.y = (int) (ysize);
+ return 0;
+}
/* forward declarion for recursive usage */
static int size_html_tbl(htmltbl_t * tbl, htmlcell_t * parent,
rv = size_html_txt(cp->child.u.txt, env);
child_sz = cp->child.u.txt->box.UR;
}
+
margin = 2 * (cp->data.pad + cp->data.border);
sz.x = child_sz.x + margin;
sz.y = child_sz.y + margin;
cp->box = pos;
}
+/* pos_html_txt:
+ * Set default alignment.
+ */
+static void
+pos_html_txt(htmltxt_t* ftxt, char c)
+{
+ int i;
+
+ for (i = 0; i < ftxt->nlines; i++) {
+ if (ftxt->lines[i].just == UNSET_ALIGN) /* unset */
+ ftxt->lines[i].just = c;
+ }
+}
+
+/* pos_html_cell:
+ */
static void pos_html_cell(htmlcell_t * cp, box pos, int sides)
{
int delx, dely;
} else if (cp->child.kind == HTML_IMAGE) {
pos_html_img(cp->child.u.img, cbox);
} else {
+ char dfltalign;
+ int af;
+
oldsz = cp->child.u.txt->box.UR;
delx = (cbox.UR.x - cbox.LL.x) - oldsz.x;
- if (delx > 0) {
- switch (cp->data.flags & HALIGN_MASK) {
+ /* If the cell is larger than the text block and alignment is
+ * done at textblock level, the text box is shrunk accordingly.
+ */
+ if ((delx > 0)&&((af=(cp->data.flags & HALIGN_MASK)) != HALIGN_TEXT)) {
+ switch (af) {
case HALIGN_LEFT:
cbox.UR.x -= delx;
break;
break;
}
}
+
dely = (cbox.UR.y - cbox.LL.y) - oldsz.y;
if (dely > 0) {
switch (cp->data.flags & VALIGN_MASK) {
}
}
cp->child.u.txt->box = cbox;
+
+ /* Set default text alignment
+ */
+ switch (cp->data.flags & BALIGN_MASK) {
+ case BALIGN_LEFT:
+ dfltalign = 'l';
+ break;
+ case BALIGN_RIGHT:
+ dfltalign = 'r';
+ break;
+ default:
+ dfltalign = 'c';
+ break;
+ }
+ pos_html_txt (cp->child.u.txt, dfltalign);
}
}
fprintf(stderr, "img: %s\n", ip->src);
}
+#ifdef OLD
void printTxt(htmltxt_t * tp, int ind)
{
int i;
tp->line[i].str);
}
}
+#endif
+
+void printTxt(htmltxt_t * txt, int ind)
+{
+ int i, j;
+
+ indent(ind);
+ fprintf (stderr, "txt lines = %d \n", txt->nlines);
+ for (i = 0; i < txt->nlines; i++) {
+ indent(ind+1);
+ fprintf (stderr, "[%d] %d items\n", i, txt->lines[i].nitems);
+ for (j = 0; j < txt->lines[i].nitems; j++) {
+ indent(ind+2);
+ fprintf (stderr, "[%d] (%f) \"%s\" ",
+ j, txt->lines[i].items[j].size,
+ txt->lines[i].items[j].str);
+ if (txt->lines[i].items[j].font)
+ fprintf (stderr, "font %s color %s size %f\n",
+ txt->lines[i].items[j].font->name,
+ txt->lines[i].items[j].font->color,
+ txt->lines[i].items[j].font->size);
+ else fprintf (stderr, "\n");
+ }
+ }
+}
void printData(htmldata_t * dp)
{
}
env.finfo.size = lp->fontsize;
env.finfo.name = lp->fontname;
- env.finfo.color = NULL;
+ 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);
- lbl = simpleHTML(nameOf(obj, &xb));
+ lp->html = FALSE;
+ size_label(env.g, nameOf(obj, &xb), lp);
agxbfree(&xb);
+ return rv;
}
if (lbl->kind == HTML_TBL) {
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
#define HALIGN_RIGHT (1 << 1)
#define HALIGN_LEFT (1 << 2)
#define HALIGN_MASK (HALIGN_RIGHT | HALIGN_LEFT)
+#define HALIGN_TEXT HALIGN_MASK
#define VALIGN_TOP (1 << 3)
#define VALIGN_BOTTOM (1 << 4)
#define VALIGN_MASK (VALIGN_TOP | VALIGN_BOTTOM)
#define BORDER_SET (1 << 5)
#define PAD_SET (1 << 6)
#define SPACE_SET (1 << 7)
+#define BALIGN_RIGHT (1 << 8)
+#define BALIGN_LEFT (1 << 9)
+#define BALIGN_MASK (BALIGN_RIGHT | BALIGN_LEFT)
+
+#define UNSET_ALIGN 0
/* font information
* If name or color is NULL, or size < 0, that attribute
* is unspecified.
*/
typedef struct {
- char *name;
- char *color;
+ char* name;
+ char* color;
double size;
+ int cnt; /* reference count */
} htmlfont_t;
/* lines of text within a cell
* NOTE: As required, the str field in line is utf-8.
* This translation is done when libexpat scans the input.
*/
+#ifdef OLD
typedef struct {
textline_t *line;
short nlines;
box box;
htmlfont_t *font; /* font info */
} htmltxt_t;
+#endif
+
+ typedef struct {
+ char *str;
+ char *xshow;
+ htmlfont_t *font;
+ double size; /* size of text item according to font */
+ } textitem_t;
+
+ typedef struct {
+ textitem_t *items;
+ short nitems;
+ char just;
+ double size; /* size of line */
+ double lfsize; /* size of largest font in line */
+ } htextline_t;
+
+ typedef struct {
+ htextline_t *lines;
+ short nlines;
+ box box;
+ } htmltxt_t;
typedef struct {
box box;
signed char space;
unsigned char border;
unsigned char pad;
- unsigned char flags;
+ unsigned char sides; /* set of sides exposed to field */
+ unsigned short flags;
unsigned short width;
unsigned short height;
box box; /* its geometric placement in points */
- unsigned char sides; /* set of sides exposed to field */
} htmldata_t;
#define HTML_UNSET 0
typedef struct htmlcell_t htmlcell_t;
typedef struct htmltbl_t htmltbl_t;
-
+
struct htmltbl_t {
htmldata_t data;
union {
htmlcell_t *cp;
} u;
} pitem;
-
+
extern htmllabel_t *parseHTML(char *, int *, int);
- extern htmllabel_t *simpleHTML(char *);
extern int make_html_label(textlabel_t * lp, void *obj);
extern void emit_html_label(GVJ_t * job, htmllabel_t * lp,
extern void free_html_label(htmllabel_t *, int);
extern void free_html_data(htmldata_t *);
extern void free_html_text(htmltxt_t *);
+ extern void free_html_font(htmlfont_t*);
extern box *html_port(node_t * n, char *pname, int* sides);
extern int html_path(node_t * n, port* p, int side, box * rv, int *k);
return lp->dimen;
}
+/* size_label:
+ * Process label text for size and line breaks.
+ */
+void
+size_label (graph_t* g, char* str, textlabel_t* rv)
+{
+ if (GD_charset(g) == CHAR_LATIN1) {
+ char* lstr = latin1ToUTF8(str);
+ label_size(lstr, rv, g);
+ free(lstr);
+ }
+ else
+ label_size(str, rv, g);
+}
+
/* make_label:
* Assume str is freshly allocated for this instance, so it
* can be freed in free_label.
rv->fontsize = fontsize;
if (html)
rv->html = TRUE;
- else if (GD_charset(g) == CHAR_LATIN1) {
- char* lstr = latin1ToUTF8(str);
- label_size(lstr, rv, g);
- free(lstr);
- }
else
- label_size(str, rv, g);
+ size_label(g, str, rv);
return rv;
}
extern void setup_graph(GVC_t * gvc, graph_t * g);
extern shape_kind shapeOf(node_t *);
extern void shape_clip(node_t * n, point curve[4]);
+ extern void size_label (graph_t* g, char* str, textlabel_t* rv);
extern void start_timer(void);
extern double textwidth(textline_t * textline, char *fontname,
double fontsz);