SVG Kit
for Adobe® Creative Suite®
  • SVG Kit trial

    Buy now

    • 1 year support
    • free updates and bug fixes
    • no functional limitations
  • SVG Kit trial

    Download free trial (160MB)

    • full-functional version
    • limited support
    • limited functionality when trial period expires

Batik 1.7 patches

Scand SVG team works with open source projects on a regular basis and as a result we often release patches to open source community. Here we've started to collect our patches related to SVG and the first ones published are patches for Apache Batik. Of course, all patches are sent to the Batik team, published into Bugzilla, so below you can see just a reference thereto.

Radial gradients for svggen

diff -Naur batik-1.7/sources/org/apache/batik/svggen/SVGPaint.java batik-1.7-vk\sources/org/apache/batik/svggen/SVGPaint.java
--- batik-1.7/sources/org/apache/batik/svggen/SVGPaint.java	2007-01-16 22:49:42.000000000 +0200
+++ batik-1.7-vk/sources/org/apache/batik/svggen/SVGPaint.java	2011-04-20 00:09:06.997364400 +0300
@@ -25,6 +25,7 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.batik.ext.awt.*;
 import org.apache.batik.ext.awt.g2d.GraphicContext;
 
 /**
@@ -44,6 +45,11 @@
     private SVGLinearGradient svgLinearGradient;
 
     /**
+     * All GradientPaint convertions are handed to svgRadialGradient
+     */
+    private SVGRadialGradient svgRadialGradient;
+
+    /**
      * All TexturePaint convertions are handed to svgTextureGradient
      */
     private SVGTexturePaint svgTexturePaint;
@@ -68,6 +74,7 @@
      */
     public SVGPaint(SVGGeneratorContext generatorContext) {
         this.svgLinearGradient = new SVGLinearGradient(generatorContext);
+        this.svgRadialGradient = new SVGRadialGradient(generatorContext);
         this.svgTexturePaint = new SVGTexturePaint(generatorContext);
         this.svgCustomPaint = new SVGCustomPaint(generatorContext);
         this.svgColor = new SVGColor(generatorContext);
@@ -80,9 +87,11 @@
      */
     public List getDefinitionSet(){
         List paintDefs = new LinkedList(svgLinearGradient.getDefinitionSet());
+        paintDefs.addAll(svgRadialGradient.getDefinitionSet());
         paintDefs.addAll(svgTexturePaint.getDefinitionSet());
         paintDefs.addAll(svgCustomPaint.getDefinitionSet());
         paintDefs.addAll(svgColor.getDefinitionSet());
+        paintDefs.addAll(svgLinearGradient.getDefinitionSet());
         return paintDefs;
     }
 
@@ -94,6 +103,10 @@
         return svgLinearGradient;
     }
 
+    public SVGRadialGradient getRadialGradientPaintConverter(){
+        return svgRadialGradient;
+    }
+
     public SVGCustomPaint getCustomPaintConverter(){
         return svgCustomPaint;
     }
@@ -128,10 +141,12 @@
         if (paintDesc == null) {
             if (paint instanceof Color)
                 paintDesc = SVGColor.toSVG((Color)paint, generatorContext);
-            else if (paint instanceof GradientPaint)
-                paintDesc = svgLinearGradient.toSVG((GradientPaint)paint);
+            else if (paint instanceof RadialGradientPaint)
+                paintDesc = svgRadialGradient.toSVG((RadialGradientPaint) paint);
             else if (paint instanceof TexturePaint)
                 paintDesc = svgTexturePaint.toSVG((TexturePaint)paint);
+            else if (paint instanceof GradientPaint)
+                paintDesc = svgLinearGradient.toSVG((GradientPaint)paint);
         }
 
         return paintDesc;
