]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
* PDFImageHandler interface split into ImageHandler and PDFImageHandler.
authorAdrian Cumiskey <acumiskey@apache.org>
Thu, 13 Nov 2008 16:11:58 +0000 (16:11 +0000)
committerAdrian Cumiskey <acumiskey@apache.org>
Thu, 13 Nov 2008 16:11:58 +0000 (16:11 +0000)
* Deleted AFPDataObjectInfoProvider and AFPImage*Factory implementations, and abstracted AbstractImageHandlerRegistry from PDFImageHandlerRegistry, creating AFPImageHandlerRegistry and AFPImageHandler so there is a common reuse of image handling implementation between AFP and PDF now.
* RendererContext instantiation is now overridable in PrintRenderer.
* Created AFPRendererContext that is able to provide AFPInfo.
* toString() added to RendererContext for ease of use.
* Removed GraphicsObjectPainterAFP.
* Added package.html for AFP (sub)packages.
* Abstracted AbstractFOPBridgeContext from PDFBridgeContext and provided AFPBridgeContext implementation.
* Abstracted AbstractFOPTextElementBridge from PDFTextElementBridge and provided AFPTextElementBridge implementation.
* Abstracted AbstractFOPImageElementBridge from PDFImageElementBridge and provided AFPImageElementBridge implementation.
* Provided inline image support/handling in AFPGraphics2D for SVG.
* Created NativeImageHandler interface.
* Fix for path iterator filled line drawing in AFPGraphics2D adding coordinate drawing implementations GraphicsLineRelative and GraphicsFilletRelative (Thanks for the patch Jeremias).
* Improved configuration.xml documentation for images mode/native setting in AFP renderer configuration.

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

82 files changed:
src/documentation/content/xdocs/trunk/configuration.xml
src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler [new file with mode: 0644]
src/java/org/apache/fop/afp/AFPForeignAttributeReader.java [deleted file]
src/java/org/apache/fop/afp/AFPGraphics2D.java
src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java
src/java/org/apache/fop/afp/AFPPageFonts.java [deleted file]
src/java/org/apache/fop/afp/AFPPaintingState.java
src/java/org/apache/fop/afp/AFPResourceManager.java
src/java/org/apache/fop/afp/AFPStreamer.java
src/java/org/apache/fop/afp/AFPTextElementBridge.java [deleted file]
src/java/org/apache/fop/afp/AFPTextHandler.java [deleted file]
src/java/org/apache/fop/afp/AFPTextPainter.java [deleted file]
src/java/org/apache/fop/afp/Graphics2DImagePainterGOCA.java
src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java
src/java/org/apache/fop/afp/fonts/AFPPageFonts.java [new file with mode: 0644]
src/java/org/apache/fop/afp/fonts/package.html [new file with mode: 0644]
src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java
src/java/org/apache/fop/afp/goca/GraphicsFilletRelative.java [new file with mode: 0644]
src/java/org/apache/fop/afp/goca/GraphicsLine.java
src/java/org/apache/fop/afp/goca/GraphicsLineRelative.java [new file with mode: 0644]
src/java/org/apache/fop/afp/goca/package.html [new file with mode: 0644]
src/java/org/apache/fop/afp/ioca/package.html [new file with mode: 0644]
src/java/org/apache/fop/afp/modca/GraphicsObject.java
src/java/org/apache/fop/afp/modca/package.html [new file with mode: 0644]
src/java/org/apache/fop/afp/modca/triplets/package.html [new file with mode: 0644]
src/java/org/apache/fop/afp/package.html [new file with mode: 0644]
src/java/org/apache/fop/afp/svg/AFPBridgeContext.java [new file with mode: 0644]
src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java [new file with mode: 0644]
src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java [new file with mode: 0644]
src/java/org/apache/fop/afp/svg/AFPTextHandler.java [new file with mode: 0644]
src/java/org/apache/fop/afp/svg/AFPTextPainter.java [new file with mode: 0644]
src/java/org/apache/fop/fonts/FontInfo.java
src/java/org/apache/fop/fonts/package.html
src/java/org/apache/fop/pdf/package.html
src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java
src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java [new file with mode: 0644]
src/java/org/apache/fop/render/ImageHandler.java [new file with mode: 0644]
src/java/org/apache/fop/render/PrintRenderer.java
src/java/org/apache/fop/render/RendererContext.java
src/java/org/apache/fop/render/afp/AFPAbstractImageFactory.java [deleted file]
src/java/org/apache/fop/render/afp/AFPDataObjectInfoFactory.java [deleted file]
src/java/org/apache/fop/render/afp/AFPDataObjectInfoProvider.java [deleted file]
src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java
src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java [deleted file]
src/java/org/apache/fop/render/afp/AFPImageHandler.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPImageRawStreamFactory.java [deleted file]
src/java/org/apache/fop/render/afp/AFPImageRenderedFactory.java [deleted file]
src/java/org/apache/fop/render/afp/AFPInfo.java
src/java/org/apache/fop/render/afp/AFPRawCCITTFaxFactory.java [deleted file]
src/java/org/apache/fop/render/afp/AFPRenderer.java
src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
src/java/org/apache/fop/render/afp/AFPRendererContext.java [new file with mode: 0644]
src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java
src/java/org/apache/fop/render/afp/AFPSVGHandler.java
src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java [deleted file]
src/java/org/apache/fop/render/afp/package.html [new file with mode: 0644]
src/java/org/apache/fop/render/pdf/PDFImageHandler.java
src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java
src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java
src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java
src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java
src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java
src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java
src/java/org/apache/fop/render/pdf/PDFRenderer.java
src/java/org/apache/fop/render/ps/PSTextPainter.java
src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java [new file with mode: 0644]
src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java [new file with mode: 0644]
src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java [new file with mode: 0644]
src/java/org/apache/fop/svg/NativeImageHandler.java [new file with mode: 0644]
src/java/org/apache/fop/svg/PDFBridgeContext.java
src/java/org/apache/fop/svg/PDFGraphics2D.java
src/java/org/apache/fop/svg/PDFImageElementBridge.java
src/java/org/apache/fop/svg/PDFTextElementBridge.java
src/java/org/apache/fop/svg/PDFTextPainter.java

index 131b89a3700bd64cf9583bacac01c7dcd9c44d5a..08463b9b98c31252e72b524e84ecdee053ce215f 100644 (file)
   <resource-group-file>resources.afp</resource-group-file>
 </renderer>]]></source>
       <p>
-        The default value for the "images mode" setting is "b+w" (black and white).  When the setting is "color" a "bits-per-pixel" setting can be provided.  When the setting "native" is set to true, images (TIFF, JPEG and Encapsulated Postscript) will be placed in the datastream in their native form using a MO:DCA Object Container.
+        The default value for the images "mode" setting is "b+w" (black and white).  When the images "mode" setting is "b+w" a "bits-per-pixel" setting can be provided to aid the grayscale conversion process.  With this setting all images referenced in your source document are converted to an IOCA FS45 grayscale bitmap image form. 
+        When the setting is "color" all images are converted to an IOCA FS45 color bitmap image form.  When "native" setting is "true", all images encountered (TIFF, GIF, JPEG and Encapsulated Postscript etc.) will be embedded directly in the datastream in their native form using a MO:DCA Object Container.
       </p>
       <p>
         The default value for the "renderer-resolution" is 240 dpi. 
diff --git a/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler b/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler
new file mode 100644 (file)
index 0000000..deab7d2
--- /dev/null
@@ -0,0 +1,5 @@
+org.apache.fop.render.afp.AFPImageHandlerRenderedImage\r
+org.apache.fop.render.afp.AFPImageHandlerRawCCITTFax\r
+org.apache.fop.render.afp.AFPImageHandlerRawStream\r
+org.apache.fop.render.afp.AFPImageHandlerGraphics2D\r
+org.apache.fop.render.afp.AFPImageHandlerXML\r
diff --git a/src/java/org/apache/fop/afp/AFPForeignAttributeReader.java b/src/java/org/apache/fop/afp/AFPForeignAttributeReader.java
deleted file mode 100644 (file)
index 710c245..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.afp;
-
-import java.io.File;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.render.afp.extensions.AFPElementMapping;
-import org.apache.xmlgraphics.util.QName;
-
-/**
- * Parses any AFP foreign attributes
- */
-public class AFPForeignAttributeReader {
-    private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
-
-    /** the resource-name attribute */
-    public static final String RESOURCE_NAME = "afp:resource-name";
-
-    /** the resource-level attribute */
-    public static final String RESOURCE_LEVEL = "afp:resource-level";
-
-    /** the resource-group-file attribute */
-    public static final String RESOURCE_GROUP_FILE = "afp:resource-group-file";
-
-    /**
-     * Main constructor
-     */
-    public AFPForeignAttributeReader() {
-    }
-
-    /**
-     * Returns the resource information
-     *
-     * @param foreignAttributes the foreign attributes
-     * @return the resource information
-     */
-    public AFPResourceInfo getResourceInfo(Map/*<QName, String>*/ foreignAttributes) {
-        AFPResourceInfo resourceInfo = new AFPResourceInfo();
-        if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
-            QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME);
-            String resourceName = (String)foreignAttributes.get(resourceNameKey);
-            if (resourceName != null) {
-                resourceInfo.setName(resourceName);
-            }
-            AFPResourceLevel level = getResourceLevel(foreignAttributes);
-            if (level != null) {
-                resourceInfo.setLevel(level);
-            }
-        }
-        return resourceInfo;
-    }
-
-    /**
-     * Returns the resource level
-     *
-     * @param foreignAttributes the foreign attributes
-     * @return the resource level
-     */
-    public AFPResourceLevel getResourceLevel(Map/*<QName, String>*/ foreignAttributes) {
-        AFPResourceLevel resourceLevel = null;
-        if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
-            QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL);
-            if (foreignAttributes.containsKey(resourceLevelKey)) {
-                String levelString = (String)foreignAttributes.get(resourceLevelKey);
-                resourceLevel = AFPResourceLevel.valueOf(levelString);
-                // if external get resource group file attributes
-                if (resourceLevel != null && resourceLevel.isExternal()) {
-                    QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE,
-                            RESOURCE_GROUP_FILE);
-                    String resourceGroupFile
-                        = (String)foreignAttributes.get(resourceGroupFileKey);
-                    if (resourceGroupFile == null) {
-                        String msg = RESOURCE_GROUP_FILE + " not specified";
-                        log.error(msg);
-                        throw new UnsupportedOperationException(msg);
-                    }
-                    File resourceExternalGroupFile = new File(resourceGroupFile);
-                    SecurityManager security = System.getSecurityManager();
-                    try {
-                        if (security != null) {
-                            security.checkWrite(resourceExternalGroupFile.getPath());
-                        }
-                    } catch (SecurityException ex) {
-                        String msg = "unable to gain write access to external resource file: "
-                        + resourceGroupFile;
-                        log.error(msg);
-                    }
-
-                    try {
-                        boolean exists = resourceExternalGroupFile.exists();
-                        if (exists) {
-                            log.warn("overwriting external resource file: "
-                                    + resourceGroupFile);
-                        }
-                        resourceLevel.setExternalFilePath(resourceGroupFile);
-                    } catch (SecurityException ex) {
-                        String msg = "unable to gain read access to external resource file: "
-                            + resourceGroupFile;
-                        log.error(msg);
-                    }
-                }
-            }
-        }
-        return resourceLevel;
-    }
-}
index dd9a0dc03e0319a553fcae04f7cca50234d837ce..df233dafaff19bae03888486615b7e8f426c70cf 100644 (file)
@@ -48,6 +48,7 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.fop.afp.goca.GraphicsSetLineType;
 import org.apache.fop.afp.modca.GraphicsObject;
 import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.svg.NativeImageHandler;
 import org.apache.xmlgraphics.image.loader.ImageInfo;
 import org.apache.xmlgraphics.image.loader.ImageSize;
 import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
@@ -65,7 +66,7 @@ import org.apache.xmlgraphics.util.MimeConstants;
  *
  * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D
  */
