#define DEFAULT_RANKSEP 0.5
#define MIN_RANKSEP 0.02
+
/* default margin for paged formats such as PostScript - in points = 0.5in */
#define DEFAULT_PRINT_MARGIN 36
/* default margin for embedded formats such as PNG - in points */
#define FOLDER (1 << 7)
#define BOX3D (1 << 8)
#define COMPONENT (1 << 9)
+#define GRADIENT (1 << 10)
+#define RGRADIENT GRADIENT + 1 /*radial gradient */
/* label types */
#define LT_NONE (0 << 1)
#define P2RECT(p, pr, sx, sy) (pr[0].x = p.x - sx, pr[0].y = p.y - sy, pr[1].x = p.x + sx, pr[1].y = p.y + sy)
#define FUZZ 3
#define EPSILON .0001
+#define GR_SZ 50
typedef struct {
xdot_op op;
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;
}
else {
/* obj->pencolor = NULL */
static void emit_background(GVJ_t * job, graph_t *g)
{
xdot* xd;
- char *str;
- int dfltColor;
+ char *str,*gcolor,*style;
+ int dfltColor,filltype;
/* if no bgcolor specified - first assume default of "white" */
if (! ((str = agget(g, "bgcolor")) && str[0])) {
}
else
dfltColor = 0;
+
+ if (((style = agget(g, "style")) && str[0])) {
+ if(strcmp(style,"linear") == 0)
+ filltype = GRADIENT;
+ else if(strcmp(style,"radial") == 0)
+ filltype = RGRADIENT;
+ else
+ filltype = 0;
+ }
+
+ if ( filltype > 0 && ((gcolor = agget(g, "gradientcolor")) && str[0])) {
+ gvrender_set_gradient(job,g,G_gradientcolor,G_gradientangle);
+ }
/* if device has no truecolor support, change "transparent" to "white" */
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);
- gvrender_box(job, job->clip, TRUE); /* filled */
+ if(filltype > 0)
+ gvrender_box(job, job->clip,filltype); /* linear or radial gradient */
+ else
+ gvrender_box(job, job->clip, TRUE); /* filled */
}
if ((xd = (xdot*)GD_drawing(g)->xdots))
gvrender_set_fillcolor(job, str);
if (((str = agget(g, "fontcolor")) != 0) && str[0])
gvrender_set_pencolor(job, str);
+
emit_cluster_colors(job, g);
for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
if (((str = agget(n, "color")) != 0) && str[0])
if (strcmp(p, "filled") == 0) {
istyle |= FILLED;
pp++;
- } else if (strcmp(p, "rounded") == 0) {
+ }
+ else if (strcmp(p, "linear") == 0) {
+ istyle |= GRADIENT;
+ pp++;
+ }
+ if (strcmp(p, "radial") == 0) {
+ istyle |= (RGRADIENT);
+ pp++;
+ }else if (strcmp(p, "rounded") == 0) {
istyle |= ROUNDED;
qp = pp; /* remove rounded from list passed to renderer */
do {
fillcolor = color;
filled = TRUE;
}
+ if (istyle & GRADIENT) { //handles both linear and radial gradients
+ gvrender_set_gradient(job,sg,G_gradientcolor,G_gradientangle);
+ filled = FALSE;
+ }
+
}
if (!pencolor) pencolor = DEFAULT_COLOR;
if (!fillcolor) fillcolor = DEFAULT_FILL;
else {
gvrender_set_pencolor(job, pencolor);
gvrender_set_fillcolor(job, fillcolor);
- if (late_int(sg, G_peripheries, 1, 0))
+ if (late_int(sg, G_peripheries, 1, 0)){
+ if (istyle & GRADIENT)
+ gvrender_box(job, GD_bb(sg), istyle);
+ else
gvrender_box(job, GD_bb(sg), filled);
+ }
+ else if (istyle & GRADIENT)
+ gvrender_box(job, GD_bb(sg), istyle);
else if (filled) {
if (fillcolor && fillcolor != pencolor)
gvrender_set_pencolor(job, fillcolor);
*G_selectedpencolor, *G_selectedfillcolor,
*G_visitedpencolor, *G_visitedfillcolor,
*G_deletedpencolor, *G_deletedfillcolor,
- *G_ordering, *G_peripheries, *G_penwidth;
+ *G_ordering, *G_peripheries, *G_penwidth,
+ *G_gradientcolor,*G_gradientangle;
EXTERN attrsym_t
*N_height, *N_width, *N_shape, *N_color, *N_fillcolor,
*N_activepencolor, *N_activefillcolor,
*N_sides, *N_peripheries, *N_ordering, *N_orientation,
*N_skew, *N_distortion, *N_fixed, *N_imagescale, *N_layer,
*N_group, *N_comment, *N_vertices, *N_z,
- *N_penwidth;
+ *N_penwidth,*N_gradientcolor, *N_gradientangle;
EXTERN attrsym_t
*E_weight, *E_minlen, *E_color,
*E_activepencolor, *E_activefillcolor,
return 0;
}
+static int gradientfn(htmldata_t * p, char *v)
+{
+ p->gradient = strdup(v);
+ return 0;
+}
+
+static int gradientcolorfn(htmldata_t * p, char *v)
+{
+ p->gradientcolor = strdup(v);
+ return 0;
+}
+
+
/* doInt:
* Scan v for integral value. Check that
* the value is >= min and <= max. Return value in ul.
{"color", (attrFn) pencolorfn},
{"columns", (attrFn) columnsfn},
{"fixedsize", (attrFn) fixedsizefn},
+ {"gradient", (attrFn) gradientfn},
+ {"gradientcolor", (attrFn) gradientcolorfn},
{"height", (attrFn) heightfn},
{"href", (attrFn) hreffn},
{"id", (attrFn) idfn},
{"color", (attrFn) pencolorfn},
{"colspan", (attrFn) colspanfn},
{"fixedsize", (attrFn) fixedsizefn},
+ {"gradient", (attrFn) gradientfn},
+ {"gradientcolor", (attrFn) gradientcolorfn},
{"height", (attrFn) heightfn},
{"href", (attrFn) hreffn},
{"id", (attrFn) idfn},
gvrender_box(job, BF, 1);
}
+static void doGrdtFill(GVJ_t * job, char *color, boxf BF, int gradient)
+{
+ //gvrender_set_fillcolor(job, color);
+ gvrender_set_pencolor(job, color);
+ gvrender_box(job, BF, gradient);
+}
+
/* initAnchor:
* Save current map values
* Initialize fields in job->obj pertaining to anchors.
int anchor; /* if true, we need to undo anchor settings. */
int doAnchor = (tbl->data.href || tbl->data.target);
pointf AF[4];
+ int gradient;
+ char *bordercolor;
if (tbl->font)
pushFontInfo(env, tbl->font, &savef);
anchor = initAnchor(job, env, &tbl->data, pts, &saved, 1);
else
anchor = 0;
-
/* Set up rounded style */
if (tbl->style & ROUNDED) {
AF[0] = pts.LL;
/* Fill first */
if (tbl->data.bgcolor) {
- if (tbl->style & ROUNDED)
+ if (tbl->style & ROUNDED){
round_corners (job, tbl->data.bgcolor, NULL, AF, 4, tbl->style, 1);
+ }
else
doFill(job, tbl->data.bgcolor, pts);
+ }
+
+ if (tbl->data.gradient && tbl->data.gradientcolor) {
+ if (strcmp(tbl->data.gradient,"linear") == 0)
+ gradient = GRADIENT;
+ else if (strcmp(tbl->data.gradient,"radial") == 0)
+ gradient = RGRADIENT;
+ else
+ gradient = 0;
+ bordercolor = gvrender_set_gradient_values(job, tbl->data.gradientcolor, 0);
+
+ if (tbl->style & ROUNDED){
+ round_corners (job, bordercolor, NULL, AF, 4, tbl->style, gradient);
+ }
+ else
+ doGrdtFill(job, bordercolor, pts,gradient);
}
+
while (*cells) {
emit_html_cell(job, *cells, env);
boxf pts = cp->data.box;
pointf pos = env->pos;
int inAnchor, doAnchor = (cp->data.href || cp->data.target);
+ int gradient;
+ char *bordercolor;
pts.LL.x += pos.x;
pts.UR.x += pos.x;
else
inAnchor = 0;
- if (cp->data.bgcolor) {
+ if (cp->data.bgcolor)
doFill(job, cp->data.bgcolor, pts);
- }
if (cp->data.border)
doBorder(job, cp->data.pencolor, cp->data.border, pts);
+
+ if(cp->data.gradient && cp->data.gradientcolor){
+ if(strcmp(cp->data.gradient,"linear")==0)
+ gradient = GRADIENT;
+ else if (strcmp(cp->data.gradient,"radial")==0)
+ gradient = RGRADIENT;
+ else
+ gradient = 0;
+ bordercolor = gvrender_set_gradient_values(job, cp->data.gradientcolor, 0);
+ doGrdtFill(job,bordercolor, pts, gradient);
+ }
if (cp->child.kind == HTML_TBL)
emit_html_tbl(job, cp->child.u.tbl, env);
char *id;
char *bgcolor;
char *pencolor;
+ char *gradient;
+ char *gradientcolor;
signed char space;
unsigned char border;
unsigned char pad;
Initial_dist = MYHUGE;
G_ordering = agfindgraphattr(g, "ordering");
+ G_gradientcolor = agfindgraphattr(g,"gradientcolor");
+ G_gradientangle = agfindgraphattr(g,"gradientangle");
/* initialize nodes */
N_height = agfindnodeattr(g, "height");
N_comment = agfindnodeattr(g, "comment");
N_vertices = agfindnodeattr(g, "vertices");
N_z = agfindnodeattr(g, "z");
+ N_gradientcolor = agfindnodeattr(g,"gradientcolor");
+ N_gradientangle = agfindnodeattr(g,"gradientangle");
/* initialize edges */
E_weight = agfindedgeattr(g, "weight");
extern void write_attributed_dot(graph_t *g, FILE *f);
extern void write_canonical_dot(graph_t *g, FILE *f);
extern boxf xdotBB (graph_t* g);
+ extern char *findStartColor(void * n, attrsym_t * attr, char *);
+ extern char *findStopColor(void * n, attrsym_t * attr, char *);
+ extern int findGradientAngle(void * n, attrsym_t * attr);
#undef extern
#define RBCONST 12
#define RBCURVE .5
+#define GR_SZ 50
static port Center = { {0, 0}, -1, 0, 0, 0, 1, 0, 0, 0 };
return (findFillDflt(n, DEFAULT_FILL));
}
+char *findStartColor(void * n, attrsym_t * attr, char *dflt)
+{
+ char *color;
+
+ color = late_nnstring(n, attr, dflt);
+ if (!color[0]) {
+ color = late_nnstring(n, N_color, "");
+ if (!color[0]) {
+ color = DEFAULT_FILL;
+ }
+ }
+ return color;
+}
+
+
+char *findStopColor(void * n, attrsym_t * attr, char *dflt)
+{
+ char *color,*str;
+
+ str = late_nnstring(n, attr, dflt);
+ color = strchr(str, ':');
+ if ((color == NULL) || !color[0]) {
+ color = str;
+ if (!color[0]) {
+ color = DEFAULT_FILL;
+ }
+ }
+ else {
+ color++;
+ if (!color[0]) {
+ color = DEFAULT_FILL;
+ }
+ }
+
+ return color;
+}
+
+int findGradientAngle(void * n, attrsym_t * attr)
+{
+ int angle;
+ angle = late_int(n, attr, 0, 0);
+ return (angle);
+}
+
static char **checkStyle(node_t * n, int *flagp)
{
char *style;
if (streq(p, "filled")) {
istyle |= FILLED;
pp++;
+ } else if (streq(p, "linear")) {
+ istyle |= GRADIENT;
+ pp++;
+ }else if (streq(p, "radial")) {
+ istyle |= (RGRADIENT);
+ pp++;
} else if (streq(p, "rounded")) {
istyle |= ROUNDED;
qp = pp; /* remove rounded from list passed to renderer */
pts[j++] = B[4 * seg + 1];
pts[j++] = B[4 * seg + 2];
}
- gvrender_polygon(job, pts, 2 * sides, TRUE);
+ if (filled & GRADIENT)
+ gvrender_polygon(job, pts, 2 * sides, filled);
+ else
+ gvrender_polygon(job, pts, 2 * sides, TRUE);
free(pts);
for (seg = 0; seg < sides; seg++) {
gvrender_beziercurve(job, B + 4 * seg + 2, 4, FALSE, FALSE,
gvrender_set_fillcolor(job, color);
filled = TRUE;
} else {
- if (style & FILLED) {
+ if (style & GRADIENT) {
+ gvrender_set_gradient(job,n,N_gradientcolor,N_gradientangle);
+ filled = FALSE;
+ }
+ else if (style & FILLED) {
gvrender_set_fillcolor(job, findFill(n)); /* emit fill color */
filled = TRUE;
- } else {
+ }
+ else {
filled = FALSE;
}
pencolor(job, n); /* emit pen color */
/* lay down fill first */
if (filled && pfilled) {
if (sides <= 2) {
- gvrender_ellipse(job, AF, sides, filled);
+ if (style & GRADIENT)
+ gvrender_ellipse(job, AF, sides, style);
+ else
+ gvrender_ellipse(job, AF, sides, filled);
+
if (style & DIAGONALS) {
Mcircle_hack(job, n);
}
} else if (style & (ROUNDED | DIAGONALS)) {
- node_round_corners(job, n, AF, sides, style, filled);
+ if (style & GRADIENT) {
+ gvrender_set_gradient(job,n,N_gradientcolor,N_gradientangle);
+ node_round_corners(job, n, AF, sides, style, style);
+ }
+ else
+ node_round_corners(job, n, AF, sides, style, filled);
} else {
- gvrender_polygon(job, AF, sides, filled);
+ if (style & GRADIENT)
+ gvrender_polygon(job, AF, sides, style);
+ else
+ gvrender_polygon(job, AF, sides, filled);
}
}
gvrender_usershape(job, name, AF, sides, filled,
AF[i].y = P.y * ysize + ND_coord(n).y;
}
if (sides <= 2) {
- gvrender_ellipse(job, AF, sides, filled);
+ if (style & GRADIENT)
+ gvrender_ellipse(job, AF, sides, style);
+ else
+ gvrender_ellipse(job, AF, sides, filled);
if (style & DIAGONALS) {
Mcircle_hack(job, n);
}
} else if (SPECIAL_CORNERS(style)) {
+ if (style & GRADIENT) {
+ gvrender_set_gradient(job,n,N_gradientcolor,N_gradientangle);
+ node_round_corners(job, n, AF, sides, style, style);
+ }
+ else
node_round_corners(job, n, AF, sides, style, filled);
} else {
- gvrender_polygon(job, AF, sides, filled);
+ if (style & GRADIENT)
+ gvrender_polygon(job, AF, sides, style);
+ else
+ gvrender_polygon(job, AF, sides, filled);
}
/* fill innermost periphery only */
filled = FALSE;
GD_flags(g) |= et;
}
+
+/* cairogen_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
+ *
+ */
+void cairogen_get_gradient_points(pointf * A, pointf * G, int n, float angle)
+{
+ int i;
+ double rx, ry;
+ 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);
+ }
+ }
+ 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);
+ }
+ }
+ center.x = min.x + (max.x - min.x)/2;
+ center.y = min.y + (max.y - min.y)/2;
+ outer_r = sqrt((center.x - min.x)*(center.x - min.x) +
+ (center.y - min.y)*(center.y - min.y));
+ inner_r = outer_r /4.;
+ G[0].x = center.x;
+ G[0].y = -center.y;
+ G[1].x = inner_r;
+ G[1].y = outer_r;
+
+}
+
#ifndef WIN32_STATIC
#ifndef HAVE_STRCASECMP
typedef struct gvloadimage_engine_s gvloadimage_engine_t;
typedef enum { PEN_NONE, PEN_DASHED, PEN_DOTTED, PEN_SOLID } pen_type;
- typedef enum { FILL_NONE, FILL_SOLID } fill_type;
+ typedef enum { FILL_NONE, FILL_SOLID, FILL_LINEAR, FILL_RADIAL } fill_type;
typedef enum { FONT_REGULAR, FONT_BOLD, FONT_ITALIC } font_type;
typedef enum { LABEL_PLAIN, LABEL_HTML } label_type;
int argc;
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);
emit_state_t emit_state;
gvcolor_t pencolor, fillcolor;
+ gv_gradient_t gradient;
pen_type pen;
fill_type fill;
double penwidth;
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(GVJ_t * job, void *g_obj, attrsym_t * color_attr, attrsym_t * angle_attr);
+ extern char *gvrender_set_gradient_values(GVJ_t* job, char* gradcolor, int angle);
extern void gvrender_set_style(GVJ_t * job, char **s);
- extern void gvrender_ellipse(GVJ_t * job, pointf * AF, int n, boolean filled);
- extern void gvrender_polygon(GVJ_t * job, pointf * AF, int n, boolean filled);
- extern void gvrender_box(GVJ_t * job, boxf BF, boolean filled);
+ extern void gvrender_ellipse(GVJ_t * job, pointf * AF, int n, int filled);
+ extern void gvrender_polygon(GVJ_t* job, pointf* af, int n, int filled);
+ extern void gvrender_box(GVJ_t * job, boxf BF, int filled);
extern void gvrender_beziercurve(GVJ_t * job, pointf * AF, int n,
int arrow_at_start, int arrow_at_end, boolean filled);
extern void gvrender_polyline(GVJ_t * job, pointf * AF, int n);
extern int emit_once(char *str);
extern shape_desc *find_user_shape(char *name);
+extern char *findStopColor(void * n, attrsym_t * attr, char *dflt);
+extern char *findStartColor(void * n, attrsym_t * attr, char *dflt);
+extern int findGradientAngle(void * n, attrsym_t * attr);
extern boolean mapbool(char *s);
#ifndef HAVE_STRCASECMP
extern int strcasecmp(const char *s1, const char *s2);
#endif
+#define GR_SZ 50
+
/* storage for temporary hacks until client API is FP */
static pointf *AF;
static int sizeAF;
*cp = ':';
}
+void gvrender_set_gradientcolor(GVJ_t * job, char *gr_color_ptr[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(GVJ_t * job, void *g_obj, attrsym_t * color_attr, attrsym_t * angle_attr){
+char *ptr, *gradcolor = NULL,*gradstartcolor;
+int angle;
+
+
+ if(g_obj != NULL && color_attr != NULL) {
+ gradcolor = N_GNEW((2 * GR_SZ)+1,char);
+ gradstartcolor = N_GNEW(GR_SZ,char);
+ strcpy(gradcolor,findStartColor(g_obj,color_attr,DEFAULT_FILL));
+ if ((ptr = strstr(gradcolor, ":")) != NULL) /* if attribute is a color list use first one */
+ *ptr = '\0';
+ strcpy(gradstartcolor,gradcolor);
+ strcat(gradcolor,":");
+ strcat(gradcolor,findStopColor(g_obj,color_attr,gradstartcolor)); /* use start color as stop color if : missing */
+ angle = findGradientAngle(g_obj,angle_attr);
+ gvrender_set_gradient_values(job,gradcolor,angle);
+ free(gradstartcolor);
+ free(gradcolor);
+ }
+
+}
+
+static char gradientcolor[2][GR_SZ];
+
+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);
+ }
+ return gr_color_ptr[1];
+
+}
+
+
void gvrender_set_style(GVJ_t * job, char **s)
{
gvrender_engine_t *gvre = job->render.engine;
obj->penwidth = atof(p);
} else if (streq(line, "filled"))
obj->fill = FILL_SOLID;
+ else if (streq(line, "linear"))
+ obj->fill = FILL_LINEAR;
+ else if (streq(line, "radial"))
+ obj->fill = FILL_RADIAL;
else if (streq(line, "unfilled"))
obj->fill = FILL_NONE;
else if (streq(line, "tapered"))
}
}
-void gvrender_ellipse(GVJ_t * job, pointf * pf, int n, boolean filled)
+void gvrender_ellipse(GVJ_t * job, pointf * pf, int n, int filled)
{
gvrender_engine_t *gvre = job->render.engine;
}
}
-void gvrender_polygon(GVJ_t * job, pointf * af, int n, boolean filled)
+void gvrender_polygon(GVJ_t * job, pointf * af, int n, int filled)
{
gvrender_engine_t *gvre = job->render.engine;
-
if (gvre) {
if (gvre->polygon && job->obj->pen != PEN_NONE) {
if (job->flags & GVRENDER_DOES_TRANSFORM)
}
}
-void gvrender_box(GVJ_t * job, boxf B, boolean filled)
+
+void gvrender_box(GVJ_t * job, boxf B, int filled)
{
pointf A[4];
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";
static void svg_grstyle(GVJ_t * job, int filled)
{
obj_state_t *obj = job->obj;
+ char sgid[11];
gvputs(job, " fill=\"");
- if (filled) {
+ 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) {
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));
gvputs(job, "</text>\n");
}
+/* svg_gradstyle
+ * Outputs the SVG statements that define the gradient pattern
+ */
+static void 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, "<defs>\n<linearGradient id=\"l_%s\" gradientUnits=\"userSpaceOnUse\" ",sgid);
+ gvprintf(job,"x1=\"%g\" y1=\"%g\" x2=\"%g\" y2=\"%g\" >\n", G[0].x,G[0].y,G[1].x,G[1].y);
+ gvputs(job,"<stop offset=\"0\" style=\"stop-color:");
+ svg_print_color(job, obj->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,"<stop offset=\"1\" style=\"stop-color:");
+ svg_print_color(job, obj->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</linearGradient>\n</defs>\n");
+}
+
+/* svg_gradstyle
+ * Outputs the SVG statements that define the radial gradient pattern
+ */
+static void 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.){
+ 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, "<defs>\n<radialGradient id=\"r_%s\" cx=\"50%\" cy=\"50%\" r=\"75%\" fx=",sgid);
+ gvprintf(job,"\"%s\"",fx);
+ gvputs(job," fy=");
+ gvprintf(job,"\"%s\">\n",fy);
+ gvputs(job,"<stop offset=\"0\" style=\"stop-color:");
+ svg_print_color(job, obj->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,"<stop offset=\"1\" style=\"stop-color:");
+ svg_print_color(job, obj->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</radialGradient>\n</defs>\n");
+}
+
+
static void svg_ellipse(GVJ_t * job, pointf * A, int filled)
{
/* 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);
+ }
gvputs(job, "<ellipse");
svg_grstyle(job, filled);
gvprintf(job, " cx=\"%g\" cy=\"%g\"", A[0].x, -A[0].y);
static void svg_polygon(GVJ_t * job, pointf * A, int n, int filled)
{
int i;
-
+ if (filled == GRADIENT) {
+ svg_gradstyle(job,A,n);
+ }
+ else if (filled == (RGRADIENT)){
+ svg_rgradstyle(job,A,n);
+ }
gvputs(job, "<polygon");
svg_grstyle(job, filled);
gvputs(job, " points=\"");
#include <string.h>
#endif
+#include "const.h"
#include "gvplugin_render.h"
#include "gvplugin_device.h"
#include "gvio.h"
#ifdef HAVE_PANGOCAIRO
#include <pango/pangocairo.h>
+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,
color->u.RGBA[2], color->u.RGBA[3]);
}
+static void cairogen_add_color_stop_rgba(cairo_pattern_t *pat,int stop , gvcolor_t * color)
+{
+ cairo_pattern_add_color_stop_rgba (pat, stop,color->u.RGBA[0], color->u.RGBA[1],
+ color->u.RGBA[2], color->u.RGBA[3]);
+}
+
+
static cairo_status_t
writer (void *closure, const unsigned char *data, unsigned int length)
{
cairo_t *cr = (cairo_t *) job->context;
cairo_matrix_t matrix;
double rx, ry;
+ float angle,r1,r2;
+ pointf G[2],c1,c2;
+ cairo_pattern_t *pat;
cairogen_set_penstyle(job, cr);
cairo_set_matrix(cr, &matrix);
- if (filled) {
+ if (filled == GRADIENT || filled == (RGRADIENT)) {
+ 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);
+ 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);
+ //r1 is inner radius, r2 is outter radius
+ r1 = G[1].x;
+ r2 = G[1].y;
+ if (angle == 0) {
+ c1.x = G[0].x;
+ c1.y = G[0].y;
+ }
+ else {
+ c1.x = G[0].x + (r2/4) * cos(angle);
+ c1.y = G[0].y - (r2/4) * sin(angle);
+ }
+ c2.x = G[0].x;
+ c2.y = G[0].y;
+ r1 = r2/4;
+ //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));
+ cairo_set_source (cr, pat);
+ cairo_fill_preserve (cr);
+ cairo_pattern_destroy (pat);
+ }
+ else if (filled) {
cairogen_set_color(cr, &(obj->fillcolor));
cairo_fill_preserve(cr);
}
obj_state_t *obj = job->obj;
cairo_t *cr = (cairo_t *) job->context;
int i;
+ float angle,r1,r2;
+ cairo_pattern_t *pat;
+ pointf G[2],c1,c2;
cairogen_set_penstyle(job, cr);
cairo_move_to(cr, A[0].x, -A[0].y);
for (i = 1; i < n; i++)
- cairo_line_to(cr, A[i].x, -A[i].y);
+ cairo_line_to(cr, A[i].x, -A[i].y);
cairo_close_path(cr);
- if (filled) {
- cairogen_set_color(cr, &(obj->fillcolor));
- cairo_fill_preserve(cr);
+ if (filled == GRADIENT || filled == (RGRADIENT)) {
+ angle = obj->gradient.angle * M_PI / 180;
+ if(filled == GRADIENT) {
+ cairogen_get_gradient_points(A, G, n, angle);
+ 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);
+ r1 = G[1].x;
+ r2 = G[1].y;
+ if (angle == 0) {
+ c1.x = G[0].x;
+ c1.y = G[0].y;
+ }
+ else {
+ c1.x = G[0].x + (r2/4) * cos(angle);
+ c1.y = G[0].y - (r2/4) * sin(angle);
+ }
+ c2.x = G[0].x;
+ c2.y = G[0].y;
+ r1 = r2/4;
+ //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));
+ cairo_set_source (cr, pat);
+ cairo_fill_preserve (cr);
+ cairo_pattern_destroy (pat);
+ }
+ else if (filled) {
+ cairogen_set_color(cr, &(obj->fillcolor));
+ cairo_fill_preserve(cr);
}
cairogen_set_color(cr, &(obj->pencolor));
cairo_stroke(cr);