[gs-cvs] rev 8741 - trunk/gs/src

giles at ghostscript.com giles at ghostscript.com
Thu May 15 17:05:42 PDT 2008


Author: giles
Date: 2008-05-15 17:05:42 -0700 (Thu, 15 May 2008)
New Revision: 8741

Modified:
   trunk/gs/src/gdevsvg.c
Log:
Accumulate imaging state changes and write a new group only when
drawing. Add support for the linewidth parameter. We're pretty
close to properly handling tiger and other vector-only files.


Modified: trunk/gs/src/gdevsvg.c
===================================================================
--- trunk/gs/src/gdevsvg.c	2008-05-16 00:05:41 UTC (rev 8740)
+++ trunk/gs/src/gdevsvg.c	2008-05-16 00:05:42 UTC (rev 8741)
@@ -45,10 +45,12 @@
     /* superclass state */
     gx_device_vector_common;
     /* local state */
-    int header;
-    int mark;
-    int page_count;
+    int header;		/* whether we've written the file header */
+    int dirty;		/* whether we need to rewrite the <g> element */
+    int mark;		/* <g> nesting level */
+    int page_count;	/* how many output_page calls we've seen */
     char *strokecolor, *fillcolor;
+    double linewidth;
 } gx_device_svg;
 
 #define svg_device_body(dname, depth)\
@@ -224,12 +226,13 @@
     if (code < 0) return code;
 
     /* svg-specific initialization goes here */
-    svg->header = 0;	/* file header hasn't been written */
-    svg->mark = 0;	/* have we drawn something? */
-    svg->page_count = 0;/* how many output_page calls we've seen */
-    svg->strokecolor = NULL; 
+    svg->header = 0;
+    svg->dirty = 0;
+    svg->mark = 0;
+    svg->page_count = 0;
+    svg->strokecolor = NULL;
     svg->fillcolor = NULL;
-
+    svg->linewidth = 1.0;
     return code;
 }
 
@@ -254,20 +257,21 @@
     gx_device_svg *const svg = (gx_device_svg*)dev;
 
     svg_write(svg, "\n<!-- svg_close_device -->\n");
-    if (svg->mark) {
+    /* close any open group elements */
+    while (svg->mark > 0) {
       svg_write(svg, "</g>\n");
-      svg->mark = 0;
+      svg->mark--;
     }
-    if (svg->fillcolor) gs_free_string(svg->memory, svg->fillcolor, 8,
-	"svg_close_device");
-    if (svg->strokecolor) gs_free_string(svg->memory, svg->strokecolor, 8,
-	"svg_close_device");
-    svg_write(svg, "</g>\n");
     if (svg->header) {
       svg_write(svg, "</svg>\n");
       svg->header = 0;
     }
 
+    if (svg->fillcolor) gs_free_string(svg->memory, svg->fillcolor, 8,
+	"svg_close_device");
+    if (svg->strokecolor) gs_free_string(svg->memory, svg->strokecolor, 8,
+	"svg_close_device");
+
     if (ferror(svg->file)) return_error(gs_error_ioerror);
 
     return gdev_vector_close_file((gx_device_vector*)dev);
@@ -363,6 +367,7 @@
     	72.0 / svg->HWResolution[1]);
     /* svg_write(svg, line); */
     sputs(s, line, strlen(line), &used);
+    svg->mark++;
 
     /* mark that we've been called */
     svg->header = 1;
@@ -394,6 +399,44 @@
     return paint;
 }
 
+static int
+svg_write_state(gx_device_svg *svg)
+{
+    char line[SVG_LINESIZE];
+
+    /* has anything changed? */
+    if (!svg->dirty) return 0;
+
+    /* close the current graphics state element, if any */
+    if (svg->mark > 1) {
+      svg_write(svg, "</g>\n");
+      svg->mark--;
+    }
+    /* write out the new current state */
+    svg_write(svg, "<g ");
+    if (svg->strokecolor) {
+        sprintf(line, " stroke='%s'", svg->strokecolor);
+	svg_write(svg, line);
+    } else {
+	svg_write(svg, " stroke='none'");
+    }
+    if (svg->fillcolor) {
+	sprintf(line, " fill='%s'", svg->fillcolor);
+	svg_write(svg, line);
+    } else {
+      svg_write(svg, " fill='none'");
+    }
+    if (svg->linewidth != 1.0) {
+      sprintf(line, " stroke-width='%lf'", svg->linewidth);
+      svg_write(svg, line);
+    }
+    svg_write(svg, ">\n");
+    svg->mark++;
+
+    svg->dirty = 0;
+    return 0;
+}
+
 /* vector device implementation */
 
         /* Page management */
@@ -412,7 +455,13 @@
 static int
 svg_setlinewidth(gx_device_vector *vdev, floatp width)
 {
+    gx_device_svg *svg = (gx_device_svg *)vdev;
+
     dprintf1("svg_setlinewidth(%lf)\n", width);
+
+    svg->linewidth = width;
+    svg->dirty++;
+
     return 0;
 }
 static int
@@ -473,25 +522,12 @@
     if (svg->fillcolor && !strcmp(fill, svg->fillcolor))
       return 0; /* not a new color */
 
-    /* update and write a new group */
+    /* update our state with the new color */
     if (svg->fillcolor) gs_free_string(svg->memory, svg->fillcolor, 8,
 	"svg_setfillcolor");
     svg->fillcolor = fill;
-    if (svg->mark) {
-      svg_write(svg, "</g>\n");
-    }
-    svg_write(svg, "<g fill='");
-    svg_write(svg, fill);
-    svg_write(svg, "'");
-    if (svg->strokecolor) {
-      svg_write(svg, " stroke='");
-      svg_write(svg, svg->strokecolor);
-      svg_write(svg, "'");
-    } else {
-      svg_write(svg, " stroke='none'");
-    }
-    svg_write(svg, ">\n");
-    svg->mark = 1;
+    /* request a new group element */
+    svg->dirty++;
 
     return 0;
 }
@@ -510,26 +546,12 @@
     if (svg->strokecolor && !strcmp(stroke, svg->strokecolor)) 
       return 0; /* not a new color */
 
-    /* update and write a new group */
+    /* update our state with the new color */
     if (svg->strokecolor) gs_free_string(svg->memory, svg->strokecolor, 8,
 	"svg_setstrokecolor");
     svg->strokecolor = stroke;
-    if (svg->mark) {
-      svg_write(svg, "</g>\n");
-    }
-    svg_write(svg, "<g ");
-    if (svg->fillcolor) {
-      svg_write(svg, " fill='");
-      svg_write(svg, svg->fillcolor);
-      svg_write(svg, "'");
-    } else {
-      svg_write(svg, " fill='none'");
-    }
-    svg_write(svg, " stroke='");
-    svg_write(svg, stroke);
-    svg_write(svg, "'");
-    svg_write(svg, ">\n");
-    svg->mark = 1;
+    /* request a new group element */
+    svg->dirty++;
 
     return 0;
 }
@@ -563,6 +585,8 @@
     svg_print_path_type(svg, type);
     dprintf("\n");
 
+    svg_write_state(svg);
+
     if (type & gx_path_type_clip) {
 	svg_write(svg, "<clipPath>\n");
     }
@@ -599,6 +623,7 @@
     svg_print_path_type(svg, type);
     dprintf("\n");
 
+    svg_write_state(svg);
     svg_write(svg, "<path d='");
 
     return 0;



More information about the gs-cvs mailing list