-public class AFPGraphics2D extends AbstractGraphics2D {
+public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHandler {
 
     private static final Log log = LogFactory.getLog(AFPGraphics2D.class);
 
@@ -109,10 +110,19 @@ public class AFPGraphics2D extends AbstractGraphics2D {
      * @param textAsShapes
      *            if true, all text is turned into shapes in the convertion. No
      *            text is output.
-     *
+     * @param paintingState painting state
+     * @param resourceManager resource manager
+     * @param resourceInfo resource info
+     * @param fontInfo font info
      */
-    public AFPGraphics2D(boolean textAsShapes) {
+    public AFPGraphics2D(boolean textAsShapes, AFPPaintingState paintingState,
+            AFPResourceManager resourceManager, AFPResourceInfo resourceInfo,
+            FontInfo fontInfo) {
         super(textAsShapes);
+        this.paintingState = paintingState;
+        this.resourceManager = resourceManager;
+        this.resourceInfo = resourceInfo;
+        this.fontInfo = fontInfo;
     }
 
     /**
@@ -123,12 +133,14 @@ public class AFPGraphics2D extends AbstractGraphics2D {
      */
     public AFPGraphics2D(AFPGraphics2D g2d) {
         super(g2d);
+        this.paintingState = g2d.paintingState;
+        this.resourceManager = g2d.resourceManager;
+        this.resourceInfo = g2d.resourceInfo;
+        this.fontInfo = g2d.fontInfo;
+
         this.graphicsObj = g2d.graphicsObj;
         this.fallbackTextHandler = g2d.fallbackTextHandler;
         this.customTextHandler = g2d.customTextHandler;
-        this.resourceManager = g2d.resourceManager;
-        this.resourceInfo = g2d.resourceInfo;
-        this.paintingState = g2d.paintingState;
     }
 
     /**
@@ -282,16 +294,13 @@ public class AFPGraphics2D extends AbstractGraphics2D {
                     mhr
             );
         } else {
-            // graphics segment opening coordinates (x,y)
-            // current position coordinates (x,y)
             for (int[] openingCoords = new int[2], currCoords = new int[2];
                 !iter.isDone(); iter.next()) {
-                // round the coordinate values and combine with current position
-                // coordinates
                 int type = iter.currentSegment(dstPts);
                 if (type == PathIterator.SEG_MOVETO) {
                     openingCoords[X] = currCoords[X] = (int)Math.round(dstPts[X]);
                     openingCoords[Y] = currCoords[Y] = (int)Math.round(dstPts[Y]);
+                    graphicsObj.setCurrentPosition(openingCoords);
                 } else {
                     int numCoords;
                     if (type == PathIterator.SEG_LINETO) {
@@ -303,32 +312,22 @@ public class AFPGraphics2D extends AbstractGraphics2D {
                     } else {
                         // close of the graphics segment
                         if (type == PathIterator.SEG_CLOSE) {
-                            coords = new int[] {
-                                    coords[coords.length - 2], //prev X
-                                    coords[coords.length - 1], //prev Y
-                                    openingCoords[X],
-                                    openingCoords[Y]
-                            };
-                            graphicsObj.addLine(coords);
+                            graphicsObj.addLine(openingCoords, true);
                         } else {
                             log.debug("Unrecognised path iterator type: "
                                     + type);
                         }
                         continue;
                     }
-                    // combine current position coordinates with new graphics
-                    // segment coordinates
-                    coords = new int[numCoords + 2];
-                    coords[X] = currCoords[X];
-                    coords[Y] = currCoords[Y];
+                    coords = new int[numCoords];
                     for (int i = 0; i < numCoords; i++) {
-                        coords[i + 2] = (int) Math.round(dstPts[i]);
+                        coords[i] = (int) Math.round(dstPts[i]);
                     }
                     if (type == PathIterator.SEG_LINETO) {
-                        graphicsObj.addLine(coords);
+                        graphicsObj.addLine(coords, true);
                     } else if (type == PathIterator.SEG_QUADTO
                             || type == PathIterator.SEG_CUBICTO) {
-                        graphicsObj.addFillet(coords);
+                        graphicsObj.addFillet(coords, true);
                     }
                     // update current position coordinates
                     currCoords[X] = coords[coords.length - 2];
@@ -408,7 +407,7 @@ public class AFPGraphics2D extends AbstractGraphics2D {
                                  BufferedImage.TYPE_INT_ARGB);
     }
 
-    private AFPImageObjectInfo getImageObjectInfo(
+    private AFPImageObjectInfo createImageObjectInfo(
             RenderedImage img, int x, int y, int width, int height) throws IOException {
         ImageInfo imageInfo = new ImageInfo(null, "image/unknown");
         ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72);
@@ -422,7 +421,8 @@ public class AFPGraphics2D extends AbstractGraphics2D {
 
         imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
 
-        imageObjectInfo.setBitsPerPixel(paintingState.getBitsPerPixel());
+        int bitsPerPixel = paintingState.getBitsPerPixel();
+        imageObjectInfo.setBitsPerPixel(bitsPerPixel);
 
         imageObjectInfo.setResourceInfo(resourceInfo);
 
@@ -442,7 +442,6 @@ public class AFPGraphics2D extends AbstractGraphics2D {
         // convert to grayscale
         if (!colorImages) {
             boas.reset();
-            int bitsPerPixel = paintingState.getBitsPerPixel();
             imageObjectInfo.setBitsPerPixel(bitsPerPixel);
             ImageEncodingHelper.encodeRGBAsGrayScale(
                   imageData, dataWidth, dataHeight, bitsPerPixel, boas);
@@ -456,21 +455,10 @@ public class AFPGraphics2D extends AbstractGraphics2D {
 
         // create object area info
         AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
-
-        AffineTransform at = gc.getTransform();
-        float[] srcPts = new float[] {x, y};
-        float[] dstPts = new float[srcPts.length];
-        at.transform(srcPts, 0, dstPts, 0, 1);
-        objectAreaInfo.setX(Math.round(dstPts[X]));
-        objectAreaInfo.setY(Math.round(dstPts[Y]));
-
-        AFPUnitConverter unitConv = paintingState.getUnitConverter();
-
-        int w = Math.round(unitConv.pt2units(width));
-        objectAreaInfo.setWidth(w);
-
-        int h = Math.round(unitConv.pt2units(height));
-        objectAreaInfo.setHeight(h);
+        objectAreaInfo.setX(x);
+        objectAreaInfo.setY(y);
+        objectAreaInfo.setWidth(width);
+        objectAreaInfo.setHeight(height);
 
         int resolution = paintingState.getResolution();
         objectAreaInfo.setWidthRes(resolution);
@@ -481,37 +469,62 @@ public class AFPGraphics2D extends AbstractGraphics2D {
         return imageObjectInfo;
     }
 
-    /** {@inheritDoc} */
-    public boolean drawImage(Image img, int x, int y, int width, int height,
-            ImageObserver observer) {
-
-        // draw with AWT Graphics2D
-        Dimension size = new Dimension(width, height);
-        BufferedImage bufferedImage = buildBufferedImage(size);
+    /**
+     * Draws an AWT image into a BufferedImage using an AWT Graphics2D implementation
+     *
+     * @param img the AWT image
+     * @param bufferedImage the AWT buffered image
+     * @param width the image width
+     * @param height the image height
+     * @param observer the image observer
+     * @return true if the image was drawn
+     */
+    private boolean drawBufferedImage(Image img, BufferedImage bufferedImage,
+            int width, int height, ImageObserver observer) {
 
         java.awt.Graphics2D g2d = bufferedImage.createGraphics();
-        g2d.setComposite(AlphaComposite.SrcOver);
+        try {
+            g2d.setComposite(AlphaComposite.SrcOver);
+
+            Color color = new Color(1, 1, 1, 0);
+            g2d.setBackground(color);
+            g2d.setPaint(color);
+
+            g2d.fillRect(0, 0, width, height);
 
-        Color color = new Color(1, 1, 1, 0);
-        g2d.setBackground(color);
-        g2d.setPaint(color);
+            int imageWidth = bufferedImage.getWidth();
+            int imageHeight = bufferedImage.getHeight();
+            Rectangle clipRect = new Rectangle(0, 0, imageWidth, imageHeight);
+            g2d.clip(clipRect);
 
-        g2d.fillRect(0, 0, width, height);
+            g2d.setComposite(gc.getComposite());
 
-        int imageWidth = bufferedImage.getWidth();
-        int imageHeight = bufferedImage.getHeight();
-        Rectangle clipRect = new Rectangle(0, 0, imageWidth, imageHeight);
-        g2d.clip(clipRect);
+            return g2d.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
+        } finally {
+            g2d.dispose(); //drawn so dispose immediately to free system resource
+        }
+    }
 
-        g2d.setComposite(gc.getComposite());
+    /** {@inheritDoc} */
+    public boolean drawImage(Image img, int x, int y, int width, int height,
+            ImageObserver observer) {
 
-        boolean drawn = g2d.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
-        g2d.dispose(); //drawn so dispose immediately to free system resource
+        // draw with AWT Graphics2D
+        Dimension imageSize = new Dimension(width, height);
+        BufferedImage bufferedImage = buildBufferedImage(imageSize);
 
+        boolean drawn = drawBufferedImage(img, bufferedImage, width, height, observer);
         if (drawn) {
+            AffineTransform at = gc.getTransform();
+            float[] srcPts = new float[] {x, y};
+            float[] dstPts = new float[srcPts.length];
+            at.transform(srcPts, 0, dstPts, 0, 1);
+            x = Math.round(dstPts[X]);
+            y = Math.round(dstPts[Y]);
             try {
                 // get image object info
-                AFPImageObjectInfo imageObjectInfo = getImageObjectInfo(bufferedImage, x, y, width, height);
+                AFPImageObjectInfo imageObjectInfo
+                    = createImageObjectInfo(bufferedImage, x, y, width, height);
 
                 // create image resource
                 resourceManager.createObject(imageObjectInfo);
@@ -523,25 +536,24 @@ public class AFPGraphics2D extends AbstractGraphics2D {
         return false;
     }
 
-    /** {@inheritDoc} */
-    public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
-        log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform);
-    }
-
     /** {@inheritDoc} */
     public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
-        log.debug("drawRenderedImage() NYI: img=" + img + ", xform=" + xform);
-    }
-
-    /** {@inheritDoc} */
-    public FontMetrics getFontMetrics(Font f) {
-        log.debug("getFontMetrics() NYI: f=" + f);
-        return null;
-    }
+        int width = img.getWidth();
+        int height = img.getHeight();
 
-    /** {@inheritDoc} */
-    public void setXORMode(Color col) {
-        log.debug("setXORMode() NYI: col=" + col);
+        AffineTransform at = paintingState.getData().getTransform();
+        AffineTransform gat = gc.getTransform();
+        int x = (int)Math.round(at.getTranslateX() + gat.getTranslateX());
+        int y = (int)Math.round(at.getTranslateY());
+        try {
+            // get image object info
+            AFPImageObjectInfo imageObjectInfo
+                = createImageObjectInfo(img, x, y, width, height);
+            // create image resource
+            resourceManager.createObject(imageObjectInfo);
+        } catch (IOException ioe) {
+            handleIOException(ioe);
+        }
     }
 
     /**
@@ -609,4 +621,27 @@ public class AFPGraphics2D extends AbstractGraphics2D {
     public FontInfo getFontInfo() {
         return this.fontInfo;
     }
+
+    /** {@inheritDoc} */
+    public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+        log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform);
+    }
+
+    /** {@inheritDoc} */
+    public FontMetrics getFontMetrics(Font f) {
+        log.debug("getFontMetrics() NYI: f=" + f);
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public void setXORMode(Color col) {
+        log.debug("setXORMode() NYI: col=" + col);
+    }
+
+    /** {@inheritDoc} */
+    public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image,
+            float x, float y, float width, float height) {
+        log.debug("NYI: addNativeImage() "+ "image=" + image
+                + ",x=" + x + ",y=" + y + ",width=" + width + ",height=" + height);
+    }
 }
index df0ef55c5b3f52facf9f522598c2100f80c021fd..cd8c7c303990e08b307861a86ab9b33de175b87f 100644 (file)
@@ -19,6 +19,7 @@
 
 package org.apache.fop.afp;
 
+import java.awt.Rectangle;
 import java.awt.geom.Rectangle2D;
 
 import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
@@ -62,7 +63,10 @@ public class AFPGraphicsObjectInfo extends AFPDataObjectInfo {
      * @return the graphics area
      */
     public Rectangle2D getArea() {
-        return this.area;
+        AFPObjectAreaInfo objectAreaInfo = getObjectAreaInfo();
+        int width = objectAreaInfo.getWidth();
+        int height = objectAreaInfo.getHeight();
+        return new Rectangle(width, height);
     }
 
     /**
diff --git a/src/java/org/apache/fop/afp/AFPPageFonts.java b/src/java/org/apache/fop/afp/AFPPageFonts.java
deleted file mode 100644 (file)
index 41fce73..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.afp;
-
-import org.apache.fop.afp.fonts.AFPFont;
-import org.apache.fop.afp.fonts.AFPFontAttributes;
-
-
-/**
- * Holds the current page fonts
- */
-public class AFPPageFonts extends java.util.HashMap {
-    private static final long serialVersionUID = -4991896259427109041L;
-
-    /**
-     * Default constructor
-     */
-    public AFPPageFonts() {
-        super();
-    }
-
-    /**
-     * Parameterized constructor
-     *
-     * @param fonts an existing set of afp page fonts
-     */
-    public AFPPageFonts(AFPPageFonts fonts) {
-        super(fonts);
-    }
-
-    /**
-     * Registers a font on the current page and returns font attributes
-     *
-     * @param fontName the internal font name
-     * @param font the AFPFont
-     * @param fontSize the font point size
-     * @return newly registered AFPFontAttributes
-     */
-    public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
-        String pageFontKey = fontName + "_" + fontSize;
-        AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
-        // Add to page font mapping if not already present
-        if (afpFontAttributes == null) {
-            afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
-            super.put(pageFontKey, afpFontAttributes);
-            afpFontAttributes.setFontReference(super.size());
-        }
-        return afpFontAttributes;
-    }
-}
\ No newline at end of file
index 60e4812b9c5fffbc4ca6f798e3f2e1b17de36f64..cb78fb36e386072b0ec5238fe7e1d77585ad7417 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.fop.afp;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.fonts.AFPPageFonts;
 import org.apache.fop.util.AbstractPaintingState;
 
 /**
@@ -42,7 +43,7 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
     private boolean colorImages = false;
 
     /** images are supported in this AFP environment */
-    private boolean nativeImages = false;
+    private boolean nativeImagesSupported = false;
 
     /** default value for image depth */
     private int bitsPerPixel = 8;
@@ -165,10 +166,10 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
     /**
      * Sets whether images are natively supported or not in the AFP environment
      *
-     * @param nativeImages true if images are natively supported in this AFP environment
+     * @param nativeImagesSupported true if images are natively supported in this AFP environment
      */
-    public void setNativeImages(boolean nativeImages) {
-        this.nativeImages = nativeImages;
+    public void setNativeImagesSupported(boolean nativeImagesSupported) {
+        this.nativeImagesSupported = nativeImagesSupported;
     }
 
     /**
@@ -176,8 +177,8 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
      *
      * @return true if images are supported natively in this AFP environment
      */
-    public boolean isNativeImages() {
-        return this.nativeImages;
+    public boolean isNativeImagesSupported() {
+        return this.nativeImagesSupported;
     }
 
     /**
index c912b8b173177628b19ed1a6c4ea71d1832c3266..21de782503a4cd7e00678795715e7b72b22890fd 100644 (file)
@@ -23,8 +23,6 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Map;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.apache.fop.afp.modca.AbstractDataObject;
 import org.apache.fop.afp.modca.AbstractNamedAFPObject;
 import org.apache.fop.afp.modca.DataStream;
@@ -36,9 +34,6 @@ import org.apache.fop.afp.modca.ResourceGroup;
  * Manages the creation and storage of document resources
  */
 public class AFPResourceManager {
-    /** Static logging instance */
-    private static final Log log = LogFactory.getLog(AFPResourceManager.class);
-
     /** The AFP datastream (document tree) */
     private DataStream dataStream;
 
index 1d9367ef654f2c1cf40bb39e64da8a350a87bddb..269e6ae085ab17a550ebd28d3e7b1d0352a699f0 100644 (file)
@@ -44,7 +44,7 @@ public class AFPStreamer implements Streamable {
 
     private static final String AFPDATASTREAM_TEMP_FILE_PREFIX = "AFPDataStream_";
 
-    private static final int BUFFER_SIZE = 4096;
+    private static final int BUFFER_SIZE = 4096; // 4k writing buffer
 
     private static final String DEFAULT_EXTERNAL_RESOURCE_FILENAME = "resources.afp";
 
@@ -159,8 +159,8 @@ public class AFPStreamer implements Streamable {
      *
      * @throws IOException if an an I/O exception of some sort has occurred
      */
-    public void close() throws IOException {
         // write out any external resource groups
+    public void close() throws IOException {
         Iterator it = pathResourceGroupMap.entrySet().iterator();
         while (it.hasNext()) {
             StreamedResourceGroup resourceGroup = (StreamedResourceGroup)it.next();
@@ -192,6 +192,7 @@ public class AFPStreamer implements Streamable {
 
     /** {@inheritDoc} */
     public void writeToStream(OutputStream os) throws IOException {
+//        long start = System.currentTimeMillis();
         int len = (int)documentFile.length();
         int numChunks = len / BUFFER_SIZE;
         int remainingChunkSize = len % BUFFER_SIZE;
@@ -212,5 +213,7 @@ public class AFPStreamer implements Streamable {
             os.write(buffer, 0, remainingChunkSize);
         }
         os.flush();
+//        long end = System.currentTimeMillis();
+//        log.debug("writing time " + (end - start) + "ms");
     }
 }
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/AFPTextElementBridge.java b/src/java/org/apache/fop/afp/AFPTextElementBridge.java
deleted file mode 100644 (file)
index 2bfccf4..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.afp;
-
-import org.apache.batik.bridge.SVGTextElementBridge;
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.TextPainter;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-/**
- * Bridge class for the &lt;text> element.
- * This bridge will use the direct text painter if the text
- * for the element is simple.
- */
-public class AFPTextElementBridge extends SVGTextElementBridge {
-    
-    private AFPTextPainter textPainter;
-
-    /**
-     * Constructs a new bridge for the &lt;text> element.
-     * @param textPainter the text painter to use
-     */
-    public AFPTextElementBridge(AFPTextPainter textPainter) {
-        this.textPainter = textPainter;
-    }
-
-    /**
-     * Create a text element bridge.
-     * This set the text painter on the node if the text is simple.
-     * @param ctx the bridge context
-     * @param e the svg element
-     * @return the text graphics node created by the super class
-     */
-    public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
-        GraphicsNode node = super.createGraphicsNode(ctx, e);
-        if (node != null && isSimple(ctx, e, node)) {
-            ((TextNode)node).setTextPainter(getTextPainter());
-        }
-        return node;
-    }
-
-    private TextPainter getTextPainter() {
-        return this.textPainter;
-    }
-
-    /**
-     * Check if text element contains simple text.
-     * This checks the children of the text element to determine
-     * if the text is simple. The text is simple if it can be rendered
-     * with basic text drawing algorithms. This means there are no
-     * alternate characters, the font is known and there are no effects
-     * applied to the text.
-     *
-     * @param ctx the bridge context
-     * @param element the svg text element
-     * @param node the graphics node
-     * @return true if this text is simple of false if it cannot be
-     *         easily rendered using normal drawString on the PDFGraphics2D
-     */
-    private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
-        for (Node n = element.getFirstChild();
-                n != null;
-                n = n.getNextSibling()) {
-
-            switch (n.getNodeType()) {
-            case Node.ELEMENT_NODE:
-
-                if (n.getLocalName().equals(SVG_TSPAN_TAG)
-                        || n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
-                    return false;
-                } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
-                    return false;
-                } else if (n.getLocalName().equals(SVG_TREF_TAG)) {
-                    return false;
-                }
-                break;
-            case Node.TEXT_NODE:
-            case Node.CDATA_SECTION_NODE:
-            default:
-            }
-        }
-
-        /*if (CSSUtilities.convertFilter(element, node, ctx) != null) {
-            return false;
-        }*/
-
-        return true;
-    }
-}
-
diff --git a/src/java/org/apache/fop/afp/AFPTextHandler.java b/src/java/org/apache/fop/afp/AFPTextHandler.java
deleted file mode 100644 (file)
index 77dc641..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.afp;
-
-import java.awt.Color;
-import java.awt.geom.AffineTransform;
-import java.io.IOException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.afp.fonts.AFPFont;
-import org.apache.fop.afp.fonts.AFPFontAttributes;
-import org.apache.fop.afp.modca.GraphicsObject;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.xmlgraphics.java2d.TextHandler;
-
-/**
- * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text
- * using AFP GOCA text operations.
- */
-public class AFPTextHandler implements TextHandler {
-
-    /** logging instance */
-    private static Log log = LogFactory.getLog(AFPTextHandler.class);
-
-    private static final int X = 0;
-    private static final int Y = 1;
-
-    private AFPGraphics2D g2d = null;
-
-    /** Overriding FontState */
-    protected Font overrideFont = null;
-
-    /**
-     * Main constructor.
-     *
-     * @param g2d the AFPGraphics2D instance
-     */
-    public AFPTextHandler(AFPGraphics2D g2d) {
-        this.g2d = g2d;
-    }
-
-    /**
-     * Return the font information associated with this object
-     *
-     * @return the FontInfo object
-     */
-    public FontInfo getFontInfo() {
-        return g2d.getFontInfo();
-    }
-
-    /**
-     * Registers a page font
-     *
-     * @param internalFontName the internal font name
-     * @param fontSize the font size
-     * @return a font reference
-     */
-    private int registerPageFont(String internalFontName, int fontSize) {
-        FontInfo fontInfo = getFontInfo();
-        AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName);
-        AFPPaintingState paintingState = g2d.getPaintingState();
-        AFPPageFonts pageFonts = paintingState.getPageFonts();
-        // register if necessary
-        AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
-                internalFontName,
-                afpFont,
-                fontSize
-        );
-        return afpFontAttributes.getFontReference();
-    }
-
-    /**
-     * Add a text string to the current data object of the AFP datastream.
-     * The text is painted using text operations.
-     *
-     * {@inheritDoc}
-     */
-    public void drawString(String str, float x, float y) throws IOException {
-        log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
-        GraphicsObject graphicsObj = g2d.getGraphicsObject();
-        Color color = g2d.getColor();
-
-        // set the color
-        AFPPaintingState paintingState = g2d.getPaintingState();
-        if (paintingState.setColor(color)) {
-            graphicsObj.setColor(color);
-        }
-
-        // set the character set
-        int fontReference = 0;
-        if (overrideFont != null) {
-            String internalFontName = overrideFont.getFontName();
-            int fontSize = overrideFont.getFontSize();
-            fontReference = registerPageFont(internalFontName, fontSize);
-        } else {
-            java.awt.Font awtFont = g2d.getFont();
-            AffineTransform fontTransform = awtFont.getTransform();
-            FontInfo fontInfo = getFontInfo();
-            Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
-            String internalFontName = fopFont.getFontName();
-            int fontSize = fopFont.getFontSize();
-            fontReference = registerPageFont(internalFontName, fontSize);
-        }
-        graphicsObj.setCharacterSet(fontReference);
-
-        // calculate x, y plotting coordinates from graphics context
-        AffineTransform at = g2d.getTransform();
-        float[] srcPts = new float[] { x, y };
-        float[] dstPts = new float[srcPts.length];
-        at.transform(srcPts, 0, dstPts, 0, 1);
-
-        // add the character string
-        graphicsObj.addString(str, Math.round(dstPts[X]), Math.round(dstPts[Y]));
-    }
-
-    /**
-     * Sets the overriding font.
-     *
-     * @param overrideFont Overriding Font to set
-     */
-    public void setOverrideFont(Font overrideFont) {
-        this.overrideFont = overrideFont;
-    }
-}
diff --git a/src/java/org/apache/fop/afp/AFPTextPainter.java b/src/java/org/apache/fop/afp/AFPTextPainter.java
deleted file mode 100644 (file)
index 7e3f340..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * 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.afp;
-
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Paint;
-import java.awt.Shape;
-import java.awt.font.TextAttribute;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-import java.text.AttributedCharacterIterator;
-import java.text.CharacterIterator;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.batik.dom.svg.SVGOMTextElement;
-import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.TextPainter;
-import org.apache.batik.gvt.font.GVTFontFamily;
-import org.apache.batik.gvt.renderer.StrokingTextPainter;
-import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
-import org.apache.batik.gvt.text.Mark;
-import org.apache.batik.gvt.text.TextPaintInfo;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.fonts.FontTriplet;
-
-
-/**
- * Renders the attributed character iterator of a <tt>TextNode</tt>.
- * This class draws the text directly into the AFPGraphics2D so that
- * the text is not drawn using shapes.
- * If the text is simple enough to draw then it sets the font and calls
- * drawString. If the text is complex or the cannot be translated
- * into a simple drawString the StrokingTextPainter is used instead.
- */
-public class AFPTextPainter implements TextPainter {
-
-    /** the logger for this class */
-    protected Log log = LogFactory.getLog(AFPTextPainter.class);
-
-    private final AFPTextHandler nativeTextHandler;
-
-    /**
-     * Use the stroking text painter to get the bounds and shape.
-     * Also used as a fallback to draw the string with strokes.
-     */
-    protected static final TextPainter
-        PROXY_PAINTER = StrokingTextPainter.getInstance();
-
-    /**
-     * Create a new PS text painter with the given font information.
-     * @param nativeTextHandler the NativeTextHandler instance used for text painting
-     */
-    public AFPTextPainter(AFPTextHandler nativeTextHandler) {
-        this.nativeTextHandler = nativeTextHandler;
-    }
-
-    /**
-     * Paints the specified attributed character iterator using the
-     * specified Graphics2D and context and font context.
-     * @param node the TextNode to paint
-     * @param g2d the Graphics2D to use
-     */
-    public void paint(TextNode node, Graphics2D g2d) {
-        Point2D loc = node.getLocation();
-        log.debug("painting text node " + node);
-        if (hasUnsupportedAttributes(node)) {
-            log.debug("hasunsuportedattributes");
-            PROXY_PAINTER.paint(node, g2d);
-        } else {
-            log.debug("allattributessupported");
-            paintTextRuns(node.getTextRuns(), g2d, loc);
-        }
-    }
-
-    private boolean hasUnsupportedAttributes(TextNode node) {
-        Iterator iter = node.getTextRuns().iterator();
-        while (iter.hasNext()) {
-            StrokingTextPainter.TextRun
-                    run = (StrokingTextPainter.TextRun)iter.next();
-            AttributedCharacterIterator aci = run.getACI();
-            boolean hasUnsupported = hasUnsupportedAttributes(aci);
-            if (hasUnsupported) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
-        boolean hasUnsupported = false;
-
-        String text = getText(aci);
-        Font font = makeFont(aci);
-        if (hasUnsupportedGlyphs(text, font)) {
-            log.trace("-> Unsupported glyphs found");
-            hasUnsupported = true;
-        }
-
-        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
-            GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
-        if ((tpi != null)
-                && ((tpi.strokeStroke != null && tpi.strokePaint != null)
-                    || (tpi.strikethroughStroke != null)
-                    || (tpi.underlineStroke != null)
-                    || (tpi.overlineStroke != null))) {
-                        log.trace("-> under/overlines etc. found");
-            hasUnsupported = true;
-        }
-
-        //Alpha is not supported
-        Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
-        if (foreground instanceof Color) {
-            Color col = (Color)foreground;
-            if (col.getAlpha() != 255) {
-                log.trace("-> transparency found");
-                hasUnsupported = true;
-            }
-        }
-
-        Object letSpace = aci.getAttribute(
-                            GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
-        if (letSpace != null) {
-            log.trace("-> letter spacing found");
-            hasUnsupported = true;
-        }
-
-        Object wordSpace = aci.getAttribute(
-                             GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
-        if (wordSpace != null) {
-            log.trace("-> word spacing found");
-            hasUnsupported = true;
-        }
-
-        Object lengthAdjust = aci.getAttribute(
-                            GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
-        if (lengthAdjust != null) {
-            log.trace("-> length adjustments found");
-            hasUnsupported = true;
-        }
-
-        Object writeMod = aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
-        if (writeMod != null
-            && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
-                  writeMod)) {
-            log.trace("-> Unsupported writing modes found");
-            hasUnsupported = true;
-        }
-
-        Object vertOr = aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
-        if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
-                  vertOr)) {
-            log.trace("-> vertical orientation found");
-            hasUnsupported = true;
-        }
-
-        Object rcDel = aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
-        //Batik 1.6 returns null here which makes it impossible to determine whether this can
-        //be painted or not, i.e. fall back to stroking. :-(
-        if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
-            log.trace("-> spans found");
-            hasUnsupported = true; //Filter spans
-        }
-
-        if (hasUnsupported) {
-            log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
-        }
-        return hasUnsupported;
-    }
-
-    /**
-     * Paint a list of text runs on the Graphics2D at a given location.
-     * @param textRuns the list of text runs
-     * @param g2d the Graphics2D to paint to
-     * @param loc the current location of the "cursor"
-     */
-    protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
-        Point2D currentloc = loc;
-        Iterator i = textRuns.iterator();
-        while (i.hasNext()) {
-            StrokingTextPainter.TextRun
-                    run = (StrokingTextPainter.TextRun)i.next();
-            currentloc = paintTextRun(run, g2d, currentloc);
-        }
-    }
-
-    /**
-     * Paint a single text run on the Graphics2D at a given location.
-     * @param run the text run to paint
-     * @param g2d the Graphics2D to paint to
-     * @param loc the current location of the "cursor"
-     * @return the new location of the "cursor" after painting the text run
-     */
-    protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
-        AttributedCharacterIterator aci = run.getACI();
-        aci.first();
-
-        updateLocationFromACI(aci, loc);
-        loc = g2d.getTransform().transform(loc, null);
-
-        // font
-        Font font = makeFont(aci);
-        nativeTextHandler.setOverrideFont(font);
-
-        // color
-        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
-        if (tpi == null) {
-            return loc;
-        }
-        Paint foreground = tpi.fillPaint;
-        if (foreground instanceof Color) {
-            Color col = (Color)foreground;
-            g2d.setColor(col);
-        }
-        g2d.setPaint(foreground);
-
-        String txt = getText(aci);
-        float advance = getStringWidth(txt, font);
-        float tx = 0;
-        TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
-        if (anchor != null) {
-            switch (anchor.getType()) {
-            case TextNode.Anchor.ANCHOR_MIDDLE:
-                tx = -advance / 2;
-                break;
-            case TextNode.Anchor.ANCHOR_END:
-                tx = -advance;
-                break;
-            default: //nop
-            }
-        }
-
-        // draw string
-        try {
-            try {
-                nativeTextHandler.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY()));
-            } catch (IOException ioe) {
-                if (g2d instanceof AFPGraphics2D) {
-                    ((AFPGraphics2D)g2d).handleIOException(ioe);
-                }
-            }
-        } finally {
-            nativeTextHandler.setOverrideFont(null);
-        }
-        loc.setLocation(loc.getX() + advance, loc.getY());
-        return loc;
-    }
-
-    /**
-     * Extract the raw text from an ACI.
-     * @param aci ACI to inspect
-     * @return the extracted text
-     */
-    protected String getText(AttributedCharacterIterator aci) {
-        StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
-        for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
-            sb.append(c);
-        }
-        return sb.toString();
-    }
-
-    private void updateLocationFromACI(
-                AttributedCharacterIterator aci,
-                Point2D loc) {
-        //Adjust position of span
-        Float xpos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.X);
-        Float ypos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.Y);
-        Float dxpos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.DX);
-        Float dypos = (Float)aci.getAttribute(
-                GVTAttributedCharacterIterator.TextAttribute.DY);
-        if (xpos != null) {
-            loc.setLocation(xpos.doubleValue(), loc.getY());
-        }
-        if (ypos != null) {
-            loc.setLocation(loc.getX(), ypos.doubleValue());
-        }
-        if (dxpos != null) {
-            loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
-        }
-        if (dypos != null) {
-            loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
-        }
-    }
-
-    private String getStyle(AttributedCharacterIterator aci) {
-        Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
-        return ((posture != null) && (posture.floatValue() > 0.0))
-                       ? Font.STYLE_ITALIC
-                       : Font.STYLE_NORMAL;
-    }
-
-    private int getWeight(AttributedCharacterIterator aci) {
-        Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
-        return ((taWeight != null) &&  (taWeight.floatValue() > 1.0))
-                       ? Font.WEIGHT_BOLD
-                       : Font.WEIGHT_NORMAL;
-    }
-
-    private Font makeFont(AttributedCharacterIterator aci) {
-        Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
-        if (fontSize == null) {
-            fontSize = new Float(10.0f);
-        }
-        String style = getStyle(aci);
-        int weight = getWeight(aci);
-
-        FontInfo fontInfo = nativeTextHandler.getFontInfo();
-        String fontFamily = null;
-        List gvtFonts = (List) aci.getAttribute(
-                      GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
-        if (gvtFonts != null) {
-            Iterator i = gvtFonts.iterator();
-            while (i.hasNext()) {
-                GVTFontFamily fam = (GVTFontFamily) i.next();
-                /* (todo) Enable SVG Font painting
-                if (fam instanceof SVGFontFamily) {
-                    PROXY_PAINTER.paint(node, g2d);
-                    return;
-                }*/
-                fontFamily = fam.getFamilyName();
-                if (fontInfo.hasFont(fontFamily, style, weight)) {
-                    FontTriplet triplet = fontInfo.fontLookup(
-                            fontFamily, style, weight);
-                    int fsize = (int)(fontSize.floatValue() * 1000);
-                    return fontInfo.getFontInstance(triplet, fsize);
-                }
-            }
-        }
-        FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
-        int fsize = (int)(fontSize.floatValue() * 1000);
-        return fontInfo.getFontInstance(triplet, fsize);
-    }
-
-    private float getStringWidth(String str, Font font) {
-        float wordWidth = 0;
-        float whitespaceWidth = font.getWidth(font.mapChar(' '));
-
-        for (int i = 0; i < str.length(); i++) {
-            float charWidth;
-            char c = str.charAt(i);
-            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
-                charWidth = font.getWidth(font.mapChar(c));
-                if (charWidth <= 0) {
-                    charWidth = whitespaceWidth;
-                }
-            } else {
-                charWidth = whitespaceWidth;
-            }
-            wordWidth += charWidth;
-        }
-        return wordWidth / 1000f;
-    }
-
-    private boolean hasUnsupportedGlyphs(String str, Font font) {
-        for (int i = 0; i < str.length(); i++) {
-            char c = str.charAt(i);
-            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
-                if (!font.hasChar(c)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Get the outline shape of the text characters.
-     * This uses the StrokingTextPainter to get the outline
-     * shape since in theory it should be the same.
-     *
-     * @param node the text node
-     * @return the outline shape of the text characters
-     */
-    public Shape getOutline(TextNode node) {
-        return PROXY_PAINTER.getOutline(node);
-    }
-
-    /**
-     * Get the bounds.
-     * This uses the StrokingTextPainter to get the bounds
-     * since in theory it should be the same.
-     *
-     * @param node the text node
-     * @return the bounds of the text
-     */
-    public Rectangle2D getBounds2D(TextNode node) {
-        /* (todo) getBounds2D() is too slow
-         * because it uses the StrokingTextPainter. We should implement this
-         * method ourselves. */
-        return PROXY_PAINTER.getBounds2D(node);
-    }
-
-    /**
-     * Get the geometry bounds.
-     * This uses the StrokingTextPainter to get the bounds
-     * since in theory it should be the same.
-     * @param node the text node
-     * @return the bounds of the text
-     */
-    public Rectangle2D getGeometryBounds(TextNode node) {
-        return PROXY_PAINTER.getGeometryBounds(node);
-    }
-
-    // Methods that have no purpose for PS
-
-    /**
-     * Get the mark.
-     * This does nothing since the output is AFP and not interactive.
-     * @param node the text node
-     * @param pos the position
-     * @param all select all
-     * @return null
-     */
-    public Mark getMark(TextNode node, int pos, boolean all) {
-        return null;
-    }
-
-    /**
-     * Select at.
-     * This does nothing since the output is AFP and not interactive.
-     * @param x the x position
-     * @param y the y position
-     * @param node the text node
-     * @return null
-     */
-    public Mark selectAt(double x, double y, TextNode node) {
-        return null;
-    }
-
-    /**
-     * Select to.
-     * This does nothing since the output is AFP and not interactive.
-     * @param x the x position
-     * @param y the y position
-     * @param beginMark the start mark
-     * @return null
-     */
-    public Mark selectTo(double x, double y, Mark beginMark) {
-        return null;
-    }
-
-    /**
-     * Selec first.
-     * This does nothing since the output is AFP and not interactive.
-     * @param node the text node
-     * @return null
-     */
-    public Mark selectFirst(TextNode node) {
-        return null;
-    }
-
-    /**
-     * Select last.
-     * This does nothing since the output is AFP and not interactive.
-     * @param node the text node
-     * @return null
-     */
-    public Mark selectLast(TextNode node) {
-        return null;
-    }
-
-    /**
-     * Get selected.
-     * This does nothing since the output is AFP and not interactive.
-     * @param start the start mark
-     * @param finish the finish mark
-     * @return null
-     */
-    public int[] getSelected(Mark start, Mark finish) {
-        return null;
-    }
-
-    /**
-     * Get the highlighted shape.
-     * This does nothing since the output is AFP and not interactive.
-     * @param beginMark the start mark
-     * @param endMark the end mark
-     * @return null
-     */
-    public Shape getHighlightShape(Mark beginMark, Mark endMark) {
-        return null;
-    }
-
-}
index 1a2883e72d53dd034d5d40a78a416bfc09137557..6a753855080ef745b3effa8f19b8a1cc736e6382 100644 (file)
@@ -51,7 +51,7 @@ public class Graphics2DImagePainterGOCA extends Graphics2DImagePainterImpl {
             /** {@inheritdoc} */
             public void prepare(Graphics2D g2d, Rectangle2D area) {
                 double tx = area.getX();
-                double ty = area.getHeight() - area.getY();
+                double ty = area.getHeight() + area.getY();
                 if (tx != 0 || ty != 0) {
                     g2d.translate(tx, ty);
                 }
index 1dd22c66a7f49faf070a7fd94b65d9e59fc306e9..de7f7f5be75d839602865fdc49b71e2f5b197304 100644 (file)
@@ -23,32 +23,24 @@ package org.apache.fop.afp.fonts;
  * This class encapsulates the font attributes that need to be included
  * in the AFP data stream. This class does not assist in converting the
  * font attributes to AFP code pages and character set values.
- *
  */
 public class AFPFontAttributes {
 
-    /**
-     * The font reference
-     */
+    /** the font reference */
     private int fontReference;
 
-    /**
-     * The font key
-     */
+    /** the font key */
     private final String fontKey;
 
-    /**
-     * The font
-     */
+    /** the font */
     private final AFPFont font;
 
-    /**
-     * The point size
-     */
+    /** the point size */
     private final int pointSize;
 
     /**
      * Constructor for the AFPFontAttributes
+     *
      * @param fontKey the font key
      * @param font the font
      * @param pointSize the point size
@@ -60,6 +52,8 @@ public class AFPFontAttributes {
     }
 
     /**
+     * Return the font
+     *
      * @return the font
      */
     public AFPFont getFont() {
@@ -67,6 +61,8 @@ public class AFPFontAttributes {
     }
 
     /**
+     * Return the FontKey attribute
+     *
      * @return the FontKey attribute
      */
     public String getFontKey() {
@@ -74,6 +70,8 @@ public class AFPFontAttributes {
     }
 
     /**
+     * Return the point size attribute
+     *
      * @return the point size attribute
      */
     public int getPointSize() {
@@ -81,6 +79,8 @@ public class AFPFontAttributes {
     }
 
     /**
+     * Return the FontReference attribute
+     *
      * @return the FontReference attribute
      */
     public int getFontReference() {
@@ -89,6 +89,7 @@ public class AFPFontAttributes {
 
     /**
      * Sets the FontReference attribute
+     *
      * @param fontReference the FontReference to set
      */
     public void setFontReference(int fontReference) {
diff --git a/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java
new file mode 100644 (file)
index 0000000..146c6f1
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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.afp.fonts;
+
+/**
+ * Holds the current page fonts
+ */
+public class AFPPageFonts extends java.util.HashMap {
+    private static final long serialVersionUID = -4991896259427109041L;
+
+    /**
+     * Default constructor
+     */
+    public AFPPageFonts() {
+        super();
+    }
+
+    /**
+     * Parameterized constructor
+     *
+     * @param fonts an existing set of afp page fonts
+     */
+    public AFPPageFonts(AFPPageFonts fonts) {
+        super(fonts);
+    }
+
+    /**
+     * Registers a font on the current page and returns font attributes
+     *
+     * @param fontName the internal font name
+     * @param font the AFPFont
+     * @param fontSize the font point size
+     * @return newly registered AFPFontAttributes
+     */
+    public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
+        String pageFontKey = fontName + "_" + fontSize;
+        AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
+        // Add to page font mapping if not already present
+        if (afpFontAttributes == null) {
+            afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
+            super.put(pageFontKey, afpFontAttributes);
+            afpFontAttributes.setFontReference(super.size());
+        }
+        return afpFontAttributes;
+    }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/fonts/package.html b/src/java/org/apache/fop/afp/fonts/package.html
new file mode 100644 (file)
index 0000000..74f8bf4
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.goca Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Graphics Object Content Architecture (GOCA) structured objects.</P>
+</BODY>
+</HTML>
\ No newline at end of file
index 6f993b84061fc6111d94289a1e818c94b67d10e8..3adcd946642478b0a6c926467353f6a018c0f469 100644 (file)
@@ -73,7 +73,6 @@ public abstract class AbstractGraphicsCoord extends AbstractPreparedAFPObject {
      * Returns the length of this order code (typically this is the same as the coordinate length)
      *
      * @return the length of this order code
-     *
      */
     protected int getLength() {
         return this.coords.length * 2;
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsFilletRelative.java b/src/java/org/apache/fop/afp/goca/GraphicsFilletRelative.java
new file mode 100644 (file)
index 0000000..b0e4084
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.afp.goca;
+
+/**
+ * A GOCA graphics curved tangential line to a specified set of
+ * straight lines drawn from the given position or current position
+ */
+public final class GraphicsFilletRelative extends AbstractGraphicsCoord {
+
+    /**
+     * Constructor
+     *
+     * @param coords the x/y coordinates for this object
+     */
+    public GraphicsFilletRelative(int[] coords) {
+        super(coords);
+    }
+
+    /** {@inheritDoc} */
+    protected byte getOrderCode() {
+        return (byte)0x85;
+    }
+
+}
\ No newline at end of file
index 319a9a122d879d6913c9f91b898a44a20e526c6f..99f54b2d15f413d252ffe94d552b1c7ab8a0779a 100644 (file)
 
 package org.apache.fop.afp.goca;
 
-
 /**
  * A GOCA graphics straight line drawn from the
- * given position or current position.
+ * given position
  */
 public class GraphicsLine extends AbstractGraphicsCoord {
 
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsLineRelative.java b/src/java/org/apache/fop/afp/goca/GraphicsLineRelative.java
new file mode 100644 (file)
index 0000000..1eddc51
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.afp.goca;
+
+/**
+ * A GOCA graphics straight line drawn from the
+ * relative from the current position.
+ */
+public class GraphicsLineRelative extends AbstractGraphicsCoord {
+
+    /**
+     * Constructor
+     *
+     * @param coords the x/y coordinates for this object
+     */
+    public GraphicsLineRelative(int[] coords) {
+        super(coords);
+    }
+
+    /** {@inheritDoc} */
+    protected byte getOrderCode() {
+        return (byte)0x81;
+    }
+
+}
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/goca/package.html b/src/java/org/apache/fop/afp/goca/package.html
new file mode 100644 (file)
index 0000000..539be8d
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.fonts Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP font related classes.</P>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/ioca/package.html b/src/java/org/apache/fop/afp/ioca/package.html
new file mode 100644 (file)
index 0000000..34e0bc1
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.ioca Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Image Object Content Architecture (IOCA) structured objects.</P>
+</BODY>
+</HTML>
\ No newline at end of file
index 8b76dde151cbd008858d24a2f1d962e9a858c9e7..3848ca4c3a57b96f0d2a92949e440e7b4a7dbf48 100644 (file)
@@ -30,8 +30,10 @@ import org.apache.fop.afp.Factory;
 import org.apache.fop.afp.goca.GraphicsBox;
 import org.apache.fop.afp.goca.GraphicsData;
 import org.apache.fop.afp.goca.GraphicsFillet;
+import org.apache.fop.afp.goca.GraphicsFilletRelative;
 import org.apache.fop.afp.goca.GraphicsFullArc;
 import org.apache.fop.afp.goca.GraphicsLine;
+import org.apache.fop.afp.goca.GraphicsLineRelative;
 import org.apache.fop.afp.goca.GraphicsSetArcParameters;
 import org.apache.fop.afp.goca.GraphicsSetCharacterSet;
 import org.apache.fop.afp.goca.GraphicsSetCurrentPosition;
@@ -181,7 +183,21 @@ public class GraphicsObject extends AbstractDataObject {
      * @param coords the x/y coordinates (can be a series)
      */
     public void addLine(int[] coords) {
-        addObject(new GraphicsLine(coords));
+        addLine(coords, false);
+    }
+
+    /**
+     * Adds a line at the given x/y coordinates
+     *
+     * @param coords the x/y coordinates (can be a series)
+     * @param relative relative true for a line at current position (relative to)
+     */
+    public void addLine(int[] coords, boolean relative) {
+        if (relative) {
+            addObject(new GraphicsLineRelative(coords));
+        } else {
+            addObject(new GraphicsLine(coords));
+        }
     }
 
     /**
@@ -199,7 +215,21 @@ public class GraphicsObject extends AbstractDataObject {
      * @param coords the x/y coordinates
      */
     public void addFillet(int[] coords) {
-        addObject(new GraphicsFillet(coords));
+        addFillet(coords, false);
+    }
+
+    /**
+     * Adds a fillet (curve) at the given coordinates
+     *
+     * @param coords the x/y coordinates
+     * @param relative relative true for a fillet at current position (relative to)
+     */
+    public void addFillet(int[] coords, boolean relative) {
+        if (relative) {
+            addObject(new GraphicsFilletRelative(coords));
+        } else {
+            addObject(new GraphicsFillet(coords));
+        }
     }
 
     /**
@@ -300,4 +330,5 @@ public class GraphicsObject extends AbstractDataObject {
         copySF(data, Type.END, Category.GRAPHICS);
         os.write(data);
     }
+
 }
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/package.html b/src/java/org/apache/fop/afp/modca/package.html
new file mode 100644 (file)
index 0000000..5727435
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.modca Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) structured objects.</P>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/triplets/package.html b/src/java/org/apache/fop/afp/modca/triplets/package.html
new file mode 100644 (file)
index 0000000..99ae55a
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp.modca.triplets Package</TITLE>
+<BODY>
+<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) triplet classes.</P>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/package.html b/src/java/org/apache/fop/afp/package.html
new file mode 100644 (file)
index 0000000..d674981
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.afp Package</TITLE>
+<BODY>
+<P>Contains an AFP library.</P>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java
new file mode 100644 (file)
index 0000000..5434b5b
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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.afp.svg;
+
+import java.awt.geom.AffineTransform;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.DocumentLoader;
+import org.apache.batik.bridge.UserAgent;
+import org.apache.batik.gvt.TextPainter;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.svg.AbstractFOPBridgeContext;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+
+public class AFPBridgeContext extends AbstractFOPBridgeContext {
+
+    private final AFPGraphics2D g2d;
+
+    /**
+     * Constructs a new bridge context.
+     *
+     * @param userAgent the user agent
+     * @param fontInfo the font list for the text painter, may be null
+     *                 in which case text is painted as shapes
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
+     * @param g2d an AFPGraphics 2D implementation
+     */
+    public AFPBridgeContext(UserAgent userAgent, FontInfo fontInfo,
+            ImageManager imageManager, ImageSessionContext imageSessionContext,
+            AffineTransform linkTransform, AFPGraphics2D g2d) {
+        super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform);
+        this.g2d = g2d;
+    }
+
+    /**
+     * Constructs a new bridge context.
+     * @param userAgent the user agent
+     * @param loader the Document Loader to use for referenced documents.
+     * @param fontInfo the font list for the text painter, may be null
+     *                 in which case text is painted as shapes
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
+     * @param an AFPGraphics 2D implementation
+     */
+    public AFPBridgeContext(UserAgent userAgent, DocumentLoader documentLoader,
+            FontInfo fontInfo, ImageManager imageManager,
+            ImageSessionContext imageSessionContext,
+            AffineTransform linkTransform, AFPGraphics2D g2d) {
+        super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform);
+        this.g2d = g2d;
+    }
+
+    /** {@inheritDoc} */
+    public void registerSVGBridges() {
+        super.registerSVGBridges();
+
+        if (fontInfo != null) {
+            AFPTextHandler textHandler = new AFPTextHandler(g2d);
+            g2d.setCustomTextHandler(textHandler);
+
+            TextPainter textPainter = new AFPTextPainter(textHandler);
+            setTextPainter(textPainter);
+
+            putBridge(new AFPTextElementBridge(textPainter));
+        }
+
+        putBridge(new AFPImageElementBridge());
+    }
+
+    /** {@inheritDoc} */
+    public BridgeContext createBridgeContext() {
+        return new AFPBridgeContext(getUserAgent(), getDocumentLoader(),
+                fontInfo,
+                getImageManager(),
+                getImageSessionContext(),
+                linkTransform, g2d);
+    }
+
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java b/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java
new file mode 100644 (file)
index 0000000..de677e7
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.afp.svg;
+
+import org.apache.fop.svg.AbstractFOPImageElementBridge;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+
+public class AFPImageElementBridge extends AbstractFOPImageElementBridge {
+
+    private final ImageFlavor[] supportedFlavors = new ImageFlavor[]
+                                                                   {ImageFlavor.RAW_JPEG,
+                                                                    ImageFlavor.RAW_CCITTFAX,
+                                                                    ImageFlavor.GRAPHICS2D,
+                                                                    ImageFlavor.XML_DOM};
+
+    /** {@inheritDoc} */
+    protected ImageFlavor[] getSupportedFlavours() {
+        return supportedFlavors;
+    }
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java
new file mode 100644 (file)
index 0000000..31aa3fe
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.afp.svg;
+
+import org.apache.batik.gvt.TextPainter;
+import org.apache.fop.svg.AbstractFOPTextElementBridge;
+
+/**
+ * Bridge class for the &lt;text> element.
+ * This bridge will use the direct text painter if the text
+ * for the element is simple.
+ */
+public class AFPTextElementBridge extends AbstractFOPTextElementBridge {
+
+    /**
+     * Constructs a new bridge for the &lt;text> element.
+     *
+     * @param textPainter the text painter to use
+     */
+    public AFPTextElementBridge(TextPainter textPainter) {
+        super(textPainter);
+    }
+
+}
+
diff --git a/src/java/org/apache/fop/afp/svg/AFPTextHandler.java b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java
new file mode 100644 (file)
index 0000000..d78e5c1
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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.afp.svg;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.fonts.AFPFont;
+import org.apache.fop.afp.fonts.AFPFontAttributes;
+import org.apache.fop.afp.fonts.AFPPageFonts;
+import org.apache.fop.afp.modca.GraphicsObject;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.xmlgraphics.java2d.TextHandler;
+
+/**
+ * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text
+ * using AFP GOCA text operations.
+ */
+public class AFPTextHandler implements TextHandler {
+
+    /** logging instance */
+    private static Log log = LogFactory.getLog(AFPTextHandler.class);
+
+    private AFPGraphics2D g2d = null;
+
+    /** Overriding FontState */
+    protected Font overrideFont = null;
+
+    /**
+     * Main constructor.
+     *
+     * @param g2d the AFPGraphics2D instance
+     */
+    public AFPTextHandler(AFPGraphics2D g2d) {
+        this.g2d = g2d;
+    }
+
+    /**
+     * Return the font information associated with this object
+     *
+     * @return the FontInfo object
+     */
+    public FontInfo getFontInfo() {
+        return g2d.getFontInfo();
+    }
+
+    /**
+     * Registers a page font
+     *
+     * @param internalFontName the internal font name
+     * @param fontSize the font size
+     * @return a font reference
+     */
+    private int registerPageFont(String internalFontName, int fontSize) {
+        FontInfo fontInfo = getFontInfo();
+        AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName);
+        AFPPaintingState paintingState = g2d.getPaintingState();
+        AFPPageFonts pageFonts = paintingState.getPageFonts();
+        // register if necessary
+        AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
+                internalFontName,
+                afpFont,
+                fontSize
+        );
+        return afpFontAttributes.getFontReference();
+    }
+
+    /**
+     * Add a text string to the current data object of the AFP datastream.
+     * The text is painted using text operations.
+     *
+     * {@inheritDoc}
+     */
+    public void drawString(String str, float x, float y) throws IOException {
+        log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
+        GraphicsObject graphicsObj = g2d.getGraphicsObject();
+        Color color = g2d.getColor();
+
+        // set the color
+        AFPPaintingState paintingState = g2d.getPaintingState();
+        if (paintingState.setColor(color)) {
+            graphicsObj.setColor(color);
+        }
+
+        // set the character set
+        int fontReference = 0;
+        if (overrideFont != null) {
+            String internalFontName = overrideFont.getFontName();
+            int fontSize = overrideFont.getFontSize();
+            fontReference = registerPageFont(internalFontName, fontSize);
+        } else {
+            java.awt.Font awtFont = g2d.getFont();
+//            AffineTransform fontTransform = awtFont.getTransform();
+            FontInfo fontInfo = getFontInfo();
+            Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
+            String internalFontName = fopFont.getFontName();
+            int fontSize = fopFont.getFontSize();
+            fontReference = registerPageFont(internalFontName, fontSize);
+        }
+        graphicsObj.setCharacterSet(fontReference);
+
+        // add the character string
+        graphicsObj.addString(str, Math.round(x), Math.round(y));
+    }
+
+    /**
+     * Sets the overriding font.
+     *
+     * @param overrideFont Overriding Font to set
+     */
+    public void setOverrideFont(Font overrideFont) {
+        this.overrideFont = overrideFont;
+    }
+}
diff --git a/src/java/org/apache/fop/afp/svg/AFPTextPainter.java b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java
new file mode 100644 (file)
index 0000000..2d68616
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * 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.afp.svg;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.font.TextAttribute;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.TextPainter;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.Mark;
+import org.apache.batik.gvt.text.TextPaintInfo;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+
+
+/**
+ * Renders the attributed character iterator of a <tt>TextNode</tt>.
+ * This class draws the text directly into the AFPGraphics2D so that
+ * the text is not drawn using shapes.
+ * If the text is simple enough to draw then it sets the font and calls
+ * drawString. If the text is complex or the cannot be translated
+ * into a simple drawString the StrokingTextPainter is used instead.
+ */
+public class AFPTextPainter implements TextPainter {
+
+    /** the logger for this class */
+    protected Log log = LogFactory.getLog(AFPTextPainter.class);
+
+    private final AFPTextHandler nativeTextHandler;
+
+    /**
+     * Use the stroking text painter to get the bounds and shape.
+     * Also used as a fallback to draw the string with strokes.
+     */
+    protected static final TextPainter
+        PROXY_PAINTER = StrokingTextPainter.getInstance();
+
+    /**
+     * Create a new PS text painter with the given font information.
+     * @param nativeTextHandler the NativeTextHandler instance used for text painting
+     */
+    public AFPTextPainter(AFPTextHandler nativeTextHandler) {
+        this.nativeTextHandler = nativeTextHandler;
+    }
+
+    /**
+     * Paints the specified attributed character iterator using the
+     * specified Graphics2D and context and font context.
+     *
+     * @param node the TextNode to paint
+     * @param g2d the Graphics2D to use
+     */
+    public void paint(TextNode node, Graphics2D g2d) {
+        Point2D loc = node.getLocation();
+        log.debug("painting text node " + node);
+        if (hasUnsupportedAttributes(node)) {
+            log.debug("hasUnsuportedAttributes");
+            PROXY_PAINTER.paint(node, g2d);
+        } else {
+            log.debug("allAttributesSupported");
+            paintTextRuns(node.getTextRuns(), g2d, loc);
+        }
+    }
+
+    private boolean hasUnsupportedAttributes(TextNode node) {
+        Iterator iter = node.getTextRuns().iterator();
+        while (iter.hasNext()) {
+            StrokingTextPainter.TextRun
+                    run = (StrokingTextPainter.TextRun)iter.next();
+            AttributedCharacterIterator aci = run.getACI();
+            boolean hasUnsupported = hasUnsupportedAttributes(aci);
+            if (hasUnsupported) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
+        boolean hasUnsupported = false;
+
+        String text = getText(aci);
+        Font font = makeFont(aci);
+        if (hasUnsupportedGlyphs(text, font)) {
+            log.trace("-> Unsupported glyphs found");
+            hasUnsupported = true;
+        }
+
+        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+            GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+        if ((tpi != null)
+                && ((tpi.strokeStroke != null && tpi.strokePaint != null)
+                    || (tpi.strikethroughStroke != null)
+                    || (tpi.underlineStroke != null)
+                    || (tpi.overlineStroke != null))) {
+                        log.trace("-> under/overlines etc. found");
+            hasUnsupported = true;
+        }
+
+        //Alpha is not supported
+        Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
+        if (foreground instanceof Color) {
+            Color col = (Color)foreground;
+            if (col.getAlpha() != 255) {
+                log.trace("-> transparency found");
+                hasUnsupported = true;
+            }
+        }
+
+        Object letSpace = aci.getAttribute(
+                            GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
+        if (letSpace != null) {
+            log.trace("-> letter spacing found");
+            hasUnsupported = true;
+        }
+
+        Object wordSpace = aci.getAttribute(
+                             GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
+        if (wordSpace != null) {
+            log.trace("-> word spacing found");
+            hasUnsupported = true;
+        }
+
+        Object lengthAdjust = aci.getAttribute(
+                            GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
+        if (lengthAdjust != null) {
+            log.trace("-> length adjustments found");
+            hasUnsupported = true;
+        }
+
+        Object writeMod = aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
+        if (writeMod != null
+            && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
+                  writeMod)) {
+            log.trace("-> Unsupported writing modes found");
+            hasUnsupported = true;
+        }
+
+        Object vertOr = aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
+        if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
+                  vertOr)) {
+            log.trace("-> vertical orientation found");
+            hasUnsupported = true;
+        }
+
+        Object rcDel = aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
+        //Batik 1.6 returns null here which makes it impossible to determine whether this can
+        //be painted or not, i.e. fall back to stroking. :-(
+        if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
+            log.trace("-> spans found");
+            hasUnsupported = true; //Filter spans
+        }
+
+        if (hasUnsupported) {
+            log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
+        }
+        return hasUnsupported;
+    }
+
+    /**
+     * Paint a list of text runs on the Graphics2D at a given location.
+     * @param textRuns the list of text runs
+     * @param g2d the Graphics2D to paint to
+     * @param loc the current location of the "cursor"
+     */
+    protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
+        Point2D currentloc = loc;
+        Iterator i = textRuns.iterator();
+        while (i.hasNext()) {
+            StrokingTextPainter.TextRun
+                    run = (StrokingTextPainter.TextRun)i.next();
+            currentloc = paintTextRun(run, g2d, currentloc);
+        }
+    }
+
+    /**
+     * Paint a single text run on the Graphics2D at a given location.
+     * @param run the text run to paint
+     * @param g2d the Graphics2D to paint to
+     * @param loc the current location of the "cursor"
+     * @return the new location of the "cursor" after painting the text run
+     */
+    protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
+        AttributedCharacterIterator aci = run.getACI();
+        aci.first();
+
+        updateLocationFromACI(aci, loc);
+        AffineTransform at = g2d.getTransform();
+        loc = at.transform(loc, null);
+
+        // font
+        Font font = makeFont(aci);
+        nativeTextHandler.setOverrideFont(font);
+
+        // color
+        TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+        if (tpi == null) {
+            return loc;
+        }
+        Paint foreground = tpi.fillPaint;
+        if (foreground instanceof Color) {
+            Color col = (Color)foreground;
+            g2d.setColor(col);
+        }
+        g2d.setPaint(foreground);
+
+        // text
+        String txt = getText(aci);
+        float advance = getStringWidth(txt, font);
+        float tx = 0;
+        TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+        if (anchor != null) {
+            switch (anchor.getType()) {
+            case TextNode.Anchor.ANCHOR_MIDDLE:
+                tx = -advance / 2;
+                break;
+            case TextNode.Anchor.ANCHOR_END:
+                tx = -advance;
+                break;
+            default: //nop
+            }
+        }
+
+        // draw string
+        double x = loc.getX();
+        double y = loc.getY();
+        try {
+            try {
+                nativeTextHandler.drawString(txt, (float)x + tx, (float)y);
+            } catch (IOException ioe) {
+                if (g2d instanceof AFPGraphics2D) {
+                    ((AFPGraphics2D)g2d).handleIOException(ioe);
+                }
+            }
+        } finally {
+            nativeTextHandler.setOverrideFont(null);
+        }
+        loc.setLocation(loc.getX() + advance, loc.getY());
+        return loc;
+    }
+
+    /**
+     * Extract the raw text from an ACI.
+     * @param aci ACI to inspect
+     * @return the extracted text
+     */
+    protected String getText(AttributedCharacterIterator aci) {
+        StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
+        for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    private void updateLocationFromACI(
+                AttributedCharacterIterator aci,
+                Point2D loc) {
+        //Adjust position of span
+        Float xpos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.X);
+        Float ypos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.Y);
+        Float dxpos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.DX);
+        Float dypos = (Float)aci.getAttribute(
+                GVTAttributedCharacterIterator.TextAttribute.DY);
+        if (xpos != null) {
+            loc.setLocation(xpos.doubleValue(), loc.getY());
+        }
+        if (ypos != null) {
+            loc.setLocation(loc.getX(), ypos.doubleValue());
+        }
+        if (dxpos != null) {
+            loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
+        }
+        if (dypos != null) {
+            loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
+        }
+    }
+
+    private String getStyle(AttributedCharacterIterator aci) {
+        Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
+        return ((posture != null) && (posture.floatValue() > 0.0))
+                       ? Font.STYLE_ITALIC
+                       : Font.STYLE_NORMAL;
+    }
+
+    private int getWeight(AttributedCharacterIterator aci) {
+        Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
+        return ((taWeight != null) &&  (taWeight.floatValue() > 1.0))
+                       ? Font.WEIGHT_BOLD
+                       : Font.WEIGHT_NORMAL;
+    }
+
+    private Font makeFont(AttributedCharacterIterator aci) {
+        Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
+        if (fontSize == null) {
+            fontSize = new Float(10.0f);
+        }
+        String style = getStyle(aci);
+        int weight = getWeight(aci);
+
+        FontInfo fontInfo = nativeTextHandler.getFontInfo();
+        String fontFamily = null;
+        List gvtFonts = (List) aci.getAttribute(
+                      GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+        if (gvtFonts != null) {
+            Iterator i = gvtFonts.iterator();
+            while (i.hasNext()) {
+                GVTFontFamily fam = (GVTFontFamily) i.next();
+                /* (todo) Enable SVG Font painting
+                if (fam instanceof SVGFontFamily) {
+                    PROXY_PAINTER.paint(node, g2d);
+                    return;
+                }*/
+                fontFamily = fam.getFamilyName();
+                if (fontInfo.hasFont(fontFamily, style, weight)) {
+                    FontTriplet triplet = fontInfo.fontLookup(
+                            fontFamily, style, weight);
+                    int fsize = (int)(fontSize.floatValue() * 1000);
+                    return fontInfo.getFontInstance(triplet, fsize);
+                }
+            }
+        }
+        FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
+        int fsize = (int)(fontSize.floatValue() * 1000);
+        return fontInfo.getFontInstance(triplet, fsize);
+    }
+
+    private float getStringWidth(String str, Font font) {
+        float wordWidth = 0;
+        float whitespaceWidth = font.getWidth(font.mapChar(' '));
+
+        for (int i = 0; i < str.length(); i++) {
+            float charWidth;
+            char c = str.charAt(i);
+            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+                charWidth = font.getWidth(font.mapChar(c));
+                if (charWidth <= 0) {
+                    charWidth = whitespaceWidth;
+                }
+            } else {
+                charWidth = whitespaceWidth;
+            }
+            wordWidth += charWidth;
+        }
+        return wordWidth / 1000f;
+    }
+
+    private boolean hasUnsupportedGlyphs(String str, Font font) {
+        for (int i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+                if (!font.hasChar(c)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Get the outline shape of the text characters.
+     * This uses the StrokingTextPainter to get the outline
+     * shape since in theory it should be the same.
+     *
+     * @param node the text node
+     * @return the outline shape of the text characters
+     */
+    public Shape getOutline(TextNode node) {
+        return PROXY_PAINTER.getOutline(node);
+    }
+
+    /**
+     * Get the bounds.
+     * This uses the StrokingTextPainter to get the bounds
+     * since in theory it should be the same.
+     *
+     * @param node the text node
+     * @return the bounds of the text
+     */
+    public Rectangle2D getBounds2D(TextNode node) {
+        /* (todo) getBounds2D() is too slow
+         * because it uses the StrokingTextPainter. We should implement this
+         * method ourselves. */
+        return PROXY_PAINTER.getBounds2D(node);
+    }
+
+    /**
+     * Get the geometry bounds.
+     * This uses the StrokingTextPainter to get the bounds
+     * since in theory it should be the same.
+     *
+     * @param node the text node
+     * @return the bounds of the text
+     */
+    public Rectangle2D getGeometryBounds(TextNode node) {
+        return PROXY_PAINTER.getGeometryBounds(node);
+    }
+
+    // Methods that have no purpose for PS
+
+    /**
+     * Get the mark.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param node the text node
+     * @param pos the position
+     * @param all select all
+     * @return null
+     */
+    public Mark getMark(TextNode node, int pos, boolean all) {
+        return null;
+    }
+
+    /**
+     * Select at.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param x the x position
+     * @param y the y position
+     * @param node the text node
+     * @return null
+     */
+    public Mark selectAt(double x, double y, TextNode node) {
+        return null;
+    }
+
+    /**
+     * Select to.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param x the x position
+     * @param y the y position
+     * @param beginMark the start mark
+     * @return null
+     */
+    public Mark selectTo(double x, double y, Mark beginMark) {
+        return null;
+    }
+
+    /**
+     * Selec first.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param node the text node
+     * @return null
+     */
+    public Mark selectFirst(TextNode node) {
+        return null;
+    }
+
+    /**
+     * Select last.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param node the text node
+     * @return null
+     */
+    public Mark selectLast(TextNode node) {
+        return null;
+    }
+
+    /**
+     * Get selected.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param start the start mark
+     * @param finish the finish mark
+     * @return null
+     */
+    public int[] getSelected(Mark start, Mark finish) {
+        return null;
+    }
+
+    /**
+     * Get the highlighted shape.
+     * This does nothing since the output is AFP and not interactive.
+     *
+     * @param beginMark the start mark
+     * @param endMark the end mark
+     * @return null
+     */
+    public Shape getHighlightShape(Mark beginMark, Mark endMark) {
+        return null;
+    }
+
+}
index 1a04d129a3626c6e798a3d4926dd7a19f46ab458..8f8032767a1cdaf71d0daef1e69d1dca2bd3886f 100644 (file)
@@ -389,8 +389,8 @@ public class FontInfo {
             }
             matchedTriplet = fontLookup(awtFontFamily, awtFontStyle, awtFontWeight);
         }
-        float awtFontSize = awtFont.getSize2D();
-        return getFontInstance(matchedTriplet, (int)(awtFontSize * 1000 + 0.5));
+        int fontSize = Math.round(awtFont.getSize2D() * 1000);
+        return getFontInstance(matchedTriplet, fontSize);
     }
 
     /**
index 33e1e2cb386b6f4651c9e159be1793181a6e2d19..fee0bf82756632579fb05b600f6055ad9a8459fe 100644 (file)
@@ -1,3 +1,20 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
 <HTML>
 <TITLE>org.apache.fop.fonts Package</TITLE>
 <BODY>
index e86318adc941ea0543844b4adf250bcc784cfa66..383f78da12d44967743e6bdc37a5b39a2346f108 100644 (file)
@@ -1,3 +1,20 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
 <HTML>
 <TITLE>org.apache.fop.pdf Package</TITLE>
 <BODY>
index 18cc81400aa145201ce44adefb812e130450ab29..5c253fe9466ccbd6d35bfaa87dfc8ce4034cb618 100644 (file)
@@ -29,10 +29,12 @@ import org.apache.batik.bridge.GVTBuilder;
 import org.apache.batik.dom.AbstractDocument;
 import org.apache.batik.dom.svg.SVGDOMImplementation;
 import org.apache.batik.gvt.GraphicsNode;
+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;
@@ -71,7 +73,7 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
      * @param imageSize the image size
      * @return a new graphics 2D image painter implementation
      */
-    protected Graphics2DImagePainter createPainter(
+    protected Graphics2DImagePainter createGraphics2DImagePainter(
             GraphicsNode root, BridgeContext ctx, Dimension imageSize) {
         return new Graphics2DImagePainterImpl(root, ctx, imageSize);
     }
@@ -85,14 +87,14 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
      * @return a built GVT root tree
      */
     protected GraphicsNode buildGraphicsNode(
-            RendererContext rendererContext, BridgeContext ctx, Document doc) {
+            FOUserAgent userAgent, BridgeContext ctx, Document doc) {
         GVTBuilder builder = new GVTBuilder();
         final GraphicsNode root;
         try {
             root = builder.build(ctx, doc);
         } catch (Exception e) {
             EventBroadcaster eventBroadcaster
-                = rendererContext.getUserAgent().getEventBroadcaster();
+                = userAgent.getEventBroadcaster();
             SVGEventProducer eventProducer = SVGEventProducer.Provider.get(eventBroadcaster);
             final String uri = getDocumentURI(doc);
             eventProducer.svgNotBuilt(this, e, uri);
@@ -101,6 +103,18 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
         return root;
     }
 
+    /**
+     * Returns the image size
+     * @param wrappedContext renderer context wrapper
+     *
+     * @return the image size
+     */
+    protected Dimension getImageSize(RendererContextWrapper wrappedContext) {
+        final int width = wrappedContext.getWidth();
+        final int height = wrappedContext.getHeight();
+        return new Dimension(width, height);
+    }
+
     /**
      * Render the SVG document.
      *
@@ -113,23 +127,21 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
         updateRendererContext(rendererContext);
 
         //Prepare
-        SVGUserAgent svgUserAgent = new SVGUserAgent(
-                rendererContext.getUserAgent(), new AffineTransform());
+        FOUserAgent userAgent = rendererContext.getUserAgent();
+        SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new AffineTransform());
+
+        //Create Batik BridgeContext
         final BridgeContext bridgeContext = new BridgeContext(svgUserAgent);
 
         //Build the GVT tree
-        final GraphicsNode root = buildGraphicsNode(rendererContext, bridgeContext, doc);
 
+        final GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc);
+
+        // Create Graphics2DImagePainter
         final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext(
                 rendererContext);
-
-        //Get Image Size
-        final int width = wrappedContext.getWidth();
-        final int height = wrappedContext.getHeight();
-        Dimension imageSize = new Dimension(width, height);
-
-        //Create the painter
-        final Graphics2DImagePainter painter = createPainter(root, bridgeContext, imageSize);
+        Dimension imageSize = getImageSize(wrappedContext);
+        final Graphics2DImagePainter painter = createGraphics2DImagePainter(root, bridgeContext, imageSize);
 
         //Let the painter paint the SVG on the Graphics2D instance
         Graphics2DAdapter g2dAdapter = rendererContext.getRenderer().getGraphics2DAdapter();
@@ -137,6 +149,8 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
         //Paint the image
         final int x = wrappedContext.getCurrentXPosition();
         final int y = wrappedContext.getCurrentYPosition();
+        final int width = wrappedContext.getWidth();
+        final int height = wrappedContext.getHeight();
         g2dAdapter.paintImage(painter, rendererContext, x, y, width, height);
     }
 
index 5861fb04266e30c56a8106b428fa76dbcd8fbcb4..ee18dff0d3333c48e72c15a5bc3cb35b85a0abb3 100644 (file)
@@ -54,8 +54,8 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter {
     protected BufferedImage paintToBufferedImage(
             org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter,
              RendererContextWrapper context, int resolution, boolean gray, boolean withAlpha) {
-        int bmw = (int)Math.ceil(UnitConv.mpt2px(context.getWidth(), resolution));
-        int bmh = (int)Math.ceil(UnitConv.mpt2px(context.getHeight(), resolution));
+        int bmw = mpt2px(context.getWidth(), resolution);
+        int bmh = mpt2px(context.getHeight(), resolution);
         BufferedImage bi;
         if (gray) {
             if (withAlpha) {
@@ -102,6 +102,17 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter {
         return bi;
     }
 
+    /**
+     * Converts millipoints to pixels
+     *
+     * @param unit the unit to convert in mpts
+     * @param resolution the target resolution
+     * @return the converted unit in pixels
+     */
+    protected int mpt2px(int unit, int resolution) {
+        return (int)Math.ceil(UnitConv.mpt2px(unit, resolution));
+    }
+
     private static BufferedImage createGrayBufferedImageWithAlpha(int width, int height) {
         BufferedImage bi;
         boolean alphaPremultiplied = true;
diff --git a/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java
new file mode 100644 (file)
index 0000000..e305e0a
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+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.util.Service;
+
+/**
+ * This class holds references to various image handlers used by the renderers. It also
+ * supports automatic discovery of additional handlers available through
+ * the class path.
+ */
+public abstract class AbstractImageHandlerRegistry {
+
+    /** the logger */
+    private static Log log = LogFactory.getLog(AbstractImageHandlerRegistry.class);
+
+    private static final Comparator HANDLER_COMPARATOR = new Comparator() {
+        public int compare(Object o1, Object o2) {
+            ImageHandler h1 = (ImageHandler)o1;
+            ImageHandler h2 = (ImageHandler)o2;
+            return h1.getPriority() - h2.getPriority();
+        }
+    };
+
+    /** Map containing image handlers for various MIME types */
+    private final Map/*<Class, ImageHandler>*/ handlers
+        = new java.util.HashMap/*<Class, ImageHandler>*/();
+
+    /** List containing the same handlers as above but ordered by priority */
+    private final List/*<ImageHandler>*/ handlerList
+        = new java.util.LinkedList/*<ImageHandler>*/();
+
+    /** Sorted Set of registered handlers */
+    private ImageFlavor[] supportedFlavors = new ImageFlavor[0];
+
+    private int handlerRegistrations;
+    private int lastSync;
+
+    /**
+     * Default constructor.
+     */
+    public AbstractImageHandlerRegistry() {
+        discoverHandlers();
+    }
+
+    /**
+     * Add an ImageHandler. The handler itself is inspected to find out what it supports.
+     * @param classname the fully qualified class name
+     */
+    public void addHandler(String classname) {
+        try {
+            ImageHandler handlerInstance
+                = (ImageHandler)Class.forName(classname).newInstance();
+            addHandler(handlerInstance);
+        } catch (ClassNotFoundException e) {
+            throw new IllegalArgumentException("Could not find "
+                                               + classname);
+        } catch (InstantiationException e) {
+            throw new IllegalArgumentException("Could not instantiate "
+                                               + classname);
+        } catch (IllegalAccessException e) {
+            throw new IllegalArgumentException("Could not access "
+                                               + classname);
+        } catch (ClassCastException e) {
+            throw new IllegalArgumentException(classname
+                                               + " is not an "
+                                               + getHandlerClass().getName());
+        }
+    }
+
+    /**
+     * Add an image handler. The handler itself is inspected to find out what it supports.
+     * @param handler the ImageHandler instance
+     */
+    public synchronized void addHandler(ImageHandler handler) {
+        Class[] imageClasses = handler.getSupportedImageClasses();
+        for (int i = 0; i < imageClasses.length; i++) {
+            this.handlers.put(imageClasses[i], handler);
+        }
+
+        //Sorted insert
+        ListIterator iter = this.handlerList.listIterator();
+        while (iter.hasNext()) {
+            ImageHandler h = (ImageHandler)iter.next();
+            if (getHandlerComparator().compare(handler, h) < 0) {
+                iter.previous();
+                break;
+            }
+        }
+        iter.add(handler);
+        this.handlerRegistrations++;
+    }
+
+    /**
+     * Returns an ImageHandler which handles an specific image type given the MIME type
+     * of the image.
+     * @param img the Image to be handled
+     * @return the ImageHandler responsible for handling the image or null if none is available
+     */
+    public ImageHandler getHandler(Image img) {
+        return getHandler(img.getClass());
+    }
+
+    /**
+     * Returns an ImageHandler which handles an specific image type given the MIME type
+     * of the image.
+     * @param imageClass the Image subclass for which to get a handler
+     * @return the ImageHandler responsible for handling the image or null if none is available
+     */
+    public synchronized ImageHandler getHandler(Class imageClass) {
+        ImageHandler handler = null;
+        Class cl = imageClass;
+        while (cl != null) {
+            handler = (ImageHandler)handlers.get(cl);
+            if (handler != null) {
+                break;
+            }
+            cl = cl.getSuperclass();
+        }
+        return handler;
+    }
+
+    /**
+     * Returns the ordered array of supported image flavors.
+     * @return the array of image flavors
+     */
+    public synchronized ImageFlavor[] getSupportedFlavors() {
+        if (this.lastSync != this.handlerRegistrations) {
+            //Extract all ImageFlavors into a single array
+            List flavors = new java.util.ArrayList();
+            Iterator iter = this.handlerList.iterator();
+            while (iter.hasNext()) {
+                ImageFlavor[] f = ((ImageHandler)iter.next()).getSupportedImageFlavors();
+                for (int i = 0; i < f.length; i++) {
+                    flavors.add(f[i]);
+                }
+            }
+            this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]);
+            this.lastSync = this.handlerRegistrations;
+        }
+        return this.supportedFlavors;
+    }
+
+    /**
+     * Discovers ImageHandler implementations through the classpath and dynamically
+     * registers them.
+     */
+    private void discoverHandlers() {
+        // add mappings from available services
+        Class imageHandlerClass = getHandlerClass();
+        Iterator providers = Service.providers(imageHandlerClass);
+        if (providers != null) {
+            while (providers.hasNext()) {
+                ImageHandler handler = (ImageHandler)providers.next();
+                try {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Dynamically adding ImageHandler: "
+                                + handler.getClass().getName());
+                    }
+                    addHandler(handler);
+                } catch (IllegalArgumentException e) {
+                    log.error("Error while adding ImageHandler", e);
+                }
+
+            }
+        }
+    }
+
+    /**
+     * Returns the ImageHandler comparator
+     *
+     * @return the ImageHandler comparator
+     */
+    public Comparator getHandlerComparator() {
+        return HANDLER_COMPARATOR;
+    }
+
+    /**
+     * Returns the ImageHandler implementing class
+     *
+     * @return the ImageHandler implementing class
+     */
+    public abstract Class getHandlerClass();
+}
diff --git a/src/java/org/apache/fop/render/ImageHandler.java b/src/java/org/apache/fop/render/ImageHandler.java
new file mode 100644 (file)
index 0000000..05d1e2e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+
+public interface ImageHandler {
+
+    /**
+     * Returns the priority for this image handler. A lower value means higher priority. This
+     * information is used to build the ordered/prioritized list of supported ImageFlavors for
+     * the PDF renderer. The built-in handlers use priorities between 100 and 999.
+     * @return a positive integer (>0) indicating the priority
+     */
+    int getPriority();
+
+    /**
+     * Returns the {@link ImageFlavor}s supported by this instance
+     * @return the supported image flavors
+     */
+    ImageFlavor[] getSupportedImageFlavors();
+
+    /**
+     * Returns the {@link Image} subclasses supported by this instance.
+     * @return the Image types
+     */
+    Class[] getSupportedImageClasses();
+}
index 56504ff53855c3cf1edb9eb0c32e958e95e48929..e4ec41e0b1ccf15dc3bd6341a5f7de180bf2af41 100644 (file)
@@ -24,8 +24,6 @@ import java.awt.geom.Rectangle2D;
 import java.util.List;
 import java.util.Map;
 
-import org.w3c.dom.Document;
-
 import org.apache.fop.area.Area;
 import org.apache.fop.area.Trait;
 import org.apache.fop.fonts.CustomFontCollection;
@@ -36,6 +34,7 @@ import org.apache.fop.fonts.FontManager;
 import org.apache.fop.fonts.FontResolver;
 import org.apache.fop.fonts.FontTriplet;
 import org.apache.fop.fonts.base14.Base14FontCollection;
+import org.w3c.dom.Document;
 
 /** Abstract base class of "Print" type renderers.  */
 public abstract class PrintRenderer extends AbstractRenderer {
@@ -111,6 +110,14 @@ public abstract class PrintRenderer extends AbstractRenderer {
         return fontInfo.getFontInstance(triplet, size);
     }
 
+    /**
+     * Instantiates a RendererContext for an image
+     * @return a newly created RendererContext.
+     */
+    protected RendererContext instantiateRendererContext() {
+        return new RendererContext(this, getMimeType());
+    }
+
     /**
      * Creates a RendererContext for an image.
      * @param x the x coordinate (in millipoints)
@@ -122,8 +129,7 @@ public abstract class PrintRenderer extends AbstractRenderer {
      */
     protected RendererContext createRendererContext(int x, int y, int width, int height,
             Map foreignAttributes) {
-        RendererContext context;
-        context = new RendererContext(this, getMimeType());
+        RendererContext context = instantiateRendererContext();
         context.setUserAgent(userAgent);
 
         context.setProperty(RendererContextConstants.WIDTH,
index e4e234cd2ef716d7a1c9ded10ba70ac5c0bef057..ac885a44bd18410b37bf5003fb877735aa6693ef 100644 (file)
 package org.apache.fop.render;
 
 //Java
+import java.util.Iterator;
 import java.util.Map;
 
-//FOP
 import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.xmlgraphics.util.QName;
 
 /**
  * The Render Context for external handlers. This provides a rendering context
@@ -31,21 +33,28 @@ import org.apache.fop.apps.FOUserAgent;
  * render target.
  */
 public class RendererContext {
+    /** conversion-mode extension attribute */
+    protected static final QName CONVERSION_MODE = new QName(
+            ExtensionElementMapping.URI, null, "conversion-mode");
+
+    /** "bitmap" value for the "conversion-mode" extension attribute. */
+    protected static final String BITMAP = "bitmap";
 
     private final String mime;
     private final AbstractRenderer renderer;
     private FOUserAgent userAgent;
-    private final Map props = new java.util.HashMap();
+
+    private final Map/*<String,Object>*/ props = new java.util.HashMap/*<String,Object>*/();
 
     /**
-     * Contructor for this class. It takes a MIME type as parameter.
+     * Constructor for this class. It takes a MIME type as parameter.
      *
-     * @param renderer The current renderer
-     * @param m  The MIME type of the output that's generated.
+     * @param renderer the current renderer
+     * @param mime the MIME type of the output that's generated.
      */
-    public RendererContext(AbstractRenderer renderer, String m) {
+    public RendererContext(AbstractRenderer renderer, String mime) {
         this.renderer = renderer;
-        this.mime = m;
+        this.mime = mime;
     }
 
     /**
@@ -113,6 +122,19 @@ public class RendererContext {
         return wrapper;
     }
 
+    /** {@inheritDoc} **/
+    public String toString() {
+        StringBuffer stringBuffer = new StringBuffer("RendererContext{\n");
+        Iterator it = props.keySet().iterator();
+        while (it.hasNext()) {
+            String key = (String)it.next();
+            Object value = props.get(key);
+            stringBuffer.append("\t" + key + "=" + value + "\n");
+        }
+        stringBuffer.append("}");
+        return stringBuffer.toString();
+    }
+
     /**
      * Base class for a wrapper around RendererContext to access its properties in a type-safe,
      * renderer-specific way.
diff --git a/src/java/org/apache/fop/render/afp/AFPAbstractImageFactory.java b/src/java/org/apache/fop/render/afp/AFPAbstractImageFactory.java
deleted file mode 100644 (file)
index 3b00804..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.afp;
-
-import java.io.IOException;
-
-import org.apache.fop.afp.AFPDataObjectInfo;
-import org.apache.fop.afp.AFPForeignAttributeReader;
-import org.apache.fop.afp.AFPObjectAreaInfo;
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.fop.afp.AFPResourceInfo;
-import org.apache.fop.afp.AFPUnitConverter;
-
-
-/**
- * Abstract image configurator
- */
-public abstract class AFPAbstractImageFactory {
-    private static final int X = 0;
-    private static final int Y = 1;
-
-    /** the AFP state */
-    protected final AFPPaintingState state;
-
-    /** foreign attribute reader */
-    private final AFPForeignAttributeReader foreignAttributeReader
-        = new AFPForeignAttributeReader();
-
-    /**
-     * Main constructor
-     *
-     * @param state the AFP painting state
-     */
-    public AFPAbstractImageFactory(AFPPaintingState state) {
-        this.state = state;
-    }
-
-    /**
-     * Configures the data object info
-     *
-     * @param afpImageInfo the afp image info
-     * @return the data object info
-     * @throws IOException thrown if an I/O exception of some sort has occurred.
-     */
-    public AFPDataObjectInfo create(AFPRendererImageInfo afpImageInfo) throws IOException {
-        AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();
-
-        // set resource information
-        AFPResourceInfo resourceInfo
-        = foreignAttributeReader.getResourceInfo(afpImageInfo.foreignAttributes);
-        resourceInfo.setUri(afpImageInfo.uri);
-        dataObjectInfo.setResourceInfo(resourceInfo);
-
-        // set object area
-        AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
-        float srcX = afpImageInfo.origin.x + (float)afpImageInfo.pos.getX();
-        float srcY = afpImageInfo.origin.y + (float)afpImageInfo.pos.getY();
-        AFPUnitConverter unitConv = state.getUnitConverter();
-        int[] coords = unitConv.mpts2units(new float[] {srcX, srcY});
-        objectAreaInfo.setX(coords[X]);
-        objectAreaInfo.setY(coords[Y]);
-        int width = Math.round(unitConv.mpt2units((float)afpImageInfo.pos.getWidth()));
-        objectAreaInfo.setWidth(width);
-        int height = Math.round(unitConv.mpt2units((float)afpImageInfo.pos.getHeight()));
-        objectAreaInfo.setHeight(height);
-        dataObjectInfo.setObjectAreaInfo(objectAreaInfo);
-        return dataObjectInfo;
-    }
-
-    /**
-     * Creates the data object information object
-     *
-     * @return the data object information object
-     */
-    protected abstract AFPDataObjectInfo createDataObjectInfo();
-}
\ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPDataObjectInfoFactory.java b/src/java/org/apache/fop/render/afp/AFPDataObjectInfoFactory.java
deleted file mode 100644 (file)
index ba23928..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.afp;
-
-import java.awt.Point;
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-
-import org.apache.fop.afp.AFPDataObjectInfo;
-import org.apache.fop.afp.AFPForeignAttributeReader;
-import org.apache.fop.afp.AFPObjectAreaInfo;
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.fop.afp.AFPResourceInfo;
-import org.apache.fop.afp.AFPUnitConverter;
-
-
-/**
- * Abstract image configurator
- */
-public abstract class AFPDataObjectInfoFactory {
-    private static final int X = 0;
-    private static final int Y = 1;
-
-    /** the AFP painting state */
-    protected final AFPPaintingState state;
-
-    /** foreign attribute reader */
-    private final AFPForeignAttributeReader foreignAttributeReader
-        = new AFPForeignAttributeReader();
-
-    /**
-     * Main constructor
-     *
-     * @param state the AFP state
-     */
-    public AFPDataObjectInfoFactory(AFPPaintingState state) {
-        this.state = state;
-    }
-
-    /**
-     * Configures the data object info
-     *
-     * @param rendererImageInfo the afp image info
-     * @return the data object info
-     * @throws IOException thrown if an I/O exception of some sort has occurred.
-     */
-    public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
-        AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();
-
-        // set resource information
-        AFPResourceInfo resourceInfo
-        = foreignAttributeReader.getResourceInfo(rendererImageInfo.getForeignAttributes());
-        resourceInfo.setUri(rendererImageInfo.getURI());
-        dataObjectInfo.setResourceInfo(resourceInfo);
-
-        // set object area
-        AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
-
-        Point origin = rendererImageInfo.getOrigin();
-        Rectangle2D position = rendererImageInfo.getPosition();
-        float srcX = origin.x + (float)position.getX();
-        float srcY = origin.y + (float)position.getY();
-        AFPUnitConverter unitConv = state.getUnitConverter();
-        int[] coords = unitConv.mpts2units(new float[] {srcX, srcY});
-        objectAreaInfo.setX(coords[X]);
-        objectAreaInfo.setY(coords[Y]);
-
-        int width = Math.round(unitConv.mpt2units((float)position.getWidth()));
-        objectAreaInfo.setWidth(width);
-
-        int height = Math.round(unitConv.mpt2units((float)position.getHeight()));
-        objectAreaInfo.setHeight(height);
-
-        int resolution = state.getResolution();
-        objectAreaInfo.setHeightRes(resolution);
-        objectAreaInfo.setWidthRes(resolution);
-
-        objectAreaInfo.setRotation(state.getRotation());
-
-        dataObjectInfo.setObjectAreaInfo(objectAreaInfo);
-
-        return dataObjectInfo;
-    }
-
-    /**
-     * Creates the data object information object
-     *
-     * @return the data object information object
-     */
-    protected abstract AFPDataObjectInfo createDataObjectInfo();
-}
diff --git a/src/java/org/apache/fop/render/afp/AFPDataObjectInfoProvider.java b/src/java/org/apache/fop/render/afp/AFPDataObjectInfoProvider.java
deleted file mode 100644 (file)
index aac17b7..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.afp;
-
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
-import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
-
-/**
- * AFP data object info factory provider
- */
-public class AFPDataObjectInfoProvider {
-
-    private final Map/*<AbstractImage,AFPDataObjectInfoFactory>*/ factoryMap
-        = new java.util.HashMap/*<AbstractImage,AFPDataObjectInfoFactory>*/();
-
-    private final AFPPaintingState state;
-
-    /**
-     * Main constructor
-     *
-     * @param state the AFP painting state
-     */
-    public AFPDataObjectInfoProvider(AFPPaintingState state) {
-        this.state = state;
-        init();
-    }
-
-    /**
-     * Initialises the configurators
-     */
-    private void init() {
-        factoryMap.put(
-                ImageRendered.class, new AFPImageRenderedFactory(state));
-        factoryMap.put(
-                ImageRawCCITTFax.class, new AFPRawCCITTFaxFactory(state));
-        factoryMap.put(
-                ImageRawStream.class, new AFPImageRawStreamFactory(state));
-        factoryMap.put(
-                ImageGraphics2D.class, new AFPImageGraphics2DFactory(state));
-    };
-
-    /**
-     * Returns the configurator for a given image
-     *
-     * @param img the image
-     * @return the image configurator for the image
-     */
-    public AFPDataObjectInfoFactory getFactory(Image img) {
-        Class clazz = img.getClass();
-        AFPDataObjectInfoFactory configurator = (AFPDataObjectInfoFactory)factoryMap.get(clazz);
-        // not directly matched so try to map ancestor
-        if (configurator == null) {
-            Iterator it = factoryMap.keySet().iterator();
-            while (it.hasNext()) {
-                Class imageClass = (Class)it.next();
-                if (imageClass.isInstance(img)) {
-                    return (AFPDataObjectInfoFactory)factoryMap.get(imageClass);
-                }
-            }
-        }
-        return configurator;
-    }
-}
diff --git a/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java b/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java
new file mode 100644 (file)
index 0000000..2b5077f
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.afp;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.fop.render.afp.extensions.AFPElementMapping;
+import org.apache.xmlgraphics.util.QName;
+
+/**
+ * Parses any AFP foreign attributes
+ */
+public class AFPForeignAttributeReader {
+    private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
+
+    /** the resource-name attribute */
+    public static final String RESOURCE_NAME = "afp:resource-name";
+
+    /** the resource-level attribute */
+    public static final String RESOURCE_LEVEL = "afp:resource-level";
+
+    /** the resource-group-file attribute */
+    public static final String RESOURCE_GROUP_FILE = "afp:resource-group-file";
+
+    /**
+     * Main constructor
+     */
+    public AFPForeignAttributeReader() {
+    }
+
+    /**
+     * Returns the resource information
+     *
+     * @param foreignAttributes the foreign attributes
+     * @return the resource information
+     */
+    public AFPResourceInfo getResourceInfo(Map/*<QName, String>*/ foreignAttributes) {
+        AFPResourceInfo resourceInfo = new AFPResourceInfo();
+        if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
+            QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME);
+            String resourceName = (String)foreignAttributes.get(resourceNameKey);
+            if (resourceName != null) {
+                resourceInfo.setName(resourceName);
+            }
+            AFPResourceLevel level = getResourceLevel(foreignAttributes);
+            if (level != null) {
+                resourceInfo.setLevel(level);
+            }
+        }
+        return resourceInfo;
+    }
+
+    /**
+     * Returns the resource level
+     *
+     * @param foreignAttributes the foreign attributes
+     * @return the resource level
+     */
+    public AFPResourceLevel getResourceLevel(Map/*<QName, String>*/ foreignAttributes) {
+        AFPResourceLevel resourceLevel = null;
+        if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
+            QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL);
+            if (foreignAttributes.containsKey(resourceLevelKey)) {
+                String levelString = (String)foreignAttributes.get(resourceLevelKey);
+                resourceLevel = AFPResourceLevel.valueOf(levelString);
+                // if external get resource group file attributes
+                if (resourceLevel != null && resourceLevel.isExternal()) {
+                    QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE,
+                            RESOURCE_GROUP_FILE);
+                    String resourceGroupFile
+                        = (String)foreignAttributes.get(resourceGroupFileKey);
+                    if (resourceGroupFile == null) {
+                        String msg = RESOURCE_GROUP_FILE + " not specified";
+                        log.error(msg);
+                        throw new UnsupportedOperationException(msg);
+                    }
+                    File resourceExternalGroupFile = new File(resourceGroupFile);
+                    SecurityManager security = System.getSecurityManager();
+                    try {
+                        if (security != null) {
+                            security.checkWrite(resourceExternalGroupFile.getPath());
+                        }
+                    } catch (SecurityException ex) {
+                        String msg = "unable to gain write access to external resource file: "
+                        + resourceGroupFile;
+                        log.error(msg);
+                    }
+
+                    try {
+                        boolean exists = resourceExternalGroupFile.exists();
+                        if (exists) {
+                            log.warn("overwriting external resource file: "
+                                    + resourceGroupFile);
+                        }
+                        resourceLevel.setExternalFilePath(resourceGroupFile);
+                    } catch (SecurityException ex) {
+                        String msg = "unable to gain read access to external resource file: "
+                            + resourceGroupFile;
+                        log.error(msg);
+                    }
+                }
+            }
+        }
+        return resourceLevel;
+    }
+}
index 4f92826cf5b4764a95f65fb8d80615a24eef367b..8e43d1c282e50063236dfc53125f61ffcf1450e0 100644 (file)
@@ -28,7 +28,6 @@ import java.io.IOException;
 import org.apache.fop.afp.AFPGraphics2D;
 import org.apache.fop.afp.AFPGraphicsObjectInfo;
 import org.apache.fop.afp.AFPPaintingState;
-import org.apache.fop.afp.AFPResourceInfo;
 import org.apache.fop.afp.AFPResourceManager;
 import org.apache.fop.render.AbstractGraphics2DAdapter;
 import org.apache.fop.render.RendererContext;
@@ -40,95 +39,67 @@ import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
  */
 public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter {
 
-    private final AFPRenderer renderer;
-
-    private final AFPGraphics2D g2d;
+    private final AFPPaintingState paintingState;
 
     /**
      * Main constructor
      *
-     * @param renderer the afp renderer
-     */
-    public AFPGraphics2DAdapter(AFPRenderer renderer) {
-        this.renderer = renderer;
-
-        final boolean textAsShapes = false;
-        this.g2d = new AFPGraphics2D(textAsShapes);
-    }
-
-    /**
-     * Returns the AFP graphics 2D implementation
-     *
-     * @return the AFP graphics 2D implementation
+     * @param paintingState the AFP painting state
      */
-    public AFPGraphics2D getGraphics2D() {
-        return g2d;
+    public AFPGraphics2DAdapter(AFPPaintingState paintingState) {
+        this.paintingState = paintingState;
     }
 
     /** {@inheritDoc} */
     public void paintImage(Graphics2DImagePainter painter,
-            RendererContext context,
+            RendererContext rendererContext,
             int x, int y, int width, int height) throws IOException {
 
-        AFPInfo afpInfo = AFPSVGHandler.getAFPInfo(context);
-
-        // set resource manager
-        AFPResourceManager resourceManager = afpInfo.getResourceManager();
-        g2d.setResourceManager(resourceManager);
-
-        // set resource information
-        AFPResourceInfo resourceInfo = afpInfo.getResourceInfo();
-        g2d.setResourceInfo(resourceInfo);
+        AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext;
+        AFPInfo afpInfo = afpRendererContext.getInfo();
 
-        // set painting state
-        AFPPaintingState paintingState = afpInfo.getPaintingState();
-        g2d.setPaintingState(paintingState);
-
-        // set graphic context
-        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
-
-        float fwidth = width / 1000f;
-        float fheight = height / 1000f;
-
-        // get the 'width' and 'height' attributes of the SVG document
-        Dimension imageSize = painter.getImageSize();
-        float imw = (float)imageSize.getWidth() / 1000f;
-        float imh = (float)imageSize.getHeight() / 1000f;
-        float sx = fwidth / imw;
-        float sy = fheight / imh;
-        AffineTransform at = new AffineTransform(sx, 0, 0, sy, x, y);
+        final boolean textAsShapes = false;
+        AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);
 
-        renderer.saveGraphicsState();
+        paintingState.push();
 
+        //Fallback solution: Paint to a BufferedImage
         if (afpInfo.paintAsBitmap()) {
-            //Fallback solution: Paint to a BufferedImage
-            int resolution = Math.round(context.getUserAgent().getTargetResolution());
-            RendererContextWrapper ctx = RendererContext.wrapRendererContext(context);
-            BufferedImage bufferedImage = paintToBufferedImage(painter, ctx, resolution, false, false);
-
-            AFPPaintingState state = afpInfo.getPaintingState();
-            AffineTransform trans = state.getData().getTransform();
-            float scale = AFPRenderer.NORMAL_AFP_RESOLUTION
-                            / context.getUserAgent().getTargetResolution();
-            if (scale != 1) {
-                at.scale(scale, scale);
-            }
-
-            if (!at.isIdentity()) {
-                trans.concatenate(at);
-            }
-
-            g2d.drawImage(bufferedImage, trans, null);
+
+            // paint image
+            RendererContextWrapper rendererContextWrapper
+                = RendererContext.wrapRendererContext(rendererContext);
+            float targetResolution = rendererContext.getUserAgent().getTargetResolution();
+            int resolution = Math.round(targetResolution);
+            boolean colorImages = afpInfo.isColorSupported();
+            BufferedImage bufferedImage = paintToBufferedImage(
+                    painter, rendererContextWrapper, resolution, !colorImages, false);
+
+            // draw image
+            AffineTransform at = paintingState.getData().getTransform();
+            at.translate(x, y);
+            g2d.drawImage(bufferedImage, at, null);
         } else {
             AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();
             graphicsObjectInfo.setPainter(painter);
             graphicsObjectInfo.setGraphics2D(g2d);
 
+            // get the 'width' and 'height' attributes of the SVG document
+            Dimension imageSize = painter.getImageSize();
+            float imw = (float)imageSize.getWidth() / 1000f;
+            float imh = (float)imageSize.getHeight() / 1000f;
+
             Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
             graphicsObjectInfo.setArea(area);
+            AFPResourceManager resourceManager = afpInfo.getResourceManager();
             resourceManager.createObject(graphicsObjectInfo);
         }
 
-        renderer.restoreGraphicsState();
+        paintingState.pop();
+    }
+
+    /** {@inheritDoc} */
+    protected int mpt2px(int unit, int resolution) {
+        return Math.round(paintingState.getUnitConverter().mpt2units(unit));
     }
 }
diff --git a/src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java b/src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java
deleted file mode 100644 (file)
index 88c0b5c..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.afp;
-
-import java.awt.Rectangle;
-import java.awt.geom.AffineTransform;
-import java.io.IOException;
-
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.fop.afp.AFPDataObjectInfo;
-import org.apache.fop.afp.AFPGraphics2D;
-import org.apache.fop.afp.AFPGraphicsObjectInfo;
-import org.apache.fop.afp.AFPObjectAreaInfo;
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.fop.afp.AFPResourceInfo;
-import org.apache.fop.afp.AFPResourceLevel;
-import org.apache.fop.afp.AFPTextElementBridge;
-import org.apache.fop.afp.AFPTextHandler;
-import org.apache.fop.afp.AFPTextPainter;
-import org.apache.fop.render.RendererContext;
-import org.apache.fop.svg.SVGUserAgent;
-import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
-import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
-import org.apache.xmlgraphics.util.MimeConstants;
-
-
-/**
- * An AFP image graphics 2d factory
- */
-public class AFPImageGraphics2DFactory extends AFPDataObjectInfoFactory {
-
-    /**
-     * Main constructor
-     *
-     * @param state the AFP painting state
-     */
-    public AFPImageGraphics2DFactory(AFPPaintingState state) {
-        super(state);
-    }
-
-    /** {@inheritDoc} */
-    protected AFPDataObjectInfo createDataObjectInfo() {
-        return new AFPGraphicsObjectInfo();
-    }
-
-    /** {@inheritDoc} */
-    public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
-        AFPGraphicsObjectInfo graphicsObjectInfo
-            = (AFPGraphicsObjectInfo)super.create(rendererImageInfo);
-
-        AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
-        // level not explicitly set/changed so default to inline for GOCA graphic objects
-        // (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07) - hard copy works just fine)
-        if (!resourceInfo.levelChanged()) {
-            resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
-        }
-
-        // set mime type (unsupported by MOD:CA registry)
-        graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);
-
-        // set graphics 2d
-        AFPGraphics2DAdapter g2dAdapter = rendererImageInfo.getGraphics2DAdapter();
-        AFPGraphics2D g2d = g2dAdapter.getGraphics2D();
-        graphicsObjectInfo.setGraphics2D(g2d);
-
-        // set resource, state and font info
-        RendererContext rendererContext = rendererImageInfo.getRendererContext();
-        AFPInfo afpInfo = AFPSVGHandler.getAFPInfo(rendererContext);
-        g2d.setResourceManager(afpInfo.getResourceManager());
-        g2d.setResourceInfo(afpInfo.getResourceInfo());
-        g2d.setPaintingState(afpInfo.getPaintingState());
-        g2d.setFontInfo(afpInfo.getFontInfo());
-
-        // set to default graphic context
-        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
-
-        // translate to current location
-        AffineTransform at = state.getData().getTransform();
-        g2d.translate(at.getTranslateX(), at.getTranslateY());
-
-        // set afp state
-        g2d.setPaintingState(state);
-
-        // controls whether text painted by Batik is generated using text or path operations
-        SVGUserAgent svgUserAgent
-            = new SVGUserAgent(rendererContext.getUserAgent(), new AffineTransform());
-        BridgeContext ctx = new BridgeContext(svgUserAgent);
-        if (!afpInfo.strokeText()) {
-            AFPTextHandler textHandler = new AFPTextHandler(g2d);
-            g2d.setCustomTextHandler(textHandler);
-            AFPTextPainter textPainter = new AFPTextPainter(textHandler);
-            ctx.setTextPainter(textPainter);
-            AFPTextElementBridge textElementBridge = new AFPTextElementBridge(textPainter);
-            ctx.putBridge(textElementBridge);
-        }
-
-        // set painter
-        ImageGraphics2D imageG2D = (ImageGraphics2D)rendererImageInfo.getImage();
-        Graphics2DImagePainter painter = imageG2D.getGraphics2DImagePainter();
-        graphicsObjectInfo.setPainter(painter);
-
-        // set object area
-        AFPObjectAreaInfo objectAreaInfo = graphicsObjectInfo.getObjectAreaInfo();
-        int width = objectAreaInfo.getWidth();
-        int height = objectAreaInfo.getHeight();
-        Rectangle area = new Rectangle(width, height);
-        graphicsObjectInfo.setArea(area);
-
-        // invert y-axis for GOCA
-        final int sx = 1;
-        final int sy = -1;
-        g2d.translate(0, height);
-        g2d.scale(sx, sy);
-
-        return graphicsObjectInfo;
-    }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandler.java b/src/java/org/apache/fop/render/afp/AFPImageHandler.java
new file mode 100644 (file)
index 0000000..8e925d4
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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.afp;
+
+import java.awt.Point;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPUnitConverter;
+import org.apache.fop.render.ImageHandler;
+
+public abstract class AFPImageHandler implements ImageHandler {
+    private static final int X = 0;
+    private static final int Y = 1;
+
+    /** foreign attribute reader */
+    private final AFPForeignAttributeReader foreignAttributeReader
+        = new AFPForeignAttributeReader();
+
+    /**
+     * Generates an intermediate AFPDataObjectInfo that is later used to construct
+     * the appropriate data object in the AFP DataStream.
+     *
+     * @param rendererImageInfo the renderer image info
+     * @return a data object info object
+     * @throws IOException thrown if an I/O exception of some sort has occurred.
+     */
+    public AFPDataObjectInfo generateDataObjectInfo(
+            AFPRendererImageInfo rendererImageInfo) throws IOException {
+        AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();
+
+        // set resource information
+        Map foreignAttributes = rendererImageInfo.getForeignAttributes();
+        AFPResourceInfo resourceInfo
+            = foreignAttributeReader.getResourceInfo(foreignAttributes);
+        resourceInfo.setUri(rendererImageInfo.getURI());
+        dataObjectInfo.setResourceInfo(resourceInfo);
+
+        // set object area
+        AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
+
+        Point origin = rendererImageInfo.getOrigin();
+        Rectangle2D position = rendererImageInfo.getPosition();
+        float srcX = origin.x + (float)position.getX();
+        float srcY = origin.y + (float)position.getY();
+
+        AFPRendererContext rendererContext
+            = (AFPRendererContext)rendererImageInfo.getRendererContext();
+        AFPInfo afpInfo = rendererContext.getInfo();
+        AFPPaintingState paintingState = afpInfo.getPaintingState();
+        AFPUnitConverter unitConv = paintingState.getUnitConverter();
+        int[] coords = unitConv.mpts2units(new float[] {srcX, srcY});
+        objectAreaInfo.setX(coords[X]);
+        objectAreaInfo.setY(coords[Y]);
+
+        int width = Math.round(unitConv.mpt2units((float)position.getWidth()));
+        objectAreaInfo.setWidth(width);
+
+        int height = Math.round(unitConv.mpt2units((float)position.getHeight()));
+        objectAreaInfo.setHeight(height);
+
+        int resolution = paintingState.getResolution();
+        objectAreaInfo.setHeightRes(resolution);
+        objectAreaInfo.setWidthRes(resolution);
+
+        objectAreaInfo.setRotation(paintingState.getRotation());
+
+        dataObjectInfo.setObjectAreaInfo(objectAreaInfo);
+
+        return dataObjectInfo;
+    }
+
+    /**
+     * Creates the data object information object
+     *
+     * @return the data object information object
+     */
+    protected abstract AFPDataObjectInfo createDataObjectInfo();
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
new file mode 100644 (file)
index 0000000..e8fe1f4
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.afp;
+
+import java.awt.geom.AffineTransform;
+import java.io.IOException;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPGraphics2D;
+import org.apache.fop.afp.AFPGraphicsObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * PDFImageHandler implementation which handles Graphics2D images.
+ */
+public class AFPImageHandlerGraphics2D extends AFPImageHandler {
+
+    private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+        ImageFlavor.GRAPHICS2D
+    };
+
+    private static final Class[] CLASSES = new Class[] {
+        ImageGraphics2D.class
+    };
+
+    /** {@inheritDoc} */
+    public AFPDataObjectInfo generateDataObjectInfo(
+            AFPRendererImageInfo rendererImageInfo) throws IOException {
+
+        AFPRendererContext rendererContext = (AFPRendererContext)rendererImageInfo.getRendererContext();
+        AFPInfo afpInfo = rendererContext.getInfo();
+        ImageGraphics2D imageG2D = (ImageGraphics2D)rendererImageInfo.getImage();
+        Graphics2DImagePainter painter = imageG2D.getGraphics2DImagePainter();
+
+        if (afpInfo.paintAsBitmap()) {
+            int x = afpInfo.getX();
+            int y = afpInfo.getY();
+            int width = afpInfo.getWidth();
+            int height = afpInfo.getHeight();
+            AFPPaintingState paintingState = afpInfo.getPaintingState();
+            AFPGraphics2DAdapter g2dAdapter = new AFPGraphics2DAdapter(paintingState);
+            g2dAdapter.paintImage(painter, rendererContext, x, y, width, height);
+            return null;
+        } else {
+            AFPGraphicsObjectInfo graphicsObjectInfo
+            = (AFPGraphicsObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+            AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
+            //level not explicitly set/changed so default to inline for GOCA graphic objects
+            // (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07) - hard copy works just fine)
+            if (!resourceInfo.levelChanged()) {
+                resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
+            }
+
+            // set mime type (unsupported by MOD:CA registry)
+            graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);
+
+            // set g2d
+            boolean textAsShapes = false;
+
+            AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);
+
+            graphicsObjectInfo.setGraphics2D(g2d);
+
+            // translate to current location
+            AFPPaintingState paintingState = afpInfo.getPaintingState();
+            AffineTransform at = paintingState.getData().getTransform();
+            g2d.translate(at.getTranslateX(), at.getTranslateY());
+
+            // set painter
+            graphicsObjectInfo.setPainter(painter);
+
+            // invert y-axis for GOCA
+            final int sx = 1;
+            final int sy = -1;
+            AFPObjectAreaInfo objectAreaInfo = graphicsObjectInfo.getObjectAreaInfo();
+            int height = objectAreaInfo.getHeight();
+            g2d.translate(0, height);
+            g2d.scale(sx, sy);
+
+            return graphicsObjectInfo;
+        }
+    }
+
+    /** {@inheritDoc} */
+    public int getPriority() {
+        return 200;
+    }
+
+    /** {@inheritDoc} */
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
+    }
+
+    /** {@inheritDoc} */
+    public ImageFlavor[] getSupportedImageFlavors() {
+        return FLAVORS;
+    }
+
+    /** {@inheritDoc} */
+    protected AFPDataObjectInfo createDataObjectInfo() {
+        return new AFPGraphicsObjectInfo();
+    }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java
new file mode 100644 (file)
index 0000000..aa91bb6
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.afp;
+
+import java.io.IOException;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPImageObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+
+/**
+ * PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4).
+ */
+public class AFPImageHandlerRawCCITTFax extends AFPImageHandler {
+
+    private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+        ImageFlavor.RAW_CCITTFAX,
+    };
+
+    private static final Class[] CLASSES = new Class[] {
+        ImageRawCCITTFax.class,
+    };
+
+    /** {@inheritDoc} */
+    public AFPDataObjectInfo generateDataObjectInfo(
+            AFPRendererImageInfo rendererImageInfo) throws IOException {
+        AFPImageObjectInfo imageObjectInfo
+            = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+        ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.getImage();
+        imageObjectInfo.setCompression(ccitt.getCompression());
+
+        AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
+        ImageSize imageSize = ccitt.getSize();
+        int widthRes = (int) (imageSize.getDpiHorizontal() * 10);
+        objectAreaInfo.setWidthRes(widthRes);
+
+        int heightRes = (int) (imageSize.getDpiVertical() * 10);
+        objectAreaInfo.setHeightRes(heightRes);
+
+        imageObjectInfo.setInputStream(ccitt.createInputStream());
+
+        return imageObjectInfo;
+    }
+
+    /** {@inheritDoc} */
+    protected AFPDataObjectInfo createDataObjectInfo() {
+        return new AFPImageObjectInfo();
+    }
+
+    /** {@inheritDoc} */
+    public int getPriority() {
+        return 400;
+    }
+
+    /** {@inheritDoc} */
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
+    }
+
+    /** {@inheritDoc} */
+    public ImageFlavor[] getSupportedImageFlavors() {
+        return FLAVORS;
+    }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java
new file mode 100644 (file)
index 0000000..47344b2
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.afp;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
+
+/**
+ * AFPImageHandler implementation which handles raw stream images.
+ */
+public class AFPImageHandlerRawStream extends AFPImageHandler {
+
+    private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+        ImageFlavor.RAW_JPEG,
+        ImageFlavor.RAW_CCITTFAX,
+        ImageFlavor.RAW_EPS,
+    };
+
+    private static final Class[] CLASSES = new Class[] {
+        ImageRawJPEG.class,
+        ImageRawCCITTFax.class,
+        ImageRawEPS.class
+    };
+
+    /** {@inheritDoc} */
+    public AFPDataObjectInfo generateDataObjectInfo(
+            AFPRendererImageInfo rendererImageInfo) throws IOException {
+        AFPDataObjectInfo dataObjectInfo = super.generateDataObjectInfo(rendererImageInfo);
+        ImageInfo imageInfo = rendererImageInfo.getImageInfo();
+        String mimeType = imageInfo.getMimeType();
+        if (mimeType != null) {
+            dataObjectInfo.setMimeType(mimeType);
+        }
+        ImageRawStream rawStream = (ImageRawStream) rendererImageInfo.getImage();
+
+        AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
+
+        AFPRendererContext rendererContext
+        = (AFPRendererContext)rendererImageInfo.getRendererContext();
+        AFPInfo afpInfo = rendererContext.getInfo();
+        AFPPaintingState paintingState = afpInfo.getPaintingState();
+        int resolution = paintingState.getResolution();
+        objectAreaInfo.setWidthRes(resolution);
+        objectAreaInfo.setHeightRes(resolution);
+
+        InputStream inputStream = rawStream.createInputStream();
+        dataObjectInfo.setInputStream(inputStream);
+
+        int dataHeight = rawStream.getSize().getHeightPx();
+        dataObjectInfo.setDataHeight(dataHeight);
+
+        int dataWidth = rawStream.getSize().getWidthPx();
+        dataObjectInfo.setDataWidth(dataWidth);
+        return dataObjectInfo;
+    }
+
+    /** {@inheritDoc} */
+    public int getPriority() {
+        return 100;
+    }
+
+    /** {@inheritDoc} */
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
+    }
+
+    /** {@inheritDoc} */
+    public ImageFlavor[] getSupportedImageFlavors() {
+        return FLAVORS;
+    }
+
+    /** {@inheritDoc} */
+    protected AFPDataObjectInfo createDataObjectInfo() {
+        return new AFPDataObjectInfo();
+    }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java
new file mode 100644 (file)
index 0000000..59ca6cf
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.afp;
+
+import org.apache.fop.render.AbstractImageHandlerRegistry;
+
+/**
+ * This class holds references to various image handlers used by the AFP renderer. It also
+ * supports automatic discovery of additional handlers available through
+ * the class path.
+ */
+public class AFPImageHandlerRegistry extends AbstractImageHandlerRegistry {
+
+    /**
+     * Main constructor
+     */
+    public AFPImageHandlerRegistry() {
+    }
+
+    /** {@inheritDoc} */
+    public Class getHandlerClass() {
+        return AFPImageHandler.class;
+    }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
new file mode 100644 (file)
index 0000000..ef6a6bb
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.afp;
+
+import java.awt.image.RenderedImage;
+import java.io.IOException;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.afp.AFPImageObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageBuffered;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.ps.ImageEncodingHelper;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+/**
+ * PDFImageHandler implementation which handles RenderedImage instances.
+ */
+public class AFPImageHandlerRenderedImage extends AFPImageHandler {
+
+    private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+        ImageFlavor.BUFFERED_IMAGE,
+        ImageFlavor.RENDERED_IMAGE
+    };
+
+    private static final Class[] CLASSES = new Class[] {
+        ImageBuffered.class,
+        ImageRendered.class
+    };
+
+    /** {@inheritDoc} */
+    public AFPDataObjectInfo generateDataObjectInfo(
+            AFPRendererImageInfo rendererImageInfo) throws IOException {
+        AFPImageObjectInfo imageObjectInfo
+            = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+        imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
+
+        AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
+        AFPRendererContext rendererContext
+            = (AFPRendererContext)rendererImageInfo.getRendererContext();
+        AFPInfo afpInfo = rendererContext.getInfo();
+        AFPPaintingState paintingState = afpInfo.getPaintingState();
+        int resolution = paintingState.getResolution();
+        objectAreaInfo.setWidthRes(resolution);
+        objectAreaInfo.setHeightRes(resolution);
+
+        ImageRendered imageRendered = (ImageRendered) rendererImageInfo.img;
+        RenderedImage renderedImage = imageRendered.getRenderedImage();
+
+        int dataHeight = renderedImage.getHeight();
+        imageObjectInfo.setDataHeight(dataHeight);
+
+        int dataWidth = renderedImage.getWidth();
+        imageObjectInfo.setDataWidth(dataWidth);
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos);
+        byte[] imageData = baos.toByteArray();
+
+        boolean colorImages = paintingState.isColorImages();
+        imageObjectInfo.setColor(colorImages);
+
+        // convert to grayscale
+        if (!colorImages) {
+            baos.reset();
+            int bitsPerPixel = paintingState.getBitsPerPixel();
+            imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+            ImageEncodingHelper.encodeRGBAsGrayScale(
+                  imageData, dataWidth, dataHeight, bitsPerPixel, baos);
+            imageData = baos.toByteArray();
+        }
+        imageObjectInfo.setData(imageData);
+
+        return imageObjectInfo;
+    }
+
+    /** {@inheritDoc} */
+    protected AFPDataObjectInfo createDataObjectInfo() {
+        return new AFPImageObjectInfo();
+    }
+
+    /** {@inheritDoc} */
+    public int getPriority() {
+        return 300;
+    }
+
+    /** {@inheritDoc} */
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
+    }
+
+    /** {@inheritDoc} */
+    public ImageFlavor[] getSupportedImageFlavors() {
+        return FLAVORS;
+    }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java
new file mode 100644 (file)
index 0000000..fee355d
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.afp;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererContextConstants;
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
+import org.w3c.dom.Document;
+
+/**
+ * PDFImageHandler implementation which handles XML-based images.
+ */
+public class AFPImageHandlerXML extends AFPImageHandler {
+
+    private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
+        ImageFlavor.XML_DOM,
+    };
+
+    private static final Class[] CLASSES = new Class[] {
+        ImageXMLDOM.class,
+    };
+
+    /** {@inheritDoc} */
+    public AFPDataObjectInfo generateDataObjectInfo(RendererContext context, Image image,
+            Point origin, Rectangle pos)
+            throws IOException {
+        AFPRenderer renderer = (AFPRenderer)context.getRenderer();
+        ImageXMLDOM imgXML = (ImageXMLDOM)image;
+        Document doc = imgXML.getDocument();
+        String ns = imgXML.getRootNamespace();
+        Map foreignAttributes = (Map)context.getProperty(
+                RendererContextConstants.FOREIGN_ATTRIBUTES);
+        renderer.renderDocument(doc, ns, pos, foreignAttributes);
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public int getPriority() {
+        return 400;
+    }
+
+    /** {@inheritDoc} */
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
+    }
+
+    /** {@inheritDoc} */
+    public ImageFlavor[] getSupportedImageFlavors() {
+        return FLAVORS;
+    }
+
+    /** {@inheritDoc} */
+    protected AFPDataObjectInfo createDataObjectInfo() {
+        return null;
+    }
+
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageRawStreamFactory.java b/src/java/org/apache/fop/render/afp/AFPImageRawStreamFactory.java
deleted file mode 100644 (file)
index 376bee7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.afp;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.fop.afp.AFPDataObjectInfo;
-import org.apache.fop.afp.AFPObjectAreaInfo;
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.xmlgraphics.image.loader.ImageInfo;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
-
-/**
- * A raw stream image data object info factory
- */
-public class AFPImageRawStreamFactory extends AFPDataObjectInfoFactory {
-
-    /**
-     * Main constructor
-     *
-     * @param state the AFP painting state
-     */
-    public AFPImageRawStreamFactory(AFPPaintingState state) {
-        super(state);
-    }
-
-    /** {@inheritDoc} */
-    public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
-        AFPDataObjectInfo dataObjectInfo = super.create(rendererImageInfo);
-        ImageInfo imageInfo = rendererImageInfo.getImageInfo();
-        String mimeType = imageInfo.getMimeType();
-        if (mimeType != null) {
-            dataObjectInfo.setMimeType(mimeType);
-        }
-        ImageRawStream rawStream = (ImageRawStream) rendererImageInfo.getImage();
-        int resolution = state.getResolution();
-
-        AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
-        objectAreaInfo.setWidthRes(resolution);
-        objectAreaInfo.setHeightRes(resolution);
-
-        InputStream inputStream = rawStream.createInputStream();
-        dataObjectInfo.setInputStream(inputStream);
-
-        int dataHeight = rawStream.getSize().getHeightPx();
-        dataObjectInfo.setDataHeight(dataHeight);
-
-        int dataWidth = rawStream.getSize().getWidthPx();
-        dataObjectInfo.setDataWidth(dataWidth);
-        return dataObjectInfo;
-    }
-
-    /** {@inheritDoc} */
-    protected AFPDataObjectInfo createDataObjectInfo() {
-        return new AFPDataObjectInfo();
-    }
-}
diff --git a/src/java/org/apache/fop/render/afp/AFPImageRenderedFactory.java b/src/java/org/apache/fop/render/afp/AFPImageRenderedFactory.java
deleted file mode 100644 (file)
index 59d6af9..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.afp;
-
-import java.awt.image.RenderedImage;
-import java.io.IOException;
-
-import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.apache.fop.afp.AFPDataObjectInfo;
-import org.apache.fop.afp.AFPImageObjectInfo;
-import org.apache.fop.afp.AFPObjectAreaInfo;
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
-import org.apache.xmlgraphics.ps.ImageEncodingHelper;
-import org.apache.xmlgraphics.util.MimeConstants;
-
-/**
- * A buffered image data object info factory
- */
-public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory {
-
-    /**
-     * Main constructor
-     *
-     * @param state the AFP painting state
-     */
-    public AFPImageRenderedFactory(AFPPaintingState state) {
-        super(state);
-    }
-
-    /** {@inheritDoc} */
-    public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
-        AFPImageObjectInfo imageObjectInfo
-            = (AFPImageObjectInfo)super.create(rendererImageInfo);
-
-        imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
-
-        AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
-        int resolution = state.getResolution();
-        objectAreaInfo.setWidthRes(resolution);
-        objectAreaInfo.setHeightRes(resolution);
-
-        ImageRendered imageRendered = (ImageRendered) rendererImageInfo.img;
-        RenderedImage renderedImage = imageRendered.getRenderedImage();
-
-        int dataHeight = renderedImage.getHeight();
-        imageObjectInfo.setDataHeight(dataHeight);
-
-        int dataWidth = renderedImage.getWidth();
-        imageObjectInfo.setDataWidth(dataWidth);
-
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos);
-        byte[] imageData = baos.toByteArray();
-
-        boolean colorImages = state.isColorImages();
-        imageObjectInfo.setColor(colorImages);
-
-        // convert to grayscale
-        if (!colorImages) {
-            baos.reset();
-            int bitsPerPixel = state.getBitsPerPixel();
-            imageObjectInfo.setBitsPerPixel(bitsPerPixel);
-            ImageEncodingHelper.encodeRGBAsGrayScale(
-                  imageData, dataWidth, dataHeight, bitsPerPixel, baos);
-            imageData = baos.toByteArray();
-        }
-        imageObjectInfo.setData(imageData);
-
-        return imageObjectInfo;
-    }
-
-    /** {@inheritDoc} */
-    protected AFPDataObjectInfo createDataObjectInfo() {
-        return new AFPImageObjectInfo();
-    }
-}
index 1059014aba02e5d1bceda090ae94fe319e0dadd5..59050b66d0d97d4cc981a5af65be5cab64ad5e11 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.render.afp;
 
 import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.fop.afp.AFPGraphics2D;
 import org.apache.fop.afp.AFPPaintingState;
 import org.apache.fop.afp.AFPResourceInfo;
 import org.apache.fop.afp.AFPResourceManager;
