]> granicus.if.org Git - graphviz/commitdiff
First pass at cleaning up gradient fill
authorEmden Gansner <erg@research.att.com>
Mon, 23 Jan 2012 22:06:55 +0000 (17:06 -0500)
committerEmden Gansner <erg@research.att.com>
Mon, 23 Jan 2012 22:06:55 +0000 (17:06 -0500)
lib/common/const.h
lib/common/emit.c
lib/common/utils.c
lib/common/utils.h
lib/gvc/gvcjob.h
lib/gvc/gvcproc.h
lib/gvc/gvrender.c
plugin/core/gvrender_core_svg.c
plugin/pango/gvrender_pango.c

index cdf45fba46249371929e568753040c393855362c..0c2380ba8a8237e12a0124621494a605831d8969 100644 (file)
 
 /* 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)
index 3b3cc9f7d83a5eba837c63a10011f3d5af92f0ce..ec2f60a40b3dc77dfa44cbd55928e95568071e17 100644 (file)
@@ -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;
index 701c669f0b9e1386eb0740d5ea5e9f9188eb1a95..002b3e6b9811a88e591ddbacb93d619a1a431870 100644 (file)
@@ -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
index b922b4a56645badd98292e2d2245cd01b6d0ee44..9b68acc039fc26715d0cb4c73c083d09c6044082 100644 (file)
@@ -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 *);
index 1944f8538d3d540db3a945e849e128acb576f2b1..954a514221df758823002dd67232af8b6fadaa28 100644 (file)
@@ -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;
index 715b4d04b9282b93607c836c3528b1d453a67b11..c8b70cc43b83bbb460ceb6789612cac6b318a647 100644 (file)
     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);
index f3ceba07537252a0b37d1b9f7630246551ba0f14..5cc84ddc04a8807ac2659331ffc88d9b4b0ccf90 100644 (file)
 
 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); */
     }
 }
index 07cbc3ca37970753793f0c614471cd88f4e882b4..f4d50985081d8a46a25a113a48c42becfc5fb92c 100644 (file)
 #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, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+    gvputs(job,
+          "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
     if ((s = agget(job->gvc->g, "stylesheet")) && s[0]) {
-        gvputs(job, "<?xml-stylesheet href=\"");
-        gvputs(job, s);
-        gvputs(job, "\" type=\"text/css\"?>\n");
+       gvputs(job, "<?xml-stylesheet href=\"");
+       gvputs(job, s);
+       gvputs(job, "\" type=\"text/css\"?>\n");
     }
 #if 0
     gvputs(job, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\n");
-    gvputs(job, " \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"");
+    gvputs(job,
+          " \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"");
     /* This is to work around a bug in the SVG 1.0 DTD */
-    gvputs(job, " [\n <!ATTLIST svg xmlns:xlink CDATA #FIXED \"http://www.w3.org/1999/xlink\">\n]");
+    gvputs(job,
+          " [\n <!ATTLIST svg xmlns:xlink CDATA #FIXED \"http://www.w3.org/1999/xlink\">\n]");
 #else
-    gvputs(job, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n"); 
-    gvputs(job, " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+    gvputs(job, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n");
+    gvputs(job,
+          " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
 #endif
 
     gvputs(job, "<!-- Generated by ");
@@ -170,16 +168,17 @@ static void svg_begin_graph(GVJ_t * job)
 
     gvputs(job, "<!--");
     if (agnameof(obj->u.g)[0]) {
-        gvputs(job, " Title: ");
+       gvputs(job, " Title: ");
        gvputs(job, xml_string(agnameof(obj->u.g)));
     }
-    gvprintf(job, " Pages: %d -->\n", job->pagesArraySize.x * job->pagesArraySize.y);
+    gvprintf(job, " Pages: %d -->\n",
+            job->pagesArraySize.x * job->pagesArraySize.y);
 
     gvprintf(job, "<svg width=\"%dpt\" height=\"%dpt\"\n",
-       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, "</svg>\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, "<g id=\"");
     gvputs(job, xml_string(layername));
@@ -213,14 +213,15 @@ static void svg_begin_page(GVJ_t * job)
     gvputs(job, "<g id=\"");
     gvputs(job, xml_string(obj->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, "<title>");
-        gvputs(job, xml_string(agnameof(obj->u.g)));
-        gvputs(job, "</title>\n");
+       gvputs(job, "<title>");
+       gvputs(job, xml_string(agnameof(obj->u.g)));
+       gvputs(job, "</title>\n");
     }
 }
 
@@ -263,8 +264,7 @@ static void svg_end_node(GVJ_t * job)
     gvputs(job, "</g>\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, "<g id=\"");
     gvputs(job, xml_string(obj->id));
     gvputs(job, "\" class=\"edge\">");
-    
+
     gvputs(job, "<title>");
-    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, "</title>\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, "<a");
 #if 0
@@ -303,14 +304,14 @@ svg_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target, char *id)
      * it changes the behavior in browsers, the link apears in the bottom information bar
      */
     else {
-        assert (id && id[0]); /* there should always be an id available */
+       assert(id && id[0]);    /* there should always be an id available */
        gvputs(job, " xlink:href=\"#");
-        gvputs(job, xml_url_string(href));
-        gvputs(job, "\"");
+       gvputs(job, xml_url_string(href));
+       gvputs(job, "\"");
     }
 #endif
     if (tooltip && tooltip[0]) {
-        gvputs(job, " xlink:title=\"");
+       gvputs(job, " xlink:title=\"");
        gvputs(job, xml_string(tooltip));
        gvputs(job, "\"");
     }
@@ -331,7 +332,7 @@ static void svg_textpara(GVJ_t * job, pointf p, textpara_t * para)
 {
     obj_state_t *obj = 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, "<text");
@@ -351,41 +352,49 @@ static void svg_textpara(GVJ_t * job, pointf p, textpara_t * para)
     gvprintf(job, " x=\"%g\" y=\"%g\"", p.x, -p.y);
     pA = para->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, "</text>\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, "<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");
+    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,
+            "<defs>\n<linearGradient id=\"l_%d\" gradientUnits=\"userSpaceOnUse\" ", id);
+    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->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, "<stop offset=\"1\" style=\"stop-color:");
+    svg_print_color(job, obj->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</linearGradient>\n</defs>\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, "<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");
+    } else {
+       ifx = 50 * (1 + cos(angle));
+       ify = 50 * (1 - sin(angle));
+    }
+    gvprintf(job,
+            "<defs>\n<radialGradient id=\"r_%d\" cx=\"50%%\" cy=\"50%%\" r=\"75%%\" fx=\"%d%%\" fy=\"%d%%\">\n",
+            id, ifx, ify);
+    gvputs(job, "<stop offset=\"0\" style=\"stop-color:");
+    svg_print_color(job, obj->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, "<stop offset=\"1\" style=\"stop-color:");
+    svg_print_color(job, obj->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</radialGradient>\n</defs>\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, "<ellipse");
-    svg_grstyle(job, filled);
+    svg_grstyle(job, filled, gid);
     gvprintf(job, " cx=\"%g\" cy=\"%g\"", A[0].x, -A[0].y);
     gvprintf(job, " rx=\"%g\" ry=\"%g\"",
-           A[1].x - A[0].x, A[1].y - A[0].y);
+            A[1].x - A[0].x, A[1].y - A[0].y);
     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, "<path");
