diff options
author | Adrian Cumiskey <acumiskey@apache.org> | 2008-03-27 16:16:30 +0000 |
---|---|---|
committer | Adrian Cumiskey <acumiskey@apache.org> | 2008-03-27 16:16:30 +0000 |
commit | f466690aaeed2dc93360d5f5f14fede90f2f5ad2 (patch) | |
tree | 33dc1c9a235eaf887ad80aaafa9c3990a87111ea /src/java/org/apache/fop | |
parent | 1105f2129784f6d85485ad222bdbc835473ee7ca (diff) | |
download | xmlgraphics-fop-f466690aaeed2dc93360d5f5f14fede90f2f5ad2.tar.gz xmlgraphics-fop-f466690aaeed2dc93360d5f5f14fede90f2f5ad2.zip |
Committing in preparation for trunk merge.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@641873 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop')
65 files changed, 4772 insertions, 1771 deletions
diff --git a/src/java/org/apache/fop/image/AbstractFopImage.java b/src/java/org/apache/fop/image/AbstractFopImage.java index 8d5180149..68949b9c9 100644 --- a/src/java/org/apache/fop/image/AbstractFopImage.java +++ b/src/java/org/apache/fop/image/AbstractFopImage.java @@ -360,7 +360,7 @@ public abstract class AbstractFopImage implements FopImage { * Return the original image data (compressed). * @return the original image data */ - public byte[] getRessourceBytes() { + public byte[] getResourceBytes() { return raw; } @@ -368,7 +368,7 @@ public abstract class AbstractFopImage implements FopImage { * Return the original image data size (compressed). * @return the original image data size */ - public int getRessourceBytesSize() { + public int getResourceBytesSize() { return (raw != null ? raw.length : 0); } diff --git a/src/java/org/apache/fop/image/FopImage.java b/src/java/org/apache/fop/image/FopImage.java index 0f780ad57..abe11ef25 100644 --- a/src/java/org/apache/fop/image/FopImage.java +++ b/src/java/org/apache/fop/image/FopImage.java @@ -168,13 +168,13 @@ public interface FopImage { * Returns the encoded/compressed image as an array of bytes. * @return the raw image */ - byte[] getRessourceBytes(); + byte[] getResourceBytes(); /** * Returns the number of bytes of the raw image. * @return the size in bytes */ - int getRessourceBytesSize(); + int getResourceBytesSize(); /** * Image info class. diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java index 3e477e224..974155630 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java @@ -44,14 +44,14 @@ import org.apache.batik.ext.awt.geom.ExtendedGeneralPath; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.modca.AFPDataStream; +import org.apache.fop.render.afp.goca.GraphicsSetLineType; import org.apache.fop.render.afp.modca.GraphicsObject; -import org.apache.fop.render.afp.modca.ImageObject; -import org.apache.fop.render.afp.modca.goca.GraphicsSetLineType; +import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; import org.apache.xmlgraphics.java2d.StrokingTextHandler; import org.apache.xmlgraphics.java2d.TextHandler; +import org.apache.xmlgraphics.ps.ImageEncodingHelper; /** * This is a concrete implementation of <tt>AbstractGraphics2D</tt> (and @@ -78,6 +78,9 @@ public class AFPGraphics2D extends AbstractGraphics2D { /** Current AFP state */ private AFPState afpState = null; + /** The SVG document URI */ + private String documentURI = null; + /** * @param textAsShapes * if true, all text is turned into shapes in the convertion. No @@ -295,7 +298,7 @@ public class AFPGraphics2D extends AbstractGraphics2D { graphicsObj.addBox(coords); } else if (shape instanceof Ellipse2D) { Ellipse2D elip = (Ellipse2D) shape; - final double factor = afpInfo.resolution / 100f; + final double factor = afpInfo.getResolution() / 100f; graphicsObj.setArcParams( (int)Math.round(elip.getWidth() * factor), (int)Math.round(elip.getHeight() * factor), @@ -345,26 +348,13 @@ public class AFPGraphics2D extends AbstractGraphics2D { */ public void handleIOException(IOException ioe) { // TODO Surely, there's a better way to do this. + log.error(ioe.getMessage()); ioe.printStackTrace(); } /** * {@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 void drawString(String s, float x, float y) { try { if (customTextHandler != null && !textAsShapes) { @@ -402,7 +392,7 @@ public class AFPGraphics2D extends AbstractGraphics2D { * {@inheritDoc} */ public void dispose() { - log.debug("dispose() NYI: "); + this.graphicsObj = null; } /** @@ -411,54 +401,62 @@ public class AFPGraphics2D extends AbstractGraphics2D { public boolean drawImage(Image img, int x, int y, ImageObserver observer) { return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), observer); } - + /** * {@inheritDoc} */ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { - log.debug("drawImage() img=" + img + ", x=" + x + ", y=" + y + //TODO: this might be achieved by creating a new IOCA image (ImageObject) + // and placing it in an Overlay - but then stacking order would not be preserved. + log.debug("drawImage(): NYI img=" + img + ", x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + ", obs=" + observer); - - int afpres = afpInfo.resolution; - int afpBitsPerPixel = afpInfo.bitsPerPixel; - int afpx = x; - int afpy = y; - int afpw = width; - int afph = height; - boolean colorImages = !afpInfo.grayscale; - int imageResolution = afpres; - if (img instanceof BufferedImage) { - BufferedImage bi = (BufferedImage)img; - ByteArrayOutputStream baout = new ByteArrayOutputStream(); - try { - // Serialize image - AFPRenderer.writeImage(bi, baout); - byte[] buf = baout.toByteArray(); - - // Generate image - AFPDataStream afpDataStream = afpInfo.afpDataStream; - ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, - afph, afpres, afpres); - io.setImageParameters(imageResolution, imageResolution, - afpw, afph); - if (colorImages) { - io.setImageIDESize((byte)24); - io.setImageData(buf); - } else { - AFPRenderer.convertToGrayScaleImage(io, buf, afpw, afph, afpBitsPerPixel); - } - } catch (IOException ioe) { - log.error("Error while serializing bitmap: " + ioe.getMessage(), - ioe); - return false; - } - return true; - } else { - log.debug("drawImage() NYI: img=" + img + ", x=" + x + ", y=" + y - + ", observer=" + observer); - } return false; +// log.debug("drawImage() img=" + img + ", x=" + x + ", y=" + y +// + ", width=" + width + ", height=" + height + ", obs=" + observer); +// if (img instanceof BufferedImage) { +// try { +// BufferedImage bi = (BufferedImage)img; +// ByteArrayOutputStream baout = new ByteArrayOutputStream(); +// +// // Serialize image +// ImageEncodingHelper.encodeRenderedImageAsRGB(bi, baout); +// +// int res = afpInfo.getResolution(); +// ImageObjectParameters params = new ImageObjectParameters( +// //TODO: provide a real url +// img.toString(), x, y, +// width, height, res, res, baout.toByteArray(), +// img.getWidth(observer), img.getHeight(observer), +// afpInfo.isColorSupported(), afpInfo.getBitsPerPixel()); +// +// afpInfo.getAFPDataStream().createImageObject(params); +// +// // Generate image +// } catch (IOException ioe) { +// log.error("Error while serializing bitmap: " + ioe.getMessage(), +// ioe); +// return false; +// } +// return true; +// } else { +// log.debug("drawImage() image type not supported: " + img); +// } +// 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); } /** @@ -489,18 +487,39 @@ public class AFPGraphics2D extends AbstractGraphics2D { } /** + * Sets the SVG document URI + * @param documentURI the SVG document URI + */ + public void setDocumentURI(String documentURI) { + this.documentURI = documentURI; + } + + /** * @return the GOCA graphics object */ protected GraphicsObject getGraphicsObject() { - if (this.graphicsObj == null) { - int x = (int)Math.round((afpInfo.currentXPosition * 25.4f) / 1000); - int y = (int)Math.round((afpInfo.currentYPosition * 25.4f) / 1000); - int res = afpInfo.resolution; - int width = (int)Math.round((afpInfo.width * res) / 72000f); - int height = (int)Math.round((afpInfo.height * res) / 72000f); - this.graphicsObj = afpInfo.getAFPDataStream().getGraphicsObject( - x, y, width, height, res, res); - } +// if (this.graphicsObj == null) { +//// DataObjectParameters params = new DataObjectParameters( +//// ((AbstractDocument)doc).getDocumentURI(), +//// afpInfo.getX(), afpInfo.getY(), +//// afpInfo.getWidth(), afpInfo.getHeight(), res, res); +//// +//// afpInfo.getAFPDataStream().createGraphicsObject(params); +// +// int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000); +// int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000); +// int res = afpInfo.getResolution(); +// int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f); +// int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f); +// DataObjectParameters params = new DataObjectParameters( +// this.documentURI, x, y, width, height, res, res); +// IncludeObject includeObj = afpInfo.getAFPDataStream().createGraphicsObject(params); +// this.graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); +// } return this.graphicsObj; } + + protected void setGraphicsObject(GraphicsObject graphicsObj) { + this.graphicsObj = graphicsObj; + } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index 687a0373e..1abe7c0d1 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -51,8 +51,11 @@ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { //Paint to a BufferedImage int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); - - afp.drawBufferedImage(bi, resolution, x, y, width, height); + + //TODO: uri + String uri = null; + java.util.Map foreignAttributes = null; + afp.drawBufferedImage(uri, bi, resolution, x, y, width, height, foreignAttributes); } } diff --git a/src/java/org/apache/fop/render/afp/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java index 026ab4dfe..19e58d30f 100644 --- a/src/java/org/apache/fop/render/afp/AFPInfo.java +++ b/src/java/org/apache/fop/render/afp/AFPInfo.java @@ -28,28 +28,28 @@ import org.apache.fop.render.afp.modca.AFPDataStream; */ public final class AFPInfo { /** see WIDTH */ - protected int width; + private int width; /** see HEIGHT */ - protected int height; + private int height; /** see XPOS */ - protected int currentXPosition; + private int x; /** see YPOS */ - protected int currentYPosition; + private int y; /** see HANDLER_CONFIGURATION */ - protected Configuration cfg; + private Configuration cfg; /** see AFP_FONT_INFO */ - protected FontInfo fontInfo; + private FontInfo fontInfo; /** See AFP_DATASTREAM */ - protected AFPDataStream afpDataStream; + private AFPDataStream afpDataStream; /** See AFP_STATE */ - protected AFPState afpState; + private AFPState afpState; /** see AFP_GRAYSCALE */ - protected boolean grayscale; + private boolean color; /** see AFP_RESOLUTION */ - protected int resolution; + private int resolution; /** see AFP_BITS_PER_PIXEL */ - protected int bitsPerPixel; + private int bitsPerPixel; /** * Returns the width. @@ -91,6 +91,14 @@ public final class AFPInfo { } /** + * Sets the handler configuration + * @param cfg the handler configuration + */ + public void setHandlerConfiguration(Configuration cfg) { + this.cfg = cfg; + } + + /** * @return FontInfo the font info */ public FontInfo getFontInfo() { @@ -115,6 +123,98 @@ public final class AFPInfo { * @return true if supports color */ public boolean isColorSupported() { - return !this.grayscale; + return this.color; + } + + /** + * @return the current x position coordinate + */ + protected int getX() { + return x; + } + + /** + * @return the current y position coordinate + */ + protected int getY() { + return y; + } + + /** + * @return the resolution + */ + protected int getResolution() { + return resolution; + } + + /** + * @return the number of bits per pixel to use + */ + protected int getBitsPerPixel() { + return bitsPerPixel; + } + + /** + * Sets the current x position coordinate + * @param x the current x position coordinate + */ + protected void setX(int x) { + this.x = x; + } + + /** + * Sets the current y position coordinate + * @param y the current y position coordinate + */ + protected void setY(int y) { + this.y = y; + } + + /** + * Sets the current resolution + * @param resolution the current resolution + */ + protected void setResolution(int resolution) { + this.resolution = resolution; + } + + /** + * Sets the current font info + * @param fontInfo the current font info + */ + protected void setFontInfo(FontInfo fontInfo) { + this.fontInfo = fontInfo; + } + + /** + * Sets the AFP state + * @param state the AFP state + */ + public void setState(AFPState state) { + this.afpState = state; + } + + /** + * Sets the AFP datastream + * @param afpDataStream the AFP datastream + */ + public void setAFPDataStream(AFPDataStream afpDataStream) { + this.afpDataStream = afpDataStream; + } + + /** + * Sets if we are supporing color + * @param color true if color is supported + */ + public void setColor(boolean color) { + this.color = color; + } + + /** + * Sets the number of bits per pixel + * @param bitsPerPixel the number of bits per pixel + */ + public void setBitsPerPixel(int bitsPerPixel) { + this.bitsPerPixel = bitsPerPixel; } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 5cdd55d98..b10f4b30f 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -23,6 +23,7 @@ import java.awt.Color; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.io.FileNotFoundException; @@ -30,8 +31,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -39,7 +38,6 @@ import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.image.loader.ImageInfo; @@ -58,6 +56,7 @@ import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; +import org.apache.fop.area.LineArea; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; import org.apache.fop.area.RegionReference; @@ -89,6 +88,7 @@ import org.apache.fop.render.afp.fonts.OutlineFont; import org.apache.fop.render.afp.modca.AFPConstants; import org.apache.fop.render.afp.modca.AFPDataStream; import org.apache.fop.render.afp.modca.ImageObject; +import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.fop.render.afp.modca.PageObject; /** @@ -139,28 +139,23 @@ import org.apache.fop.render.afp.modca.PageObject; * handle all types of inline area, text, image etc and draws various lines and * rectangles. * </p> - * - * Note: There are specific extensions that have been added to the FO. They are - * specific to their location within the FO and have to be processed accordingly - * (ie. at the start or end of the page). - * + * + * Note: There are specific extensions that have been added to the + * FO. They are specific to their location within the FO and have to be + * processed accordingly (ie. at the start or end of the page). + * */ public class AFPRenderer extends AbstractPathOrientedRenderer { /** - * 2400 dpi renderer resolution - */ - protected static final int DPI_240_RESOLUTION = 240; - - /** - * 14400 dpi renderer resolution + * The default afp renderer output resolution */ - protected static final int DPI_1440_RESOLUTION = 1440; + public static final int DPI_240_RESOLUTION = 240; /** * The afp factor for calculating resolutions (e.g. 72000/240 = 300) */ - protected static final int DPI_CONVERSION_FACTOR = 72000; + private static final int DPI_CONVERSION_FACTOR = 72000; /** * The afp data stream object responsible for generating afp data @@ -168,11 +163,46 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private AFPDataStream afpDataStream = null; /** + * The map of afp root extensions + */ + // UNUSED + // private HashMap rootExtensionMap = null; + /** * The map of page segments */ private Map pageSegmentsMap = null; /** + * The fonts on the current page + */ + private Map currentPageFonts = null; + + /** + * The current color object + */ + private Color currentColor = null; + + /** + * The page font number counter, used to determine the next font reference + */ + private int pageFontCounter = 0; + + /** + * The current font family + */ + // UNUSED + // private String currentFontFamily = ""; + /** + * The current font size + */ + private int currentFontSize = 0; + + /** + * The Options to be set on the AFPRenderer + */ + // UNUSED + // private Map afpOptions = null; + /** * The page width */ private int pageWidth = 0; @@ -183,6 +213,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private int pageHeight = 0; /** + * The current page sequence id + */ + // UNUSED + // private String pageSequenceId = null; + /** * The portrait rotation */ private int portraitRotation = 0; @@ -193,6 +228,21 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private int landscapeRotation = 270; /** + * The line cache, avoids drawing duplicate lines in tables. + */ + // UNUSED + // private HashSet lineCache = null; + /** + * The current x position for line drawing + */ + // UNUSED + // private float x; + /** + * The current y position for line drawing + */ + // UNUSED + // private float y; + /** * The map of saved incomplete pages */ private Map pages = null; @@ -213,7 +263,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private int resolution = DPI_240_RESOLUTION; /** drawing state */ - protected AFPState currentState = null; + private AFPState currentState = null; /** * Constructor for AFPRenderer. @@ -224,22 +274,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Set up the font info - * - * @param inFontInfo - * font info to set up + * + * @param inFontInfo font info to set up */ public void setupFontInfo(FontInfo inFontInfo) { this.fontInfo = inFontInfo; int num = 1; if (this.fontList != null && this.fontList.size() > 0) { for (Iterator it = this.fontList.iterator(); it.hasNext();) { - AFPFontInfo afi = (AFPFontInfo) it.next(); - AFPFont bf = (AFPFont) afi.getAFPFont(); - for (Iterator it2 = afi.getFontTriplets().iterator(); it2 - .hasNext();) { - FontTriplet ft = (FontTriplet) it2.next(); - this.fontInfo.addFontProperties("F" + num, ft.getName(), ft - .getStyle(), ft.getWeight()); + AFPFontInfo afi = (AFPFontInfo)it.next(); + AFPFont bf = (AFPFont)afi.getAFPFont(); + for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) { + FontTriplet ft = (FontTriplet)it2.next(); + this.fontInfo.addFontProperties("F" + num, ft.getName() + , ft.getStyle(), ft.getWeight()); this.fontInfo.addMetrics("F" + num, bf); num++; } @@ -248,36 +296,33 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { log.warn("No AFP fonts configured - using default setup"); } if (this.fontInfo.fontLookup("sans-serif", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", - "CZH200 ", 1, new Helvetica()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZH200 ", + 1, new Helvetica()); AFPFont bf = new OutlineFont("Helvetica", cs); - this.fontInfo.addFontProperties("F" + num, "sans-serif", "normal", - 400); + this.fontInfo.addFontProperties("F" + num, "sans-serif", "normal", 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("serif", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", - "CZN200 ", 1, new TimesRoman()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZN200 ", + 1, new TimesRoman()); AFPFont bf = new OutlineFont("Helvetica", cs); this.fontInfo.addFontProperties("F" + num, "serif", "normal", 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("monospace", "normal", 400) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", - "CZ4200 ", 1, new Courier()); + CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZ4200 ", + 1, new Courier()); AFPFont bf = new OutlineFont("Helvetica", cs); - this.fontInfo.addFontProperties("F" + num, "monospace", "normal", - 400); + this.fontInfo.addFontProperties("F" + num, "monospace", "normal", 400); this.fontInfo.addMetrics("F" + num, bf); num++; } if (this.fontInfo.fontLookup("any", "normal", 400) == null) { - FontTriplet ft = this.fontInfo.fontLookup("sans-serif", "normal", - 400); - this.fontInfo.addFontProperties(this.fontInfo - .getInternalFontKey(ft), "any", "normal", 400); + FontTriplet ft = this.fontInfo.fontLookup("sans-serif", "normal", 400); + this.fontInfo.addFontProperties( + this.fontInfo.getInternalFontKey(ft), "any", "normal", 400); } } @@ -292,54 +337,62 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ public void startRenderer(OutputStream outputStream) throws IOException { - this.currentState = new AFPState(); - this.afpDataStream = new AFPDataStream(); - this.afpDataStream.setPortraitRotation(portraitRotation); - this.afpDataStream.setLandscapeRotation(landscapeRotation); - this.afpDataStream.startDocument(outputStream); + currentPageFonts = new java.util.HashMap(); + currentColor = new Color(255, 255, 255); + afpDataStream = new AFPDataStream(); + afpDataStream.setPortraitRotation(portraitRotation); + afpDataStream.setLandscapeRotation(landscapeRotation); + afpDataStream.setOutputStream(outputStream); } /** * {@inheritDoc} */ public void stopRenderer() throws IOException { - this.afpDataStream.endDocument(); + afpDataStream.write(); } /** * {@inheritDoc} */ public boolean supportsOutOfOrder() { - // return false; + //return false; return true; } /** - * Prepare a page for rendering. This is called if the renderer supports out - * of order rendering. The renderer should prepare the page so that a page - * further on in the set of pages can be rendered. The body of the page - * should not be rendered. The page will be rendered at a later time by the - * call to render page. - * + * Prepare a page for rendering. This is called if the renderer supports + * out of order rendering. The renderer should prepare the page so that a + * page further on in the set of pages can be rendered. The body of the + * page should not be rendered. The page will be rendered at a later time + * by the call to render page. + * * {@inheritDoc} */ public void preparePage(PageViewport page) { + // initializeRootExtensions(page); - this.currentState.reset(); + // this.currentFontFamily = ""; + this.currentFontSize = 0; + this.pageFontCounter = 0; + this.currentPageFonts.clear(); + // this.lineCache = new HashSet(); Rectangle2D bounds = page.getViewArea(); this.pageWidth = mpts2units(bounds.getWidth()); this.pageHeight = mpts2units(bounds.getHeight()); + // renderPageGroupExtensions(page); + final int pageRotation = 0; this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, - this.resolution, this.resolution); + getResolution(), getResolution()); renderPageObjectExtensions(page); if (this.pages == null) { - this.pages = new HashMap(); + this.pages = new java.util.HashMap(); } this.pages.put(page, afpDataStream.savePage()); @@ -372,15 +425,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } /** - * Renders a region viewport. - * <p> - * - * The region may clip the area and it establishes a position from where the - * region is placed. - * </p> - * - * @param port - * The region viewport to be rendered + * Renders a region viewport. <p> + * + * The region may clip the area and it establishes a position from where + * the region is placed.</p> + * + * @param port The region viewport to be rendered */ public void renderRegionViewport(RegionViewport port) { if (port != null) { @@ -395,9 +445,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { handleRegionTraits(port); /* - * _afpDataStream.startOverlay(mpts2units(view.getX()) , - * mpts2units(view.getY()) , mpts2units(view.getWidth()) , - * mpts2units(view.getHeight()) , rotation); + _afpDataStream.startOverlay(mpts2units(view.getX()) + , mpts2units(view.getY()) + , mpts2units(view.getWidth()) + , mpts2units(view.getHeight()) + , rotation); */ pushViewPortPos(new ViewPortPos(view, regionReference.getCTM())); @@ -408,7 +460,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderRegion(regionReference); } /* - * _afpDataStream.endOverlay(); + _afpDataStream.endOverlay(); */ popViewPortPos(); } @@ -423,65 +475,77 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // save positions int saveIP = currentIPPosition; int saveBP = currentBPPosition; - // String saveFontName = currentFontName; CTM ctm = bv.getCTM(); int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); - float x, y; - x = (float) (bv.getXOffset() + containingIPPosition) / 1000f; - y = (float) (bv.getYOffset() + containingBPPosition) / 1000f; - // This is the content-rect - float width = (float) bv.getIPD() / 1000f; - float height = (float) bv.getBPD() / 1000f; + //This is the content-rect + float width = (float)bv.getIPD() / 1000f; + float height = (float)bv.getBPD() / 1000f; if (bv.getPositioning() == Block.ABSOLUTE || bv.getPositioning() == Block.FIXED) { - currentIPPosition = bv.getXOffset(); - currentBPPosition = bv.getYOffset(); - - // For FIXED, we need to break out of the current viewports to the - // one established by the page. We save the state stack for - // restoration - // after the block-container has been painted. See below. + //For FIXED, we need to break out of the current viewports to the + //one established by the page. We save the state stack for restoration + //after the block-container has been painted. See below. List breakOutList = null; if (bv.getPositioning() == Block.FIXED) { breakOutList = breakOutOfStateStack(); } - CTM tempctm = new CTM(containingIPPosition, containingBPPosition); - ctm = tempctm.multiply(ctm); - - // Adjust for spaces (from margin or indirectly by start-indent etc. - x += bv.getSpaceStart() / 1000f; - currentIPPosition += bv.getSpaceStart(); - - y += bv.getSpaceBefore() / 1000f; - currentBPPosition += bv.getSpaceBefore(); - - float bpwidth = (borderPaddingStart + bv - .getBorderAndPaddingWidthEnd()) / 1000f; - float bpheight = (borderPaddingBefore + bv - .getBorderAndPaddingWidthAfter()) / 1000f; - - drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight); - - // Now adjust for border/padding - currentIPPosition += borderPaddingStart; - currentBPPosition += borderPaddingBefore; + AffineTransform positionTransform = new AffineTransform(); + positionTransform.translate(bv.getXOffset(), bv.getYOffset()); + + //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle + positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); - Rectangle2D clippingRect = null; - clippingRect = new Rectangle(currentIPPosition, currentBPPosition, - bv.getIPD(), bv.getBPD()); + //skipping fox:transform here - // startVParea(ctm, clippingRect); - pushViewPortPos(new ViewPortPos(clippingRect, ctm)); + //saveGraphicsState(); + //Viewport position + //concatenateTransformationMatrix(mptToPt(positionTransform)); + + //Background and borders + float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; + float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; + Point2D ptSrc = new Point(0, 0); + Point2D ptDst = positionTransform.transform(ptSrc, null); + Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), + 1000 * (width + bpwidth), 1000 * (height + bpheight)); + pushViewPortPos(new ViewPortPos(borderRect, new CTM(positionTransform))); + drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight); + + //Shift to content rectangle after border painting + AffineTransform contentRectTransform = new AffineTransform(); + contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); + //concatenateTransformationMatrix(mptToPt(contentRectTransform)); + ptSrc = new Point(0, 0); + ptDst = contentRectTransform.transform(ptSrc, null); + Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), + 1000 * width, 1000 * height); + pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentRectTransform))); + + //Clipping is not supported, yet + //Rectangle2D clippingRect = null; + //clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD()); + + //saveGraphicsState(); + //Set up coordinate system for content rectangle + AffineTransform contentTransform = ctm.toAffineTransform(); + //concatenateTransformationMatrix(mptToPt(contentTransform)); + contentRect = new Rectangle2D.Double(0, 0, 1000 * width, 1000 * height); + pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentTransform))); + currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); - // endVParea(); + popViewPortPos(); + popViewPortPos(); + //restoreGraphicsState(); + popViewPortPos(); + //restoreGraphicsState(); if (breakOutList != null) { restoreStateStackAfterBreakOut(breakOutList); @@ -493,37 +557,36 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { currentBPPosition += bv.getSpaceBefore(); - // borders and background in the old coordinate system + //borders and background in the old coordinate system handleBlockTraits(bv); - // Advance to start of content area + //Advance to start of content area currentIPPosition += bv.getStartIndent(); CTM tempctm = new CTM(containingIPPosition, currentBPPosition); ctm = tempctm.multiply(ctm); - // Now adjust for border/padding + //Now adjust for border/padding currentBPPosition += borderPaddingBefore; Rectangle2D clippingRect = null; clippingRect = new Rectangle(currentIPPosition, currentBPPosition, bv.getIPD(), bv.getBPD()); - // startVParea(ctm, clippingRect); + //startVParea(ctm, clippingRect); pushViewPortPos(new ViewPortPos(clippingRect, ctm)); currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); - // endVParea(); + //endVParea(); popViewPortPos(); currentIPPosition = saveIP; currentBPPosition = saveBP; - currentBPPosition += (int) (bv.getAllocBPD()); + currentBPPosition += (int)(bv.getAllocBPD()); } - // currentFontName = saveFontName; } /** {@inheritDoc} */ @@ -537,7 +600,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ public void renderPage(PageViewport pageViewport) { - currentState.reset(); + // initializeRootExtensions(page); + + // this.currentFontFamily = ""; + this.currentFontSize = 0; + this.pageFontCounter = 0; + this.currentPageFonts.clear(); + // this.lineCache = new HashSet(); Rectangle2D bounds = pageViewport.getViewArea(); @@ -546,14 +615,14 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (pages != null && pages.containsKey(pageViewport)) { - this.afpDataStream.restorePage((PageObject) pages - .remove(pageViewport)); + this.afpDataStream.restorePage((PageObject) pages.remove(pageViewport)); } else { + // renderPageGroupExtensions(page); final int pageRotation = 0; this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, - this.resolution, this.resolution); + getResolution(), getResolution()); renderPageObjectExtensions(pageViewport); @@ -563,16 +632,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { renderPageAreas(pageViewport.getPage()); - this.afpDataStream.addFontsToCurrentPage(currentState.getPageFonts()); + Iterator i = currentPageFonts.values().iterator(); + while (i.hasNext()) { + AFPFontAttributes afpFontAttributes = (AFPFontAttributes) i.next(); + + afpDataStream.createFont( + (byte)afpFontAttributes.getFontReference(), + afpFontAttributes.getFont(), + afpFontAttributes.getPointSize()); - try { - afpDataStream.endPage(); - } catch (IOException ioex) { - // TODO What shall we do? } + afpDataStream.endPage(); + popViewPortPos(); - } /** @@ -615,12 +688,22 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ public void fillRect(float x, float y, float width, float height) { /* - * afpDataStream.createShading( pts2units(x), pts2units(y), - * pts2units(width), pts2units(height), currentColor.getRed(), - * currentColor.getGreen(), currentColor.getBlue()); + afpDataStream.createShading( + pts2units(x), + pts2units(y), + pts2units(width), + pts2units(height), + currentColor.getRed(), + currentColor.getGreen(), + currentColor.getBlue()); */ - afpDataStream.createLine(pts2units(x), pts2units(y), pts2units(x - + width), pts2units(y), pts2units(height), currentState.getColor()); + afpDataStream.createLine( + pts2units(x), + pts2units(y), + pts2units(x + width), + pts2units(y), + pts2units(height), + currentColor); } /** @@ -635,112 +718,193 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { return; } switch (style) { - case Constants.EN_DOUBLE: - if (horz) { - float h3 = h / 3; - float ym1 = y1; - float ym2 = ym1 + h3 + h3; - afpDataStream.createLine(pts2units(x1), pts2units(ym1), - pts2units(x2), pts2units(ym1), pts2units(h3), col); - afpDataStream.createLine(pts2units(x1), pts2units(ym2), - pts2units(x2), pts2units(ym2), pts2units(h3), col); - } else { - float w3 = w / 3; - float xm1 = x1; - float xm2 = xm1 + w3 + w3; - afpDataStream.createLine(pts2units(xm1), pts2units(y1), - pts2units(xm1), pts2units(y2), pts2units(w3), col); - afpDataStream.createLine(pts2units(xm2), pts2units(y1), - pts2units(xm2), pts2units(y2), pts2units(w3), col); - } - break; - case Constants.EN_DASHED: - if (horz) { - float w2 = 2 * h; - while (x1 + w2 < x2) { - afpDataStream.createLine(pts2units(x1), pts2units(y1), - pts2units(x1 + w2), pts2units(y1), pts2units(h), - col); - x1 += 2 * w2; + case Constants.EN_DOUBLE: + if (horz) { + float h3 = h / 3; + float ym1 = y1; + float ym2 = ym1 + h3 + h3; + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1), + pts2units(x2), + pts2units(ym1), + pts2units(h3), + col + ); + afpDataStream.createLine( + pts2units(x1), + pts2units(ym2), + pts2units(x2), + pts2units(ym2), + pts2units(h3), + col + ); + } else { + float w3 = w / 3; + float xm1 = x1; + float xm2 = xm1 + w3 + w3; + afpDataStream.createLine( + pts2units(xm1), + pts2units(y1), + pts2units(xm1), + pts2units(y2), + pts2units(w3), + col + ); + afpDataStream.createLine( + pts2units(xm2), + pts2units(y1), + pts2units(xm2), + pts2units(y2), + pts2units(w3), + col + ); } - } else { - float h2 = 2 * w; - while (y1 + h2 < y2) { - afpDataStream.createLine(pts2units(x1), pts2units(y1), - pts2units(x1), pts2units(y1 + h2), pts2units(w), - col); - y1 += 2 * h2; + break; + case Constants.EN_DASHED: + if (horz) { + float w2 = 2 * h; + while (x1 + w2 < x2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1 + w2), + pts2units(y1), + pts2units(h), + col + ); + x1 += 2 * w2; + } + } else { + float h2 = 2 * w; + while (y1 + h2 < y2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1), + pts2units(y1 + h2), + pts2units(w), + col + ); + y1 += 2 * h2; + } } - } - break; - case Constants.EN_DOTTED: - if (horz) { - while (x1 + h < x2) { - afpDataStream - .createLine(pts2units(x1), pts2units(y1), - pts2units(x1 + h), pts2units(y1), - pts2units(h), col); - x1 += 2 * h; + break; + case Constants.EN_DOTTED: + if (horz) { + while (x1 + h < x2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1 + h), + pts2units(y1), + pts2units(h), + col + ); + x1 += 2 * h; + } + } else { + while (y1 + w < y2) { + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(x1), + pts2units(y1 + w), + pts2units(w), + col + ); + y1 += 2 * w; + } } - } else { - while (y1 + w < y2) { - afpDataStream - .createLine(pts2units(x1), pts2units(y1), - pts2units(x1), pts2units(y1 + w), - pts2units(w), col); - y1 += 2 * w; + break; + case Constants.EN_GROOVE: + case Constants.EN_RIDGE: + { + float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); + if (horz) { + Color uppercol = lightenColor(col, -colFactor); + Color lowercol = lightenColor(col, colFactor); + float h3 = h / 3; + float ym1 = y1; + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1), + pts2units(x2), + pts2units(ym1), + pts2units(h3), + uppercol + ); + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1 + h3), + pts2units(x2), + pts2units(ym1 + h3), + pts2units(h3), + col + ); + afpDataStream.createLine( + pts2units(x1), + pts2units(ym1 + h3 + h3), + pts2units(x2), + pts2units(ym1 + h3 + h3), + pts2units(h3), + lowercol + ); + } else { + Color leftcol = lightenColor(col, -colFactor); + Color rightcol = lightenColor(col, colFactor); + float w3 = w / 3; + float xm1 = x1 + (w3 / 2); + afpDataStream.createLine( + pts2units(xm1), + pts2units(y1), + pts2units(xm1), + pts2units(y2), + pts2units(w3), + leftcol + ); + afpDataStream.createLine( + pts2units(xm1 + w3), + pts2units(y1), + pts2units(xm1 + w3), + pts2units(y2), + pts2units(w3), + col + ); + afpDataStream.createLine( + pts2units(xm1 + w3 + w3), + pts2units(y1), + pts2units(xm1 + w3 + w3), + pts2units(y2), + pts2units(w3), + rightcol + ); } + break; } - break; - case Constants.EN_GROOVE: - case Constants.EN_RIDGE: { - float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); - if (horz) { - Color uppercol = lightenColor(col, -colFactor); - Color lowercol = lightenColor(col, colFactor); - float h3 = h / 3; - float ym1 = y1; - afpDataStream.createLine(pts2units(x1), pts2units(ym1), - pts2units(x2), pts2units(ym1), pts2units(h3), uppercol); - afpDataStream.createLine(pts2units(x1), pts2units(ym1 + h3), - pts2units(x2), pts2units(ym1 + h3), pts2units(h3), col); - afpDataStream.createLine(pts2units(x1), - pts2units(ym1 + h3 + h3), pts2units(x2), pts2units(ym1 - + h3 + h3), pts2units(h3), lowercol); - } else { - Color leftcol = lightenColor(col, -colFactor); - Color rightcol = lightenColor(col, colFactor); - float w3 = w / 3; - float xm1 = x1 + (w3 / 2); - afpDataStream.createLine(pts2units(xm1), pts2units(y1), - pts2units(xm1), pts2units(y2), pts2units(w3), leftcol); - afpDataStream.createLine(pts2units(xm1 + w3), pts2units(y1), - pts2units(xm1 + w3), pts2units(y2), pts2units(w3), col); - afpDataStream.createLine(pts2units(xm1 + w3 + w3), - pts2units(y1), pts2units(xm1 + w3 + w3), pts2units(y2), - pts2units(w3), rightcol); - } - break; - } - case Constants.EN_HIDDEN: - break; - case Constants.EN_INSET: - case Constants.EN_OUTSET: - default: - afpDataStream.createLine(pts2units(x1), pts2units(y1), - pts2units(horz ? x2 : x1), pts2units(horz ? y1 : y2), - pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), col); + case Constants.EN_HIDDEN: + break; + case Constants.EN_INSET: + case Constants.EN_OUTSET: + default: + afpDataStream.createLine( + pts2units(x1), + pts2units(y1), + pts2units(horz ? x2 : x1), + pts2units(horz ? y1 : y2), + pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), + col + ); } } /** * {@inheritDoc} */ - protected RendererContext createRendererContext(int x, int y, int width, - int height, Map foreignAttributes) { + protected RendererContext createRendererContext(int x, int y, int width, int height, + Map foreignAttributes) { RendererContext context; - context = super.createRendererContext(x, y, width, height, - foreignAttributes); + context = super.createRendererContext(x, y, width, height, foreignAttributes); context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, new Boolean(!this.colorImages)); context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO, @@ -750,9 +914,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { context.setProperty(AFPRendererContextConstants.AFP_BITS_PER_PIXEL, new Integer(this.bitsPerPixel)); context.setProperty(AFPRendererContextConstants.AFP_DATASTREAM, - this.afpDataStream); + getAFPDataStream()); context.setProperty(AFPRendererContextConstants.AFP_STATE, - this.currentState); + getState()); return context; } @@ -763,6 +927,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { ImageFlavor.RENDERED_IMAGE, ImageFlavor.XML_DOM}; + /** {@inheritDoc} */ public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { uri = URISpecification.getURL(uri); @@ -784,6 +949,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } else { ImageManager manager = getUserAgent().getFactory().getImageManager(); ImageInfo info = null; + InputStream in = null; try { ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); @@ -806,48 +972,62 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } else if (img instanceof ImageRendered) { ImageRendered imgRend = (ImageRendered)img; RenderedImage ri = imgRend.getRenderedImage(); - - drawBufferedImage(ri, getResolution(), + drawBufferedImage(uri, ri, getResolution(), posInt.x + currentIPPosition, posInt.y + currentBPPosition, posInt.width, - posInt.height); + posInt.height, foreignAttributes); } else if (img instanceof ImageRawCCITTFax) { ImageRawCCITTFax ccitt = (ImageRawCCITTFax)img; + in = ccitt.createInputStream(); + byte[] buf = IOUtils.toByteArray(in); int afpx = mpts2units(posInt.x + currentIPPosition); int afpy = mpts2units(posInt.y + currentBPPosition); int afpw = mpts2units(posInt.getWidth()); int afph = mpts2units(posInt.getHeight()); int afpres = getResolution(); - ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph, - afpres, afpres); - io.setImageParameters( - (int) (ccitt.getSize().getDpiHorizontal() * 10), - (int) (ccitt.getSize().getDpiVertical() * 10), + ImageObjectParameters params = new ImageObjectParameters( + uri, afpx, afpy, afpw, afph, afpres, afpres, + buf, ccitt.getSize().getWidthPx(), - ccitt.getSize().getHeightPx()); - int compression = ccitt.getCompression(); - switch (compression) { - case TIFFImage.COMP_FAX_G3_1D : - io.setImageEncoding((byte) 0x80); - break; - case TIFFImage.COMP_FAX_G3_2D : - io.setImageEncoding((byte) 0x81); - break; - case TIFFImage.COMP_FAX_G4_2D : - io.setImageEncoding((byte) 0x82); - break; - default: - throw new IllegalStateException( - "Invalid compression scheme: " + compression); - } - InputStream in = ccitt.createInputStream(); - try { - byte[] buf = IOUtils.toByteArray(in); - io.setImageData(buf); - } finally { - IOUtils.closeQuietly(in); - } + ccitt.getSize().getHeightPx(), + colorImages, bitsPerPixel + ); + params.setCompression(ccitt.getCompression()); + params.setResourceLevelFromForeignAttributes(foreignAttributes); +// params.setData(buf); + afpDataStream.createImageObject(params); + + +// ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph, +// afpres, afpres); +// io.setImageParameters( +// (int) (ccitt.getSize().getDpiHorizontal() * 10), +// (int) (ccitt.getSize().getDpiVertical() * 10), +// ccitt.getSize().getWidthPx(), +// ccitt.getSize().getHeightPx()); +// int compression = ccitt.getCompression(); +// switch (compression) { +// case TIFFImage.COMP_FAX_G3_1D : +// io.setImageEncoding((byte) 0x80); +// break; +// case TIFFImage.COMP_FAX_G3_2D : +// io.setImageEncoding((byte) 0x81); +// break; +// case TIFFImage.COMP_FAX_G4_2D : +// io.setImageEncoding((byte) 0x82); +// break; +// default: +// throw new IllegalStateException( +// "Invalid compression scheme: " + compression); +// } +// InputStream in = ccitt.createInputStream(); +// try { +// byte[] buf = IOUtils.toByteArray(in); +// io.setImageData(buf); +// } finally { +// IOUtils.closeQuietly(in); +// } } else if (img instanceof ImageXMLDOM) { ImageXMLDOM imgXML = (ImageXMLDOM)img; renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(), @@ -864,6 +1044,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } catch (IOException ioe) { log.error("I/O error while processing image: " + (info != null ? info.toString() : uri), ioe); + } finally { + if (in != null) { + IOUtils.closeQuietly(in); + } } /* @@ -906,46 +1090,47 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * io.setImageData(fopimage.getRessourceBytes()); *//* } else if (MimeConstants.MIME_TIFF.equals(mime) - && fopimage instanceof TIFFImage) { + && fopimage instanceof TIFFImage) { TIFFImage tiffImage = (TIFFImage) fopimage; int x = mpts2units(pos.getX() + currentIPPosition); int y = mpts2units(pos.getY() + currentBPPosition); int w = mpts2units(pos.getWidth()); int h = mpts2units(pos.getHeight()); - int res = getResolution(); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, res, - res); + ImageObject io = afpDataStream.getImageObject(x, y, w, h, + getResolution(), getResolution()); io.setImageParameters( - (int) (fopimage.getHorizontalResolution() * 10), - (int) (fopimage.getVerticalResolution() * 10), fopimage - .getWidth(), fopimage.getHeight()); + (int)(fopimage.getHorizontalResolution() * 10), + (int)(fopimage.getVerticalResolution() * 10), + fopimage.getWidth(), + fopimage.getHeight() + ); if (tiffImage.getStripCount() == 1) { int comp = tiffImage.getCompression(); if (comp == 3) { if (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; } - io.setImageEncoding((byte) 0x81); + io.setImageEncoding((byte)0x81); io.setImageData(fopimage.getRessourceBytes()); } else if (comp == 4) { if (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; } - io.setImageEncoding((byte) 0x82); + io.setImageEncoding((byte)0x82); io.setImageData(fopimage.getRessourceBytes()); } else { if (!fopimage.load(FopImage.BITMAP)) { return; } - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight(), this.bitsPerPixel); + convertToGrayScaleImage(io, fopimage.getBitmaps(), + fopimage.getWidth(), fopimage.getHeight()); } } else { if (!fopimage.load(FopImage.BITMAP)) { return; } - convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage - .getWidth(), fopimage.getHeight(), this.bitsPerPixel); + convertToGrayScaleImage(io, fopimage.getBitmaps(), + fopimage.getWidth(), fopimage.getHeight()); } } else { if (!fopimage.load(FopImage.BITMAP)) { @@ -957,19 +1142,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { int y = mpts2units(pos.getY() + currentBPPosition); int w = mpts2units(pos.getWidth()); int h = mpts2units(pos.getHeight()); - int res = getResolution(); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, res, - res); + ImageObject io = afpDataStream.getImageObject(x, y, w, h, + getResolution(), getResolution()); io.setImageParameters( - (int) (fopimage.getHorizontalResolution() * 10), - (int) (fopimage.getVerticalResolution() * 10), fopimage - .getWidth(), fopimage.getHeight()); + (int)(fopimage.getHorizontalResolution() * 10), + (int)(fopimage.getVerticalResolution() * 10), + fopimage.getWidth(), + fopimage.getHeight() + ); if (colorImages) { - io.setImageIDESize((byte) 24); + io.setImageIDESize((byte)24); io.setImageData(fopimage.getBitmaps()); } else { - convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage - .getWidth(), fopimage.getHeight(), this.bitsPerPixel); + convertToGrayScaleImage(io, fopimage.getBitmaps(), + fopimage.getWidth(), fopimage.getHeight()); } }*/ } @@ -983,7 +1169,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param out * the OutputStream * @throws IOException - * In case of an I/O error. + * In case of an I/O error. + * @deprecated + * use ImageEncodingHelper.encodeRenderedImageAsRGB(image, out) directly instead */ public static void writeImage(RenderedImage image, OutputStream out) throws IOException { @@ -993,9 +1181,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Draws a BufferedImage to AFP. * + * @param uri + * the uri of the image * @param image * the RenderedImage - * @param imageResolution + * @param imageRes * the resolution of the BufferedImage * @param x * the x coordinate (in mpt) @@ -1006,55 +1196,67 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @param h * the height of the viewport (in mpt) */ - public void drawBufferedImage(RenderedImage image, int imageResolution, int x, - int y, int w, int h) { - int afpx = mpts2units(x); - int afpy = mpts2units(y); - int afpw = mpts2units(w); - int afph = mpts2units(h); - int afpres = getResolution(); + public void drawBufferedImage(String uri, RenderedImage image, int imageRes, int x, + int y, int w, int h, Map foreignAttributes) { +// int afpx = mpts2units(x); +// int afpy = mpts2units(y); +// int afpw = mpts2units(w); +// int afph = mpts2units(h); ByteArrayOutputStream baout = new ByteArrayOutputStream(); try { // Serialize image //TODO Eventually, this should be changed not to buffer as this increases the //memory consumption (see PostScript output) - writeImage(image, baout); - byte[] buf = baout.toByteArray(); - - // Generate image - ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, - afph, afpres, afpres); - io.setImageParameters(imageResolution, imageResolution, - image.getWidth(), image.getHeight()); - if (colorImages) { - io.setImageIDESize((byte)24); - io.setImageData(buf); - } else { - // TODO Teach it how to handle grayscale BufferedImages directly - // because this is pretty inefficient - convertToGrayScaleImage(io, buf, - image.getWidth(), image.getHeight(), this.bitsPerPixel); - } + ImageEncodingHelper.encodeRenderedImageAsRGB(image, baout); } catch (IOException ioe) { - log.error("Error while serializing bitmap: " + ioe.getMessage(), - ioe); + log.error("Error while serializing bitmap: " + ioe.getMessage(), ioe); + return; } + //int res = getResolution(); +// String uri = null;// = image.getProperty(name); +// String uri = image.getProperty(name); + // Generate image + ImageObjectParameters params = new ImageObjectParameters( + uri, + mpts2units(x), mpts2units(y), + mpts2units(w), mpts2units(h), + imageRes, imageRes, + baout.toByteArray(), + image.getWidth(), + image.getHeight(), + colorImages, + bitsPerPixel); + + params.setResourceLevelFromForeignAttributes(foreignAttributes); + IncludeObject io = afpDataStream.createImageObject(params); +// ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, +// afph, afpres, afpres); +// io.setImageParameters(imageResolution, imageResolution, +// image.getWidth(), image.getHeight()); +// if (colorImages) { +// io.setImageIDESize((byte)24); +// io.setImageData(buf); +// } else { +// // TODO Teach it how to handle grayscale BufferedImages directly +// // because this is pretty inefficient +// convertToGrayScaleImage(io, buf, +// image.getWidth(), image.getHeight(), this.bitsPerPixel); +// } } /** - * Establishes a new foreground or fill color. {@inheritDoc} + * Establishes a new foreground or fill color. + * {@inheritDoc} */ public void updateColor(Color col, boolean fill) { if (fill) { - currentState.setColor(col); + currentColor = col; } } /** * Restores the state stack after a break out. - * - * @param breakOutList - * the state stack to restore. + * @param breakOutList the state stack to restore. */ public void restoreStateStackAfterBreakOut(List breakOutList) { @@ -1062,7 +1264,6 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Breaks out of the state stack to handle fixed block-containers. - * * @return the saved state stack to recreate later */ public List breakOutOfStateStack() { @@ -1093,8 +1294,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { - String url = image.getURL(); - drawImage(url, pos); + drawImage(image.getURL(), pos, image.getForeignAttributes()); } /** @@ -1103,58 +1303,76 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void renderText(TextArea text) { renderInlineAreaBackAndBorders(text); - String internalFontName = getInternalFontNameForArea(text); - this.currentState.setFontName(internalFontName); - int currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); - this.currentState.setFontSize(currentFontSize); - AFPFont font = (AFPFont) fontInfo.getFonts().get(internalFontName); + String name = getInternalFontNameForArea(text); + currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); + AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); Color col = (Color) text.getTrait(Trait.COLOR); - int vsci = mpts2units(font.getWidth(' ', currentFontSize) / 1000 - + text.getTextWordSpaceAdjust() - + text.getTextLetterSpaceAdjust()); + int vsci = mpts2units(tf.getWidth(' ', currentFontSize) / 1000 + + text.getTextWordSpaceAdjust() + + text.getTextLetterSpaceAdjust()); // word.getOffset() = only height of text itself // currentBlockIPPosition: 0 for beginning of line; nonzero - // where previous line area failed to take up entire allocated space + // where previous line area failed to take up entire allocated space int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); - int bl = currentBPPosition + text.getOffset() - + text.getBaselineOffset(); + int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); // Set letterSpacing - // float ls = fs.getLetterSpacing() / this.currentFontSize; + //float ls = fs.getLetterSpacing() / this.currentFontSize; String worddata = text.getText(); - AFPPageFonts pageFonts = this.currentState.getPageFonts(); - AFPFontAttributes afpFontAttributes = pageFonts.registerFont( - internalFontName, font, currentFontSize); + // Create an AFPFontAttributes object from the current font details + AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, tf, currentFontSize); + + if (!currentPageFonts.containsKey(afpFontAttributes.getFontKey())) { + // Font not found on current page, so add the new one + pageFontCounter++; + afpFontAttributes.setFontReference(pageFontCounter); + currentPageFonts.put( + afpFontAttributes.getFontKey(), + afpFontAttributes); + + } else { + // Use the previously stored font attributes + afpFontAttributes = (AFPFontAttributes) currentPageFonts.get( + afpFontAttributes.getFontKey()); + } // Try and get the encoding to use for the font String encoding = null; try { - encoding = font.getCharacterSet(currentFontSize).getEncoding(); + encoding = tf.getCharacterSet(currentFontSize).getEncoding(); } catch (Throwable ex) { encoding = AFPConstants.EBCIDIC_ENCODING; - log.warn("renderText():: Error getting encoding for font " - + " - using default encoding " + encoding); + log.warn( + "renderText():: Error getting encoding for font " + + " - using default encoding " + + encoding); } try { - afpDataStream.createText(afpFontAttributes.getFontReference(), - mpts2units(rx), pts2units(bl), col, vsci, mpts2units(text - .getTextLetterSpaceAdjust()), worddata - .getBytes(encoding)); + afpDataStream.createText( + afpFontAttributes.getFontReference(), + mpts2units(rx), + mpts2units(bl), + col, + vsci, + mpts2units(text.getTextLetterSpaceAdjust()), + worddata.getBytes(encoding)); } catch (UnsupportedEncodingException usee) { - log.error("renderText:: Font " + afpFontAttributes.getFontKey() - + " caused UnsupportedEncodingException"); + log.error( + "renderText:: Font " + + afpFontAttributes.getFontKey() + + " caused UnsupportedEncodingException"); } super.renderText(text); - renderTextDecoration(font, currentFontSize, text, bl, rx); + renderTextDecoration(tf, currentFontSize, text, bl, rx); } /** @@ -1192,41 +1410,88 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } /** - * Render leader area. This renders a leader area which is an area with a - * rule. - * - * @param area - * the leader area to render + * Render leader area. + * This renders a leader area which is an area with a rule. + * @param area the leader area to render */ public void renderLeader(Leader area) { renderInlineAreaBackAndBorders(area); int style = area.getRuleStyle(); - float startx = (currentIPPosition + area - .getBorderAndPaddingWidthStart()) / 1000f; + float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; float starty = (currentBPPosition + area.getOffset()) / 1000f; - float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + area - .getIPD()) / 1000f; + float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + + area.getIPD()) / 1000f; float ruleThickness = area.getRuleThickness() / 1000f; - Color col = (Color) area.getTrait(Trait.COLOR); + Color col = (Color)area.getTrait(Trait.COLOR); switch (style) { - case EN_SOLID: - case EN_DASHED: - case EN_DOUBLE: - case EN_DOTTED: - case EN_GROOVE: - case EN_RIDGE: - drawBorderLine(startx, starty, endx, starty + ruleThickness, true, - true, style, col); - break; - default: - throw new UnsupportedOperationException("rule style not supported"); + case EN_SOLID: + case EN_DASHED: + case EN_DOUBLE: + case EN_DOTTED: + case EN_GROOVE: + case EN_RIDGE: + drawBorderLine(startx, starty, endx, starty + ruleThickness, + true, true, style, col); + break; + default: + throw new UnsupportedOperationException("rule style not supported"); } super.renderLeader(area); } /** + * Sets the AFPRenderer options + * @param options the <code>Map</code> containing the options + */ +// UNUSED +// public void setOptions(Map options) { +// +// this.afpOptions = options; +// +// } + /** + * Determines the orientation from the string representation, this method + * guarantees to return a value of either 0, 90, 180 or 270. + * + * @return the orientation + */ +// UNUSED +// private int getOrientation(String orientationString) { +// +// int orientation = 0; +// if (orientationString != null && orientationString.length() > 0) { +// try { +// orientation = Integer.parseInt(orientationString); +// } catch (NumberFormatException nfe) { +// log.error("Cannot use orientation of " + orientation +// + " defaulting to zero."); +// orientation = 0; +// } +// } else { +// orientation = 0; +// } +// switch (orientation) { +// case 0: +// break; +// case 90: +// break; +// case 180: +// break; +// case 270: +// break; +// default: +// log.error("Cannot use orientation of " + orientation +// + " defaulting to zero."); +// orientation = 0; +// break; +// } +// +// return orientation; +// +// } + /** * Sets the rotation to be used for portrait pages, valid values are 0 * (default), 90, 180, 270. * @@ -1235,13 +1500,14 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { */ public void setPortraitRotation(int rotation) { - if (rotation == 0 || rotation == 90 || rotation == 180 - || rotation == 270) { + if (rotation == 0 + || rotation == 90 + || rotation == 180 + || rotation == 270) { portraitRotation = rotation; } else { - throw new IllegalArgumentException( - "The portrait rotation must be one" - + " of the values 0, 90, 180, 270"); + throw new IllegalArgumentException("The portrait rotation must be one" + + " of the values 0, 90, 180, 270"); } @@ -1250,19 +1516,20 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Sets the rotation to be used for landsacpe pages, valid values are 0, 90, * 180, 270 (default). - * + * * @param rotation * The rotation in degrees. */ public void setLandscapeRotation(int rotation) { - if (rotation == 0 || rotation == 90 || rotation == 180 - || rotation == 270) { + if (rotation == 0 + || rotation == 90 + || rotation == 180 + || rotation == 270) { landscapeRotation = rotation; } else { - throw new IllegalArgumentException( - "The landscape rotation must be one" - + " of the values 0, 90, 180, 270"); + throw new IllegalArgumentException("The landscape rotation must be one" + + " of the values 0, 90, 180, 270"); } } @@ -1270,7 +1537,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Get the MIME type of the renderer. * - * @return The MIME type of the renderer + * @return The MIME type of the renderer */ public String getMimeType() { return MimeConstants.MIME_AFP; @@ -1280,8 +1547,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * Method to render the page extension. * <p> * - * @param pageViewport - * the page object + * @param pageViewport the page object */ private void renderPageObjectExtensions(PageViewport pageViewport) { @@ -1292,7 +1558,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { // the s-p-m Iterator i = pageViewport.getExtensionAttachments().iterator(); while (i.hasNext()) { - ExtensionAttachment attachment = (ExtensionAttachment) i.next(); + ExtensionAttachment attachment = (ExtensionAttachment)i.next(); if (AFPPageSetup.CATEGORY.equals(attachment.getCategory())) { AFPPageSetup aps = (AFPPageSetup) attachment; String element = aps.getElementName(); @@ -1306,7 +1572,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { String name = aps.getName(); String source = aps.getValue(); if (pageSegmentsMap == null) { - pageSegmentsMap = new HashMap(); + pageSegmentsMap = new java.util.HashMap(); } pageSegmentsMap.put(source, name); } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT @@ -1314,7 +1580,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { String name = aps.getName(); String value = aps.getValue(); if (pageSegmentsMap == null) { - pageSegmentsMap = new HashMap(); + pageSegmentsMap = new java.util.HashMap(); } afpDataStream.createTagLogicalElement(name, value); } else if (AFPElementMapping.NO_OPERATION.equals(element)) { @@ -1322,6 +1588,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { if (content != null) { afpDataStream.createNoOperation(content); } + } else if (AFPElementMapping.RESOURCE.equals(element)) { + System.out.println("resource: " + attachment); } } } @@ -1331,9 +1599,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Converts FOP mpt measurement to afp measurement units - * - * @param mpt - * the millipoints value + * @param mpt the millipoints value */ private int mpts2units(int mpt) { return mpts2units((double) mpt); @@ -1341,9 +1607,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { /** * Converts FOP pt measurement to afp measurement units - * - * @param mpt - * the millipoints value + * @param mpt the millipoints value */ private int pts2units(float mpt) { return mpts2units(mpt * 1000d); @@ -1357,8 +1621,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @return afp measurement unit value */ private int mpts2units(double mpt) { - return (int) Math - .round(mpt / (DPI_CONVERSION_FACTOR / getResolution())); + return (int)Math.round(mpt / (DPI_CONVERSION_FACTOR / getResolution())); } /** @@ -1422,7 +1685,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { io.setImageIDESize((byte) bitsPerPixel); io.setImageData(bw); } - + private final class ViewPortPos { private int x = 0; @@ -1521,7 +1784,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } - private List viewPortPositions = new ArrayList(); + private List viewPortPositions = new java.util.ArrayList(); private void pushViewPortPos(ViewPortPos vpp) { viewPortPositions.add(vpp); @@ -1531,8 +1794,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { private void popViewPortPos() { viewPortPositions.remove(viewPortPositions.size() - 1); if (viewPortPositions.size() > 0) { - ViewPortPos vpp = (ViewPortPos) viewPortPositions - .get(viewPortPositions.size() - 1); + ViewPortPos vpp = (ViewPortPos)viewPortPositions.get(viewPortPositions.size() - 1); afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); } } @@ -1546,9 +1808,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { public void setBitsPerPixel(int bitsPerPixel) { this.bitsPerPixel = bitsPerPixel; switch (bitsPerPixel) { - case 1: - case 4: - case 8: + case 1: + case 4: + case 8: break; default: log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8."); @@ -1573,6 +1835,9 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * @return the AFPDataStream */ public AFPDataStream getAFPDataStream() { + if (afpDataStream == null) { + this.afpDataStream = new AFPDataStream(); + } return afpDataStream; } @@ -1583,24 +1848,46 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * the output resolution (dpi) */ public void setResolution(int resolution) { - if (resolution == DPI_240_RESOLUTION - || resolution == DPI_1440_RESOLUTION) { - this.resolution = resolution; - if (log.isDebugEnabled()) { - log.debug("renderer-resolution set to: " + resolution + " dpi"); - } - } else { - log.error("invalid resolution, can only be " + DPI_240_RESOLUTION - + " or " + DPI_1440_RESOLUTION + " dpi"); + if (log.isDebugEnabled()) { + log.debug("renderer-resolution set to: " + resolution + "dpi"); } + this.resolution = resolution; } - + /** * Returns the output/device resolution. - * * @return the resolution in dpi */ public int getResolution() { return this.resolution; } + + private AFPState getState() { + if (currentState == null) { + currentState = new AFPState(); + } + return currentState; + } + + private boolean gocaEnabled = false; + + /** + * @param enabled true if AFP GOCA is enabled for SVG support + */ + protected void setGOCAEnabled(boolean enabled) { + this.gocaEnabled = enabled; + } + + /** + * @return true of AFP GOCA is enabled for SVG support + */ + protected boolean isGOCAEnabled() { + return this.gocaEnabled; + } + + /** {@inheritDoc} */ + public void startPageSequence(LineArea seqTitle) { + afpDataStream.endPageGroup(); + afpDataStream.startPageGroup(); + } } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index 9917eec70..4c8a3dc9f 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -140,18 +140,14 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { return new AFPFontInfo(font, tripleList); } else if ("outline".equalsIgnoreCase(type)) { - String characterset = afpFontCfg.getAttribute("characterset"); if (characterset == null) { log.error("Mandatory afp-font configuration attribute 'characterset=' is missing"); return null; } String name = afpFontCfg.getAttribute("name", characterset); - CharacterSet characterSet = null; - String base14 = afpFontCfg.getAttribute("base14-font", null); - if (base14 != null) { try { Class clazz = Class.forName("org.apache.fop.fonts.base14." @@ -205,7 +201,6 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { + triplet.getWeight()); } } - fontList.add(afi); } } @@ -242,6 +237,31 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger( AFPRenderer.DPI_240_RESOLUTION)); } + + Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false); + if (gocaSupportCfg != null) { + afpRenderer.setGOCAEnabled(true); + } + +// Configuration resourceGroupsCfg = cfg.getChild("resource-groups", false); +// if (resourceGroupsCfg != null) { +// resourceGroupsCfg.getValue("print-file-level"); +// } +// if (externalCfg != null) { +// Configuration[] resourceGroups = externalCfg.getChildren("resource-groups"); +// for (int i = 0; i < resourceGroups.length; i++) { +// String resourceresourceGroups[i].getAttribute("url", null); +// Configuration resourceGroup = externalCfg.getChild("resource-group", false); +// } +// } +// Configuration externalResourceGroupCfg = cfg.getChild("external-resource-group", false); +// if (externalResourceGroupCfg != null) { +//// afpRenderer.setExternalResources(true); +// String resourceLibraryUrl = externalResourceGroupCfg.getAttribute("url", null); +// if (resourceLibraryUrl != null) { +// afpRenderer.setExternalResourceLibraryUrl(resourceLibraryUrl); +// } +// } } } } diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 13fa62514..2641e6fbe 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -22,10 +22,12 @@ package org.apache.fop.render.afp; // FOP import java.awt.geom.AffineTransform; 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.GVTBuilder; +import org.apache.batik.dom.AbstractDocument; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; import org.apache.commons.logging.Log; @@ -33,7 +35,10 @@ import org.apache.commons.logging.LogFactory; 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.afp.modca.AFPDataStream; +import org.apache.fop.render.afp.modca.GraphicsObject; +import org.apache.fop.render.afp.modca.IncludeObject; import org.apache.fop.svg.SVGUserAgent; import org.w3c.dom.Document; @@ -65,28 +70,29 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { */ public static AFPInfo getAFPInfo(RendererContext context) { AFPInfo afpi = new AFPInfo(); - afpi.width = ((Integer)context.getProperty(WIDTH)).intValue(); - afpi.height = ((Integer)context.getProperty(HEIGHT)).intValue(); - afpi.currentXPosition = ((Integer)context.getProperty(XPOS)).intValue(); - afpi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue(); - afpi.cfg = (Configuration)context.getProperty(HANDLER_CONFIGURATION); - afpi.fontInfo = (org.apache.fop.fonts.FontInfo)context.getProperty( - AFPRendererContextConstants.AFP_FONT_INFO); - afpi.resolution = ((Integer)context.getProperty( - AFPRendererContextConstants.AFP_RESOLUTION)).intValue(); - afpi.afpState = (AFPState)context.getProperty( - AFPRendererContextConstants.AFP_STATE); - afpi.afpDataStream = (AFPDataStream)context.getProperty( - AFPRendererContextConstants.AFP_DATASTREAM); - afpi.grayscale = ((Boolean)context.getProperty( - AFPRendererContextConstants.AFP_GRAYSCALE)).booleanValue(); - afpi.bitsPerPixel = ((Integer)context.getProperty( - AFPRendererContextConstants.AFP_BITS_PER_PIXEL)).intValue(); + 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.setResolution(((Integer)context.getProperty( + AFPRendererContextConstants.AFP_RESOLUTION)).intValue()); + afpi.setState((AFPState)context.getProperty( + AFPRendererContextConstants.AFP_STATE)); + afpi.setAFPDataStream((AFPDataStream)context.getProperty( + AFPRendererContextConstants.AFP_DATASTREAM)); + afpi.setColor(!((Boolean)context.getProperty( + AFPRendererContextConstants.AFP_GRAYSCALE)).booleanValue()); + afpi.setBitsPerPixel(((Integer)context.getProperty( + AFPRendererContextConstants.AFP_BITS_PER_PIXEL)).intValue()); return afpi; } /** * Render the SVG document. + * * @param context the renderer context * @param doc the SVG document * @param afpInfo the AFPInfo renderer parameters @@ -100,14 +106,16 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); graphics.setAFPInfo(afpInfo); + String uri = ((AbstractDocument)doc).getDocumentURI(); + graphics.setDocumentURI(uri); + GVTBuilder builder = new GVTBuilder(); boolean strokeText = false; - Configuration cfg = afpInfo.cfg; + Configuration cfg = afpInfo.getHandlerConfiguration(); if (cfg != null) { strokeText = cfg.getChild("stroke-text", true).getValueAsBoolean(strokeText); } - final float uaResolution = context.getUserAgent().getSourceResolution(); SVGUserAgent svgUserAgent = new SVGUserAgent(25.4f / uaResolution, new AffineTransform()); @@ -122,7 +130,7 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { AFPTextElementBridge tBridge = new AFPTextElementBridge(textPainter); ctx.putBridge(tBridge); } - + GraphicsNode root; try { root = builder.build(ctx, doc); @@ -132,33 +140,59 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { return; } log.debug("Generating SVG at " - + afpInfo.resolution + "dpi."); + + afpInfo.getResolution() + "dpi."); - int res = afpInfo.resolution; - + int res = afpInfo.getResolution(); double w = ctx.getDocumentSize().getWidth() * 1000f; double h = ctx.getDocumentSize().getHeight() * 1000f; // convert to afp inches - double sx = ((afpInfo.width / w) * res) / 72f; - double sy = ((afpInfo.height / h) * res) / 72f; - double xOffset = (afpInfo.currentXPosition * res) / 72000f; - double yOffset = ((afpInfo.height - afpInfo.currentYPosition) * res) / 72000f; + double sx = ((afpInfo.getWidth() / w) * res) / 72f; + double sy = ((afpInfo.getHeight() / h) * res) / 72f; + double xOffset = (afpInfo.getX() * res) / 72000f; + double yOffset = ((afpInfo.getHeight() - afpInfo.getY()) * res) / 72000f; // 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(sx, 0, 0, -sy, xOffset, yOffset); graphics.setTransform(trans); + + int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000); + int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000); + int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f); + int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f); + + DataObjectParameters params = new DataObjectParameters( + uri, x, y, width, height, res, res); + + Map/*<QName, String>*/ foreignAttributes + = (Map/*<QName, String>*/)context.getProperty( + RendererContextConstants.FOREIGN_ATTRIBUTES); + + if (foreignAttributes != null) { + params.setResourceLevelFromForeignAttributes(foreignAttributes); + } + + IncludeObject includeObj = afpInfo.getAFPDataStream().createGraphicsObject(params); + GraphicsObject graphicsObj = (GraphicsObject)includeObj.getReferencedObject(); + graphics.setGraphicsObject(graphicsObj); + try { root.paint(graphics); } catch (Exception e) { log.error("SVG graphic could not be rendered: " + e.getMessage(), e); } + + graphics.dispose(); } /** {@inheritDoc} */ public boolean supportsRenderer(Renderer renderer) { - return (renderer instanceof AFPRenderer); + if (renderer instanceof AFPRenderer) { + AFPRenderer afpRenderer = (AFPRenderer)renderer; + return afpRenderer.isGOCAEnabled(); + } + return false; } /** {@inheritDoc} */ @@ -166,4 +200,3 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { return SVGDOMImplementation.SVG_NAMESPACE_URI; } } - diff --git a/src/java/org/apache/fop/render/afp/AFPState.java b/src/java/org/apache/fop/render/afp/AFPState.java index 7cb37e2f3..5977d0de2 100644 --- a/src/java/org/apache/fop/render/afp/AFPState.java +++ b/src/java/org/apache/fop/render/afp/AFPState.java @@ -20,51 +20,18 @@ package org.apache.fop.render.afp; import java.awt.Color; +import java.awt.geom.AffineTransform; +import java.io.Serializable; import java.util.Arrays; +import java.util.List; /** * This keeps information about the current state when writing to pdf. */ public class AFPState { - /** - * The current color - */ - private Color color = null; - - /** - * The current background color - */ - private Color backColor = null; - - /** - * The current font name - */ - private String fontName = null; - - /** - * The current font size - */ - private int fontSize = 0; - - /** - * The current line width - */ - private float lineWidth = 0; - - /** - * The dash array for the current basic stroke (line type) - */ - private float[] dashArray = null; - - /** - * The current fill status - */ - private boolean filled = false; + private Data data = new Data(); - /** - * The fonts on the current page - */ - private AFPPageFonts pageFonts = null; + private List stateStack = new java.util.ArrayList(); /** * Set the current color. @@ -74,8 +41,8 @@ public class AFPState { * @return true if the color has changed */ protected boolean setColor(Color col) { - if (!col.equals(this.color)) { - this.color = col; + if (!col.equals(getData().color)) { + getData().color = col; return true; } return false; @@ -87,8 +54,8 @@ public class AFPState { * @return true if the fill value has changed */ protected boolean setFill(boolean fill) { - if (fill != this.filled) { - this.filled = fill; + if (fill != getData().filled) { + getData().filled = fill; return true; } return false; @@ -99,10 +66,10 @@ public class AFPState { * @return the color */ protected Color getColor() { - if (this.color == null) { - this.color = Color.black; + if (getData().color == null) { + getData().color = Color.black; } - return this.color; + return getData().color; } /** @@ -111,8 +78,8 @@ public class AFPState { * @return true if the line width has changed */ protected boolean setLineWidth(float width) { - if (this.lineWidth != width) { - this.lineWidth = width; + if (getData().lineWidth != width) { + getData().lineWidth = width; return true; } return false; @@ -124,8 +91,8 @@ public class AFPState { * @return true if the dash array has changed */ public boolean setDashArray(float[] dash) { - if (!Arrays.equals(dash, this.dashArray)) { - this.dashArray = dash; + if (!Arrays.equals(dash, getData().dashArray)) { + getData().dashArray = dash; return true; } return false; @@ -136,7 +103,7 @@ public class AFPState { * @return the current line width */ protected float getLineWidth() { - return lineWidth; + return getData().lineWidth; } /** @@ -144,10 +111,10 @@ public class AFPState { * @return the background color */ protected Color getBackColor() { - if (this.backColor == null) { - this.backColor = Color.white; + if (getData().backColor == null) { + getData().backColor = Color.white; } - return backColor; + return getData().backColor; } /** @@ -158,8 +125,8 @@ public class AFPState { * @return true if the color has changed */ protected boolean setBackColor(Color col) { - if (!col.equals(this.backColor)) { - this.backColor = col; + if (!col.equals(getData().backColor)) { + getData().backColor = col; return true; } return false; @@ -171,8 +138,8 @@ public class AFPState { * @return true if the font name has changed */ protected boolean setFontName(String internalFontName) { - if (!internalFontName.equals(this.fontName)) { - this.fontName = internalFontName; + if (!internalFontName.equals(getData().fontName)) { + getData().fontName = internalFontName; return true; } return false; @@ -183,7 +150,7 @@ public class AFPState { * @return the current font name */ protected String getFontName() { - return this.fontName; + return getData().fontName; } /** @@ -191,7 +158,7 @@ public class AFPState { * @return the current font size */ protected int getFontSize() { - return this.fontSize; + return getData().fontSize; } /** @@ -202,8 +169,8 @@ public class AFPState { * @return true if the font size has changed */ protected boolean setFontSize(int size) { - if (size != this.fontSize) { - this.fontSize = size; + if (size != getData().fontSize) { + getData().fontSize = size; return true; } return false; @@ -214,25 +181,98 @@ public class AFPState { * @return the current page fonts */ protected AFPPageFonts getPageFonts() { - if (this.pageFonts == null) { - this.pageFonts = new AFPPageFonts(); + if (getData().pageFonts == null) { + getData().pageFonts = new AFPPageFonts(); } - return this.pageFonts; - } - - /** - * Resets the current state - */ - protected void reset() { - this.color = null; - this.backColor = null; - this.fontName = null; - this.fontSize = 0; - this.lineWidth = 0; - this.dashArray = null; - this.filled = false; - if (this.pageFonts != null) { - this.pageFonts.clear(); + return getData().pageFonts; + } + + /** + * Push the current state onto the stack. + * This call should be used when the q operator is used + * so that the state is known when popped. + */ + public void push() { + Data copy; + try { + copy = (Data)getData().clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e.getMessage()); + } + stateStack.add(copy); + } + + /** + * Get the current stack level. + * + * @return the current stack level + */ + public int getStackLevel() { + return stateStack.size(); + } + + /** + * Pop the state from the stack and set current values to popped state. + * This should be called when a Q operator is used so + * the state is restored to the correct values. + * @return the restored state, null if the stack is empty + */ + public Data pop() { + if (getStackLevel() > 0) { + Data popped = (Data)stateStack.remove(stateStack.size() - 1); + data = popped; + return popped; + } else { + return null; + } + } + + /** + * @return the currently valid state + */ + public Data getData() { + return data; + } + + public class Data implements Cloneable, Serializable { + private static final long serialVersionUID = -1789481244175275686L; + + /** The current color */ + private Color color = null; + + /** The current background color */ + private Color backColor = null; + + /** The current font name */ + private String fontName = null; + + /** The current font size */ + private int fontSize = 0; + + /** The current line width */ + private float lineWidth = 0; + + /** The dash array for the current basic stroke (line type) */ + private float[] dashArray = null; + + /** The current fill status */ + private boolean filled = false; + + /** The fonts on the current page */ + private AFPPageFonts pageFonts = null; + + /** {@inheritDoc} */ + public Object clone() throws CloneNotSupportedException { + Data obj = new Data(); + obj.color = this.color; + obj.backColor = this.backColor; + obj.fontName = this.fontName; + obj.fontSize = this.fontSize; + obj.lineWidth = this.lineWidth; + obj.dashArray = this.dashArray; + obj.filled = this.filled; + obj.pageFonts = this.pageFonts; + return obj; } } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/DataObjectParameters.java b/src/java/org/apache/fop/render/afp/DataObjectParameters.java new file mode 100644 index 000000000..2ec56a4e3 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/DataObjectParameters.java @@ -0,0 +1,173 @@ +/* + * 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.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.render.afp.extensions.AFPElementMapping; +import org.apache.fop.util.QName; + +/** + * A list of parameters associated with an AFP data objects + */ +public class DataObjectParameters { + private static final ResourceLevel DEFAULT_RESOURCE_LEVEL = new ResourceLevel(); + + private String uri; + private int x; + private int y; + private int width; + private int height; + private int widthRes; + private int heightRes; + private ResourceLevel resourceLevel = DEFAULT_RESOURCE_LEVEL; + + /** + * Main constructor + * + * @param uri the data object uri + * @param x the data object x coordinate + * @param y the data object y coordinate + * @param width the data object width + * @param height the data object height + * @param widthRes the data object width resolution + * @param heightRes the data object height resolution + */ + public DataObjectParameters(String uri, int x, int y, int width, int height, + int widthRes, int heightRes) { + this.uri = uri; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.widthRes = widthRes; + this.heightRes = heightRes; + } + + /** + * @return the uri of this data object + */ + public String getUri() { + return uri; + } + + /** + * @return the x coordinate of this data object + */ + public int getX() { + return x; + } + + /** + * @return the y coordinate of this data object + */ + public int getY() { + return y; + } + + /** + * @return the width of this data object + */ + public int getWidth() { + return width; + } + + /** + * @return the height of this data object + */ + public int getHeight() { + return height; + } + + /** + * @return the width resolution of this data object + */ + public int getWidthRes() { + return widthRes; + } + + /** + * @return the height resolution of this data object + */ + public int getHeightRes() { + return heightRes; + } + + /** + * @return returns the resource level at which this data object should reside + */ + public ResourceLevel getResourceLevel() { + return resourceLevel; + } + + /** + * Sets the resource level at which this object should reside + * @param resourceLevel the resource level at which this data object should reside + */ + public void setResourceLevel(ResourceLevel resourceLevel) { + this.resourceLevel = resourceLevel; + } + + /** + * Sets the resource level using the given foreign attributes + * @param foreignAttributes a mapping of element attributes names to values + */ + public void setResourceLevelFromForeignAttributes(Map/*<QName, String>*/ foreignAttributes) { + if (foreignAttributes != null) { + QName resourceLevelKey = new QName( + AFPElementMapping.NAMESPACE, + "afp:resource-level"); + if (foreignAttributes.containsKey(resourceLevelKey)) { + String level = (String)foreignAttributes.get(resourceLevelKey); + this.resourceLevel = new ResourceLevel(); + if (resourceLevel.setLevel(level)) { + if (resourceLevel.isExternal()) { + QName resourceDestKey = new QName( + AFPElementMapping.NAMESPACE, + "afp:resource-dest"); + String resourceExternalDest + = (String)foreignAttributes.get(resourceDestKey); + resourceLevel.setExternalDest(resourceExternalDest); + } + } else { + Log log = LogFactory.getLog("org.apache.fop.afp"); + log.warn("invalid resource level '" + level + + "', using default document level"); + } + } + } + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "uri=" + uri + + ", x=" + x + + ", y=" + y + + ", width=" + width + + ", height=" + height + + ", widthRes=" + widthRes + + ", heightRes=" + heightRes + + (resourceLevel != null ? ", resourceLevel=" + resourceLevel : ""); + } +} diff --git a/src/java/org/apache/fop/render/afp/ImageObjectParameters.java b/src/java/org/apache/fop/render/afp/ImageObjectParameters.java new file mode 100644 index 000000000..8b430f042 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ImageObjectParameters.java @@ -0,0 +1,138 @@ +/* + * 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; + +/** + * A list of parameters associated with an image + */ +public class ImageObjectParameters extends DataObjectParameters { + private int bitsPerPixel; + private boolean color; + private int compression = -1; + private byte[] imageData; + private int imageDataWidth; + private int imageDataHeight; + + /** + * Main constructor + * + * @param uri the image uri + * @param x the image x coordinate + * @param y the image y coordinate + * @param width the image width + * @param height the image height + * @param widthRes the image width resolution + * @param heightRes the image height resolution + */ + public ImageObjectParameters(String uri, int x, int y, int width, int height, + int widthRes, int heightRes, byte[] imageData, + int imageDataWidth, int imageDataHeight, boolean color, int bitsPerPixel) { + super(uri, x, y, width, height, widthRes, heightRes); + this.imageData = imageData; + this.imageDataWidth = imageDataWidth; + this.imageDataHeight = imageDataHeight; + this.color = color; + this.bitsPerPixel = bitsPerPixel; + } + + /** + * @return the numner of bits used per pixel + */ + public int getBitsPerPixel() { + return bitsPerPixel; + } + + /** + * @return true if this is a color image + */ + public boolean isColor() { + return color; + } + + /** + * @return the image data + */ + public byte[] getData() { + return imageData; + } + + /** + * @return true of this image uses compression + */ + public boolean hasCompression() { + return compression > -1; + } + + /** + * @return the compression type + */ + public int getCompression() { + return compression; + } + + /** + * Sets the compression used with this image + * @param compression the type of compression used with this image + */ + public void setCompression(int compression) { + this.compression = compression; + } + + /** + * @return the image data width + */ + public int getImageDataWidth() { + return imageDataWidth; + } + + /** + * Sets the image data width + * @param imageDataWidth the image data width + */ + protected void setImageDataWidth(int imageDataWidth) { + this.imageDataWidth = imageDataWidth; + } + + /** + * @return the image data height + */ + public int getImageDataHeight() { + return imageDataHeight; + } + + /** + * Sets the image data height + * @param imageDataHeight the image data height + */ + protected void setImageDataHeight(int imageDataHeight) { + this.imageDataHeight = imageDataHeight; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return super.toString() + + ", imageDataWidth=" + imageDataWidth + + ", imageDataHeight=" + imageDataHeight + + ", color=" + color + + ", bitPerPixel=" + bitsPerPixel; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/ResourceLevel.java b/src/java/org/apache/fop/render/afp/ResourceLevel.java new file mode 100644 index 000000000..f397edb04 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/ResourceLevel.java @@ -0,0 +1,123 @@ +/* + * 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; + +/** + * The level at which a resource is to reside in the AFP output + */ +public class ResourceLevel { + private static final String EXTERNAL = "external"; + + private static final String PRINT_FILE = "print-file"; + + private static final String DOCUMENT = "document"; + + private static final String PAGE_GROUP = "page-group"; + + private static final String PAGE = "page"; + + /** + * where the resource will reside in the AFP output + */ + private String level = PAGE; // default is page level + + /** + * the destination location of the resource + */ + private String dest = null; + + /** + * @return true if this is a page level resource group + */ + public boolean isPage() { + return level.equals(PAGE); + } + + /** + * @return true if this is a page group level resource group + */ + public boolean isPageGroup() { + return level.equals(PAGE_GROUP); + } + + /** + * @return true if this is a document level resource group + */ + public boolean isDocument() { + return level.equals(DOCUMENT); + } + + /** + * @return true if this is an external level resource group + */ + public boolean isExternal() { + return level.equals(EXTERNAL); + } + + /** + * @return true if this is a print-file level resource group + */ + public boolean isPrintFile() { + return level.equals(PRINT_FILE); + } + + private boolean isValid(String lvl) { + return lvl.equals(EXTERNAL) + || lvl.equals(PRINT_FILE) + || lvl.equals(DOCUMENT) + || lvl.equals(PAGE_GROUP) + || lvl.equals(PAGE); + } + + /** + * Sets the resource placement level within the AFP output + * @param level the resource level (page, page-group, document, print-file or external) + * @return true if the resource level was successfully set + */ + public boolean setLevel(String level) { + if (isValid(level)) { + this.level = level; + return true; + } + return false; + } + + /** + * @return the external destination of the resource + */ + public String getExternalDest() { + return dest; + } + + /** + * Sets the external destination of the resource + * @param dest the external destination of the resource + */ + public void setExternalDest(String dest) { + this.dest = dest; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "level=" + level + (isExternal() ? ", dest=" + dest : ""); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java index 665a77562..6b4bc4eb9 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java @@ -19,14 +19,13 @@ package org.apache.fop.render.afp.extensions; -import org.apache.fop.apps.FOPException; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.StringProperty; /** * This class extends the org.apache.fop.fo.StringProperty.Maker inner class - * in order to provide a static property maker. The object faciliates + * in order to provide a static property maker. The object facilitates * extraction of attributes from formatted objects based on the static list * as defined in the AFPElementMapping implementation. * <p/> @@ -58,5 +57,4 @@ public class AFPAttribute extends StringProperty.Maker { } return property; } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java index b8bfa74b6..808cd88f1 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java @@ -23,6 +23,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; /** * This class extends the org.apache.fop.extensions.ExtensionObj class. The @@ -54,4 +55,7 @@ public class AFPElement extends AbstractAFPExtensionObject { } } + protected ExtensionAttachment instantiateExtensionAttachment() { + return null; + } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java index 216379cc0..8d4b0ae5e 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java @@ -50,6 +50,9 @@ public class AFPElementMapping extends ElementMapping { /** include page segment element */ public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment"; + /** include resource element (external) */ + public static final String RESOURCE = "resource"; + /** NOP */ public static final String NO_OPERATION = "no-operation"; diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java new file mode 100644 index 000000000..9a8429b00 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java @@ -0,0 +1,155 @@ +/* + * 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.extensions; + +import java.io.Serializable; + +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.xmlgraphics.util.XMLizable; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * This is the pass-through value object for the AFP extension. + */ +public abstract class AFPExtensionAttachment + implements ExtensionAttachment, Serializable, XMLizable { + private static final long serialVersionUID = 7190606822558332901L; + + /** The category URI for this extension attachment. */ + public static final String CATEGORY = "apache:fop:extensions:afp"; + + /** + * the extension element name + */ + protected String elementName; + + /** + * the extension content + */ + protected String content; + + /** + * the extension name attribute + */ + protected String name; + + /** + * the extension value attribute + */ + protected String value; + + /** + * Default constructor. + * + * @param elementName the name of the afp extension attachment, may be null + */ + public AFPExtensionAttachment(String elementName) { + this.elementName = elementName; + } + + /** @return the name */ + public String getElementName() { + return elementName; + } + + /** + * @return true if this element has a name attribute + */ + protected boolean hasName() { + return name != null; + } + + /** @return the name */ + public String getName() { + return name; + } + + /** + * Sets the name of the setup code object. + * @param name The name to set. + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } + + /** + * Sets the value + * @param source The value name to set. + */ + public void setValue(String source) { + this.value = source; + } + + /** {@inheritDoc} */ + public String getCategory() { + return CATEGORY; + } + + /** + * @return the data + */ + public String getContent() { + return content; + } + + /** + * Sets the data + * @param content The byte data to set. + */ + public void setContent(String content) { + this.content = content; + } + + /** + * name attribute + */ + protected static final String ATT_NAME = "name"; + + /** + * value attribute + */ + protected static final String ATT_VALUE = "value"; + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + if (name != null && name.length() > 0) { + atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); + } + if (value != null && value.length() > 0) { + atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value); + } + handler.startElement(CATEGORY, elementName, elementName, atts); + if (content != null && content.length() > 0) { + char[] chars = content.toCharArray(); + handler.characters(chars, 0, chars.length); + } + handler.endElement(CATEGORY, elementName, elementName); + } +} diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java index 7fdf7cd11..72d7639bd 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java @@ -54,7 +54,9 @@ public class AFPExtensionHandler extends DefaultHandler || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) || localName.equals(AFPElementMapping.PAGE) - || localName.equals(AFPElementMapping.PAGE_GROUP)) { + || localName.equals(AFPElementMapping.PAGE_GROUP) + || localName.equals(AFPElementMapping.PAGE_GROUP) + || localName.equals(AFPResource.ELEMENT)) { //handled in endElement } else { handled = false; diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java index 91ab2dfa5..437222daa 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java @@ -19,33 +19,10 @@ package org.apache.fop.render.afp.extensions; -import java.io.Serializable; - -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -import org.apache.xmlgraphics.util.XMLizable; - -import org.apache.fop.fo.extensions.ExtensionAttachment; - /** * This is the pass-through value object for the PostScript extension. */ -public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizable { - - private static final long serialVersionUID = 7190606822558332901L; - - /** The category URI for this extension attachment. */ - public static final String CATEGORY = "apache:fop:extensions:afp"; - - private String elementName; - - private String name; - - private String value; - - private String content; +public class AFPPageSetup extends AFPExtensionAttachment { /** * Default constructor. @@ -53,85 +30,16 @@ public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizabl * @param elementName the name of the setup code object, may be null */ public AFPPageSetup(String elementName) { - this.elementName = elementName; + super(elementName); } - /** @return the name */ - public String getElementName() { - return elementName; - } - - /** @return the name */ - public String getName() { - return name; - } + private static final long serialVersionUID = -549941295384013190L; /** - * Sets the name of the setup code object. - * @param name The name to set. + * {@inheritDoc} */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the value - */ - public String getValue() { - return value; - } - - /** - * Sets the value - * @param source The value name to set. - */ - public void setValue(String source) { - this.value = source; - } - - /** {@inheritDoc} */ - public String getCategory() { - return CATEGORY; - } - - /** - * @return the data - */ - public String getContent() { - return content; - } - - /** - * Sets the data - * @param content The byte data to set. - */ - public void setContent(String content) { - this.content = content; - } - - /** {@inheritDoc} */ public String toString() { return "AFPPageSetup(element-name=" + getElementName() + " name=" + getName() + " value=" + getValue() + ")"; } - - private static final String ATT_NAME = "name"; - private static final String ATT_VALUE = "value"; - - /** {@inheritDoc} */ - public void toSAX(ContentHandler handler) throws SAXException { - AttributesImpl atts = new AttributesImpl(); - if (name != null && name.length() > 0) { - atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); - } - if (value != null && value.length() > 0) { - atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value); - } - handler.startElement(CATEGORY, elementName, elementName, atts); - if (content != null && content.length() > 0) { - char[] chars = content.toCharArray(); - handler.characters(chars, 0, chars.length); - } - handler.endElement(CATEGORY, elementName, elementName); - } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java index 4971928f8..d167a8d4b 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java @@ -23,9 +23,10 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; /** - * Extension element for fox:ps-page-setup-code. + * Extension element for afp:ps-page-setup-code. */ public class AFPPageSetupElement extends AbstractAFPExtensionObject { @@ -45,4 +46,10 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject { } } + /** + * {@inheritDoc} + */ + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPPageSetup(this.name); + } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java index e641d2df8..ff6d56785 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java +++ b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java @@ -34,11 +34,14 @@ import org.xml.sax.Locator; public abstract class AbstractAFPExtensionObject extends FONode { /** - * AFP setup code + * the AFP extension attachment */ - private AFPPageSetup setupCode; + protected AFPExtensionAttachment extensionAttachment; - private String name; + /** + * the element name of this extension + */ + protected String name; /** * @see org.apache.fop.fo.FONode#FONode(FONode) @@ -48,10 +51,11 @@ public abstract class AbstractAFPExtensionObject extends FONode { public AbstractAFPExtensionObject(FONode parent, String name) { super(parent); this.name = name; - this.setupCode = new AFPPageSetup(name); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { @@ -59,60 +63,85 @@ public abstract class AbstractAFPExtensionObject extends FONode { } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected void addCharacters(char[] data, int start, int end, - PropertyList pList, Locator locator) { - setupCode.setContent(new String(data, start, end - start)); + PropertyList pList, Locator locator) throws FOPException { + ((AFPExtensionAttachment)getExtensionAttachment()).setContent( + new String(data, start, end - start)); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getNamespaceURI() { return AFPElementMapping.NAMESPACE; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getNormalNamespacePrefix() { return AFPElementMapping.NAMESPACE_PREFIX; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException { - String name = attlist.getValue("name"); - if (name != null && name.length() > 0) { - setupCode.setName(name); + getExtensionAttachment(); + String attr = attlist.getValue("name"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setName(attr); } else { throw new FOPException(elementName + " must have a name attribute."); } if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) { - name = attlist.getValue("src"); - if (name != null && name.length() > 0) { - setupCode.setValue(name); + attr = attlist.getValue("src"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setValue(attr); } else { throw new FOPException(elementName + " must have a src attribute."); } } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) { - name = attlist.getValue("value"); - if (name != null && name.length() > 0) { - setupCode.setValue(name); + attr = attlist.getValue("value"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setValue(attr); } else { throw new FOPException(elementName + " must have a value attribute."); } } } - - /** {@inheritDoc} */ + + /** + * {@inheritDoc} + */ protected void endOfNode() throws FOPException { super.endOfNode(); } - /** {@inheritDoc} */ + /** + * Instantiates extension attachment object + * @return extension attachment + */ + protected abstract ExtensionAttachment instantiateExtensionAttachment(); + + /** + * {@inheritDoc} + */ public ExtensionAttachment getExtensionAttachment() { - return this.setupCode; + if (extensionAttachment == null) { + this.extensionAttachment = (AFPExtensionAttachment)instantiateExtensionAttachment(); + } + return this.extensionAttachment; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getLocalName() { return name; } diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java index 62de923c8..bf534e3c7 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java @@ -20,6 +20,7 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; @@ -28,7 +29,11 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.render.afp.AFPFontAttributes; +import org.apache.fop.render.afp.DataObjectParameters; +import org.apache.fop.render.afp.ImageObjectParameters; +import org.apache.fop.render.afp.ResourceLevel; import org.apache.fop.render.afp.fonts.AFPFont; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.render.afp.tools.StringUtils; /** @@ -47,7 +52,7 @@ import org.apache.fop.render.afp.tools.StringUtils; * them. * */ -public class AFPDataStream { +public class AFPDataStream extends AbstractResourceGroupContainer { /** * Static logging instance @@ -81,6 +86,11 @@ public class AFPDataStream { private PageObject currentPageObject = null; /** + * The current resource group + */ +// private ResourceGroup currentResourceGroup = null; + + /** * The current overlay object */ private Overlay currentOverlay = null; @@ -98,8 +108,7 @@ public class AFPDataStream { /** * The page group count */ -// not used -// private int pageGroupCount = 0; + private int pageGroupCount = 0; /** * The overlay count @@ -135,40 +144,71 @@ public class AFPDataStream { * The outputstream for the data stream */ private OutputStream outputStream = null; + + /** + * A mapping of external resource destinations to resource groups + */ + private Map/*<String,ResourceGroup>*/ externalResourceGroups = null; /** * Default constructor for the AFPDataStream. */ public AFPDataStream() { + this.document = new Document(); + } + + private Document getDocument() { + return this.document; + } + + private AbstractPageObject getCurrentPage() { + return this.currentPage; } /** * The document is started by invoking this method which creates an instance * of the AFP Document object. * - * @param docOutputStream - * the outputStream which the document is written to. - */ - public void startDocument(OutputStream docOutputStream) { - if (document != null) { - String msg = "Invalid state - document already started."; - log.warn("startDocument():: " + msg); - throw new IllegalStateException(msg); + * @param name + * the name of this document. + */ + public void setDocumentName(String name) { +// if (document != null) { +// String msg = "Invalid state - document already started."; +// log.warn("startDocument():: " + msg); +// throw new IllegalStateException(msg); +// } +// if (document != null) { +// String msg = "Invalid state - print file level document already started"; +// log.warn(msg); +// throw new IllegalStateException(msg); +// } + + if (name != null) { + document.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_DOCUMENT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + name); } - - this.document = new Document(); - this.outputStream = docOutputStream; } /** - * The document is ended by invoking this method which creates an instance + * Sets the OutputStream + * @param outputStream the AFP OutputStream + */ + public void setOutputStream(OutputStream outputStream) { + this.outputStream = outputStream; + } + + /** + * The document is written/ended by invoking this method which creates an instance * of the AFP Document object and registers the start with a validation map * which ensures that methods are not invoked out of the correct sequence. * * @throws java.io.IOException * throws an I/O exception of some sort has occurred */ - public void endDocument() throws IOException { + public void write() throws IOException { if (complete) { String msg = "Invalid state - document already ended."; log.warn("endDocument():: " + msg); @@ -185,8 +225,22 @@ public class AFPDataStream { endPageGroup(); } - document.endDocument(); - document.writeDataStream(this.outputStream); + // Write out any external resource groups + if (externalResourceGroups != null) { + writeExternalResources(); + } + + // Write out any print-file level resources + if (hasResources()) { + getResourceGroup().writeDataStream(this.outputStream); + } + + // Write out document + if (document != null) { + document.endDocument(); + document.writeDataStream(this.outputStream); + } + this.outputStream.flush(); complete = true; @@ -195,7 +249,7 @@ public class AFPDataStream { this.outputStream = null; } - + /** * Start a new page. When processing has finished on the current page, the * {@link #endPage()}method must be invoked to mark the page ending. @@ -213,7 +267,6 @@ public class AFPDataStream { */ public void startPage(int pageWidth, int pageHeight, int pageRotation, int pageWidthRes, int pageHeightRes) { - String pageName = "PGN" + StringUtils.lpad(String.valueOf(pageCount++), '0', 5); @@ -229,34 +282,30 @@ public class AFPDataStream { * the {@link #endOverlay()}method must be invoked to mark the overlay * ending. * - * @param overlayX + * @param x * the x position of the overlay on the page - * @param overlayY + * @param y * the y position of the overlay on the page - * @param overlayWidth + * @param width * the width of the overlay - * @param overlayHeight + * @param height * the height of the overlay - * @param overlayWidthResolution + * @param widthRes * the width resolution of the overlay - * @param overlayHeightResolution + * @param heightRes * the height resolution of the overlay - * @param overlayRotation + * @param rotation * the rotation of the overlay */ - public void startOverlay(int overlayX, int overlayY, int overlayWidth, - int overlayHeight, int overlayWidthResolution, - int overlayHeightResolution, int overlayRotation) { - + public void startOverlay(int x, int y, int width, int height, int widthRes, + int heightRes, int rotation) { String overlayName = "OVL" + StringUtils.lpad(String.valueOf(ovlCount++), '0', 5); - currentOverlay = new Overlay(overlayName, overlayWidth, overlayHeight, - overlayWidthResolution, overlayHeightResolution, - overlayRotation); - currentPageObject.addOverlay(currentOverlay); - currentPageObject.createIncludePageOverlay(overlayName, overlayX, - overlayY, 0); + currentOverlay = new Overlay(overlayName, width, height, + widthRes, heightRes, rotation); + + currentPageObject.createIncludePageOverlay(overlayName, x, y, 0); currentPage = currentOverlay; setOffsets(0, 0, 0); } @@ -300,17 +349,13 @@ public class AFPDataStream { /** * Helper method to mark the end of the current page. - * - * @throws java.io.IOException - * thrown when an I/O exception of some sort has occurred */ - public void endPage() throws IOException { + public void endPage() { currentPageObject.endPage(); if (currentPageGroup != null) { currentPageGroup.addPage(currentPageObject); } else { document.addPage(currentPageObject); - document.writeDataStream(this.outputStream); } currentPageObject = null; currentPage = null; @@ -363,7 +408,6 @@ public class AFPDataStream { currentPage.createFont(fontReference, font, size); } - /** * Helper method to create text on the current page, this method delegates * to the current presentation text object in order to construct the text. @@ -388,55 +432,46 @@ public class AFPDataStream { currentPage.createText(fontReference, x + xOffset, y + yOffset, rotation, col, vsci, ica, data); } - + /** - * Returns an ImageObject used to create an image in the datastream. - * - * @param x - * the x position of the image - * @param y - * the y position of the image - * @param width - * the width of the image - * @param height - * the height of the image - * @param widthRes - * the resolution width of the image - * @param heightRes - * the resolution height of the image + * Returns true if the resource exists within this resource group, + * false otherwise. + * + * @param uri the uri of the resource + * @return true if the resource exists within this resource group + */ + public boolean resourceExists(String uri) { + return getResourceGroup().resourceExists(uri); + } + + /** + * Returns an IncludeObject referencing an image in the datastream. + * + * @param params + * the unique uri of the image * @return - * a new image object + * a new include object referencing an image object */ - public ImageObject getImageObject(int x, int y, int width, int height, - int widthRes, int heightRes) { - ImageObject imageObj = currentPage.getImageObject(); - setObjectViewPort(imageObj, x, y, width, height, widthRes, heightRes); - return imageObj; + public IncludeObject createImageObject(ImageObjectParameters params) { + ResourceLevel resourceLevel = params.getResourceLevel(); + IncludeObject includeObj = getResourceGroup(resourceLevel).addObject(params); + currentPage.addObject(includeObj); + return includeObj; } /** - * Returns an GraphicObject used to create an graphic in the datastream. + * Returns an IncludeObject referencing a graphic in the datastream. * - * @param x - * the x position of the graphic - * @param y - * the y position of the graphic - * @param width - * the width of the graphic - * @param height - * the height of the graphic - * @param widthRes - * the resolution width of the graphic - * @param heightRes - * the resolution height of the graphic + * @param params + * the data object parameters * @return - * a new graphics object + * a new include object referencing the graphics object */ - public GraphicsObject getGraphicsObject(int x, int y, int width, int height, - int widthRes, int heightRes) { - GraphicsObject graphicsObj = currentPage.getGraphicsObject(); - setObjectViewPort(graphicsObj, x, y, width, height, widthRes, heightRes); - return graphicsObj; + public IncludeObject createGraphicsObject(DataObjectParameters params) { + ResourceLevel resourceLevel = params.getResourceLevel(); + IncludeObject includeObj = getResourceGroup(resourceLevel).addObject(params); + currentPage.addObject(includeObj); + return includeObj; } /** @@ -559,9 +594,7 @@ public class AFPDataStream { */ public void createIncludePageOverlay(String name) { currentPageObject.createIncludePageOverlay(name, 0, 0, rotation); - ActiveEnvironmentGroup aeg = currentPageObject - .getActiveEnvironmentGroup(); - aeg.createOverlay(name); + currentPageObject.getActiveEnvironmentGroup().createOverlay(name); } /** @@ -571,10 +604,7 @@ public class AFPDataStream { * the name of the medium map */ public void createInvokeMediumMap(String name) { - if (currentPageGroup == null) { - startPageGroup(); - } - currentPageGroup.createInvokeMediumMap(name); + getCurrentPageGroup().createInvokeMediumMap(name); } /** @@ -621,7 +651,7 @@ public class AFPDataStream { for (int i = 0; i < attributes.length; i++) { String name = (String) attributes[i].getKey(); String value = (String) attributes[i].getValue(); - currentPage.createTagLogicalElement(name, value); + getCurrentPage().createTagLogicalElement(name, value); } } @@ -635,7 +665,7 @@ public class AFPDataStream { for (int i = 0; i < attributes.length; i++) { String name = (String) attributes[i].getKey(); String value = (String) attributes[i].getValue(); - currentPageGroup.createTagLogicalElement(name, value); + getCurrentPageGroup().createTagLogicalElement(name, value); } } @@ -665,31 +695,33 @@ public class AFPDataStream { currentPage.createNoOperation(content); } + private PageGroup getCurrentPageGroup() { + if (currentPageGroup == null) { + String pageGroupName = "PGP" + + StringUtils.lpad(String.valueOf(pageGroupCount++), '0', 5); + this.currentPageGroup = new PageGroup(pageGroupName); + } + return currentPageGroup; + } + /** * Start a new page group. When processing has finished on the current page * group the {@link #endPageGroup()}method must be invoked to mark the page * group ending. */ public void startPageGroup() { - - String pageGroupName = "PGP" - + StringUtils.lpad(String.valueOf(pageCount++), '0', 5); - - currentPageGroup = new PageGroup(pageGroupName); - + getCurrentPageGroup(); } /** * Helper method to mark the end of the page group. - * @throws IOException thrown if an I/O exception of some sort has occurred */ - public void endPageGroup() throws IOException { - - currentPageGroup.endPageGroup(); - document.addPageGroup(currentPageGroup); - document.writeDataStream(outputStream); - currentPageGroup = null; - + public void endPageGroup() { + if (currentPageGroup != null) { + currentPageGroup.endPageGroup(); + document.addPageGroup(currentPageGroup); + currentPageGroup = null; + } } /** @@ -700,7 +732,6 @@ public class AFPDataStream { * The rotation in degrees. */ public void setPortraitRotation(int pageRotation) { - if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180 || pageRotation == 270) { this.portraitRotation = pageRotation; @@ -708,7 +739,6 @@ public class AFPDataStream { throw new IllegalArgumentException( "The portrait rotation must be one of the values 0, 90, 180, 270"); } - } /** @@ -719,7 +749,6 @@ public class AFPDataStream { * The rotation in degrees. */ public void setLandscapeRotation(int pageRotation) { - if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180 || pageRotation == 270) { this.landscapeRotation = pageRotation; @@ -727,6 +756,72 @@ public class AFPDataStream { throw new IllegalArgumentException( "The landscape rotation must be one of the values 0, 90, 180, 270"); } + } + + /** + * Writes out external AFP resources + */ + private void writeExternalResources() { + // write any external resources + Iterator it = getExternalResourceGroups().keySet().iterator(); + while (it.hasNext()) { + String externalDest = (String)it.next(); + ResourceGroup resourceGroup + = (ResourceGroup)getExternalResourceGroups().get(externalDest); + OutputStream os = null; + try { + log.debug("Writing external AFP resource file " + externalDest); + os = new java.io.FileOutputStream(externalDest); + resourceGroup.writeDataStream(os); + } catch (FileNotFoundException e) { + log.error("Failed to open external AFP resource file " + + externalDest); + } catch (IOException e) { + log.error("An error occurred when attempting to write external AFP resource file " + + externalDest); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + log.error("Failed to close outputstream for external AFP resource file " + + externalDest); + } + } + } + } + } + /** + * Returns the resource group for a given resource level + * @param resourceLevel a resource level + * @return a resource group container for the given level + */ + private ResourceGroup getResourceGroup(ResourceLevel resourceLevel) { + ResourceGroup resourceGroup = null; + if (resourceLevel.isPrintFile()) { + resourceGroup = this.getResourceGroup(); + } else if (resourceLevel.isDocument()) { + resourceGroup = document.getResourceGroup(); + } else if (resourceLevel.isPageGroup()) { + resourceGroup = getCurrentPageGroup().getResourceGroup(); + } else if (resourceLevel.isPage()) { + resourceGroup = getCurrentPage().getResourceGroup(); + } else if (resourceLevel.isExternal()) { + String externalDest = resourceLevel.getExternalDest(); + resourceGroup = (ResourceGroup)getExternalResourceGroups().get(externalDest); + if (resourceGroup == null) { + resourceGroup = new ResourceGroup(); + externalResourceGroups.put(externalDest, resourceGroup); + } + } + return resourceGroup; + } + + private Map/*<String,ResourceGroup>*/ getExternalResourceGroups() { + if (externalResourceGroups == null) { + externalResourceGroups = new java.util.HashMap(); + } + return externalResourceGroups; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java index cd8b25810..26d42b2d4 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java @@ -21,8 +21,8 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; +import java.util.Collection; import java.util.Iterator; -import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -50,16 +50,18 @@ public abstract class AbstractAFPObject { /** * Help method to write a set of AFPObjects to the AFP datastream. - * @param afpObjects a list of AFPObjects + * @param objects a list of AFPObjects * @param os The stream to write to * @throws java.io.IOException in the event that an I/O exception occurred */ - protected void writeObjectList(List afpObjects, OutputStream os) + protected void writeObjects(Collection/*<AbstractAFPObject>*/ objects, OutputStream os) throws IOException { - - Iterator it = afpObjects.iterator(); - while (it.hasNext()) { - ((AbstractAFPObject)it.next()).writeDataStream(os); + if (objects != null) { + for (Iterator it = objects.iterator(); it.hasNext();) { + Object obj1 = it.next(); + AbstractAFPObject obj = (AbstractAFPObject)obj1; + obj.writeDataStream(os); + } } } -} +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java index cf5aad382..aa97065d1 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java @@ -22,7 +22,7 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.modca.goca.AbstractGraphicsContainer; +import org.apache.fop.render.afp.goca.AbstractGraphicsContainer; /** * Abstract base class used by the ImageObject and GraphicsObject which both diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/AbstractEnvironmentGroup.java new file mode 100644 index 000000000..3f371d628 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractEnvironmentGroup.java @@ -0,0 +1,100 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +/** + * A base class that encapsulates common features of + * ActiveEnvironmentGroup and ResourceEnvironmentGroup + */ +public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject { + + /** + * The collection of MapPageOverlay objects + */ + protected List mapPageOverlays = null; + + /** + * Main constructor + * @param name the object name + */ + public AbstractEnvironmentGroup(String name) { + super(name); + } + + private List getMapPageOverlays() { + if (mapPageOverlays == null) { + mapPageOverlays = new java.util.ArrayList(); + } + return mapPageOverlays; + } + + /** + * Actually creates the MPO object. + * Also creates the supporting object (an IPO) + * @param name the name of the overlay to be used + */ + public void createOverlay(String name) { + MapPageOverlay mpo = getCurrentMapPageOverlay(); + if (mpo == null) { + mpo = new MapPageOverlay(); + getMapPageOverlays().add(mpo); + } + + try { + mpo.addOverlay(name); + } catch (MaximumSizeExceededException msee) { + mpo = new MapPageOverlay(); + getMapPageOverlays().add(mpo); + try { + mpo.addOverlay(name); + } catch (MaximumSizeExceededException ex) { + // Should never happen (but log just in case) + log.error("createOverlay():: resulted in a MaximumSizeExceededException"); + } + } + } + + /** + * Getter method for the most recent MapPageOverlay added to the + * Active Environment Group (returns null if no MapPageOverlay exist) + * @return the most recent Map Coded Font + */ + private MapPageOverlay getCurrentMapPageOverlay() { + if (mapPageOverlays != null && mapPageOverlays.size() > 0) { + return (MapPageOverlay) mapPageOverlays.get(mapPageOverlays.size() - 1); + } else { + return null; + } + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (mapPageOverlays != null) { + writeObjects(mapPageOverlays, os); + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java index 7545ee3af..393cff84b 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java @@ -18,14 +18,17 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.UnsupportedEncodingException; /** * This is the base class for all named data stream objects. * A named data stream object has an 8 byte EBCIDIC name. */ -public abstract class AbstractNamedAFPObject extends AbstractAFPObject { - +public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject { + + private static final int DEFAULT_NAME_LENGTH = 8; + /** * The actual name of the object */ @@ -41,22 +44,13 @@ public abstract class AbstractNamedAFPObject extends AbstractAFPObject { */ protected AbstractNamedAFPObject() { } - - private static final int DEFAULT_NAME_LENGTH = 8; - - /** - * @return the name length of this object - */ - protected int getNameLength() { - return DEFAULT_NAME_LENGTH; - } - + /** * Constructor for the ActiveEnvironmentGroup, this takes a * name parameter which should be 8 characters long. * @param name the object name */ - public AbstractNamedAFPObject(String name) { + protected AbstractNamedAFPObject(String name) { int nameLen = getNameLength(); if (name.length() < nameLen) { this.name = (name + " ").substring(0, nameLen); @@ -66,19 +60,27 @@ public abstract class AbstractNamedAFPObject extends AbstractAFPObject { } else { this.name = name; } - try { - this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException usee) { - this.nameBytes = name.getBytes(); log.warn( "Constructor:: UnsupportedEncodingException translating the name " + name); - } - + } + + /** + * @return the name length of this object + */ + protected int getNameLength() { + return DEFAULT_NAME_LENGTH; + } + + /** + * @return the name of the page group + */ + public String getName() { + return name; } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java index 4ffcc4d94..f373b5bf7 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java @@ -20,7 +20,8 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; -import java.util.ArrayList; +import java.io.IOException; +import java.io.OutputStream; import java.util.List; import org.apache.fop.render.afp.fonts.AFPFont; @@ -46,32 +47,27 @@ import org.apache.fop.render.afp.tools.StringUtils; * in page state. * */ -public abstract class AbstractPageObject extends AbstractNamedAFPObject { +public abstract class AbstractPageObject extends AbstractResourceGroupContainer { /** * The active environment group for the page */ - protected ActiveEnvironmentGroup activeEnvironmentGroup = null; + protected ActiveEnvironmentGroup activeEnvironmentGroup; /** * The presentation text object, we only have one per page */ - private PresentationTextObject presentationTextObject = null; - - /** - * The list of objects within the page - */ - protected List objects = new ArrayList(); + private PresentationTextObject presentationTextObject; /** * The list of tag logical elements */ - protected ArrayList tagLogicalElements = new ArrayList(); + protected List tagLogicalElements; /** * The list of the include page segments */ - protected ArrayList segments = new ArrayList(); + protected List segments; /** * The page width @@ -112,8 +108,8 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { */ public AbstractPageObject(String name, int width, int height, int rotation, int widthRes, int heightRes) { - super(name); + this.width = width; this.height = height; this.rotation = rotation; @@ -121,7 +117,8 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { /** * Every page object must have an ActiveEnvironmentGroup */ - activeEnvironmentGroup = new ActiveEnvironmentGroup(width, height, widthRes, heightRes); + this.activeEnvironmentGroup = new ActiveEnvironmentGroup( + width, height, widthRes, heightRes); if (rotation != 0) { switch (rotation) { @@ -152,7 +149,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * the point size of the font */ public void createFont(int fontReference, AFPFont font, int size) { - activeEnvironmentGroup.createFont(fontReference, font, size, 0); + getActiveEnvironmentGroup().createFont(fontReference, font, size, 0); } /** @@ -183,7 +180,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * Helper method to create text on the current page, this method delegates * to the presentation text object in order to construct the text. * - * @param fontReference + * @param fontRef * the font number used as the resource identifier * @param x * the x coordinate of the text data @@ -200,15 +197,15 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * @param data * the text data to create */ - public void createText(int fontReference, int x, int y, int textRotation, Color col, + public void createText(int fontRef, int x, int y, int textRotation, Color col, int vsci, int ica, byte[] data) { getPresentationTextObject().createTextData( - fontReference, x, y, textRotation, col, vsci, ica, data); + fontRef, x, y, textRotation, col, vsci, ica, data); } /** * Helper method to mark the end of the page. This should end the control - * sequence on the current presenation text object. + * sequence on the current presentation text object. */ public void endPage() { if (presentationTextObject != null) { @@ -237,14 +234,11 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * @param blue * the blue value */ - public void createShading(int x, int y, int w, int h, int red, int green, - int blue) { - + public void createShading(int x, int y, int w, int h, int red, int green, int blue) { int xCoord = 0; int yCoord = 0; int areaWidth = 0; int areaHeight = 0; - switch (rotation) { case 90: xCoord = areaWidth - y - h; @@ -278,7 +272,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { int greyscale = Math.round((shade / 255) * 16); String imageName = "IMG" - + StringUtils.lpad(String.valueOf(objects.size() + 1), + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); IMImageObject io = new IMImageObject(imageName); @@ -291,17 +285,23 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { icp.setYSize(8); //defining this as a resource - ImageRasterData ird = new ImageRasterData(ImageRasterPattern - .getRasterData(greyscale)); + ImageRasterData ird = new ImageRasterData( + ImageRasterPattern.getRasterData(greyscale)); io.setImageOutputControl(ioc); io.setImageInputDescriptor(iid); io.setImageCellPosition(icp); io.setImageRasterData(ird); - objects.add(io); - + addObject(io); } + private void endPresentationObject() { + if (presentationTextObject != null) { + presentationTextObject.endControlSequence(); + presentationTextObject = null; + } + } + /** * Helper method to create a presentation text object * on the current page and to return the object. @@ -310,49 +310,12 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { private PresentationTextObject getPresentationTextObject() { if (presentationTextObject == null) { this.presentationTextObject = new PresentationTextObject(); - objects.add(this.presentationTextObject); + addObject(this.presentationTextObject); } return presentationTextObject; } /** - * Helper method to create an image on the current page and to return - * the object. - * @return the image object - */ - public ImageObject getImageObject() { - - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); - presentationTextObject = null; - } - String imageName = "IMG" - + StringUtils.lpad(String.valueOf(objects.size() + 1), - '0', 5); - ImageObject imageObj = new ImageObject(imageName); - objects.add(imageObj); - return imageObj; - } - - /** - * Helper method to create a graphic on the current page and to return - * the object. - * @return the graphics object - */ - public GraphicsObject getGraphicsObject() { - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); - presentationTextObject = null; - } - String graphicName = "GRA" - + StringUtils.lpad(String.valueOf(objects.size() + 1), - '0', 5); - GraphicsObject graphicsObj = new GraphicsObject(graphicName); - objects.add(graphicsObj); - return graphicsObj; - } - - /** * Creates a TagLogicalElement on the page. * * @param name @@ -362,6 +325,9 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { */ public void createTagLogicalElement(String name, String value) { TagLogicalElement tle = new TagLogicalElement(name, value); + if (tagLogicalElements == null) { + tagLogicalElements = new java.util.ArrayList(); + } tagLogicalElements.add(tle); } @@ -371,8 +337,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { * @param content the byte data */ public void createNoOperation(String content) { - NoOperation noOp = new NoOperation(content); - objects.add(noOp); + addObject(new NoOperation(content)); } /** @@ -387,6 +352,9 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { */ public void createIncludePageSegment(String name, int xCoor, int yCoor) { IncludePageSegment ips = new IncludePageSegment(name, xCoor, yCoor); + if (segments == null) { + segments = new java.util.ArrayList(); + } segments.add(ips); } @@ -430,4 +398,54 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject { public int getRotation() { return rotation; } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + getActiveEnvironmentGroup().writeDataStream(os); + writeObjects(segments, os); + writeObjects(tagLogicalElements, os); + writeObjects(objects, os); + } + +// /** +// * {@inheritDoc} +// */ +// public IncludeObject createImageObject(ImageObjectParameters params) { +// endPresentationObject(); +// return super.createImageObject(params); +// } +// +// /** +// * {@inheritDoc} +// */ +// public IncludeObject createGraphicsObject(DataObjectParameters params) { +// endPresentationObject(); +// return super.createGraphicsObject(params); +// } + + /** + * {@inheritDoc} + */ + protected void addObject(AbstractStructuredAFPObject obj) { + if (obj instanceof IncludeObject) { + IncludeObject includeObj = (IncludeObject)obj; + AbstractStructuredAFPObject refObj = includeObj.getReferencedObject(); + if (refObj instanceof ImageObject || refObj instanceof GraphicsObject) { + getActiveEnvironmentGroup().createResource(refObj); + } + } + endPresentationObject(); + super.addObject(obj); + } + +// /** +// * {@inheritDoc} +// */ +// protected void addObject(AbstractStructuredAFPObject obj) { +// endPresentationObject(); +// super.addObject(obj); +// } } diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java new file mode 100644 index 000000000..e40aa1b4f --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractPreparedAFPObject.java @@ -0,0 +1,83 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; + + +/** + * A base class that carries out early preparation of structured field data + * for the AFP object (so the data length can be pre-calculated) + */ +public abstract class AbstractPreparedAFPObject extends AbstractNamedAFPObject +implements PreparedAFPObject { + + /** structured field data to be written */ + protected byte[] data = null; + + /** + * Default constructor + */ + public AbstractPreparedAFPObject() { + } + + /** + * Named constructor + * @param name the name of this AFP object + */ + public AbstractPreparedAFPObject(String name) { + super(name); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); // write triplets + if (this.data != null) { + os.write(this.data); + } + } + + /** + * @return the start data length of this structured field + */ + protected int getStartDataLength() { + return 0; + } + + /** + * @return the data length of the structured field data of this AFP object + */ + public int getDataLength() { + if (this.data != null) { + return this.data.length; + } + return 0; + } + + /** + * @return the structured field length + */ + protected int getLength() { + return getStartDataLength() + getTripletDataLength() + getDataLength(); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java new file mode 100644 index 000000000..eac4b778f --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceEnvironmentGroupContainer.java @@ -0,0 +1,108 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; + +/** + * An abstract class which encapsulates the common features of + * Document and PageGroup resource containers + */ +public abstract class AbstractResourceEnvironmentGroupContainer + extends AbstractResourceGroupContainer { + + /** + * The resource environment group used to store complex resources + */ + protected ResourceEnvironmentGroup resourceEnvironmentGroup = null; + + /** + * Main constructor + * @param name the name of this resource container + */ + public AbstractResourceEnvironmentGroupContainer(String name) { + super(name); + } + + /** + * Adds a page to the resource container. + * @param page - the Page object + */ + public void addPage(PageObject page) { + addObject(page); + } + + /** + * Adds a PageGroup to the resource container. + * @param pageGroup the PageGroup object + */ + public void addPageGroup(PageGroup pageGroup) { + addObject(pageGroup); + } + + /** + * Creates an InvokeMediaMap on the page. + * + * @param name + * the name of the media map + */ + public void createInvokeMediumMap(String name) { + addObject(new InvokeMediumMap(name)); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (resourceEnvironmentGroup != null) { + resourceEnvironmentGroup.writeDataStream(os); + } + if (objects != null) { + for (Iterator it = objects.iterator(); it.hasNext();) { + AbstractAFPObject ao = (AbstractAFPObject)it.next(); + if (ao instanceof PageObject && ((PageObject)ao).isComplete() + || ao instanceof PageGroup && ((PageGroup)ao).isComplete()) { + ao.writeDataStream(os); + it.remove(); + } else { + break; + } + } + } + } + + private ResourceEnvironmentGroup getResourceEnvironmentGroup() { + if (resourceEnvironmentGroup == null) { + this.resourceEnvironmentGroup = new ResourceEnvironmentGroup(); + } + return this.resourceEnvironmentGroup; + } + + /** + * Adds a resource mapping to this resource environment group + * @param obj a resource to be referenced in this resource environment group + */ + protected void addResource(AbstractStructuredAFPObject obj) { + getResourceEnvironmentGroup().addObject(obj); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java new file mode 100644 index 000000000..e8e25b6b8 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/AbstractResourceGroupContainer.java @@ -0,0 +1,124 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Set; + +import org.apache.fop.render.afp.DataObjectParameters; +import org.apache.fop.render.afp.ImageObjectParameters; + +/** + * An abstract container of resource objects + */ +public abstract class AbstractResourceGroupContainer extends AbstractNamedAFPObject { + /** + * The resource group object + */ + private ResourceGroup resourceGroup = null; + + /** + * The list of objects within this resource container + */ + protected Set/*<AbstractStructuredAFPObject>*/ objects = null; + + /** + * Unnamed constructor + */ + public AbstractResourceGroupContainer() { + } + + /** + * Named constructor + * @param name the name of this resource container + */ + public AbstractResourceGroupContainer(String name) { + super(name); + } + + /** + * @return the number of resources in this container + */ + protected int getResourceCount() { + if (resourceGroup != null) { + return resourceGroup.getResourceCount(); + } + return 0; + } + + /** + * Adds an AFP object to the resource group in this container + * @param obj an AFP object + */ + protected void addObject(AbstractAFPObject obj) { + if (objects == null) { + this.objects = new java.util.LinkedHashSet/*<AbstractAFPObject>*/(); + } + objects.add(obj); + } + + /** + * @return true if this resource group container contains resources + */ + protected boolean hasResources() { + return resourceGroup != null && resourceGroup.getResourceCount() > 0; + } + + /** + * @return the resource group in this resource group container + */ + protected ResourceGroup getResourceGroup() { + if (resourceGroup == null) { + resourceGroup = new ResourceGroup(); + } + return resourceGroup; + } + + /** + * Helper method to create an image on the current container and to return + * the object. + * @param params the image object parameters + * @return the image object + */ + public IncludeObject createImageObject(ImageObjectParameters params) { + return getResourceGroup().addObject(params); + } + + /** + * Helper method to create a graphic in the current container and to return + * the object. + * @param params the data object parameters + * @return the graphics object + */ + public IncludeObject createGraphicsObject(DataObjectParameters params) { + return getResourceGroup().addObject(params); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (resourceGroup != null) { + resourceGroup.writeDataStream(os); + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java index e061748ca..3c448b2ab 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java +++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java @@ -19,65 +19,225 @@ package org.apache.fop.render.afp.modca; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.modca.triplets.MeasurementUnitsTriplet; +import org.apache.fop.render.afp.modca.triplets.ObjectAreaSizeTriplet; +import org.apache.fop.render.afp.modca.triplets.ObjectClassificationTriplet; +import org.apache.fop.render.afp.modca.triplets.Triplet; /** * An abstract class encapsulating an MODCA structured object */ -public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject { +public abstract class AbstractStructuredAFPObject extends AbstractAFPObject { /** + * list of object triplets + */ + protected List/*<Triplet>*/ triplets = null; + + /** + * triplet data created from triplet list + */ + protected byte[] tripletData = null; + + /** * Default constructor */ - public AbstractStructuredAFPObject() { - super(); + protected AbstractStructuredAFPObject() { } /** - * Named constructor - * @param name name of structured object + * @return the triplet data length */ - public AbstractStructuredAFPObject(String name) { - super(name); + protected int getTripletDataLength() { + if (tripletData != null) { + return tripletData.length; + } + return 0; } - + /** * Helper method to write the start of the Object. * @param os The stream to write to * @throws IOException an I/O exception if one occurred */ protected void writeStart(OutputStream os) throws IOException { + if (triplets != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + writeObjects(triplets, baos); + this.tripletData = baos.toByteArray(); + } } /** * Helper method to write the contents of the Object. * @param os The stream to write to - * @throws IOException an I/O exception if one occurred + * @throws IOException The stream to write to */ protected void writeContent(OutputStream os) throws IOException { + writeTriplets(os); } /** + * Writes any triplet data + * @param os The stream to write to + * @throws IOException The stream to write to + */ + protected void writeTriplets(OutputStream os) throws IOException { + if (tripletData != null) { + os.write(tripletData); + } else if (triplets != null) { + writeObjects(triplets, os); + } + } + + /** * Helper method to write the end of the Object. * @param os The stream to write to * @throws IOException an I/O exception if one occurred */ protected void writeEnd(OutputStream os) throws IOException { } - + /** * Accessor method to write the AFP datastream for the Image Object * @param os The stream to write to * @throws IOException in the event that an I/O exception occurred */ - public void writeDataStream(OutputStream os) - throws IOException { - + public void writeDataStream(OutputStream os) throws IOException { writeStart(os); - writeContent(os); - writeEnd(os); - } + } + + /** + * Returns the first matching triplet found in the structured field triplet list + * @param tripletId the triplet identifier + */ + private Triplet getTriplet(byte tripletId) { + Iterator it = getTriplets().iterator(); + while (it.hasNext()) { + Triplet triplet = (Triplet)it.next(); + if (triplet.getId() == tripletId) { + return triplet; + } + } + return null; + } + + /** + * @param tripletId the triplet identifier + * @return true if the structured field has the given triplet + */ + private boolean hasTriplet(byte tripletId) { + return getTriplet(tripletId) != null; + } + + /** + * Adds a triplet to this structured object + * @param triplet the triplet to add + */ + private void addTriplet(Triplet triplet) { + getTriplets().add(triplet); + } + + /** + * Adds a list of triplets to the triplets contained within this structured field + * @param tripletCollection a collection of triplets + */ + private void addTriplets(Collection/*<Triplet>*/ tripletCollection) { + if (tripletCollection != null) { + getTriplets().addAll(tripletCollection); + } + } + + /** + * @return the triplet list pertaining to this resource + */ + protected List/*<Triplet>*/ getTriplets() { + if (triplets == null) { + triplets = new java.util.ArrayList(); + } + return triplets; + } + + /** + * Sets the fully qualified name of this resource + * @param fqnType the fully qualified name type of this resource + * @param fqnFormat the fully qualified name format of this resource + * @param fqName the fully qualified name of this resource + */ + public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName) { + byte[] fqNameBytes; + try { + fqNameBytes = fqName.getBytes(AFPConstants.EBCIDIC_ENCODING); + addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqNameBytes)); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + } + + /** + * @return the fully qualified name of this triplet or null if it does not exist + */ + public String getFullyQualifiedName() { + FullyQualifiedNameTriplet fqNameTriplet + = (FullyQualifiedNameTriplet)getTriplet(Triplet.FULLY_QUALIFIED_NAME); + byte[] nameBytes = fqNameTriplet.getFullyQualifiedName(); + if (nameBytes != null) { + try { + return new String(nameBytes, AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + } else { + log.warn(this + " has no fully qualified name"); + } + return null; + } + + /** + * Sets the objects classification + * @param objectClass the classification of the object + * @param componentId the component Id of the object + */ + public void setObjectClassification(byte objectClass, byte componentId) { + addTriplet(new ObjectClassificationTriplet(objectClass, componentId)); + } + + /** + * Specifies the extent of an object area in the X and Y directions + * @param x the x direction extent + * @param y the y direction extent + */ + public void setObjectAreaSize(int x, int y) { + addTriplet(new ObjectAreaSizeTriplet(x, y)); + } + + /** + * Sets the measurement units used to specify the units of measure + */ + public void setMeasurementUnits() { + addTriplet(new MeasurementUnitsTriplet()); + } + + /** + * Sets a comment on this resource + * @param comment a comment string + */ + public void setComment(String comment) { + try { + addTriplet(new Triplet(Triplet.COMMENT, comment)); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage()); + } + } } diff --git a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java index eb537b0d7..845af4dfc 100644 --- a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java @@ -18,6 +18,7 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; import java.util.List; @@ -37,7 +38,7 @@ import org.apache.fop.render.afp.fonts.AFPFont; * containing page or overlay. * */ -public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { +public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { /** * Default name for the active environment group @@ -47,7 +48,12 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { /** * The collection of MapCodedFont objects */ - private List mapCodedFonts = new java.util.ArrayList(); + private List mapCodedFonts = null; + + /** + * The collection of MapDataResource objects + */ + private List mapDataResources = null; /** * The Object Area Descriptor for the active environment group @@ -70,22 +76,14 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { private PageDescriptor pageDescriptor = null; /** - * The collection of MapPageOverlay objects - */ - private List mapPageOverlays = new java.util.ArrayList(); - - /** * Default constructor for the ActiveEnvironmentGroup. * @param width the page width * @param height the page height * @param widthRes the page width resolution * @param heightRes the page height resolution */ - public ActiveEnvironmentGroup(int width, int height, - int widthRes, int heightRes) { - + public ActiveEnvironmentGroup(int width, int height, int widthRes, int heightRes) { this(DEFAULT_NAME, width, height, widthRes, heightRes); - } /** @@ -97,9 +95,7 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @param widthRes the page width resolution * @param heightRes the page height resolution */ - public ActiveEnvironmentGroup(String name, int width, int height, - int widthRes, int heightRes) { - + public ActiveEnvironmentGroup(String name, int width, int height, int widthRes, int heightRes) { super(name); // Create PageDescriptor @@ -112,7 +108,6 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { // Create PresentationTextDataDescriptor presentationTextDataDescriptor = new PresentationTextDescriptor(width, height, widthRes, heightRes); - } /** @@ -122,10 +117,8 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @param rotation the rotation */ public void setPosition(int x, int y, int rotation) { - // Create ObjectAreaPosition objectAreaPosition = new ObjectAreaPosition(x, y, rotation); - } /** @@ -134,9 +127,7 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @return the page descriptor object */ public PageDescriptor getPageDescriptor() { - return pageDescriptor; - } /** @@ -145,47 +136,36 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { * @return the presentation text descriptor */ public PresentationTextDescriptor getPresentationTextDataDescriptor() { - return presentationTextDataDescriptor; - } /** - * Accessor method to write the AFP datastream for the active environment group. - * @param os The stream to write to - * @throws java.io.IOException throws if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(mapCodedFonts, os); - - writeObjectList(mapPageOverlays, os); - - pageDescriptor.writeDataStream(os); - + public void writeContent(OutputStream os) throws IOException { + super.writeTriplets(os); + + writeObjects(mapCodedFonts, os); + writeObjects(mapPageOverlays, os); + writeObjects(mapDataResources, os); + + if (pageDescriptor != null) { + pageDescriptor.writeDataStream(os); + } if (objectAreaDescriptor != null && objectAreaPosition != null) { objectAreaDescriptor.writeDataStream(os); objectAreaPosition.writeDataStream(os); } - - presentationTextDataDescriptor.writeDataStream(os); - - writeEnd(os); - + if (presentationTextDataDescriptor != null) { + presentationTextDataDescriptor.writeDataStream(os); + } } /** - * Helper method to write the start of the active environment group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -195,26 +175,17 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - - os.write(data); - + os.write(data); } /** - * Helper method to write the end of the active environment group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -224,130 +195,75 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); + } + private List getMapCodedFonts() { + if (mapCodedFonts == null) { + mapCodedFonts = new java.util.ArrayList(); + } + return mapCodedFonts; + } + + private List getMapDataResources() { + if (mapDataResources == null) { + mapDataResources = new java.util.ArrayList(); + } + return mapDataResources; } /** * Method to create a map coded font object - * @param fontReference the font number used as the resource identifier + * @param fontRef the font number used as the resource identifier * @param font the font * @param size the point size of the font * @param orientation the orientation of the font (e.g. 0, 90, 180, 270) */ - public void createFont( - int fontReference, - AFPFont font, - int size, - int orientation) { - + public void createFont(int fontRef, AFPFont font, int size, int orientation) { MapCodedFont mcf = getCurrentMapCodedFont(); - if (mcf == null) { mcf = new MapCodedFont(); - mapCodedFonts.add(mcf); + getMapCodedFonts().add(mcf); } try { - - mcf.addFont( - fontReference, - font, - size, - orientation); - + mcf.addFont(fontRef, font, size, orientation); } catch (MaximumSizeExceededException msee) { - mcf = new MapCodedFont(); - mapCodedFonts.add(mcf); + getMapCodedFonts().add(mcf); try { - - mcf.addFont( - fontReference, - font, - size, - orientation); - + mcf.addFont(fontRef, font, size, orientation); } catch (MaximumSizeExceededException ex) { - // Should never happen (but log just in case) log.error("createFont():: resulted in a MaximumSizeExceededException"); - - } - - } - - } - - /** - * Actually creates the MPO object. - * Also creates the supporting object (an IPO) - * @param name the name of the overlay to be used - */ - public void createOverlay(String name) { - - MapPageOverlay mpo = getCurrentMapPageOverlay(); - - if (mpo == null) { - mpo = new MapPageOverlay(); - mapPageOverlays.add(mpo); - } - - try { - - mpo.addOverlay(name); - - } catch (MaximumSizeExceededException msee) { - mpo = new MapPageOverlay(); - mapPageOverlays.add(mpo); - try { - mpo.addOverlay(name); - } catch (MaximumSizeExceededException ex) { - // Should never happen (but log just in case) - log.error("createOverlay():: resulted in a MaximumSizeExceededException"); } } } - + /** * Getter method for the most recent MapCodedFont added to the * Active Environment Group (returns null if no MapCodedFonts exist) * @return the most recent Map Coded Font. */ private MapCodedFont getCurrentMapCodedFont() { - - int size = mapCodedFonts.size(); + int size = getMapCodedFonts().size(); if (size > 0) { - return (MapCodedFont) mapCodedFonts.get(mapCodedFonts.size() - 1); + return (MapCodedFont)mapCodedFonts.get(size - 1); } else { return null; } - } - + + /** - * Getter method for the most recent MapPageOverlay added to the - * Active Environment Group (returns null if no MapPageOverlay exist) - * @return the most recent Map Coded Font + * Method to create a map data resource object + * @param obj creates a map data resource entry for a given AFP data resource object */ - private MapPageOverlay getCurrentMapPageOverlay() { - - int size = mapPageOverlays.size(); - if (size > 0) { - return (MapPageOverlay) mapPageOverlays.get( - mapPageOverlays.size() - 1); - } else { - return null; - } - + public void createResource(AbstractStructuredAFPObject obj) { + getMapDataResources().add(new MapDataResource(obj)); } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/Document.java b/src/java/org/apache/fop/render/afp/modca/Document.java index 3d2d40a3a..72c65e8a7 100644 --- a/src/java/org/apache/fop/render/afp/modca/Document.java +++ b/src/java/org/apache/fop/render/afp/modca/Document.java @@ -18,10 +18,9 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; /** * The document is the highest level of the MO:DCA data-stream document @@ -48,23 +47,13 @@ import java.util.List; * document to be presented. * */ -public final class Document extends AbstractNamedAFPObject { +public final class Document extends AbstractResourceEnvironmentGroupContainer { /** - * Ststic default name reference + * Static default generated name reference */ private static final String DEFAULT_NAME = "DOC00001"; - - /** - * A list of the objects in the document - */ - private List objects = new java.util.ArrayList(); - - /** - * The document started state - */ - private boolean started = false; - + /** * The document completion state */ @@ -82,36 +71,14 @@ public final class Document extends AbstractNamedAFPObject { * @param name The name of the document */ public Document(String name) { - super(name); - - } - - /** - * Adds a page to the document. - * @param page - the Page object - */ - public void addPage(PageObject page) { - if (!objects.contains(page)) { - objects.add(page); - } - } - - /** - * Adds a PageGroup to the document. - * @param pageGroup the PageGroup object - */ - public void addPageGroup(PageGroup pageGroup) { - objects.add(pageGroup); } /** * Method to mark the end of the page group. */ public void endDocument() { - complete = true; - } /** @@ -127,40 +94,17 @@ public final class Document extends AbstractNamedAFPObject { * @param os The stream to write to * @throws java.io.IOException thrown if an I/O exception of some sort has occurred */ - public void writeDataStream(OutputStream os) - throws IOException { - - if (!started) { - writeStart(os); - started = true; - } - - for (Iterator it = objects.iterator(); it.hasNext();) { - AbstractAFPObject ao = (AbstractAFPObject)it.next(); - if (ao instanceof PageObject && ((PageObject)ao).isComplete() - || ao instanceof PageGroup && ((PageGroup)ao).isComplete()) { - ao.writeDataStream(os); - it.remove(); - } else { - break; - } + public void writeDataStream(OutputStream os) throws IOException { + if (isComplete()) { + super.writeDataStream(os); } - - if (complete) { - writeEnd(os); - } - } /** - * Helper method to write the start of the Document - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -170,26 +114,17 @@ public final class Document extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** - * Helper method to write the end of the Document. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -199,15 +134,16 @@ public final class Document extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - + + /** + * {@inheritDoc} + */ + public String toString() { + return this.name; + } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java index 065ca6626..7e5f12877 100644 --- a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java +++ b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java @@ -23,22 +23,22 @@ import java.awt.Color; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.modca.goca.GraphicsBox; -import org.apache.fop.render.afp.modca.goca.GraphicsData; -import org.apache.fop.render.afp.modca.goca.GraphicsFillet; -import org.apache.fop.render.afp.modca.goca.GraphicsFullArc; -import org.apache.fop.render.afp.modca.goca.GraphicsImageBegin; -import org.apache.fop.render.afp.modca.goca.GraphicsImageData; -import org.apache.fop.render.afp.modca.goca.GraphicsImageEnd; -import org.apache.fop.render.afp.modca.goca.GraphicsLine; -import org.apache.fop.render.afp.modca.goca.GraphicsSetArcParameters; -import org.apache.fop.render.afp.modca.goca.GraphicsSetCharacterSet; -import org.apache.fop.render.afp.modca.goca.GraphicsSetCurrentPosition; -import org.apache.fop.render.afp.modca.goca.GraphicsSetLineType; -import org.apache.fop.render.afp.modca.goca.GraphicsSetLineWidth; -import org.apache.fop.render.afp.modca.goca.GraphicsSetPatternSymbol; -import org.apache.fop.render.afp.modca.goca.GraphicsSetProcessColor; -import org.apache.fop.render.afp.modca.goca.GraphicsString; +import org.apache.fop.render.afp.goca.GraphicsBox; +import org.apache.fop.render.afp.goca.GraphicsData; +import org.apache.fop.render.afp.goca.GraphicsFillet; +import org.apache.fop.render.afp.goca.GraphicsFullArc; +import org.apache.fop.render.afp.goca.GraphicsImageBegin; +import org.apache.fop.render.afp.goca.GraphicsImageData; +import org.apache.fop.render.afp.goca.GraphicsImageEnd; +import org.apache.fop.render.afp.goca.GraphicsLine; +import org.apache.fop.render.afp.goca.GraphicsSetArcParameters; +import org.apache.fop.render.afp.goca.GraphicsSetCharacterSet; +import org.apache.fop.render.afp.goca.GraphicsSetCurrentPosition; +import org.apache.fop.render.afp.goca.GraphicsSetLineType; +import org.apache.fop.render.afp.goca.GraphicsSetLineWidth; +import org.apache.fop.render.afp.goca.GraphicsSetPatternSymbol; +import org.apache.fop.render.afp.goca.GraphicsSetProcessColor; +import org.apache.fop.render.afp.goca.GraphicsString; /** * Top-level GOCA graphics object. @@ -309,7 +309,7 @@ public class GraphicsObject extends AbstractDataObject { * {@inheritDoc} */ public String toString() { - return "GraphicsObject"; + return "GraphicsObject: " + getName(); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java b/src/java/org/apache/fop/render/afp/modca/IMImageObject.java index bb43950dd..2afd3fa49 100644 --- a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IMImageObject.java @@ -63,9 +63,7 @@ public class IMImageObject extends AbstractNamedAFPObject { * @param name The name of the image. */ public IMImageObject(String name) { - super(name); - } /** @@ -101,44 +99,29 @@ public class IMImageObject extends AbstractNamedAFPObject { } /** - * Accessor method to write the AFP datastream for the IM Image Objetc - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); if (imageOutputControl != null) { imageOutputControl.writeDataStream(os); } - if (imageInputDescriptor != null) { imageInputDescriptor.writeDataStream(os); } - if (imageCellPosition != null) { imageCellPosition.writeDataStream(os); } - if (imageRasterData != null) { imageRasterData.writeDataStream(os); } - - writeEnd(os); - } /** - * Helper method to write the start of the IM Image Object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -148,26 +131,17 @@ public class IMImageObject extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** - * Helper method to write the end of the IM Image Object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -177,15 +151,9 @@ public class IMImageObject extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - } diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java index e7fd538e1..4aea02901 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java @@ -26,7 +26,31 @@ import org.apache.fop.render.afp.tools.BinaryUtils; /** * Image content IOCA object */ -public class ImageContent extends AbstractAFPObject { +public class ImageContent extends AbstractStructuredAFPObject { + + /** + * The CCITT T.4 Group 3 Coding Standard (G3 MH-Modified Huffman) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * one-dimensional compression. + */ + public static final byte COMPID_G3_MH = (byte)0x80; + + /** + * The CCITT T.4 Group 3 Coding Option (G3 MR-Modified READ) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * two-dimensional compression. + */ + public static final byte COMPID_G3_MR = (byte)0x81; + + /** + * The CCITT T.6 Group 4 Coding Standard (G4 MMR-Modified Modified READ) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * two-dimensional compression. + */ + public static final byte COMPID_G3_MMR = (byte)0x82; /** * The image size parameter @@ -56,13 +80,12 @@ public class ImageContent extends AbstractAFPObject { /** * The image data */ - private byte[] data = null; + private byte[] imageData = null; /** * Constructor for the image content */ public ImageContent() { - } /** @@ -111,70 +134,55 @@ public class ImageContent extends AbstractAFPObject { /** * Set the data of the image. - * @param dat the image data + * @param data the image data */ - public void setImageData(byte[] dat) { - this.data = dat; + public void setImageData(byte[] data) { + this.imageData = data; } /** - * Accessor method to write the AFP datastream for the Image Content - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurs + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { - - writeStart(os); - + protected void writeContent(OutputStream os) throws IOException { if (imageSizeParam != null) { imageSizeParam.writeDataStream(os); } - os.write(getImageEncodingParameter()); - os.write(getImageIDESizeParameter()); - os.write(getIDEStructureParameter()); - os.write(getExternalAlgorithmParameter()); - - if (data != null) { + if (imageData != null) { int off = 0; - while (off < data.length) { - int len = Math.min(30000, data.length - off); + while (off < imageData.length) { + int len = Math.min(30000, imageData.length - off); os.write(getImageDataStart(len)); - os.write(data, off, len); + os.write(imageData, off, len); off += len; } } - - writeEnd(os); - } /** - * Helper method to write the start of the Image Content. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) throws IOException { - byte[] startData = new byte[] { + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[] { (byte)0x91, // ID 0x01, // Length (byte)0xff, // Object Type = IOCA Image Object }; - os.write(startData); + os.write(data); } /** - * Helper method to write the end of the Image Content. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) throws IOException { - byte[] endData = new byte[] { + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { (byte)0x93, // ID 0x00, // Length }; - os.write(endData); + os.write(data); } /** diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java index 5f8454fa8..2876e8348 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java @@ -21,7 +21,6 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import java.io.UnsupportedEncodingException; /** * An Image Segment is represented by a set of self-defining fields, fields @@ -33,7 +32,7 @@ import java.io.UnsupportedEncodingException; * * Only one Image Content can exist within a single IOCA Image Segment. */ -public class ImageSegment extends AbstractAFPObject { +public class ImageSegment extends AbstractNamedAFPObject { /** * Default name for the object environment group @@ -41,16 +40,6 @@ public class ImageSegment extends AbstractAFPObject { private static final String DEFAULT_NAME = "IS01"; /** - * The name of the image segment - */ - private String name; - - /** - * The name of the image segment as EBCIDIC bytes - */ - private byte[] nameBytes; - - /** * The ImageContent for the image segment */ private ImageContent imageContent = null; @@ -68,20 +57,14 @@ public class ImageSegment extends AbstractAFPObject { * @param name The name of the image. */ public ImageSegment(String name) { - if (name.length() != 4) { - String msg = "Image segment name must be 4 characters long " + name; - log.error("Constructor:: " + msg); - throw new IllegalArgumentException(msg); - } - this.name = name; - try { - this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException usee) { - this.nameBytes = name.getBytes(); - log.warn( - "Constructor:: UnsupportedEncodingException translating the name " - + name); - } + super(name); + } + + /** + * {@inheritDoc} + */ + protected int getNameLength() { + return 4; } /** @@ -155,43 +138,33 @@ public class ImageSegment extends AbstractAFPObject { } /** - * Accessor method to write the AFP datastream for the Image Segment - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) throws IOException { - writeStart(os); + public void writeContent(OutputStream os) throws IOException { if (imageContent != null) { imageContent.writeDataStream(os); } - writeEnd(os); } /** - * Helper method to write the start of the Image Segment. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) throws IOException { + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[] { 0x70, // ID 0x04, // Length - 0x00, // Name byte 1 - 0x00, // Name byte 2 - 0x00, // Name byte 3 - 0x00, // Name byte 4 + nameBytes[0], // Name byte 1 + nameBytes[1], // Name byte 2 + nameBytes[2], // Name byte 3 + nameBytes[3], // Name byte 4 }; - for (int i = 0; i < nameBytes.length; i++) { - data[2 + i] = nameBytes[i]; - } os.write(data); - } /** - * Helper method to write the end of the Image Segment. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) throws IOException { + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[] { 0x71, // ID 0x00, // Length diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java index 890fdcd9d..0fceff893 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java @@ -40,28 +40,92 @@ import org.apache.fop.render.afp.tools.BinaryUtils; public class IncludeObject extends AbstractNamedAFPObject { /** - * The object type + * the include object is of type page segment */ - private byte objectType = (byte) 0x92; + protected static final byte TYPE_PAGE_SEGMENT = (byte)0x5F; + + /** + * the include object is of type other + */ + protected static final byte TYPE_OTHER = (byte)0x92; + + /** + * the include object is of type graphic + */ + protected static final byte TYPE_GRAPHIC = (byte)0xBB; + + /** + * the included object is of type barcode + */ + protected static final byte TYPE_BARCODE = (byte)0xEB; + + /** + * the included object is of type image + */ + protected static final byte TYPE_IMAGE = (byte)0xFB; + + /** + * The object type (default is other) + */ + private byte objectType = TYPE_OTHER; /** * The orientation on the include object */ - private int orientation = 0; + private int orientation = -1; + + /** + * The X-axis origin of the object area + */ + private int xOffset = -1; + + /** + * The Y-axis origin of the object area + */ + private int yOffset = -1; + + /** + * The X-axis origin defined in the object + */ + private int xContentOffset = -1; /** + * The Y-axis origin defined in the object + */ + private int yContentOffset = -1; + + /** + * The object referenced by this include object + */ + private AbstractStructuredAFPObject referencedObject = null; + + /** * Constructor for the include object with the specified name, the name must * be a fixed length of eight characters and is the name of the referenced * object. * - * @param name - * the name of the image + * @param resourceObj + * the resource object wrapper */ - public IncludeObject(String name) { - - super(name); - objectType = (byte) 0xFB; + public IncludeObject(ResourceObject resourceObj) { + super(resourceObj.getResource().getName()); + this.referencedObject = resourceObj.getResource(); + if (referencedObject instanceof ImageObject) { + this.objectType = TYPE_IMAGE; + } else if (referencedObject instanceof GraphicsObject) { + this.objectType = TYPE_GRAPHIC; + } else if (referencedObject instanceof PageSegment) { + this.objectType = TYPE_PAGE_SEGMENT; + } else { + this.objectType = TYPE_OTHER; + } + } + /** + * @return the object referenced by this include object + */ + public AbstractStructuredAFPObject getReferencedObject() { + return referencedObject; } /** @@ -71,7 +135,6 @@ public class IncludeObject extends AbstractNamedAFPObject { * The orientation (0,90, 180, 270) */ public void setOrientation(int orientation) { - if (orientation == 0 || orientation == 90 || orientation == 180 || orientation == 270) { this.orientation = orientation; @@ -79,25 +142,39 @@ public class IncludeObject extends AbstractNamedAFPObject { throw new IllegalArgumentException( "The orientation must be one of the values 0, 90, 180, 270"); } - } /** - * Accessor method to write the AFP datastream for the Include Object - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * Sets the x and y offset to the origin in the object area + * @param x the X-axis origin of the object area + * @param y the Y-axis origin of the object area */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = new byte[37]; - + public void setObjectArea(int x, int y) { + this.xOffset = x; + this.yOffset = y; + } + + /** + * Sets the x and y offset of the content area to the object area + * @param x the X-axis origin defined in the object + * @param y the Y-axis origin defined in the object + */ + public void setContentArea(int x, int y) { + this.xContentOffset = x; + this.yContentOffset = y; + } + + /** + * {@inheritDoc} + */ + public void writeDataStream(OutputStream os) throws IOException { + byte[] data = new byte[36]; data[0] = 0x5A; // Set the total record length - byte[] rl1 = BinaryUtils.convert(36, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; + byte[] len = BinaryUtils.convert(35, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; // Structured field ID for a IOB data[3] = (byte) 0xD3; @@ -112,60 +189,91 @@ public class IncludeObject extends AbstractNamedAFPObject { data[9 + i] = nameBytes[i]; } - data[17] = 0x00; + data[17] = 0x00; // reserved data[18] = objectType; - // XoaOset - data[20] = (byte) 0xFF; - data[21] = (byte) 0xFF; - data[22] = (byte) 0xFF; + //XoaOset (object area) + if (xOffset > 0) { + byte[] x = BinaryUtils.convert(xOffset, 3); + data[19] = x[0]; + data[20] = x[1]; + data[21] = x[2]; + } else { + data[19] = (byte)0xFF; + data[20] = (byte)0xFF; + data[21] = (byte)0xFF; + } - // YoaOset - data[23] = (byte) 0xFF; - data[24] = (byte) 0xFF; - data[25] = (byte) 0xFF; + // YoaOset (object area) + if (yOffset > 0) { + byte[] y = BinaryUtils.convert(yOffset, 3); + data[22] = y[0]; + data[23] = y[1]; + data[24] = y[2]; + } else { + data[22] = (byte)0xFF; + data[23] = (byte)0xFF; + data[24] = (byte)0xFF; + } switch (orientation) { + case -1: // use x/y axis orientation defined in object + data[25] = (byte)0xFF; // x axis rotation + data[26] = (byte)0xFF; // + data[27] = (byte)0xFF; // y axis rotation + data[28] = (byte)0xFF; + break; case 90: - data[26] = 0x2D; - data[27] = 0x00; - data[28] = 0x5A; - data[29] = 0x00; + data[25] = 0x2D; + data[26] = 0x00; + data[27] = 0x5A; + data[28] = 0x00; break; case 180: - data[26] = 0x5A; - data[27] = 0x00; - data[28] = (byte) 0x87; - data[29] = 0x00; + data[25] = 0x5A; + data[25] = 0x00; + data[27] = (byte)0x87; + data[28] = 0x00; break; case 270: - data[26] = (byte) 0x87; + data[25] = (byte)0x87; + data[26] = 0x00; data[27] = 0x00; data[28] = 0x00; - data[29] = 0x00; break; default: + data[25] = 0x00; data[26] = 0x00; - data[27] = 0x00; - data[28] = 0x2D; - data[29] = 0x00; + data[27] = 0x2D; + data[28] = 0x00; break; } - // XocaOset - data[30] = (byte) 0xFF; - data[31] = (byte) 0xFF; - data[32] = (byte) 0xFF; - - // YocaOset - data[33] = (byte) 0xFF; - data[34] = (byte) 0xFF; - data[35] = (byte) 0xFF; + // XocaOset (object content) + if (xContentOffset > 0) { + byte[] y = BinaryUtils.convert(xContentOffset, 3); + data[29] = y[0]; + data[30] = y[1]; + data[31] = y[2]; + } else { + data[29] = (byte)0xFF; + data[30] = (byte)0xFF; + data[31] = (byte)0xFF; + } - data[36] = 0x01; + // YocaOset (object content) + if (yContentOffset > 0) { + byte[] y = BinaryUtils.convert(yContentOffset, 3); + data[32] = y[0]; + data[33] = y[1]; + data[34] = y[2]; + } else { + data[32] = (byte)0xFF; + data[33] = (byte)0xFF; + data[34] = (byte)0xFF; + } + data[35] = 0x01; os.write(data); - } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java b/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java index 7c52fe0a2..8a7d4720a 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java @@ -69,7 +69,7 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { } /** - * Sets the orienation to use for the overlay. + * Sets the orientation to use for the overlay. * * @param orientation * The orientation (0,90, 180, 270) @@ -85,15 +85,10 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { } /** - * Accessor method to write the AFP datastream for the Include Page Overlay - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - + public void writeDataStream(OutputStream os) throws IOException { byte[] data = new byte[25]; //(9 +16) - data[0] = 0x5A; // Set the total record length diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java b/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java index 7792a7162..b87222c00 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java +++ b/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java @@ -59,35 +59,29 @@ public class IncludePageSegment extends AbstractNamedAFPObject { * @param y The y position */ public IncludePageSegment(String name, int x, int y) { - super(name); this.x = BinaryUtils.convert(x, 3); this.y = BinaryUtils.convert(y, 3); - } /** - * Accessor method to write the AFP datastream for the Include Page Segment - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { + public void writeDataStream(OutputStream os) throws IOException { byte[] data = new byte[23]; //(9 +14) data[0] = 0x5A; // Set the total record length - byte[] rl1 = BinaryUtils.convert(22, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; + byte[] len = BinaryUtils.convert(22, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; // Structured field ID for a IPS data[3] = (byte) 0xD3; data[4] = (byte) 0xAF; data[5] = (byte) 0x5F; - data[6] = 0x00; // Reserved data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved @@ -95,11 +89,9 @@ public class IncludePageSegment extends AbstractNamedAFPObject { for (int i = 0; i < nameBytes.length; i++) { data[9 + i] = nameBytes[i]; } - data[17] = x[0]; // x coordinate data[18] = x[1]; data[19] = x[2]; - data[20] = y[0]; // y coordinate data[21] = y[1]; data[22] = y[2]; diff --git a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java b/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java index f38096ade..f67ee8268 100644 --- a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java +++ b/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java @@ -34,30 +34,25 @@ public class InvokeMediumMap extends AbstractNamedAFPObject { /** * Constructor for the Invoke Medium Map - * @param mediumMapName Name of the medium map + * @param name the name of the medium map */ - public InvokeMediumMap(String mediumMapName) { - - super(mediumMapName); - + public InvokeMediumMap(String name) { + super(name); } /** - * Accessor method to write the AFP datastream for the Invoke Medium Map - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { + public void writeDataStream(OutputStream os) throws IOException { byte[] data = new byte[17]; data[0] = 0x5A; // Set the total record length - byte[] rl1 = BinaryUtils.convert(16, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; + byte[] len = BinaryUtils.convert(16, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; // Structured field ID for a IPO data[3] = (byte) 0xD3; @@ -69,13 +64,8 @@ public class InvokeMediumMap extends AbstractNamedAFPObject { data[8] = 0x00; // Reserved for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java index 05d45dc2f..e83f04b78 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java +++ b/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java @@ -138,7 +138,6 @@ public class MapCodedFont extends AbstractAFPObject { baos.write(0x5D); baos.write(BinaryUtils.convert(fd.scale, 2)); } - } byte[] data = baos.toByteArray(); @@ -149,7 +148,6 @@ public class MapCodedFont extends AbstractAFPObject { data[2] = rl1[1]; os.write(data); - } /** diff --git a/src/java/org/apache/fop/render/afp/modca/MapDataResource.java b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java new file mode 100644 index 000000000..66ae57d75 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/MapDataResource.java @@ -0,0 +1,72 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Map Data Resource structured field specifies resources that are + * required for presentation. + */ +public class MapDataResource extends AbstractStructuredAFPObject { + /** + * Static default generated name reference + */ + private static final String DEFAULT_NAME = "MDR00001"; + + /** + * Main constructor + * @param obj a map data resource for a given structured AFP object + */ + public MapDataResource(AbstractStructuredAFPObject obj) { + String fqName = obj.getFullyQualifiedName(); + if (fqName != null) { + super.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, fqName); + } + } + + /** + * {@inheritDoc} + */ + public void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + // RGLength + byte[] len = BinaryUtils.convert(8 + getTripletDataLength(), 2); + byte[] data = new byte[] { + 0x5A, // Structured field identifier + len[0], // Length byte 1 + len[1], // Length byte 2 + (byte) 0xD3, // Structured field id byte 1 + (byte) 0xAB, // Structured field id byte 2 + (byte) 0xC3, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00 // Reserved + }; + os.write(data); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java b/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java index 129a3f5a1..65f90aa2b 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java +++ b/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java @@ -36,15 +36,21 @@ public class MapPageOverlay extends AbstractAFPObject { /** * The collection of overlays (maximum of 254 stored as byte[]) */ - private List overLays = new java.util.ArrayList(); + private List overLays = null; /** * Constructor for the Map Page Overlay */ public MapPageOverlay() { - } + private List getOverlays() { + if (overLays == null) { + this.overLays = new java.util.ArrayList(); + } + return this.overLays; + } + /** * Add an overlay to to the map page overlay object. * @@ -53,23 +59,19 @@ public class MapPageOverlay extends AbstractAFPObject { * @throws MaximumSizeExceededException if the maximum size is reached */ public void addOverlay(String name) throws MaximumSizeExceededException { - - if (overLays.size() > 253) { + if (getOverlays().size() > 253) { throw new MaximumSizeExceededException(); } - if (name.length() != 8) { throw new IllegalArgumentException("The name of overlay " + name + " must be 8 characters"); } - if (log.isDebugEnabled()) { log.debug("addOverlay():: adding overlay " + name); } - try { byte[] data = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - overLays.add(data); + getOverlays().add(data); } catch (UnsupportedEncodingException usee) { log.error("addOverlay():: UnsupportedEncodingException translating the name " + name); @@ -82,7 +84,7 @@ public class MapPageOverlay extends AbstractAFPObject { * @throws java.io.IOException if an I/O exception occurred */ public void writeDataStream(OutputStream os) throws IOException { - int oLayCount = overLays.size(); + int oLayCount = getOverlays().size(); int recordlength = oLayCount * 18; byte[] data = new byte[recordlength + 9]; diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java index 688288063..6ff3f03f8 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java @@ -55,7 +55,6 @@ public class ObjectAreaPosition extends AbstractAFPObject { byte[] len = BinaryUtils.convert(32, 2); byte[] xcoord = BinaryUtils.convert(x, 3); byte[] ycoord = BinaryUtils.convert(y, 3); - byte[] data = new byte[] { 0x5A, len[0], // Length @@ -91,9 +90,6 @@ public class ObjectAreaPosition extends AbstractAFPObject { 0x00, 0x00, // RefCSys }; - os.write(data); - } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java index 27fe7c270..b2108d0d7 100644 --- a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java @@ -34,7 +34,7 @@ import java.io.OutputStream; * normally contained in the object environment group, or it may specify that one or * more default values are to be used. */ -public final class ObjectEnvironmentGroup extends AbstractStructuredAFPObject { +public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject { /** * Default name for the object environment group @@ -150,7 +150,9 @@ public final class ObjectEnvironmentGroup extends AbstractStructuredAFPObject { /** * {@inheritDoc} */ - public void writeContent(OutputStream os) throws IOException { + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + objectAreaDescriptor.writeDataStream(os); objectAreaPosition.writeDataStream(os); diff --git a/src/java/org/apache/fop/render/afp/modca/Overlay.java b/src/java/org/apache/fop/render/afp/modca/Overlay.java index 628ef5516..e7d3b87d0 100644 --- a/src/java/org/apache/fop/render/afp/modca/Overlay.java +++ b/src/java/org/apache/fop/render/afp/modca/Overlay.java @@ -50,43 +50,14 @@ public class Overlay extends AbstractPageObject { */ public Overlay(String name, int width, int height, int rotation, int widthResolution, int heightResolution) { - super(name, width, height, rotation, widthResolution, heightResolution); - } /** - * Accessor method to write the AFP datastream for the overlay. - * - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - activeEnvironmentGroup.writeDataStream(os); - - writeObjectList(segments, os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the overlay. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -96,26 +67,17 @@ public class Overlay extends AbstractPageObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** - * Helper method to write the end of the overlay. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -125,15 +87,9 @@ public class Overlay extends AbstractPageObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - } diff --git a/src/java/org/apache/fop/render/afp/modca/PageGroup.java b/src/java/org/apache/fop/render/afp/modca/PageGroup.java index 0b40a83c5..39d7920e6 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/PageGroup.java @@ -18,9 +18,9 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; import java.util.List; /** @@ -34,17 +34,12 @@ import java.util.List; * * @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a> */ -public class PageGroup extends AbstractNamedAFPObject { - - /** - * The pages contained within this group - */ - private List objects = new ArrayList(); +public class PageGroup extends AbstractResourceEnvironmentGroupContainer { /** * The tag logical elements contained within this group */ - private List tagLogicalElements = new ArrayList(); + private List tagLogicalElements = null; /** * The page state @@ -58,32 +53,16 @@ public class PageGroup extends AbstractNamedAFPObject { * the name of the page group */ public PageGroup(String name) { - super(name); - } - /** - * Adds a page object to the group. - * - * @param page - * the page object to add - */ - public void addPage(PageObject page) { - - if (!objects.contains(page)) { - objects.add(page); + private List getTagLogicalElements() { + if (tagLogicalElements == null) { + this.tagLogicalElements = new java.util.ArrayList(); } - + return this.tagLogicalElements; } - - /** - * @return the name of the page group - */ - public String getName() { - return name; - } - + /** * Creates a TagLogicalElement on the page. * @@ -93,32 +72,17 @@ public class PageGroup extends AbstractNamedAFPObject { * the value of the tag */ public void createTagLogicalElement(String name, String value) { - TagLogicalElement tle = new TagLogicalElement(name, value); - tagLogicalElements.add(tle); - - } - - /** - * Creates an InvokeMediaMap on the page. - * - * @param name - * the name of the media map - */ - public void createInvokeMediumMap(String name) { - - InvokeMediumMap imm = new InvokeMediumMap(name); - objects.add(imm); - + if (!getTagLogicalElements().contains(tle)) { + getTagLogicalElements().add(tle); + } } /** * Method to mark the end of the page group. */ - public void endPageGroup() { - + protected void endPageGroup() { complete = true; - } /** @@ -129,33 +93,19 @@ public class PageGroup extends AbstractNamedAFPObject { return complete; } - /** - * Accessor method to write the AFP datastream for the page group. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + /** + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - + protected void writeContent(OutputStream os) throws IOException { + writeObjects(tagLogicalElements, os); + super.writeContent(os); } /** - * Helper method to write the start of the page group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -165,26 +115,17 @@ public class PageGroup extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** - * Helper method to write the end of the page group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -194,15 +135,9 @@ public class PageGroup extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java index a9a4581e7..bad80bcc1 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java @@ -18,11 +18,10 @@ /* $Id$ */ package org.apache.fop.render.afp.modca; + import java.io.IOException; import java.io.OutputStream; - - /** * Pages contain the data objects that comprise a presentation document. Each * page has a set of data objects associated with it. Each page within a @@ -46,11 +45,6 @@ import java.io.OutputStream; public class PageObject extends AbstractPageObject { /** - * The resource group object - */ - private ResourceGroup resourceGroup = null; - - /** * Construct a new page object for the specified name argument, the page * name should be an 8 character identifier. * @@ -69,20 +63,7 @@ public class PageObject extends AbstractPageObject { */ public PageObject(String name, int width, int height, int rotation, int widthRes, int heightRes) { - super(name, width, height, rotation, widthRes, heightRes); - - } - - /** - * Adds an overlay to the page resources - * @param overlay the overlay to add - */ - public void addOverlay(Overlay overlay) { - if (resourceGroup == null) { - resourceGroup = new ResourceGroup(); - } - resourceGroup.addOverlay(overlay); } /** @@ -98,47 +79,14 @@ public class PageObject extends AbstractPageObject { * the orientation required for the overlay */ public void createIncludePageOverlay(String name, int x, int y, int orientation) { - - IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation); - objects.add(ipo); - + addObject(new IncludePageOverlay(name, x, y, orientation)); } /** - * Accessor method to write the AFP datastream for the page. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred + * {@inheritDoc} */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - if (resourceGroup != null) { - resourceGroup.writeDataStream(os); - } - - activeEnvironmentGroup.writeDataStream(os); - - writeObjectList(segments, os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the page. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -148,26 +96,17 @@ public class PageObject extends AbstractPageObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** - * Helper method to write the end of the page. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -177,15 +116,9 @@ public class PageObject extends AbstractPageObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageSegment.java b/src/java/org/apache/fop/render/afp/modca/PageSegment.java new file mode 100644 index 000000000..f88e3cc55 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/PageSegment.java @@ -0,0 +1,102 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +/** + * A page segment is a MO:DCA-P resource object. It may be stored in an + * external resource library or it may be carried in a resource group. + * Page segments contain any combination of IOCA image objects and + * GOCA graphics objects. + */ +public class PageSegment extends AbstractNamedAFPObject { + + private List objects = null; + + /** + * Main constructor + * @param name the name of this object + */ + public PageSegment(String name) { + super(name); + } + + /** + * Adds a resource object (image/graphic) to this page segment + * @param object the resource objec to add to this page segment + */ + public void addObject(AbstractAFPObject object) { + if (objects == null) { + objects = new java.util.ArrayList(); + } + objects.add(object); + } + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + data[0] = 0x5A; // Structured field identifier + data[1] = 0x00; // Length byte 1 + data[2] = 0x10; // Length byte 2 + data[3] = (byte) 0xD3; // Structured field id byte 1 + data[4] = (byte) 0xA8; // Structured field id byte 2 + data[5] = (byte) 0x5F; // Structured field id byte 3 + data[6] = 0x00; // Flags + data[7] = 0x00; // Reserved + data[8] = 0x00; // Reserved + for (int i = 0; i < nameBytes.length; i++) { + data[9 + i] = nameBytes[i]; + } + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + data[0] = 0x5A; // Structured field identifier + data[1] = 0x00; // Length byte 1 + data[2] = 0x10; // Length byte 2 + data[3] = (byte) 0xD3; // Structured field id byte 1 + data[4] = (byte) 0xA9; // Structured field id byte 2 + data[5] = (byte) 0x5F; // Structured field id byte 3 + data[6] = 0x00; // Flags + data[7] = 0x00; // Reserved + data[8] = 0x00; // Reserved + for (int i = 0; i < nameBytes.length; i++) { + data[9 + i] = nameBytes[i]; + } + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + writeObjects(objects, os); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java b/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java new file mode 100644 index 000000000..33e6407ee --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/PreprocessPresentationObject.java @@ -0,0 +1,153 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Preprocess Presentation Object structured field specifies presentation + * parameters for a data object that has been mapped as a resource. + */ +public class PreprocessPresentationObject extends AbstractStructuredAFPObject { + private static final byte TYPE_OTHER = (byte)0x92; + private static final byte TYPE_OVERLAY = (byte)0xDF; + private static final byte TYPE_IMAGE = (byte)0xFB; + + private byte objType = TYPE_OTHER; + private byte objOrent = 0; // object always processed at 0 degree orientation + private int objXOffset = -1; + private int objYOffset = -1; + + /** + * Main constructor + * @param prePresObj the presentation object to be preprocessed + */ + public PreprocessPresentationObject(AbstractStructuredAFPObject prePresObj) { + if (prePresObj instanceof ImageObject || prePresObj instanceof Overlay) { + if (prePresObj instanceof ImageObject) { + this.objType = TYPE_IMAGE; + } else { + this.objType = TYPE_OVERLAY; + } + setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + prePresObj.getFullyQualifiedName()); + } else { + this.objType = TYPE_OTHER; +// Registry registry = Registry.getInstance(); +// Registry.Entry entry = registry.getEntry(compontentId); +// entry. +// setObjectClassification(objectClass, componentId) + } + } + + public static final byte ORIENTATION_ZERO_DEGREES = 1; + public static final byte ORIENTATION_90_DEGREES = 2; + public static final byte ORIENTATION_180_DEGREES = 4; + public static final byte ORIENTATION_270_DEGREES = 8; + + /** + * Sets the object orientations relative to media leading edge + * @param orientation the object orientations relative to media leading edge + */ + public void setOrientation(byte orientation) { + objOrent = (byte)orientation; + } + + /** + * Sets the X axis origin for object content + * @param xOffset the X axis origin for object content + */ + public void setXOffset(int xOffset) { + this.objXOffset = xOffset; + } + + /** + * Sets the Y axis origin for object content + * @param yOffset the Y axis origin for object content + */ + public void setYOffset(int yOffset) { + this.objYOffset = yOffset; + } + + /** + * {@inheritDoc} + */ + public void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + byte[] l = BinaryUtils.convert(19 + getTripletDataLength(), 2); + byte[] data = new byte[9]; + data[0] = 0x5A; // Structured field identifier + data[1] = l[0]; // Length byte 1 + data[2] = l[1]; // Length byte 1 + data[3] = (byte)0xD3; // Structured field id byte 1 + data[4] = (byte)0xAD; // Structured field id byte 2 + data[5] = (byte)0xC3; // Structured field id byte 3 + data[6] = 0x00; // Flags + data[7] = 0x00; // Reserved + data[8] = 0x00; // Reserved + + os.write(data); + } + + /** + * {@inheritDoc} + */ + public void writeContent(OutputStream os) throws IOException { + byte[] data = new byte[12]; + byte[] l = BinaryUtils.convert(12 + getTripletDataLength(), 2); + data[0] = l[0]; // RGLength + data[1] = l[1]; // RGLength + data[2] = objType; // ObjType + data[3] = 0x00; // Reserved + data[4] = 0x00; // Reserved + data[5] = objOrent; // ObjOrent + if (objXOffset > 0) { + byte[] xOff = BinaryUtils.convert(objYOffset, 3); + data[6] = xOff[0]; // XocaOset (not specified) + data[7] = xOff[1]; // XocaOset + data[8] = xOff[2]; // XocaOset + } else { + data[6] = (byte)0xFF; // XocaOset (not specified) + data[7] = (byte)0xFF; // XocaOset + data[8] = (byte)0xFF; // XocaOset + } + if (objYOffset > 0) { + byte[] yOff = BinaryUtils.convert(objYOffset, 3); + data[9] = yOff[0]; // YocaOset (not specified) + data[10] = yOff[1]; // YocaOset + data[11] = yOff[2]; // YocaOset + } else { + data[9] = (byte)0xFF; // YocaOset (not specified) + data[10] = (byte)0xFF; // YocaOset + data[11] = (byte)0xFF; // YocaOset + } + os.write(data); + + // Triplets + super.writeContent(os); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java index 901f24bb1..49f7c81a8 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java +++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java @@ -22,7 +22,7 @@ package org.apache.fop.render.afp.modca; import java.awt.Color; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; +import java.util.List; /** * The Presentation Text object is the data object used in document processing @@ -47,17 +47,15 @@ public class PresentationTextObject extends AbstractNamedAFPObject { */ private static final String DEFAULT_NAME = "PTO00001"; - private PresentationTextData currentPresentationTextData = null; + private PresentationTextData currentPresentationTextData; - private ArrayList presentationTextData = new ArrayList(); + private List presentationTextData; /** * Default constructor for the PresentationTextObject */ public PresentationTextObject() { - this(DEFAULT_NAME); - } /** @@ -66,15 +64,13 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @param name the name of this presentation object */ public PresentationTextObject(String name) { - super(name); - } /** * Create the presentation text data for the byte array of data. * - * @param fontNumber + * @param fontNum * The font resource identifier. * @param x * The x coordinate for the text data. @@ -89,18 +85,16 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @param data * The text data to be created. */ - public void createTextData(int fontNumber, int x, int y, Color col, + public void createTextData(int fontNum, int x, int y, Color col, int vsci, int ica, byte[] data) { - // Use a default orientation of zero - createTextData(fontNumber, x, y, 0, col, vsci, ica, data); - + createTextData(fontNum, x, y, 0, col, vsci, ica, data); } /** * Create the presentation text data for the byte array of data. * - * @param fontReference + * @param fontRef * The font resource identifier. * @param x * The x coordinate for the text data. @@ -117,25 +111,19 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @param data * The text data to be created. */ - public void createTextData(int fontReference, int x, int y, int orientation, + public void createTextData(int fontRef, int x, int y, int orientation, Color col, int vsci, int ica, byte[] data) { - if (currentPresentationTextData == null) { startPresentationTextData(); } - try { - currentPresentationTextData.createTextData(fontReference, x, y, + currentPresentationTextData.createTextData(fontRef, x, y, orientation, col, vsci, ica, data); - } catch (MaximumSizeExceededException msee) { - endPresentationTextData(); - createTextData(fontReference, x, y, orientation, col, vsci, ica, data); - + createTextData(fontRef, x, y, orientation, col, vsci, ica, data); } - } /** @@ -180,47 +168,38 @@ public class PresentationTextObject extends AbstractNamedAFPObject { */ public void createLineData(int x1, int y1, int x2, int y2, int thickness, int orientation, Color col) { - if (currentPresentationTextData == null) { startPresentationTextData(); } - try { - currentPresentationTextData.createLineData(x1, y1, x2, y2, thickness, orientation, col); - } catch (MaximumSizeExceededException msee) { - endPresentationTextData(); createLineData(x1, y1, x2, y2, thickness, orientation, col); - } - } /** * Helper method to mark the start of the presentation text data */ private void startPresentationTextData() { - + if (presentationTextData == null) { + presentationTextData = new java.util.ArrayList(); + } if (presentationTextData.size() == 0) { currentPresentationTextData = new PresentationTextData(true); } else { currentPresentationTextData = new PresentationTextData(); } - presentationTextData.add(currentPresentationTextData); - } /** * Helper method to mark the end of the presentation text data */ private void endPresentationTextData() { - currentPresentationTextData = null; - } /** @@ -228,15 +207,10 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @param os The stream to write to * @throws java.io.IOException thrown if an I/O exception of some sort has occurred */ - public void writeDataStream(OutputStream os) - throws IOException { - + public void writeDataStream(OutputStream os) throws IOException { writeStart(os); - - writeObjectList(presentationTextData, os); - + writeObjects(presentationTextData, os); writeEnd(os); - } /** @@ -244,20 +218,14 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * @return the name of this presentation text object */ public String getName() { - return name; - } /** - * Helper method to write the start of the presenation text object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { - + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -267,27 +235,17 @@ public class PresentationTextObject extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** - * Helper method to write the end of the presenation text object. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -297,15 +255,10 @@ public class PresentationTextObject extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** @@ -316,22 +269,14 @@ public class PresentationTextObject extends AbstractNamedAFPObject { * method terminates the control sequence. */ public void endControlSequence() { - if (currentPresentationTextData == null) { startPresentationTextData(); } - try { - currentPresentationTextData.endControlSequence(); - } catch (MaximumSizeExceededException msee) { - endPresentationTextData(); endControlSequence(); - } - } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/Registry.java b/src/java/org/apache/fop/render/afp/modca/Registry.java new file mode 100644 index 000000000..b643cd2d2 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/Registry.java @@ -0,0 +1,353 @@ +/* + * 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.modca; + +import java.io.UnsupportedEncodingException; + +import org.apache.commons.logging.LogFactory; + +/** + * MOD:CA object type registry + */ +public final class Registry { + + /** IOB supported object types */ + public static final byte IOCA_FS10 = 5; + public static final byte IOCA_FS11 = 11; + public static final byte IOCA_FS45 = 12; + public static final byte DIB_WIN = 17; //device independent bitmap + public static final byte DIB_OS2 = 18; + public static final byte PCX = 19; + public static final byte GIF = 22; + public static final byte JFIF = 23; // jpeg file interchange format + public static final byte PDF_SINGLE_PAGE = 25; + public static final byte PCL_PAGE_OBJECT = 34; + public static final byte EPS_TRANS = 48; + public static final byte PDF_SINGLE_PAGE_TRANS = 49; + public static final byte JPEG2000 = 58; + + /** IOB unsupported object types */ + public static final byte EPS = 13; + public static final byte TIFF = 14; + public static final byte COM_SETUP_FILE = 15; + public static final byte TAPE_LABEL_SETUP_FILE = 16; + public static final byte CMT = 20; // color mapping table + public static final byte ANACOMP_CONTROL_RECORD = 24; + public static final byte PDF_RESOURCE_OBJECT = 26; + public static final byte IOCA_FS42 = 45; + public static final byte RESIDENT_COLOR_PROFILE = 46; + public static final byte IOCA_FS45_TILE_RESOURCE = 47; + public static final byte FONT = 51; + public static final byte FONT_COLLECTION = 53; + public static final byte RESOURCE_ACCESS_TABLE = 54; + public static final byte IOCA_FS40 = 55; + public static final byte UP3I_PRINT_DATA = 56; + public static final byte COLOR_MANAGEMENT_RESOURCE = 57; + + + /** internal mapping array references */ + private static final int COMPONENT_ID = 0; + private static final int OBJECT_TYPE_NAME = 1; + private static final int OBJECT_ID = 2; + private static final int CAN_BE_INCLUDED = 3; + + private byte[][][] componentIdMap; + + private static Registry instance = null; + + /** + * @return a single instance of Registry + */ + public static Registry getInstance() { + synchronized (instance) { + if (instance == null) { + instance = new Registry(); + } + } + return instance; + } + + private Registry() { + init(); + } + + private void init() { + try { + componentIdMap = new byte[][][] { + /* object type id (OID), object type name, compontent Id, can be included with IOB?, */ + { + {IOCA_FS10}, + "IOCA FS10".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x05}, + {1} + }, + { + {IOCA_FS11}, + "IOCA FS11".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0B}, + {1} + }, + { + {IOCA_FS45}, + "IOCA FS45".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0C}, + {1} + }, + { + {EPS}, + "Encapsulated Postscript".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, + {0} + }, + { + {TIFF}, + "TIFF".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, + {0} + }, + { + {COM_SETUP_FILE}, + "COM setup".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0F}, + {0} + }, + { + {TAPE_LABEL_SETUP_FILE}, + "Tape Label setup".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x10}, + {0} + }, + { + {DIB_WIN}, + "DIB, Windows Version".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x11}, + {1} + }, + { + {DIB_OS2}, + "DIB, OS/2 PM Version".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x12}, + {1} + }, + { + {PCX}, + "PCX".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x13}, + {1} + }, + { + {CMT}, + "Color Mapping Table (CMT)".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x14}, + {0} + }, + { + {GIF}, + "GIF".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, + {1} + }, + { + {JFIF}, + "JFIF".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, + {1} + }, + { + {ANACOMP_CONTROL_RECORD}, + "AnaStak Control Record".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x18}, + {0} + }, + { + {PDF_SINGLE_PAGE}, + "PDF Single-page Object".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, + {1} + }, + { + {PDF_RESOURCE_OBJECT}, + "PDF Resource Object".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x1A}, + {0} + }, + { + {PCL_PAGE_OBJECT}, + "PCL Page Object".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, + {1} + }, + { + {IOCA_FS42}, + "IOCA FS42".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2D}, + {0} + }, + { + {RESIDENT_COLOR_PROFILE}, + "Resident Color Profile".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2E}, + {0} + }, + { + {IOCA_FS45_TILE_RESOURCE}, + "IOCA FS45".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x2E}, + {0} + }, + { + {EPS_TRANS}, + "EPS with Transparency".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x30}, + {1} + }, + { + {PDF_SINGLE_PAGE_TRANS}, + "PDF with Transparency".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x31}, + {1} + }, + { + {FONT}, + "TrueType/OpenType Font".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x33}, + {0} + }, + { + {FONT_COLLECTION}, + "TrueType/OpenType Font Collection".getBytes( + AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x35}, + {0} + }, + { + {RESOURCE_ACCESS_TABLE}, + "Resource Access Table".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x36}, + {0} + }, + { + {IOCA_FS40}, + "IOCA FS40".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x37}, + {0} + }, + { + {UP3I_PRINT_DATA}, + "IP3i Print Data".getBytes(AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x38}, + {0} + }, + { + {COLOR_MANAGEMENT_RESOURCE}, + "Color Management Resource (CMR)".getBytes( + AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x39}, + {0} + }, + { + {JPEG2000}, + "JPEG2000 (JP2) File Format".getBytes( + AFPConstants.EBCIDIC_ENCODING), + {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x3A}, + {1} + } + }; + } catch (UnsupportedEncodingException e) { + // should never happen! + LogFactory.getLog("org.apache.fop.render.afp.modca.Registry").error(e.getMessage()); + } + } + + private byte[][][] getComponentIdMap() { + if (componentIdMap == null) { + init(); + } + return componentIdMap; + } + + private byte[][] getMapData(byte compontentId) { + getComponentIdMap(); + for (int i = 0; i < componentIdMap.length; i++) { + if (compontentId == componentIdMap[i][0][0]) { + return componentIdMap[i]; + } + } + return null; + } + + /** + * Returns a registry Entry for a given componentId + * @param compontentId a compontent id + * @return the registry entry for a give componentId + */ + public Entry getEntry(byte compontentId) { + byte[][] data = getMapData(compontentId); + if (data != null) { + return new Registry.Entry(data); + } + return null; + } + + /** + * Encapsulates a MOD:CA Registry Entry + */ + public final class Entry { + private byte[][] data; + + /** + * Main constructor + * @param the map data structure array + */ + private Entry(byte[][] data) { + this.data = data; + } + + /** + * Returns a MOD:CA object type OID from a given a componentId + * @return the corresponding object type id for a given component id + * or null if the component id is unknown and the object type OID was not found. + */ + public byte[] getOID() { + return data[OBJECT_ID]; + } + + /** + * @return the object type name for the given componentId + */ + public byte[] getObjectTypeName() { + return data[OBJECT_TYPE_NAME]; + } + + /** + * @return the compontentId for this entry + */ + public byte[] getComponentId() { + return data[COMPONENT_ID]; + } + + /** + * @return true if this component can be included with an IOB structured field + */ + public boolean canBeIncluded() { + return data[CAN_BE_INCLUDED][0] == 1; + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java new file mode 100644 index 000000000..080226e9f --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/ResourceEnvironmentGroup.java @@ -0,0 +1,158 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +/** + * A Resource Environment Group contains a set of resources for a document + * or for a group of pages in a document. + */ +public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup { + /** + * Default name for the resource group + */ + private static final String DEFAULT_NAME = "REG00001"; + + /** + * The maps data resources contained in this resource environment group + */ + private List mapDataResources = null; + + /** + * The maps page overlays contained in this resource environment group + */ + private List mapPageOverlays = null; + + /** + * The pre-process presentation objects contained in this resource environment group + */ + private List preProcessPresentationObjects = null; + + /** + * The resource environment group state + */ + private boolean complete = false; + + /** + * Default constructor + */ + public ResourceEnvironmentGroup() { + this(DEFAULT_NAME); + } + + private List getMapDataResources() { + if (mapDataResources == null) { + this.mapDataResources = new java.util.ArrayList(); + } + return this.mapDataResources; + } + + private List getMapPageOverlays() { + if (mapPageOverlays == null) { + this.mapPageOverlays = new java.util.ArrayList(); + } + return this.mapPageOverlays; + } + + private List getPreprocessPresentationObjects() { + if (preProcessPresentationObjects == null) { + this.preProcessPresentationObjects = new java.util.ArrayList(); + } + return this.preProcessPresentationObjects; + } + + /** + * Constructor for the ResourceEnvironmentGroup, this takes a + * name parameter which must be 8 characters long. + * @param name the resource environment group name + */ + public ResourceEnvironmentGroup(String name) { + super(name); + } + + /** + * Adds an AFP object mapping reference to this resource environment group + * @param obj the object to add + */ + public void addObject(AbstractStructuredAFPObject obj) { + getMapDataResources().add(new MapDataResource(obj)); + getPreprocessPresentationObjects().add(new PreprocessPresentationObject(obj)); + } + + /** + * Returns an indication if the resource environment group is complete + * @return whether or not this resource environment group is complete or not + */ + public boolean isComplete() { + return complete; + } + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + data[0] = 0x5A; // Structured field identifier + data[1] = 0x00; // Length byte 1 + data[2] = 0x10; // Length byte 2 + data[3] = (byte) 0xD3; // Structured field id byte 1 + data[4] = (byte) 0xA8; // Structured field id byte 2 + data[5] = (byte) 0xD9; // Structured field id byte 3 + data[6] = 0x00; // Flags + data[7] = 0x00; // Reserved + data[8] = 0x00; // Reserved + for (int i = 0; i < nameBytes.length; i++) { + data[9 + i] = nameBytes[i]; + } + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + writeObjects(mapDataResources, os); + writeObjects(mapPageOverlays, os); + writeObjects(preProcessPresentationObjects, os); + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + data[0] = 0x5A; // Structured field identifier + data[1] = 0x00; // Length byte 1 + data[2] = 0x10; // Length byte 2 + data[3] = (byte) 0xD3; // Structured field id byte 1 + data[4] = (byte) 0xA9; // Structured field id byte 2 + data[5] = (byte) 0xD9; // Structured field id byte 3 + data[6] = 0x00; // Flags + data[7] = 0x00; // Reserved + data[8] = 0x00; // Reserved + for (int i = 0; i < nameBytes.length; i++) { + data[9 + i] = nameBytes[i]; + } + os.write(data); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java index 07043dcf1..48f4f0eeb 100644 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java @@ -21,32 +21,34 @@ package org.apache.fop.render.afp.modca; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; +import java.util.Map; + +import org.apache.fop.render.afp.DataObjectParameters; +import org.apache.fop.render.afp.ImageObjectParameters; +import org.apache.fop.render.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.render.afp.tools.StringUtils; +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; /** * A Resource Group contains a set of overlays. */ public final class ResourceGroup extends AbstractNamedAFPObject { - + /** * Default name for the resource group */ private static final String DEFAULT_NAME = "RG000001"; - /** - * The overlays contained in this resource group + * Mapping of resource uri to data resource object (image/graphic) */ - private List overlays = new ArrayList(); + private Map/*<String,AbstractAFPObject>*/ resourceMap = null; /** * Default constructor */ public ResourceGroup() { - this(DEFAULT_NAME); - } /** @@ -55,53 +57,208 @@ public final class ResourceGroup extends AbstractNamedAFPObject { * @param name the resource group name */ public ResourceGroup(String name) { - super(name); - } + private static final String IMAGE_NAME_PREFIX = "IMG"; + private static final String GRAPHIC_NAME_PREFIX = "GRA"; + private static final String PAGE_SEGMENT_NAME_PREFIX = "PAG"; + private static final String BARCODE_NAME_PREFIX = "BAR"; + private static final String OTHER_NAME_PREFIX = "OTH"; + /** - * Adds an overlay to the resource group - * @param overlay the overlay to add + * Converts a byte array containing 24 bit RGB image data to a grayscale + * image. + * + * @param io + * the target image object + * @param raw + * the buffer containing the RGB image data + * @param width + * the width of the image in pixels + * @param height + * the height of the image in pixels + * @param bitsPerPixel + * the number of bits to use per pixel */ - public void addOverlay(Overlay overlay) { - overlays.add(overlay); + private static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, + int height, int bitsPerPixel) { + int pixelsPerByte = 8 / bitsPerPixel; + int bytewidth = (width / pixelsPerByte); + if ((width % pixelsPerByte) != 0) { + bytewidth++; + } + byte[] bw = new byte[height * bytewidth]; + byte ib; + for (int y = 0; y < height; y++) { + ib = 0; + int i = 3 * y * width; + for (int x = 0; x < width; x++, i += 3) { + + // see http://www.jguru.com/faq/view.jsp?EID=221919 + double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d + * ((int) raw[i + 1] & 0xff) + 0.072169d + * ((int) raw[i + 2] & 0xff); + switch (bitsPerPixel) { + case 1: + if (greyVal < 128) { + ib |= (byte) (1 << (7 - (x % 8))); + } + break; + case 4: + greyVal /= 16; + ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4)); + break; + case 8: + ib = (byte) greyVal; + break; + default: + throw new UnsupportedOperationException( + "Unsupported bits per pixel: " + bitsPerPixel); + } + + if ((x % pixelsPerByte) == (pixelsPerByte - 1) + || ((x + 1) == width)) { + bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; + ib = 0; + } + } + } + io.setImageIDESize((byte) bitsPerPixel); + io.setImageData(bw); } /** - * Returns the list of overlays - * @return the list of overlays + * Helper method to create an image on the current container and to return + * the object. + * @param params the set of image object parameters + * @return a newly created image object */ - public List getOverlays() { - return overlays; + private ImageObject createImage(ImageObjectParameters params) { + String name = IMAGE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + ImageObject imageObj = new ImageObject(name); + if (params.hasCompression()) { + int compression = params.getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MH); + break; + case TIFFImage.COMP_FAX_G3_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MR); + break; + case TIFFImage.COMP_FAX_G4_2D: + imageObj.setImageEncoding(ImageContent.COMPID_G3_MMR); + break; + default: + throw new IllegalStateException( + "Invalid compression scheme: " + compression); + } + } + imageObj.setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_URL, params.getUri()); + imageObj.setImageParameters(params.getWidthRes(), params.getHeightRes(), + params.getImageDataWidth(), params.getImageDataHeight()); + if (params.isColor()) { + imageObj.setImageIDESize((byte)24); + imageObj.setImageData(params.getData()); + } else { + convertToGrayScaleImage(imageObj, params.getData(), + params.getImageDataWidth(), params.getImageDataHeight(), + params.getBitsPerPixel()); + } + return imageObj; } - + /** - * Accessor method to obtain write the AFP datastream for - * the resource group. - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception of some sort has occurred + * Helper method to create a graphic in the current container and to return + * the object. + * @param params the data object parameters + * @return a newly created graphics object */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(overlays, os); - - writeEnd(os); + private GraphicsObject createGraphic(DataObjectParameters params) { + String name = GRAPHIC_NAME_PREFIX + + StringUtils.lpad(String.valueOf(getResourceCount() + 1), '0', 5); + GraphicsObject graphicsObj = new GraphicsObject(name); + return graphicsObj; + } + /** + * Adds a data object to this resource group + * @param params the data object parameters + * @return an include object reference + */ + public IncludeObject addObject(DataObjectParameters params) { + ResourceObject resourceObj = (ResourceObject)getResourceMap().get(params.getUri()); + if (resourceObj == null) { + AbstractDataObject dataObj; + if (params instanceof ImageObjectParameters) { + dataObj = createImage((ImageObjectParameters)params); + } else { + dataObj = createGraphic(params); + } + // TODO: AC - rotation? + int rotation = 0; + dataObj.setViewport(params.getX(), params.getY(), + params.getWidth(), params.getHeight(), + params.getWidthRes(), params.getHeightRes(), rotation); + + // Wrap the data object in a resource object + resourceObj = new ResourceObject(dataObj.getName(), dataObj); + getResourceMap().put(params.getUri(), resourceObj); + } + IncludeObject includeObj = new IncludeObject(resourceObj); + //includeObj.setObjectAreaSize(params.getX(), params.getY()); + return includeObj; + } + + /** + * @return the number of resources contained in this resource group + */ + public int getResourceCount() { + if (resourceMap != null) { + return resourceMap.size(); + } + return 0; + } + + /** + * Returns true if the resource exists within this resource group, + * false otherwise. + * + * @param uri the uri of the resource + * @return true if the resource exists within this resource group + */ + public boolean resourceExists(String uri) { + return getResourceMap().containsKey(uri); + } + + /** + * Returns the list of resources + * @return the list of resources + */ + public Map/*<String,AbstractAFPObject>*/ getResourceMap() { + if (resourceMap == null) { + resourceMap = new java.util.HashMap/*<String,AbstractAFPObject>*/(); + } + return resourceMap; } /** - * Helper method to write the start of the resource group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeStart(OutputStream os) - throws IOException { + public void writeContent(OutputStream os) throws IOException { + if (resourceMap != null) { + super.writeObjects(resourceMap.values(), os); + } + } + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -111,26 +268,17 @@ public final class ResourceGroup extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } /** - * Helper method to write the end of the resource group. - * @param os The stream to write to + * {@inheritDoc} */ - private void writeEnd(OutputStream os) - throws IOException { - + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - data[0] = 0x5A; // Structured field identifier data[1] = 0x00; // Length byte 1 data[2] = 0x10; // Length byte 2 @@ -140,15 +288,16 @@ public final class ResourceGroup extends AbstractNamedAFPObject { data[6] = 0x00; // Flags data[7] = 0x00; // Reserved data[8] = 0x00; // Reserved - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - os.write(data); - } - -}
\ No newline at end of file + + /** + * {@inheritDoc} + */ + public String toString() { + return this.name + " " + this.resourceMap; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceObject.java b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java new file mode 100644 index 000000000..ff660a208 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/ResourceObject.java @@ -0,0 +1,180 @@ +/* + * 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.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.render.afp.modca.triplets.Triplet; +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * This resource structured field begins an envelope that is used to carry + * resource objects in print-file-level (external) resource groups. + */ +public class ResourceObject extends AbstractPreparedAFPObject { + + /** + * Resource object types + */ + private static final byte GRAPHICS_OBJECT = 0x03; + private static final byte BARCODE_OBJECT = 0x05; + private static final byte IMAGE_OBJECT = 0x06; + private static final byte FONT_CHARACTER_SET_OBJECT = 0x40; + private static final byte CODE_PAGE_OBJECT = 0x41; + private static final byte CODED_FONT_OBJECT = 0x42; + private static final byte OBJECT_CONTAINER = (byte) 0x92; + private static final byte DOCUMENT_OBJECT = (byte) 0xA8; + private static final byte PAGE_SEGMENT_OBJECT = (byte) 0xFB; + private static final byte OVERLAY_OBJECT = (byte) 0xFC; + private static final byte PAGEDEF_OBJECT = (byte) 0xFD; + private static final byte FORMDEF_OBJECT = (byte) 0xFE; + + /** + * the resource object + */ + private AbstractNamedAFPObject resourceObj = null; + + /** + * Default constructor + * + * @param name the name of this resource (reference id) + * @param resourceObj the resource object to be added + */ + public ResourceObject(String name, AbstractNamedAFPObject resourceObj) { + super(name); + this.resourceObj = resourceObj; + byte type; + if (resourceObj instanceof ImageObject) { + type = IMAGE_OBJECT; + } else if (resourceObj instanceof GraphicsObject) { + type = GRAPHICS_OBJECT; + } else if (resourceObj instanceof Document) { + type = DOCUMENT_OBJECT; + } else if (resourceObj instanceof PageSegment) { + type = PAGE_SEGMENT_OBJECT; + } else if (resourceObj instanceof Overlay) { + type = OVERLAY_OBJECT; + } else { + throw new UnsupportedOperationException( + "Unsupported resource object type " + resourceObj); + } + setResourceObjectType(type); + } + + private void setResourceObjectType(byte type) { + getTriplets().add(new ResourceObjectTypeTriplet(type)); + } + + /** + * @return the resource object contained in this envelope + */ + public AbstractNamedAFPObject getResource() { + return this.resourceObj; + } + + /** + * {@inheritDoc} + */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + // Set the total record length + byte[] len = BinaryUtils.convert(18 + getTripletDataLength(), 2); + byte[] data = new byte[] { + 0x5A, // Structured field identifier + len[0], // Length byte 1 + len[1], // Length byte 2 + (byte)0xD3, // Structured field id byte 1 + (byte)0xA8, // Structured field id byte 2 + (byte)0xCE, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + nameBytes[0], + nameBytes[1], + nameBytes[2], + nameBytes[3], + nameBytes[4], + nameBytes[5], + nameBytes[6], + nameBytes[7], + 0x00, // Reserved + 0x00, // Reserved + }; + os.write(data); + } + + /** + * {@inheritDoc} + */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); // write triplets + if (resourceObj != null) { + resourceObj.writeDataStream(os); + } + } + + /** + * {@inheritDoc} + */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { + 0x5A, // Structured field identifier + 0x00, // Length byte 1 + 0x10, // Length byte 2 + (byte)0xD3, // Structured field id byte 1 + (byte)0xA9, // Structured field id byte 2 + (byte)0xCE, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + nameBytes[0], + nameBytes[1], + nameBytes[2], + nameBytes[3], + nameBytes[4], + nameBytes[5], + nameBytes[6], + nameBytes[7], + }; + os.write(data); + } + + private class ResourceObjectTypeTriplet extends Triplet { + + private static final byte RESOURCE_OBJECT = 0x21; + + /** + * Main constructor + * + * @param type + * the resource type + */ + public ResourceObjectTypeTriplet(byte type) { + super(RESOURCE_OBJECT, + new byte[] { + type, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } + ); + } + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java new file mode 100644 index 000000000..23c0d7e6b --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -0,0 +1,102 @@ +/* + * 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: $ */ + +/* + * 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.modca.triplets; + + +/** + * A Fully Qualified Name triplet enable the identification and referencing of + * objects using Gloabl Identifiers (GIDs). + */ +public class FullyQualifiedNameTriplet extends Triplet { + // Specifies how the GID will be used + public static final byte TYPE_REPLACE_FIRST_GID_NAME = 0x01; + public static final byte TYPE_FONT_FAMILY_NAME = 0x07; + public static final byte TYPE_FONT_TYPEFACE_NAME = 0x08; + public static final byte TYPE_MODCA_RESOURCE_HIERARCHY_REF = 0x09; + public static final byte TYPE_BEGIN_RESOURCE_GROUP_REF = 0x0A; + public static final byte TYPE_ATTRIBUTE_GID = 0x0B; + public static final byte TYPE_PROCESS_ELEMENT_GID = 0x0C; + public static final byte TYPE_BEGIN_PAGE_GROUP_REF = 0x0D; + public static final byte TYPE_MEDIA_TYPE_REF = 0x11; + public static final byte TYPE_COLOR_MANAGEMENT_RESOURCE_REF = 0x41; + public static final byte TYPE_DATA_OBJECT_FONT_BASE_FONT_ID = 0x6E; + public static final byte TYPE_DATA_OBJECT_FONT_LINKED_FONT_ID = 0x7E; + public static final byte TYPE_BEGIN_DOCUMENT_REF = (byte)0x83; + public static final byte TYPE_BEGIN_RESOURCE_OBJECT_REF = (byte)0x84; + public static final byte TYPE_CODE_PAGE_NAME_REF = (byte)0x85; + public static final byte TYPE_FONT_CHARSET_NAME_REF = (byte)0x86; + public static final byte TYPE_BEGIN_PAGE_REF = (byte)0x87; + public static final byte TYPE_BEGIN_MEDIUM_MAP_REF = (byte)0x8D; + public static final byte TYPE_CODED_FONT_NAME_REF = (byte)0x8E; + public static final byte TYPE_BEGIN_DOCUMENT_INDEX_REF = (byte)0x98; + public static final byte TYPE_BEGIN_OVERLAY_REF = (byte)0xB0; + public static final byte TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF = (byte)0xBE; + public static final byte TYPE_INDEX_ELEMENT_GID = (byte)0xCA; + public static final byte TYPE_OTHER_OBJECT_DATA_REF = (byte)0xCE; + public static final byte TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF = (byte)0xDE; + + // GID Format + public static final byte FORMAT_CHARSTR = (byte)0x00; + public static final byte FORMAT_OID = (byte)0x10; + public static final byte FORMAT_URL = (byte)0x20; + + private byte[] fqName; + + /** + * @return the actual fully qualified name of this triplet + */ + public byte[] getFullyQualifiedName() { + return fqName; + } + + /** + * Main constructor + * @param fqnType the fully qualified name type + * @param fqnFmt the fully qualified name format + * @param fqName the fully qualified name + */ + public FullyQualifiedNameTriplet(byte fqnType, byte fqnFmt, byte[] fqName) { + super(FULLY_QUALIFIED_NAME); + this.fqName = fqName; + super.data = new byte[2 + fqName.length]; + data[0] = fqnType; + data[1] = fqnFmt; + // FQName + System.arraycopy(fqName, 0, data, 2, fqName.length); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java new file mode 100644 index 000000000..e99045292 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/MeasurementUnitsTriplet.java @@ -0,0 +1,50 @@ +/* + * 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.modca.triplets; + +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Measurement Units triplet is used to specify the units of measure + * for a presentation space + */ +public class MeasurementUnitsTriplet extends Triplet { + + private static final byte TEN_INCHES = 0x00; + private static final byte TEN_CM = 0x01; + + /** + * Main constructor + */ + public MeasurementUnitsTriplet() { + super(MEASUREMENT_UNITS); + //TODO: units correct? + byte[] xUnits = BinaryUtils.convert(1, 2); + byte[] yUnits = BinaryUtils.convert(1, 2); + super.data = new byte[] { + TEN_INCHES, // XoaBase + TEN_INCHES, // YoaBase + xUnits[0], // XoaUnits (x units per unit base) + xUnits[1], + yUnits[0], // YoaUnits (y units per unit base) + yUnits[1] + }; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java new file mode 100644 index 000000000..bd026763d --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectAreaSizeTriplet.java @@ -0,0 +1,49 @@ +/* + * 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.modca.triplets; + +import org.apache.fop.render.afp.tools.BinaryUtils; + +/** + * The Object Area Size triplet is used to specify the extent of an object area + * in the X and Y directions + */ +public class ObjectAreaSizeTriplet extends Triplet { + + /** + * Main constructor + * @param x the object area extent for the X axis + * @param y the object area extent for the Y axis + */ + public ObjectAreaSizeTriplet(int x, int y) { + super(Triplet.OBJECT_AREA_SIZE); + byte[] xOASize = BinaryUtils.convert(x, 3); + byte[] yOASize = BinaryUtils.convert(y, 3); + super.data = new byte[] { + 0x02, // SizeType + xOASize[0], // XoaSize - Object area extent for X axis + xOASize[1], + xOASize[2], + yOASize[0], // YoaSize - Object area extent for Y axis + yOASize[1], + yOASize[2] + }; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java new file mode 100644 index 000000000..4d5f41359 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ObjectClassificationTriplet.java @@ -0,0 +1,70 @@ +/* + * 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.modca.triplets; + +import org.apache.fop.render.afp.modca.Registry; + +/** + * The Object Classification is used to classify and identify object data. + * The object data may or may not be defined by an IBM presentation architecture + */ +public class ObjectClassificationTriplet extends Triplet { + public static final byte CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT = 0x01; + public static final byte CLASS_TIME_VARIANT_PRESENTATION_OBJECT = 0x10; + public static final byte CLASS_EXECUTABLE_PROGRAM = 0x20; + public static final byte CLASS_SETUP_FILE = 0x30; + public static final byte CLASS_SECONDARY_RESOURCE = 0x40; + public static final byte CLASS_DATA_OBJECT_FONT = 0x41; + + /** + * Main constructor + * + * @param objectClass + * the object class type + * @param componentId + * the object componentId + */ + public ObjectClassificationTriplet(byte objectClass, byte componentId) { + super(OBJECT_CLASSIFICATION); + byte[] data = new byte[93]; + data[0] = 0x00; // reserved (must be zero) + data[1] = objectClass; // ObjClass + data[2] = 0x00; // reserved (must be zero) + data[3] = 0x00; // reserved (must be zero) + data[4] = 0x00; // StrucFlgs - Information on the structure of the object container + data[5] = 0x00; // StrucFlgs + + Registry.Entry entry = Registry.getInstance().getEntry(componentId); + + if (entry == null) { + throw new UnsupportedOperationException("unknown registry entry " + componentId); + } + // RegObjId - MOD:CA-registered ASN.1 OID for object type (8-23) + System.arraycopy(entry.getOID(), 0, data, 6, entry.getOID().length); + + // ObjTpName - name of object type (24-55) + System.arraycopy(entry.getObjectTypeName(), 0, data, 22, + entry.getObjectTypeName().length); + + // ObjLev (not specified) - Release level or version number of object type (56-63) + + // CompName (not specified) - Name of company or org that owns object definition (64-95) + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/ResourceObjectTypeTriplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/ResourceObjectTypeTriplet.java new file mode 100644 index 000000000..c157659d6 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/ResourceObjectTypeTriplet.java @@ -0,0 +1,21 @@ +/* + * 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.modca.triplets; + diff --git a/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java new file mode 100644 index 000000000..bcf6f22c3 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/modca/triplets/Triplet.java @@ -0,0 +1,158 @@ +/* + * 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.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.fop.render.afp.modca.AFPConstants; +import org.apache.fop.render.afp.modca.AbstractAFPObject; + +/** + * A simple implementation of a MOD:CA triplet + */ +public class Triplet extends AbstractAFPObject { + public static final byte CODED_GRAPHIC_CHARACTER_SET_GLOBAL_IDENTIFIER = 0x01; + public static final byte FULLY_QUALIFIED_NAME = 0x02; + public static final byte MAPPING_OPTION = 0x04; + public static final byte OBJECT_CLASSIFICATION = 0x10; + public static final byte MODCA_INTERCHANGE_SET = 0x18; + public static final byte FONT_DESCRIPTOR_SPECIFICATION = 0x1F; + public static final byte OBJECT_FUNCTION_SET_SPECIFICATION = 0x21; + public static final byte EXTENDED_RESOURCE_LOCAL_IDENTIFIER = 0x22; + public static final byte RESOURCE_LOCAL_IDENTIFIER = 0x24; + public static final byte RESOURCE_SECTION_NUMBER = 0x25; + public static final byte CHARACTER_ROTATION = 0x26; + public static final byte OBJECT_BYTE_OFFSET = 0x2D; + public static final byte ATTRIBUTE_VALUE = 0x36; + public static final byte DESCRIPTOR_POSITION = 0x43; + public static final byte MEDIA_EJECT_CONTROL = 0x45; + public static final byte PAGE_OVERLAY_CONDITIONAL_PROCESSING = 0x46; + public static final byte RESOURCE_USAGE_ATTRIBUTE = 0x47; + public static final byte MEASUREMENT_UNITS = 0x4B; + public static final byte OBJECT_AREA_SIZE = 0x4C; + public static final byte AREA_DEFINITION = 0x4D; + public static final byte COLOR_SPECIFICATION = 0x4E; + public static final byte ENCODING_SCHEME_ID = 0x50; + public static final byte MEDIUM_MAP_PAGE_NUMBER = 0x56; + public static final byte OBJECT_BYTE_EXTENT = 0x57; + public static final byte OBJECT_STRUCTURED_FIELD_OFFSET = 0x58; + public static final byte OBJECT_STRUCTURED_FIELD_EXTENT = 0x59; + public static final byte OBJECT_OFFSET = 0x5A; + public static final byte FONT_HORIZONTAL_SCALE_FACTOR = 0x5D; + public static final byte OBJECT_COUNT = 0x5E; + public static final byte OBJECT_DATE_AND_TIMESTAMP = 0x62; + public static final byte COMMENT = 0x65; + public static final byte MEDIUM_ORIENTATION = 0x68; + public static final byte RESOURCE_OBJECT_INCLUDE = 0x6C; + public static final byte PRESENTATION_SPACE_RESET_MIXING = 0x70; + public static final byte PRESENTATION_SPACE_MIXING_RULE = 0x71; + public static final byte UNIVERSAL_DATE_AND_TIMESTAMP = 0x72; + public static final byte TONER_SAVER = 0x74; + public static final byte COLOR_FIDELITY = 0x75; + public static final byte FONT_FIDELITY = 0x78; + public static final byte ATTRIBUTE_QUALIFIER = (byte)0x80; + public static final byte PAGE_POSITION_INFORMATION = (byte)0x81; + public static final byte PARAMETER_VALUE = (byte)0x82; + public static final byte PRESENTATION_CONTROL = (byte)0x83; + public static final byte FONT_RESOLUTION_AND_METRIC_TECHNOLOGY = (byte)0x84; + public static final byte FINISHING_OPERATION = (byte)0x85; + public static final byte TEXT_FIDELITY = (byte)0x86; + public static final byte MEDIA_FIDELITY = (byte)0x87; + public static final byte FINISHING_FIDELITY = (byte)0x88; + public static final byte DATA_OBJECT_FONT_DESCRIPTOR = (byte)0x8B; + public static final byte LOCALE_SELECTOR = (byte)0x8C; + public static final byte UP3I_FINISHING_OPERATION = (byte)0x8E; + public static final byte COLOR_MANAGEMENT_RESOURCE_DESCRIPTOR = (byte)0x91; + public static final byte RENDERING_INTENT = (byte)0x95; + public static final byte CMR_TAG_FIDELITY = (byte)0x96; + public static final byte DEVICE_APPEARANCE = (byte)0x97; + + /** + * the triplet identifier + */ + protected byte id; + + /** + * the triplet's data contents + */ + protected byte[] data; + + /** + * Main constructor + * @param id the triplet identifier (see static definitions above) + * @param contents the data item contained in this triplet + */ + public Triplet(byte id, byte[] contents) { + this(id); + this.data = contents; + } + + /** + * Constructor + * @param id the triplet identifier (see static definitions above) + */ + public Triplet(byte id) { + this.id = id; + } + + /** + * Constructor + * @param id the triplet identifier (see static definitions above) + * @param content the content byte data + */ + public Triplet(byte id, byte content) { + this(id, new byte[] {content}); + } + + /** + * Constructor + * @param id the triplet identifier (see static definitions above) + * @param data the data item (in String form) contained in this triplet + * @throws UnsupportedEncodingException EBCIDIC encoding is not supported + */ + public Triplet(byte id, String data) throws UnsupportedEncodingException { + this(id, data.getBytes(AFPConstants.EBCIDIC_ENCODING)); + } + + /** + * {@inheritDoc} + */ + public void writeDataStream(OutputStream os) throws IOException { + os.write((byte)data.length + 2); + os.write(id); + os.write(data); + } + + /** + * @return the triplet identifier + */ + public byte getId() { + return this.id; + } + + /** + * @return the contents of the triplet + */ + public byte[] getData() { + return this.data; + } +} diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 5b7dd840e..19f274902 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -1086,10 +1086,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** * {@inheritDoc} */ - protected void fillRect(float x, float y, float w, float h) { - if (w != 0 && h != 0) { + protected void fillRect(float x, float y, float width, float height) { + if (width > 0 && height > 0) { currentStream.add(format(x) + " " + format(y) + " " - + format(w) + " " + format(h) + " re f\n"); + + format(width) + " " + format(height) + " re f\n"); } } @@ -1684,7 +1684,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { endTextObject(); putImage(url, pos, foreignAttributes); } - + /** * Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced. * @param uri URL of the bitmap @@ -1767,6 +1767,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { this.pdfDoc.output(ostream); } catch (IOException ioe) { // ioexception will be caught later + log.error(ioe.getMessage()); } } diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java index 306cd7bda..4bbfa0c73 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java @@ -27,8 +27,6 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentAfterElement extends AbstractPSCommentElement { - protected static final String ELEMENT = "ps-comment-after"; - /** * Main constructor * @param parent node @@ -42,7 +40,7 @@ public class PSCommentAfterElement extends AbstractPSCommentElement { * @see org.apache.fop.fo.FONode#getLocalName() */ public String getLocalName() { - return ELEMENT; + return PSCommentAfter.ELEMENT; } /** diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java index 6058f355b..f05e7c7fe 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java @@ -27,8 +27,6 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; */ public class PSCommentBeforeElement extends AbstractPSCommentElement { - protected static final String ELEMENT = "ps-comment-before"; - /** * Main constructor * @param parent parent node @@ -42,7 +40,7 @@ public class PSCommentBeforeElement extends AbstractPSCommentElement { * @see org.apache.fop.fo.FONode#getLocalName() */ public String getLocalName() { - return ELEMENT; + return PSCommentBefore.ELEMENT; } /** diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java index 45ace5f80..b23ff54da 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java @@ -42,8 +42,8 @@ public class PSExtensionElementMapping extends ElementMapping { foObjs.put(PSSetupCodeElement.ELEMENT, new PSSetupCodeMaker()); foObjs.put(PSPageSetupCodeElement.ELEMENT, new PSPageSetupCodeMaker()); foObjs.put(PSSetPageDeviceElement.ELEMENT, new PSSetPageDeviceMaker()); - foObjs.put(PSCommentBeforeElement.ELEMENT, new PSCommentBeforeMaker()); - foObjs.put(PSCommentAfterElement.ELEMENT, new PSCommentAfterMaker()); + foObjs.put(PSCommentBefore.ELEMENT, new PSCommentBeforeMaker()); + foObjs.put(PSCommentAfter.ELEMENT, new PSCommentAfterMaker()); } } |