@@ -47,18 +48,18 @@ public final class AFPInfo {
     /** see AFP_FONT_INFO */
     private FontInfo fontInfo;
 
-    /** See AFP_STATE */
-    private AFPPaintingState state;
+    /** See AFP_PAINTING_STATE */
+    private AFPPaintingState paintingState;
 
     /** See AFP_RESOURCE_MANAGER */
     private AFPResourceManager resourceManager;
 
+    /** See AFP_RESOURCE_INFO */
+    private AFPResourceInfo resourceInfo;
+
     /** true if SVG should be rendered as a bitmap instead of natively */
     private boolean paintAsBitmap;
 
-    /** the resource information */
-    private AFPResourceInfo resourceInfo;
-
     /**
      * Returns the width.
      *
@@ -128,7 +129,7 @@ public final class AFPInfo {
      * @return the current AFP state
      */
     public AFPPaintingState getPaintingState() {
-        return this.state;
+        return this.paintingState;
     }
 
     /**
@@ -217,7 +218,7 @@ public final class AFPInfo {
      * @param state the AFP state
      */
     public void setPaintingState(AFPPaintingState state) {
-        this.state = state;
+        this.paintingState = state;
     }
 
     /**
@@ -278,6 +279,19 @@ public final class AFPInfo {
         return resourceInfo;
     }
 
+    /**
+     * Creates an AFPGraphics2D implementation
+     *
+     * @param textAsShapes true when text is painted as shapes
+     * @return a newly created AFPGraphics2D
+     */
+    public AFPGraphics2D createGraphics2D(boolean textAsShapes) {
+        AFPGraphics2D g2d = new AFPGraphics2D(
+                    textAsShapes, paintingState, resourceManager, resourceInfo, fontInfo);
+        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
+        return g2d;
+    }
+
     /** {@inheritDoc} */
     public String toString() {
         return "AFPInfo{width=" + width
@@ -287,7 +301,7 @@ public final class AFPInfo {
             + ", cfg=" + handlerConfiguration
             + ", fontInfo=" + fontInfo
             + ", resourceManager=" + resourceManager
-            + ", state=" + state
+            + ", paintingState=" + paintingState
             + ", paintAsBitmap=" + paintAsBitmap
             + ", resourceInfo=" + resourceInfo
         + "}";
diff --git a/src/java/org/apache/fop/render/afp/AFPRawCCITTFaxFactory.java b/src/java/org/apache/fop/render/afp/AFPRawCCITTFaxFactory.java
deleted file mode 100644 (file)
index 2e6eca6..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.afp;
-
-import java.io.IOException;
-
-import org.apache.fop.afp.AFPDataObjectInfo;
-import org.apache.fop.afp.AFPImageObjectInfo;
-import org.apache.fop.afp.AFPObjectAreaInfo;
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-
-/**
- * An CITT fax image data object info factory
- */
-public class AFPRawCCITTFaxFactory extends AFPDataObjectInfoFactory {
-
-    /**
-     * Main constructor
-     *
-     * @param state the AFP painting state
-     */
-    public AFPRawCCITTFaxFactory(AFPPaintingState state) {
-        super(state);
-    }
-
-    /** {@inheritDoc} */
-    public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
-        AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)super.create(rendererImageInfo);
-
-        ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.img;
-        imageObjectInfo.setCompression(ccitt.getCompression());
-
-        AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
-        int xresol = (int) (ccitt.getSize().getDpiHorizontal() * 10);
-        objectAreaInfo.setWidthRes(xresol);
-
-        int yresol = (int) (ccitt.getSize().getDpiVertical() * 10);
-        objectAreaInfo.setHeightRes(yresol);
-
-        imageObjectInfo.setInputStream(ccitt.createInputStream());
-
-        return imageObjectInfo;
-    }
-
-    /** {@inheritDoc} */
-    protected AFPDataObjectInfo createDataObjectInfo() {
-        return new AFPImageObjectInfo();
-    }
-}
\ No newline at end of file
index 87c098a8958d433d590945fdc104039e9510d14a..ede556ecb9c4c8d22d5ce64f52ab42dee63fc3e1 100644 (file)
@@ -36,7 +36,6 @@ import java.util.Map;
 import org.apache.fop.afp.AFPBorderPainter;
 import org.apache.fop.afp.AFPConstants;
 import org.apache.fop.afp.AFPDataObjectInfo;
-import org.apache.fop.afp.AFPPageFonts;
 import org.apache.fop.afp.AFPPaintingState;
 import org.apache.fop.afp.AFPRectanglePainter;
 import org.apache.fop.afp.AFPResourceManager;
@@ -47,6 +46,7 @@ import org.apache.fop.afp.RectanglePaintInfo;
 import org.apache.fop.afp.fonts.AFPFont;
 import org.apache.fop.afp.fonts.AFPFontAttributes;
 import org.apache.fop.afp.fonts.AFPFontCollection;
+import org.apache.fop.afp.fonts.AFPPageFonts;
 import org.apache.fop.afp.modca.DataStream;
 import org.apache.fop.afp.modca.PageObject;
 import org.apache.fop.apps.FOPException;
@@ -77,7 +77,6 @@ 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;
-import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
 import org.apache.xmlgraphics.image.loader.util.ImageUtil;
 import org.apache.xmlgraphics.ps.ImageEncodingHelper;
 
@@ -137,35 +136,33 @@ import org.apache.xmlgraphics.ps.ImageEncodingHelper;
  */
 public class AFPRenderer extends AbstractPathOrientedRenderer {
 
-    /** Normal PDF resolution (72dpi) */
-    public static final int NORMAL_AFP_RESOLUTION = 72;
-
     private static final int X = 0;
     private static final int Y = 1;
 
-    /** resource manager */
+    /** the resource manager */
     private AFPResourceManager resourceManager;
 
-    /** painting state */
+    /** the painting state */
     private final AFPPaintingState paintingState;
 
     /** unit converter */
     private final AFPUnitConverter unitConv;
 
-    /** line painter */
+    /** the line painter */
     private AFPBorderPainter borderPainter;
 
-    /** The map of page segments */
-    private final Map/*<String,String>*/pageSegmentMap = new java.util.HashMap/*<String,String>*/();
+    /** the map of page segments */
+    private final Map/*<String,String>*/pageSegmentMap
+        = new java.util.HashMap/*<String,String>*/();
 
-    /** The map of saved incomplete pages */
+    /** the map of saved incomplete pages */
     private final Map pages = new java.util.HashMap/*<PageViewport,PageObject>*/();
 
-    /** the afp datastream */
+    /** the AFP datastream */
     private DataStream dataStream;
 
-    /** data object information factory */
-    private final AFPDataObjectInfoProvider dataObjectInfoProvider;
+    /** the image handler registry */
+    private final AFPImageHandlerRegistry imageHandlerRegistry;
 
     private AFPRectanglePainter rectanglePainter;
 
@@ -176,7 +173,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
         super();
         this.resourceManager = new AFPResourceManager();
         this.paintingState = new AFPPaintingState();
-        this.dataObjectInfoProvider = new AFPDataObjectInfoProvider(paintingState);
+        this.imageHandlerRegistry = new AFPImageHandlerRegistry();
         this.unitConv = paintingState.getUnitConverter();
     }
 
@@ -252,7 +249,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
 
     /** {@inheritDoc} */
     public Graphics2DAdapter getGraphics2DAdapter() {
-        return new AFPGraphics2DAdapter(this);
+        return new AFPGraphics2DAdapter(paintingState);
     }
 
     /** {@inheritDoc} */
@@ -379,6 +376,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
         rectanglePainter.paint(rectanglePaintInfo);
     }
 