diff -Naur batik-1.7/sources/org/apache/batik/svggen/SVGRadialGradient.java batik-1.7-vk\sources/org/apache/batik/svggen/SVGRadialGradient.java
--- batik-1.7/sources/org/apache/batik/svggen/SVGRadialGradient.java	1970-01-01 02:00:00.000000000 +0200
+++ batik-1.7-vk/sources/org/apache/batik/svggen/SVGRadialGradient.java	2011-04-20 00:03:45.953864400 +0300
@@ -0,0 +1,94 @@
+package org.apache.batik.svggen;
+
+import org.apache.batik.ext.awt.*;
+import org.apache.batik.ext.awt.g2d.*;
+import org.w3c.dom.*;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class SVGRadialGradient extends AbstractSVGConverter {
+    public SVGRadialGradient(SVGGeneratorContext generatorContext) {
+        super(generatorContext);
+    }
+
+    public SVGDescriptor toSVG(GraphicContext gc) {
+        Paint paint = gc.getPaint();
+        return toSVG((RadialGradientPaint) paint);
+    }
+
+    public SVGPaintDescriptor toSVG(final RadialGradientPaint gradient) {
+        // Reuse definition if gradient has already been converted
+        SVGPaintDescriptor gradientDesc = (SVGPaintDescriptor) descMap.get(gradient);
+
+        Document domFactory = generatorContext.domFactory;
+
+        if (gradientDesc == null) {
+            Element gradientDef = domFactory.createElementNS(SVG_NAMESPACE_URI, SVG_RADIAL_GRADIENT_TAG);
+
+            gradientDef.setAttributeNS(null, SVG_GRADIENT_UNITS_ATTRIBUTE, SVG_USER_SPACE_ON_USE_VALUE);
+
+            String transformString
+                    = new SVGTransform(generatorContext).toSVGTransform(new GraphicContext(gradient.getTransform())).trim();
+            if (!"".equals(transformString))
+                gradientDef.setAttributeNS(null, SVG_GRADIENT_TRANSFORM_ATTRIBUTE, transformString);
+
+            Color[] colors = gradient.getColors();
+            float[] fractions = gradient.getFractions();
+            for (int i = 0; i < colors.length; i++) {
+                Element gradientStop = domFactory.createElementNS(SVG_NAMESPACE_URI, SVG_STOP_TAG);
+                gradientStop.setAttributeNS(null, SVG_OFFSET_ATTRIBUTE, String.valueOf(fractions[i]));
+
+                SVGPaintDescriptor colorDesc = SVGColor.toSVG(colors[i], generatorContext);
+                gradientStop.setAttributeNS(null, SVG_STOP_COLOR_ATTRIBUTE, colorDesc.getPaintValue());
+                gradientStop.setAttributeNS(null, SVG_STOP_OPACITY_ATTRIBUTE, colorDesc.getOpacityValue());
+
+                gradientDef.appendChild(gradientStop);
+            }
+
+            //
+            // Spread method
+            //
+            MultipleGradientPaint.CycleMethodEnum cycleMethodEnum = gradient.getCycleMethod();
+            if (cycleMethodEnum == MultipleGradientPaint.REFLECT)
+                gradientDef.setAttributeNS(null, SVG_SPREAD_METHOD_ATTRIBUTE, SVG_REFLECT_VALUE);
+            else if (cycleMethodEnum == MultipleGradientPaint.REPEAT)
+                gradientDef.setAttributeNS(null, SVG_SPREAD_METHOD_ATTRIBUTE, SVG_REPEAT_VALUE);
+
+            Point2D centerPoint = gradient.getCenterPoint();
+
+            gradientDef.setAttributeNS(null, SVG_CX_ATTRIBUTE, String.valueOf(centerPoint.getX()));
+            gradientDef.setAttributeNS(null, SVG_CY_ATTRIBUTE, String.valueOf(centerPoint.getY()));
+
+            gradientDef.setAttributeNS(null, SVG_R_ATTRIBUTE, String.valueOf(gradient.getRadius()));
+
+            Point2D focusPoint = gradient.getFocusPoint();
+            gradientDef.setAttributeNS(null, SVG_FX_ATTRIBUTE, String.valueOf(focusPoint.getX()));
+            gradientDef.setAttributeNS(null, SVG_FY_ATTRIBUTE, String.valueOf(focusPoint.getY()));
+
+            //
+            // Gradient ID
+            //
+            gradientDef.setAttributeNS(null, SVG_ID_ATTRIBUTE,
+                    generatorContext.idGenerator.generateID(ID_PREFIX_RADIAL_GRADIENT));
+
+            //
+            // Build Paint descriptor
+            //
+            StringBuffer paintAttrBuf = new StringBuffer(URL_PREFIX);
+            paintAttrBuf.append(SIGN_POUND);
+            paintAttrBuf.append(gradientDef.getAttributeNS(null, SVG_ID_ATTRIBUTE));
+            paintAttrBuf.append(URL_SUFFIX);
+
+            gradientDesc = new SVGPaintDescriptor(paintAttrBuf.toString(), SVG_OPAQUE_VALUE, gradientDef);
+
+            //
+            // Update maps so that gradient can be reused if needed
+            //
+            descMap.put(gradient, gradientDesc);
+            defSet.add(gradientDef);
+        }
+
+        return gradientDesc;
+    }
+}
      

Simple patch fixing unexpected crash if CSS fill rule has no numbers but text

diff -Naur batik-1.7/sources/org/apache/batik/css/engine/value/svg/BaselineShiftManager.java batik-1.7-vk\sources/org/apache/batik/css/engine/value/svg/BaselineShiftManager.java
--- batik-1.7/sources/org/apache/batik/css/engine/value/svg/BaselineShiftManager.java	2007-01-16 13:04:12.000000000 +0200
+++ batik-1.7-vk/sources/org/apache/batik/css/engine/value/svg/BaselineShiftManager.java	2011-02-17 17:04:52.666005700 +0200
@@ -152,11 +152,16 @@
                 // http://www.w3.org/TR/SVG11/text.html#BaselineShiftProperty
                 parent = elt;
             }
