diff options
Diffstat (limited to 'src/java/org/apache')
71 files changed, 2328 insertions, 1561 deletions
diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java index dd9a0dc03..df233dafa 100644 --- a/src/java/org/apache/fop/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java @@ -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); @@ -524,24 +537,23 @@ public class AFPGraphics2D extends AbstractGraphics2D { } /** {@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); + } } diff --git a/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java b/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java index df0ef55c5..cd8c7c303 100644 --- a/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java +++ b/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java @@ -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/AFPPaintingState.java b/src/java/org/apache/fop/afp/AFPPaintingState.java index 60e4812b9..cb78fb36e 100644 --- a/src/java/org/apache/fop/afp/AFPPaintingState.java +++ b/src/java/org/apache/fop/afp/AFPPaintingState.java @@ -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; } /** diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java index c912b8b17..21de78250 100644 --- a/src/java/org/apache/fop/afp/AFPResourceManager.java +++ b/src/java/org/apache/fop/afp/AFPResourceManager.java @@ -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; diff --git a/src/java/org/apache/fop/afp/AFPStreamer.java b/src/java/org/apache/fop/afp/AFPStreamer.java index 1d9367ef6..269e6ae08 100644 --- a/src/java/org/apache/fop/afp/AFPStreamer.java +++ b/src/java/org/apache/fop/afp/AFPStreamer.java @@ -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/Graphics2DImagePainterGOCA.java b/src/java/org/apache/fop/afp/Graphics2DImagePainterGOCA.java index 1a2883e72..6a7538550 100644 --- a/src/java/org/apache/fop/afp/Graphics2DImagePainterGOCA.java +++ b/src/java/org/apache/fop/afp/Graphics2DImagePainterGOCA.java @@ -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); } diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java index 1dd22c66a..de7f7f5be 100644 --- a/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java +++ b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java @@ -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/AFPPageFonts.java b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java index 41fce731d..146c6f14b 100644 --- a/src/java/org/apache/fop/afp/AFPPageFonts.java +++ b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java @@ -17,11 +17,7 @@ /* $Id$ */ -package org.apache.fop.afp; - -import org.apache.fop.afp.fonts.AFPFont; -import org.apache.fop.afp.fonts.AFPFontAttributes; - +package org.apache.fop.afp.fonts; /** * Holds the current page fonts 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 index 000000000..74f8bf450 --- /dev/null +++ b/src/java/org/apache/fop/afp/fonts/package.html @@ -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 diff --git a/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java b/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java index 6f993b840..3adcd9466 100644 --- a/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java +++ b/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java @@ -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 index 000000000..b0e408405 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsFilletRelative.java @@ -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 diff --git a/src/java/org/apache/fop/afp/goca/GraphicsLine.java b/src/java/org/apache/fop/afp/goca/GraphicsLine.java index 319a9a122..99f54b2d1 100644 --- a/src/java/org/apache/fop/afp/goca/GraphicsLine.java +++ b/src/java/org/apache/fop/afp/goca/GraphicsLine.java @@ -19,10 +19,9 @@ 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 index 000000000..1eddc5129 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsLineRelative.java @@ -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 index 000000000..539be8d13 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/package.html @@ -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 index 000000000..34e0bc19d --- /dev/null +++ b/src/java/org/apache/fop/afp/ioca/package.html @@ -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 diff --git a/src/java/org/apache/fop/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/afp/modca/GraphicsObject.java index 8b76dde15..3848ca4c3 100644 --- a/src/java/org/apache/fop/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/afp/modca/GraphicsObject.java @@ -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 index 000000000..572743558 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/package.html @@ -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 index 000000000..99ae55a45 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/package.html @@ -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 index 000000000..d67498159 --- /dev/null +++ b/src/java/org/apache/fop/afp/package.html @@ -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 index 000000000..5434b5b9d --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java @@ -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 index 000000000..de677e7ab --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java @@ -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 index 000000000..31aa3fe60 --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java @@ -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 <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 <text> element. + * + * @param textPainter the text painter to use + */ + public AFPTextElementBridge(TextPainter textPainter) { + super(textPainter); + } + +} + diff --git a/src/java/org/apache/fop/afp/AFPTextHandler.java b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java index 77dc641b9..d78e5c16e 100644 --- a/src/java/org/apache/fop/afp/AFPTextHandler.java +++ b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java @@ -17,16 +17,18 @@ /* $Id$ */ -package org.apache.fop.afp; +package org.apache.fop.afp.svg; 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.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; @@ -41,9 +43,6 @@ 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 */ @@ -113,7 +112,7 @@ public class AFPTextHandler implements TextHandler { fontReference = registerPageFont(internalFontName, fontSize); } else { java.awt.Font awtFont = g2d.getFont(); - AffineTransform fontTransform = awtFont.getTransform(); +// AffineTransform fontTransform = awtFont.getTransform(); FontInfo fontInfo = getFontInfo(); Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont); String internalFontName = fopFont.getFontName(); @@ -122,14 +121,8 @@ public class AFPTextHandler implements TextHandler { } 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])); + graphicsObj.addString(str, Math.round(x), Math.round(y)); } /** diff --git a/src/java/org/apache/fop/afp/AFPTextPainter.java b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java index 7e3f3405f..2d68616a3 100644 --- a/src/java/org/apache/fop/afp/AFPTextPainter.java +++ b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java @@ -17,13 +17,14 @@ /* $Id$ */ -package org.apache.fop.afp; +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; @@ -42,6 +43,7 @@ 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; @@ -80,6 +82,7 @@ public class AFPTextPainter implements TextPainter { /** * 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 */ @@ -87,10 +90,10 @@ public class AFPTextPainter implements TextPainter { Point2D loc = node.getLocation(); log.debug("painting text node " + node); if (hasUnsupportedAttributes(node)) { - log.debug("hasunsuportedattributes"); + log.debug("hasUnsuportedAttributes"); PROXY_PAINTER.paint(node, g2d); } else { - log.debug("allattributessupported"); + log.debug("allAttributesSupported"); paintTextRuns(node.getTextRuns(), g2d, loc); } } @@ -221,7 +224,8 @@ public class AFPTextPainter implements TextPainter { aci.first(); updateLocationFromACI(aci, loc); - loc = g2d.getTransform().transform(loc, null); + AffineTransform at = g2d.getTransform(); + loc = at.transform(loc, null); // font Font font = makeFont(aci); @@ -240,6 +244,7 @@ public class AFPTextPainter implements TextPainter { } g2d.setPaint(foreground); + // text String txt = getText(aci); float advance = getStringWidth(txt, font); float tx = 0; @@ -258,9 +263,11 @@ public class AFPTextPainter implements TextPainter { } // draw string + double x = loc.getX(); + double y = loc.getY(); try { try { - nativeTextHandler.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY())); + nativeTextHandler.drawString(txt, (float)x + tx, (float)y); } catch (IOException ioe) { if (g2d instanceof AFPGraphics2D) { ((AFPGraphics2D)g2d).handleIOException(ioe); @@ -424,6 +431,7 @@ public class AFPTextPainter implements TextPainter { * 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 */ @@ -436,6 +444,7 @@ public class AFPTextPainter implements TextPainter { /** * 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 @@ -448,6 +457,7 @@ public class AFPTextPainter implements TextPainter { /** * 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 @@ -460,6 +470,7 @@ public class AFPTextPainter implements TextPainter { /** * 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 @@ -472,6 +483,7 @@ public class AFPTextPainter implements TextPainter { /** * Selec first. * This does nothing since the output is AFP and not interactive. + * * @param node the text node * @return null */ @@ -482,6 +494,7 @@ public class AFPTextPainter implements TextPainter { /** * Select last. * This does nothing since the output is AFP and not interactive. + * * @param node the text node * @return null */ @@ -492,6 +505,7 @@ public class AFPTextPainter implements TextPainter { /** * 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 @@ -503,6 +517,7 @@ public class AFPTextPainter implements TextPainter { /** * 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 diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index 1a04d129a..8f8032767 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -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); } /** diff --git a/src/java/org/apache/fop/fonts/package.html b/src/java/org/apache/fop/fonts/package.html index 33e1e2cb3..fee0bf827 100644 --- a/src/java/org/apache/fop/fonts/package.html +++ b/src/java/org/apache/fop/fonts/package.html @@ -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> diff --git a/src/java/org/apache/fop/pdf/package.html b/src/java/org/apache/fop/pdf/package.html index e86318adc..383f78da1 100644 --- a/src/java/org/apache/fop/pdf/package.html +++ b/src/java/org/apache/fop/pdf/package.html @@ -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> diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index 18cc81400..5c253fe94 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -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); @@ -102,6 +104,18 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC } /** + * 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. * * @param rendererContext the renderer context @@ -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); } diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java index 5861fb042..ee18dff0d 100644 --- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java @@ -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 index 000000000..e305e0a55 --- /dev/null +++ b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java @@ -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 index 000000000..05d1e2e79 --- /dev/null +++ b/src/java/org/apache/fop/render/ImageHandler.java @@ -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(); +} diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index 56504ff53..e4ec41e0b 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -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 { @@ -112,6 +111,14 @@ public abstract class PrintRenderer extends AbstractRenderer { } /** + * 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) * @param y the y 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, diff --git a/src/java/org/apache/fop/render/RendererContext.java b/src/java/org/apache/fop/render/RendererContext.java index e4e234cd2..ac885a44b 100644 --- a/src/java/org/apache/fop/render/RendererContext.java +++ b/src/java/org/apache/fop/render/RendererContext.java @@ -20,10 +20,12 @@ 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 index 3b00804fc..000000000 --- a/src/java/org/apache/fop/render/afp/AFPAbstractImageFactory.java +++ /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/AFPDataObjectInfoProvider.java b/src/java/org/apache/fop/render/afp/AFPDataObjectInfoProvider.java deleted file mode 100644 index aac17b701..000000000 --- a/src/java/org/apache/fop/render/afp/AFPDataObjectInfoProvider.java +++ /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/afp/AFPForeignAttributeReader.java b/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java index 710c24533..2b5077fe9 100644 --- a/src/java/org/apache/fop/afp/AFPForeignAttributeReader.java +++ b/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java @@ -17,13 +17,15 @@ /* $Id$ */ -package org.apache.fop.afp; +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; diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index 4f92826cf..8e43d1c28 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -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 index 88c0b5c26..000000000 --- a/src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java +++ /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/AFPDataObjectInfoFactory.java b/src/java/org/apache/fop/render/afp/AFPImageHandler.java index ba2392835..8e925d460 100644 --- a/src/java/org/apache/fop/render/afp/AFPDataObjectInfoFactory.java +++ b/src/java/org/apache/fop/render/afp/AFPImageHandler.java @@ -22,51 +22,39 @@ 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.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; +import org.apache.fop.render.ImageHandler; - -/** - * Abstract image configurator - */ -public abstract class AFPDataObjectInfoFactory { +public abstract class AFPImageHandler implements ImageHandler { 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 + * Generates an intermediate AFPDataObjectInfo that is later used to construct + * the appropriate data object in the AFP DataStream. * - * @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 + * @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 create(AFPRendererImageInfo rendererImageInfo) throws IOException { + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { AFPDataObjectInfo dataObjectInfo = createDataObjectInfo(); // set resource information + Map foreignAttributes = rendererImageInfo.getForeignAttributes(); AFPResourceInfo resourceInfo - = foreignAttributeReader.getResourceInfo(rendererImageInfo.getForeignAttributes()); + = foreignAttributeReader.getResourceInfo(foreignAttributes); resourceInfo.setUri(rendererImageInfo.getURI()); dataObjectInfo.setResourceInfo(resourceInfo); @@ -77,7 +65,12 @@ public abstract class AFPDataObjectInfoFactory { Rectangle2D position = rendererImageInfo.getPosition(); float srcX = origin.x + (float)position.getX(); float srcY = origin.y + (float)position.getY(); - AFPUnitConverter unitConv = state.getUnitConverter(); + + 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]); @@ -88,11 +81,11 @@ public abstract class AFPDataObjectInfoFactory { int height = Math.round(unitConv.mpt2units((float)position.getHeight())); objectAreaInfo.setHeight(height); - int resolution = state.getResolution(); + int resolution = paintingState.getResolution(); objectAreaInfo.setHeightRes(resolution); objectAreaInfo.setWidthRes(resolution); - objectAreaInfo.setRotation(state.getRotation()); + objectAreaInfo.setRotation(paintingState.getRotation()); dataObjectInfo.setObjectAreaInfo(objectAreaInfo); 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 index 000000000..e8fe1f4f1 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java @@ -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/AFPRawCCITTFaxFactory.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java index 2e6eca6ae..aa91bb660 100644 --- a/src/java/org/apache/fop/render/afp/AFPRawCCITTFaxFactory.java +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java @@ -24,36 +24,39 @@ 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.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageSize; import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; /** - * An CITT fax image data object info factory + * PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4). */ -public class AFPRawCCITTFaxFactory extends AFPDataObjectInfoFactory { - - /** - * Main constructor - * - * @param state the AFP painting state - */ - public AFPRawCCITTFaxFactory(AFPPaintingState state) { - super(state); - } +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 create(AFPRendererImageInfo rendererImageInfo) throws IOException { - AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)super.create(rendererImageInfo); + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { + AFPImageObjectInfo imageObjectInfo + = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo); - ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.img; + ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.getImage(); imageObjectInfo.setCompression(ccitt.getCompression()); AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo(); - int xresol = (int) (ccitt.getSize().getDpiHorizontal() * 10); - objectAreaInfo.setWidthRes(xresol); + ImageSize imageSize = ccitt.getSize(); + int widthRes = (int) (imageSize.getDpiHorizontal() * 10); + objectAreaInfo.setWidthRes(widthRes); - int yresol = (int) (ccitt.getSize().getDpiVertical() * 10); - objectAreaInfo.setHeightRes(yresol); + int heightRes = (int) (imageSize.getDpiVertical() * 10); + objectAreaInfo.setHeightRes(heightRes); imageObjectInfo.setInputStream(ccitt.createInputStream()); @@ -64,4 +67,20 @@ public class AFPRawCCITTFaxFactory extends AFPDataObjectInfoFactory { protected AFPDataObjectInfo createDataObjectInfo() { return new AFPImageObjectInfo(); } -}
\ No newline at end of file + + /** {@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/AFPImageRawStreamFactory.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java index 376bee7b9..47344b200 100644 --- a/src/java/org/apache/fop/render/afp/AFPImageRawStreamFactory.java +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java @@ -25,35 +25,48 @@ 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; /** - * A raw stream image data object info factory + * AFPImageHandler implementation which handles raw stream images. */ -public class AFPImageRawStreamFactory extends AFPDataObjectInfoFactory { - - /** - * Main constructor - * - * @param state the AFP painting state - */ - public AFPImageRawStreamFactory(AFPPaintingState state) { - super(state); - } +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 create(AFPRendererImageInfo rendererImageInfo) throws IOException { - AFPDataObjectInfo dataObjectInfo = super.create(rendererImageInfo); + 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(); - int resolution = state.getResolution(); 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); @@ -69,6 +82,21 @@ public class AFPImageRawStreamFactory extends AFPDataObjectInfoFactory { } /** {@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 index 000000000..59ca6cf38 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java @@ -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/AFPImageRenderedFactory.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java index 59d6af9a8..ef6a6bb65 100644 --- a/src/java/org/apache/fop/render/afp/AFPImageRenderedFactory.java +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java @@ -27,33 +27,41 @@ 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; /** - * A buffered image data object info factory + * PDFImageHandler implementation which handles RenderedImage instances. */ -public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory { - - /** - * Main constructor - * - * @param state the AFP painting state - */ - public AFPImageRenderedFactory(AFPPaintingState state) { - super(state); - } +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 create(AFPRendererImageInfo rendererImageInfo) throws IOException { + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { AFPImageObjectInfo imageObjectInfo - = (AFPImageObjectInfo)super.create(rendererImageInfo); + = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo); imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45); AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo(); - int resolution = state.getResolution(); + AFPRendererContext rendererContext + = (AFPRendererContext)rendererImageInfo.getRendererContext(); + AFPInfo afpInfo = rendererContext.getInfo(); + AFPPaintingState paintingState = afpInfo.getPaintingState(); + int resolution = paintingState.getResolution(); objectAreaInfo.setWidthRes(resolution); objectAreaInfo.setHeightRes(resolution); @@ -70,13 +78,13 @@ public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory { ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos); byte[] imageData = baos.toByteArray(); - boolean colorImages = state.isColorImages(); + boolean colorImages = paintingState.isColorImages(); imageObjectInfo.setColor(colorImages); // convert to grayscale if (!colorImages) { baos.reset(); - int bitsPerPixel = state.getBitsPerPixel(); + int bitsPerPixel = paintingState.getBitsPerPixel(); imageObjectInfo.setBitsPerPixel(bitsPerPixel); ImageEncodingHelper.encodeRGBAsGrayScale( imageData, dataWidth, dataHeight, bitsPerPixel, baos); @@ -91,4 +99,20 @@ public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory { 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 index 000000000..fee355da7 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java @@ -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/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java index 1059014ab..59050b66d 100644 --- a/src/java/org/apache/fop/render/afp/AFPInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPInfo.java @@ -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/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 87c098a89..ede556ecb 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -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} */ @@ -380,6 +377,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } /** {@inheritDoc} */ + protected RendererContext instantiateRendererContext() { + return new AFPRendererContext(this, getMimeType()); + } + + /** {@inheritDoc} */ protected RendererContext createRendererContext(int x, int y, int width, int height, Map foreignAttributes) { RendererContext context; @@ -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); } /** diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index 6a59d27e3..532d45967 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -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 index 000000000..8d544a7c4 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPRendererContext.java @@ -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; + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java index d4a14d3c2..0aa3eb6ab 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java @@ -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; } @@ -86,15 +85,6 @@ public class AFPRendererImageInfo { } /** - * Sets the graphics 2d adapter - * - * @param adapter the graphics 2d adapter - */ - public void setGraphics2DAdapter(AFPGraphics2DAdapter adapter) { - this.g2dAdapter = adapter; - } - - /** * Returns the image info * * @return the image info @@ -113,15 +103,6 @@ public class AFPRendererImageInfo { } /** - * Returns the graphics 2D adapter - * - * @return the graphics 2D adapter - */ - public AFPGraphics2DAdapter getGraphics2DAdapter() { - return this.g2dAdapter; - } - - /** * Returns the renderer context * * @return the renderer context diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 3bdab289c..2800686d9 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -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 index 7eb2c1001..000000000 --- a/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java +++ /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 index 000000000..3e611d964 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/package.html @@ -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 diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java index f93ee5a97..6343d0c50 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java @@ -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 diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java index a58fe5922..9f44e58b5 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java @@ -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} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java index 9f56ebfea..158e93c86 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java @@ -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} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java index f971a49ae..1432547da 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java @@ -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} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java index b664a0a24..1d4c733a3 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java @@ -19,171 +19,18 @@ 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); - } - - } - } - } } diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java index 783cb225c..edbe9005d 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java @@ -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} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java index d111e733f..069fef172 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java @@ -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} */ diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 0eba2fe91..ba3d89195 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -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()); diff --git a/src/java/org/apache/fop/render/ps/PSTextPainter.java b/src/java/org/apache/fop/render/ps/PSTextPainter.java index 7c525dbf7..a318c6465 100644 --- a/src/java/org/apache/fop/render/ps/PSTextPainter.java +++ b/src/java/org/apache/fop/render/ps/PSTextPainter.java @@ -19,40 +19,34 @@ 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 index 000000000..be1c3c122 --- /dev/null +++ b/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java @@ -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 index 000000000..31895cebe --- /dev/null +++ b/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java @@ -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 <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 <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/afp/AFPTextElementBridge.java b/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java index 2bfccf47d..53b8e2ad5 100644 --- a/src/java/org/apache/fop/afp/AFPTextElementBridge.java +++ b/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java @@ -5,9 +5,9 @@ * 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. @@ -17,10 +17,10 @@ /* $Id$ */ -package org.apache.fop.afp; +package org.apache.fop.svg; -import org.apache.batik.bridge.SVGTextElementBridge; 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; @@ -31,21 +31,26 @@ import org.w3c.dom.Node; * Bridge class for the <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 class AFPTextElementBridge extends SVGTextElementBridge { - - private AFPTextPainter textPainter; +public abstract class AbstractFOPTextElementBridge extends SVGTextElementBridge { + + /** text painter */ + protected TextPainter textPainter; /** - * Constructs a new bridge for the <text> element. - * @param textPainter the text painter to use + * Main constructor + * + * @param textPainter the text painter */ - public AFPTextElementBridge(AFPTextPainter textPainter) { + 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 @@ -53,16 +58,13 @@ public class AFPTextElementBridge extends SVGTextElementBridge { */ public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) { GraphicsNode node = super.createGraphicsNode(ctx, e); - if (node != null && isSimple(ctx, e, node)) { - ((TextNode)node).setTextPainter(getTextPainter()); + if (node != null) { + //Set our own text painter + ((TextNode)node).setTextPainter(textPainter); } 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 @@ -75,9 +77,9 @@ public class AFPTextElementBridge extends SVGTextElementBridge { * @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 + * easily rendered using normal drawString on the Graphics2D */ - private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) { + protected boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) { for (Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) { @@ -106,5 +108,6 @@ public class AFPTextElementBridge extends SVGTextElementBridge { 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 index 000000000..8e74cba1d --- /dev/null +++ b/src/java/org/apache/fop/svg/NativeImageHandler.java @@ -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); + +} diff --git a/src/java/org/apache/fop/svg/PDFBridgeContext.java b/src/java/org/apache/fop/svg/PDFBridgeContext.java index 6aa29cfa1..364c7a6f3 100644 --- a/src/java/org/apache/fop/svg/PDFBridgeContext.java +++ b/src/java/org/apache/fop/svg/PDFBridgeContext.java @@ -20,30 +20,20 @@ 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"); } diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index cafb5f4d3..f8a0bd415 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -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(); diff --git a/src/java/org/apache/fop/svg/PDFImageElementBridge.java b/src/java/org/apache/fop/svg/PDFImageElementBridge.java index 7eb89d2b1..1a17aa410 100644 --- a/src/java/org/apache/fop/svg/PDFImageElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFImageElementBridge.java @@ -19,36 +19,14 @@ 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 <image> element when jpeg images. + * PDF Image Element Bridge class for the <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 <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; } } diff --git a/src/java/org/apache/fop/svg/PDFTextElementBridge.java b/src/java/org/apache/fop/svg/PDFTextElementBridge.java index 4c11aa97e..c983d2b45 100644 --- a/src/java/org/apache/fop/svg/PDFTextElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFTextElementBridge.java @@ -19,13 +19,7 @@ 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 <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 <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; - } - } diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java index 06fea54cc..8a0feb3a2 100644 --- a/src/java/org/apache/fop/svg/PDFTextPainter.java +++ b/src/java/org/apache/fop/svg/PDFTextPainter.java @@ -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; |