+    /** {@inheritDoc} */
+    protected RendererContext instantiateRendererContext() {
+        return new AFPRendererContext(this, getMimeType());
+    }
+
     /** {@inheritDoc} */
     protected RendererContext createRendererContext(int x, int y, int width,
             int height, Map foreignAttributes) {
@@ -394,25 +396,34 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
     }
 
     private static final ImageFlavor[] NATIVE_FLAVORS = new ImageFlavor[] {
+        ImageFlavor.XML_DOM,
         /*ImageFlavor.RAW_PNG, */ // PNG not natively supported in AFP
-        ImageFlavor.XML_DOM, ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS,
+        ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS,
         ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };
 
     private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
-        ImageFlavor.XML_DOM, ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };
+        ImageFlavor.XML_DOM,
+        ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };
 
     /** {@inheritDoc} */
     public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
         uri = URISpecification.getURL(uri);
         paintingState.setImageUri(uri);
-        Rectangle posInt = new Rectangle((int) pos.getX(), (int) pos.getY(),
-                (int) pos.getWidth(), (int) pos.getHeight());
+
+        Point origin = new Point(currentIPPosition, currentBPPosition);
+        Rectangle posInt = new Rectangle(
+                (int)Math.round(pos.getX()),
+                (int)Math.round(pos.getY()),
+                (int)Math.round(pos.getWidth()),
+                (int)Math.round(pos.getHeight())
+        );
+        int x = origin.x + posInt.x;
+        int y = origin.y + posInt.y;
+
         String name = (String)pageSegmentMap.get(uri);
