You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2008/08/06 20:40:47 UTC

svn commit: r683364 - in /xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java: META-INF/services/ org/apache/fop/render/intermediate/ org/apache/fop/render/pdf/

Author: jeremias
Date: Wed Aug  6 11:40:47 2008
New Revision: 683364

URL: http://svn.apache.org/viewvc?rev=683364&view=rev
Log:
Fix for kerning (switched to SVG semantics, now working correctly for both SVG and PDF)
Introduced a special SVG image handler (the successor to PDFSVGHandler).
Fixed placement of patterns and links in SVGs for PDF output (the transformations for viewbox and group were not recorded in the state).

Added:
    xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java   (contents, props changed)
      - copied, changed from r680381, xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java
Modified:
    xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/META-INF/services/org.apache.fop.render.ImageHandler
    xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/intermediate/IFRenderer.java
    xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
    xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFPainter.java
    xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFRenderer.java

Modified: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/META-INF/services/org.apache.fop.render.ImageHandler
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/META-INF/services/org.apache.fop.render.ImageHandler?rev=683364&r1=683363&r2=683364&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/META-INF/services/org.apache.fop.render.ImageHandler (original)
+++ xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/META-INF/services/org.apache.fop.render.ImageHandler Wed Aug  6 11:40:47 2008
@@ -2,3 +2,4 @@
 org.apache.fop.render.pdf.PDFImageHandlerRenderedImage
 org.apache.fop.render.pdf.PDFImageHandlerRawJPEG
 org.apache.fop.render.pdf.PDFImageHandlerRawCCITTFax
+org.apache.fop.render.pdf.PDFImageHandlerSVG

Modified: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/intermediate/IFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/intermediate/IFRenderer.java?rev=683364&r1=683363&r2=683364&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/intermediate/IFRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/intermediate/IFRenderer.java Wed Aug  6 11:40:47 2008
@@ -670,14 +670,14 @@
                 glyphAdjust -= tls;
             }
             curX += font.getCharWidth(ch);
