diff options
Diffstat (limited to 'src/java/org/apache/fop/render/pdf/PDFPainter.java')
-rw-r--r-- | src/java/org/apache/fop/render/pdf/PDFPainter.java | 230 |
1 files changed, 114 insertions, 116 deletions
diff --git a/src/java/org/apache/fop/render/pdf/PDFPainter.java b/src/java/org/apache/fop/render/pdf/PDFPainter.java index e75417d33..5b763b197 100644 --- a/src/java/org/apache/fop/render/pdf/PDFPainter.java +++ b/src/java/org/apache/fop/render/pdf/PDFPainter.java @@ -24,16 +24,23 @@ import java.awt.Dimension; import java.awt.Paint; import java.awt.Rectangle; import java.awt.geom.AffineTransform; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; 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.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; import org.apache.xmlgraphics.xmp.Metadata; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; +import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.extensions.xmp.XMPMetadata; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontTriplet; @@ -42,19 +49,17 @@ import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.pdf.PDFAnnotList; import org.apache.fop.pdf.PDFDocument; -import org.apache.fop.pdf.PDFFilterList; import org.apache.fop.pdf.PDFNumber; import org.apache.fop.pdf.PDFPage; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; -import org.apache.fop.pdf.PDFState; -import org.apache.fop.pdf.PDFStream; import org.apache.fop.pdf.PDFTextUtil; +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.ImageHandler; import org.apache.fop.render.intermediate.AbstractBinaryWritingIFPainter; import org.apache.fop.render.intermediate.IFException; import org.apache.fop.render.intermediate.IFState; import org.apache.fop.util.CharUtilities; -import org.apache.fop.util.ColorUtil; /** * IFPainter implementation that produces PDF. @@ -79,8 +84,8 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { /** the /Resources object of the PDF document being created */ protected PDFResources pdfResources; - /** the current stream to add PDF commands to */ - protected PDFStream currentStream; + /** The current content generator */ + protected PDFContentGenerator generator; /** the current annotation list to add annotations to */ protected PDFResourceContext currentContext; @@ -98,16 +103,6 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { /** the current page's PDF reference string (to avoid numerous function calls) */ protected String currentPageRef; - /** drawing state */ - protected PDFState currentState; - - /** Text generation utility holding the current font status */ - protected PDFTextUtil textutil; - - - /** Image handler registry */ - private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry(); - /** * Default constructor. */ @@ -173,11 +168,9 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { //pageReferences.clear(); pdfResources = null; - currentStream = null; + this.generator = null; currentContext = null; currentPage = null; - currentState = null; - this.textutil = null; //idPositions.clear(); //idGoTos.clear(); @@ -213,20 +206,11 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { currentPageRef = currentPage.referencePDF(); - currentStream = this.pdfDoc.getFactory() - .makeStream(PDFFilterList.CONTENT_FILTER, false); - this.textutil = new PDFTextUtil() { - protected void write(String code) { - currentStream.add(code); - } - }; - - currentState = new PDFState(); + this.generator = new PDFContentGenerator(this.pdfDoc, this.outputStream, this.currentPage); // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFPainter's AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0, size.height); - currentState.concatenate(basicPageTransform); - currentStream.add(CTMHelper.toPDFString(basicPageTransform, true) + " cm\n"); + generator.concatenate(basicPageTransform, true); } /** {@inheritDoc} */ @@ -258,80 +242,136 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { /** {@inheritDoc} */ public void endPage() throws IFException { try { - this.pdfDoc.registerObject(currentStream); - currentPage.setContents(currentStream); + this.pdfDoc.registerObject(generator.getStream()); + currentPage.setContents(generator.getStream()); PDFAnnotList annots = currentPage.getAnnotations(); if (annots != null) { this.pdfDoc.addObject(annots); } this.pdfDoc.addObject(currentPage); - this.pdfDoc.output(this.outputStream); - this.textutil = null; + this.generator.flushPDFDoc(); + this.generator = null; } catch (IOException ioe) { throw new IFException("I/O error in endPage()", ioe); } } /** {@inheritDoc} */ - private void saveGraphicsState() { - //endTextObject(); - currentState.push(); - this.state = this.state.push(); - currentStream.add("q\n"); - } - - private void restoreGraphicsState(boolean popState) { - endTextObject(); - currentStream.add("Q\n"); - if (popState) { - currentState.pop(); - this.state = this.state.pop(); - } - } - - private void restoreGraphicsState() { - restoreGraphicsState(true); - } - - /** {@inheritDoc} */ public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect) throws IFException { - saveGraphicsState(); - currentStream.add(CTMHelper.toPDFString(transform, true) + " cm\n"); + generator.saveGraphicsState(); + generator.add(CTMHelper.toPDFString(transform, true) + " cm\n"); if (clipRect != null) { StringBuffer sb = new StringBuffer(); sb.append(format(clipRect.x)).append(' '); sb.append(format(clipRect.y)).append(' '); sb.append(format(clipRect.width)).append(' '); sb.append(format(clipRect.height)).append(" re W n\n"); - currentStream.add(sb.toString()); + generator.add(sb.toString()); } } /** {@inheritDoc} */ - public void startGroup(AffineTransform transform) throws IFException { - saveGraphicsState(); - currentStream.add(CTMHelper.toPDFString(transform, true) + " cm\n"); + public void endViewport() throws IFException { + generator.restoreGraphicsState(); } /** {@inheritDoc} */ - public void endGroup() throws IFException { - restoreGraphicsState(); + public void startGroup(AffineTransform transform) throws IFException { + generator.saveGraphicsState(); + generator.add(CTMHelper.toPDFString(transform, true) + " cm\n"); } /** {@inheritDoc} */ - public void endViewport() throws IFException { - restoreGraphicsState(); + public void endGroup() throws IFException { + generator.restoreGraphicsState(); } /** {@inheritDoc} */ - public void startImage(Rectangle rect) throws IFException { - // TODO Auto-generated method stub + public void drawImage(String uri, Rectangle rect, Map foreignAttributes) throws IFException { + PDFXObject xobject = pdfDoc.getXObject(uri); + if (xobject != null) { + placeImage(rect, xobject); + return; + } + + ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageInfo info = null; + try { + ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + info = manager.getImageInfo(uri, sessionContext); + + PDFRenderingContext pdfContext = new PDFRenderingContext( + getUserAgent(), generator, currentPage, getFontInfo()); + + Map hints = ImageUtil.getDefaultHints(sessionContext); + org.apache.xmlgraphics.image.loader.Image img = manager.getImage( + info, imageHandlerRegistry.getSupportedFlavors(pdfContext), + hints, sessionContext); + + //First check for a dynamically registered handler + ImageHandler handler = imageHandlerRegistry.getHandler(pdfContext, img); + if (handler == null) { + throw new UnsupportedOperationException( + "No ImageHandler available for image: " + + info + " (" + img.getClass().getName() + ")"); + } + + if (log.isDebugEnabled()) { + log.debug("Using ImageHandler: " + handler.getClass().getName()); + } + try { + //TODO foreign attributes + handler.handleImage(pdfContext, img, rect); + } catch (IOException ioe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageWritingError(this, ioe); + return; + } + } catch (ImageException ie) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); + } catch (FileNotFoundException fe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); + } catch (IOException ioe) { + ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( + getUserAgent().getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); + } + // output new data + try { + generator.flushPDFDoc(); + } catch (IOException ioe) { + throw new IFException("I/O error flushing the PDF document", ioe); + } + } + + /** + * Places a previously registered image at a certain place on the page. + * @param x X coordinate + * @param y Y coordinate + * @param w width for image + * @param h height for image + * @param xobj the image XObject + */ + private void placeImage(Rectangle rect, PDFXObject xobj) { + generator.saveGraphicsState(); + generator.add(format(rect.width) + " 0 0 " + + format(-rect.height) + " " + + format(rect.x) + " " + + format(rect.y + rect.height ) + + " cm " + xobj.getName() + " Do\n"); + generator.restoreGraphicsState(); } + /** {@inheritDoc} */ - public void drawImage(String uri, Rectangle rect) throws IFException { + public void startImage(Rectangle rect) throws IFException { // TODO Auto-generated method stub } @@ -348,14 +388,6 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { } - private static String toString(Paint paint) { - if (paint instanceof Color) { - return ColorUtil.colorToString((Color)paint); - } else { - throw new UnsupportedOperationException("Paint not supported: " + paint); - } - } - /** * Formats a integer value (normally coordinates in millipoints) to a String. * @param value the value (in millipoints) @@ -365,37 +397,16 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { return PDFNumber.doubleOut(value / 1000f); } - /** - * Establishes a new foreground or fill color. - * @param col the color to apply (null skips this operation) - * @param fill true to set the fill color, false for the foreground color - */ - private void updateColor(Color col, boolean fill) { - if (col == null) { - return; - } - boolean update = false; - if (fill) { - update = currentState.setBackColor(col); - } else { - update = currentState.setColor(col); - } - - if (update) { - pdfUtil.setColor(col, fill, this.currentStream); - } - } - /** {@inheritDoc} */ public void drawRect(Rectangle rect, Paint fill, Color stroke) throws IFException { if (fill == null && stroke == null) { return; } - endTextObject(); + generator.endTextObject(); if (rect.width != 0 && rect.height != 0) { if (fill != null) { if (fill instanceof Color) { - updateColor((Color)fill, true); + generator.updateColor((Color)fill, true, null); } else { throw new UnsupportedOperationException("Non-Color paints NYI"); } @@ -415,21 +426,7 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { sb.append(" S"); } sb.append('\n'); - currentStream.add(sb.toString()); - } - } - - /** Indicates the beginning of a text object. */ - private void beginTextObject() { - if (!textutil.isInTextObject()) { - textutil.beginTextObject(); - } - } - - /** Indicates the end of a text object. */ - private void endTextObject() { - if (textutil.isInTextObject()) { - textutil.endTextObject(); + generator.add(sb.toString()); } } @@ -447,14 +444,14 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { /** {@inheritDoc} */ public void drawText(int x, int y, int[] dx, int[] dy, String text) throws IFException { //Note: dy is currently ignored - beginTextObject(); + generator.beginTextObject(); FontTriplet triplet = new FontTriplet( state.getFontFamily(), state.getFontStyle(), state.getFontWeight()); //TODO Ignored: state.getFontVariant() String fontKey = fontInfo.getInternalFontKey(triplet); int sizeMillipoints = state.getFontSize(); float fontSize = sizeMillipoints / 1000f; - updateColor(state.getTextColor(), true); + generator.updateColor(state.getTextColor(), true, null); // This assumes that *all* CIDFonts use a /ToUnicode mapping Typeface tf = getTypeface(fontKey); @@ -465,6 +462,7 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { Font font = fontInfo.getFontInstance(triplet, sizeMillipoints); String fontName = font.getFontName(); + PDFTextUtil textutil = generator.getTextUtil(); textutil.updateTf(fontKey, fontSize, tf.isMultiByte()); textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, x / 1000f, y / 1000f)); |