Browse Source

Implemented foreign-object support for the new intermediate format.

Note: foreign namespace are only properly processed if there is an ImagePreloader and, where necessary, one or more supporting ImageConverters and/or ImageHandlers.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@683637 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Jeremias Maerki 16 years ago
parent
commit
5ca81a092a

+ 131
- 0
src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java View File

@@ -22,15 +22,40 @@ package org.apache.fop.render.intermediate;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;

import javax.xml.transform.dom.DOMSource;

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.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.fop.apps.FOUserAgent;
import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.ImageHandlerRegistry;
import org.apache.fop.render.RenderingContext;

/**
* Abstract base class for IFPainter implementations.
*/
public abstract class AbstractIFPainter implements IFPainter {

/** logging instance */
private static Log log = LogFactory.getLog(AbstractIFPainter.class);

/** non-URI that can be used in feedback messages that an image is an instream-object */
protected static final String INSTREAM_OBJECT_URI = "(instream-object)";

private FOUserAgent userAgent;

/** Image handler registry */
@@ -77,4 +102,110 @@ public abstract class AbstractIFPainter implements IFPainter {
startGroup(combine(transforms));
}

/**
* Creates a new RenderingContext instance.
* @return the new rendering context.
*/
protected abstract RenderingContext createRenderingContext();

/**
* Loads a preloaded image and draws it using a suitable image handler.
* @param info the information object of the preloaded image
* @param rect the rectangle in which to paint the image
* @throws ImageException if there's an error while processing the image
* @throws IOException if there's an I/O error while loading the image
*/
protected void drawImageUsingImageHandler(ImageInfo info, Rectangle rect)
throws ImageException, IOException {
ImageManager manager = getUserAgent().getFactory().getImageManager();
ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();

//Load and convert the image to a supported format
RenderingContext context = createRenderingContext();
Map hints = ImageUtil.getDefaultHints(sessionContext);
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
info, imageHandlerRegistry.getSupportedFlavors(context),
hints, sessionContext);

//First check for a dynamically registered handler
ImageHandler handler = imageHandlerRegistry.getHandler(context, 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(context, img, rect);
} catch (IOException ioe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageWritingError(this, ioe);
return;
}
}

/**
* Default drawing method for handling an image referenced by a URI.
* @param uri the image's URI
* @param rect the rectangle in which to paint the image
*/
protected void drawImageUsingURI(String uri, Rectangle rect) {
ImageManager manager = getUserAgent().getFactory().getImageManager();
ImageInfo info = null;
try {
ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
info = manager.getImageInfo(uri, sessionContext);

drawImageUsingImageHandler(info, rect);
} 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);
}
}

/**
* Default drawing method for handling a foreign object in the form of a DOM document.
* @param doc the DOM document containing the foreign object
* @param rect the rectangle in which to paint the image
*/
protected void drawImageUsingDocument(Document doc, Rectangle rect) {
ImageManager manager = getUserAgent().getFactory().getImageManager();
ImageInfo info = null;
try {
info = manager.preloadImage(null, new DOMSource(doc));

drawImageUsingImageHandler(info, rect);
} catch (ImageException ie) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageError(this,
(info != null ? info.toString() : INSTREAM_OBJECT_URI), ie, null);
} catch (FileNotFoundException fe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageNotFound(this,
(info != null ? info.toString() : INSTREAM_OBJECT_URI), fe, null);
} catch (IOException ioe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageIOError(this,
(info != null ? info.toString() : INSTREAM_OBJECT_URI), ioe, null);
}
}


}

+ 29
- 3
src/java/org/apache/fop/render/intermediate/IFPainter.java View File

@@ -28,6 +28,8 @@ import java.util.Map;

import javax.xml.transform.Result;

import org.w3c.dom.Document;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontInfo;