-            if (letterAdjust != null && i < l - 1) {
-                glyphAdjust -= letterAdjust[i + 1];
+            if (letterAdjust != null && i < l) {
+                glyphAdjust -= letterAdjust[i];
             }
 
             float adjust = glyphAdjust / fontSize;
 
             if (adjust != 0) {
-                dx[i] = Math.round(adjust);
+                dx[i] = Math.round(adjust * -10);
                 if (dx[i] != 0) {
                     hasDX = true;
                 }

Modified: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java?rev=683364&r1=683363&r2=683364&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java (original)
+++ xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java Wed Aug  6 11:40:47 2008
@@ -185,23 +185,27 @@
     }
 
     /**
-     * Concatenates the given transformation matrix with the current one.
-     * @param transform the transformation matrix (in points)
-     */
-    public void concatenate(AffineTransform transform) {
-        concatenate(transform, false);
+     * Converts a transformation matrix from millipoints to points.
+     * @param transform the transformation matrix (in millipoints)
+     * @return the converted transformation matrix (in points)
+     */
+    public AffineTransform toPoints(AffineTransform transform) {
+        final double[] matrix = new double[6];
+        transform.getMatrix(matrix);
+        //Convert from millipoints to points
+        matrix[4] /= 1000;
+        matrix[5] /= 1000;
+        return new AffineTransform(matrix);
     }
 
     /**
      * Concatenates the given transformation matrix with the current one.
-     * @param transform the transformation matrix
-     * @param convertMillipoints true if the coordinates are in millipoints and need to be
-     *          converted to points
+     * @param transform the transformation matrix (in points)
      */
-    public void concatenate(AffineTransform transform, boolean convertMillipoints) {
+    public void concatenate(AffineTransform transform) {
         if (!transform.isIdentity()) {
             currentState.concatenate(transform);
-            currentStream.add(CTMHelper.toPDFString(transform, convertMillipoints) + " cm\n");
+            currentStream.add(CTMHelper.toPDFString(transform, false) + " cm\n");
         }
     }
 

Copied: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java (from r680381, xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java)
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java?p2=xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java&p1=xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java&r1=680381&r2=683364&rev=683364&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java (original)
+++ xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java Wed Aug  6 11:40:47 2008
@@ -19,41 +19,157 @@
 
 package org.apache.fop.render.pdf;
 
-import java.awt.Point;
+import java.awt.Color;
 import java.awt.Rectangle;
+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.svg.SVGDOMImplementation;
+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.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
 
-import org.apache.fop.pdf.PDFXObject;
-import org.apache.fop.render.RendererContext;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.image.loader.batik.BatikImageFlavors;
+import org.apache.fop.render.ImageHandler;
+import org.apache.fop.render.RenderingContext;
+import org.apache.fop.svg.PDFAElementBridge;
+import org.apache.fop.svg.PDFBridgeContext;
+import org.apache.fop.svg.PDFGraphics2D;
+import org.apache.fop.svg.SVGEventProducer;
+import org.apache.fop.svg.SVGUserAgent;
 
 /**
- * PDFImageHandler implementation which handles XML-based images.
+ * Image Handler implementation which handles SVG images.
  */
-public class PDFImageHandlerXML implements PDFImageHandler {
+public class PDFImageHandlerSVG implements ImageHandler {
 
-    private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
-        ImageFlavor.XML_DOM,
-    };
+    /** logging instance */
+    private static Log log = LogFactory.getLog(PDFImageHandlerSVG.class);
 
     /** {@inheritDoc} */
-    public PDFXObject generateImage(RendererContext context, Image image,
-            Point origin, Rectangle pos)
-            throws IOException {
-        PDFRenderer renderer = (PDFRenderer)context.getRenderer();
-        ImageXMLDOM imgXML = (ImageXMLDOM)image;
-        Document doc = imgXML.getDocument();
-        String ns = imgXML.getRootNamespace();
-        Map foreignAttributes = (Map)context.getProperty(
-                PDFRendererContextConstants.FOREIGN_ATTRIBUTES);
-        renderer.renderDocument(doc, ns, pos, foreignAttributes);
-        return null;
+    public void handleImage(RenderingContext context, Image image, Rectangle pos)
+                throws IOException {
+        PDFRenderingContext pdfContext = (PDFRenderingContext)context;
+        PDFContentGenerator generator = pdfContext.getGenerator();
+        ImageXMLDOM imageSVG = (ImageXMLDOM)image;
+
+        FOUserAgent userAgent = context.getUserAgent();
+        final float deviceResolution = userAgent.getTargetResolution();
+        if (log.isDebugEnabled()) {
+            log.debug("Generating SVG at " + deviceResolution + "dpi.");
+        }
+
+        final float uaResolution = userAgent.getSourceResolution();
+        SVGUserAgent ua = new SVGUserAgent(userAgent, new AffineTransform());
+
+        //Scale for higher resolution on-the-fly images from Batik
+        double s = uaResolution / deviceResolution;
+        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;
+        //TODO connect with configuration elsewhere.
+
+        BridgeContext ctx = new PDFBridgeContext(ua,
+                (strokeText ? null : pdfContext.getFontInfo()),
+                userAgent.getFactory().getImageManager(),
+                userAgent.getImageSessionContext(),
+                new AffineTransform());
+
+        GraphicsNode root;
+        try {
+            root = builder.build(ctx, imageSVG.getDocument());
+            builder = null;
+        } catch (Exception e) {
+            SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+                    context.getUserAgent().getEventBroadcaster());
+            eventProducer.svgNotBuilt(this, e, image.getInfo().getOriginalURI());
+            return;
+        }
+        // get the 'width' and 'height' attributes of the SVG document
+        float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
+        float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
+
+        float sx = pos.width / (float)w;
+        float sy = pos.height / (float)h;
+
+        //Scaling and translation for the bounding box of the image
+        AffineTransform scaling = new AffineTransform(
+                sx, 0, 0, sy, pos.x / 1000f, pos.y / 1000f);
+
+        //Transformation matrix that establishes the local coordinate system for the SVG graphic
+        //in relation to the current coordinate system
+        AffineTransform imageTransform = new AffineTransform();
+        imageTransform.concatenate(scaling);
+        imageTransform.concatenate(resolutionScaling);
+
+        /*
+         * Clip to the svg area.
+         * Note: To have the svg overlay (under) a text area then use
+         * an fo:block-container
+         */
+        generator.comment("SVG setup");
+        generator.saveGraphicsState();
+        generator.setColor(Color.black, false);
+        generator.setColor(Color.black, true);
+
+        if (!scaling.isIdentity()) {
+            generator.comment("viewbox");
+            generator.add(CTMHelper.toPDFString(scaling, false) + " cm\n");
+        }
+
+        //SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
+
+        PDFGraphics2D graphics = new PDFGraphics2D(true, pdfContext.getFontInfo(),
+                generator.getDocument(),
+                generator.getResourceContext(), pdfContext.getPage().referencePDF(),
+                "", 0);
+        graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
+
+        if (!resolutionScaling.isIdentity()) {
+            generator.comment("resolution scaling for " + uaResolution
+                        + " -> " + deviceResolution + "\n");
+            generator.add(
+                    CTMHelper.toPDFString(resolutionScaling, false) + " cm\n");
+            graphics.scale(1 / s, 1 / s);
+        }
+
+        generator.comment("SVG start");
+
+        //Save state and update coordinate system for the SVG image
+        generator.getState().push();
+        generator.getState().concatenate(imageTransform);
+
+        //Now that we have the complete transformation matrix for the image, we can update the
+        //transformation matrix for the AElementBridge.
+        PDFAElementBridge aBridge = (PDFAElementBridge)ctx.getBridge(
+                SVGDOMImplementation.SVG_NAMESPACE_URI, SVGConstants.SVG_A_TAG);
+        aBridge.getCurrentTransform().setTransform(generator.getState().getTransform());
+
+        graphics.setPDFState(generator.getState());
+        graphics.setOutputStream(generator.getOutputStream());
+        try {
+            root.paint(graphics);
+            generator.add(graphics.getString());
+        } catch (Exception e) {
+            SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
+                    context.getUserAgent().getEventBroadcaster());
+            eventProducer.svgRenderingError(this, e, image.getInfo().getOriginalURI());
+        }
+        generator.getState().pop();
+        generator.restoreGraphicsState();
+        generator.comment("SVG end");
     }
 
     /** {@inheritDoc} */
@@ -68,7 +184,17 @@
 
     /** {@inheritDoc} */
     public ImageFlavor[] getSupportedImageFlavors() {
-        return FLAVORS;
+        return new ImageFlavor[] {
+                BatikImageFlavors.SVG_DOM
+            };
+    }
+
+    /** {@inheritDoc} */
+    public boolean isCompatible(RenderingContext targetContext, Image image) {
+        return (image == null
+                || (image instanceof ImageXMLDOM
+                        && image.getFlavor().isCompatible(BatikImageFlavors.SVG_DOM))
+                && targetContext instanceof PDFRenderingContext);
     }
 
 }

Propchange: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
------------------------------------------------------------------------------
--- svn:mergeinfo (added)
+++ svn:mergeinfo Wed Aug  6 11:40:47 2008
@@ -0,0 +1 @@
+/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java:603620-680380

Modified: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFPainter.java?rev=683364&r1=683363&r2=683364&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFPainter.java (original)
+++ xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFPainter.java Wed Aug  6 11:40:47 2008
@@ -209,8 +209,8 @@
         this.generator = new PDFContentGenerator(this.pdfDoc, this.outputStream, this.currentPage);
         // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFPainter's
         AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0,
-                size.height);
-        generator.concatenate(basicPageTransform, true);
+                size.height / 1000f);
+        generator.concatenate(basicPageTransform);
     }
 
     /** {@inheritDoc} */
