/* emit_html_label: */ void emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t * tp) { htmlenv_t env; allocObj (job); env.pos = tp->pos; env.finfo.color = tp->fontcolor; env.finfo.name = tp->fontname; env.finfo.size = tp->fontsize; env.finfo.size = tp->fontsize; env.imgscale = agget (job->obj->u.n, "imagescale"); env.objid = job->obj->id; env.objid_set = 0; if ((env.imgscale == NULL) || (env.imgscale[0] == '\0')) env.imgscale = "false"; if (lp->kind == HTML_TBL) { htmltbl_t *tbl = lp->u.tbl; /* set basic graphics context */ /* Need to override line style set by node. */ gvrender_set_style(job, job->gvc->defaultlinestyle); if (tbl->data.pencolor) gvrender_set_pencolor(job, tbl->data.pencolor); else gvrender_set_pencolor(job, DEFAULT_COLOR); emit_html_tbl(job, tbl, &env); } else { emit_html_txt(job, lp->u.txt, &env); } if (env.objid_set) free (env.objid); freeObj (job); }
/* emit_html_label: */ void emit_html_label(GVJ_t * job, htmllabel_t * lp, textlabel_t * tp) { htmlenv_t env; env.p = tp->p; env.finfo.color = tp->fontcolor; env.finfo.name = tp->fontname; env.finfo.size = tp->fontsize; if (lp->kind == HTML_TBL) { htmltbl_t *tbl = lp->u.tbl; /* set basic graphics context */ gvrender_begin_context(job); /* Need to override line style set by node. */ gvrender_set_style(job, job->gvc->defaultlinestyle); if (tbl->data.pencolor) gvrender_set_pencolor(job, tbl->data.pencolor); else gvrender_set_pencolor(job, DEFAULT_COLOR); emit_html_tbl(job, tbl, &env); gvrender_end_context(job); } else { emit_html_txt(job, lp->u.txt, &env); } }
void emit_label(GVJ_t * job, emit_state_t emit_state, textlabel_t * lp) { obj_state_t *obj = job->obj; int i; pointf p; emit_state_t old_emit_state; old_emit_state = obj->emit_state; obj->emit_state = emit_state; if (lp->html) { emit_html_label(job, lp->u.html, lp); obj->emit_state = old_emit_state; return; } /* make sure that there is something to do */ if (lp->u.txt.nspans < 1) return; gvrender_begin_label(job, LABEL_PLAIN); gvrender_set_pencolor(job, lp->fontcolor); /* position for first span */ switch (lp->valign) { case 't': p.y = lp->pos.y + lp->space.y / 2.0 - lp->fontsize; break; case 'b': p.y = lp->pos.y - lp->space.y / 2.0 + lp->dimen.y - lp->fontsize; break; case 'c': default: p.y = lp->pos.y + lp->dimen.y / 2.0 - lp->fontsize; break; } if (obj->labeledgealigned) p.y -= lp->pos.y; for (i = 0; i < lp->u.txt.nspans; i++) { switch (lp->u.txt.span[i].just) { case 'l': p.x = lp->pos.x - lp->space.x / 2.0; break; case 'r': p.x = lp->pos.x + lp->space.x / 2.0; break; default: case 'n': p.x = lp->pos.x; break; } gvrender_textspan(job, p, &(lp->u.txt.span[i])); /* UL position for next span */ p.y -= lp->u.txt.span[i].size.y; } gvrender_end_label(job); obj->emit_state = old_emit_state; }
/* doBorder: * Draw rectangle of width border inside rectangle given * by box. If border is 1, we call use a single call to gvrender_polygon. * (We have set linewidth to 1 below.) Otherwise, we use four separate * filled rectangles. We could use a richer graphics model, as things * can go wrong when cell spacing and borders are small. * We decrement the border value by 1, as typically a filled rectangle * from x to x+border will all pixels from x to x+border, and thus have * width border+1. */ static void doBorder(GVJ_t * job, char *color, int border, box B) { pointf pt; boxf BF; double wd, ht; gvrender_begin_context(job); if (!color) color = "black"; gvrender_set_fillcolor(job, color); gvrender_set_pencolor(job, color); B2BF(B, BF); if (border == 1) { gvrender_box(job, BF, 0); } else { border--; ht = BF.UR.y - BF.LL.y; wd = BF.UR.x - BF.LL.x; doSide(job, BF.LL, border, ht); pt.x = BF.LL.x; pt.y = BF.UR.y; doSide(job, pt, wd, -border); doSide(job, BF.UR, -border, -ht); pt.x = BF.UR.x; pt.y = BF.LL.y; doSide(job, pt, -wd, border); } gvrender_end_context(job); }
/* doBorder: * Draw rectangle of width border inside rectangle given * by box. If border is 1, we call use a single call to gvrender_polygon. * (We have set linewidth to 1 below.) Otherwise, we use four separate * filled rectangles. We could use a richer graphics model, as things * can go wrong when cell spacing and borders are small. * We decrement the border value by 1, as typically a filled rectangle * from x to x+border will all pixels from x to x+border, and thus have * width border+1. */ static void doBorder(GVJ_t * job, char *color, int border, boxf BF) { pointf pt; double wd, ht; if (!color) color = DEFAULT_COLOR; gvrender_set_fillcolor(job, color); gvrender_set_pencolor(job, color); if (border == 1) { gvrender_box(job, BF, 0); } else { border--; ht = BF.UR.y - BF.LL.y; wd = BF.UR.x - BF.LL.x; doSide(job, BF.LL, border, ht); pt.x = BF.LL.x; pt.y = BF.UR.y; doSide(job, pt, wd, -border); doSide(job, BF.UR, -border, -ht); pt.x = BF.UR.x; pt.y = BF.LL.y; doSide(job, pt, -wd, border); } }
static void doFill(GVJ_t * job, char *color, box B) { boxf BF; gvrender_set_fillcolor(job, color); gvrender_set_pencolor(job, color); B2BF(B, BF); gvrender_box(job, BF, 1); }
void emit_textlines(GVJ_t* job, int nlines, textline_t lines[], pointf p, double halfwidth_x, char* fname, double fsize, char* fcolor) { int i, linespacing; double tmp, center_x, left_x, right_x; center_x = p.x; left_x = center_x - halfwidth_x; right_x = center_x + halfwidth_x; /* set linespacing to an exact no. of pixelrows */ linespacing = (int) (fsize * LINESPACING); /* position for first line */ p.y += (linespacing * (nlines - 1) / 2) /* cl of topline */ -fsize / 3.0; /* cl to baseline */ tmp = ROUND(p.y); /* align with interger points */ p.y = (double)tmp; gvrender_begin_context(job); gvrender_set_pencolor(job, fcolor); gvrender_set_font(job, fname, fsize); for (i = 0; i < nlines; i++) { switch (lines[i].just) { case 'l': p.x = left_x; break; case 'r': p.x = right_x; break; default: case 'n': p.x = center_x; break; } gvrender_textline(job, p, &(lines[i])); /* position for next line */ p.y -= linespacing; } gvrender_end_context(job); }
/* setFill: * Set up fill values from given color; make pen transparent. * Return type of fill required. */ static int setFill (GVJ_t* job, char* color, int angle, int style, char* clrs[2]) { int filled; if (findStopColor (color, clrs)) { gvrender_set_fillcolor(job, clrs[0]); if (clrs[1]) gvrender_set_gradient_vals(job,clrs[1],angle); else gvrender_set_gradient_vals(job,DEFAULT_COLOR,angle); if (style & RADIAL) filled = RGRADIENT; else filled = GRADIENT; } else { gvrender_set_fillcolor(job, color); filled = FILL; } gvrender_set_pencolor(job, "transparent"); return filled; }
static void emit_htextparas(GVJ_t* job, int nparas, htextpara_t* paras, 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; char *fname_ , *fcolor_; textpara_t tl; pointf p_ = {0.0, 0.0}; textitem_t* ti; center_x = p.x; left_x = center_x - halfwidth_x; right_x = center_x + halfwidth_x; /* Initial p is in center of text block; set initial baseline * to top of text block. */ p_.y = p.y + (double)(b.UR.y-b.LL.y)/2.0; tmp = ROUND(p_.y); /* align with integer points */ p_.y = (double)tmp; gvrender_begin_context(job); for(i=0; i<nparas; i++) { switch (paras[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; } p_.y -= paras[i].lfsize; /* move to current base line */ ti = paras[i].items; offset = 0.0; for(j=0; j<paras[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.fontname = fname_; tl.fontsize = fsize_; tl.xshow = ti->xshow; tl.postscript_alias = ti->postscript_alias; tl.layout = ti->layout; tl.width = paras[i].size; tl.height = paras[i].lfsize; tl.just = paras[i].just; gvrender_textpara(job, p_, &tl); offset += ti->size; p_.x = p.x + offset; ti++; } } gvrender_end_context(job); }
static void emit_html_tbl(GVJ_t * job, htmltbl_t * tbl, htmlenv_t * env) { boxf pts = tbl->data.box; pointf pos = env->pos; htmlcell_t **cells = tbl->u.n.cells; htmlcell_t *cp; static htmlfont_t savef; htmlmap_data_t saved; int anchor; /* if true, we need to undo anchor settings. */ int doAnchor = (tbl->data.href || tbl->data.target); pointf AF[4]; if (tbl->font) pushFontInfo(env, tbl->font, &savef); pts.LL.x += pos.x; pts.UR.x += pos.x; pts.LL.y += pos.y; pts.UR.y += pos.y; if (doAnchor && !(job->flags & EMIT_CLUSTERS_LAST)) anchor = initAnchor(job, env, &tbl->data, pts, &saved, 1); else anchor = 0; /* Set up rounded style */ if (tbl->data.style & ROUNDED) { AF[0] = pts.LL; AF[2] = pts.UR; if (tbl->data.border) { double delta = ((double)tbl->data.border)/2.0; AF[0].x += delta; AF[0].y += delta; AF[2].x -= delta; AF[2].y -= delta; } AF[1].x = AF[2].x; AF[1].y = AF[0].y; AF[3].x = AF[0].x; AF[3].y = AF[2].y; } /* Fill first */ if (tbl->data.bgcolor) { char* clrs[2]; int filled = setFill (job, tbl->data.bgcolor, tbl->data.gradientangle, tbl->data.style, clrs); if (tbl->data.style & ROUNDED){ round_corners (job, AF, 4, tbl->data.style, filled); } else gvrender_box(job, pts, filled); free (clrs[0]); } while (*cells) { emit_html_cell(job, *cells, env); cells++; } /* Draw table rules and border. * Draw after cells so we can draw over any fill. * At present, we set the penwidth to 1 for rules until we provide the calculations to take * into account wider rules. */ cells = tbl->u.n.cells; gvrender_set_penwidth(job, 1.0); while ((cp = *cells++)){ if (cp->ruled) emit_html_rules(job, cp, env, tbl->data.pencolor); } if (tbl->data.border) { if (tbl->data.style & ROUNDED) { char* color = (tbl->data.pencolor ? tbl->data.pencolor : DEFAULT_COLOR); gvrender_set_penwidth(job, tbl->data.border); gvrender_set_pencolor(job, color); round_corners (job, AF, 4, tbl->data.style, 0); } else doBorder(job, tbl->data.pencolor, tbl->data.border, pts); } if (anchor) endAnchor (job, &saved, 1); if (doAnchor && (job->flags & EMIT_CLUSTERS_LAST)) { if (initAnchor(job, env, &tbl->data, pts, &saved, 0)) endAnchor (job, &saved, 0); } if (tbl->font) popFontInfo(env, &savef); }
/* emit_html_rules: * place vertical and horizontal lines between adjacent cells and * extend the lines to intersect the rounded table boundary */ static void emit_html_rules(GVJ_t * job, htmlcell_t * cp, htmlenv_t * env, char *color) { pointf rule_pt; double rule_length; unsigned char base; boxf pts = cp->data.box; pointf pos = env->pos; if (!color) color = DEFAULT_COLOR; gvrender_set_fillcolor(job, color); gvrender_set_pencolor(job, color); pts = cp->data.box; pts.LL.x += pos.x; pts.UR.x += pos.x; pts.LL.y += pos.y; pts.UR.y += pos.y; //Determine vertical line coordinate and length if ((cp->ruled & HTML_VRULE) && (cp->col + cp->cspan < cp->parent->cc)) { if(cp->row == 0) { // first row // extend to center of table border and add half cell spacing base = cp->parent->data.border + cp->parent->data.space/2; rule_pt.y = pts.LL.y - cp->parent->data.space/2; } else if(cp->row + cp->rspan == cp->parent->rc){ // bottom row // extend to center of table border and add half cell spacing base = cp->parent->data.border + cp->parent->data.space/2; rule_pt.y = pts.LL.y - cp->parent->data.space/2 - base; } else { base = 0; rule_pt.y = pts.LL.y - cp->parent->data.space/2; } rule_pt.x = pts.UR.x + cp->parent->data.space/2; rule_length = base + pts.UR.y - pts.LL.y + cp->parent->data.space; doSide(job,rule_pt,0,rule_length); } //Determine the horizontal coordinate and length if ((cp->ruled & HTML_HRULE) && (cp->row + cp->rspan < cp->parent->rc)) { if(cp->col == 0) { // first column // extend to center of table border and add half cell spacing base = cp->parent->data.border + cp->parent->data.space/2; rule_pt.x = pts.LL.x - base - cp->parent->data.space/2; if(cp->col + cp->cspan == cp->parent->cc) // also last column base *= 2; } else if(cp->col + cp->cspan == cp->parent->cc){ // last column // extend to center of table border and add half cell spacing base = cp->parent->data.border + cp->parent->data.space/2; rule_pt.x = pts.LL.x - cp->parent->data.space/2; } else { base = 0; rule_pt.x = pts.LL.x - cp->parent->data.space/2; } rule_pt.y = pts.LL.y - cp->parent->data.space/2; rule_length = base + pts.UR.x - pts.LL.x + cp->parent->data.space; doSide(job,rule_pt,rule_length,0); } }
static void emit_htextparas(GVJ_t* job, int nparas, htextpara_t* paras, pointf p, double halfwidth_x, htmlfont_t finfo, boxf b) { int i,j; double center_x, left_x, right_x, fsize_; char *fname_ , *fcolor_; textpara_t tl; pointf p_ = {0.0, 0.0}; textpara_t* ti; center_x = p.x; left_x = center_x - halfwidth_x; right_x = center_x + halfwidth_x; /* Initial p is in center of text block; set initial baseline * to top of text block. */ p_.y = p.y + (b.UR.y-b.LL.y)/2.0; gvrender_begin_label(job, LABEL_HTML); for(i=0; i<nparas; i++) { /* set p.x to leftmost point where the line of text begins */ switch (paras[i].just) { case 'l': p.x = left_x; break; case 'r': p.x = right_x - paras[i].size; break; default: case 'n': p.x = center_x - paras[i].size/2.0; break; } p_.y -= paras[i].lfsize; /* move to current base line */ ti = paras[i].items; for(j=0; j<paras[i].nitems; j++) { if (ti->font && (ti->font->size > 0)) fsize_ = ti->font->size; else fsize_ = finfo.size; if (ti->font && ti->font->name) fname_ = ti->font->name; else fname_ = finfo.name; if (ti->font && ti->font->color) fcolor_ = ti->font->color; else fcolor_ = finfo.color; gvrender_set_pencolor(job, fcolor_); tl.str = ti->str; tl.fontname = fname_; tl.fontsize = fsize_; tl.font = ti->font; tl.yoffset_layout = ti->yoffset_layout; /* tl.yoffset_centerline = ti->yoffset_centerline; */ tl.yoffset_centerline = 1; tl.postscript_alias = ti->postscript_alias; tl.layout = ti->layout; tl.width = ti->size; tl.height = paras[i].lfsize; tl.just = 'l'; p_.x = p.x; gvrender_textpara(job, p_, &tl); p.x += ti->size; ti++; } } gvrender_end_label(job); }