aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/render/pdf/PDFPainter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/render/pdf/PDFPainter.java')
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFPainter.java230
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));