diff options
Diffstat (limited to 'src/java/org/apache/fop/render/pcl')
5 files changed, 194 insertions, 127 deletions
diff --git a/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java b/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java index 80c010afc..06a4d37a0 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pcl/PCLGraphics2DAdapter.java @@ -28,11 +28,13 @@ import java.io.IOException; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + import org.apache.fop.render.AbstractGraphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.RendererContext; import org.apache.fop.util.UnitConv; -import org.apache.xmlgraphics.java2d.GraphicContext; /** * Graphics2DAdapter implementation for PCL and HP GL/2. @@ -110,7 +112,8 @@ public class PCLGraphics2DAdapter extends AbstractGraphics2DAdapter { if (!painted) { //Fallback solution: Paint to a BufferedImage int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); - BufferedImage bi = paintToBufferedImage(painter, pclContext, resolution, true, false); + BufferedImage bi = paintToBufferedImage(painter, pclContext, + resolution, !pclContext.isColorCanvas(), false); pcl.setCursorPos(x, y); gen.paintBitmap(bi, new Dimension(width, height), pclContext.isSourceTransparency()); diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 732ce0f8f..b48c28089 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -24,24 +24,17 @@ import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; +import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; -import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.ComponentColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.PixelInterleavedSampleModel; -import java.awt.image.Raster; import java.awt.image.RenderedImage; -import java.awt.image.SampleModel; -import java.awt.image.WritableRaster; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.util.List; @@ -52,7 +45,19 @@ import org.w3c.dom.Document; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +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.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.MimeConstants; @@ -70,16 +75,12 @@ import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.Viewport; import org.apache.fop.area.inline.WordArea; +import org.apache.fop.datatypes.URISpecification; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontMetrics; -import org.apache.fop.image.EPSImage; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.XMLImage; import org.apache.fop.render.Graphics2DAdapter; -import org.apache.fop.render.Graphics2DImagePainter; import org.apache.fop.render.PrintRenderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; @@ -135,6 +136,13 @@ public class PCLRenderer extends PrintRenderer { private boolean allTextAsBitmaps = false; /** + * Controls whether an RGB canvas is used when converting Java2D graphics to bitmaps. + * This can be used to work around problems with Apache Batik, for example, but setting + * this to true will increase memory consumption. + */ + private boolean useColorCanvas = false; + + /** * Controls whether the generation of PJL commands gets disabled. */ private boolean disabledPJL = false; @@ -991,87 +999,88 @@ public class PCLRenderer extends PrintRenderer { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ + protected RendererContext createRendererContext(int x, int y, int width, int height, + Map foreignAttributes) { + RendererContext context = super.createRendererContext( + x, y, width, height, foreignAttributes); + context.setProperty(PCLRendererContextConstants.PCL_COLOR_CANVAS, + Boolean.valueOf(this.useColorCanvas)); + return context; + } + + /** {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { drawImage(image.getURL(), pos, image.getForeignAttributes()); } + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] + {ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, + ImageFlavor.XML_DOM}; /** * Draw an image at the indicated location. - * @param url the URI/URL of the image + * @param uri the URI/URL of the image * @param pos the position of the image * @param foreignAttributes an optional Map with foreign attributes, may be null */ - protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) { - url = ImageFactory.getURL(url); - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(url, userAgent); - if (fopimage == null) { - return; - } - if (!fopimage.load(FopImage.DIMENSIONS)) { - return; - } - String mime = fopimage.getMimeType(); - if ("text/xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if ("image/svg+xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if (fopimage instanceof EPSImage) { - log.warn("EPS images are not supported by this renderer"); - } else { - if (!fopimage.load(FopImage.BITMAP)) { - log.error("Bitmap image could not be processed: " + fopimage); - return; - } - byte[] imgmap = fopimage.getBitmaps(); + protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { + uri = URISpecification.getURL(uri); + Rectangle posInt = new Rectangle( + (int)pos.getX(), + (int)pos.getY(), + (int)pos.getWidth(), + (int)pos.getHeight()); + Point origin = new Point(currentIPPosition, currentBPPosition); + int x = origin.x + posInt.x; + int y = origin.y + posInt.y; + + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageInfo info = null; + try { + ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); - ColorModel cm = new ComponentColorModel( - ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), - new int[] {8, 8, 8}, - false, false, - ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); - int imgw = fopimage.getWidth(); - int imgh = fopimage.getHeight(); - SampleModel sampleModel = new PixelInterleavedSampleModel( - DataBuffer.TYPE_BYTE, imgw, imgh, 3, imgw * 3, new int[] {0, 1, 2}); - DataBuffer dbuf = new DataBufferByte(imgmap, imgw * imgh * 3); - - WritableRaster raster = Raster.createWritableRaster(sampleModel, - dbuf, null); - - // Combine the color model and raster into a buffered image - RenderedImage img = new BufferedImage(cm, raster, false, null); - - try { - setCursorPos(this.currentIPPosition + (int)pos.getX(), - this.currentBPPosition + (int)pos.getY()); - gen.paintBitmap(img, - new Dimension((int)pos.getWidth(), (int)pos.getHeight()), + //Only now fully load/prepare the image + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, FLAVORS, hints, sessionContext); + + //...and process the image + if (img instanceof ImageGraphics2D) { + ImageGraphics2D imageG2D = (ImageGraphics2D)img; + RendererContext context = createRendererContext( + posInt.x, posInt.y, + posInt.width, posInt.height, foreignAttributes); + getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(), + context, x, y, posInt.width, posInt.height); + } else if (img instanceof ImageRendered) { + ImageRendered imgRend = (ImageRendered)img; + RenderedImage ri = imgRend.getRenderedImage(); + setCursorPos(x, y); + gen.paintBitmap(ri, + new Dimension(posInt.width, posInt.height), false); - } catch (IOException ioe) { - handleIOTrouble(ioe); + } else if (img instanceof ImageXMLDOM) { + ImageXMLDOM imgXML = (ImageXMLDOM)img; + renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(), + pos, foreignAttributes); + } else { + throw new UnsupportedOperationException("Unsupported image type: " + img); } + + } catch (ImageException ie) { + log.error("Error while processing image: " + + (info != null ? info.toString() : uri), ie); + } catch (FileNotFoundException fe) { + log.error(fe.getMessage()); + } catch (IOException ioe) { + handleIOTrouble(ioe); } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { Document doc = fo.getDocument(); String ns = fo.getNameSpace(); @@ -1153,52 +1162,45 @@ public class PCLRenderer extends PrintRenderer { } // background image - if (back.getFopImage() != null) { - FopImage fopimage = back.getFopImage(); - if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) { - saveGraphicsState(); - clipRect(sx, sy, paddRectWidth, paddRectHeight); - int horzCount = (int) ((paddRectWidth * 1000 / fopimage - .getIntrinsicWidth()) + 1.0f); - int vertCount = (int) ((paddRectHeight * 1000 / fopimage - .getIntrinsicHeight()) + 1.0f); - if (back.getRepeat() == EN_NOREPEAT) { - horzCount = 1; - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATX) { - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATY) { - horzCount = 1; - } - // change from points to millipoints - sx *= 1000; - sy *= 1000; - if (horzCount == 1) { - sx += back.getHoriz(); - } - if (vertCount == 1) { - sy += back.getVertical(); - } - for (int x = 0; x < horzCount; x++) { - for (int y = 0; y < vertCount; y++) { - // place once - Rectangle2D pos; - // Image positions are relative to the currentIP/BP - pos = new Rectangle2D.Float( - sx - currentIPPosition - + (x * fopimage.getIntrinsicWidth()), - sy - currentBPPosition - + (y * fopimage.getIntrinsicHeight()), - fopimage.getIntrinsicWidth(), - fopimage.getIntrinsicHeight()); - drawImage(back.getURL(), pos, null); - } + if (back.getImageInfo() != null) { + ImageSize imageSize = back.getImageInfo().getSize(); + saveGraphicsState(); + clipRect(sx, sy, paddRectWidth, paddRectHeight); + int horzCount = (int) ((paddRectWidth * 1000 / imageSize.getWidthMpt()) + 1.0f); + int vertCount = (int) ((paddRectHeight * 1000 / imageSize.getHeightMpt()) + 1.0f); + if (back.getRepeat() == EN_NOREPEAT) { + horzCount = 1; + vertCount = 1; + } else if (back.getRepeat() == EN_REPEATX) { + vertCount = 1; + } else if (back.getRepeat() == EN_REPEATY) { + horzCount = 1; + } + // change from points to millipoints + sx *= 1000; + sy *= 1000; + if (horzCount == 1) { + sx += back.getHoriz(); + } + if (vertCount == 1) { + sy += back.getVertical(); + } + for (int x = 0; x < horzCount; x++) { + for (int y = 0; y < vertCount; y++) { + // place once + Rectangle2D pos; + // Image positions are relative to the currentIP/BP + pos = new Rectangle2D.Float( + sx - currentIPPosition + + (x * imageSize.getWidthMpt()), + sy - currentBPPosition + + (y * imageSize.getHeightMpt()), + imageSize.getWidthMpt(), + imageSize.getHeightMpt()); + drawImage(back.getURL(), pos, null); } - restoreGraphicsState(); - } else { - log.warn( - "Can't find background image: " + back.getURL()); } + restoreGraphicsState(); } } @@ -1508,6 +1510,11 @@ public class PCLRenderer extends PrintRenderer { } } + /** + * Controls whether all text should be generated as bitmaps or only text for which there's + * no native font. + * @param allTextAsBitmaps true if all text should be painted as bitmaps + */ public void setAllTextAsBitmaps(boolean allTextAsBitmaps) { this.allTextAsBitmaps = allTextAsBitmaps; } diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererContext.java b/src/java/org/apache/fop/render/pcl/PCLRendererContext.java index 32510137b..62d4bcaa4 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRendererContext.java +++ b/src/java/org/apache/fop/render/pcl/PCLRendererContext.java @@ -62,11 +62,28 @@ public class PCLRendererContext extends RendererContext.RendererContextWrapper { && "true".equalsIgnoreCase((String)getForeignAttributes().get(qName)); } + /** + * Indicates whether the background should not be erased prior to painting. + * @return true if the background shouldn't be erased + */ public boolean isSourceTransparency() { QName qName = new QName(ExtensionElementMapping.URI, null, "source-transparency"); return getForeignAttributes() != null && "true".equalsIgnoreCase((String)getForeignAttributes().get(qName)); } + /** + * Indicates whether an RGB canvas should be used rather than one with grayscales. + * This can be used to work around limitations of Apache Batik if you get error while + * processing SVG graphics. Note, however, that RGB mode will use more memory. + * @return true if an EGB canvas should be used + */ + public boolean isColorCanvas() { + QName qName = new QName(ExtensionElementMapping.URI, null, "color-canvas"); + Boolean prop = (Boolean)context.getProperty(PCLRendererContextConstants.PCL_COLOR_CANVAS); + return Boolean.TRUE.equals(prop) + || (getForeignAttributes() != null + && "true".equalsIgnoreCase((String)getForeignAttributes().get(qName))); + } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererContextConstants.java b/src/java/org/apache/fop/render/pcl/PCLRendererContextConstants.java new file mode 100644 index 000000000..66ce40f5e --- /dev/null +++ b/src/java/org/apache/fop/render/pcl/PCLRendererContextConstants.java @@ -0,0 +1,32 @@ +/* + * 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.pcl; + +import org.apache.fop.render.RendererContextConstants; + +/** + * Defines a number of standard constants (keys) for use by the RendererContext class. + */ +public interface PCLRendererContextConstants extends RendererContextConstants { + + /** The PDF document that this image is being drawn into. */ + String PCL_COLOR_CANVAS = "color-canvas"; + +} diff --git a/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java b/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java index 8c9179063..a016c692f 100644 --- a/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java +++ b/src/java/org/apache/fop/render/pcl/PCLSVGHandler.java @@ -22,6 +22,7 @@ package org.apache.fop.render.pcl; // FOP import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; +import org.apache.fop.render.RendererContext; /** * PCL XML handler for SVG. Uses Apache Batik for SVG processing. @@ -36,5 +37,12 @@ public class PCLSVGHandler extends AbstractGenericSVGHandler { return (renderer instanceof PCLRenderer); } + /** {@inheritDoc} */ + protected void updateRendererContext(RendererContext context) { + //Work around a problem in Batik: Gradients cannot be done in ColorSpace.CS_GRAY + context.setProperty(PCLRendererContextConstants.PCL_COLOR_CANVAS, + Boolean.TRUE); + } + } |