From: erg Date: Thu, 31 Jan 2008 21:51:35 +0000 (+0000) Subject: Fix mapping geometry of edges to account for line width. X-Git-Tag: LAST_LIBGRAPH~32^2~4795 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a38c14955ecb7417487426f0f33dfd5f63ef1775;p=graphviz Fix mapping geometry of edges to account for line width. Unfortunately, this involved a bit of code shuffling. Since map generation is done in emit_begin_edge(), the use of style and penwidth was removed from emit_edge_graphics() and moved earlier. --- diff --git a/lib/common/emit.c b/lib/common/emit.c index d1e4eeafa..94cf8c292 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -384,13 +384,13 @@ static double bisect (pointf pp, pointf cp, pointf np) /* mkSegPts: * Determine polygon points related to 2 segments prv-cur and cur-nxt. * The points lie on the bisector of the 2 segments, passing through cur, - * and distance HW from cur. The points are stored in p1 and p2. + * and distance w2 from cur. The points are stored in p1 and p2. * If p1 is NULL, we use the normal to cur-nxt. * If p2 is NULL, we use the normal to prv-cur. * Assume at least one of prv or nxt is non-NULL. */ static void mkSegPts (segitem_t* prv, segitem_t* cur, segitem_t* nxt, - pointf* p1, pointf* p2) + pointf* p1, pointf* p2, double w2) { pointf cp, pp, np; double theta, delx, dely; @@ -416,8 +416,8 @@ static void mkSegPts (segitem_t* prv, segitem_t* cur, segitem_t* nxt, pp.y = 2*cp.y - np.y; } theta = bisect(pp,cp,np); - delx = HW*cos(theta); - dely = HW*sin(theta); + delx = w2*cos(theta); + dely = w2*sin(theta); p.x = cp.x + delx; p.y = cp.y + dely; *p1 = p; @@ -434,7 +434,7 @@ static void mkSegPts (segitem_t* prv, segitem_t* cur, segitem_t* nxt, * In cmapx, polygons are limited to 100 points, so we output polygons * in chunks of 100. */ -static void map_output_bspline (pointf **pbs, int **pbs_n, int *pbs_poly_n, bezier* bp) +static void map_output_bspline (pointf **pbs, int **pbs_n, int *pbs_poly_n, bezier* bp, double w2) { segitem_t* segl = GNEW(segitem_t); segitem_t* segp = segl; @@ -459,7 +459,7 @@ static void map_output_bspline (pointf **pbs, int **pbs_n, int *pbs_poly_n, bezi cnt = 0; while (segp) { segnext = segp->next; - mkSegPts (segprev, segp, segnext, pt1+cnt, pt2+cnt); + mkSegPts (segprev, segp, segnext, pt1+cnt, pt2+cnt, w2); cnt++; if ((segnext == NULL) || (cnt == 50)) { map_bspline_poly (pbs, pbs_n, pbs_poly_n, cnt, pt1, pt2); @@ -1254,44 +1254,26 @@ static char* default_pencolor(char *pencolor, char *deflt) return buf; } -static void emit_edge_graphics(GVJ_t * job, edge_t * e) +static void emit_edge_graphics(GVJ_t * job, edge_t * e, char** styles) { int i, j, cnum, numc = 0; - char *color, *pencolor, *fillcolor, *style; + char *color, *pencolor, *fillcolor; char *headcolor, *tailcolor, *lastcolor; char *colors = NULL; - char **styles = 0; - char **sp; bezier bz = { 0, 0, 0, 0 }; bezierf bzf; splinesf offspl, tmpspl; pointf pf0, pf1, pf2 = { 0, 0 }, pf3, *offlist, *tmplist; double scale, numc2; - double penwidth; - char *p; + char* p; #define SEP 2.0 - style = late_string(e, E_style, ""); - /* We shortcircuit drawing an invisible edge because the arrowhead - * code resets the style to solid, and most of the code generators - * (except PostScript) won't honor a previous style of invis. - */ - if (style[0]) { - styles = parse_style(style); - sp = styles; - while ((p = *sp++)) { - if (streq(p, "invis")) - return; - } - } setColorScheme (agget (e, "colorscheme")); if (ED_spl(e)) { scale = late_double(e, E_arrowsz, 1.0, 0.0); color = late_string(e, E_color, ""); - if (styles) gvrender_set_style(job, styles); - /* need to know how many colors separated by ':' */ for (p = color; *p; p++) if (*p == ':') @@ -1318,10 +1300,6 @@ static void emit_edge_graphics(GVJ_t * job, edge_t * e) default_pencolor(pencolor, DEFAULT_VISITEDPENCOLOR)); fillcolor = late_nnstring(e, E_visitedfillcolor, DEFAULT_VISITEDFILLCOLOR); } - if (E_penwidth && ((p=agxget(e,E_penwidth->index)) && p[0])) { - penwidth = late_double(e, E_penwidth, 1.0, 0.0); - gvrender_set_penwidth(job, penwidth); - } if (pencolor != color) gvrender_set_pencolor(job, pencolor); if (fillcolor != color) @@ -1484,7 +1462,7 @@ static boolean edge_in_box(edge_t *e, boxf b) return FALSE; } -void emit_begin_edge(GVJ_t * job, edge_t * e) +static void emit_begin_edge(GVJ_t * job, edge_t * e, char** styles) { obj_state_t *obj; int flags = job->flags; @@ -1494,12 +1472,23 @@ void emit_begin_edge(GVJ_t * job, edge_t * e) int i, nump, *pbs_n = NULL, pbs_poly_n = 0; char* dflt_url = NULL; char* dflt_target = NULL; + double penwidth; obj = push_obj_state(job); obj->type = EDGE_OBJTYPE; obj->u.e = e; obj->emit_state = EMIT_EDRAW; + /* We handle the edge style and penwidth here because the width + * is needed below for calculating polygonal image maps + */ + if (styles && ED_spl(e)) gvrender_set_style(job, styles); + + if (E_penwidth && ((s=agxget(e,E_penwidth->index)) && s[0])) { + penwidth = late_double(e, E_penwidth, 1.0, 0.0); + gvrender_set_penwidth(job, penwidth); + } + if (flags & GVRENDER_DOES_Z) { obj->tail_z= late_double(e->tail, N_z, 0.0, -1000.0); obj->head_z= late_double(e->head, N_z, 0.0, -MAXFLOAT); @@ -1605,11 +1594,12 @@ void emit_begin_edge(GVJ_t * job, edge_t * e) if (ED_spl(e) && (obj->url || obj->tooltip) && (flags & GVRENDER_DOES_MAP_POLYGON)) { int ns; splines *spl; + double w2 = MAX(job->obj->penwidth/2.0,2.0); spl = ED_spl(e); ns = spl->size; /* number of splines */ for (i = 0; i < ns; i++) - map_output_bspline (&pbs, &pbs_n, &pbs_poly_n, spl->list+i); + map_output_bspline (&pbs, &pbs_n, &pbs_poly_n, spl->list+i, w2); obj->url_bsplinemap_poly_n = pbs_poly_n; obj->url_bsplinemap_n = pbs_n; if (! (flags & GVRENDER_DOES_TRANSFORM)) { @@ -1706,7 +1696,7 @@ nodeIntersect (GVJ_t * job, point p, } } -void emit_end_edge(GVJ_t * job) +static void emit_end_edge(GVJ_t * job) { obj_state_t *obj = job->obj; edge_t *e = obj->u.e; @@ -1772,6 +1762,10 @@ void emit_end_edge(GVJ_t * job) static void emit_edge(GVJ_t * job, edge_t * e) { char *s; + char *style; + char **styles = 0; + char **sp; + char *p; if (edge_in_box(e, job->clip) && edge_in_layer(job, e->head->graph, e) ) { @@ -1789,8 +1783,21 @@ static void emit_edge(GVJ_t * job, edge_t * e) if (s[0]) gvrender_comment(job, s); - emit_begin_edge(job, e); - emit_edge_graphics (job, e); + style = late_string(e, E_style, ""); + /* We shortcircuit drawing an invisible edge because the arrowhead + * code resets the style to solid, and most of the code generators + * (except PostScript) won't honor a previous style of invis. + */ + if (style[0]) { + styles = parse_style(style); + sp = styles; + while ((p = *sp++)) { + if (streq(p, "invis")) return; + } + } + + emit_begin_edge(job, e, styles); + emit_edge_graphics (job, e, styles); emit_end_edge(job); } }