aboutsummaryrefslogtreecommitdiffstats
path: root/src/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java')
-rw-r--r--src/java/META-INF/services/org.apache.fop.render.ImageHandler1
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFRenderer.java6
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFContentGenerator.java22
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java200
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFPainter.java12
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java4
6 files changed, 226 insertions, 19 deletions
diff --git a/src/java/META-INF/services/org.apache.fop.render.ImageHandler b/src/java/META-INF/services/org.apache.fop.render.ImageHandler
index 8f4354630..81accc88a 100644
--- a/src/java/META-INF/services/org.apache.fop.render.ImageHandler
+++ b/src/java/META-INF/services/org.apache.fop.render.ImageHandler
@@ -2,3 +2,4 @@ org.apache.fop.render.pdf.PDFImageHandlerGraphics2D
org.apache.fop.render.pdf.PDFImageHandlerRenderedImage
org.apache.fop.render.pdf.PDFImageHandlerRawJPEG
org.apache.fop.render.pdf.PDFImageHandlerRawCCITTFax
+org.apache.fop.render.pdf.PDFImageHandlerSVG
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index e870a4263..ed25063e5 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -670,14 +670,14 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
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;
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
index ba2a20707..8d5b4ccb0 100644
--- a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
+++ b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
@@ -185,23 +185,27 @@ public class PDFContentGenerator {
}
/**
- * Concatenates the given transformation matrix with the current one.
- * @param transform the transformation matrix (in points)
+ * Converts a transformation matrix from millipoints to points.
+ * @param transform the transformation matrix (in millipoints)
+ * @return the converted transformation matrix (in points)
*/
- public void concatenate(AffineTransform transform) {
- concatenate(transform, false);
+ 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");
}
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
new file mode 100644
index 000000000..975f72c06
--- /dev/null
+++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerSVG.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.pdf;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.io.IOException;
+
+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.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;
+
+/**
+ * Image Handler implementation which handles SVG images.
+ */
+public class PDFImageHandlerSVG implements ImageHandler {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(PDFImageHandlerSVG.class);
+
+ /** {@inheritDoc} */
+ 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} */
+ public int getPriority() {
+ return 400;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageXMLDOM.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ 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);
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/pdf/PDFPainter.java b/src/java/org/apache/fop/render/pdf/PDFPainter.java
index 5b763b197..8747edcec 100644
--- a/src/java/org/apache/fop/render/pdf/PDFPainter.java
+++ b/src/java/org/apache/fop/render/pdf/PDFPainter.java
@@ -209,8 +209,8 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
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 class PDFPainter extends AbstractBinaryWritingIFPainter {
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 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
/** {@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 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
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 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
}
if (glyphAdjust != 0) {
- textutil.adjustGlyphTJ(glyphAdjust / fontSize);
+ textutil.adjustGlyphTJ(-glyphAdjust / 10f);
}
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 4ce3dfbd9..fbcf892a0 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -34,6 +34,7 @@ import java.util.List;
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 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
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());