<resource-group-file>resources.afp</resource-group-file>
</renderer>]]></source>
<p>
- The default value for the "images mode" setting is "b+w" (black and white). When the setting is "color" a "bits-per-pixel" setting can be provided. When the setting "native" is set to true, images (TIFF, JPEG and Encapsulated Postscript) will be placed in the datastream in their native form using a MO:DCA Object Container.
+ The default value for the images "mode" setting is "b+w" (black and white). When the images "mode" setting is "b+w" a "bits-per-pixel" setting can be provided to aid the grayscale conversion process. With this setting all images referenced in your source document are converted to an IOCA FS45 grayscale bitmap image form.
+ When the setting is "color" all images are converted to an IOCA FS45 color bitmap image form. When "native" setting is "true", all images encountered (TIFF, GIF, JPEG and Encapsulated Postscript etc.) will be embedded directly in the datastream in their native form using a MO:DCA Object Container.
</p>
<p>
The default value for the "renderer-resolution" is 240 dpi.
--- /dev/null
+org.apache.fop.render.afp.AFPImageHandlerRenderedImage\r
+org.apache.fop.render.afp.AFPImageHandlerRawCCITTFax\r
+org.apache.fop.render.afp.AFPImageHandlerRawStream\r
+org.apache.fop.render.afp.AFPImageHandlerGraphics2D\r
+org.apache.fop.render.afp.AFPImageHandlerXML\r
+++ /dev/null
-/*
- * 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;
-
-import java.io.File;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.render.afp.extensions.AFPElementMapping;
-import org.apache.xmlgraphics.util.QName;
-
-/**
- * Parses any AFP foreign attributes
- */
-public class AFPForeignAttributeReader {
- private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
-
- /** the resource-name attribute */
- public static final String RESOURCE_NAME = "afp:resource-name";
-
- /** the resource-level attribute */
- public static final String RESOURCE_LEVEL = "afp:resource-level";
-
- /** the resource-group-file attribute */
- public static final String RESOURCE_GROUP_FILE = "afp:resource-group-file";
-
- /**
- * Main constructor
- */
- public AFPForeignAttributeReader() {
- }
-
- /**
- * Returns the resource information
- *
- * @param foreignAttributes the foreign attributes
- * @return the resource information
- */
- public AFPResourceInfo getResourceInfo(Map/*<QName, String>*/ foreignAttributes) {
- AFPResourceInfo resourceInfo = new AFPResourceInfo();
- if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
- QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME);
- String resourceName = (String)foreignAttributes.get(resourceNameKey);
- if (resourceName != null) {
- resourceInfo.setName(resourceName);
- }
- AFPResourceLevel level = getResourceLevel(foreignAttributes);
- if (level != null) {
- resourceInfo.setLevel(level);
- }
- }
- return resourceInfo;
- }
-
- /**
- * Returns the resource level
- *
- * @param foreignAttributes the foreign attributes
- * @return the resource level
- */
- public AFPResourceLevel getResourceLevel(Map/*<QName, String>*/ foreignAttributes) {
- AFPResourceLevel resourceLevel = null;
- if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
- QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL);
- if (foreignAttributes.containsKey(resourceLevelKey)) {
- String levelString = (String)foreignAttributes.get(resourceLevelKey);
- resourceLevel = AFPResourceLevel.valueOf(levelString);
- // if external get resource group file attributes
- if (resourceLevel != null && resourceLevel.isExternal()) {
- QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE,
- RESOURCE_GROUP_FILE);
- String resourceGroupFile
- = (String)foreignAttributes.get(resourceGroupFileKey);
- if (resourceGroupFile == null) {
- String msg = RESOURCE_GROUP_FILE + " not specified";
- log.error(msg);
- throw new UnsupportedOperationException(msg);
- }
- File resourceExternalGroupFile = new File(resourceGroupFile);
- SecurityManager security = System.getSecurityManager();
- try {
- if (security != null) {
- security.checkWrite(resourceExternalGroupFile.getPath());
- }
- } catch (SecurityException ex) {
- String msg = "unable to gain write access to external resource file: "
- + resourceGroupFile;
- log.error(msg);
- }
-
- try {
- boolean exists = resourceExternalGroupFile.exists();
- if (exists) {
- log.warn("overwriting external resource file: "
- + resourceGroupFile);
- }
- resourceLevel.setExternalFilePath(resourceGroupFile);
- } catch (SecurityException ex) {
- String msg = "unable to gain read access to external resource file: "
- + resourceGroupFile;
- log.error(msg);
- }
- }
- }
- }
- return resourceLevel;
- }
-}
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;
*
* @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);
* @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;
}
/**
*/
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;
}
/**
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) {
} 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];
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);
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
- imageObjectInfo.setBitsPerPixel(paintingState.getBitsPerPixel());
+ int bitsPerPixel = paintingState.getBitsPerPixel();
+ imageObjectInfo.setBitsPerPixel(bitsPerPixel);
imageObjectInfo.setResourceInfo(resourceInfo);
// convert to grayscale
if (!colorImages) {
boas.reset();
- int bitsPerPixel = paintingState.getBitsPerPixel();
imageObjectInfo.setBitsPerPixel(bitsPerPixel);
ImageEncodingHelper.encodeRGBAsGrayScale(
imageData, dataWidth, dataHeight, bitsPerPixel, boas);
// 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);
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);
return false;
}
- /** {@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);
+ }
}
/**
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);
+ }
}
package org.apache.fop.afp;
+import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
* @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);
}
/**
+++ /dev/null
-/*
- * 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;
-
-import org.apache.fop.afp.fonts.AFPFont;
-import org.apache.fop.afp.fonts.AFPFontAttributes;
-
-
-/**
- * Holds the current page fonts
- */
-public class AFPPageFonts extends java.util.HashMap {
- private static final long serialVersionUID = -4991896259427109041L;
-
- /**
- * Default constructor
- */
- public AFPPageFonts() {
- super();
- }
-
- /**
- * Parameterized constructor
- *
- * @param fonts an existing set of afp page fonts
- */
- public AFPPageFonts(AFPPageFonts fonts) {
- super(fonts);
- }
-
- /**
- * Registers a font on the current page and returns font attributes
- *
- * @param fontName the internal font name
- * @param font the AFPFont
- * @param fontSize the font point size
- * @return newly registered AFPFontAttributes
- */
- public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
- String pageFontKey = fontName + "_" + fontSize;
- AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
- // Add to page font mapping if not already present
- if (afpFontAttributes == null) {
- afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
- super.put(pageFontKey, afpFontAttributes);
- afpFontAttributes.setFontReference(super.size());
- }
- return afpFontAttributes;
- }
-}
\ No newline at end of file
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;
/**
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;
/**
* 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;
}
/**
*
* @return true if images are supported natively in this AFP environment
*/
- public boolean isNativeImages() {
- return this.nativeImages;
+ public boolean isNativeImagesSupported() {
+ return this.nativeImagesSupported;
}
/**
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;
* 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;
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";
*
* @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();
/** {@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;
os.write(buffer, 0, remainingChunkSize);
}
os.flush();
+// long end = System.currentTimeMillis();
+// log.debug("writing time " + (end - start) + "ms");
}
}
\ No newline at end of file
+++ /dev/null
-/*
- * 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;
-
-import org.apache.batik.bridge.SVGTextElementBridge;
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.TextPainter;
-import org.w3c.dom.Element;
-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.
- */
-public class AFPTextElementBridge extends SVGTextElementBridge {
-
- private AFPTextPainter textPainter;
-
- /**
- * Constructs a new bridge for the <text> element.
- * @param textPainter the text painter to use
- */
- public AFPTextElementBridge(AFPTextPainter 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
- * @return the text graphics node created by the super class
- */
- public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
- GraphicsNode node = super.createGraphicsNode(ctx, e);
- if (node != null && isSimple(ctx, e, node)) {
- ((TextNode)node).setTextPainter(getTextPainter());
- }
- 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
- * if the text is simple. The text is simple if it can be rendered
- * with basic text drawing algorithms. This means there are no
- * alternate characters, the font is known and there are no effects
- * applied to the text.
- *
- * @param ctx the bridge context
- * @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
- */
- private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
- for (Node n = element.getFirstChild();
- n != null;
- n = n.getNextSibling()) {
-
- switch (n.getNodeType()) {
- case Node.ELEMENT_NODE:
-
- if (n.getLocalName().equals(SVG_TSPAN_TAG)
- || n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
- return false;
- } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
- return false;
- } else if (n.getLocalName().equals(SVG_TREF_TAG)) {
- return false;
- }
- break;
- case Node.TEXT_NODE:
- case Node.CDATA_SECTION_NODE:
- default:
- }
- }
-
- /*if (CSSUtilities.convertFilter(element, node, ctx) != null) {
- return false;
- }*/
-
- return true;
- }
-}
-
+++ /dev/null
-/*
- * 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;
-
-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.fonts.AFPFont;
-import org.apache.fop.afp.fonts.AFPFontAttributes;
-import org.apache.fop.afp.modca.GraphicsObject;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.fonts.FontInfo;
-import org.apache.xmlgraphics.java2d.TextHandler;
-
-/**
- * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text
- * using AFP GOCA text operations.
- */
-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 */
- protected Font overrideFont = null;
-
- /**
- * Main constructor.
- *
- * @param g2d the AFPGraphics2D instance
- */
- public AFPTextHandler(AFPGraphics2D g2d) {
- this.g2d = g2d;
- }
-
- /**
- * Return the font information associated with this object
- *
- * @return the FontInfo object
- */
- public FontInfo getFontInfo() {
- return g2d.getFontInfo();
- }
-
- /**
- * Registers a page font
- *
- * @param internalFontName the internal font name
- * @param fontSize the font size
- * @return a font reference
- */
- private int registerPageFont(String internalFontName, int fontSize) {
- FontInfo fontInfo = getFontInfo();
- AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName);
- AFPPaintingState paintingState = g2d.getPaintingState();
- AFPPageFonts pageFonts = paintingState.getPageFonts();
- // register if necessary
- AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
- internalFontName,
- afpFont,
- fontSize
- );
- return afpFontAttributes.getFontReference();
- }
-
- /**
- * Add a text string to the current data object of the AFP datastream.
- * The text is painted using text operations.
- *
- * {@inheritDoc}
- */
- public void drawString(String str, float x, float y) throws IOException {
- log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
- GraphicsObject graphicsObj = g2d.getGraphicsObject();
- Color color = g2d.getColor();
-
- // set the color
- AFPPaintingState paintingState = g2d.getPaintingState();
- if (paintingState.setColor(color)) {
- graphicsObj.setColor(color);
- }
-
- // set the character set
- int fontReference = 0;
- if (overrideFont != null) {
- String internalFontName = overrideFont.getFontName();
- int fontSize = overrideFont.getFontSize();
- fontReference = registerPageFont(internalFontName, fontSize);
- } else {
- java.awt.Font awtFont = g2d.getFont();
- AffineTransform fontTransform = awtFont.getTransform();
- FontInfo fontInfo = getFontInfo();
- Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
- String internalFontName = fopFont.getFontName();
- int fontSize = fopFont.getFontSize();
- fontReference = registerPageFont(internalFontName, fontSize);
- }
- 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]));
- }
-
- /**
- * Sets the overriding font.
- *
- * @param overrideFont Overriding Font to set
- */
- public void setOverrideFont(Font overrideFont) {
- this.overrideFont = overrideFont;
- }
-}
+++ /dev/null
-/*
- * 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;
-
-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.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-import java.text.AttributedCharacterIterator;
-import java.text.CharacterIterator;
-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;
-
-
-/**
- * Renders the attributed character iterator of a <tt>TextNode</tt>.
- * This class draws the text directly into the AFPGraphics2D so that
- * the text is not drawn using shapes.
- * If the text is simple enough to draw then it sets the font and calls
- * drawString. If the text is complex or the cannot be translated
- * into a simple drawString the StrokingTextPainter is used instead.
- */
-public class AFPTextPainter implements TextPainter {
-
- /** the logger for this class */
- protected Log log = LogFactory.getLog(AFPTextPainter.class);
-
- private final AFPTextHandler nativeTextHandler;
-
- /**
- * Use the stroking text painter to get the bounds and shape.
- * Also used as a fallback to draw the string with strokes.
- */
- protected static final TextPainter
- PROXY_PAINTER = StrokingTextPainter.getInstance();
-
- /**
- * Create a new PS text painter with the given font information.
- * @param nativeTextHandler the NativeTextHandler instance used for text painting
- */
- public AFPTextPainter(AFPTextHandler nativeTextHandler) {
- this.nativeTextHandler = nativeTextHandler;
- }
-
- /**
- * 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
- */
- public void paint(TextNode node, Graphics2D g2d) {
- Point2D loc = node.getLocation();
- log.debug("painting text node " + node);
- if (hasUnsupportedAttributes(node)) {
- log.debug("hasunsuportedattributes");
- PROXY_PAINTER.paint(node, g2d);
- } else {
- log.debug("allattributessupported");
- paintTextRuns(node.getTextRuns(), g2d, loc);
- }
- }
-
- private boolean hasUnsupportedAttributes(TextNode node) {
- Iterator iter = node.getTextRuns().iterator();
- while (iter.hasNext()) {
- StrokingTextPainter.TextRun
- run = (StrokingTextPainter.TextRun)iter.next();
- AttributedCharacterIterator aci = run.getACI();
- boolean hasUnsupported = hasUnsupportedAttributes(aci);
- if (hasUnsupported) {
- return true;
- }
- }
- return false;
- }
-
- private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
- boolean hasUnsupported = false;
-
- String text = getText(aci);
- Font font = makeFont(aci);
- if (hasUnsupportedGlyphs(text, font)) {
- log.trace("-> Unsupported glyphs found");
- hasUnsupported = true;
- }
-
- TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
- if ((tpi != null)
- && ((tpi.strokeStroke != null && tpi.strokePaint != null)
- || (tpi.strikethroughStroke != null)
- || (tpi.underlineStroke != null)
- || (tpi.overlineStroke != null))) {
- log.trace("-> under/overlines etc. found");
- hasUnsupported = true;
- }
-
- //Alpha is not supported
- Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
- if (foreground instanceof Color) {
- Color col = (Color)foreground;
- if (col.getAlpha() != 255) {
- log.trace("-> transparency found");
- hasUnsupported = true;
- }
- }
-
- Object letSpace = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
- if (letSpace != null) {
- log.trace("-> letter spacing found");
- hasUnsupported = true;
- }
-
- Object wordSpace = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
- if (wordSpace != null) {
- log.trace("-> word spacing found");
- hasUnsupported = true;
- }
-
- Object lengthAdjust = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
- if (lengthAdjust != null) {
- log.trace("-> length adjustments found");
- hasUnsupported = true;
- }
-
- Object writeMod = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
- if (writeMod != null
- && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
- writeMod)) {
- log.trace("-> Unsupported writing modes found");
- hasUnsupported = true;
- }
-
- Object vertOr = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
- if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
- vertOr)) {
- log.trace("-> vertical orientation found");
- hasUnsupported = true;
- }
-
- Object rcDel = aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
- //Batik 1.6 returns null here which makes it impossible to determine whether this can
- //be painted or not, i.e. fall back to stroking. :-(
- if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
- log.trace("-> spans found");
- hasUnsupported = true; //Filter spans
- }
-
- if (hasUnsupported) {
- log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
- }
- return hasUnsupported;
- }
-
- /**
- * Paint a list of text runs on the Graphics2D at a given location.
- * @param textRuns the list of text runs
- * @param g2d the Graphics2D to paint to
- * @param loc the current location of the "cursor"
- */
- protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
- Point2D currentloc = loc;
- Iterator i = textRuns.iterator();
- while (i.hasNext()) {
- StrokingTextPainter.TextRun
- run = (StrokingTextPainter.TextRun)i.next();
- currentloc = paintTextRun(run, g2d, currentloc);
- }
- }
-
- /**
- * Paint a single text run on the Graphics2D at a given location.
- * @param run the text run to paint
- * @param g2d the Graphics2D to paint to
- * @param loc the current location of the "cursor"
- * @return the new location of the "cursor" after painting the text run
- */
- protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
- AttributedCharacterIterator aci = run.getACI();
- aci.first();
-
- updateLocationFromACI(aci, loc);
- loc = g2d.getTransform().transform(loc, null);
-
- // font
- Font font = makeFont(aci);
- nativeTextHandler.setOverrideFont(font);
-
- // color
- TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
- if (tpi == null) {
- return loc;
- }
- Paint foreground = tpi.fillPaint;
- if (foreground instanceof Color) {
- Color col = (Color)foreground;
- g2d.setColor(col);
- }
- g2d.setPaint(foreground);
-
- String txt = getText(aci);
- float advance = getStringWidth(txt, font);
- float tx = 0;
- TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
- if (anchor != null) {
- switch (anchor.getType()) {
- case TextNode.Anchor.ANCHOR_MIDDLE:
- tx = -advance / 2;
- break;
- case TextNode.Anchor.ANCHOR_END:
- tx = -advance;
- break;
- default: //nop
- }
- }
-
- // draw string
- try {
- try {
- nativeTextHandler.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY()));
- } catch (IOException ioe) {
- if (g2d instanceof AFPGraphics2D) {
- ((AFPGraphics2D)g2d).handleIOException(ioe);
- }
- }
- } finally {
- nativeTextHandler.setOverrideFont(null);
- }
- loc.setLocation(loc.getX() + advance, loc.getY());
- return loc;
- }
-
- /**
- * Extract the raw text from an ACI.
- * @param aci ACI to inspect
- * @return the extracted text
- */
- protected String getText(AttributedCharacterIterator aci) {
- StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
- for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
- sb.append(c);
- }
- return sb.toString();
- }
-
- private void updateLocationFromACI(
- AttributedCharacterIterator aci,
- Point2D loc) {
- //Adjust position of span
- Float xpos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.X);
- Float ypos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.Y);
- Float dxpos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.DX);
- Float dypos = (Float)aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.DY);
- if (xpos != null) {
- loc.setLocation(xpos.doubleValue(), loc.getY());
- }
- if (ypos != null) {
- loc.setLocation(loc.getX(), ypos.doubleValue());
- }
- if (dxpos != null) {
- loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
- }
- if (dypos != null) {
- loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
- }
- }
-
- private String getStyle(AttributedCharacterIterator aci) {
- Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
- return ((posture != null) && (posture.floatValue() > 0.0))
- ? Font.STYLE_ITALIC
- : Font.STYLE_NORMAL;
- }
-
- private int getWeight(AttributedCharacterIterator aci) {
- Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
- return ((taWeight != null) && (taWeight.floatValue() > 1.0))
- ? Font.WEIGHT_BOLD
- : Font.WEIGHT_NORMAL;
- }
-
- private Font makeFont(AttributedCharacterIterator aci) {
- Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
- if (fontSize == null) {
- fontSize = new Float(10.0f);
- }
- String style = getStyle(aci);
- int weight = getWeight(aci);
-
- FontInfo fontInfo = nativeTextHandler.getFontInfo();
- String fontFamily = null;
- List gvtFonts = (List) aci.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
- if (gvtFonts != null) {
- Iterator i = gvtFonts.iterator();
- while (i.hasNext()) {
- GVTFontFamily fam = (GVTFontFamily) i.next();
- /* (todo) Enable SVG Font painting
- if (fam instanceof SVGFontFamily) {
- PROXY_PAINTER.paint(node, g2d);
- return;
- }*/
- fontFamily = fam.getFamilyName();
- if (fontInfo.hasFont(fontFamily, style, weight)) {
- FontTriplet triplet = fontInfo.fontLookup(
- fontFamily, style, weight);
- int fsize = (int)(fontSize.floatValue() * 1000);
- return fontInfo.getFontInstance(triplet, fsize);
- }
- }
- }
- FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
- int fsize = (int)(fontSize.floatValue() * 1000);
- return fontInfo.getFontInstance(triplet, fsize);
- }
-
- private float getStringWidth(String str, Font font) {
- float wordWidth = 0;
- float whitespaceWidth = font.getWidth(font.mapChar(' '));
-
- for (int i = 0; i < str.length(); i++) {
- float charWidth;
- char c = str.charAt(i);
- if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
- charWidth = font.getWidth(font.mapChar(c));
- if (charWidth <= 0) {
- charWidth = whitespaceWidth;
- }
- } else {
- charWidth = whitespaceWidth;
- }
- wordWidth += charWidth;
- }
- return wordWidth / 1000f;
- }
-
- private boolean hasUnsupportedGlyphs(String str, Font font) {
- for (int i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
- if (!font.hasChar(c)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Get the outline shape of the text characters.
- * This uses the StrokingTextPainter to get the outline
- * shape since in theory it should be the same.
- *
- * @param node the text node
- * @return the outline shape of the text characters
- */
- public Shape getOutline(TextNode node) {
- return PROXY_PAINTER.getOutline(node);
- }
-
- /**
- * Get the 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
- */
- public Rectangle2D getBounds2D(TextNode node) {
- /* (todo) getBounds2D() is too slow
- * because it uses the StrokingTextPainter. We should implement this
- * method ourselves. */
- return PROXY_PAINTER.getBounds2D(node);
- }
-
- /**
- * 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
- */
- public Rectangle2D getGeometryBounds(TextNode node) {
- return PROXY_PAINTER.getGeometryBounds(node);
- }
-
- // Methods that have no purpose for PS
-
- /**
- * 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
- * @return null
- */
- public Mark getMark(TextNode node, int pos, boolean all) {
- return null;
- }
-
- /**
- * 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
- * @return null
- */
- public Mark selectAt(double x, double y, TextNode node) {
- return null;
- }
-
- /**
- * 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
- * @return null
- */
- public Mark selectTo(double x, double y, Mark beginMark) {
- return null;
- }
-
- /**
- * Selec first.
- * This does nothing since the output is AFP and not interactive.
- * @param node the text node
- * @return null
- */
- public Mark selectFirst(TextNode node) {
- return null;
- }
-
- /**
- * Select last.
- * This does nothing since the output is AFP and not interactive.
- * @param node the text node
- * @return null
- */
- public Mark selectLast(TextNode node) {
- return null;
- }
-
- /**
- * 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
- */
- public int[] getSelected(Mark start, Mark finish) {
- return null;
- }
-
- /**
- * 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
- */
- public Shape getHighlightShape(Mark beginMark, Mark endMark) {
- return null;
- }
-
-}
/** {@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);
}
* 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
}
/**
+ * Return the font
+ *
* @return the font
*/
public AFPFont getFont() {
}
/**
+ * Return the FontKey attribute
+ *
* @return the FontKey attribute
*/
public String getFontKey() {
}
/**
+ * Return the point size attribute
+ *
* @return the point size attribute
*/
public int getPointSize() {
}
/**
+ * Return the FontReference attribute
+ *
* @return the FontReference attribute
*/
public int getFontReference() {
/**
* Sets the FontReference attribute
+ *
* @param fontReference the FontReference to set
*/
public void setFontReference(int fontReference) {
--- /dev/null
+/*
+ * 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.fonts;
+
+/**
+ * Holds the current page fonts
+ */
+public class AFPPageFonts extends java.util.HashMap {
+ private static final long serialVersionUID = -4991896259427109041L;
+
+ /**
+ * Default constructor
+ */
+ public AFPPageFonts() {
+ super();
+ }
+
+ /**
+ * Parameterized constructor
+ *
+ * @param fonts an existing set of afp page fonts
+ */
+ public AFPPageFonts(AFPPageFonts fonts) {
+ super(fonts);
+ }
+
+ /**
+ * Registers a font on the current page and returns font attributes
+ *
+ * @param fontName the internal font name
+ * @param font the AFPFont
+ * @param fontSize the font point size
+ * @return newly registered AFPFontAttributes
+ */
+ public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
+ String pageFontKey = fontName + "_" + fontSize;
+ AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
+ // Add to page font mapping if not already present
+ if (afpFontAttributes == null) {
+ afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
+ super.put(pageFontKey, afpFontAttributes);
+ afpFontAttributes.setFontReference(super.size());
+ }
+ return afpFontAttributes;
+ }
+}
\ No newline at end of file
--- /dev/null
+<!--
+ 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
* 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;
--- /dev/null
+/*
+ * 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
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 {
--- /dev/null
+/*
+ * 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
--- /dev/null
+<!--
+ 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
--- /dev/null
+<!--
+ 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
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;
* @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));
+ }
}
/**
* @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));
+ }
}
/**
copySF(data, Type.END, Category.GRAPHICS);
os.write(data);
}
+
}
\ No newline at end of file
--- /dev/null
+<!--
+ 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
--- /dev/null
+<!--
+ 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
--- /dev/null
+<!--
+ 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
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
+
--- /dev/null
+/*
+ * 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.Color;
+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;
+import org.apache.xmlgraphics.java2d.TextHandler;
+
+/**
+ * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text
+ * using AFP GOCA text operations.
+ */
+public class AFPTextHandler implements TextHandler {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(AFPTextHandler.class);
+
+ private AFPGraphics2D g2d = null;
+
+ /** Overriding FontState */
+ protected Font overrideFont = null;
+
+ /**
+ * Main constructor.
+ *
+ * @param g2d the AFPGraphics2D instance
+ */
+ public AFPTextHandler(AFPGraphics2D g2d) {
+ this.g2d = g2d;
+ }
+
+ /**
+ * Return the font information associated with this object
+ *
+ * @return the FontInfo object
+ */
+ public FontInfo getFontInfo() {
+ return g2d.getFontInfo();
+ }
+
+ /**
+ * Registers a page font
+ *
+ * @param internalFontName the internal font name
+ * @param fontSize the font size
+ * @return a font reference
+ */
+ private int registerPageFont(String internalFontName, int fontSize) {
+ FontInfo fontInfo = getFontInfo();
+ AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName);
+ AFPPaintingState paintingState = g2d.getPaintingState();
+ AFPPageFonts pageFonts = paintingState.getPageFonts();
+ // register if necessary
+ AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
+ internalFontName,
+ afpFont,
+ fontSize
+ );
+ return afpFontAttributes.getFontReference();
+ }
+
+ /**
+ * Add a text string to the current data object of the AFP datastream.
+ * The text is painted using text operations.
+ *
+ * {@inheritDoc}
+ */
+ public void drawString(String str, float x, float y) throws IOException {
+ log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
+ GraphicsObject graphicsObj = g2d.getGraphicsObject();
+ Color color = g2d.getColor();
+
+ // set the color
+ AFPPaintingState paintingState = g2d.getPaintingState();
+ if (paintingState.setColor(color)) {
+ graphicsObj.setColor(color);
+ }
+
+ // set the character set
+ int fontReference = 0;
+ if (overrideFont != null) {
+ String internalFontName = overrideFont.getFontName();
+ int fontSize = overrideFont.getFontSize();
+ fontReference = registerPageFont(internalFontName, fontSize);
+ } else {
+ java.awt.Font awtFont = g2d.getFont();
+// AffineTransform fontTransform = awtFont.getTransform();
+ FontInfo fontInfo = getFontInfo();
+ Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
+ String internalFontName = fopFont.getFontName();
+ int fontSize = fopFont.getFontSize();
+ fontReference = registerPageFont(internalFontName, fontSize);
+ }
+ graphicsObj.setCharacterSet(fontReference);
+
+ // add the character string
+ graphicsObj.addString(str, Math.round(x), Math.round(y));
+ }
+
+ /**
+ * Sets the overriding font.
+ *
+ * @param overrideFont Overriding Font to set
+ */
+ public void setOverrideFont(Font overrideFont) {
+ this.overrideFont = overrideFont;
+ }
+}
--- /dev/null
+/*
+ * 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.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;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+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.afp.AFPGraphics2D;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+
+
+/**
+ * Renders the attributed character iterator of a <tt>TextNode</tt>.
+ * This class draws the text directly into the AFPGraphics2D so that
+ * the text is not drawn using shapes.
+ * If the text is simple enough to draw then it sets the font and calls
+ * drawString. If the text is complex or the cannot be translated
+ * into a simple drawString the StrokingTextPainter is used instead.
+ */
+public class AFPTextPainter implements TextPainter {
+
+ /** the logger for this class */
+ protected Log log = LogFactory.getLog(AFPTextPainter.class);
+
+ private final AFPTextHandler nativeTextHandler;
+
+ /**
+ * Use the stroking text painter to get the bounds and shape.
+ * Also used as a fallback to draw the string with strokes.
+ */
+ protected static final TextPainter
+ PROXY_PAINTER = StrokingTextPainter.getInstance();
+
+ /**
+ * Create a new PS text painter with the given font information.
+ * @param nativeTextHandler the NativeTextHandler instance used for text painting
+ */
+ public AFPTextPainter(AFPTextHandler nativeTextHandler) {
+ this.nativeTextHandler = nativeTextHandler;
+ }
+
+ /**
+ * 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
+ */
+ public void paint(TextNode node, Graphics2D g2d) {
+ Point2D loc = node.getLocation();
+ log.debug("painting text node " + node);
+ if (hasUnsupportedAttributes(node)) {
+ log.debug("hasUnsuportedAttributes");
+ PROXY_PAINTER.paint(node, g2d);
+ } else {
+ log.debug("allAttributesSupported");
+ paintTextRuns(node.getTextRuns(), g2d, loc);
+ }
+ }
+
+ private boolean hasUnsupportedAttributes(TextNode node) {
+ Iterator iter = node.getTextRuns().iterator();
+ while (iter.hasNext()) {
+ StrokingTextPainter.TextRun
+ run = (StrokingTextPainter.TextRun)iter.next();
+ AttributedCharacterIterator aci = run.getACI();
+ boolean hasUnsupported = hasUnsupportedAttributes(aci);
+ if (hasUnsupported) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
+ boolean hasUnsupported = false;
+
+ String text = getText(aci);
+ Font font = makeFont(aci);
+ if (hasUnsupportedGlyphs(text, font)) {
+ log.trace("-> Unsupported glyphs found");
+ hasUnsupported = true;
+ }
+
+ TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+ if ((tpi != null)
+ && ((tpi.strokeStroke != null && tpi.strokePaint != null)
+ || (tpi.strikethroughStroke != null)
+ || (tpi.underlineStroke != null)
+ || (tpi.overlineStroke != null))) {
+ log.trace("-> under/overlines etc. found");
+ hasUnsupported = true;
+ }
+
+ //Alpha is not supported
+ Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
+ if (foreground instanceof Color) {
+ Color col = (Color)foreground;
+ if (col.getAlpha() != 255) {
+ log.trace("-> transparency found");
+ hasUnsupported = true;
+ }
+ }
+
+ Object letSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
+ if (letSpace != null) {
+ log.trace("-> letter spacing found");
+ hasUnsupported = true;
+ }
+
+ Object wordSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
+ if (wordSpace != null) {
+ log.trace("-> word spacing found");
+ hasUnsupported = true;
+ }
+
+ Object lengthAdjust = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
+ if (lengthAdjust != null) {
+ log.trace("-> length adjustments found");
+ hasUnsupported = true;
+ }
+
+ Object writeMod = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
+ if (writeMod != null
+ && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
+ writeMod)) {
+ log.trace("-> Unsupported writing modes found");
+ hasUnsupported = true;
+ }
+
+ Object vertOr = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
+ if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
+ vertOr)) {
+ log.trace("-> vertical orientation found");
+ hasUnsupported = true;
+ }
+
+ Object rcDel = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
+ //Batik 1.6 returns null here which makes it impossible to determine whether this can
+ //be painted or not, i.e. fall back to stroking. :-(
+ if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
+ log.trace("-> spans found");
+ hasUnsupported = true; //Filter spans
+ }
+
+ if (hasUnsupported) {
+ log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
+ }
+ return hasUnsupported;
+ }
+
+ /**
+ * Paint a list of text runs on the Graphics2D at a given location.
+ * @param textRuns the list of text runs
+ * @param g2d the Graphics2D to paint to
+ * @param loc the current location of the "cursor"
+ */
+ protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
+ Point2D currentloc = loc;
+ Iterator i = textRuns.iterator();
+ while (i.hasNext()) {
+ StrokingTextPainter.TextRun
+ run = (StrokingTextPainter.TextRun)i.next();
+ currentloc = paintTextRun(run, g2d, currentloc);
+ }
+ }
+
+ /**
+ * Paint a single text run on the Graphics2D at a given location.
+ * @param run the text run to paint
+ * @param g2d the Graphics2D to paint to
+ * @param loc the current location of the "cursor"
+ * @return the new location of the "cursor" after painting the text run
+ */
+ protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
+ AttributedCharacterIterator aci = run.getACI();
+ aci.first();
+
+ updateLocationFromACI(aci, loc);
+ AffineTransform at = g2d.getTransform();
+ loc = at.transform(loc, null);
+
+ // font
+ Font font = makeFont(aci);
+ nativeTextHandler.setOverrideFont(font);
+
+ // color
+ TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+ if (tpi == null) {
+ return loc;
+ }
+ Paint foreground = tpi.fillPaint;
+ if (foreground instanceof Color) {
+ Color col = (Color)foreground;
+ g2d.setColor(col);
+ }
+ g2d.setPaint(foreground);
+
+ // text
+ String txt = getText(aci);
+ float advance = getStringWidth(txt, font);
+ float tx = 0;
+ TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+ if (anchor != null) {
+ switch (anchor.getType()) {
+ case TextNode.Anchor.ANCHOR_MIDDLE:
+ tx = -advance / 2;
+ break;
+ case TextNode.Anchor.ANCHOR_END:
+ tx = -advance;
+ break;
+ default: //nop
+ }
+ }
+
+ // draw string
+ double x = loc.getX();
+ double y = loc.getY();
+ try {
+ try {
+ nativeTextHandler.drawString(txt, (float)x + tx, (float)y);
+ } catch (IOException ioe) {
+ if (g2d instanceof AFPGraphics2D) {
+ ((AFPGraphics2D)g2d).handleIOException(ioe);
+ }
+ }
+ } finally {
+ nativeTextHandler.setOverrideFont(null);
+ }
+ loc.setLocation(loc.getX() + advance, loc.getY());
+ return loc;
+ }
+
+ /**
+ * Extract the raw text from an ACI.
+ * @param aci ACI to inspect
+ * @return the extracted text
+ */
+ protected String getText(AttributedCharacterIterator aci) {
+ StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
+ for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ private void updateLocationFromACI(
+ AttributedCharacterIterator aci,
+ Point2D loc) {
+ //Adjust position of span
+ Float xpos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.X);
+ Float ypos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.Y);
+ Float dxpos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DX);
+ Float dypos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DY);
+ if (xpos != null) {
+ loc.setLocation(xpos.doubleValue(), loc.getY());
+ }
+ if (ypos != null) {
+ loc.setLocation(loc.getX(), ypos.doubleValue());
+ }
+ if (dxpos != null) {
+ loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
+ }
+ if (dypos != null) {
+ loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
+ }
+ }
+
+ private String getStyle(AttributedCharacterIterator aci) {
+ Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
+ return ((posture != null) && (posture.floatValue() > 0.0))
+ ? Font.STYLE_ITALIC
+ : Font.STYLE_NORMAL;
+ }
+
+ private int getWeight(AttributedCharacterIterator aci) {
+ Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
+ return ((taWeight != null) && (taWeight.floatValue() > 1.0))
+ ? Font.WEIGHT_BOLD
+ : Font.WEIGHT_NORMAL;
+ }
+
+ private Font makeFont(AttributedCharacterIterator aci) {
+ Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
+ if (fontSize == null) {
+ fontSize = new Float(10.0f);
+ }
+ String style = getStyle(aci);
+ int weight = getWeight(aci);
+
+ FontInfo fontInfo = nativeTextHandler.getFontInfo();
+ String fontFamily = null;
+ List gvtFonts = (List) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+ if (gvtFonts != null) {
+ Iterator i = gvtFonts.iterator();
+ while (i.hasNext()) {
+ GVTFontFamily fam = (GVTFontFamily) i.next();
+ /* (todo) Enable SVG Font painting
+ if (fam instanceof SVGFontFamily) {
+ PROXY_PAINTER.paint(node, g2d);
+ return;
+ }*/
+ fontFamily = fam.getFamilyName();
+ if (fontInfo.hasFont(fontFamily, style, weight)) {
+ FontTriplet triplet = fontInfo.fontLookup(
+ fontFamily, style, weight);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ return fontInfo.getFontInstance(triplet, fsize);
+ }
+ }
+ }
+ FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ return fontInfo.getFontInstance(triplet, fsize);
+ }
+
+ private float getStringWidth(String str, Font font) {
+ float wordWidth = 0;
+ float whitespaceWidth = font.getWidth(font.mapChar(' '));
+
+ for (int i = 0; i < str.length(); i++) {
+ float charWidth;
+ char c = str.charAt(i);
+ if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+ charWidth = font.getWidth(font.mapChar(c));
+ if (charWidth <= 0) {
+ charWidth = whitespaceWidth;
+ }
+ } else {
+ charWidth = whitespaceWidth;
+ }
+ wordWidth += charWidth;
+ }
+ return wordWidth / 1000f;
+ }
+
+ private boolean hasUnsupportedGlyphs(String str, Font font) {
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+ if (!font.hasChar(c)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the outline shape of the text characters.
+ * This uses the StrokingTextPainter to get the outline
+ * shape since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the outline shape of the text characters
+ */
+ public Shape getOutline(TextNode node) {
+ return PROXY_PAINTER.getOutline(node);
+ }
+
+ /**
+ * Get the 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
+ */
+ public Rectangle2D getBounds2D(TextNode node) {
+ /* (todo) getBounds2D() is too slow
+ * because it uses the StrokingTextPainter. We should implement this
+ * method ourselves. */
+ return PROXY_PAINTER.getBounds2D(node);
+ }
+
+ /**
+ * 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
+ */
+ public Rectangle2D getGeometryBounds(TextNode node) {
+ return PROXY_PAINTER.getGeometryBounds(node);
+ }
+
+ // Methods that have no purpose for PS
+
+ /**
+ * 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
+ * @return null
+ */
+ public Mark getMark(TextNode node, int pos, boolean all) {
+ return null;
+ }
+
+ /**
+ * 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
+ * @return null
+ */
+ public Mark selectAt(double x, double y, TextNode node) {
+ return null;
+ }
+
+ /**
+ * 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
+ * @return null
+ */
+ public Mark selectTo(double x, double y, Mark beginMark) {
+ return null;
+ }
+
+ /**
+ * Selec first.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectFirst(TextNode node) {
+ return null;
+ }
+
+ /**
+ * Select last.
+ * This does nothing since the output is AFP and not interactive.
+ *
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectLast(TextNode node) {
+ return null;
+ }
+
+ /**
+ * 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
+ */
+ public int[] getSelected(Mark start, Mark finish) {
+ return null;
+ }
+
+ /**
+ * 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
+ */
+ public Shape getHighlightShape(Mark beginMark, Mark endMark) {
+ return null;
+ }
+
+}
}
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);
}
/**
+<!--
+ 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>
+<!--
+ 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>
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;
* @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);
}
* @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);
return root;
}
+ /**
+ * 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.
*
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();
//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);
}
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) {
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;
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+}
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;
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 {
return fontInfo.getFontInstance(triplet, size);
}
+ /**
+ * 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)
*/
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,
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
* 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;
}
/**
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.
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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.geom.Rectangle2D;
-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 AFPDataObjectInfoFactory {
- 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
- *
- * @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
- * @throws IOException thrown if an I/O exception of some sort has occurred.
- */
- public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
- AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();
-
- // set resource information
- AFPResourceInfo resourceInfo
- = foreignAttributeReader.getResourceInfo(rendererImageInfo.getForeignAttributes());
- resourceInfo.setUri(rendererImageInfo.getURI());
- dataObjectInfo.setResourceInfo(resourceInfo);
-
- // set object area
- AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
-
- Point origin = rendererImageInfo.getOrigin();
- Rectangle2D position = rendererImageInfo.getPosition();
- float srcX = origin.x + (float)position.getX();
- float srcY = origin.y + (float)position.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)position.getWidth()));
- objectAreaInfo.setWidth(width);
-
- int height = Math.round(unitConv.mpt2units((float)position.getHeight()));
- objectAreaInfo.setHeight(height);
-
- int resolution = state.getResolution();
- objectAreaInfo.setHeightRes(resolution);
- objectAreaInfo.setWidthRes(resolution);
-
- objectAreaInfo.setRotation(state.getRotation());
-
- dataObjectInfo.setObjectAreaInfo(objectAreaInfo);
-
- return dataObjectInfo;
- }
-
- /**
- * Creates the data object information object
- *
- * @return the data object information object
- */
- protected abstract AFPDataObjectInfo createDataObjectInfo();
-}
+++ /dev/null
-/*
- * 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;
- }
-}
--- /dev/null
+/*
+ * 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.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;
+
+/**
+ * Parses any AFP foreign attributes
+ */
+public class AFPForeignAttributeReader {
+ private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp");
+
+ /** the resource-name attribute */
+ public static final String RESOURCE_NAME = "afp:resource-name";
+
+ /** the resource-level attribute */
+ public static final String RESOURCE_LEVEL = "afp:resource-level";
+
+ /** the resource-group-file attribute */
+ public static final String RESOURCE_GROUP_FILE = "afp:resource-group-file";
+
+ /**
+ * Main constructor
+ */
+ public AFPForeignAttributeReader() {
+ }
+
+ /**
+ * Returns the resource information
+ *
+ * @param foreignAttributes the foreign attributes
+ * @return the resource information
+ */
+ public AFPResourceInfo getResourceInfo(Map/*<QName, String>*/ foreignAttributes) {
+ AFPResourceInfo resourceInfo = new AFPResourceInfo();
+ if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
+ QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME);
+ String resourceName = (String)foreignAttributes.get(resourceNameKey);
+ if (resourceName != null) {
+ resourceInfo.setName(resourceName);
+ }
+ AFPResourceLevel level = getResourceLevel(foreignAttributes);
+ if (level != null) {
+ resourceInfo.setLevel(level);
+ }
+ }
+ return resourceInfo;
+ }
+
+ /**
+ * Returns the resource level
+ *
+ * @param foreignAttributes the foreign attributes
+ * @return the resource level
+ */
+ public AFPResourceLevel getResourceLevel(Map/*<QName, String>*/ foreignAttributes) {
+ AFPResourceLevel resourceLevel = null;
+ if (foreignAttributes != null && !foreignAttributes.isEmpty()) {
+ QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL);
+ if (foreignAttributes.containsKey(resourceLevelKey)) {
+ String levelString = (String)foreignAttributes.get(resourceLevelKey);
+ resourceLevel = AFPResourceLevel.valueOf(levelString);
+ // if external get resource group file attributes
+ if (resourceLevel != null && resourceLevel.isExternal()) {
+ QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE,
+ RESOURCE_GROUP_FILE);
+ String resourceGroupFile
+ = (String)foreignAttributes.get(resourceGroupFileKey);
+ if (resourceGroupFile == null) {
+ String msg = RESOURCE_GROUP_FILE + " not specified";
+ log.error(msg);
+ throw new UnsupportedOperationException(msg);
+ }
+ File resourceExternalGroupFile = new File(resourceGroupFile);
+ SecurityManager security = System.getSecurityManager();
+ try {
+ if (security != null) {
+ security.checkWrite(resourceExternalGroupFile.getPath());
+ }
+ } catch (SecurityException ex) {
+ String msg = "unable to gain write access to external resource file: "
+ + resourceGroupFile;
+ log.error(msg);
+ }
+
+ try {
+ boolean exists = resourceExternalGroupFile.exists();
+ if (exists) {
+ log.warn("overwriting external resource file: "
+ + resourceGroupFile);
+ }
+ resourceLevel.setExternalFilePath(resourceGroupFile);
+ } catch (SecurityException ex) {
+ String msg = "unable to gain read access to external resource file: "
+ + resourceGroupFile;
+ log.error(msg);
+ }
+ }
+ }
+ }
+ return resourceLevel;
+ }
+}
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;
*/
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));
}
}
+++ /dev/null
-/*
- * 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;
- }
-
-}
--- /dev/null
+/*
+ * 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.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.fop.afp.AFPDataObjectInfo;
+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;
+
+public abstract class AFPImageHandler implements ImageHandler {
+ private static final int X = 0;
+ private static final int Y = 1;
+
+ /** foreign attribute reader */
+ private final AFPForeignAttributeReader foreignAttributeReader
+ = new AFPForeignAttributeReader();
+
+ /**
+ * Generates an intermediate AFPDataObjectInfo that is later used to construct
+ * the appropriate data object in the AFP DataStream.
+ *
+ * @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 generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+ AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();
+
+ // set resource information
+ Map foreignAttributes = rendererImageInfo.getForeignAttributes();
+ AFPResourceInfo resourceInfo
+ = foreignAttributeReader.getResourceInfo(foreignAttributes);
+ resourceInfo.setUri(rendererImageInfo.getURI());
+ dataObjectInfo.setResourceInfo(resourceInfo);
+
+ // set object area
+ AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
+
+ Point origin = rendererImageInfo.getOrigin();
+ Rectangle2D position = rendererImageInfo.getPosition();
+ float srcX = origin.x + (float)position.getX();
+ float srcY = origin.y + (float)position.getY();
+
+ 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]);
+
+ int width = Math.round(unitConv.mpt2units((float)position.getWidth()));
+ objectAreaInfo.setWidth(width);
+
+ int height = Math.round(unitConv.mpt2units((float)position.getHeight()));
+ objectAreaInfo.setHeight(height);
+
+ int resolution = paintingState.getResolution();
+ objectAreaInfo.setHeightRes(resolution);
+ objectAreaInfo.setWidthRes(resolution);
+
+ objectAreaInfo.setRotation(paintingState.getRotation());
+
+ dataObjectInfo.setObjectAreaInfo(objectAreaInfo);
+
+ return dataObjectInfo;
+ }
+
+ /**
+ * Creates the data object information object
+ *
+ * @return the data object information object
+ */
+ protected abstract AFPDataObjectInfo createDataObjectInfo();
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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.AFPImageObjectInfo;
+import org.apache.fop.afp.AFPObjectAreaInfo;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
+
+/**
+ * PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4).
+ */
+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 generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+ AFPImageObjectInfo imageObjectInfo
+ = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+ ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.getImage();
+ imageObjectInfo.setCompression(ccitt.getCompression());
+
+ AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
+ ImageSize imageSize = ccitt.getSize();
+ int widthRes = (int) (imageSize.getDpiHorizontal() * 10);
+ objectAreaInfo.setWidthRes(widthRes);
+
+ int heightRes = (int) (imageSize.getDpiVertical() * 10);
+ objectAreaInfo.setHeightRes(heightRes);
+
+ imageObjectInfo.setInputStream(ccitt.createInputStream());
+
+ return imageObjectInfo;
+ }
+
+ /** {@inheritDoc} */
+ protected AFPDataObjectInfo createDataObjectInfo() {
+ return new AFPImageObjectInfo();
+ }
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 400;
+ }
+
+ /** {@inheritDoc} */
+ public Class[] getSupportedImageClasses() {
+ return CLASSES;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return FLAVORS;
+ }
+
+}
--- /dev/null
+/*
+ * 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 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;
+
+/**
+ * AFPImageHandler implementation which handles raw stream images.
+ */
+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 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();
+
+ 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);
+
+ InputStream inputStream = rawStream.createInputStream();
+ dataObjectInfo.setInputStream(inputStream);
+
+ int dataHeight = rawStream.getSize().getHeightPx();
+ dataObjectInfo.setDataHeight(dataHeight);
+
+ int dataWidth = rawStream.getSize().getWidthPx();
+ dataObjectInfo.setDataWidth(dataWidth);
+ return dataObjectInfo;
+ }
+
+ /** {@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();
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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.image.RenderedImage;
+import java.io.IOException;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+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;
+
+/**
+ * PDFImageHandler implementation which handles RenderedImage instances.
+ */
+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 generateDataObjectInfo(
+ AFPRendererImageInfo rendererImageInfo) throws IOException {
+ AFPImageObjectInfo imageObjectInfo
+ = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);
+
+ imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
+
+ AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
+ AFPRendererContext rendererContext
+ = (AFPRendererContext)rendererImageInfo.getRendererContext();
+ AFPInfo afpInfo = rendererContext.getInfo();
+ AFPPaintingState paintingState = afpInfo.getPaintingState();
+ int resolution = paintingState.getResolution();
+ objectAreaInfo.setWidthRes(resolution);
+ objectAreaInfo.setHeightRes(resolution);
+
+ ImageRendered imageRendered = (ImageRendered) rendererImageInfo.img;
+ RenderedImage renderedImage = imageRendered.getRenderedImage();
+
+ int dataHeight = renderedImage.getHeight();
+ imageObjectInfo.setDataHeight(dataHeight);
+
+ int dataWidth = renderedImage.getWidth();
+ imageObjectInfo.setDataWidth(dataWidth);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos);
+ byte[] imageData = baos.toByteArray();
+
+ boolean colorImages = paintingState.isColorImages();
+ imageObjectInfo.setColor(colorImages);
+
+ // convert to grayscale
+ if (!colorImages) {
+ baos.reset();
+ int bitsPerPixel = paintingState.getBitsPerPixel();
+ imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+ ImageEncodingHelper.encodeRGBAsGrayScale(
+ imageData, dataWidth, dataHeight, bitsPerPixel, baos);
+ imageData = baos.toByteArray();
+ }
+ imageObjectInfo.setData(imageData);
+
+ return imageObjectInfo;
+ }
+
+ /** {@inheritDoc} */
+ protected AFPDataObjectInfo createDataObjectInfo() {
+ return new AFPImageObjectInfo();
+ }
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 300;
+ }
+
+ /** {@inheritDoc} */
+ public Class[] getSupportedImageClasses() {
+ return CLASSES;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return FLAVORS;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
+++ /dev/null
-/*
- * 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 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.ImageInfo;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
-
-/**
- * A raw stream image data object info factory
- */
-public class AFPImageRawStreamFactory extends AFPDataObjectInfoFactory {
-
- /**
- * Main constructor
- *
- * @param state the AFP painting state
- */
- public AFPImageRawStreamFactory(AFPPaintingState state) {
- super(state);
- }
-
- /** {@inheritDoc} */
- public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
- AFPDataObjectInfo dataObjectInfo = super.create(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();
- objectAreaInfo.setWidthRes(resolution);
- objectAreaInfo.setHeightRes(resolution);
-
- InputStream inputStream = rawStream.createInputStream();
- dataObjectInfo.setInputStream(inputStream);
-
- int dataHeight = rawStream.getSize().getHeightPx();
- dataObjectInfo.setDataHeight(dataHeight);
-
- int dataWidth = rawStream.getSize().getWidthPx();
- dataObjectInfo.setDataWidth(dataWidth);
- return dataObjectInfo;
- }
-
- /** {@inheritDoc} */
- protected AFPDataObjectInfo createDataObjectInfo() {
- return new AFPDataObjectInfo();
- }
-}
+++ /dev/null
-/*
- * 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.image.RenderedImage;
-import java.io.IOException;
-
-import org.apache.commons.io.output.ByteArrayOutputStream;
-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.impl.ImageRendered;
-import org.apache.xmlgraphics.ps.ImageEncodingHelper;
-import org.apache.xmlgraphics.util.MimeConstants;
-
-/**
- * A buffered image data object info factory
- */
-public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory {
-
- /**
- * Main constructor
- *
- * @param state the AFP painting state
- */
- public AFPImageRenderedFactory(AFPPaintingState state) {
- super(state);
- }
-
- /** {@inheritDoc} */
- public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
- AFPImageObjectInfo imageObjectInfo
- = (AFPImageObjectInfo)super.create(rendererImageInfo);
-
- imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
-
- AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
- int resolution = state.getResolution();
- objectAreaInfo.setWidthRes(resolution);
- objectAreaInfo.setHeightRes(resolution);
-
- ImageRendered imageRendered = (ImageRendered) rendererImageInfo.img;
- RenderedImage renderedImage = imageRendered.getRenderedImage();
-
- int dataHeight = renderedImage.getHeight();
- imageObjectInfo.setDataHeight(dataHeight);
-
- int dataWidth = renderedImage.getWidth();
- imageObjectInfo.setDataWidth(dataWidth);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos);
- byte[] imageData = baos.toByteArray();
-
- boolean colorImages = state.isColorImages();
- imageObjectInfo.setColor(colorImages);
-
- // convert to grayscale
- if (!colorImages) {
- baos.reset();
- int bitsPerPixel = state.getBitsPerPixel();
- imageObjectInfo.setBitsPerPixel(bitsPerPixel);
- ImageEncodingHelper.encodeRGBAsGrayScale(
- imageData, dataWidth, dataHeight, bitsPerPixel, baos);
- imageData = baos.toByteArray();
- }
- imageObjectInfo.setData(imageData);
-
- return imageObjectInfo;
- }
-
- /** {@inheritDoc} */
- protected AFPDataObjectInfo createDataObjectInfo() {
- return new AFPImageObjectInfo();
- }
-}
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;
/** 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.
*
* @return the current AFP state
*/
public AFPPaintingState getPaintingState() {
- return this.state;
+ return this.paintingState;
}
/**
* @param state the AFP state
*/
public void setPaintingState(AFPPaintingState state) {
- this.state = state;
+ this.paintingState = state;
}
/**
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
+ ", cfg=" + handlerConfiguration
+ ", fontInfo=" + fontInfo
+ ", resourceManager=" + resourceManager
- + ", state=" + state
+ + ", paintingState=" + paintingState
+ ", paintAsBitmap=" + paintAsBitmap
+ ", resourceInfo=" + resourceInfo
+ "}";
+++ /dev/null
-/*
- * 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.AFPImageObjectInfo;
-import org.apache.fop.afp.AFPObjectAreaInfo;
-import org.apache.fop.afp.AFPPaintingState;
-import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
-
-/**
- * An CITT fax image data object info factory
- */
-public class AFPRawCCITTFaxFactory extends AFPDataObjectInfoFactory {
-
- /**
- * Main constructor
- *
- * @param state the AFP painting state
- */
- public AFPRawCCITTFaxFactory(AFPPaintingState state) {
- super(state);
- }
-
- /** {@inheritDoc} */
- public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
- AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)super.create(rendererImageInfo);
-
- ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.img;
- imageObjectInfo.setCompression(ccitt.getCompression());
-
- AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
- int xresol = (int) (ccitt.getSize().getDpiHorizontal() * 10);
- objectAreaInfo.setWidthRes(xresol);
-
- int yresol = (int) (ccitt.getSize().getDpiVertical() * 10);
- objectAreaInfo.setHeightRes(yresol);
-
- imageObjectInfo.setInputStream(ccitt.createInputStream());
-
- return imageObjectInfo;
- }
-
- /** {@inheritDoc} */
- protected AFPDataObjectInfo createDataObjectInfo() {
- return new AFPImageObjectInfo();
- }
-}
\ No newline at end of file
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;
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;
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;
*/
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;
super();
this.resourceManager = new AFPResourceManager();
this.paintingState = new AFPPaintingState();
- this.dataObjectInfoProvider = new AFPDataObjectInfoProvider(paintingState);
+ this.imageHandlerRegistry = new AFPImageHandlerRegistry();
this.unitConv = paintingState.getUnitConverter();
}
/** {@inheritDoc} */
public Graphics2DAdapter getGraphics2DAdapter() {
- return new AFPGraphics2DAdapter(this);
+ return new AFPGraphics2DAdapter(paintingState);
}
/** {@inheritDoc} */
rectanglePainter.paint(rectanglePaintInfo);
}
+ /** {@inheritDoc} */
+ protected RendererContext instantiateRendererContext() {
+ return new AFPRendererContext(this, getMimeType());
+ }
+
/** {@inheritDoc} */
protected RendererContext createRendererContext(int x, int y, int width,
int height, Map foreignAttributes) {
}
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();
// 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());
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();
* @param nativeImages
* native image support
*/
- public void setNativeImages(boolean nativeImages) {
- paintingState.setNativeImages(nativeImages);
+ public void setNativeImagesSupported(boolean nativeImages) {
+ paintingState.setNativeImagesSupported(nativeImages);
}
/**
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.
*
// 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);
+ 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);
-// }
}
}
}
--- /dev/null
+/*
+ * 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;
+ }
+}
/** the image */
protected final Image img;
- /** the AFP graphics 2d adapter */
- protected AFPGraphics2DAdapter g2dAdapter;
-
/** the renderer context */
protected RendererContext rendererContext;
* @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;
}
this.rendererContext = rendererContext;
}
- /**
- * Sets the graphics 2d adapter
- *
- * @param adapter the graphics 2d adapter
- */
- public void setGraphics2DAdapter(AFPGraphics2DAdapter adapter) {
- this.g2dAdapter = adapter;
- }
-
/**
* Returns the image info
*
return this.img;
}
- /**
- * Returns the graphics 2D adapter
- *
- * @return the graphics 2D adapter
- */
- public AFPGraphics2DAdapter getGraphics2DAdapter() {
- return this.g2dAdapter;
- }
-
/**
* Returns the renderer context
*
// 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;
/**
}
}
- /**
- * 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} */
}
/** {@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;
+++ /dev/null
-/*
- * 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);
- }
-
-}
--- /dev/null
+<!--
+ 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
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
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.
*/
ImageFlavor.GRAPHICS2D,
};
+ private static final Class[] CLASSES = new Class[] {
+ ImageGraphics2D.class,
+ };
+
/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
}
/** {@inheritDoc} */
- public Class getSupportedImageClass() {
- return ImageGraphics2D.class;
+ public Class[] getSupportedImageClasses() {
+ return CLASSES;
}
/** {@inheritDoc} */
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).
ImageFlavor.RAW_CCITTFAX,
};
+ private static final Class[] CLASSES = new Class[] {
+ ImageRawCCITTFax.class,
+ };
+
/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
}
/** {@inheritDoc} */
- public Class getSupportedImageClass() {
- return ImageRawCCITTFax.class;
+ public Class[] getSupportedImageClasses() {
+ return CLASSES;
}
/** {@inheritDoc} */
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.
ImageFlavor.RAW_JPEG,
};
+ private static final Class[] CLASSES = new Class[] {
+ ImageRawJPEG.class,
+ };
+
/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
}
/** {@inheritDoc} */
- public Class getSupportedImageClass() {
- return ImageRawJPEG.class;
+ public Class[] getSupportedImageClasses() {
+ return CLASSES;
}
/** {@inheritDoc} */
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);
- }
-
- }
- }
- }
}
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.
ImageFlavor.RENDERED_IMAGE
};
+ private static final Class[] CLASSES = new Class[] {
+ ImageRendered.class,
+ };
+
+
/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
}
/** {@inheritDoc} */
- public Class getSupportedImageClass() {
- return ImageRendered.class;
+ public Class[] getSupportedImageClasses() {
+ return CLASSES;
}
/** {@inheritDoc} */
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.
ImageFlavor.XML_DOM,
};
+ private static final Class[] CLASSES = new Class[] {
+ ImageXMLDOM.class,
+ };
+
/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
}
/** {@inheritDoc} */
- public Class getSupportedImageClass() {
- return ImageXMLDOM.class;
+ public Class[] getSupportedImageClasses() {
+ return CLASSES;
}
/** {@inheritDoc} */
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());
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;
/**
/** 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.
}
drawPrimitiveString(g2d, loc, font, txt, tx);
- loc.setLocation(loc.getX() + (double)advance, loc.getY());
+ loc.setLocation(loc.getX() + advance, loc.getY());
return loc;
}
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) {
--- /dev/null
+/*
+ * 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();
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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 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.w3c.dom.Element;
+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 abstract class AbstractFOPTextElementBridge extends SVGTextElementBridge {
+
+ /** text painter */
+ protected TextPainter textPainter;
+
+ /**
+ * Main constructor
+ *
+ * @param textPainter the text painter
+ */
+ 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
+ * @return the text graphics node created by the super class
+ */
+ public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
+ GraphicsNode node = super.createGraphicsNode(ctx, e);
+ if (node != null) {
+ //Set our own text painter
+ ((TextNode)node).setTextPainter(textPainter);
+ }
+ return node;
+ }
+
+ /**
+ * Check if text element contains simple text.
+ * This checks the children of the text element to determine
+ * if the text is simple. The text is simple if it can be rendered
+ * with basic text drawing algorithms. This means there are no
+ * alternate characters, the font is known and there are no effects
+ * applied to the text.
+ *
+ * @param ctx the bridge context
+ * @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 Graphics2D
+ */
+ protected boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
+ for (Node n = element.getFirstChild();
+ n != null;
+ n = n.getNextSibling()) {
+
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+
+ if (n.getLocalName().equals(SVG_TSPAN_TAG)
+ || n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
+ return false;
+ } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
+ return false;
+ } else if (n.getLocalName().equals(SVG_TREF_TAG)) {
+ return false;
+ }
+ break;
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ default:
+ }
+ }
+
+ /*if (CSSUtilities.convertFilter(element, node, ctx) != null) {
+ return false;
+ }*/
+
+ return true;
+ }
+
+}
+
--- /dev/null
+/*
+ * 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);
+
+}
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.
* 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);
}
/**
* @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);
}
/**
* @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} */
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");
}
* @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();
* @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();
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();
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.
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;
}
}
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.
*
* @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;
- }
-
}
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;
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.
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;