]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #46360:
authorJeremias Maerki <jeremias@apache.org>
Sun, 7 Dec 2008 18:01:24 +0000 (18:01 +0000)
committerJeremias Maerki <jeremias@apache.org>
Sun, 7 Dec 2008 18:01:24 +0000 (18:01 +0000)
Fixed a multi-threading issue when rendering SVG.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@724163 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java
src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
src/java/org/apache/fop/render/afp/AFPSVGHandler.java
src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java
src/java/org/apache/fop/render/pdf/PDFRenderer.java
src/java/org/apache/fop/render/pdf/PDFSVGHandler.java
src/java/org/apache/fop/render/ps/PSSVGHandler.java
status.xml

index 81c12a628d4bcea8e8e96f86adf9b5e67069513b..2bb521dc9485c2e80fef0c901ba8f9a733bb1e9b 100644 (file)
@@ -23,6 +23,8 @@ import java.awt.Dimension;
 import java.awt.geom.AffineTransform;
 import java.util.Map;
 
+import org.w3c.dom.Document;
+
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.GVTBuilder;
 import org.apache.batik.bridge.UserAgent;
@@ -30,7 +32,7 @@ import org.apache.batik.dom.svg.SVGDOMImplementation;
 import org.apache.batik.gvt.GraphicsNode;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.fop.svg.SimpleSVGUserAgent;
+
 import org.apache.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageException;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
@@ -43,6 +45,8 @@ import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
 import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
 import org.apache.xmlgraphics.util.UnitConv;
 