-        int x = currentIPPosition + posInt.x;
-        int y = currentBPPosition + posInt.y;
-        float[] srcPts = {x, y};
-        int[] coords = unitConv.mpts2units(srcPts);
         if (name != null) {
+            float[] srcPts = {x, y};
+            int[] coords = unitConv.mpts2units(srcPts);
             dataStream.createIncludePageSegment(name, coords[X], coords[Y]);
         } else {
             ImageManager manager = userAgent.getFactory().getImageManager();
@@ -425,41 +436,40 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
                 // Only now fully load/prepare the image
                 Map hints = ImageUtil.getDefaultHints(sessionContext);
 
-                ImageFlavor[] flavors = paintingState.isNativeImages() ? NATIVE_FLAVORS : FLAVORS;
+                boolean nativeImagesSupported = paintingState.isNativeImagesSupported();
+                ImageFlavor[] flavors = nativeImagesSupported ? NATIVE_FLAVORS : FLAVORS;
+
+                // Load image
                 org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
                         info, flavors, hints, sessionContext);
 
-                Point origin = new Point(currentIPPosition, currentBPPosition);
-                AFPDataObjectInfoFactory factory = dataObjectInfoProvider.getFactory(img);
-                if (factory != null) {
-                    AFPRendererImageInfo afpImageInfo
-                    = new AFPRendererImageInfo(uri, pos, origin, info, img, foreignAttributes);
-                    if (factory instanceof AFPImageGraphics2DFactory) {
-                        RendererContext rendererContext = createRendererContext(
-                                x, y, posInt.width, posInt.height, foreignAttributes);
-                        afpImageInfo.setRendererContext(rendererContext);
-                        AFPGraphics2DAdapter g2dAdapter
-                            = (AFPGraphics2DAdapter)getGraphics2DAdapter();
-                        afpImageInfo.setGraphics2DAdapter(g2dAdapter);
-                    }
+                // Handle image
+                AFPImageHandler imageHandler
+                    = (AFPImageHandler)imageHandlerRegistry.getHandler(img);
+                if (imageHandler != null) {
+                    RendererContext rendererContext = createRendererContext(
+                            x, y, posInt.width, posInt.height, foreignAttributes);
+                    AFPRendererImageInfo rendererImageInfo = new AFPRendererImageInfo(
+                            uri, pos, origin, info, img, rendererContext, foreignAttributes);
                     AFPDataObjectInfo dataObjectInfo = null;
                     try {
-                        dataObjectInfo = factory.create(afpImageInfo);
+                        dataObjectInfo = imageHandler.generateDataObjectInfo(rendererImageInfo);
+                        // Create image
+                        if (dataObjectInfo != null) {
+                            resourceManager.createObject(dataObjectInfo);
+                        }
                     } catch (IOException ioe) {
                         ResourceEventProducer eventProducer
                             = ResourceEventProducer.Provider.get(userAgent.getEventBroadcaster());
                         eventProducer.imageWritingError(this, ioe);
                         throw ioe;
                     }
-                    resourceManager.createObject(dataObjectInfo);
-                } else if (img instanceof ImageXMLDOM) {
-                    ImageXMLDOM imgXML = (ImageXMLDOM) img;
-                    renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(),
-                            posInt, foreignAttributes);
                 } else {
                     throw new UnsupportedOperationException(
-                            "Unsupported image type: " + img);
+                            "No AFPImageHandler available for image: "
+                                + info + " (" + img.getClass().getName() + ")");
                 }