@@ -258,9 +260,33 @@ public interface IFPainter {
* @throws IFException if an error occurs while handling this event
*/
void drawRect(Rectangle rect, Paint fill, Color stroke) throws IFException;
void drawImage(String uri, Rectangle rect, Map foreignAttributes) throws IFException; //external images
void startImage(Rectangle rect) throws IFException; //followed by a SAX stream (SVG etc.)
void endImage() throws IFException;

/**
* Draws an image identified by a URI inside a given rectangle. This is the equivalent to
* an fo:external-graphic in XSL-FO.
* @param uri the image's URI
* @param rect the rectangle in which the image shall be painted
* @param foreignAttributes a optional Map with foreign attributes (Map<QName,String>)
* @throws IFException if an error occurs while handling this event
*/
void drawImage(String uri, Rectangle rect, Map foreignAttributes) throws IFException;

/**
* Draws an image (represented by a DOM document) inside a given rectangle. This is the
* equivalent to an fo:instream-foreign-object in XSL-FO.
* @param doc the DOM document containing the foreign object
* @param rect the rectangle in which the image shall be painted
* @param foreignAttributes a optional Map with foreign attributes (Map<QName,String>)
* @throws IFException if an error occurs while handling this event
*/
void drawImage(Document doc, Rectangle rect, Map foreignAttributes)
throws IFException;
//Note: For now, all foreign objects are handled as DOM documents. At the moment, all known
//implementations use a DOM anyway, so optimizing this to work with SAX wouldn't result in
//any performance benefits. The IFRenderer itself has a DOM anyway. Only the IFParser could
//potentially profit if there's an image handler that can efficiently deal with the foreign
//object without building a DOM.

//etc. etc.

/**

+ 27
- 0
src/java/org/apache/fop/render/intermediate/IFRenderer.java View File

@@ -32,6 +32,8 @@ import java.util.Stack;

import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.xml.sax.SAXException;

import org.apache.batik.parser.AWTTransformProducer;
@@ -57,6 +59,7 @@ import org.apache.fop.area.PageViewport;
import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.AbstractTextArea;
import org.apache.fop.area.inline.ForeignObject;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
@@ -73,6 +76,10 @@ import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Renderer;

/**
* This renderer implementation is an adapter to the {@code IFPainter} interface. It is used
* to generate content using FOP's intermediate format.
*/
public class IFRenderer extends AbstractPathOrientedRenderer {

/** logging instance */
@@ -714,21 +721,41 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
}
}

/** {@inheritDoc} */
public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
endTextObject();
Rectangle posInt = new Rectangle(
currentIPPosition + (int)pos.getX(),
currentBPPosition + (int)pos.getY(),
(int)pos.getWidth(),
(int)pos.getHeight());
Document doc = fo.getDocument();
try {
painter.drawImage(doc, posInt, fo.getForeignAttributes());
} catch (IFException ife) {
handleIFException(ife);
}
}

/** {@inheritDoc} */
protected void clip() {
// TODO Auto-generated method stub
log.warn("clip() NYI");
}

/** {@inheritDoc} */
protected void clipRect(float x, float y, float width, float height) {
// TODO Auto-generated method stub
log.warn("clipRect() NYI");
}

/** {@inheritDoc} */
protected void closePath() {
// TODO Auto-generated method stub
log.warn("closePath() NYI");
}

/** {@inheritDoc} */
protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz,
boolean startOrBefore, int style, Color col) {
// TODO Auto-generated method stub

+ 31
- 10
src/java/org/apache/fop/render/intermediate/IFSerializer.java View File

@@ -27,13 +27,17 @@ import java.awt.geom.AffineTransform;
import java.util.Iterator;
import java.util.Map;

import org.w3c.dom.Document;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.XMLizable;

import org.apache.fop.render.RenderingContext;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.DOM2SAX;

/**
* IFPainter implementation that serializes the intermediate format to XML.
@@ -214,7 +218,8 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
startViewport(toString(transforms), size, clipRect);
}

private void startViewport(String transform, Dimension size, Rectangle clipRect) throws IFException {
private void startViewport(String transform, Dimension size, Rectangle clipRect)
throws IFException {
try {
AttributesImpl atts = new AttributesImpl();
if (transform != null && transform.length() > 0) {
@@ -271,12 +276,6 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
}
}

/** {@inheritDoc} */
public void startImage(Rectangle rect) throws IFException {
// TODO Auto-generated method stub

}

/** {@inheritDoc} */
public void drawImage(String uri, Rectangle rect, Map foreignAttributes) throws IFException {
try {
@@ -300,9 +299,26 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
}

/** {@inheritDoc} */
public void endImage() throws IFException {
// TODO Auto-generated method stub

public void drawImage(Document doc, Rectangle rect, Map foreignAttributes) throws IFException {
try {
AttributesImpl atts = new AttributesImpl();
atts.addAttribute("", "x", "x", CDATA, Integer.toString(rect.x));
atts.addAttribute("", "y", "y", CDATA, Integer.toString(rect.y));
atts.addAttribute("", "width", "width", CDATA, Integer.toString(rect.width));
atts.addAttribute("", "height", "height", CDATA, Integer.toString(rect.height));
if (foreignAttributes != null) {
Iterator iter = foreignAttributes.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
addAttribute(atts, (QName)entry.getKey(), entry.getValue().toString());
}
}
startElement(EL_IMAGE, atts);
new DOM2SAX(handler).writeDocument(doc, true);
endElement(EL_IMAGE);
} catch (SAXException e) {
throw new IFException("SAX error in startGroup()", e);
}
}

/** {@inheritDoc} */
@@ -406,4 +422,9 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
}
}

/** {@inheritDoc} */
protected RenderingContext createRenderingContext() {
throw new IllegalStateException("Should never be called!");
}

}