-            Value fs = engine.getComputedStyle(parent, pseudo, fsi);
-            float fsv = fs.getFloatValue();
-            float v = value.getFloatValue();
-            return new FloatValue(CSSPrimitiveValue.CSS_NUMBER,
-                                  (fsv * v) / 100f);
+            try{
+                Value fs = engine.getComputedStyle(parent, pseudo, fsi);
+                float fsv = fs.getFloatValue();
+                float v = value.getFloatValue();
+                return new FloatValue(CSSPrimitiveValue.CSS_NUMBER,
+                                      (fsv * v) / 100f);
+            }
+            catch(Exception e) {
+                return super.computeValue(elt, pseudo, engine, idx, sm, value);
+            }
         }
         return super.computeValue(elt, pseudo, engine, idx, sm, value);
     }
      

Version fix for SVG: version="1" means not 1.0 but 1.2 (workaround for Inkscape old versions)

diff -Naur batik-1.7/sources/org/apache/batik/dom/svg/SAXSVGDocumentFactory.java batik-1.7-vk\sources/org/apache/batik/dom/svg/SAXSVGDocumentFactory.java
--- batik-1.7/sources/org/apache/batik/dom/svg/SAXSVGDocumentFactory.java	2007-12-26 22:26:58.000000000 +0200
+++ batik-1.7-vk/sources/org/apache/batik/dom/svg/SAXSVGDocumentFactory.java	2010-11-16 15:42:07.645206300 +0200
@@ -319,10 +319,10 @@
         if (ver == null || ver.length() == 0
                 || ver.equals("1.0") || ver.equals("1.1")) {
             return SVGDOMImplementation.getDOMImplementation();
-        } else if (ver.equals("1.2")) {
+        } else if (ver.equals("1.2") || ver.equals("1"))  {
             return SVG12DOMImplementation.getDOMImplementation();
         }
-        throw new RuntimeException("Unsupport SVG version '" + ver + "'");
+        throw new RuntimeException("Unsupported SVG version '" + ver + "', expected 1.0, 1.1 or 1.2");
     }
 
     /**
	

Fix for unexpected exception `out of raster size`

diff -Naur batik-1.7/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java batik-1.7-vk\sources/org/apache/batik/ext/awt/image/GraphicsUtil.java
--- batik-1.7/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java	2007-12-26 22:27:04.000000000 +0200
+++ batik-1.7-vk/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java	2010-11-16 15:38:09.003206300 +0200
@@ -273,7 +273,17 @@
                 // Affine are prone to the 'CGGStackRestore: gstack
                 // underflow' bug on Mac OS X.  This should work
                 // around that problem.
-                g2d.drawImage(bi, clipR.x, clipR.y, null);
+
+                // VK: fix for out of raster size
+                try {
+                    g2d.drawImage(bi, clipR.x, clipR.y, null);
+                }
+                catch(Exception eo) {
+                    Shape oldClip = g2d.getClip();
+                    g2d.setClip(clipR);
+                    g2d.drawImage(bi, clipR.x, clipR.y, null);
+                    g2d.setClip(oldClip);
+                }
             } else {
                 // Use tiles to draw image...
                 wr = Raster.createWritableRaster(srcSM, new Point(0,0));
	

Workaround for SVGGen to not write `id` attribute twice

diff -Naur batik-1.7/sources/org/apache/batik/svggen/XmlWriter.java batik-1.7-vk\sources/org/apache/batik/svggen/XmlWriter.java
--- batik-1.7/sources/org/apache/batik/svggen/XmlWriter.java	2007-01-16 13:04:14.000000000 +0200
+++ batik-1.7-vk/sources/org/apache/batik/svggen/XmlWriter.java	2010-11-16 20:32:11.313897700 +0200
@@ -372,10 +372,22 @@
         out.write (element.getTagName());
 
         NamedNodeMap attributes = element.getAttributes();
+        boolean gotId = false;
         if (attributes != null){
             int nAttr = attributes.getLength();
             for(int i=0; i < nAttr; i++){
                 Attr attr = (Attr)attributes.item(i);
+                String ln = attr.getLocalName();
+                if(ln == null) ln = attr.getName();
+                if(ln == null) continue;
+                if(ln.endsWith(":id")) ln = "id";
+                if(ln.equalsIgnoreCase("id")) {
+                	if(gotId){ 
+                		continue;
+                	}
+                	else 
+                		gotId = true;
+                }
                 out.write(' ');
                 writeXml(attr, out, escaped);
             }
	

To be continued