+
             } catch (ImageException ie) {
                 ResourceEventProducer eventProducer = ResourceEventProducer.Provider
                         .get(userAgent.getEventBroadcaster());
@@ -546,29 +556,17 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
     public void renderText(TextArea text) {
         renderInlineAreaBackAndBorders(text);
 
+        // set font size
         int fontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
         paintingState.setFontSize(fontSize);
 
-        String name = getInternalFontNameForArea(text);
-        AFPFont font = (AFPFont)fontInfo.getFonts().get(name);
-
-        // Set letterSpacing
-        // float ls = fs.getLetterSpacing() / this.currentFontSize;
-
-        // Create an AFPFontAttributes object from the current font details
-        AFPFontAttributes fontAttributes
-            = new AFPFontAttributes(name, font, fontSize);
-
+        // register font as necessary
+        String internalFontName = getInternalFontNameForArea(text);
+        AFPFont font = (AFPFont)fontInfo.getFonts().get(internalFontName);
         AFPPageFonts pageFonts = paintingState.getPageFonts();
-        if (!pageFonts.containsKey(fontAttributes.getFontKey())) {
-            // Font not found on current page, so add the new one
-            fontAttributes.setFontReference(paintingState.incrementPageFontCount());
-            pageFonts.put(fontAttributes.getFontKey(), fontAttributes);
-        } else {
-            // Use the previously stored font attributes
-            fontAttributes = (AFPFontAttributes)pageFonts.get(fontAttributes.getFontKey());
-        }
+        AFPFontAttributes fontAttributes = pageFonts.registerFont(internalFontName, font, fontSize);
 
+        // create text data info
         AFPTextDataInfo textDataInfo = new AFPTextDataInfo();
 
         int fontReference = fontAttributes.getFontReference();
@@ -765,8 +763,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
      * @param nativeImages
      *            native image support
      */
-    public void setNativeImages(boolean nativeImages) {
-        paintingState.setNativeImages(nativeImages);
+    public void setNativeImagesSupported(boolean nativeImages) {
+        paintingState.setNativeImagesSupported(nativeImages);
     }
 
     /**
index 6a59d27e387735bbc23082ef60d1897f3c227477..532d4596795e12aa1d1c58b52f6becac22487a59 100644 (file)
@@ -213,6 +213,12 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
         return fontList;
     }
 
+    /** images are converted to grayscale bitmapped IOCA */
+    private static final String IMAGES_MODE_GRAYSCALE = "b+w";
+
+    /** images are converted to color bitmapped IOCA */
+    private static final String IMAGES_MODE_COLOR = "color";
+
     /**
      * Configure the AFP renderer.
      *
@@ -234,15 +240,21 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
 
             // image information
             Configuration imagesCfg = cfg.getChild("images");
-            if (!"color".equalsIgnoreCase(imagesCfg.getAttribute("mode", "b+w"))) {
-                afpRenderer.setColorImages(false);
-                afpRenderer.setBitsPerPixel(imagesCfg.getAttributeAsInteger("bits-per-pixel", 8));
-            } else {
+
+            // default to grayscale images
+            String imagesMode = imagesCfg.getAttribute("mode", IMAGES_MODE_GRAYSCALE);
+            if (IMAGES_MODE_COLOR.equals(imagesMode)) {
                 afpRenderer.setColorImages(true);
+            } else {
+                afpRenderer.setColorImages(false);
+                // default to 8 bits per pixel
+                int bitsPerPixel = imagesCfg.getAttributeAsInteger("bits-per-pixel", 8);
+                afpRenderer.setBitsPerPixel(bitsPerPixel);
             }
 
-            // images are embedded directly without conversion to bitmapped IOCA
-            afpRenderer.setNativeImages(imagesCfg.getAttributeAsBoolean("native", false));
+            // native image support
+            boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false);
+            afpRenderer.setNativeImagesSupported(nativeImageSupport);
 
             // renderer resolution
             Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false);
@@ -269,16 +281,6 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
                                 + resourceGroupDest + "'");
                 }
             }
-
-            // TODO: provide support for different MO:DCA interchange sets
-            // the MO:DCA interchange set in use (defaults to MO:DCA-L)
-//            Configuration modcaCfg = cfg.getChild("modca", false);
-//            if (modcaCfg != null) {
-//                String interchangeSetString = cfg.getAttribute(
-//                        "interchange-set", InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2);
-//                InterchangeSet interchangeSet = InterchangeSet.valueOf(interchangeSetString);
-//                afpRenderer.getAFPDataStream().setInterchangeSet(interchangeSet);
-//            }
         }
     }
 }
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererContext.java b/src/java/org/apache/fop/render/afp/AFPRendererContext.java
new file mode 100644 (file)
index 0000000..8d544a7
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.afp;
+
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceInfo;
+import org.apache.fop.afp.AFPResourceLevel;
+import org.apache.fop.afp.AFPResourceManager;
+import org.apache.fop.render.AbstractRenderer;
+import org.apache.fop.render.RendererContext;
+import org.apache.fop.render.RendererContextConstants;
+
+public class AFPRendererContext extends RendererContext {
+
+    /**
+     * Main constructor
+     *
+     * @param renderer the current renderer
+     * @param mime the MIME type of the output that's generated.
+     */
+    public AFPRendererContext(AbstractRenderer renderer, String mime) {
+        super(renderer, mime);
+    }
+
+    /**
+     * Returns a new AFPInfo for this renderer context
+     *
+     * @return an AFPInfo for this renderer context
+     */
+    public AFPInfo getInfo() {
+        AFPInfo info = new AFPInfo();
+        info.setWidth(((Integer)getProperty(RendererContextConstants.WIDTH)).intValue());
+        info.setHeight(((Integer)getProperty(RendererContextConstants.HEIGHT)).intValue());
+        info.setX(((Integer)getProperty(RendererContextConstants.XPOS)).intValue());
+        info.setY(((Integer)getProperty(RendererContextConstants.YPOS)).intValue());
+        info.setHandlerConfiguration((Configuration)getProperty(
+                RendererContextConstants.HANDLER_CONFIGURATION));
+        info.setFontInfo((org.apache.fop.fonts.FontInfo)getProperty(
+                AFPRendererContextConstants.AFP_FONT_INFO));
+        info.setPaintingState((AFPPaintingState)getProperty(
+                AFPRendererContextConstants.AFP_PAINTING_STATE));
+        info.setResourceManager(((AFPResourceManager)getProperty(
+                AFPRendererContextConstants.AFP_RESOURCE_MANAGER)));
+
+        Map foreignAttributes = (Map)getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
+        if (foreignAttributes != null) {
+            String conversionMode = (String)foreignAttributes.get(CONVERSION_MODE);
+            boolean paintAsBitmap = BITMAP.equalsIgnoreCase(conversionMode);
+            info.setPaintAsBitmap(paintAsBitmap);
+
+            AFPForeignAttributeReader foreignAttributeReader
+                = new AFPForeignAttributeReader();
+            AFPResourceInfo resourceInfo
+                = foreignAttributeReader.getResourceInfo(foreignAttributes);
+            // default to inline level if painted as GOCA
+            if (!resourceInfo.levelChanged() && !paintAsBitmap) {
+                resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
+            }
+            info.setResourceInfo(resourceInfo);
+        }
+        return info;
+    }
+}
index d4a14d3c2a19c9aad169d01af5918898de87da9c..0aa3eb6abe457b8bdc4976c18435eccf5370683e 100644 (file)
@@ -50,9 +50,6 @@ public class AFPRendererImageInfo {
     /** the image */
     protected final Image img;
 
-    /** the AFP graphics 2d adapter */
-    protected AFPGraphics2DAdapter g2dAdapter;
-
     /** the renderer context */
     protected RendererContext rendererContext;
 
@@ -64,15 +61,17 @@ public class AFPRendererImageInfo {
      * @param origin the current position
      * @param info the image info
      * @param img the image
+     * @param rendererContext the renderer context
      * @param foreignAttributes the foreign attributes
      */
     public AFPRendererImageInfo(String uri, Rectangle2D pos, Point origin,
-            ImageInfo info, Image img, Map foreignAttributes) {
+            ImageInfo info, Image img, RendererContext rendererContext, Map foreignAttributes) {
         this.uri = uri;
         this.pos = pos;
         this.origin = origin;
         this.info = info;
         this.img = img;
+        this.rendererContext = rendererContext;
         this.foreignAttributes = foreignAttributes;
     }
 
@@ -85,15 +84,6 @@ public class AFPRendererImageInfo {
         this.rendererContext = rendererContext;
     }
 
-    /**
-     * Sets the graphics 2d adapter
-     *
-     * @param adapter the graphics 2d adapter
-     */
-    public void setGraphics2DAdapter(AFPGraphics2DAdapter adapter) {
-        this.g2dAdapter = adapter;
-    }
-
     /**
      * Returns the image info
      *
@@ -112,15 +102,6 @@ public class AFPRendererImageInfo {
         return this.img;
     }
 
-    /**
-     * Returns the graphics 2D adapter
-     *
-     * @return the graphics 2D adapter
-     */
-    public AFPGraphics2DAdapter getGraphics2DAdapter() {
-        return this.g2dAdapter;
-    }
-
     /**
      * Returns the renderer context
      *
index 3bdab289cf899c22496a8bae6846bb5135f1e6e6..2800686d9e5dd8972cecbe0ece804179870782ca 100644 (file)
@@ -22,39 +22,32 @@ package org.apache.fop.render.afp;
 // FOP
 import java.awt.Dimension;
 import java.awt.geom.AffineTransform;
-import java.awt.geom.Dimension2D;
 import java.io.IOException;
-import java.util.Map;
 
-import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.BridgeException;
-import org.apache.batik.bridge.GVTBuilder;
-import org.apache.batik.dom.AbstractDocument;
 import org.apache.batik.dom.svg.SVGDOMImplementation;
 import org.apache.batik.gvt.GraphicsNode;
-import org.apache.fop.afp.AFPForeignAttributeReader;
 import org.apache.fop.afp.AFPGraphics2D;
 import org.apache.fop.afp.AFPGraphicsObjectInfo;
 import org.apache.fop.afp.AFPObjectAreaInfo;
 import org.apache.fop.afp.AFPPaintingState;
 import org.apache.fop.afp.AFPResourceInfo;
-import org.apache.fop.afp.AFPResourceLevel;
 import org.apache.fop.afp.AFPResourceManager;
-import org.apache.fop.afp.AFPTextElementBridge;
-import org.apache.fop.afp.AFPTextHandler;
-import org.apache.fop.afp.AFPTextPainter;
 import org.apache.fop.afp.AFPUnitConverter;
 import org.apache.fop.afp.Graphics2DImagePainterGOCA;
+import org.apache.fop.afp.svg.AFPBridgeContext;
+import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fonts.FontInfo;
 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.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;
 
 /**
@@ -74,177 +67,138 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler {
         }
     }
 
-    /**
-     * Get the AFP information from the render context.
-     *
-     * @param context the renderer context
-     * @return the AFP information retrieved from the context
-     */
-    public static AFPInfo getAFPInfo(RendererContext context) {
-        AFPInfo afpi = new AFPInfo();
-        afpi.setWidth(((Integer)context.getProperty(WIDTH)).intValue());
-        afpi.setHeight(((Integer)context.getProperty(HEIGHT)).intValue());
-        afpi.setX(((Integer)context.getProperty(XPOS)).intValue());
-        afpi.setY(((Integer)context.getProperty(YPOS)).intValue());
-        afpi.setHandlerConfiguration((Configuration)context.getProperty(HANDLER_CONFIGURATION));
-        afpi.setFontInfo((org.apache.fop.fonts.FontInfo)context.getProperty(
-                AFPRendererContextConstants.AFP_FONT_INFO));
-        afpi.setPaintingState((AFPPaintingState)context.getProperty(
-                AFPRendererContextConstants.AFP_PAINTING_STATE));
-        afpi.setResourceManager(((AFPResourceManager)context.getProperty(
-                AFPRendererContextConstants.AFP_RESOURCE_MANAGER)));
-
-        Map foreignAttributes = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
-        if (foreignAttributes != null) {
-            String conversionMode = (String)foreignAttributes.get(CONVERSION_MODE);
-            boolean paintAsBitmap = BITMAP.equalsIgnoreCase(conversionMode);
-            afpi.setPaintAsBitmap(paintAsBitmap);
-
-            AFPForeignAttributeReader foreignAttributeReader = new AFPForeignAttributeReader();
-            AFPResourceInfo resourceInfo = foreignAttributeReader.getResourceInfo(foreignAttributes);
-            // default to inline level if painted as GOCA
-            if (!resourceInfo.levelChanged() && !paintAsBitmap) {
-                resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
-            }
-            afpi.setResourceInfo(resourceInfo);
-        }
-        return afpi;
-    }
-
     private static final int X = 0;
     private static final int Y = 1;
 
     /**
      * Render the SVG document.
      *
-     * @param context the renderer context
+     * @param rendererContext the renderer context
      * @param doc the SVG document
      * @throws IOException In case of an I/O error while painting the image
      */
-    protected void renderSVGDocument(final RendererContext context,
+    protected void renderSVGDocument(final RendererContext rendererContext,
             final Document doc) throws IOException {
 
-        AFPInfo afpInfo = getAFPInfo(context);
+        AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext;
+        AFPInfo afpInfo = afpRendererContext.getInfo();
 
         this.paintAsBitmap = afpInfo.paintAsBitmap();
 
+        FOUserAgent userAgent = rendererContext.getUserAgent();
+
         // fallback paint as bitmap
+        String uri = getDocumentURI(doc);
         if (paintAsBitmap) {
             try {
-                super.renderSVGDocument(context, doc);
+                super.renderSVGDocument(rendererContext, doc);
             } catch (IOException ioe) {
                 SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
-                        context.getUserAgent().getEventBroadcaster());
-                eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc));
+                        userAgent.getEventBroadcaster());
+                eventProducer.svgRenderingError(this, ioe, uri);
             }
             return;
         }
 
-        String uri = ((AbstractDocument)doc).getDocumentURI();
-        AFPPaintingState paintingState = afpInfo.getPaintingState();
+        // Create a new AFPGraphics2D
+        final boolean textAsShapes = false;
+        AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);
+
+        AFPPaintingState paintingState = g2d.getPaintingState();
         paintingState.setImageUri(uri);
 
+        // Create an AFPBridgeContext
+        BridgeContext bridgeContext = createBridgeContext(userAgent, g2d);
+
+        // Build the SVG DOM and provide the painter with it
+        GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc);
+
+        // Create Graphics2DImagePainter
+        final RendererContextWrapper wrappedContext
+            = RendererContext.wrapRendererContext(rendererContext);
+        Dimension imageSize = getImageSize(wrappedContext);
+        Graphics2DImagePainter painter
+            = createGrapics2DImagePainter(bridgeContext, root, imageSize);
+
+        // Create AFPObjectAreaInfo
+        RendererContextWrapper rctx = RendererContext.wrapRendererContext(rendererContext);
+        int x = rctx.getCurrentXPosition();
+        int y = rctx.getCurrentYPosition();
+        int width = afpInfo.getWidth();
+        int height = afpInfo.getHeight();
+        int resolution = afpInfo.getResolution();
+
+        paintingState.push(); // save
+
+        AFPObjectAreaInfo objectAreaInfo
+            = createObjectAreaInfo(paintingState, x, y, width, height, resolution);
+
+        // Create AFPGraphicsObjectInfo
+        AFPResourceInfo resourceInfo = afpInfo.getResourceInfo();
+        AFPGraphicsObjectInfo graphicsObjectInfo = createGraphicsObjectInfo(
+                paintingState, painter, userAgent, resourceInfo, g2d);
+        graphicsObjectInfo.setObjectAreaInfo(objectAreaInfo);
+
+        // Create the GOCA GraphicsObject in the DataStream
+        AFPResourceManager resourceManager = afpInfo.getResourceManager();
+        resourceManager.createObject(graphicsObjectInfo);
+
+        paintingState.pop(); // resume
+    }
+
+    private AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState,
+            int x, int y, int width, int height, int resolution) {
         // set the data object parameters
         AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
 
-        RendererContextWrapper rctx = RendererContext.wrapRendererContext(context);
-        int currx = rctx.getCurrentXPosition();
-        int curry = rctx.getCurrentYPosition();
-        float[] srcPts = {currx, curry};
-
-        AFPUnitConverter unitConv = paintingState.getUnitConverter();
-        int[] coords = unitConv.mpts2units(srcPts);
-        objectAreaInfo.setX(coords[X]);
-        objectAreaInfo.setY(coords[Y]);
+        AffineTransform at = paintingState.getData().getTransform();
+        at.translate(x, y);
+        objectAreaInfo.setX((int)Math.round(at.getTranslateX()));
+        objectAreaInfo.setY((int)Math.round(at.getTranslateY()));
 
-        int resolution = afpInfo.getResolution();
         objectAreaInfo.setWidthRes(resolution);
         objectAreaInfo.setHeightRes(resolution);
 
-        int width = Math.round(unitConv.mpt2units(afpInfo.getWidth()));
-        objectAreaInfo.setWidth(width);
-
-        int height = Math.round(unitConv.mpt2units(afpInfo.getHeight()));
-        objectAreaInfo.setHeight(height);
+        AFPUnitConverter unitConv = paintingState.getUnitConverter();
+        objectAreaInfo.setWidth(Math.round(unitConv.mpt2units(width)));
+        objectAreaInfo.setHeight(Math.round(unitConv.mpt2units(height)));
 
         int rotation = paintingState.getRotation();
         objectAreaInfo.setRotation(rotation);
 
-        AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();
-        graphicsObjectInfo.setUri(uri);
+        return objectAreaInfo;
+    }
 
-        // Configure Graphics2D implementation
-        final boolean textAsShapes = false;
-        AFPGraphics2D g2d = new AFPGraphics2D(textAsShapes);
+    private AFPGraphicsObjectInfo createGraphicsObjectInfo(AFPPaintingState paintingState, Graphics2DImagePainter painter,
+            FOUserAgent userAgent, AFPResourceInfo resourceInfo, AFPGraphics2D g2d) {
+        AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();
 
-        g2d.setPaintingState(paintingState);
+        String uri = paintingState.getImageUri();
+        graphicsObjectInfo.setUri(uri);
 
-        AFPResourceManager resourceManager = afpInfo.getResourceManager();
-        g2d.setResourceManager(resourceManager);
+        graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);
 
-        AFPResourceInfo resourceInfo = afpInfo.getResourceInfo();
-        g2d.setResourceInfo(resourceInfo);
         graphicsObjectInfo.setResourceInfo(resourceInfo);
 
-        g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
-
-        FontInfo fontInfo = afpInfo.getFontInfo();
-        g2d.setFontInfo(fontInfo);
-
-        // Configure GraphicsObjectPainter with the Graphics2D implementation
-        GraphicsObjectPainterAFP painter = new GraphicsObjectPainterAFP(g2d);
-        (graphicsObjectInfo).setPainter(painter);
+        graphicsObjectInfo.setPainter(painter);
 