+import org.apache.fop.svg.SimpleSVGUserAgent;
+
 /**
  * This ImageConverter converts SVG images to Java2D.
  * <p>
@@ -75,10 +79,15 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter {
         GVTBuilder builder = new GVTBuilder();
         final BridgeContext ctx = new BridgeContext(ua);
 
+        Document doc = svg.getDocument();
+        //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+        //to it.
+        Document clonedDoc = BatikUtil.cloneSVGDocument(doc);
+
         //Build the GVT tree
         final GraphicsNode root;
         try {
-            root = builder.build(ctx, svg.getDocument());
+            root = builder.build(ctx, clonedDoc);
         } catch (Exception e) {
             throw new ImageException("GVT tree could not be built for SVG graphic", e);
         }
index 5c253fe9466ccbd6d35bfaa87dfc8ce4034cb618..35876a728398926d2e98e950649a7ce4fd16201c 100644 (file)
@@ -24,22 +24,25 @@ import java.awt.Dimension;
 import java.awt.geom.AffineTransform;
 import java.io.IOException;
 
+import org.w3c.dom.Document;
+
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.GVTBuilder;
 import org.apache.batik.dom.AbstractDocument;
 import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.dom.util.DOMUtilities;
 import org.apache.batik.gvt.GraphicsNode;
+
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.apache.xmlgraphics.util.QName;
+
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.events.EventBroadcaster;
 import org.apache.fop.fo.extensions.ExtensionElementMapping;
 import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl;
 import org.apache.fop.render.RendererContext.RendererContextWrapper;
-import org.apache.fop.render.afp.AFPGraphics2DAdapter;
 import org.apache.fop.svg.SVGEventProducer;
 import org.apache.fop.svg.SVGUserAgent;
-import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
-import org.apache.xmlgraphics.util.QName;
-import org.w3c.dom.Document;
 
 /**
  * Generic XML handler for SVG. Uses Apache Batik for SVG processing and simply paints to
@@ -133,15 +136,19 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
         //Create Batik BridgeContext
         final BridgeContext bridgeContext = new BridgeContext(svgUserAgent);
 
-        //Build the GVT tree
+        //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+        //to it.
+        Document clonedDoc = DOMUtilities.deepCloneDocument(doc, doc.getImplementation());
 
-        final GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc);
+        //Build the GVT tree
+        final GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, clonedDoc);
 
         // Create Graphics2DImagePainter
         final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext(
                 rendererContext);
         Dimension imageSize = getImageSize(wrappedContext);
-        final Graphics2DImagePainter painter = createGraphics2DImagePainter(root, bridgeContext, imageSize);
+        final Graphics2DImagePainter painter = createGraphics2DImagePainter(
+                root, bridgeContext, imageSize);
 
         //Let the painter paint the SVG on the Graphics2D instance
         Graphics2DAdapter g2dAdapter = rendererContext.getRenderer().getGraphics2DAdapter();
index 9deea77b420c207a67424ace85d661702ed4a090..ca64d6bc294842ab460a6e3d24607a096d4b44ed 100644 (file)
@@ -24,9 +24,18 @@ import java.awt.Dimension;
 import java.awt.geom.AffineTransform;
 import java.io.IOException;
 
+import org.w3c.dom.Document;
+
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.dom.util.DOMUtilities;
 import org.apache.batik.gvt.GraphicsNode;
+
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.apache.xmlgraphics.util.MimeConstants;
+
 import org.apache.fop.afp.AFPGraphics2D;
 import org.apache.fop.afp.AFPGraphicsObjectInfo;
 import org.apache.fop.afp.AFPObjectAreaInfo;
@@ -44,11 +53,6 @@ import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.RendererContext.RendererContextWrapper;
 import org.apache.fop.svg.SVGEventProducer;
 import org.apache.fop.svg.SVGUserAgent;
-import org.apache.xmlgraphics.image.loader.ImageManager;
-import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
-import org.apache.xmlgraphics.util.MimeConstants;
-import org.w3c.dom.Document;
 
 /**
  * AFP XML handler for SVG. Uses Apache Batik for SVG processing.
@@ -107,8 +111,12 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler {
         // Create an AFPBridgeContext
         BridgeContext bridgeContext = createBridgeContext(userAgent, g2d);
 
+        //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+        //to it.
+        Document clonedDoc = DOMUtilities.deepCloneDocument(doc, doc.getImplementation());
+
         // Build the SVG DOM and provide the painter with it
-        GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc);
+        GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, clonedDoc);
 
         // Create Graphics2DImagePainter
         final RendererContextWrapper wrappedContext
index ba5c860594a24d5b6e085496b57f36d577d36217..2d16b120d142b2bfc0a5e7b3cf43947b2e6df3fb 100644 (file)
@@ -23,18 +23,21 @@ import java.awt.geom.AffineTransform;
 import java.io.IOException;
 import java.util.Map;
 
+import org.w3c.dom.Document;
+
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.GVTBuilder;
+import org.apache.batik.dom.util.DOMUtilities;
 import org.apache.batik.gvt.GraphicsNode;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.apache.fop.render.AbstractGenericSVGHandler;
 import org.apache.fop.render.Renderer;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.render.RendererContextConstants;
 import org.apache.fop.svg.SVGEventProducer;
 import org.apache.fop.svg.SVGUserAgent;
-import org.w3c.dom.Document;
 
 /**
  * Java2D XML handler for SVG (uses Apache Batik).
@@ -128,12 +131,16 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler
 
         SVGUserAgent ua = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
 
-        GVTBuilder builder = new GVTBuilder();
         BridgeContext ctx = new BridgeContext(ua);
 
+        //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+        //to it.
+        Document clonedDoc = DOMUtilities.deepCloneDocument(doc, doc.getImplementation());
+
         GraphicsNode root;
         try {
-            root = builder.build(ctx, doc);
+            GVTBuilder builder = new GVTBuilder();
+            root = builder.build(ctx, clonedDoc);
         } catch (Exception e) {
             SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
                     context.getUserAgent().getEventBroadcaster());
index e31f1eaeae82965575a5d156c6fb06f5fdd52c8e..dda7e2083733b411365d183eb2316b4f00fa115d 100644 (file)
@@ -1635,6 +1635,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
                 (int)pos.getHeight());
 
         uri = URISpecification.getURL(uri);
+        uri = URISpecification.preResolveURI(uri, userAgent.getBaseURL());
         PDFXObject xobject = pdfDoc.getXObject(uri);
         if (xobject != null) {
             float w = (float) pos.getWidth() / 1000f;
index 5d027aefe21405a6d2ce1c2b30191956658732b1..0bf9bd95bdb0af0783ffaec42064df3ed572cb14 100644 (file)
@@ -25,14 +25,18 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Map;
 
+import org.w3c.dom.Document;
+
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.GVTBuilder;
 import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.dom.util.DOMUtilities;
 import org.apache.batik.gvt.GraphicsNode;
 import org.apache.batik.util.SVGConstants;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.pdf.PDFDocument;
@@ -49,7 +53,6 @@ import org.apache.fop.svg.PDFBridgeContext;
 import org.apache.fop.svg.PDFGraphics2D;
 import org.apache.fop.svg.SVGEventProducer;
 import org.apache.fop.svg.SVGUserAgent;
-import org.w3c.dom.Document;
 
 /**
  * PDF XML handler for SVG (uses Apache Batik).
@@ -164,8 +167,6 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
         AffineTransform resolutionScaling = new AffineTransform();
         resolutionScaling.scale(s, s);
 
-        GVTBuilder builder = new GVTBuilder();
-
         //Controls whether text painted by Batik is generated using text or path operations
         boolean strokeText = false;
         Configuration cfg = pdfInfo.cfg;
@@ -179,10 +180,14 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler
                 userAgent.getImageSessionContext(),
                 new AffineTransform());
 
+        //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+        //to it.
+        Document clonedDoc = DOMUtilities.deepCloneDocument(doc, doc.getImplementation());
+
         GraphicsNode root;
         try {
-            root = builder.build(ctx, doc);
-            builder = null;
+            GVTBuilder builder = new GVTBuilder();
+            root = builder.build(ctx, clonedDoc);
         } catch (Exception e) {
             SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
                     context.getUserAgent().getEventBroadcaster());
index 1e65dfb984b37c9a36f3c0f78c77e0fa9aa82a1b..646cd3823464bd8a37196c16e826fc850e656664 100644 (file)
@@ -29,6 +29,7 @@ import org.w3c.dom.Document;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.GVTBuilder;
+import org.apache.batik.dom.util.DOMUtilities;
 import org.apache.batik.gvt.GraphicsNode;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -258,7 +259,6 @@ public class PSSVGHandler extends AbstractGenericSVGHandler
         PSGraphics2D graphics = new PSGraphics2D(strokeText, gen);
         graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
 
-        GVTBuilder builder = new GVTBuilder();
         NativeTextHandler nativeTextHandler = null;
         BridgeContext ctx = new BridgeContext(ua);
         if (!strokeText) {
@@ -271,9 +271,14 @@ public class PSSVGHandler extends AbstractGenericSVGHandler
             ctx.putBridge(tBridge);
         }
 
+        //Cloning SVG DOM as Batik attaches non-thread-safe facilities (like the CSS engine)
+        //to it.
+        Document clonedDoc = DOMUtilities.deepCloneDocument(doc, doc.getImplementation());
+
         GraphicsNode root;
         try {
-            root = builder.build(ctx, doc);
+            GVTBuilder builder = new GVTBuilder();
+            root = builder.build(ctx, clonedDoc);
         } catch (Exception e) {
             SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
                     context.getUserAgent().getEventBroadcaster());
@@ -288,7 +293,6 @@ public class PSSVGHandler extends AbstractGenericSVGHandler
         float sy = psInfo.getHeight() / h;
 
         ctx = null;
-        builder = null;
 
         try {
             gen.commentln("%FOPBeginSVG");
index 0f139fba78602a754e2fcbb027b8480921d7bd4f..b2e37dd33a6381a2131cd6206f00bdd0b26bece8 100644 (file)
@@ -53,6 +53,9 @@
 
   <changes>
     <release version="FOP Trunk" date="TBD">
+      <action context="Renderers" dev="JM" type="fix" fixed-bug="46360">
+        Fixed a multi-threading issue when rendering SVG.
+      </action>
       <action context="Renderers" dev="AC" importance="high" type="add">
         AFP Output: An AFPGraphics2D implementation which provides the ability to use Batik to drive the production of AFP Graphics (GOCA) output from SVG.
       </action>