From: Emden Gansner Date: Mon, 23 Jan 2012 22:06:55 +0000 (-0500) Subject: First pass at cleaning up gradient fill X-Git-Tag: LAST_LIBGRAPH~32^2~557^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3cb90cb43caa21982ac7daa352cf89e57406cd33;p=graphviz First pass at cleaning up gradient fill --- diff --git a/lib/common/const.h b/lib/common/const.h index cdf45fba4..0c2380ba8 100644 --- a/lib/common/const.h +++ b/lib/common/const.h @@ -202,17 +202,21 @@ /* style flags */ #define FILLED (1 << 0) -#define ROUNDED (1 << 1) -#define DIAGONALS (1 << 2) -#define AUXLABELS (1 << 3) -#define INVISIBLE (1 << 4) -#define DOGEAR (1 << 5) -#define TAB (1 << 6) -#define FOLDER (1 << 7) -#define BOX3D (1 << 8) -#define COMPONENT (1 << 9) -#define GRADIENT (1 << 10) -#define RGRADIENT GRADIENT + 1 /*radial gradient */ +#define RADIAL (1 << 1) +#define ROUNDED (1 << 2) +#define DIAGONALS (1 << 3) +#define AUXLABELS (1 << 4) +#define INVISIBLE (1 << 5) +#define DOGEAR (1 << 6) +#define TAB (1 << 7) +#define FOLDER (1 << 8) +#define BOX3D (1 << 9) +#define COMPONENT (1 << 10) + +/* fill types */ +#define FILL 1 +#define GRADIENT 2 +#define RGRADIENT 3 /* label types */ #define LT_NONE (0 << 1) diff --git a/lib/common/emit.c b/lib/common/emit.c index 3b3cc9f7d..ec2f60a40 100644 --- a/lib/common/emit.c +++ b/lib/common/emit.c @@ -91,9 +91,8 @@ obj_state_t* push_obj_state(GVJ_t *job) obj->pen = parent->pen; obj->fill = parent->fill; obj->penwidth = parent->penwidth; - obj->gradient.angle = parent->gradient.angle; - obj->gradient.startcolor = parent->gradient.startcolor; - obj->gradient.stopcolor = parent->gradient.stopcolor; + obj->gradient_angle = parent->gradient_angle; + obj->stopcolor = parent->stopcolor; } else { /* obj->pencolor = NULL */ @@ -269,6 +268,39 @@ static void map_point(GVJ_t *job, pointf pf) } } +static char **checkClusterStyle(graph_t* sg, int *flagp) +{ + char *style; + char **pstyle = 0; + int istyle = 0; + + if (((style = agget(sg, "style")) != 0) && style[0]) { + char **pp; + char **qp; + char *p; + pp = pstyle = parse_style(style); + while ((p = *pp)) { + if (strcmp(p, "filled") == 0) { + istyle |= FILLED; + pp++; + }else if (strcmp(p, "radial") == 0) { + istyle |= (FILLED | RADIAL); + pp++; + }else if (strcmp(p, "rounded") == 0) { + istyle |= ROUNDED; + qp = pp; /* remove rounded from list passed to renderer */ + do { + qp++; + *(qp-1) = *qp; + } while (*qp); + } else pp++; + } + } + + *flagp = istyle; + return pstyle; +} + void emit_map_rect(GVJ_t *job, boxf b) { obj_state_t *obj = job->obj; @@ -1014,11 +1046,34 @@ static void emit_xdot (GVJ_t * job, xdot* xd) free (pts); } +static boolean findStopColor (char* colorlist, char* clrs[2]) +{ + char* p = strchr(colorlist,':'); + + if (p) { + char* s; + *p = '\0'; + clrs[0] = strdup (colorlist); + *p++ = ':'; + if (*p == '\0') + clrs[1] = NULL; + else if ((s = strchr(p,':'))) { + *s = '\0'; + clrs[0] = strdup (p); + *s++ = ':'; + } + else + clrs[1] = strdup (p); + return TRUE; + } + else return FALSE; +} + static void emit_background(GVJ_t * job, graph_t *g) { xdot* xd; - char *str,*fillcolor; - int dfltColor,gradient; + char *str; + int dfltColor; /* if no bgcolor specified - first assume default of "white" */ if (! ((str = agget(g, "bgcolor")) && str[0])) { @@ -1038,17 +1093,30 @@ static void emit_background(GVJ_t * job, graph_t *g) /* except for "transparent" on truecolor, or default "white" on (assumed) white paper, paint background */ if (!( ((job->flags & GVDEVICE_DOES_TRUECOLOR) && streq(str, "transparent")) || ((job->flags & GVRENDER_NO_WHITE_BG) && dfltColor))) { - gvrender_set_fillcolor(job, str); - gvrender_set_pencolor(job, str); - gradient = findGradient(g,G_gradient); - if(gradient > 0){ - if (! ((fillcolor = agget(g, "fillcolor")) && str[0])) - fillcolor = str; - gvrender_set_gradient(job,g,fillcolor,findGradientAngle(g,G_gradientangle)); - gvrender_box(job, job->clip,gradient); /* linear or radial gradient */ + char* clrs[2]; + + if ((findStopColor (str, clrs))) { + int filled, istyle = 0; + gvrender_set_fillcolor(job, clrs[0]); + gvrender_set_pencolor(job, "transparent"); + checkClusterStyle(g, &istyle); + if (clrs[1]) + gvrender_set_gradient_vals(job,clrs[1],findGradientAngle(g,G_gradientangle)); + else + gvrender_set_gradient_vals(job,DEFAULT_COLOR,findGradientAngle(g,G_gradientangle)); + if (istyle & RADIAL) + filled = RGRADIENT; + else + filled = GRADIENT; + gvrender_box(job, job->clip, filled); + free (clrs[0]); + free (clrs[1]); + } + else { + gvrender_set_fillcolor(job, str); + gvrender_set_pencolor(job, str); + gvrender_box(job, job->clip, FILL); /* filled */ } - else - gvrender_box(job, job->clip, TRUE); /* filled */ } if ((xd = (xdot*)GD_drawing(g)->xdots)) @@ -3153,36 +3221,6 @@ void emit_once_reset(void) } } -static char **checkClusterStyle(graph_t* sg, int *flagp) -{ - char *style; - char **pstyle = 0; - int istyle = 0; - - if (((style = agget(sg, "style")) != 0) && style[0]) { - char **pp; - char **qp; - char *p; - pp = pstyle = parse_style(style); - while ((p = *pp)) { - if (strcmp(p, "filled") == 0) { - istyle |= FILLED; - pp++; - }else if (strcmp(p, "rounded") == 0) { - istyle |= ROUNDED; - qp = pp; /* remove rounded from list passed to renderer */ - do { - qp++; - *(qp-1) = *qp; - } while (*qp); - } else pp++; - } - } - - *flagp = istyle; - return pstyle; -} - static void emit_begin_cluster(GVJ_t * job, Agraph_t * sg) { obj_state_t *obj; diff --git a/lib/common/utils.c b/lib/common/utils.c index 701c669f0..002b3e6b9 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -1832,19 +1832,20 @@ void setEdgeType (graph_t* g, int dflt) } -/* cairogen_get_gradient_points +/* get_gradient_points * Evaluates the extreme points of an ellipse or polygon * Determines the point at the center of the extreme points - * Uses the angle parameter to identify two points on a line that defines the gradient direction - * + * If isRadial is true,sets the inner radius to half the distance to the min point; + * else uses the angle parameter to identify two points on a line that defines the + * gradient direction */ -void cairogen_get_gradient_points(pointf * A, pointf * G, int n, float angle) +void get_gradient_points(pointf * A, pointf * G, int n, float angle, boolean isRadial) { int i; double rx, ry; pointf min,max,center; - if ( n == 2) { + if (n == 2) { rx = A[1].x - A[0].x; ry = A[1].y - A[0].y; min.x = A[0].x - rx; @@ -1856,52 +1857,16 @@ void cairogen_get_gradient_points(pointf * A, pointf * G, int n, float angle) min.x = max.x = A[0].x; min.y = max.y = A[0].y; for (i = 0; i < n; i++){ - min.x = (A[i].x < min.x ? A[i].x : min.x); - min.y = (A[i].y < min.y ? A[i].y : min.y); - max.x = (A[i].x > max.x ? A[i].x : max.x); - max.y = (A[i].y > max.y ? A[i].y : max.y); - } - } - center.x = min.x + (max.x - min.x)/2; - center.y = min.y + (max.y - min.y)/2; - G[0].x = center.x - (max.x - center.x) * cos(angle); - G[0].y = -center.y + (max.y - center.y) * sin(angle); - G[1].x = center.x + (center.x - min.x) * cos(angle); - G[1].y = -center.y - (center.y - min.y) * sin(angle); -} - -/* cairogen_get_rgradient_points - * Evaluates the extreme points of an ellipse or polygon - * Determines the point at the center of the extreme points - * Sets the inner radius to half the distance to the min point - * - */ -void cairogen_get_rgradient_points(pointf * A, pointf * G, int n) -{ - int i; - double rx, ry,inner_r,outer_r; - pointf min,max,center; - - if ( n == 2) { - rx = A[1].x - A[0].x; - ry = A[1].y - A[0].y; - min.x = A[0].x - rx; - max.x = A[0].x + rx; - min.y = A[0].y - ry; - max.y = A[0].y + ry; - } - else { - min.x = max.x = A[0].x; - min.y = max.y = A[0].y; - for (i = 0; i < n; i++){ - min.x = (A[i].x < min.x ? A[i].x : min.x); - min.y = (A[i].y < min.y ? A[i].y : min.y); - max.x = (A[i].x > max.x ? A[i].x : max.x); - max.y = (A[i].y > max.y ? A[i].y : max.y); + min.x = MIN(A[i].x,min.x); + min.y = MIN(A[i].y,min.y); + max.x = MAX(A[i].x,max.x); + max.y = MAX(A[i].y,max.y); } } center.x = min.x + (max.x - min.x)/2; center.y = min.y + (max.y - min.y)/2; + if (isRadial) { + double inner_r, outer_r; outer_r = sqrt((center.x - min.x)*(center.x - min.x) + (center.y - min.y)*(center.y - min.y)); inner_r = outer_r /4.; @@ -1909,7 +1874,13 @@ void cairogen_get_rgradient_points(pointf * A, pointf * G, int n) G[0].y = -center.y; G[1].x = inner_r; G[1].y = outer_r; - + } + else { + G[0].x = center.x - (max.x - center.x) * cos(angle); + G[0].y = -center.y + (max.y - center.y) * sin(angle); + G[1].x = center.x + (center.x - min.x) * cos(angle); + G[1].y = -center.y - (center.y - min.y) * sin(angle); + } } #ifndef WIN32_STATIC diff --git a/lib/common/utils.h b/lib/common/utils.h index b922b4a56..9b68acc03 100644 --- a/lib/common/utils.h +++ b/lib/common/utils.h @@ -95,6 +95,8 @@ extern "C" { extern boolean overlap_label(textlabel_t *lp, boxf b); extern boolean overlap_edge(edge_t *e, boxf b); + extern void get_gradient_points(pointf * A, pointf * G, int n, float angle, boolean isRadial); + extern int processClusterEdges(graph_t * g); extern char *latin1ToUTF8(char *); diff --git a/lib/gvc/gvcjob.h b/lib/gvc/gvcjob.h index 1944f8538..954a51422 100644 --- a/lib/gvc/gvcjob.h +++ b/lib/gvc/gvcjob.h @@ -153,12 +153,6 @@ extern "C" { int alloc; } gv_argvlist_t; - typedef struct gv_gradient_s { - int angle; - gvcolor_t startcolor, stopcolor; - int id; - } gv_gradient_t; - typedef struct gvdevice_callbacks_s { void (*refresh) (GVJ_t * job); void (*button_press) (GVJ_t * job, int button, pointf pointer); @@ -206,8 +200,8 @@ extern "C" { emit_state_t emit_state; - gvcolor_t pencolor, fillcolor; - gv_gradient_t gradient; + gvcolor_t pencolor, fillcolor, stopcolor; + int gradient_angle; pen_type pen; fill_type fill; double penwidth; diff --git a/lib/gvc/gvcproc.h b/lib/gvc/gvcproc.h index 715b4d04b..c8b70cc43 100644 --- a/lib/gvc/gvcproc.h +++ b/lib/gvc/gvcproc.h @@ -103,12 +103,10 @@ extern void gvrender_set_pencolor(GVJ_t * job, char *name); extern void gvrender_set_penwidth(GVJ_t * job, double penwidth); extern void gvrender_set_fillcolor(GVJ_t * job, char *name); - extern void gvrender_set_gradientcolor(GVJ_t * job, char *gr_color_ptr[2]); - extern void gvrender_set_gradientAngle(GVJ_t * job, int angle); - extern void gvrender_set_gradientId(GVJ_t * job); extern void gvrender_set_gradient_attr(GVJ_t * job, void *g_obj, attrsym_t * color_attr, attrsym_t * angle_attr); extern void gvrender_set_gradient(GVJ_t * job, void *g_obj, char *color, int angle); extern char *gvrender_set_gradient_values(GVJ_t* job, char* gradcolor, int angle); + extern void gvrender_set_gradient_vals (GVJ_t * job, char *stopcolor, int angle); extern void gvrender_set_style(GVJ_t * job, char **s); extern void gvrender_ellipse(GVJ_t * job, pointf * AF, int n, int filled); diff --git a/lib/gvc/gvrender.c b/lib/gvc/gvrender.c index f3ceba075..5cc84ddc0 100644 --- a/lib/gvc/gvrender.c +++ b/lib/gvc/gvrender.c @@ -39,9 +39,10 @@ extern int emit_once(char *str); extern shape_desc *find_user_shape(char *name); -extern char *findGradientColor(void * n, char *pos, char *color, char *dflt); -extern char *findAttrColor(void *obj, attrsym_t *colorattr, char *dflt); -extern int findGradientAngle(void * n, attrsym_t * attr); +extern char *findGradientColor(void *n, char *pos, char *color, + char *dflt); +extern char *findAttrColor(void *obj, attrsym_t * colorattr, char *dflt); +extern int findGradientAngle(void *n, attrsym_t * attr); extern boolean mapbool(char *s); #ifndef HAVE_STRCASECMP @@ -72,39 +73,38 @@ int gvrender_select(GVJ_t * job, const char *str) /* job->flags = 0; */ plugin = gvc->api[API_device]; if (plugin) { - typeptr = plugin->typeptr; - job->device.engine = (gvdevice_engine_t *) (typeptr->engine); - job->device.features = (gvdevice_features_t *) (typeptr->features); - job->device.id = typeptr->id; - job->device.type = plugin->typestr; + typeptr = plugin->typeptr; + job->device.engine = (gvdevice_engine_t *) (typeptr->engine); + job->device.features = (gvdevice_features_t *) (typeptr->features); + job->device.id = typeptr->id; + job->device.type = plugin->typestr; + + job->flags |= job->device.features->flags; + } else + return NO_SUPPORT; /* FIXME - should differentiate problem */ - job->flags |= job->device.features->flags; - } - else - return NO_SUPPORT; /* FIXME - should differentiate problem */ - /* The device plugin has a dependency on a render plugin, * so the render plugin should be available as well now */ plugin = gvc->api[API_render]; if (plugin) { - typeptr = plugin->typeptr; - job->render.engine = (gvrender_engine_t *) (typeptr->engine); - job->render.features = (gvrender_features_t *) (typeptr->features); - job->render.type = plugin->typestr; + typeptr = plugin->typeptr; + job->render.engine = (gvrender_engine_t *) (typeptr->engine); + job->render.features = (gvrender_features_t *) (typeptr->features); + job->render.type = plugin->typestr; - job->flags |= job->render.features->flags; + job->flags |= job->render.features->flags; - if (job->device.engine) - job->render.id = typeptr->id; + if (job->device.engine) + job->render.id = typeptr->id; else /* A null device engine indicates that the device id is also the renderer id * and that the renderer doesn't need "device" functions. * Device "features" settings are still available */ - job->render.id = job->device.id; - return GVRENDER_PLUGIN; + job->render.id = job->device.id; + return GVRENDER_PLUGIN; } job->render.engine = NULL; - return NO_SUPPORT; /* FIXME - should differentiate problem */ + return NO_SUPPORT; /* FIXME - should differentiate problem */ } int gvrender_features(GVJ_t * job) @@ -128,7 +128,7 @@ int gvrender_begin_job(GVJ_t * job) if (gvdevice_initialize(job)) return 1; if (gvre) { - if (gvre->begin_job) + if (gvre->begin_job) gvre->begin_job(job); } return 0; @@ -139,10 +139,10 @@ void gvrender_end_job(GVJ_t * job) gvrender_engine_t *gvre = job->render.engine; if (gvre) { - if (gvre->end_job) + if (gvre->end_job) gvre->end_job(job); } - job->gvc->common.lib = NULL; /* FIXME - minimally this doesn't belong here */ + job->gvc->common.lib = NULL; /* FIXME - minimally this doesn't belong here */ gvdevice_finalize(job); } @@ -151,7 +151,7 @@ void gvrender_end_job(GVJ_t * job) #define BOLD 1 #define ITALIC 2 -pointf gvrender_ptf(GVJ_t *job, pointf p) +pointf gvrender_ptf(GVJ_t * job, pointf p) { pointf rv, translation, scale; @@ -160,11 +160,11 @@ pointf gvrender_ptf(GVJ_t *job, pointf p) scale.y = job->zoom * job->devscale.y; if (job->rotation) { - rv.x = -(p.y + translation.y) * scale.x; - rv.y = (p.x + translation.x) * scale.y; + rv.x = -(p.y + translation.y) * scale.x; + rv.y = (p.x + translation.x) * scale.y; } else { - rv.x = (p.x + translation.x) * scale.x; - rv.y = (p.y + translation.y) * scale.y; + rv.x = (p.x + translation.x) * scale.x; + rv.y = (p.y + translation.y) * scale.y; } return rv; } @@ -172,7 +172,7 @@ pointf gvrender_ptf(GVJ_t *job, pointf p) /* transform an array of n points */ /* *AF and *af must be preallocated */ /* *AF can be the same as *af for inplace transforms */ -pointf* gvrender_ptf_A(GVJ_t *job, pointf *af, pointf *AF, int n) +pointf *gvrender_ptf_A(GVJ_t * job, pointf * af, pointf * AF, int n) { int i; double t; @@ -183,16 +183,15 @@ pointf* gvrender_ptf_A(GVJ_t *job, pointf *af, pointf *AF, int n) scale.y = job->zoom * job->devscale.y; if (job->rotation) { - for (i = 0; i < n; i++) { - t = -(af[i].y + translation.y) * scale.x; - AF[i].y = (af[i].x + translation.x) * scale.y; + for (i = 0; i < n; i++) { + t = -(af[i].y + translation.y) * scale.x; + AF[i].y = (af[i].x + translation.x) * scale.y; AF[i].x = t; } - } - else { - for (i = 0; i < n; i++) { - AF[i].x = (af[i].x + translation.x) * scale.x; - AF[i].y = (af[i].y + translation.y) * scale.y; + } else { + for (i = 0; i < n; i++) { + AF[i].x = (af[i].x + translation.x) * scale.x; + AF[i].y = (af[i].y + translation.y) * scale.y; } } return AF; @@ -212,8 +211,11 @@ static void gvrender_resolve_color(gvrender_features_t * features, color->u.string = name; color->type = COLOR_STRING; tok = canontoken(name); - if (!features->knowncolors || (bsearch(&tok, features->knowncolors, features->sz_knowncolors, - sizeof(char *), gvrender_comparestr)) == NULL) { + if (!features->knowncolors + || + (bsearch + (&tok, features->knowncolors, features->sz_knowncolors, + sizeof(char *), gvrender_comparestr)) == NULL) { /* if tok was not found in known_colors */ rc = colorxlate(name, color, features->color_type); if (rc != COLOR_OK) { @@ -223,8 +225,7 @@ static void gvrender_resolve_color(gvrender_features_t * features, if (emit_once(missedcolor)) agerr(AGWARN, "%s is not a known color.\n", name); free(missedcolor); - } - else { + } else { agerr(AGERR, "error in colxlate()\n"); } } @@ -233,21 +234,24 @@ static void gvrender_resolve_color(gvrender_features_t * features, void gvrender_begin_graph(GVJ_t * job, graph_t * g) { - GVC_t *gvc = job->gvc; + /* GVC_t *gvc = job->gvc; */ gvrender_engine_t *gvre = job->render.engine; - char *s; + /* char *s; */ if (gvre) { /* render specific init */ if (gvre->begin_graph) gvre->begin_graph(job); +#if 0 /* background color */ if (((s = agget(g, "bgcolor")) != 0) && s[0]) { - gvrender_resolve_color(job->render.features, s, &(gvc->bgcolor)); + gvrender_resolve_color(job->render.features, s, + &(gvc->bgcolor)); if (gvre->resolve_color) gvre->resolve_color(job, &(gvc->bgcolor)); } +#endif } } @@ -257,7 +261,7 @@ void gvrender_end_graph(GVJ_t * job) gvrender_engine_t *gvre = job->render.engine; if (gvre) { - if (gvre->end_graph) + if (gvre->end_graph) gvre->end_graph(job); } gvdevice_format(job); @@ -268,7 +272,7 @@ void gvrender_begin_page(GVJ_t * job) gvrender_engine_t *gvre = job->render.engine; if (gvre) { - if (gvre->begin_page) + if (gvre->begin_page) gvre->begin_page(job); } } @@ -278,7 +282,7 @@ void gvrender_end_page(GVJ_t * job) gvrender_engine_t *gvre = job->render.engine; if (gvre) { - if (gvre->end_page) + if (gvre->end_page) gvre->end_page(job); } } @@ -289,7 +293,8 @@ void gvrender_begin_layer(GVJ_t * job) if (gvre) { if (gvre->begin_layer) - gvre->begin_layer(job, job->gvc->layerIDs[job->layerNum], job->layerNum, job->numLayers); + gvre->begin_layer(job, job->gvc->layerIDs[job->layerNum], + job->layerNum, job->numLayers); } } @@ -298,7 +303,7 @@ void gvrender_end_layer(GVJ_t * job) gvrender_engine_t *gvre = job->render.engine; if (gvre) { - if (gvre->end_layer) + if (gvre->end_layer) gvre->end_layer(job); } } @@ -313,12 +318,12 @@ void gvrender_begin_cluster(GVJ_t * job, graph_t * sg) } } -void gvrender_end_cluster(GVJ_t * job, graph_t *g) +void gvrender_end_cluster(GVJ_t * job, graph_t * g) { gvrender_engine_t *gvre = job->render.engine; if (gvre) { - if (gvre->end_cluster) + if (gvre->end_cluster) gvre->end_cluster(job); } } @@ -403,7 +408,8 @@ void gvrender_end_edge(GVJ_t * job) } } -void gvrender_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target, char *id) +void gvrender_begin_anchor(GVJ_t * job, char *href, char *tooltip, + char *target, char *id) { gvrender_engine_t *gvre = job->render.engine; @@ -426,20 +432,20 @@ void gvrender_end_anchor(GVJ_t * job) void gvrender_begin_label(GVJ_t * job, label_type type) { gvrender_engine_t *gvre = job->render.engine; - + if (gvre) { - if (gvre->begin_label) - gvre->begin_label(job, type); + if (gvre->begin_label) + gvre->begin_label(job, type); } } void gvrender_end_label(GVJ_t * job) { gvrender_engine_t *gvre = job->render.engine; - + if (gvre) { - if (gvre->end_label) - gvre->end_label(job); + if (gvre->end_label) + gvre->end_label(job); } } @@ -449,8 +455,8 @@ void gvrender_textpara(GVJ_t * job, pointf p, textpara_t * para) pointf PF; if (para->str && para->str[0] - && ( ! job->obj /* because of xdgen non-conformity */ - || job->obj->pen != PEN_NONE)) { + && (!job->obj /* because of xdgen non-conformity */ + || job->obj->pen != PEN_NONE)) { if (job->flags & GVRENDER_DOES_TRANSFORM) PF = p; else @@ -468,14 +474,14 @@ void gvrender_set_pencolor(GVJ_t * job, char *name) gvcolor_t *color = &(job->obj->pencolor); char *cp = NULL; - if ((cp = strstr(name, ":"))) /* if its a color list, then use only first */ + if ((cp = strstr(name, ":"))) /* if its a color list, then use only first */ *cp = '\0'; if (gvre) { gvrender_resolve_color(job->render.features, name, color); if (gvre->resolve_color) gvre->resolve_color(job, color); } - if (cp) /* restore color list */ + if (cp) /* restore color list */ *cp = ':'; } @@ -485,7 +491,7 @@ void gvrender_set_fillcolor(GVJ_t * job, char *name) gvcolor_t *color = &(job->obj->fillcolor); char *cp = NULL; - if ((cp = strstr(name, ":"))) /* if its a color list, then use only first */ + if ((cp = strstr(name, ":"))) /* if its a color list, then use only first */ *cp = '\0'; if (gvre) { gvrender_resolve_color(job->render.features, name, color); @@ -496,105 +502,107 @@ void gvrender_set_fillcolor(GVJ_t * job, char *name) *cp = ':'; } -void gvrender_set_gradientcolor(GVJ_t * job, char *gr_color_ptr[2]) +static void gvrender_set_gradientcolor(GVJ_t * job, char *colors[2]) { gvrender_engine_t *gvre = job->render.engine; gvcolor_t *color; - char * start_color, * stop_color; - - start_color = gr_color_ptr[0]; - stop_color = gr_color_ptr[1]; - if (gvre && gr_color_ptr[0] != NULL && gr_color_ptr[1] != NULL) { - color = &(job->obj->gradient.startcolor); - gvrender_resolve_color(job->render.features, start_color, color); - if (gvre->resolve_color) - gvre->resolve_color(job, color); - color = &(job->obj->gradient.stopcolor); - gvrender_resolve_color(job->render.features, stop_color, color); - if (gvre->resolve_color) - gvre->resolve_color(job, color); - } -} - -void gvrender_set_gradientAngle(GVJ_t * job, int angle) -{ - obj_state_t *obj = job->obj; - obj->gradient.angle = angle; - -} -static int gradientId; -void gvrender_set_gradientId(GVJ_t * job){ - - obj_state_t *obj = job->obj; - obj->gradient.id = gradientId++; -} - -void gvrender_set_gradient_attr(GVJ_t * job, void *g_obj, attrsym_t * color_attr, attrsym_t * angle_attr){ - char *color; - int angle; - - if(color_attr != NULL) { - color = N_GNEW(GR_SZ,char); - strcpy(color,findAttrColor(g_obj, color_attr, "")); - if ( angle_attr != NULL ) - angle = findGradientAngle(g_obj,angle_attr); - else - angle = 0; - gvrender_set_gradient(job, g_obj, color, angle); - free(color); - } - -} - -void gvrender_set_gradient(GVJ_t * job, void *g_obj, char * color, int angle){ -char *gradcolor = NULL,*startcolor,*stopcolor; - - if(color != NULL) { - gradcolor = N_GNEW((2 * GR_SZ)+1,char); - startcolor = strdup(color); - stopcolor = strdup(color); - findGradientColor(g_obj,GR_START,startcolor,DEFAULT_FILL); - strcpy(gradcolor,startcolor); - strcat(gradcolor,":"); - strcat(gradcolor,findGradientColor(g_obj,GR_STOP, stopcolor, startcolor)); /* use start color as stop color if : missing */ - gvrender_set_gradient_values(job,gradcolor,angle); - free(startcolor); - free(stopcolor); - free(gradcolor); - } - + + if (gvre && colors[0]) { + color = &(job->obj->fillcolor); + gvrender_resolve_color(job->render.features, colors[0], color); + if (gvre->resolve_color) + gvre->resolve_color(job, color); + } + if (gvre && colors[1]) { + color = &(job->obj->stopcolor); + gvrender_resolve_color(job->render.features, colors[1], color); + if (gvre->resolve_color) + gvre->resolve_color(job, color); + } +} + +void gvrender_set_gradient_attr(GVJ_t * job, void *g_obj, + attrsym_t * color_attr, + attrsym_t * angle_attr) +{ + char *color; + int angle; + + if (color_attr != NULL) { + color = N_GNEW(GR_SZ, char); + strcpy(color, findAttrColor(g_obj, color_attr, "")); + if (angle_attr != NULL) + angle = findGradientAngle(g_obj, angle_attr); + else + angle = 0; + gvrender_set_gradient(job, g_obj, color, angle); + free(color); + } + +} + +void gvrender_set_gradient(GVJ_t * job, void *g_obj, char *color, + int angle) +{ + char *gradcolor = NULL, *startcolor, *stopcolor; + + if (color != NULL) { + gradcolor = N_GNEW((2 * GR_SZ) + 1, char); + startcolor = strdup(color); + stopcolor = strdup(color); + findGradientColor(g_obj, GR_START, startcolor, DEFAULT_FILL); + strcpy(gradcolor, startcolor); + strcat(gradcolor, ":"); + strcat(gradcolor, findGradientColor(g_obj, GR_STOP, stopcolor, startcolor)); /* use start color as stop color if : missing */ + gvrender_set_gradient_values(job, gradcolor, angle); + free(startcolor); + free(stopcolor); + free(gradcolor); + } + } static char gradientcolor[2][GR_SZ]; -char *gvrender_set_gradient_values(GVJ_t* job, char* gradcolor, int angle){ +char *gvrender_set_gradient_values(GVJ_t * job, char *gradcolor, int angle) +{ char *gr_color_ptr[2], *ptr; gr_color_ptr[0] = gradientcolor[0]; gr_color_ptr[1] = gradientcolor[1]; gr_color_ptr[0][GR_SZ - 1] = gr_color_ptr[0][0] = 0; gr_color_ptr[1][GR_SZ - 1] = gr_color_ptr[1][0] = 0; - if(gradcolor != NULL && gradcolor[0]){ - ptr= strstr(gradcolor,":"); - if(ptr != NULL){ - *ptr = '\0'; - ++ptr; - if(ptr[0]) - strncpy(gr_color_ptr[1],ptr,GR_SZ - 1); - else - strncpy(gr_color_ptr[1],gradcolor,GR_SZ - 1); //use start color as stop color - } - else - strncpy(gr_color_ptr[1],gradcolor,GR_SZ - 1); //use start color as stop color - strncpy(gr_color_ptr[0],gradcolor,GR_SZ - 1); - gvrender_set_gradientcolor(job, gr_color_ptr); - gvrender_set_gradientAngle(job,angle); - gvrender_set_gradientId(job); + if (gradcolor != NULL && gradcolor[0]) { + ptr = strstr(gradcolor, ":"); + if (ptr != NULL) { + *ptr = '\0'; + ++ptr; + if (ptr[0]) + strncpy(gr_color_ptr[1], ptr, GR_SZ - 1); + else + strncpy(gr_color_ptr[1], gradcolor, GR_SZ - 1); //use start color as stop color + } else + strncpy(gr_color_ptr[1], gradcolor, GR_SZ - 1); //use start color as stop color + strncpy(gr_color_ptr[0], gradcolor, GR_SZ - 1); + gvrender_set_gradientcolor(job, gr_color_ptr); + job->obj->gradient_angle = angle; } return gr_color_ptr[1]; } +void gvrender_set_gradient_vals (GVJ_t * job, char *stopcolor, int angle) +{ + gvrender_engine_t *gvre = job->render.engine; + gvcolor_t *color = &(job->obj->stopcolor); + + if (gvre) { + gvrender_resolve_color(job->render.features, stopcolor, color); + if (gvre->resolve_color) + gvre->resolve_color(job, color); + } + job->obj->gradient_angle = angle; +} void gvrender_set_style(GVJ_t * job, char **s) { @@ -604,34 +612,34 @@ void gvrender_set_style(GVJ_t * job, char **s) obj->rawstyle = s; if (gvre) { - if (s) while ((p = line = *s++)) { - if (streq(line, "solid")) - obj->pen = PEN_SOLID; - else if (streq(line, "dashed")) - obj->pen = PEN_DASHED; - else if (streq(line, "dotted")) - obj->pen = PEN_DOTTED; - else if (streq(line, "invis") || streq(line, "invisible")) - obj->pen = PEN_NONE; - else if (streq(line, "bold")) - obj->penwidth = PENWIDTH_BOLD; - else if (streq(line, "setlinewidth")) { - while (*p) + if (s) + while ((p = line = *s++)) { + if (streq(line, "solid")) + obj->pen = PEN_SOLID; + else if (streq(line, "dashed")) + obj->pen = PEN_DASHED; + else if (streq(line, "dotted")) + obj->pen = PEN_DOTTED; + else if (streq(line, "invis") || streq(line, "invisible")) + obj->pen = PEN_NONE; + else if (streq(line, "bold")) + obj->penwidth = PENWIDTH_BOLD; + else if (streq(line, "setlinewidth")) { + while (*p) + p++; p++; - p++; - obj->penwidth = atof(p); - } else if (streq(line, "filled")) - obj->fill = FILL_SOLID; - else if (streq(line, "unfilled")) - obj->fill = FILL_NONE; - else if (streq(line, "tapered")) - ; - else { - agerr(AGWARN, - "gvrender_set_style: unsupported style %s - ignoring\n", - line); + obj->penwidth = atof(p); + } else if (streq(line, "filled")) + obj->fill = FILL_SOLID; + else if (streq(line, "unfilled")) + obj->fill = FILL_NONE; + else if (streq(line, "tapered")); + else { + agerr(AGWARN, + "gvrender_set_style: unsupported style %s - ignoring\n", + line); + } } - } } } @@ -644,13 +652,13 @@ void gvrender_ellipse(GVJ_t * job, pointf * pf, int n, int filled) pointf af[2]; /* center */ - af[0].x = (pf[0].x + pf[1].x)/2.; - af[0].y = (pf[0].y + pf[1].y)/2.; + af[0].x = (pf[0].x + pf[1].x) / 2.; + af[0].y = (pf[0].y + pf[1].y) / 2.; /* corner */ af[1] = pf[1]; - if (! (job->flags & GVRENDER_DOES_TRANSFORM)) - gvrender_ptf_A(job, af, af, 2); + if (!(job->flags & GVRENDER_DOES_TRANSFORM)) + gvrender_ptf_A(job, af, af, 2); gvre->ellipse(job, af, filled); } } @@ -664,12 +672,12 @@ void gvrender_polygon(GVJ_t * job, pointf * af, int n, int filled) if (job->flags & GVRENDER_DOES_TRANSFORM) gvre->polygon(job, af, n, filled); else { - if (sizeAF < n) { - sizeAF = n+10; + if (sizeAF < n) { + sizeAF = n + 10; AF = grealloc(AF, sizeAF * sizeof(pointf)); - } - gvrender_ptf_A(job, af, AF, n); - gvre->polygon(job, AF, n, filled); + } + gvrender_ptf_A(job, af, AF, n); + gvre->polygon(job, AF, n, filled); } } } @@ -686,26 +694,29 @@ void gvrender_box(GVJ_t * job, boxf B, int filled) A[1].y = A[2].y; A[3].x = A[2].x; A[3].y = A[0].y; - + gvrender_polygon(job, A, 4, filled); } void gvrender_beziercurve(GVJ_t * job, pointf * af, int n, - int arrow_at_start, int arrow_at_end, boolean filled) + int arrow_at_start, int arrow_at_end, + boolean filled) { gvrender_engine_t *gvre = job->render.engine; if (gvre) { if (gvre->beziercurve && job->obj->pen != PEN_NONE) { if (job->flags & GVRENDER_DOES_TRANSFORM) - gvre->beziercurve(job, af, n, arrow_at_start, arrow_at_end,filled); + gvre->beziercurve(job, af, n, arrow_at_start, arrow_at_end, + filled); else { - if (sizeAF < n) { - sizeAF = n+10; + if (sizeAF < n) { + sizeAF = n + 10; AF = grealloc(AF, sizeAF * sizeof(pointf)); - } - gvrender_ptf_A(job, af, AF, n); - gvre->beziercurve(job, AF, n, arrow_at_start, arrow_at_end,filled); + } + gvrender_ptf_A(job, af, AF, n); + gvre->beziercurve(job, AF, n, arrow_at_start, arrow_at_end, + filled); } } } @@ -718,14 +729,14 @@ void gvrender_polyline(GVJ_t * job, pointf * af, int n) if (gvre) { if (gvre->polyline && job->obj->pen != PEN_NONE) { if (job->flags & GVRENDER_DOES_TRANSFORM) - gvre->polyline(job, af, n); - else { - if (sizeAF < n) { - sizeAF = n+10; + gvre->polyline(job, af, n); + else { + if (sizeAF < n) { + sizeAF = n + 10; AF = grealloc(AF, sizeAF * sizeof(pointf)); - } - gvrender_ptf_A(job, af, AF, n); - gvre->polyline(job, AF, n); + } + gvrender_ptf_A(job, af, AF, n); + gvre->polyline(job, AF, n); } } } @@ -746,38 +757,44 @@ void gvrender_comment(GVJ_t * job, char *str) static imagescale_t get_imagescale(char *s) { - if (*s == '\0') return IMAGESCALE_FALSE; - if (!strcasecmp(s, "width")) return IMAGESCALE_WIDTH; - if (!strcasecmp(s, "height")) return IMAGESCALE_HEIGHT; - if (!strcasecmp(s, "both")) return IMAGESCALE_BOTH; - if (mapbool(s)) return IMAGESCALE_TRUE; - return IMAGESCALE_FALSE; + if (*s == '\0') + return IMAGESCALE_FALSE; + if (!strcasecmp(s, "width")) + return IMAGESCALE_WIDTH; + if (!strcasecmp(s, "height")) + return IMAGESCALE_HEIGHT; + if (!strcasecmp(s, "both")) + return IMAGESCALE_BOTH; + if (mapbool(s)) + return IMAGESCALE_TRUE; + return IMAGESCALE_FALSE; } /* gvrender_usershape: * Scale image to fill polygon bounding box according to "imagescale" */ -void gvrender_usershape(GVJ_t * job, char *name, pointf * a, int n, - boolean filled, char *imagescale) +void gvrender_usershape(GVJ_t * job, char *name, pointf * a, int n, + boolean filled, char *imagescale) { gvrender_engine_t *gvre = job->render.engine; usershape_t *us; double iw, ih, pw, ph; - double scalex, scaley; /* scale factors */ - boxf b; /* target box */ + double scalex, scaley; /* scale factors */ + boxf b; /* target box */ int i; - point isz; + point isz; - if (! (us = gvusershape_find(name))) { + if (!(us = gvusershape_find(name))) { if (find_user_shape(name)) { if (gvre && gvre->library_shape) - gvre->library_shape(job, name, a, n, filled); + gvre->library_shape(job, name, a, n, filled); } - return; + return; } - isz = gvusershape_size_dpi (us, job->dpi); - if ((isz.x <= 0) && (isz.y <= 0)) return; + isz = gvusershape_size_dpi(us, job->dpi); + if ((isz.x <= 0) && (isz.y <= 0)) + return; /* compute bb of polygon */ b.LL = b.UR = a[0]; @@ -787,15 +804,15 @@ void gvrender_usershape(GVJ_t * job, char *name, pointf * a, int n, pw = b.UR.x - b.LL.x; ph = b.UR.y - b.LL.y; - ih = (double)isz.y; - iw = (double)isz.x; + ih = (double) isz.y; + iw = (double) isz.x; scalex = pw / iw; scaley = ph / ih; switch (get_imagescale(imagescale)) { case IMAGESCALE_TRUE: - /* keep aspect ratio fixed by just using the smaller scale */ + /* keep aspect ratio fixed by just using the smaller scale */ if (scalex < scaley) { iw *= scalex; ih *= scalex; @@ -821,12 +838,12 @@ void gvrender_usershape(GVJ_t * job, char *name, pointf * a, int n, /* if image is smaller than target area then center it */ if (iw < pw) { - b.LL.x += (pw - iw) / 2.0; - b.UR.x -= (pw - iw) / 2.0; + b.LL.x += (pw - iw) / 2.0; + b.UR.x -= (pw - iw) / 2.0; } if (ih < ph) { - b.LL.y += (ph - ih) / 2.0; - b.UR.y -= (ph - ih) / 2.0; + b.LL.y += (ph - ih) / 2.0; + b.UR.y -= (ph - ih) / 2.0; } /* convert from graph to device coordinates */ @@ -855,7 +872,7 @@ void gvrender_set_penwidth(GVJ_t * job, double penwidth) gvrender_engine_t *gvre = job->render.engine; if (gvre) { - job->obj->penwidth = penwidth; - /*if (gvre->set_penwidth) gvre->set_penwidth(job, penwidth);*/ + job->obj->penwidth = penwidth; + /*if (gvre->set_penwidth) gvre->set_penwidth(job, penwidth); */ } } diff --git a/plugin/core/gvrender_core_svg.c b/plugin/core/gvrender_core_svg.c index 07cbc3ca3..f4d509850 100644 --- a/plugin/core/gvrender_core_svg.c +++ b/plugin/core/gvrender_core_svg.c @@ -34,19 +34,14 @@ #include "const.h" #include "gvplugin_render.h" +#include "agxbuf.h" +#include "utils.h" #include "gvplugin_device.h" #include "gvio.h" #include "gvcint.h" -extern char *strdup_and_subst_obj(char *str, void *obj); - typedef enum { FORMAT_SVG, FORMAT_SVGZ, } format_type; -extern char *xml_string(char *str); -extern char *xml_url_string(char *str); -extern void cairogen_get_gradient_points(pointf * A, pointf * G, int n, float angle); -extern void cairogen_get_rgradient_points(pointf * A, pointf * G, int n); - /* SVG dash array */ static char *sdasharray = "5,2"; /* SVG dot array */ @@ -78,39 +73,36 @@ static void svg_print_color(GVJ_t * job, gvcolor_t color) gvputs(job, color.u.string); break; case RGBA_BYTE: - if (color.u.rgba[3] == 0) /* transparent */ + if (color.u.rgba[3] == 0) /* transparent */ gvputs(job, "none"); else gvprintf(job, "#%02x%02x%02x", - color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]); + color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]); break; default: assert(0); /* internal error */ } } -static void svg_grstyle(GVJ_t * job, int filled) +static void svg_grstyle(GVJ_t * job, int filled, int gid) { obj_state_t *obj = job->obj; - char sgid[11]; gvputs(job, " fill=\""); - if (filled == GRADIENT){ - sprintf(sgid,"%d",obj->gradient.id); - gvprintf(job,"url(#l_%s)",sgid); - } - else if (filled == RGRADIENT){ - sprintf(sgid,"%d",obj->gradient.id); - gvprintf(job,"url(#r_%s)",sgid); - } - else if (filled) { + if (filled == GRADIENT) { + gvprintf(job, "url(#l_%d)", gid); + } else if (filled == RGRADIENT) { + gvprintf(job, "url(#r_%d)", gid); + } else if (filled) { svg_print_color(job, obj->fillcolor); - if (obj->fillcolor.type == RGBA_BYTE && obj->fillcolor.u.rgba[3] > 0 && obj->fillcolor.u.rgba[3] < 255 ) - gvprintf(job, "\" fill-opacity=\"%f", ((float)obj->fillcolor.u.rgba[3]/255.0)); + if (obj->fillcolor.type == RGBA_BYTE + && obj->fillcolor.u.rgba[3] > 0 + && obj->fillcolor.u.rgba[3] < 255) + gvprintf(job, "\" fill-opacity=\"%f", + ((float) obj->fillcolor.u.rgba[3] / 255.0)); gvputs(job, "\" stroke=\""); svg_print_color(job, obj->pencolor); - } - else { + } else { gvputs(job, "none"); gvputs(job, "\" stroke=\""); svg_print_color(job, obj->pencolor); @@ -122,8 +114,10 @@ static void svg_grstyle(GVJ_t * job, int filled) } else if (obj->pen == PEN_DOTTED) { gvprintf(job, "\" stroke-dasharray=\"%s", sdotarray); } - if (obj->pencolor.type == RGBA_BYTE && obj->pencolor.u.rgba[3] > 0 && obj->pencolor.u.rgba[3] < 255) - gvprintf(job, "\" stroke-opacity=\"%f", ((float)obj->pencolor.u.rgba[3]/255.0)); + if (obj->pencolor.type == RGBA_BYTE && obj->pencolor.u.rgba[3] > 0 + && obj->pencolor.u.rgba[3] < 255) + gvprintf(job, "\" stroke-opacity=\"%f", + ((float) obj->pencolor.u.rgba[3] / 255.0)); gvputs(job, "\""); } @@ -138,20 +132,24 @@ static void svg_comment(GVJ_t * job, char *str) static void svg_begin_job(GVJ_t * job) { char *s; - gvputs(job, "\n"); + gvputs(job, + "\n"); if ((s = agget(job->gvc->g, "stylesheet")) && s[0]) { - gvputs(job, "\n"); + gvputs(job, "\n"); } #if 0 gvputs(job, "\n]"); + gvputs(job, + " [\n \n]"); #else - gvputs(job, "\n"); + gvputs(job, "\n"); #endif gvputs(job, "\n", job->pagesArraySize.x * job->pagesArraySize.y); + gvprintf(job, " Pages: %d -->\n", + job->pagesArraySize.x * job->pagesArraySize.y); gvprintf(job, "width, job->height); + job->width, job->height); gvprintf(job, " viewBox=\"%.2f %.2f %.2f %.2f\"", - job->canvasBox.LL.x, job->canvasBox.LL.y, - job->canvasBox.UR.x, job->canvasBox.UR.y); + job->canvasBox.LL.x, job->canvasBox.LL.y, + job->canvasBox.UR.x, job->canvasBox.UR.y); /* namespace of svg */ gvputs(job, " xmlns=\"http://www.w3.org/2000/svg\""); /* namespace of xlink */ @@ -192,7 +191,8 @@ static void svg_end_graph(GVJ_t * job) gvputs(job, "\n"); } -static void svg_begin_layer(GVJ_t * job, char *layername, int layerNum, int numLayers) +static void svg_begin_layer(GVJ_t * job, char *layername, int layerNum, + int numLayers) { gvputs(job, "id)); gvputs(job, "\" class=\"graph\""); - gvprintf(job, " transform=\"scale(%g %g) rotate(%d) translate(%g %g)\">\n", - job->scale.x, job->scale.y, -job->rotation, - job->translation.x, -job->translation.y); + gvprintf(job, + " transform=\"scale(%g %g) rotate(%d) translate(%g %g)\">\n", + job->scale.x, job->scale.y, -job->rotation, + job->translation.x, -job->translation.y); /* default style */ if (agnameof(obj->u.g)[0]) { - gvputs(job, ""); - gvputs(job, xml_string(agnameof(obj->u.g))); - gvputs(job, "\n"); + gvputs(job, ""); + gvputs(job, xml_string(agnameof(obj->u.g))); + gvputs(job, "\n"); } } @@ -263,8 +264,7 @@ static void svg_end_node(GVJ_t * job) gvputs(job, "\n"); } -static void -svg_begin_edge(GVJ_t * job) +static void svg_begin_edge(GVJ_t * job) { obj_state_t *obj = job->obj; char *ename; @@ -272,9 +272,9 @@ svg_begin_edge(GVJ_t * job) gvputs(job, "id)); gvputs(job, "\" class=\"edge\">"); - + gvputs(job, ""); - ename = strdup_and_subst_obj("\\E", (void*)(obj->u.e)); + ename = strdup_and_subst_obj("\\E", (void *) (obj->u.e)); gvputs(job, xml_string(ename)); free(ename); gvputs(job, "\n"); @@ -286,7 +286,8 @@ static void svg_end_edge(GVJ_t * job) } static void -svg_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target, char *id) +svg_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target, + char *id) { gvputs(job, "obj; PostscriptAlias *pA; - char *family=NULL, *weight=NULL, *stretch=NULL, *style=NULL; + char *family = NULL, *weight = NULL, *stretch = NULL, *style = NULL; int flags; gvputs(job, "postscript_alias; if (pA) { - switch(GD_fontnames(job->gvc->g)) { - case PSFONTS: - family = pA->name; - weight = pA->weight; - style = pA->style; - break; - case SVGFONTS: - family = pA->svg_font_family; - weight = pA->svg_font_weight; - style = pA->svg_font_style; - break; - default: - case NATIVEFONTS: - family = pA->family; - weight = pA->weight; - style = pA->style; - break; + switch (GD_fontnames(job->gvc->g)) { + case PSFONTS: + family = pA->name; + weight = pA->weight; + style = pA->style; + break; + case SVGFONTS: + family = pA->svg_font_family; + weight = pA->svg_font_weight; + style = pA->svg_font_style; + break; + default: + case NATIVEFONTS: + family = pA->family; + weight = pA->weight; + style = pA->style; + break; } stretch = pA->stretch; - gvprintf(job, " font-family=\"%s", family); - if (pA->svg_font_family) gvprintf(job, ",%s", pA->svg_font_family); - gvputs(job, "\""); - if (weight) gvprintf(job, " font-weight=\"%s\"", weight); - if (stretch) gvprintf(job, " font-stretch=\"%s\"", stretch); - if (style) gvprintf(job, " font-style=\"%s\"", style); - } - else + gvprintf(job, " font-family=\"%s", family); + if (pA->svg_font_family) + gvprintf(job, ",%s", pA->svg_font_family); + gvputs(job, "\""); + if (weight) + gvprintf(job, " font-weight=\"%s\"", weight); + if (stretch) + gvprintf(job, " font-stretch=\"%s\"", stretch); + if (style) + gvprintf(job, " font-style=\"%s\"", style); + } else gvprintf(job, " font-family=\"%s\"", para->fontname); if ((para->font) && (flags = para->font->flags)) { - if ((flags & HTML_BF) && !weight) gvprintf(job, " font-weight=\"bold\""); - if ((flags & HTML_IF) && !style) gvprintf(job, " font-style=\"italic\""); - if ((flags & HTML_UL)) gvprintf(job, " text-decoration=\"underline\""); - if ((flags & HTML_SUP)) gvprintf(job, " baseline-shift=\"super\""); - if ((flags & HTML_SUB)) gvprintf(job, " baseline-shift=\"sub\""); + if ((flags & HTML_BF) && !weight) + gvprintf(job, " font-weight=\"bold\""); + if ((flags & HTML_IF) && !style) + gvprintf(job, " font-style=\"italic\""); + if ((flags & HTML_UL)) + gvprintf(job, " text-decoration=\"underline\""); + if ((flags & HTML_SUP)) + gvprintf(job, " baseline-shift=\"super\""); + if ((flags & HTML_SUB)) + gvprintf(job, " baseline-shift=\"sub\""); } gvprintf(job, " font-size=\"%.2f\"", para->fontsize); @@ -396,7 +405,8 @@ static void svg_textpara(GVJ_t * job, pointf p, textpara_t * para) break; case RGBA_BYTE: gvprintf(job, " fill=\"#%02x%02x%02x\"", - obj->pencolor.u.rgba[0], obj->pencolor.u.rgba[1], obj->pencolor.u.rgba[2]); + obj->pencolor.u.rgba[0], obj->pencolor.u.rgba[1], + obj->pencolor.u.rgba[2]); break; default: assert(0); /* internal error */ @@ -406,107 +416,116 @@ static void svg_textpara(GVJ_t * job, pointf p, textpara_t * para) gvputs(job, "\n"); } +static int gradId; + /* svg_gradstyle * Outputs the SVG statements that define the gradient pattern */ -static void svg_gradstyle(GVJ_t * job, pointf * A, int n) +static int svg_gradstyle(GVJ_t * job, pointf * A, int n) { - pointf G[2]; - float angle; - char sgid[11]; - - obj_state_t *obj = job->obj; - angle = obj->gradient.angle * M_PI / 180; //angle of gradient line - G[0].x = G[0].y = G[1].x = G[1].y = 0.; - cairogen_get_gradient_points(A, G, n, angle); //get points on gradient line - sprintf(sgid,"%d",obj->gradient.id); - - gvprintf(job, "\n\n", G[0].x,G[0].y,G[1].x,G[1].y); - gvputs(job,"gradient.startcolor); - gvputs(job,";stop-opacity:"); - if (obj->gradient.startcolor.type == RGBA_BYTE && obj->gradient.startcolor.u.rgba[3] > 0 && obj->gradient.startcolor.u.rgba[3] < 255 ) - gvprintf(job, "%f", ((float)obj->gradient.startcolor.u.rgba[3]/255.0)); - else gvputs(job,"1."); - gvputs(job,";\"/>\n"); - gvputs(job,"gradient.stopcolor); - gvputs(job,";stop-opacity:"); - if (obj->gradient.stopcolor.type == RGBA_BYTE && obj->gradient.stopcolor.u.rgba[3] > 0 && obj->gradient.stopcolor.u.rgba[3] < 255 ) - gvprintf(job, "%f", ((float)obj->gradient.stopcolor.u.rgba[3]/255.0)); - else gvputs(job,"1."); - gvputs(job,";\"/>\n\n\n"); + pointf G[2]; + float angle; + int id = gradId++; + + obj_state_t *obj = job->obj; + angle = obj->gradient_angle * M_PI / 180; //angle of gradient line + G[0].x = G[0].y = G[1].x = G[1].y = 0.; + get_gradient_points(A, G, n, angle, 0); //get points on gradient line + + gvprintf(job, + "\n\n", G[0].x, + G[0].y, G[1].x, G[1].y); + gvputs(job, "fillcolor); + gvputs(job, ";stop-opacity:"); + if (obj->fillcolor.type == RGBA_BYTE && obj->fillcolor.u.rgba[3] > 0 + && obj->fillcolor.u.rgba[3] < 255) + gvprintf(job, "%f", ((float) obj->fillcolor.u.rgba[3] / 255.0)); + else + gvputs(job, "1."); + gvputs(job, ";\"/>\n"); + gvputs(job, "stopcolor); + gvputs(job, ";stop-opacity:"); + if (obj->stopcolor.type == RGBA_BYTE && obj->stopcolor.u.rgba[3] > 0 + && obj->stopcolor.u.rgba[3] < 255) + gvprintf(job, "%f", ((float) obj->stopcolor.u.rgba[3] / 255.0)); + else + gvputs(job, "1."); + gvputs(job, ";\"/>\n\n\n"); + return id; } -/* svg_gradstyle +/* svg_rgradstyle * Outputs the SVG statements that define the radial gradient pattern */ -static void svg_rgradstyle(GVJ_t * job, pointf * A, int n) +static int svg_rgradstyle(GVJ_t * job, pointf * A, int n) { - pointf G[2]; - float angle; - char fx[5],fy[5],sgid[11]; - int ifx,ify; - - obj_state_t *obj = job->obj; - angle = obj->gradient.angle * M_PI / 180; //angle of gradient line - G[0].x = G[0].y = G[1].x = G[1].y = G[2].x = G[2].y= 0.; - cairogen_get_rgradient_points(A, G, n); - if(angle == 0.){ + pointf G[2]; + float angle; + int ifx, ify; + int id = gradId++; + + obj_state_t *obj = job->obj; + angle = obj->gradient_angle * M_PI / 180; //angle of gradient line + G[0].x = G[0].y = G[1].x = G[1].y; + get_gradient_points(A, G, n, 0, 1); + if (angle == 0.) { ifx = ify = 50; - } - else { - ifx = 50*(1 + cos(angle)); - ify = 50*(1 - sin(angle)); - } - sprintf(sgid,"%d",obj->gradient.id); - sprintf(fx,"%d%%",ifx); - sprintf(fy,"%d%%",ify); - gvprintf(job, "\n\n",fy); - gvputs(job,"gradient.startcolor); - gvputs(job,";stop-opacity:"); - if (obj->gradient.startcolor.type == RGBA_BYTE && obj->gradient.startcolor.u.rgba[3] > 0 && obj->gradient.startcolor.u.rgba[3] < 255 ) - gvprintf(job, "%f", ((float)obj->gradient.startcolor.u.rgba[3]/255.0)); - else gvputs(job,"1."); - gvputs(job,";\"/>\n"); - gvputs(job,"gradient.stopcolor); - gvputs(job,";stop-opacity:"); - if (obj->gradient.stopcolor.type == RGBA_BYTE && obj->gradient.stopcolor.u.rgba[3] > 0 && obj->gradient.stopcolor.u.rgba[3] < 255 ) - gvprintf(job, "%f", ((float)obj->gradient.stopcolor.u.rgba[3]/255.0)); - else gvputs(job,"1."); - gvputs(job,";\"/>\n\n\n"); + } else { + ifx = 50 * (1 + cos(angle)); + ify = 50 * (1 - sin(angle)); + } + gvprintf(job, + "\n\n", + id, ifx, ify); + gvputs(job, "fillcolor); + gvputs(job, ";stop-opacity:"); + if (obj->fillcolor.type == RGBA_BYTE && obj->fillcolor.u.rgba[3] > 0 + && obj->fillcolor.u.rgba[3] < 255) + gvprintf(job, "%f", ((float) obj->fillcolor.u.rgba[3] / 255.0)); + else + gvputs(job, "1."); + gvputs(job, ";\"/>\n"); + gvputs(job, "stopcolor); + gvputs(job, ";stop-opacity:"); + if (obj->stopcolor.type == RGBA_BYTE && obj->stopcolor.u.rgba[3] > 0 + && obj->stopcolor.u.rgba[3] < 255) + gvprintf(job, "%f", ((float) obj->stopcolor.u.rgba[3] / 255.0)); + else + gvputs(job, "1."); + gvputs(job, ";\"/>\n\n\n"); + return id; } static void svg_ellipse(GVJ_t * job, pointf * A, int filled) { + int gid = 0; + /* A[] contains 2 points: the center and corner. */ if (filled == GRADIENT) { - svg_gradstyle(job,A,2); - } - else if (filled == (RGRADIENT)){ - svg_rgradstyle(job,A,2); + gid = svg_gradstyle(job, A, 2); + } else if (filled == (RGRADIENT)) { + gid = svg_rgradstyle(job, A, 2); } gvputs(job, "\n"); } static void svg_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, - int arrow_at_end, int filled) + int arrow_at_end, int filled) { gvputs(job, "\n"); @@ -514,15 +533,14 @@ svg_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, static void svg_polygon(GVJ_t * job, pointf * A, int n, int filled) { - int i; + int i, gid = 0; if (filled == GRADIENT) { - svg_gradstyle(job,A,n); - } - else if (filled == (RGRADIENT)){ - svg_rgradstyle(job,A,n); + gid = svg_gradstyle(job, A, n); + } else if (filled == (RGRADIENT)) { + gid = svg_rgradstyle(job, A, n); } gvputs(job, " -extern void cairogen_get_gradient_points(pointf * A, pointf * G, int n, float angle); -extern void cairogen_get_rgradient_points(pointf * A, pointf * G, int n); typedef enum { FORMAT_CAIRO, @@ -292,14 +292,13 @@ if (ry < RMIN) ry = RMIN; cairo_set_matrix(cr, &matrix); if (filled == GRADIENT || filled == (RGRADIENT)) { - angle = obj->gradient.angle * M_PI / 180; + angle = obj->gradient_angle * M_PI / 180; if(filled == GRADIENT) { - angle = obj->gradient.angle * M_PI / 180; - cairogen_get_gradient_points(A, G, 2, angle); + get_gradient_points(A, G, 2, angle, 0); pat = cairo_pattern_create_linear (G[0].x,G[0].y,G[1].x,G[1].y); } else { - cairogen_get_rgradient_points(A, G, 2); + get_gradient_points(A, G, 2, 0, 1); //r1 is inner radius, r2 is outter radius r1 = G[1].x; r2 = G[1].y; @@ -317,8 +316,8 @@ if (ry < RMIN) ry = RMIN; //r1 is inner radius, r2 is outter radius pat = cairo_pattern_create_radial(c1.x,c1.y,r1,c2.x,c2.y,r2); } - cairogen_add_color_stop_rgba(pat,0,&(obj->gradient.startcolor)); - cairogen_add_color_stop_rgba(pat,1,&(obj->gradient.stopcolor)); + cairogen_add_color_stop_rgba(pat,0,&(obj->fillcolor)); + cairogen_add_color_stop_rgba(pat,1,&(obj->stopcolor)); cairo_set_source (cr, pat); cairo_fill_preserve (cr); cairo_pattern_destroy (pat); @@ -348,13 +347,13 @@ cairogen_polygon(GVJ_t * job, pointf * A, int n, int filled) cairo_line_to(cr, A[i].x, -A[i].y); cairo_close_path(cr); if (filled == GRADIENT || filled == (RGRADIENT)) { - angle = obj->gradient.angle * M_PI / 180; + angle = obj->gradient_angle * M_PI / 180; if(filled == GRADIENT) { - cairogen_get_gradient_points(A, G, n, angle); + get_gradient_points(A, G, n, angle, 0); pat = cairo_pattern_create_linear (G[0].x,G[0].y,G[1].x,G[1].y); } else { - cairogen_get_rgradient_points(A, G, n); + get_gradient_points(A, G, n, 0, 1); r1 = G[1].x; r2 = G[1].y; if (angle == 0) { @@ -371,8 +370,8 @@ cairogen_polygon(GVJ_t * job, pointf * A, int n, int filled) //r1 is inner radius, r2 is outter radius pat = cairo_pattern_create_radial(c1.x,c1.y,r1,c2.x,c2.y,r2); } - cairogen_add_color_stop_rgba(pat,0,&(obj->gradient.startcolor)); - cairogen_add_color_stop_rgba(pat,1,&(obj->gradient.stopcolor)); + cairogen_add_color_stop_rgba(pat,0,&(obj->fillcolor)); + cairogen_add_color_stop_rgba(pat,1,&(obj->stopcolor)); cairo_set_source (cr, pat); cairo_fill_preserve (cr); cairo_pattern_destroy (pat);