-        // Controls whether text painted by Batik is generated using text or path operations
-        SVGUserAgent svgUserAgent
-            = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
-        BridgeContext ctx = new BridgeContext(svgUserAgent);
-        if (!afpInfo.strokeText()) {
-            AFPTextHandler textHandler = new AFPTextHandler(g2d);
-            g2d.setCustomTextHandler(textHandler);
-            AFPTextPainter textPainter = new AFPTextPainter(textHandler);
-            ctx.setTextPainter(textPainter);
-            AFPTextElementBridge tBridge = new AFPTextElementBridge(textPainter);
-            ctx.putBridge(tBridge);
-        }
+        // Set the afp graphics 2d implementation
+        graphicsObjectInfo.setGraphics2D(g2d);
 
-        // Build the SVG DOM and provide the painter with it
-        GraphicsNode root;
-        GVTBuilder builder = new GVTBuilder();
-        try {
-            root = builder.build(ctx, doc);
-            painter.setGraphicsNode(root);
-        } catch (BridgeException e) {
-            SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
-                    context.getUserAgent().getEventBroadcaster());
-            eventProducer.svgNotBuilt(this, e, uri);
-            return;
-        }
+        return graphicsObjectInfo;
+    }
 
-        // convert to afp inches
-        Dimension2D dim = ctx.getDocumentSize();
-        double w = dim.getWidth() * 1000f;
-        double h = dim.getHeight() * 1000f;
-        double wx = (afpInfo.getWidth() / w);
-        double hx = (afpInfo.getHeight() / h);
-        double scaleX = unitConv.pt2units((float)wx);
-        double scaleY = unitConv.pt2units((float)hx);
-        double yOffset = unitConv.mpt2units(afpInfo.getHeight());
-
-        // Transformation matrix that establishes the local coordinate system
-        // for the SVG graphic in relation to the current coordinate system
-        // (note: y axis is inverted)
-        AffineTransform trans = new AffineTransform(scaleX, 0, 0, -scaleY, 0, yOffset);
-        g2d.setTransform(trans);
+    public static BridgeContext createBridgeContext(FOUserAgent userAgent, AFPGraphics2D g2d) {
+        ImageManager imageManager = userAgent.getFactory().getImageManager();
 
-        // Set the afp graphics 2d implementation
-        graphicsObjectInfo.setGraphics2D(g2d);
+        SVGUserAgent svgUserAgent
+            = new SVGUserAgent(userAgent, new AffineTransform());
 
-        // Set the object area info
-        graphicsObjectInfo.setObjectAreaInfo(objectAreaInfo);
+        ImageSessionContext imageSessionContext = userAgent.getImageSessionContext();
 
-        // Create the graphics object
-        resourceManager.createObject(graphicsObjectInfo);
+        FontInfo fontInfo = g2d.getFontInfo();
+        return new AFPBridgeContext(svgUserAgent, fontInfo, imageManager, imageSessionContext,
+                new AffineTransform(), g2d);
     }
 
     /** {@inheritDoc} */
@@ -259,11 +213,13 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler {
     }
 
     /** {@inheritDoc} */
-    protected Graphics2DImagePainter createPainter(BridgeContext ctx, GraphicsNode root, Dimension imageSize) {
+    protected Graphics2DImagePainter createGrapics2DImagePainter(BridgeContext ctx, GraphicsNode root, Dimension imageSize) {
         Graphics2DImagePainter painter = null;
         if (paintAsBitmap()) {
-            painter = super.createPainter(root, ctx, imageSize);
+            // paint as IOCA Image
+            painter = super.createGraphics2DImagePainter(root, ctx, imageSize);
         } else {
+            // paint as GOCA Graphics
             painter = new Graphics2DImagePainterGOCA(root, ctx, imageSize);
         }
         return painter;
diff --git a/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java b/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java
deleted file mode 100644 (file)
index 7eb2c10..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.afp;
-
-import java.awt.Dimension;
-import java.awt.Graphics2D;
-import java.awt.geom.Rectangle2D;
-
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.afp.AFPGraphics2D;
-import org.apache.fop.afp.modca.GraphicsObject;
-import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
-
-/**
- * Paints SVG as a GOCA Graphics Object using Batik
- */
-public class GraphicsObjectPainterAFP implements Graphics2DImagePainter {
-    /** Static logging instance */
-    protected static Log log = LogFactory.getLog(GraphicsObjectPainterAFP.class);
-
-    private final AFPGraphics2D graphics2D;
-
-    /** the batik root node of the svg document */
-    private GraphicsNode root;
-
-    /**
-     * Main constructor
-     *
-     * @param graphics an AFP graphics 2D implementation
-     */
-    public GraphicsObjectPainterAFP(AFPGraphics2D graphics) {
-        final boolean textAsShapes = false;
-        this.graphics2D = new AFPGraphics2D(textAsShapes);
-    }
-
-    /**
-     * Sets the graphics node
-     *
-     * @param rootNode the graphics root node
-     */
-    public void setGraphicsNode(GraphicsNode rootNode) {
-        this.root = rootNode;
-    }
-
-    /** {@inheritDoc} */
-    public void paint(Graphics2D g2d, Rectangle2D area) {
-        log.debug("Painting SVG using GOCA");
-
-        // tell batik to paint the graphics object
-        root.paint(g2d);
-
-        // dispose of the graphics 2d implementation
-        g2d.dispose();
-    }
-
-    /** {@inheritDoc} */
-    public Dimension getImageSize() {
-        return null;
-    }
-
-    /**
-     * Sets the GOCA Graphics Object
-     *
-     * @param graphicsObject the GOCA Graphics Object
-     */
-    public void setGraphicsObject(GraphicsObject graphicsObject) {
-        this.graphics2D.setGraphicsObject(graphicsObject);
-    }
-
-}
diff --git a/src/java/org/apache/fop/render/afp/package.html b/src/java/org/apache/fop/render/afp/package.html
new file mode 100644 (file)
index 0000000..3e611d9
--- /dev/null
@@ -0,0 +1,23 @@
+<!--
+  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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
+<HTML>
+<TITLE>org.apache.fop.render.afp Package</TITLE>
+<BODY>
+<P>An AFP Renderer implementation and supporting classes.</P>
+</BODY>
+</HTML>
\ No newline at end of file
index f93ee5a9732f8888410cf750db01a6c40ad2ede5..6343d0c50321f85084bdb4e376e2abadf329a4a0 100644 (file)
@@ -23,36 +23,15 @@ import java.awt.Point;
 import java.awt.Rectangle;
 import java.io.IOException;
 
-import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
-
 import org.apache.fop.pdf.PDFXObject;
+import org.apache.fop.render.ImageHandler;
 import org.apache.fop.render.RendererContext;
+import org.apache.xmlgraphics.image.loader.Image;
 
 /**
  * This interface is used for handling all sorts of image type for PDF output.
  */
-public interface PDFImageHandler {
-
-    /**
-     * Returns the priority for this image handler. A lower value means higher priority. This
-     * information is used to build the ordered/prioritized list of supported ImageFlavors for
-     * the PDF renderer. The built-in handlers use priorities between 100 and 999.
-     * @return a positive integer (>0) indicating the priority
-     */
-    int getPriority();
-
-    /**
-     * Returns the {@link ImageFlavor}s supported by this instance
-     * @return the supported image flavors
-     */
-    ImageFlavor[] getSupportedImageFlavors();
-
-    /**
-     * Returns the {@link Image} subclass supported by this instance.
-     * @return the Image type
-     */
-    Class getSupportedImageClass();
+public interface PDFImageHandler extends ImageHandler {
 
     /**
      * Generates the PDF objects for the given {@link Image} instance. If the handler generates
index a58fe5922c9c2d7533ff638add528e07d5d168fa..9f44e58b5331e303ac2277e87c85543d3dc4ab37 100644 (file)
@@ -23,13 +23,12 @@ import java.awt.Point;
 import java.awt.Rectangle;
 import java.io.IOException;
 
+import org.apache.fop.pdf.PDFXObject;
+import org.apache.fop.render.RendererContext;
 import org.apache.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
 import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
 
-import org.apache.fop.pdf.PDFXObject;
-import org.apache.fop.render.RendererContext;
-
 /**
  * PDFImageHandler implementation which handles Graphics2D images.
  */
@@ -39,6 +38,10 @@ public class PDFImageHandlerGraphics2D implements PDFImageHandler {
         ImageFlavor.GRAPHICS2D,
     };
 
+    private static final Class[] CLASSES = new Class[] {
+        ImageGraphics2D.class,
+    };
+
     /** {@inheritDoc} */
     public PDFXObject generateImage(RendererContext context, Image image,
             Point origin, Rectangle pos)
@@ -56,8 +59,8 @@ public class PDFImageHandlerGraphics2D implements PDFImageHandler {
     }
 
     /** {@inheritDoc} */
-    public Class getSupportedImageClass() {
-        return ImageGraphics2D.class;
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
     }
 
     /** {@inheritDoc} */
index 9f56ebfea0f2ed670a58d853e35cd7bfe3065339..158e93c86116f04786ae9f3073682428e0213adf 100644 (file)
@@ -23,15 +23,14 @@ import java.awt.Point;
 import java.awt.Rectangle;
 import java.io.IOException;
 
-import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFImage;
 import org.apache.fop.pdf.PDFResourceContext;
 import org.apache.fop.pdf.PDFXObject;
 import org.apache.fop.render.RendererContext;
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
 
 /**
  * PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4).
@@ -42,6 +41,10 @@ public class PDFImageHandlerRawCCITTFax implements PDFImageHandler {
         ImageFlavor.RAW_CCITTFAX,
     };
 
+    private static final Class[] CLASSES = new Class[] {
+        ImageRawCCITTFax.class,
+    };
+
     /** {@inheritDoc} */
     public PDFXObject generateImage(RendererContext context, Image image,
             Point origin, Rectangle pos)
@@ -71,8 +74,8 @@ public class PDFImageHandlerRawCCITTFax implements PDFImageHandler {
     }
 
     /** {@inheritDoc} */
-    public Class getSupportedImageClass() {
-        return ImageRawCCITTFax.class;
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
     }
 
     /** {@inheritDoc} */
index f971a49aecd0c2669b8050160eda9cd9f1bc3915..1432547da4111bb97cb0f4e3ba22a72a3dabaae2 100644 (file)
@@ -23,15 +23,14 @@ import java.awt.Point;
 import java.awt.Rectangle;
 import java.io.IOException;
 
-import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
-
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFImage;
 import org.apache.fop.pdf.PDFResourceContext;
 import org.apache.fop.pdf.PDFXObject;
 import org.apache.fop.render.RendererContext;
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
 
 /**
  * PDFImageHandler implementation which handles raw JPEG images.
@@ -42,6 +41,10 @@ public class PDFImageHandlerRawJPEG implements PDFImageHandler {
         ImageFlavor.RAW_JPEG,
     };
 
+    private static final Class[] CLASSES = new Class[] {
+        ImageRawJPEG.class,
+    };
+
     /** {@inheritDoc} */
     public PDFXObject generateImage(RendererContext context, Image image,
             Point origin, Rectangle pos)
@@ -71,8 +74,8 @@ public class PDFImageHandlerRawJPEG implements PDFImageHandler {
     }
 
     /** {@inheritDoc} */
-    public Class getSupportedImageClass() {
-        return ImageRawJPEG.class;
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
     }
 
     /** {@inheritDoc} */
index b664a0a24bae7d536226c97c6fa0669ef2975cd9..1d4c733a3edff652dfbf7e578ea3ea68b99bda80 100644 (file)
 
 package org.apache.fop.render.pdf;
 
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-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.util.Service;
+import org.apache.fop.render.AbstractImageHandlerRegistry;
 
 /**
  * This class holds references to various image handlers used by the PDF renderer. It also
  * supports automatic discovery of additional handlers available through
  * the class path.
  */
-public class PDFImageHandlerRegistry {
-
-    /** the logger */
-    private static Log log = LogFactory.getLog(PDFImageHandlerRegistry.class);
-
-    private static final Comparator HANDLER_COMPARATOR = new Comparator() {
-        public int compare(Object o1, Object o2) {
-            PDFImageHandler h1 = (PDFImageHandler)o1;
-            PDFImageHandler h2 = (PDFImageHandler)o2;
-            return h1.getPriority() - h2.getPriority();
-        }
-    };
-
-    /** Map containing PDF image handlers for various MIME types */
-    private Map handlers = new java.util.HashMap();
-    /** List containing the same handlers as above but ordered by priority */
-    private List handlerList = new java.util.LinkedList();
+public class PDFImageHandlerRegistry extends AbstractImageHandlerRegistry {
 
-    /** Sorted Set of registered handlers */
-    private ImageFlavor[] supportedFlavors = new ImageFlavor[0];
-    private int handlerRegistrations;
-    private int lastSync;
-
-    /**
-     * Default constructor.
-     */
-    public PDFImageHandlerRegistry() {
-        discoverHandlers();
-    }
-
-    /**
-     * Add an PDFImageHandler. The handler itself is inspected to find out what it supports.
-     * @param classname the fully qualified class name
-     */
-    public void addHandler(String classname) {
-        try {
-            PDFImageHandler handlerInstance
-                = (PDFImageHandler)Class.forName(classname).newInstance();
-            addHandler(handlerInstance);
-        } catch (ClassNotFoundException e) {
-            throw new IllegalArgumentException("Could not find "
-                                               + classname);
-        } catch (InstantiationException e) {
-            throw new IllegalArgumentException("Could not instantiate "
-                                               + classname);
-        } catch (IllegalAccessException e) {
-            throw new IllegalArgumentException("Could not access "
-                                               + classname);
-        } catch (ClassCastException e) {
-            throw new IllegalArgumentException(classname
-                                               + " is not an "
-                                               + PDFImageHandler.class.getName());
-        }
+    /** {@inheritDoc} */
+    public Class getHandlerClass() {
+        return PDFImageHandler.class;
     }
 
-    /**
-     * Add an image handler. The handler itself is inspected to find out what it supports.
-     * @param handler the PDFImageHandler instance
-     */
-    public synchronized void addHandler(PDFImageHandler handler) {
-        Class imageClass = handler.getSupportedImageClass();
-        this.handlers.put(imageClass, handler);
-
-        //Sorted insert
-        ListIterator iter = this.handlerList.listIterator();
-        while (iter.hasNext()) {
-            PDFImageHandler h = (PDFImageHandler)iter.next();
-            if (HANDLER_COMPARATOR.compare(handler, h) < 0) {
-                iter.previous();
-                break;
-            }
-        }
-        iter.add(handler);
-        this.handlerRegistrations++;
-    }
-
-    /**
-     * Returns an PDFImageHandler which handles an specific image type given the MIME type
-     * of the image.
-     * @param img the Image to be handled
-     * @return the PDFImageHandler responsible for handling the image or null if none is available
-     */
-    public PDFImageHandler getHandler(Image img) {
-        return getHandler(img.getClass());
-    }
-
-    /**
-     * Returns an PDFImageHandler which handles an specific image type given the MIME type
-     * of the image.
-     * @param imageClass the Image subclass for which to get a handler
-     * @return the PDFImageHandler responsible for handling the image or null if none is available
-     */
-    protected synchronized PDFImageHandler getHandler(Class imageClass) {
-        PDFImageHandler handler = null;
-        Class cl = imageClass;
-        while (cl != null) {
-            handler = (PDFImageHandler)handlers.get(cl);
-            if (handler != null) {
-                break;
-            }
-            cl = cl.getSuperclass();
-        }
-        return handler;
-    }
-
-    /**
-     * Returns the ordered array of supported image flavors.
-     * @return the array of image flavors
-     */
-    public synchronized ImageFlavor[] getSupportedFlavors() {
-        if (this.lastSync != this.handlerRegistrations) {
-            //Extract all ImageFlavors into a single array
-            List flavors = new java.util.ArrayList();
-            Iterator iter = this.handlerList.iterator();
-            while (iter.hasNext()) {
-                ImageFlavor[] f = ((PDFImageHandler)iter.next()).getSupportedImageFlavors();
-                for (int i = 0; i < f.length; i++) {
-                    flavors.add(f[i]);
-                }
-            }
-            this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]);
-            this.lastSync = this.handlerRegistrations;
-        }
-        return this.supportedFlavors;
-    }
-
-    /**
-     * Discovers PDFImageHandler implementations through the classpath and dynamically
-     * registers them.
-     */
-    private void discoverHandlers() {
-        // add mappings from available services
-        Iterator providers = Service.providers(PDFImageHandler.class);
-        if (providers != null) {
-            while (providers.hasNext()) {
-                PDFImageHandler handler = (PDFImageHandler)providers.next();
-                try {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Dynamically adding PDFImageHandler: "
-                                + handler.getClass().getName());
-                    }
-                    addHandler(handler);
-                } catch (IllegalArgumentException e) {
-                    log.error("Error while adding PDFImageHandler", e);
-                }
-
-            }
-        }
-    }
 }
index 783cb225cff0e85330240914e143d59ad7a99836..edbe9005dfd244e22217bb63d19ac19090cfac2a 100644 (file)
@@ -23,15 +23,14 @@ import java.awt.Point;
 import java.awt.Rectangle;
 import java.io.IOException;
 
-import org.apache.xmlgraphics.image.loader.Image;
-import org.apache.xmlgraphics.image.loader.ImageFlavor;
-import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
-
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFImage;
 import org.apache.fop.pdf.PDFResourceContext;
 import org.apache.fop.pdf.PDFXObject;
 import org.apache.fop.render.RendererContext;
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
 
 /**
  * PDFImageHandler implementation which handles RenderedImage instances.
@@ -43,6 +42,11 @@ public class PDFImageHandlerRenderedImage implements PDFImageHandler {
         ImageFlavor.RENDERED_IMAGE
     };
 
+    private static final Class[] CLASSES = new Class[] {
+        ImageRendered.class,
+    };
+
+
     /** {@inheritDoc} */
     public PDFXObject generateImage(RendererContext context, Image image,
             Point origin, Rectangle pos)
@@ -72,8 +76,8 @@ public class PDFImageHandlerRenderedImage implements PDFImageHandler {
     }
 
     /** {@inheritDoc} */
-    public Class getSupportedImageClass() {
-        return ImageRendered.class;
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
     }
 
     /** {@inheritDoc} */
index d111e733fb4c48177428a2f4096339c49fb57797..069fef172f1fcca20023cb078fda036ad125812a 100644 (file)
@@ -24,14 +24,12 @@ import java.awt.Rectangle;
 import java.io.IOException;
 import java.util.Map;
 
-import org.w3c.dom.Document;
-
+import org.apache.fop.pdf.PDFXObject;
+import org.apache.fop.render.RendererContext;
 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.w3c.dom.Document;
 
 /**
  * PDFImageHandler implementation which handles XML-based images.
@@ -42,6 +40,10 @@ public class PDFImageHandlerXML implements PDFImageHandler {
         ImageFlavor.XML_DOM,
     };
 
+    private static final Class[] CLASSES = new Class[] {
+        ImageXMLDOM.class,
+    };
+
     /** {@inheritDoc} */
     public PDFXObject generateImage(RendererContext context, Image image,
             Point origin, Rectangle pos)
@@ -62,8 +64,8 @@ public class PDFImageHandlerXML implements PDFImageHandler {
     }
 
     /** {@inheritDoc} */
-    public Class getSupportedImageClass() {
-        return ImageXMLDOM.class;
+    public Class[] getSupportedImageClasses() {
+        return CLASSES;
     }
 
     /** {@inheritDoc} */
index 0eba2fe91e93cfc45bfa35168f6d78d665d13eb9..ba3d8919531f3c186f12f4b430f958e79e98c599 100644 (file)
@@ -1658,7 +1658,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
                         info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext);
 
             //First check for a dynamically registered handler
-            PDFImageHandler handler = imageHandlerRegistry.getHandler(img.getClass());
+            PDFImageHandler handler
+                = (PDFImageHandler)imageHandlerRegistry.getHandler(img.getClass());
             if (handler != null) {
                 if (log.isDebugEnabled()) {
                     log.debug("Using PDFImageHandler: " + handler.getClass().getName());
index 7c525dbf75d226b647493a48110ef764b74228d2..a318c64651647da2198a4255a996da3f27d8f049 100644 (file)
 
 package org.apache.fop.render.ps;
 
+import java.awt.Color;
 import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.font.TextAttribute;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
-/* java.awt.Font is not imported to avoid confusion with
-   org.apache.fop.fonts.Font */
-
+import java.io.IOException;
 import java.text.AttributedCharacterIterator;
 import java.text.CharacterIterator;
-import java.awt.font.TextAttribute;
-import java.awt.Shape;
-import java.awt.Paint;
-import java.awt.Stroke;
-import java.awt.Color;
-import java.io.IOException;
-import java.util.List;
 import java.util.Iterator;
+import java.util.List;
 
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.TextPainter;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.Mark;
+import org.apache.batik.gvt.text.TextPaintInfo;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontTriplet;
-
 import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
-import org.apache.xmlgraphics.java2d.TextHandler;
-
-import org.apache.batik.dom.svg.SVGOMTextElement;
-import org.apache.batik.gvt.text.Mark;
-import org.apache.batik.gvt.TextPainter;
-import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
-import org.apache.batik.gvt.text.TextPaintInfo;
-import org.apache.batik.gvt.font.GVTFontFamily;
-import org.apache.batik.gvt.renderer.StrokingTextPainter;
 
 
 /**
@@ -74,8 +68,8 @@ public class PSTextPainter implements TextPainter {
     /** the logger for this class */
     protected Log log = LogFactory.getLog(PSTextPainter.class);
 
-    private NativeTextHandler nativeTextHandler;
-    private FontInfo fontInfo;
+    private final NativeTextHandler nativeTextHandler;
+    private final FontInfo fontInfo;
 
     /**
      * Use the stroking text painter to get the bounds and shape.
@@ -317,7 +311,7 @@ public class PSTextPainter implements TextPainter {
         }
 
         drawPrimitiveString(g2d, loc, font, txt, tx);
-        loc.setLocation(loc.getX() + (double)advance, loc.getY());
+        loc.setLocation(loc.getX() + advance, loc.getY());
         return loc;
     }
 
@@ -422,7 +416,7 @@ public class PSTextPainter implements TextPainter {
             fStyle |= java.awt.Font.ITALIC;
         }
         return new java.awt.Font(font.getFontName(), fStyle,
-                             (int)(font.getFontSize() / 1000));
+                             (font.getFontSize() / 1000));
     }
 
     private float getStringWidth(String str, Font font) {
diff --git a/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java b/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java
new file mode 100644 (file)
index 0000000..be1c3c1
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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.svg;
+
+import java.awt.geom.AffineTransform;
+import java.lang.reflect.Constructor;
+
+import org.apache.batik.bridge.Bridge;
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.DocumentLoader;
+import org.apache.batik.bridge.UserAgent;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.ImageSessionContext;
+
+public abstract class AbstractFOPBridgeContext extends BridgeContext {
+
+    /** The font list. */
+    protected final FontInfo fontInfo;
+
+    protected final ImageManager imageManager;
+    protected final ImageSessionContext imageSessionContext;
+
+    protected final AffineTransform linkTransform;
+
+    /**
+     * Constructs a new bridge context.
+     * @param userAgent the user agent
+     * @param loader the Document Loader to use for referenced documents.
+     * @param fontInfo the font list for the text painter, may be null
+     *                 in which case text is painted as shapes
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
+     */
+    public AbstractFOPBridgeContext(UserAgent userAgent,
+                            DocumentLoader loader,
+                            FontInfo fontInfo,
+                            ImageManager imageManager,
+                            ImageSessionContext imageSessionContext,
+                            AffineTransform linkTransform) {
+        super(userAgent, loader);
+        this.fontInfo = fontInfo;
+        this.imageManager = imageManager;
+        this.imageSessionContext = imageSessionContext;
+        this.linkTransform = linkTransform;
+    }
+
+    /**
+     * Constructs a new bridge context.
+     * @param userAgent the user agent
+     * @param fontInfo the font list for the text painter, may be null
+     *                 in which case text is painted as shapes
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
+     */
+    public AbstractFOPBridgeContext(UserAgent userAgent,
+                            FontInfo fontInfo,
+                            ImageManager imageManager,
+                            ImageSessionContext imageSessionContext,
+                            AffineTransform linkTransform) {
+        super(userAgent);
+        this.fontInfo = fontInfo;
+        this.imageManager = imageManager;
+        this.imageSessionContext = imageSessionContext;
+        this.linkTransform = linkTransform;
+    }
+
+    /**
+     * Constructs a new bridge context.
+     * @param userAgent the user agent
+     * @param fontInfo the font list for the text painter, may be null
+     *                 in which case text is painted as shapes
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
+     */
+    public AbstractFOPBridgeContext(UserAgent userAgent,
+                            FontInfo fontInfo,
+                            ImageManager imageManager,
+                            ImageSessionContext imageSessionContext) {
+        this(userAgent, fontInfo, imageManager, imageSessionContext, null);
+    }
+
+    /**
+     * Returns the ImageManager to be used by the ImageElementBridge.
+     * @return the image manager
+     */
+    public ImageManager getImageManager() {
+        return this.imageManager;
+    }
+
+    /**
+     * Returns the ImageSessionContext to be used by the ImageElementBridge.
+     * @return the image session context
+     */
+    public ImageSessionContext getImageSessionContext() {
+        return this.imageSessionContext;
+    }
+
+    protected void putElementBridgeConditional(String className, String testFor) {
+        try {
+            Class.forName(testFor);
+            //if we get here the test class is available
+
+            Class clazz = Class.forName(className);
+            Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class});
+            putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo}));
+        } catch (Throwable t) {
+            //simply ignore (bridges instantiated over this method are optional)
+        }
+    }
+
+    // Make sure any 'sub bridge contexts' also have our bridges.
+    //TODO There's no matching method in the super-class here
+    public abstract BridgeContext createBridgeContext();
+
+}
diff --git a/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java b/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java
new file mode 100644 (file)
index 0000000..31895ce
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * 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.svg;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.SVGImageElementBridge;
+import org.apache.batik.gvt.AbstractGraphicsNode;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.util.ParsedURL;
+import org.apache.xmlgraphics.image.loader.Image;
+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;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
+import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
+import org.w3c.dom.Element;
+import org.w3c.dom.svg.SVGDocument;
+
+/**
+ * Bridge class for the &lt;image> element when jpeg images.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+public abstract class AbstractFOPImageElementBridge extends SVGImageElementBridge {
+
+    /**
+     * Constructs a new bridge for the &lt;image> element.
+     */
+    public AbstractFOPImageElementBridge() { }
+
+    /**
+     * Create the raster image node.
+     * THis checks if it is a jpeg file and creates a jpeg node
+     * so the jpeg can be inserted directly into the pdf document.
+     * @param ctx the bridge context
+     * @param imageElement the svg element for the image
+     * @param purl the parsed url for the image resource
+     * @return a new graphics node
+     */
+    protected GraphicsNode createImageGraphicsNode
+                (BridgeContext ctx, Element imageElement, ParsedURL purl) {
+        AbstractFOPBridgeContext bridgeCtx = (AbstractFOPBridgeContext)ctx;
+
+        ImageManager manager = bridgeCtx.getImageManager();
+        ImageSessionContext sessionContext = bridgeCtx.getImageSessionContext();
+        try {
+            ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext);
+            ImageFlavor[] supportedFlavors = getSupportedFlavours();
+            Image image = manager.getImage(info, supportedFlavors, sessionContext);
+
+            //TODO color profile overrides aren't handled, yet!
+            //ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx);
+            AbstractGraphicsNode specializedNode = null;
+            if (image instanceof ImageXMLDOM) {
+                ImageXMLDOM xmlImage = (ImageXMLDOM)image;
+                if (xmlImage.getDocument() instanceof SVGDocument) {
+                    return createSVGImageNode(ctx, imageElement,
+                            (SVGDocument)xmlImage.getDocument());
+                } else {
+                    //Convert image to Graphics2D
+                    image = manager.convertImage(xmlImage,
+                            new ImageFlavor[] {ImageFlavor.GRAPHICS2D});
+                }
+            }
+            if (image instanceof ImageRawJPEG) {
+                specializedNode = createLoaderImageNode(image, ctx, imageElement, purl);
+            } else if (image instanceof ImageRawCCITTFax) {
+                specializedNode = createLoaderImageNode(image, ctx, imageElement, purl);
+            } else if (image instanceof ImageGraphics2D) {
+                ImageGraphics2D g2dImage = (ImageGraphics2D)image;
+                specializedNode = new Graphics2DNode(g2dImage);
+            } else {
+                ctx.getUserAgent().displayError(
+                        new ImageException("Cannot convert an image to a usable format: " + purl));
+            }
+
+            Rectangle2D imgBounds = getImageBounds(ctx, imageElement);
+            Rectangle2D bounds = specializedNode.getPrimitiveBounds();
+            float [] vb = new float[4];
+            vb[0] = 0; // x
+            vb[1] = 0; // y
+            vb[2] = (float) bounds.getWidth(); // width
+            vb[3] = (float) bounds.getHeight(); // height
+
+            // handles the 'preserveAspectRatio', 'overflow' and 'clip'
+            // and sets the appropriate AffineTransform to the image node
+            initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds);
+            return specializedNode;
+        } catch (Exception e) {
+            ctx.getUserAgent().displayError(e);
+        }
+
+        return superCreateGraphicsNode(ctx, imageElement, purl);
+    }
+
+    /**
+     * Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode.
+     * @param ctx the bridge context
+     * @param imageElement the image element
+     * @param purl the parsed URL
+     * @return the newly created graphics node
+     * @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element)
+     */
+    protected GraphicsNode superCreateGraphicsNode
+            (BridgeContext ctx, Element imageElement, ParsedURL purl) {
+        return super.createImageGraphicsNode(ctx, imageElement, purl);
+    }
+
+    /**
+     * Returns an array of supported image flavours
+     *
+     * @return an array of supported image flavours
+     */
+    protected abstract ImageFlavor[] getSupportedFlavours();
+
+    /**
+     * Creates a loader image node implementation
+     * @param purl the parsed url
+     * @param imageElement the image element
+     * @param ctx the batik bridge context
+     * @param image the image
+     *
+     * @return a loader image node implementation
+     */
+    protected LoaderImageNode createLoaderImageNode(
+            Image image, BridgeContext ctx, Element imageElement, ParsedURL purl) {
+        return new LoaderImageNode(image, ctx, imageElement, purl);
+    }
+
+    /**
+     * An image node for natively handled Image instance.
+     * This holds a natively handled image so that it can be drawn into
+     * the PDFGraphics2D.
+     */
+    public class LoaderImageNode extends AbstractGraphicsNode {
+
+        protected final Image image;
+        protected final BridgeContext ctx;
+        protected final Element imageElement;
+        protected final ParsedURL purl;
+        protected GraphicsNode origGraphicsNode = null;
+
+        /**
+         * Create a new image node for drawing natively handled images
+         * into PDF graphics.
+         * @param image the JPEG image
+         * @param ctx the bridge context
+         * @param imageElement the SVG image element
+         * @param purl the URL to the image
+         */
+        public LoaderImageNode(Image image, BridgeContext ctx,
+                           Element imageElement, ParsedURL purl) {
+            this.image = image;
+            this.ctx  = ctx;
+            this.imageElement = imageElement;
+            this.purl = purl;
+        }
+
+        /** {@inheritDoc} */
+        public Shape getOutline() {
+            return getPrimitiveBounds();
+        }
+
+        /** {@inheritDoc} */
+        public void primitivePaint(Graphics2D g2d) {
+            if (g2d instanceof NativeImageHandler) {
+                NativeImageHandler nativeImageHandler = (NativeImageHandler) g2d;
+                float x = 0;
+                float y = 0;
+                try {
+                    float width = image.getSize().getWidthPx();
+                    float height = image.getSize().getHeightPx();
+                    nativeImageHandler.addNativeImage(image, x, y, width, height);
+                } catch (Exception e) {
+                    ctx.getUserAgent().displayError(e);
+                }
+            } else {
+                // Not going directly into PDF so use
+                // original implementation so filters etc work.
+                if (origGraphicsNode == null) {
+                    // Haven't constructed base class Graphics Node,
+                    // so do so now.
+                    origGraphicsNode
+                        = superCreateGraphicsNode(ctx,  imageElement, purl);
+                }
+                origGraphicsNode.primitivePaint(g2d);
+            }
+        }
+
+        /** {@inheritDoc} */
+        public Rectangle2D getGeometryBounds() {
+            return getPrimitiveBounds();
+        }
+
+        /** {@inheritDoc} */
+        public Rectangle2D getPrimitiveBounds() {
+            return new Rectangle2D.Double(0, 0,
+                       image.getSize().getWidthPx(),
+                       image.getSize().getHeightPx());
+        }
+
+        /** {@inheritDoc} */
+        public Rectangle2D getSensitiveBounds() {
+            //No interactive features, just return primitive bounds
+            return getPrimitiveBounds();
+        }
+
+    }
+
+    /**
+     * A node that holds a Graphics2D image.
+     */
+    public class Graphics2DNode extends AbstractGraphicsNode {
+
+        private final ImageGraphics2D image;
+
+        /**
+         * Create a new Graphics2D node.
+         * @param g2d the Graphics2D image
+         */
+        public Graphics2DNode(ImageGraphics2D g2d) {
+            this.image = g2d;
+        }
+
+        /** {@inheritDoc} */
+        public Shape getOutline() {
+            return getPrimitiveBounds();
+        }
+
+        /** {@inheritDoc} */
+        public void primitivePaint(Graphics2D g2d) {
+            int width = image.getSize().getWidthPx();
+            int height = image.getSize().getHeightPx();
+            Rectangle2D area = new Rectangle2D.Double(0, 0, width, height);
+            Graphics2DImagePainter painter = image.getGraphics2DImagePainter();
+            painter.paint(g2d, area);
+        }
+
+        /** {@inheritDoc} */
+        public Rectangle2D getGeometryBounds() {
+            return getPrimitiveBounds();
+        }
+
+        /** {@inheritDoc} */
+        public Rectangle2D getPrimitiveBounds() {
+            return new Rectangle2D.Double(0, 0,
+                    image.getSize().getWidthPx(),
+                    image.getSize().getHeightPx());
+        }
+
+        /** {@inheritDoc} */
+        public Rectangle2D getSensitiveBounds() {
+            //No interactive features, just return primitive bounds
+            return getPrimitiveBounds();
+        }
+
+    }
+}
diff --git a/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java b/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java
new file mode 100644 (file)
index 0000000..53b8e2a
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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.svg;
+
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.SVGTextElementBridge;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.TextPainter;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Bridge class for the &lt;text> element.
+ * This bridge will use the direct text painter if the text
+ * for the element is simple.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+public abstract class AbstractFOPTextElementBridge extends SVGTextElementBridge {
+
+    /** text painter */
+    protected TextPainter textPainter;
+
+    /**
+     * Main constructor
+     *
+     * @param textPainter the text painter
+     */
+    public AbstractFOPTextElementBridge(TextPainter textPainter) {
+        this.textPainter = textPainter;
+    }
+
+    /**
+     * Create a text element bridge.
+     *
+     * This set the text painter on the node if the text is simple.
+     * @param ctx the bridge context
+     * @param e the svg element
+     * @return the text graphics node created by the super class
+     */
+    public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
+        GraphicsNode node = super.createGraphicsNode(ctx, e);
+        if (node != null) {
+            //Set our own text painter
+            ((TextNode)node).setTextPainter(textPainter);
+        }
+        return node;
+    }
+
+    /**
+     * Check if text element contains simple text.
+     * This checks the children of the text element to determine
+     * if the text is simple. The text is simple if it can be rendered
+     * with basic text drawing algorithms. This means there are no
+     * alternate characters, the font is known and there are no effects
+     * applied to the text.
+     *
+     * @param ctx the bridge context
+     * @param element the svg text element
+     * @param node the graphics node
+     * @return true if this text is simple of false if it cannot be
+     *         easily rendered using normal drawString on the Graphics2D
+     */
+    protected boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
+        for (Node n = element.getFirstChild();
+                n != null;
+                n = n.getNextSibling()) {
+
+            switch (n.getNodeType()) {
+            case Node.ELEMENT_NODE:
+
+                if (n.getLocalName().equals(SVG_TSPAN_TAG)
+                        || n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
+                    return false;
+                } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
+                    return false;
+                } else if (n.getLocalName().equals(SVG_TREF_TAG)) {
+                    return false;
+                }
+                break;
+            case Node.TEXT_NODE:
+            case Node.CDATA_SECTION_NODE:
+            default:
+            }
+        }
+
+        /*if (CSSUtilities.convertFilter(element, node, ctx) != null) {
+            return false;
+        }*/
+
+        return true;
+    }
+
+}
+
diff --git a/src/java/org/apache/fop/svg/NativeImageHandler.java b/src/java/org/apache/fop/svg/NativeImageHandler.java
new file mode 100644 (file)
index 0000000..8e74cba
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.svg;
+
+public interface NativeImageHandler {
+
+    /**
+     * Add a natively handled image directly to the document.
+     * This is used by the ImageElementBridge to draw a natively handled image
+     * (like JPEG or CCITT images)
+     * directly into the document rather than converting the image into
+     * a bitmap and increasing the size.
+     *
+     * @param image the image to draw
+     * @param x the x position
+     * @param y the y position
+     * @param width the width to draw the image
+     * @param height the height to draw the image
+     */
+    void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
+                             float width, float height);
+
+}
index 6aa29cfa13209962ef7e56f979e3059c97d8574e..364c7a6f3a0bf7ff8e7fb2a6e09a48f677941b6e 100644 (file)
 package org.apache.fop.svg;
 
 import java.awt.geom.AffineTransform;