-    svg_grstyle(job, filled);
+    svg_grstyle(job, filled, 0);
     gvputs(job, " d=\"");
     svg_bzptarray(job, A, n);
     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, "<polygon");
-    svg_grstyle(job, filled);
+    svg_grstyle(job, filled, gid);
     gvputs(job, " points=\"");
     for (i = 0; i < n; i++)
        gvprintf(job, "%g,%g ", A[i].x, -A[i].y);
@@ -535,7 +553,7 @@ static void svg_polyline(GVJ_t * job, pointf * A, int n)
     int i;
 
     gvputs(job, "<polyline");
-    svg_grstyle(job, 0);
+    svg_grstyle(job, 0, 0);
     gvputs(job, " points=\"");
     for (i = 0; i < n; i++)
        gvprintf(job, "%g,%g ", A[i].x, -A[i].y);
@@ -609,7 +627,7 @@ gvrender_engine_t svg_engine = {
     svg_begin_anchor,
     svg_end_anchor,
     0,                         /* svg_begin_anchor */
-       0,                              /* svg_end_anchor */
+    0,                         /* svg_end_anchor */
     svg_textpara,
     0,                         /* svg_resolve_color */
     svg_ellipse,
@@ -621,13 +639,8 @@ gvrender_engine_t svg_engine = {
 };
 
 gvrender_features_t render_features_svg = {
-    GVRENDER_Y_GOES_DOWN
-        | GVRENDER_DOES_TRANSFORM
-       | GVRENDER_DOES_LABELS
-       | GVRENDER_DOES_MAPS
-       | GVRENDER_DOES_TARGETS
-       | GVRENDER_DOES_TOOLTIPS, /* flags */
-    4.,                         /* default pad - graph units */
+    GVRENDER_Y_GOES_DOWN | GVRENDER_DOES_TRANSFORM | GVRENDER_DOES_LABELS | GVRENDER_DOES_MAPS | GVRENDER_DOES_TARGETS | GVRENDER_DOES_TOOLTIPS,       /* flags */
+    4.,                                /* default pad - graph units */
     svg_knowncolors,           /* knowncolors */
     sizeof(svg_knowncolors) / sizeof(char *),  /* sizeof knowncolors */
     RGBA_BYTE,                 /* color_type */
@@ -635,18 +648,16 @@ gvrender_features_t render_features_svg = {
 
 gvdevice_features_t device_features_svg = {
     GVDEVICE_DOES_TRUECOLOR,   /* flags */
-    {0.,0.},                   /* default margin - points */
-    {0.,0.},                    /* default page width, height - points */
-    {72.,72.},                 /* default dpi */
+    {0., 0.},                  /* default margin - points */
+    {0., 0.},                  /* default page width, height - points */
+    {72., 72.},                        /* default dpi */
 };
 
 gvdevice_features_t device_features_svgz = {
-    GVDEVICE_BINARY_FORMAT
-      | GVDEVICE_COMPRESSED_FORMAT
-      | GVDEVICE_DOES_TRUECOLOR,/* flags */
-    {0.,0.},                   /* default margin - points */
-    {0.,0.},                    /* default page width, height - points */
-    {72.,72.},                 /* default dpi */
+    GVDEVICE_BINARY_FORMAT | GVDEVICE_COMPRESSED_FORMAT | GVDEVICE_DOES_TRUECOLOR,     /* flags */
+    {0., 0.},                  /* default margin - points */
+    {0., 0.},                  /* default page width, height - points */
+    {72., 72.},                        /* default dpi */
 };
 
 gvplugin_installed_t gvrender_svg_types[] = {
index 281b07293ae6b8e0929a79e44303c14fe9842ebb..c63129c87b4e72729d821943e7fc9d0da40f5641 100644 (file)
@@ -24,6 +24,8 @@
 
 #include "const.h"
 #include "gvplugin_render.h"
+#include "agxbuf.h"
+#include "utils.h"
 #include "gvplugin_device.h"
 #include "gvio.h"
 
@@ -31,8 +33,6 @@
 
 #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,
@@ -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);