@@ -260,7 +260,7 @@
     public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect)
             throws IFException {
         generator.saveGraphicsState();
-        generator.add(CTMHelper.toPDFString(transform, true) + " cm\n");
+        generator.concatenate(generator.toPoints(transform));
         if (clipRect != null) {
             StringBuffer sb = new StringBuffer();
             sb.append(format(clipRect.x)).append(' ');
@@ -279,7 +279,7 @@
     /** {@inheritDoc} */
     public void startGroup(AffineTransform transform) throws IFException {
         generator.saveGraphicsState();
-        generator.add(CTMHelper.toPDFString(transform, true) + " cm\n");
+        generator.concatenate(generator.toPoints(transform));
     }
 
     /** {@inheritDoc} */
@@ -470,7 +470,7 @@
         int dxl = (dx != null ? dx.length : 0);
 
         if (dx != null && dxl > 0 && dx[0] != 0) {
-            textutil.adjustGlyphTJ(dx[0] / fontSize);
+            textutil.adjustGlyphTJ(dx[0]);
         }
         for (int i = 0; i < l; i++) {
             char orgChar = text.charAt(i);
@@ -504,7 +504,7 @@
             }
 
             if (glyphAdjust != 0) {
-                textutil.adjustGlyphTJ(glyphAdjust / fontSize);
+                textutil.adjustGlyphTJ(-glyphAdjust / 10f);
             }
 
         }

Modified: xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFRenderer.java?rev=683364&r1=683363&r2=683364&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFRenderer.java (original)
+++ xmlgraphics/fop/branches/Temp_AreaTreeNewDesign/src/java/org/apache/fop/render/pdf/PDFRenderer.java Wed Aug  6 11:40:47 2008
@@ -34,6 +34,7 @@
 import java.util.Map;
 
 import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.ImageInfo;
 import org.apache.xmlgraphics.image.loader.ImageManager;
 import org.apache.xmlgraphics.image.loader.ImageSessionContext;
@@ -1296,8 +1297,9 @@
             info = manager.getImageInfo(uri, sessionContext);
 
             Map hints = ImageUtil.getDefaultHints(sessionContext);
+            ImageFlavor[] supportedFlavors = imageHandlerRegistry.getSupportedFlavors();
             org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
-                        info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext);
+                        info, supportedFlavors, hints, sessionContext);
 
             //First check for a dynamically registered handler
             PDFImageHandler handler = imageHandlerRegistry.getHandler(img.getClass());



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org