+ 21
- 67
src/java/org/apache/fop/render/pdf/PDFPainter.java View File

@@ -24,23 +24,18 @@ 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.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.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;
@@ -55,7 +50,7 @@ import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFResources;
import org.apache.fop.pdf.PDFTextUtil;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFPainter;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFState;
@@ -295,60 +290,16 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
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() + ")");
}
drawImageUsingURI(uri, rect);

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);
}
flushPDFDoc();
}

// output new data
try {
generator.flushPDFDoc();
} catch (IOException ioe) {
throw new IFException("I/O error flushing the PDF document", ioe);
}
/** {@inheritDoc} */
protected RenderingContext createRenderingContext() {
PDFRenderingContext pdfContext = new PDFRenderingContext(
getUserAgent(), generator, currentPage, getFontInfo());
return pdfContext;
}

/**
@@ -369,17 +320,20 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
generator.restoreGraphicsState();
}


/** {@inheritDoc} */
public void startImage(Rectangle rect) throws IFException {
// TODO Auto-generated method stub
public void drawImage(Document doc, Rectangle rect, Map foreignAttributes) throws IFException {
drawImageUsingDocument(doc, rect);

flushPDFDoc();
}

/** {@inheritDoc} */
public void endImage() throws IFException {
// TODO Auto-generated method stub

private void flushPDFDoc() throws IFException {
// output new data
try {
generator.flushPDFDoc();
} catch (IOException ioe) {
throw new IFException("I/O error flushing the PDF document", ioe);
}
}

/** {@inheritDoc} */

+ 21
- 41
src/sandbox/org/apache/fop/render/svg/AbstractSVGPainter.java View File

@@ -28,6 +28,8 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;

import org.w3c.dom.Document;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

@@ -38,14 +40,13 @@ 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.util.MimeConstants;
import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.xmp.Metadata;

import org.apache.fop.events.ResourceEventProducer;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RenderingContext;
import org.apache.fop.render.intermediate.AbstractXMLWritingIFPainter;
import org.apache.fop.render.intermediate.IFConstants;
import org.apache.fop.render.intermediate.IFException;
@@ -197,14 +198,8 @@ public abstract class AbstractSVGPainter extends AbstractXMLWritingIFPainter
}
}

/** {@inheritDoc} */
public void startImage(Rectangle rect) throws IFException {
//establish(MODE_NORMAL);
// TODO Auto-generated method stub

}

private QName CONVERSION_MODE = new QName(ExtensionElementMapping.URI, null, "conversion-mode");
private static final QName CONVERSION_MODE
= new QName(ExtensionElementMapping.URI, null, "conversion-mode");

/** {@inheritDoc} */
public void drawImage(String uri, Rectangle rect, Map foreignAttributes) throws IFException {
@@ -216,6 +211,7 @@ public abstract class AbstractSVGPainter extends AbstractXMLWritingIFPainter
try {
ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
info = manager.getImageInfo(uri, sessionContext);

String mime = info.getMimeType();
String conversionMode = (String)foreignAttributes.get(CONVERSION_MODE);
if ("reference".equals(conversionMode)
@@ -233,35 +229,7 @@ public abstract class AbstractSVGPainter extends AbstractXMLWritingIFPainter
atts.addAttribute("", "height", "height", CDATA, Integer.toString(rect.height));
element("image", atts);
} else {
//Convert the image
SVGRenderingContext svgContext = new SVGRenderingContext(
getUserAgent(), handler);

Map hints = ImageUtil.getDefaultHints(sessionContext);
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
info, imageHandlerRegistry.getSupportedFlavors(svgContext),
hints, sessionContext);

//First check for a dynamically registered handler
ImageHandler handler = imageHandlerRegistry.getHandler(svgContext, 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(svgContext, img, rect);
} catch (IOException ioe) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
getUserAgent().getEventBroadcaster());
eventProducer.imageWritingError(this, ioe);
return;
}
drawImageUsingImageHandler(info, rect);
}
} catch (ImageException ie) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
@@ -282,9 +250,21 @@ public abstract class AbstractSVGPainter extends AbstractXMLWritingIFPainter
}

/** {@inheritDoc} */
public void endImage() throws IFException {
// TODO Auto-generated method stub
public void drawImage(Document doc, Rectangle rect, Map foreignAttributes) throws IFException {
try {
establish(MODE_NORMAL);

drawImageUsingDocument(doc, rect);
} catch (SAXException e) {
throw new IFException("SAX error in drawImage()", e);
}
}

/** {@inheritDoc} */
protected RenderingContext createRenderingContext() {
SVGRenderingContext svgContext = new SVGRenderingContext(
getUserAgent(), handler);
return svgContext;
}

/** {@inheritDoc} */

Loading…
Cancel
Save