-import java.lang.reflect.Constructor;
 
-import org.apache.batik.bridge.Bridge;
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.DocumentLoader;
+import org.apache.batik.bridge.SVGTextElementBridge;
 import org.apache.batik.bridge.UserAgent;
+import org.apache.batik.gvt.TextPainter;
 import org.apache.fop.fonts.FontInfo;
-
 import org.apache.xmlgraphics.image.loader.ImageManager;
 import org.apache.xmlgraphics.image.loader.ImageSessionContext;
 
-
 /**
  * BridgeContext which registers the custom bridges for PDF output.
  */
-public class PDFBridgeContext extends BridgeContext {
-
-    /** The font list. */
-    private final FontInfo fontInfo;
-
-    private final ImageManager imageManager;
-    private final ImageSessionContext imageSessionContext;
-
-    private AffineTransform linkTransform;
+public class PDFBridgeContext extends AbstractFOPBridgeContext {
 
     /**
      * Constructs a new bridge context.
@@ -53,18 +43,16 @@ public class PDFBridgeContext extends BridgeContext {
      *                 in which case text is painted as shapes
      * @param linkTransform AffineTransform to properly place links,
      *                      may be null
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
      */
-    public PDFBridgeContext(UserAgent userAgent,
-                            DocumentLoader loader,
-                            FontInfo fontInfo,
-                            ImageManager imageManager,
-                            ImageSessionContext imageSessionContext,
-                            AffineTransform linkTransform) {
-        super(userAgent, loader);
-        this.fontInfo = fontInfo;
-        this.imageManager = imageManager;
-        this.imageSessionContext = imageSessionContext;
-        this.linkTransform = linkTransform;
+    public PDFBridgeContext(UserAgent userAgent, DocumentLoader documentLoader,
+            FontInfo fontInfo, ImageManager imageManager,
+            ImageSessionContext imageSessionContext,
+            AffineTransform linkTransform) {
+        super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform);
     }
 
     /**
@@ -72,19 +60,12 @@ public class PDFBridgeContext extends BridgeContext {
      * @param userAgent the user agent
      * @param fontInfo the font list for the text painter, may be null
      *                 in which case text is painted as shapes
-     * @param linkTransform AffineTransform to properly place links,
-     *                      may be null
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
      */
-    public PDFBridgeContext(UserAgent userAgent,
-                            FontInfo fontInfo,
-                            ImageManager imageManager,
-                            ImageSessionContext imageSessionContext,
-                            AffineTransform linkTransform) {
-        super(userAgent);
-        this.fontInfo = fontInfo;
-        this.imageManager = imageManager;
-        this.imageSessionContext = imageSessionContext;
-        this.linkTransform = linkTransform;
+    public PDFBridgeContext(UserAgent userAgent, FontInfo fontInfo,
+            ImageManager imageManager, ImageSessionContext imageSessionContext) {
+        super(userAgent, fontInfo, imageManager, imageSessionContext);
     }
 
     /**
@@ -92,41 +73,15 @@ public class PDFBridgeContext extends BridgeContext {
      * @param userAgent the user agent
      * @param fontInfo the font list for the text painter, may be null
      *                 in which case text is painted as shapes
+     * @param imageManager an image manager
+     * @param imageSessionContext an image session context
+     * @param linkTransform AffineTransform to properly place links,
+     *                      may be null
      */
-    public PDFBridgeContext(UserAgent userAgent,
-                            FontInfo fontInfo,
-                            ImageManager imageManager,
-                            ImageSessionContext imageSessionContext) {
-        this(userAgent, fontInfo, imageManager, imageSessionContext, null);
-    }
-
-    /**
-     * Returns the ImageManager to be used by the ImageElementBridge.
-     * @return the image manager
-     */
-    public ImageManager getImageManager() {
-        return this.imageManager;
-    }
-
-    /**
-     * Returns the ImageSessionContext to be used by the ImageElementBridge.
-     * @return the image session context
-     */
-    public ImageSessionContext getImageSessionContext() {
-        return this.imageSessionContext;
-    }
-
-    private void putPDFElementBridgeConditional(String className, String testFor) {
-        try {
-            Class.forName(testFor);
-            //if we get here the test class is available
-
-            Class clazz = Class.forName(className);
-            Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class});
-            putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo}));
-        } catch (Throwable t) {
-            //simply ignore (bridges instantiated over this method are optional)
-        }
+    public PDFBridgeContext(SVGUserAgent userAgent, FontInfo fontInfo,
+            ImageManager imageManager, ImageSessionContext imageSessionContext,
+            AffineTransform linkTransform) {
+        super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform);
     }
 
     /** {@inheritDoc} */
@@ -134,23 +89,24 @@ public class PDFBridgeContext extends BridgeContext {
         super.registerSVGBridges();
 
         if (fontInfo != null) {
-            PDFTextElementBridge textElementBridge = new PDFTextElementBridge(fontInfo);
+            TextPainter textPainter = new PDFTextPainter(fontInfo);
+            SVGTextElementBridge textElementBridge = new PDFTextElementBridge(textPainter);
             putBridge(textElementBridge);
 
             //Batik flow text extension (may not always be available)
             //putBridge(new PDFBatikFlowTextElementBridge(fontInfo);
-            putPDFElementBridgeConditional(
+            putElementBridgeConditional(
                     "org.apache.fop.svg.PDFBatikFlowTextElementBridge",
                     "org.apache.batik.extension.svg.BatikFlowTextElementBridge");
 
             //SVG 1.2 flow text support
             //putBridge(new PDFSVG12TextElementBridge(fontInfo)); //-->Batik 1.7
-            putPDFElementBridgeConditional(
+            putElementBridgeConditional(
                     "org.apache.fop.svg.PDFSVG12TextElementBridge",
                     "org.apache.batik.bridge.svg12.SVG12TextElementBridge");
 
             //putBridge(new PDFSVGFlowRootElementBridge(fontInfo));
-            putPDFElementBridgeConditional(
+            putElementBridgeConditional(
                     "org.apache.fop.svg.PDFSVGFlowRootElementBridge",
                     "org.apache.batik.bridge.svg12.SVGFlowRootElementBridge");
         }
index cafb5f4d38b741530e0fdde89dd1d0460528eaff..f8a0bd415169145ede6209ec3521b0f7d5b00ae3 100644 (file)
@@ -100,7 +100,7 @@ import org.apache.xmlgraphics.java2d.GraphicContext;
  * @version $Id$
  * @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D
  */
-public class PDFGraphics2D extends AbstractGraphics2D {
+public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHandler {
 
     private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();
 
@@ -414,7 +414,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
      * @param width the width to draw the image
      * @param height the height to draw the image
      */
-    void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
+    public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
                              float width, float height) {
         preparePainting();
         String key = image.getInfo().getOriginalURI();
@@ -521,7 +521,8 @@ public class PDFGraphics2D extends AbstractGraphics2D {
             g.clip(new Rectangle(0, 0, imageWidth, imageHeight));
             g.setComposite(gc.getComposite());
 
-            if (!g.drawImage(img, 0, 0, imageWidth, imageHeight, observer)) {
+            boolean drawn = g.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
+            if (!drawn) {
                 return false;
             }
             g.dispose();
index 7eb89d2b15918b1faa43a44ff5791d5e954d1613..1a17aa41032b3db1efb8aacc604dfc36d2c6cd71 100644 (file)
 
 package org.apache.fop.svg;
 
-import java.awt.Graphics2D;
-import java.awt.Shape;
-import java.awt.geom.Rectangle2D;
-
-import org.w3c.dom.Element;
-import org.w3c.dom.svg.SVGDocument;
-
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.SVGImageElementBridge;
-import org.apache.batik.gvt.AbstractGraphicsNode;
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.util.ParsedURL;
-
-import org.apache.xmlgraphics.image.loader.Image;
-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;
-import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
-import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
 
 /**
- * Bridge class for the &lt;image> element when jpeg images.
+ * PDF Image Element Bridge class for the &lt;image> element when jpeg images.
  *
  * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
  */
-public class PDFImageElementBridge extends SVGImageElementBridge {
+public class PDFImageElementBridge extends AbstractFOPImageElementBridge {
 
     /**
      * Constructs a new bridge for the &lt;image> element.
@@ -60,210 +38,9 @@ public class PDFImageElementBridge extends SVGImageElementBridge {
                                                 ImageFlavor.RAW_CCITTFAX,
                                                 ImageFlavor.GRAPHICS2D,
                                                 ImageFlavor.XML_DOM};
-    /**
-     * Create the raster image node.
-     * THis checks if it is a jpeg file and creates a jpeg node
-     * so the jpeg can be inserted directly into the pdf document.
-     * @param ctx the bridge context
-     * @param imageElement the svg element for the image
-     * @param purl the parsed url for the image resource
-     * @return a new graphics node
-     */
-    protected GraphicsNode createImageGraphicsNode
-                (BridgeContext ctx, Element imageElement, ParsedURL purl) {
-        PDFBridgeContext pdfCtx = (PDFBridgeContext)ctx;
-
-        ImageManager manager = pdfCtx.getImageManager();
-        ImageSessionContext sessionContext = pdfCtx.getImageSessionContext();
-        try {
-            ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext);
-            Image image = manager.getImage(info, supportedFlavors, sessionContext);
-
-            //TODO color profile overrides aren't handled, yet!
-            //ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx);
-            AbstractGraphicsNode specializedNode = null;
-            if (image instanceof ImageXMLDOM) {
-                ImageXMLDOM xmlImage = (ImageXMLDOM)image;
-                if (xmlImage.getDocument() instanceof SVGDocument) {
-                    return createSVGImageNode(ctx, imageElement,
-                            (SVGDocument)xmlImage.getDocument());
-                } else {
-                    //Convert image to Graphics2D
-                    image = manager.convertImage(xmlImage,
-                            new ImageFlavor[] {ImageFlavor.GRAPHICS2D});
-                }
-            }
-            if (image instanceof ImageRawJPEG) {
-                specializedNode = new LoaderImageNode(image, ctx, imageElement, purl);
-            } else if (image instanceof ImageRawCCITTFax) {
-                specializedNode = new LoaderImageNode(image, ctx, imageElement, purl);
-            } else if (image instanceof ImageGraphics2D) {
-                ImageGraphics2D g2dImage = (ImageGraphics2D)image;
-                specializedNode = new Graphics2DNode(g2dImage);
-            } else {
-                ctx.getUserAgent().displayError(
-                        new ImageException("Cannot convert an image to a usable format: " + purl));
-            }
-
-            Rectangle2D imgBounds = getImageBounds(ctx, imageElement);
-            Rectangle2D bounds = specializedNode.getPrimitiveBounds();
-            float [] vb = new float[4];
-            vb[0] = 0; // x
-            vb[1] = 0; // y
-            vb[2] = (float) bounds.getWidth(); // width
-            vb[3] = (float) bounds.getHeight(); // height
-
-            // handles the 'preserveAspectRatio', 'overflow' and 'clip'
-            // and sets the appropriate AffineTransform to the image node
-            initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds);
-            return specializedNode;
-        } catch (Exception e) {
-            ctx.getUserAgent().displayError(e);
-        }
-
-        return superCreateGraphicsNode(ctx, imageElement, purl);
-    }
-
-    /**
-     * Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode.
-     * @param ctx the bridge context
-     * @param imageElement the image element
-     * @param purl the parsed URL
-     * @return the newly created graphics node
-     * @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element)
-     */
-    protected GraphicsNode superCreateGraphicsNode
-            (BridgeContext ctx, Element imageElement, ParsedURL purl) {
-        return super.createImageGraphicsNode(ctx, imageElement, purl);
-    }
-
-
-    /**
-     * An image node for natively handled Image instance.
-     * This holds a natively handled image so that it can be drawn into
-     * the PDFGraphics2D.
-     */
-    public class LoaderImageNode extends AbstractGraphicsNode {
-
-        private Image image;
-        private BridgeContext ctx;
-        private Element imageElement;
-        private ParsedURL purl;
-        private GraphicsNode origGraphicsNode = null;
-
-        /**
-         * Create a new image node for drawing natively handled images
-         * into PDF graphics.
-         * @param image the JPEG image
-         * @param ctx the bridge context
-         * @param imageElement the SVG image element
-         * @param purl the URL to the image
-         */
-        public LoaderImageNode(Image image, BridgeContext ctx,
-                           Element imageElement, ParsedURL purl) {
-            this.image = image;
-            this.ctx  = ctx;
-            this.imageElement = imageElement;
-            this.purl = purl;
-        }
-
-        /** {@inheritDoc} */
-        public Shape getOutline() {
-            return getPrimitiveBounds();
-        }
-
-        /** {@inheritDoc} */
-        public void primitivePaint(Graphics2D g2d) {
-            if (g2d instanceof PDFGraphics2D) {
-                PDFGraphics2D pdfg = (PDFGraphics2D) g2d;
-                float x = 0;
-                float y = 0;
-                try {
-                    float width = image.getSize().getWidthPx();
-                    float height = image.getSize().getHeightPx();
-                    pdfg.addNativeImage(image, x, y, width, height);
-                } catch (Exception e) {
-                    ctx.getUserAgent().displayError(e);
-                }
-            } else {
-                // Not going directly into PDF so use
-                // original implementation so filters etc work.
-                if (origGraphicsNode == null) {
-                    // Haven't constructed baseclass Graphics Node,
-                    // so do so now.
-                    origGraphicsNode
-                        = PDFImageElementBridge.this.superCreateGraphicsNode
-                            (ctx,  imageElement, purl);
-                }
-                origGraphicsNode.primitivePaint(g2d);
-            }
-        }
-
-        /** {@inheritDoc} */
-        public Rectangle2D getGeometryBounds() {
-            return getPrimitiveBounds();
-        }
-
-        /** {@inheritDoc} */
-        public Rectangle2D getPrimitiveBounds() {
-            return new Rectangle2D.Double(0, 0,
-                       image.getSize().getWidthPx(),
-                       image.getSize().getHeightPx());
-        }
-
-        /** {@inheritDoc} */
-        public Rectangle2D getSensitiveBounds() {
-            //No interactive features, just return primitive bounds
-            return getPrimitiveBounds();
-        }
-
-    }
-
-    /**
-     * A node that holds a Graphics2D image.
-     */
-    public class Graphics2DNode extends AbstractGraphicsNode {
-
-        private ImageGraphics2D image;
-
-        /**
-         * Create a new Graphics2D node.
-         * @param g2d the Graphics2D image
-         */
-        public Graphics2DNode(ImageGraphics2D g2d) {
-            this.image = g2d;
-        }
-
-        /** {@inheritDoc} */
-        public Shape getOutline() {
-            return getPrimitiveBounds();
-        }
-
-        /** {@inheritDoc} */
-        public void primitivePaint(Graphics2D g2d) {
-            int width = image.getSize().getWidthPx();
-            int height = image.getSize().getHeightPx();
-            Rectangle2D area = new Rectangle2D.Double(0, 0, width, height);
-            image.getGraphics2DImagePainter().paint(g2d, area);
-        }
-
-        /** {@inheritDoc} */
-        public Rectangle2D getGeometryBounds() {
-            return getPrimitiveBounds();
-        }
-
-        /** {@inheritDoc} */
-        public Rectangle2D getPrimitiveBounds() {
-            return new Rectangle2D.Double(0, 0,
-                    image.getSize().getWidthPx(),
-                    image.getSize().getHeightPx());
-        }
-
-        /** {@inheritDoc} */
-        public Rectangle2D getSensitiveBounds() {
-            //No interactive features, just return primitive bounds
-            return getPrimitiveBounds();
-        }
 
+    /** {@inheritDoc} */
+    protected ImageFlavor[] getSupportedFlavours() {
+        return supportedFlavors;
     }
 }
index 4c11aa97e09b37bd487169ccb32a399e308dd56e..c983d2b4522d1fda0355d6caa7cf4e473f7ad6c0 100644 (file)
 
 package org.apache.fop.svg;
 
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.SVGTextElementBridge;
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.gvt.TextNode;
 import org.apache.batik.gvt.TextPainter;
-import org.apache.fop.fonts.FontInfo;
-import org.w3c.dom.Element;
 
 /**
  * Bridge class for the &lt;text> element.
@@ -34,41 +28,15 @@ import org.w3c.dom.Element;
  *
  * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
  */
-public class PDFTextElementBridge extends SVGTextElementBridge {
-
-    private PDFTextPainter pdfTextPainter;
+public class PDFTextElementBridge extends AbstractFOPTextElementBridge {
 
     /**
      * Constructs a new bridge for the &lt;text> element.
-     * @param fi the font information
-     */
-    public PDFTextElementBridge(FontInfo fi) {
-        pdfTextPainter = new PDFTextPainter(fi);
-    }
-
-    /**
-     * Create a text element bridge.
-     * This set the text painter on the node if the text is simple.
-     * @param ctx the bridge context
-     * @param e the svg element
-     * @return the text graphics node created by the super class
+     *
+     * @param textPainter the text painter to use
      */
-    public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
-        GraphicsNode node = super.createGraphicsNode(ctx, e);
-        if (node != null) {
-            //Set our own text painter
-            ((TextNode)node).setTextPainter(getTextPainter());
-        }
-        return node;
+    public PDFTextElementBridge(TextPainter textPainter) {
+        super(textPainter);
     }
-
-    /**
-     * Returns the TextPainter instance used by this bridge.
-     * @return the text painter
-     */
-    public TextPainter getTextPainter() {
-        return pdfTextPainter;
-    }
-
 }
 
index 06fea54cc0f80be96d5c9a6281ac4b4137f83702..8a0feb3a234a1cb6fa6bff16abff6fd4d49fa49f 100644 (file)
@@ -43,7 +43,6 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter;
 import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
 import org.apache.batik.gvt.text.TextPaintInfo;
 import org.apache.batik.gvt.text.TextSpanLayout;
-
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontTriplet;
@@ -63,8 +62,8 @@ public class PDFTextPainter extends StrokingTextPainter {
 
     private static final boolean DEBUG = false;
 
-    private boolean strokeText = false;
-    private FontInfo fontInfo;
+    private final boolean strokeText = false;
+    private final FontInfo fontInfo;
 
     /**
      * Create a new PDF text painter with the given font information.
@@ -280,7 +279,7 @@ public class PDFTextPainter extends StrokingTextPainter {
         Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);
 
         String style = ((posture != null) && (posture.floatValue() > 0.0))
-                       ? "italic" : "normal";
+                       ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
         int weight = ((taWeight != null)
                        &&  (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
                        : Font.WEIGHT_NORMAL;