aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop
diff options
context:
space:
mode:
authorAdrian Cumiskey <acumiskey@apache.org>2007-12-12 12:24:10 +0000
committerAdrian Cumiskey <acumiskey@apache.org>2007-12-12 12:24:10 +0000
commite30bf175fe7a4caddd9379b44599b31dada3895a (patch)
tree82e26cf01a492a1db3dd2dcc708ae07c1fc3d2a4 /src/java/org/apache/fop
parent3ad1cf6d677d963b63f89a01114a4f8de176bd2b (diff)
downloadxmlgraphics-fop-e30bf175fe7a4caddd9379b44599b31dada3895a.tar.gz
xmlgraphics-fop-e30bf175fe7a4caddd9379b44599b31dada3895a.zip
* Added an SVG handler and Graphics2D implementation for AFP which injects AFP GOCA structured fields into the AFPDataStream.
* Fixed many checkstyle problems. * Updated xmlgraphics-commons-1.3svn.jar to include changes to TextHandler git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603590 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop')
-rw-r--r--src/java/org/apache/fop/render/afp/AFPGraphics2D.java501
-rw-r--r--src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.java155
-rw-r--r--src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java80
-rw-r--r--src/java/org/apache/fop/render/afp/AFPInfo.java120
-rw-r--r--src/java/org/apache/fop/render/afp/AFPPageFonts.java48
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRenderer.java1014
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java3
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java84
-rw-r--r--src/java/org/apache/fop/render/afp/AFPSVGHandler.java132
-rw-r--r--src/java/org/apache/fop/render/afp/AFPState.java238
-rw-r--r--src/java/org/apache/fop/render/afp/AFPTextElementBridge.java110
-rw-r--r--src/java/org/apache/fop/render/afp/AFPTextHandler.java106
-rw-r--r--src/java/org/apache/fop/render/afp/AFPTextPainter.java516
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AFPDataStream.java173
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java11
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java90
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java14
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java41
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java94
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java83
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java30
-rw-r--r--src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java118
-rw-r--r--src/java/org/apache/fop/render/afp/modca/GraphicsObject.java321
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageContent.java138
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java81
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageObject.java99
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageSegment.java17
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java21
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java59
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java147
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PageDescriptor.java12
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PageObject.java8
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java31
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PresentationTextData.java122
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java13
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java8
-rw-r--r--src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java4
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java95
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java126
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java56
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java82
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java66
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java179
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java147
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java41
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java81
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java85
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java57
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java50
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java42
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java53
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java55
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java41
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java86
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java54
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java106
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java92
-rw-r--r--src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java115
-rw-r--r--src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java2
-rw-r--r--src/java/org/apache/fop/render/ps/NativeTextHandler.java4
-rw-r--r--src/java/org/apache/fop/render/ps/PSTextPainter.java3
61 files changed, 5325 insertions, 1235 deletions
diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java
new file mode 100644
index 000000000..bdd33f3de
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPGraphics2D.java
@@ -0,0 +1,501 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.io.IOException;
+
+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.modca.GraphicsObject;
+import org.apache.fop.render.afp.modca.ImageObject;
+import org.apache.fop.render.afp.modca.goca.GraphicsSetLineType;
+import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
+import org.apache.xmlgraphics.java2d.GraphicContext;
+import org.apache.xmlgraphics.java2d.StrokingTextHandler;
+import org.apache.xmlgraphics.java2d.TextHandler;
+
+/**
+ * This is a concrete implementation of <tt>AbstractGraphics2D</tt> (and
+ * therefore of <tt>Graphics2D</tt>) which is able to generate GOCA byte
+ * codes.
+ *
+ * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D
+ */
+public class AFPGraphics2D extends AbstractGraphics2D {
+
+ private static final Log log = LogFactory.getLog(AFPGraphics2D.class);
+
+ private GraphicsObject graphicsObj = null;
+
+ /** Fallback text handler */
+ protected TextHandler fallbackTextHandler = new StrokingTextHandler(this);
+
+ /** Custom text handler */
+ protected TextHandler customTextHandler = null;
+
+ /** AFP info */
+ private AFPInfo afpInfo = null;
+
+ /** Current AFP state */
+ private AFPState afpState = null;
+
+ /**
+ * @param textAsShapes
+ * if true, all text is turned into shapes in the convertion. No
+ * text is output.
+ *
+ */
+ public AFPGraphics2D(boolean textAsShapes) {
+ super(textAsShapes);
+ }
+
+ /**
+ * Creates a new AbstractGraphics2D from an existing instance.
+ *
+ * @param g
+ * the AbstractGraphics2D whose properties should be copied
+ */
+ public AFPGraphics2D(AFPGraphics2D g) {
+ super(g);
+ }
+
+ /**
+ * Sets the AFPInfo
+ *
+ * @param info
+ * the AFP Info to use
+ */
+ public void setAFPInfo(AFPInfo info) {
+ this.afpInfo = info;
+ this.afpState = info.getState();
+ }
+
+ /**
+ * Gets the AFPInfo
+ *
+ * @return the AFPInfo
+ */
+ public AFPInfo getAFPInfo() {
+ return this.afpInfo;
+ }
+
+ /**
+ * Sets the GraphicContext
+ *
+ * @param gc
+ * GraphicContext to use
+ */
+ public void setGraphicContext(GraphicContext gc) {
+ this.gc = gc;
+ }
+
+ /**
+ * Apply the stroke to the AFP graphics object.
+ * This takes the java stroke and outputs the appropriate settings
+ * to the AFP graphics object so that the stroke attributes are handled.
+ *
+ * @param stroke the java stroke
+ */
+ protected void applyStroke(Stroke stroke) {
+ if (stroke instanceof BasicStroke) {
+ BasicStroke basicStroke = (BasicStroke) stroke;
+ float lineWidth = basicStroke.getLineWidth();
+ if (afpState.setLineWidth(lineWidth)) {
+ getGraphicsObject().setLineWidth(Math.round(lineWidth * 2));
+ }
+ // note: this is an approximation at best!
+ float[] dashArray = basicStroke.getDashArray();
+ if (afpState.setDashArray(dashArray)) {
+ byte type = GraphicsSetLineType.DEFAULT; // normally SOLID
+ if (dashArray != null) {
+ type = GraphicsSetLineType.DOTTED; // default to DOTTED
+ // float offset = basicStroke.getDashPhase();
+ if (dashArray.length == 2) {
+ if (dashArray[0] < dashArray[1]) {
+ type = GraphicsSetLineType.SHORT_DASHED;
+ } else if (dashArray[0] > dashArray[1]) {
+ type = GraphicsSetLineType.LONG_DASHED;
+ }
+ } else if (dashArray.length == 4) {
+ if (dashArray[0] > dashArray[1]
+ && dashArray[2] < dashArray[3]) {
+ type = GraphicsSetLineType.DASH_DOT;
+ } else if (dashArray[0] < dashArray[1]
+ && dashArray[2] < dashArray[3]) {
+ type = GraphicsSetLineType.DOUBLE_DOTTED;
+ }
+ } else if (dashArray.length == 6) {
+ if (dashArray[0] > dashArray[1]
+ && dashArray[2] < dashArray[3]
+ && dashArray[4] < dashArray[5]) {
+ type = GraphicsSetLineType.DASH_DOUBLE_DOTTED;
+ }
+ }
+ }
+ getGraphicsObject().setLineType(type);
+ }
+ } else {
+ log.warn("Unsupported Stroke: " + stroke.getClass().getName());
+ }
+ }
+
+ /**
+ * Handle the Batik drawing event
+ *
+ * @param shape
+ * the shape to draw
+ * @param fill
+ * true if the shape is to be drawn filled
+ */
+ private void doDrawing(Shape shape, boolean fill) {
+ getGraphicsObject();
+ if (!fill) {
+ graphicsObj.newSegment();
+ }
+ Color col = getColor();
+ if (afpState.setColor(col)) {
+ graphicsObj.setColor(col);
+ }
+
+ applyStroke(getStroke());
+
+ if (fill) {
+ graphicsObj.beginArea();
+ }
+ AffineTransform trans = super.getTransform();
+ PathIterator iter = shape.getPathIterator(trans);
+ double[] vals = new double[6];
+ int[] coords = null;
+ if (shape instanceof GeneralPath || shape instanceof ExtendedGeneralPath) {
+ // graphics segment opening coordinates (x,y)
+ int[] openingCoords = new int[2];
+ // current position coordinates (x,y)
+ int[] currCoords = new int[2];
+ NEXT_ITER: while (!iter.isDone()) {
+ // round the coordinate values and combine with current position
+ // coordinates
+ int type = iter.currentSegment(vals);
+ if (type == PathIterator.SEG_MOVETO) {
+ log.debug("SEG_MOVETO");
+ openingCoords[0] = currCoords[0] = (int)Math.round(vals[0]);
+ openingCoords[1] = currCoords[1] = (int)Math.round(vals[1]);
+ } else {
+ int numCoords;
+ if (type == PathIterator.SEG_LINETO) {
+ log.debug("SEG_LINETO");
+ numCoords = 2;
+ } else if (type == PathIterator.SEG_QUADTO) {
+ log.debug("SEG_QUADTO");
+ numCoords = 4;
+ } else if (type == PathIterator.SEG_CUBICTO) {
+ log.debug("SEG_CUBICTO");
+ numCoords = 6;
+ } else {
+ // close of the graphics segment
+ if (type == PathIterator.SEG_CLOSE) {
+ log.debug("SEG_CLOSE");
+ coords = new int[] {
+ coords[coords.length - 2],
+ coords[coords.length - 1],
+ openingCoords[0],
+ openingCoords[1]
+ };
+ graphicsObj.addLine(coords);
+ } else {
+ log.debug("Unrecognised path iterator type: "
+ + type);
+ }
+ iter.next();
+ continue NEXT_ITER;
+ }
+ // combine current position coordinates with new graphics
+ // segment coordinates
+ coords = new int[numCoords + 2];
+ coords[0] = currCoords[0];
+ coords[1] = currCoords[1];
+ for (int i = 0; i < numCoords; i++) {
+ coords[i + 2] = (int) Math.round(vals[i]);
+ }
+ if (type == PathIterator.SEG_LINETO) {
+ graphicsObj.addLine(coords);
+ } else if (type == PathIterator.SEG_QUADTO
+ || type == PathIterator.SEG_CUBICTO) {
+ graphicsObj.addFillet(coords);
+ }
+ // update current position coordinates
+ currCoords[0] = coords[coords.length - 2];
+ currCoords[1] = coords[coords.length - 1];
+ }
+ iter.next();
+ }
+ } else if (shape instanceof Line2D) {
+ iter.currentSegment(vals);
+ coords = new int[4];
+ coords[0] = (int) Math.round(vals[0]);
+ coords[1] = (int) Math.round(vals[1]);
+ iter.next();
+ iter.currentSegment(vals);
+ coords[2] = (int) Math.round(vals[0]);
+ coords[3] = (int) Math.round(vals[1]);
+ graphicsObj.addLine(coords);
+ } else if (shape instanceof Rectangle2D) {
+ iter.currentSegment(vals);
+ coords = new int[4];
+ coords[2] = (int) Math.round(vals[0]);
+ coords[3] = (int) Math.round(vals[1]);
+ iter.next();
+ iter.next();
+ iter.currentSegment(vals);
+ coords[0] = (int) Math.round(vals[0]);
+ coords[1] = (int) Math.round(vals[1]);
+ graphicsObj.addBox(coords);
+ } else if (shape instanceof Ellipse2D) {
+ Ellipse2D elip = (Ellipse2D) shape;
+ final double factor = afpInfo.resolution / 100f;
+ graphicsObj.setArcParams(
+ (int)Math.round(elip.getWidth() * factor),
+ (int)Math.round(elip.getHeight() * factor),
+ 0,
+ 0
+ );
+ trans.transform(
+ new double[] {elip.getCenterX(), elip.getCenterY()}, 0,
+ vals, 0, 1);
+ final int mh = 1;
+ final int mhr = 0;
+ graphicsObj.addFullArc(
+ (int)Math.round(vals[0]),
+ (int)Math.round(vals[1]),
+ mh,
+ mhr
+ );
+ } else {
+ log.error("Unrecognised shape: " + shape);
+ }
+ if (fill) {
+ graphicsObj.endArea();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void draw(Shape shape) {
+ log.debug("draw() shape=" + shape);
+ doDrawing(shape, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void fill(Shape shape) {
+ log.debug("fill() shape=" + shape);
+ doDrawing(shape, true);
+ }
+
+ /**
+ * Central handler for IOExceptions for this class.
+ *
+ * @param ioe
+ * IOException to handle
+ */
+ public void handleIOException(IOException ioe) {
+ // TODO Surely, there's a better way to do this.
+ 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) {
+ customTextHandler.drawString(s, x, y);
+ } else {
+ fallbackTextHandler.drawString(s, x, y);
+ }
+ } catch (IOException ioe) {
+ handleIOException(ioe);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return new AFPGraphicsConfiguration();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+ log.debug("copyArea() NYI: ");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Graphics create() {
+ return new AFPGraphics2D(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ log.debug("dispose() NYI: ");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ 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
+ + ", 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;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public FontMetrics getFontMetrics(Font f) {
+ log.debug("getFontMetrics() NYI: f=" + f);
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setXORMode(Color col) {
+ log.debug("setXORMode() NYI: col=" + col);
+ }
+
+ /**
+ * Sets a custom TextHandler implementation that is responsible for painting
+ * text. The default TextHandler paints all text as shapes. A custom
+ * implementation can implement text painting using text painting operators.
+ *
+ * @param handler
+ * the custom TextHandler implementation
+ */
+ public void setCustomTextHandler(TextHandler handler) {
+ this.customTextHandler = handler;
+ }
+
+ /**
+ * @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);
+ }
+ return this.graphicsObj;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.java b/src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.java
new file mode 100644
index 000000000..086308975
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPGraphicsConfiguration.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;
+
+import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.svg.GraphicsConfiguration;
+
+/**
+ * Our implementation of the class that returns information about
+ * roughly what we can handle and want to see (alpha for example).
+ */
+public class AFPGraphicsConfiguration extends GraphicsConfiguration {
+ // We use this to get a good colormodel..
+ private static final BufferedImage BI_WITH_ALPHA
+ = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+ // We use this to get a good colormodel..
+ private static final BufferedImage BI_WITHOUT_ALPHA
+ = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+
+ /**
+ * Construct a buffered image with an alpha channel, unless
+ * transparencty is OPAQUE (no alpha at all).
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param transparency the alpha value of the image
+ * @return the new buffered image
+ */
+ public BufferedImage createCompatibleImage(int width, int height,
+ int transparency) {
+ if (transparency == Transparency.OPAQUE) {
+ return new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ } else {
+ return new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+ }
+ }
+
+ /**
+ * Construct a buffered image with an alpha channel.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the new buffered image
+ */
+ public BufferedImage createCompatibleImage(int width, int height) {
+ return new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+ }
+
+ /**
+ * TODO: This should return the page bounds in Pts,
+ * I couldn't figure out how to get this for the current
+ * page from the PDFDocument (this still works for now,
+ * but it should be fixed...).
+ *
+ * @return the bounds of the PDF document page
+ */
+ public Rectangle getBounds() {
+ return null;
+ }
+
+ /**
+ * Return a good default color model for this 'device'.
+ * @return the colour model for the configuration
+ */
+ public ColorModel getColorModel() {
+ return BI_WITH_ALPHA.getColorModel();
+ }
+
+ /**
+ * Return a good color model given <tt>transparency</tt>
+ *
+ * @param transparency the alpha value for the colour model
+ * @return the colour model for the configuration
+ */
+ public ColorModel getColorModel(int transparency) {
+ if (transparency == Transparency.OPAQUE) {
+ return BI_WITHOUT_ALPHA.getColorModel();
+ } else {
+ return BI_WITH_ALPHA.getColorModel();
+ }
+ }
+
+ private static final Log log = LogFactory.getLog(AFPGraphicsConfiguration.class);
+
+ private AffineTransform defaultTransform = null;
+ private AffineTransform normalizingTransform = null;
+ private GraphicsDevice graphicsDevice = null;
+
+ /**
+ * The default transform (1:1).
+ *
+ * @return the default transform for the configuration
+ */
+ public AffineTransform getDefaultTransform() {
+ log.debug("getDefaultTransform()");
+ if (defaultTransform == null) {
+ defaultTransform = new AffineTransform();
+ }
+ return defaultTransform;
+ }
+
+ /**
+ * The normalizing transform (1:1) (since we currently
+ * render images at 72dpi, which we might want to change
+ * in the future).
+ *
+ * @return the normalizing transform for the configuration
+ */
+ public AffineTransform getNormalizingTransform() {
+ log.debug("getNormalizingTransform()");
+ if (normalizingTransform == null) {
+ normalizingTransform = new AffineTransform(2, 0, 0, 2, 0, 0);
+ }
+ return normalizingTransform;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public GraphicsDevice getDevice() {
+ log.debug("getDevice()");
+ if (graphicsDevice == null) {
+ graphicsDevice = new AFPGraphicsDevice(this);
+ }
+ return graphicsDevice;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java b/src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java
new file mode 100644
index 000000000..dd31af9f1
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPGraphicsDevice.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+
+/**
+ * This implements the GraphicsDevice interface as appropriate for
+ * an AFPGraphics2D.
+ */
+public class AFPGraphicsDevice extends GraphicsDevice {
+
+ /**
+ * The Graphics Config that created us...
+ */
+ protected GraphicsConfiguration gc;
+
+ /**
+ * Create a new AF{ graphics device.
+ *
+ * @param gc The graphics configuration we should reference
+ */
+ public AFPGraphicsDevice(AFPGraphicsConfiguration gc) {
+ this.gc = gc;
+ }
+
+ /**
+ * Return an array of our one GraphicsConfig
+ *
+ * @return an array containing the one graphics configuration
+ */
+ public GraphicsConfiguration[] getConfigurations() {
+ return new GraphicsConfiguration[] {gc};
+ }
+
+ /**
+ * Return out sole GraphicsConfig.
+ *
+ * @return the graphics configuration that created this object
+ */
+ public GraphicsConfiguration getDefaultConfiguration() {
+ return this.gc;
+ }
+
+ /**
+ * Generate an IdString..
+ *
+ * @return the ID string for this device, uses toString
+ */
+ public String getIDstring() {
+ return toString();
+ }
+
+ /**
+ * Let the caller know that we are "a printer"
+ *
+ * @return the type which is always printer
+ */
+ public int getType() {
+ return GraphicsDevice.TYPE_PRINTER;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java
new file mode 100644
index 000000000..cd291da56
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPInfo.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.render.afp;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.render.afp.modca.AFPDataStream;
+
+/**
+ * AFP information structure for drawing the XML document.
+ */
+public final class AFPInfo {
+ /** see WIDTH */
+ protected int width;
+ /** see HEIGHT */
+ protected int height;
+ /** see XPOS */
+ protected int currentXPosition;
+ /** see YPOS */
+ protected int currentYPosition;
+ /** see HANDLER_CONFIGURATION */
+ protected Configuration cfg;
+
+ /** see AFP_FONT_INFO */
+ protected FontInfo fontInfo;
+ /** See AFP_DATASTREAM */
+ protected AFPDataStream afpDataStream;
+ /** See AFP_STATE */
+ protected AFPState afpState;
+ /** see AFP_GRAYSCALE */
+ protected boolean grayscale;
+ /** see AFP_RESOLUTION */
+ protected int resolution;
+ /** see AFP_BITS_PER_PIXEL */
+ protected int bitsPerPixel;
+
+ /**
+ * Returns the width.
+ * @return the width
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the width.
+ * @param width The pageWidth to set
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * Returns the height.
+ * @return the height
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the height.
+ * @param height The height to set
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * @return Configuration the handler configuration
+ */
+ public Configuration getHandlerConfiguration() {
+ return this.cfg;
+ }
+
+ /**
+ * @return FontInfo the font info
+ */
+ public FontInfo getFontInfo() {
+ return this.fontInfo;
+ }
+
+ /**
+ * @return Map the current page fonts
+ */
+ public AFPState getState() {
+ return this.afpState;
+ }
+
+ /**
+ * @return AFPDataStream the afp datastream
+ */
+ public AFPDataStream getAFPDataStream() {
+ return this.afpDataStream;
+ }
+
+ /**
+ * @return true if supports color
+ */
+ public boolean isColorSupported() {
+ return !this.grayscale;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPPageFonts.java b/src/java/org/apache/fop/render/afp/AFPPageFonts.java
new file mode 100644
index 000000000..1ca38a58f
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPPageFonts.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.render.afp;
+
+import org.apache.fop.render.afp.fonts.AFPFont;
+
+/**
+ * Holds the current page fonts
+ */
+public class AFPPageFonts extends java.util.HashMap {
+ private static final long serialVersionUID = -4991896259427109041L;
+
+ /**
+ * Registers a font on the current page and returns font attributes
+ * @param fontName the internal font name
+ * @param font the AFPFont
+ * @param fontSize the font point size
+ * @return newly registered AFPFontAttributes
+ */
+ public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) {
+ String pageFontKey = fontName + "_" + fontSize;
+ AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey);
+ // Add to page font mapping if not already present
+ if (afpFontAttributes == null) {
+ afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize);
+ super.put(pageFontKey, afpFontAttributes);
+ afpFontAttributes.setFontReference(super.size());
+ }
+ return afpFontAttributes;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java
index 3a228e172..de414fa10 100644
--- a/src/java/org/apache/fop/render/afp/AFPRenderer.java
+++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java
@@ -124,23 +124,28 @@ import org.w3c.dom.Document;
* 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 {
/**
- * The default afp renderer output resolution
+ * 2400 dpi renderer resolution
+ */
+ protected static final int DPI_240_RESOLUTION = 240;
+
+ /**
+ * 14400 dpi renderer resolution
*/
- private static final int DEFAULT_DPI_RESOLUTION = 240;
+ protected static final int DPI_1440_RESOLUTION = 1440;
/**
* The afp factor for calculating resolutions (e.g. 72000/240 = 300)
*/
- private static final int DPI_CONVERSION_FACTOR = 72000;
+ protected static final int DPI_CONVERSION_FACTOR = 72000;
/**
* The afp data stream object responsible for generating afp data
@@ -148,46 +153,11 @@ 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 HashMap pageSegmentsMap = null;
-
- /**
- * The fonts on the current page
- */
- private HashMap 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;
+ private Map pageSegmentsMap = null;
/**
- * 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;
@@ -198,11 +168,6 @@ 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;
@@ -213,21 +178,6 @@ 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;
@@ -245,7 +195,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
/**
* The output resolution
*/
- private int resolution = DEFAULT_DPI_RESOLUTION;
+ private int resolution = DPI_240_RESOLUTION;
+
+ /** drawing state */
+ protected AFPState currentState = null;
/**
* Constructor for AFPRenderer.
@@ -256,20 +209,22 @@ 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++;
}
@@ -278,33 +233,36 @@ 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);
}
}
@@ -319,57 +277,49 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
* {@inheritDoc}
*/
public void startRenderer(OutputStream outputStream) throws IOException {
- currentPageFonts = new HashMap();
- currentColor = new Color(255, 255, 255);
- afpDataStream = new AFPDataStream();
- afpDataStream.setPortraitRotation(portraitRotation);
- afpDataStream.setLandscapeRotation(landscapeRotation);
- afpDataStream.startDocument(outputStream);
+ this.currentState = new AFPState();
+ this.afpDataStream = new AFPDataStream();
+ this.afpDataStream.setPortraitRotation(portraitRotation);
+ this.afpDataStream.setLandscapeRotation(landscapeRotation);
+ this.afpDataStream.startDocument(outputStream);
}
/**
* {@inheritDoc}
*/
public void stopRenderer() throws IOException {
- afpDataStream.endDocument();
+ this.afpDataStream.endDocument();
}
/**
* {@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.currentFontFamily = "";
- this.currentFontSize = 0;
- this.pageFontCounter = 0;
- this.currentPageFonts.clear();
- // this.lineCache = new HashSet();
+ this.currentState.reset();
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,
- getResolution(), getResolution());
+ this.resolution, this.resolution);
renderPageObjectExtensions(page);
@@ -407,12 +357,15 @@ 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) {
@@ -427,11 +380,9 @@ 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()));
@@ -442,7 +393,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
renderRegion(regionReference);
}
/*
- _afpDataStream.endOverlay();
+ * _afpDataStream.endOverlay();
*/
popViewPortPos();
}
@@ -457,18 +408,17 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
// save positions
int saveIP = currentIPPosition;
int saveBP = currentBPPosition;
- //String saveFontName = currentFontName;
+ // 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;
-
+ 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;
if (bv.getPositioning() == Block.ABSOLUTE
|| bv.getPositioning() == Block.FIXED) {
@@ -476,9 +426,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
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();
@@ -487,19 +438,21 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
ctm = tempctm.multiply(ctm);
- //Adjust for spaces (from margin or indirectly by start-indent etc.
+ // 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;
+ 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
+ // Now adjust for border/padding
currentIPPosition += borderPaddingStart;
currentBPPosition += borderPaddingBefore;
@@ -512,7 +465,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
currentIPPosition = 0;
currentBPPosition = 0;
renderBlocks(bv, children);
- //endVParea();
+ // endVParea();
popViewPortPos();
if (breakOutList != null) {
@@ -525,35 +478,35 @@ 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;
}
@@ -563,13 +516,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
*/
public void renderPage(PageViewport pageViewport) {
- // initializeRootExtensions(page);
-
- // this.currentFontFamily = "";
- this.currentFontSize = 0;
- this.pageFontCounter = 0;
- this.currentPageFonts.clear();
- // this.lineCache = new HashSet();
+ currentState.reset();
Rectangle2D bounds = pageViewport.getViewArea();
@@ -578,14 +525,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,
- getResolution(), getResolution());
+ this.resolution, this.resolution);
renderPageObjectExtensions(pageViewport);
@@ -595,16 +542,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
renderPageAreas(pageViewport.getPage());
- Iterator i = currentPageFonts.values().iterator();
- while (i.hasNext()) {
- AFPFontAttributes afpFontAttributes = (AFPFontAttributes) i.next();
-
- afpDataStream.createFont(
- (byte)afpFontAttributes.getFontReference(),
- afpFontAttributes.getFont(),
- afpFontAttributes.getPointSize());
-
- }
+ this.afpDataStream.addFontsToCurrentPage(currentState.getPageFonts());
try {
afpDataStream.endPage();
@@ -656,22 +594,12 @@ 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),
- currentColor);
+ afpDataStream.createLine(pts2units(x), pts2units(y), pts2units(x
+ + width), pts2units(y), pts2units(height), currentState.getColor());
}
/**
@@ -686,195 +614,124 @@ 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
- );
+ 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;
}
- 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;
- }
+ } 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;
- }
- } 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_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_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
- );
+ } 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_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
- );
+ 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);
}
}
/**
* {@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,
+ this.fontInfo);
+ context.setProperty(AFPRendererContextConstants.AFP_RESOLUTION,
+ new Integer(this.resolution));
+ context.setProperty(AFPRendererContextConstants.AFP_BITS_PER_PIXEL,
+ new Integer(this.bitsPerPixel));
+ context.setProperty(AFPRendererContextConstants.AFP_DATASTREAM,
+ this.afpDataStream);
+ context.setProperty(AFPRendererContextConstants.AFP_STATE,
+ this.currentState);
return context;
}
@@ -911,71 +768,65 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
renderDocument(doc, ns, pos, foreignAttributes);
} else if (MimeConstants.MIME_EPS.equals(mime)) {
log.warn("EPS images are not supported by this renderer");
- /*
- } else if (MimeConstants.MIME_JPEG.equals(mime)) {
- if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
- return;
- }
- fact.releaseImage(url, userAgent);
-
- int x = mpts2units(pos.getX() + currentIPPosition);
- int y = mpts2units(pos.getY() + currentBPPosition);
- int w = mpts2units(pos.getWidth());
- int h = mpts2units(pos.getHeight());
- ImageObject io = _afpDataStream.getImageObject();
- io.setImageViewport(x, y, w, h);
- io.setImageParameters(
- (int)(fopimage.getHorizontalResolution() * 10),
- (int)(fopimage.getVerticalResolution() * 10),
- fopimage.getWidth(),
- fopimage.getHeight()
- );
- io.setImageIDESize((byte)fopimage.getBitsPerPixel());
- io.setImageEncoding((byte)0x83);
- io.setImageData(fopimage.getRessourceBytes());
- */
+ /*
+ * } else if (MimeConstants.MIME_JPEG.equals(mime)) { if
+ * (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; }
+ * fact.releaseImage(url, userAgent);
+ *
+ * int x = mpts2units(pos.getX() + currentIPPosition); int y =
+ * mpts2units(pos.getY() + currentBPPosition); int w =
+ * mpts2units(pos.getWidth()); int h =
+ * mpts2units(pos.getHeight()); ImageObject io =
+ * _afpDataStream.getImageObject(); io.setImageViewport(x, y, w,
+ * h); io.setImageParameters(
+ * (int)(fopimage.getHorizontalResolution() * 10),
+ * (int)(fopimage.getVerticalResolution() * 10),
+ * fopimage.getWidth(), fopimage.getHeight() );
+ * io.setImageIDESize((byte)fopimage.getBitsPerPixel());
+ * io.setImageEncoding((byte)0x83);
+ * 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());
- ImageObject io = afpDataStream.getImageObject(x, y, w, h,
- getResolution(), getResolution());
+ int res = getResolution();
+ ImageObject io = afpDataStream.getImageObject(x, y, w, h, res,
+ res);
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());
+ convertToGrayScaleImage(io, fopimage.getBitmaps(),
+ fopimage.getWidth(), fopimage.getHeight(), this.bitsPerPixel);
}
} else {
if (!fopimage.load(FopImage.BITMAP)) {
return;
}
- convertToGrayScaleImage(io, fopimage.getBitmaps(),
- fopimage.getWidth(), fopimage.getHeight());
+ convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage
+ .getWidth(), fopimage.getHeight(), this.bitsPerPixel);
}
} else {
if (!fopimage.load(FopImage.BITMAP)) {
@@ -987,20 +838,19 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
int y = mpts2units(pos.getY() + currentBPPosition);
int w = mpts2units(pos.getWidth());
int h = mpts2units(pos.getHeight());
- ImageObject io = afpDataStream.getImageObject(x, y, w, h,
- getResolution(), getResolution());
+ int res = getResolution();
+ ImageObject io = afpDataStream.getImageObject(x, y, w, h, res,
+ res);
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());
+ convertToGrayScaleImage(io, fopimage.getBitmaps(), fopimage
+ .getWidth(), fopimage.getHeight(), this.bitsPerPixel);
}
}
}
@@ -1008,13 +858,18 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
/**
* Writes a BufferedImage to an OutputStream as raw sRGB bitmaps.
- * @param img the BufferedImage
- * @param out the OutputStream
- * @throws IOException In case of an I/O error.
- */
- public static void writeImage(BufferedImage img, OutputStream out) throws IOException {
- int w = img.getWidth();
- int h = img.getHeight();
+ *
+ * @param img
+ * the BufferedImage
+ * @param out
+ * the OutputStream
+ * @throws IOException
+ * In case of an I/O error.
+ */
+ public static void writeImage(BufferedImage img, OutputStream out)
+ throws IOException {
+ int w = img.getWidth();
+ int h = img.getHeight();
int[] tmpMap = img.getRGB(0, 0, w, h, null, 0, w);
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
@@ -1022,21 +877,28 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
int r = (p >> 16) & 0xFF;
int g = (p >> 8) & 0xFF;
int b = (p) & 0xFF;
- out.write((byte)(r & 0xFF));
- out.write((byte)(g & 0xFF));
- out.write((byte)(b & 0xFF));
+ out.write((byte) (r & 0xFF));
+ out.write((byte) (g & 0xFF));
+ out.write((byte) (b & 0xFF));
}
}
}
/**
* Draws a BufferedImage to AFP.
- * @param bi the BufferedImage
- * @param imageResolution the resolution of the BufferedImage
- * @param x the x coordinate (in mpt)
- * @param y the y coordinate (in mpt)
- * @param w the width of the viewport (in mpt)
- * @param h the height of the viewport (in mpt)
+ *
+ * @param bi
+ * the BufferedImage
+ * @param imageResolution
+ * the resolution of the BufferedImage
+ * @param x
+ * the x coordinate (in mpt)
+ * @param y
+ * the y coordinate (in mpt)
+ * @param w
+ * the width of the viewport (in mpt)
+ * @param h
+ * the height of the viewport (in mpt)
*/
public void drawBufferedImage(BufferedImage bi, int imageResolution, int x,
int y, int w, int h) {
@@ -1044,46 +906,46 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
int afpy = mpts2units(y);
int afpw = mpts2units(w);
int afph = mpts2units(h);
+ int afpres = getResolution();
ByteArrayOutputStream baout = new ByteArrayOutputStream();
try {
- //Serialize image
+ // Serialize image
writeImage(bi, baout);
byte[] buf = baout.toByteArray();
- //Generate image
- ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph,
- getResolution(), getResolution());
- io.setImageParameters(
- imageResolution, imageResolution,
- bi.getWidth(),
- bi.getHeight()
- );
+ // Generate image
+ ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw,
+ afph, afpres, afpres);
+ io.setImageParameters(imageResolution, imageResolution,
+ bi.getWidth(), bi.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, bi.getWidth(), bi.getHeight());
+ // TODO Teach it how to handle grayscale BufferedImages directly
+ // because this is pretty inefficient
+ convertToGrayScaleImage(io, buf, bi.getWidth(), bi.getHeight(), this.bitsPerPixel);
}
} catch (IOException ioe) {
- log.error("Error while serializing bitmap: " + ioe.getMessage(), ioe);
+ log.error("Error while serializing bitmap: " + ioe.getMessage(),
+ ioe);
}
}
/**
- * 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) {
- currentColor = col;
+ currentState.setColor(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) {
@@ -1091,6 +953,7 @@ 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() {
@@ -1131,76 +994,58 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
public void renderText(TextArea text) {
renderInlineAreaBackAndBorders(text);
- String name = getInternalFontNameForArea(text);
- currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
- AFPFont tf = (AFPFont) fontInfo.getFonts().get(name);
+ 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);
Color col = (Color) text.getTrait(Trait.COLOR);
- int vsci = mpts2units(tf.getWidth(' ', currentFontSize) / 1000
- + text.getTextWordSpaceAdjust()
- + text.getTextLetterSpaceAdjust());
+ int vsci = mpts2units(font.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();
- // 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());
- }
+ AFPPageFonts pageFonts = this.currentState.getPageFonts();
+ AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
+ internalFontName, font, currentFontSize);
// Try and get the encoding to use for the font
String encoding = null;
try {
- encoding = tf.getCharacterSet(currentFontSize).getEncoding();
+ encoding = font.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),
- mpts2units(bl),
- col,
- vsci,
- mpts2units(text.getTextLetterSpaceAdjust()),
- worddata.getBytes(encoding));
+ afpDataStream.createText(afpFontAttributes.getFontReference(),
+ mpts2units(rx), pts2units(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(tf, currentFontSize, text, bl, rx);
+ renderTextDecoration(font, currentFontSize, text, bl, rx);
}
/**
@@ -1238,88 +1083,41 @@ 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.
*
@@ -1328,14 +1126,13 @@ 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");
}
@@ -1344,20 +1141,19 @@ 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");
}
}
@@ -1365,7 +1161,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;
@@ -1375,7 +1171,8 @@ 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) {
@@ -1386,7 +1183,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();
@@ -1425,7 +1222,9 @@ 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);
@@ -1433,7 +1232,9 @@ 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);
@@ -1447,17 +1248,27 @@ 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()));
}
/**
- * 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
+ * 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
*/
- private void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, int height) {
+ protected 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) {
@@ -1469,26 +1280,26 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
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);
+ 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(
+ 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);
}
@@ -1502,7 +1313,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
io.setImageIDESize((byte) bitsPerPixel);
io.setImageData(bw);
}
-
+
private final class ViewPortPos {
private int x = 0;
@@ -1611,7 +1422,8 @@ 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);
}
}
@@ -1625,9 +1437,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.");
@@ -1647,20 +1459,36 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
}
/**
+ * Returns the AFPDataStream
+ *
+ * @return the AFPDataStream
+ */
+ public AFPDataStream getAFPDataStream() {
+ return afpDataStream;
+ }
+
+ /**
* Sets the output/device resolution
*
* @param resolution
* the output resolution (dpi)
*/
public void setResolution(int resolution) {
- if (log.isDebugEnabled()) {
- log.debug("renderer-resolution set to: " + resolution + "dpi");
+ 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");
}
- this.resolution = resolution;
}
-
+
/**
* Returns the output/device resolution.
+ *
* @return the resolution in dpi
*/
public int getResolution() {
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
index dee741ab4..c0f6a9c6f 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
@@ -239,7 +239,8 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false);
if (rendererResolutionCfg != null) {
- afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240));
+ afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(
+ AFPRenderer.DPI_240_RESOLUTION));
}
}
}
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java b/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java
index 88cb73547..a4b449bb0 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java
@@ -1,35 +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;
-
-import org.apache.fop.render.RendererContextConstants;
-
-/**
- * Defines a number of standard constants (keys) for use by the RendererContext class.
- */
-public interface AFPRendererContextConstants extends RendererContextConstants {
-
- /**
- * Key for a Boolean value that enables grayscale processing instead of color
- * processing.
- */
- String AFP_GRAYSCALE = "afpGrayscale";
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import org.apache.fop.render.RendererContextConstants;
+
+/**
+ * Defines a number of standard constants (keys) for use by the RendererContext class.
+ */
+public interface AFPRendererContextConstants extends RendererContextConstants {
+
+ /**
+ * Key for a Boolean value that enables grayscale processing instead of color
+ * processing.
+ */
+ String AFP_GRAYSCALE = "afpGrayscale";
+
+ /** The font information for the AFP renderer. */
+ String AFP_FONT_INFO = "afpFontInfo";
+
+ /** The afp resolution. */
+ String AFP_RESOLUTION = "afpResolution";
+
+ /** The afp datastream */
+ String AFP_DATASTREAM = "afpDataStream";
+
+ /** The afp state */
+ String AFP_STATE = "afpPageState";
+
+ /** The afp bits per pixel */
+ String AFP_BITS_PER_PIXEL = "afpBitsPerPixel";
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
index e216244c5..1506acb4b 100644
--- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
@@ -15,13 +15,27 @@
* limitations under the License.
*/
-/* $Id$ */
+/* $Id: $ */
package org.apache.fop.render.afp;
// FOP
+import java.awt.geom.AffineTransform;
+import java.io.IOException;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.bridge.GVTBuilder;
+import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.commons.logging.Log;
+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.afp.modca.AFPDataStream;
+import org.apache.fop.svg.SVGUserAgent;
+import org.w3c.dom.Document;
/**
* AFP XML handler for SVG. Uses Apache Batik for SVG processing.
@@ -30,10 +44,126 @@ import org.apache.fop.render.Renderer;
*/
public class AFPSVGHandler extends AbstractGenericSVGHandler {
+ /** logging instance */
+ private static Log log = LogFactory.getLog(AFPSVGHandler.class);
+
+ /** {@inheritDoc} */
+ public void handleXML(RendererContext context,
+ Document doc, String ns) throws Exception {
+ AFPInfo afpi = getAFPInfo(context);
+
+ if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) {
+ renderSVGDocument(context, doc, afpi);
+ }
+ }
+
+ /**
+ * Get the afp information from the render context.
+ *
+ * @param context the renderer context
+ * @return the afp information retrieved from the context
+ */
+ public static AFPInfo getAFPInfo(RendererContext context) {
+ AFPInfo afpi = new AFPInfo();
+ afpi.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();
+ return afpi;
+ }
+
+ /**
+ * Render the SVG document.
+ * @param context the renderer context
+ * @param doc the SVG document
+ * @param afpInfo the AFPInfo renderer parameters
+ * @throws IOException In case of an I/O error while painting the image
+ */
+ protected void renderSVGDocument(final RendererContext context,
+ final Document doc, AFPInfo afpInfo) throws IOException {
+
+ final boolean textAsShapes = false;
+ AFPGraphics2D graphics = new AFPGraphics2D(textAsShapes);
+ graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
+ graphics.setAFPInfo(afpInfo);
+
+ GVTBuilder builder = new GVTBuilder();
+
+ boolean strokeText = false;
+ Configuration cfg = afpInfo.cfg;
+ 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());
+
+ BridgeContext ctx = new BridgeContext(svgUserAgent);
+ AFPTextHandler afpTextHandler = null;
+ //Controls whether text painted by Batik is generated using text or path operations
+ if (!strokeText) {
+ afpTextHandler = new AFPTextHandler(graphics);
+ graphics.setCustomTextHandler(afpTextHandler);
+ AFPTextPainter textPainter = new AFPTextPainter(afpTextHandler);
+ ctx.setTextPainter(textPainter);
+ AFPTextElementBridge tBridge = new AFPTextElementBridge(textPainter);
+ ctx.putBridge(tBridge);
+ }
+
+ GraphicsNode root;
+ try {
+ root = builder.build(ctx, doc);
+ } catch (Exception e) {
+ log.error("SVG graphic could not be built: "
+ + e.getMessage(), e);
+ return;
+ }
+ log.debug("Generating SVG at "
+ + afpInfo.resolution + "dpi.");
+
+ int res = afpInfo.resolution;
+
+ 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;
+
+ // 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);
+ try {
+ root.paint(graphics);
+ } catch (Exception e) {
+ log.error("SVG graphic could not be rendered: " + e.getMessage(), e);
+ }
+ }
+
/** {@inheritDoc} */
public boolean supportsRenderer(Renderer renderer) {
return (renderer instanceof AFPRenderer);
}
+ /** {@inheritDoc} */
+ public String getNamespace() {
+ 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
new file mode 100644
index 000000000..a86d55cf9
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPState.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: $ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.Color;
+import java.util.Arrays;
+
+/**
+ * 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;
+
+ /**
+ * The fonts on the current page
+ */
+ private AFPPageFonts pageFonts = null;
+
+ /**
+ * Set the current color.
+ * Check if the new color is a change and then set the current color.
+ *
+ * @param col the color to set
+ * @return true if the color has changed
+ */
+ protected boolean setColor(Color col) {
+ if (!col.equals(this.color)) {
+ this.color = col;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets if the current painted shape is to be filled
+ * @param fill true if the current painted shape is to be filled
+ * @return true if the fill value has changed
+ */
+ protected boolean setFill(boolean fill) {
+ if (fill != this.filled) {
+ this.filled = fill;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the color.
+ * @return the color
+ */
+ protected Color getColor() {
+ if (this.color == null) {
+ this.color = Color.black;
+ }
+ return this.color;
+ }
+
+ /**
+ * Set the current line width.
+ * @param width the line width in points
+ * @return true if the line width has changed
+ */
+ protected boolean setLineWidth(float width) {
+ if (this.lineWidth != width) {
+ this.lineWidth = width;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the dash array (line type) for the current basic stroke
+ * @param dash the line dash array
+ * @return true if the dash array has changed
+ */
+ public boolean setDashArray(float[] dash) {
+ if (!Arrays.equals(dash, this.dashArray)) {
+ this.dashArray = dash;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the current line width
+ * @return the current line width
+ */
+ protected float getLineWidth() {
+ return lineWidth;
+ }
+
+ /**
+ * Get the background color.
+ * @return the background color
+ */
+ protected Color getBackColor() {
+ if (this.backColor == null) {
+ this.backColor = Color.white;
+ }
+ return backColor;
+ }
+
+ /**
+ * Set the current background color.
+ * Check if the new background color is a change and then set the current background color.
+ *
+ * @param col the background color to set
+ * @return true if the color has changed
+ */
+ protected boolean setBackColor(Color col) {
+ if (!col.equals(this.backColor)) {
+ this.backColor = col;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set the current font name
+ * @param internalFontName the internal font name
+ * @return true if the font name has changed
+ */
+ protected boolean setFontName(String internalFontName) {
+ if (!internalFontName.equals(this.fontName)) {
+ this.fontName = internalFontName;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the current font name
+ * @return the current font name
+ */
+ protected String getFontName() {
+ return this.fontName;
+ }
+
+ /**
+ * Gets the current font size
+ * @return the current font size
+ */
+ protected int getFontSize() {
+ return this.fontSize;
+ }
+
+ /**
+ * Set the current font size.
+ * Check if the font size is a change and then set the current font size.
+ *
+ * @param size the font size to set
+ * @return true if the font size has changed
+ */
+ protected boolean setFontSize(int size) {
+ if (size != this.fontSize) {
+ this.fontSize = size;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the current page fonts
+ * @return the current page fonts
+ */
+ protected AFPPageFonts getPageFonts() {
+ if (this.pageFonts == null) {
+ this.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();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/AFPTextElementBridge.java b/src/java/org/apache/fop/render/afp/AFPTextElementBridge.java
new file mode 100644
index 000000000..150cbb236
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPTextElementBridge.java
@@ -0,0 +1,110 @@
+/*
+ * 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: PSTextElementBridge.java 426576 2006-07-28 15:44:37Z jeremias $ */
+
+package org.apache.fop.render.afp;
+
+import org.apache.batik.bridge.SVGTextElementBridge;
+import org.apache.batik.bridge.BridgeContext;
+import org.apache.batik.gvt.GraphicsNode;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.TextPainter;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Bridge class for the &lt;text> element.
+ * This bridge will use the direct text painter if the text
+ * for the element is simple.
+ */
+public class AFPTextElementBridge extends SVGTextElementBridge {
+
+ private AFPTextPainter textPainter;
+
+ /**
+ * Constructs a new bridge for the &lt;text> element.
+ * @param textPainter the text painter to use
+ */
+ public AFPTextElementBridge(AFPTextPainter textPainter) {
+ this.textPainter = textPainter;
+ }
+
+ /**
+ * Create a text element bridge.
+ * This set the text painter on the node if the text is simple.
+ * @param ctx the bridge context
+ * @param e the svg element
+ * @return the text graphics node created by the super class
+ */
+ public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
+ GraphicsNode node = super.createGraphicsNode(ctx, e);
+ if (node != null && isSimple(ctx, e, node)) {
+ ((TextNode)node).setTextPainter(getTextPainter());
+ }
+ return node;
+ }
+
+ private TextPainter getTextPainter() {
+ return this.textPainter;
+ }
+
+ /**
+ * Check if text element contains simple text.
+ * This checks the children of the text element to determine
+ * if the text is simple. The text is simple if it can be rendered
+ * with basic text drawing algorithms. This means there are no
+ * alternate characters, the font is known and there are no effects
+ * applied to the text.
+ *
+ * @param ctx the bridge context
+ * @param element the svg text element
+ * @param node the graphics node
+ * @return true if this text is simple of false if it cannot be
+ * easily rendered using normal drawString on the PDFGraphics2D
+ */
+ private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
+ for (Node n = element.getFirstChild();
+ n != null;
+ n = n.getNextSibling()) {
+
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+
+ if (n.getLocalName().equals(SVG_TSPAN_TAG)
+ || n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
+ return false;
+ } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) {
+ return false;
+ } else if (n.getLocalName().equals(SVG_TREF_TAG)) {
+ return false;
+ }
+ break;
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ default:
+ }
+ }
+
+ /*if (CSSUtilities.convertFilter(element, node, ctx) != null) {
+ return false;
+ }*/
+
+ return true;
+ }
+}
+
diff --git a/src/java/org/apache/fop/render/afp/AFPTextHandler.java b/src/java/org/apache/fop/render/afp/AFPTextHandler.java
new file mode 100644
index 000000000..a6e8ffeb8
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPTextHandler.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.render.afp.fonts.AFPFont;
+import org.apache.fop.render.afp.modca.GraphicsObject;
+
+import org.apache.xmlgraphics.java2d.TextHandler;
+
+/**
+ * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text
+ * using AFP GOCA text operations.
+ */
+public class AFPTextHandler implements TextHandler {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(AFPTextHandler.class);
+
+ private AFPGraphics2D g2d = null;
+
+ /** Overriding FontState */
+ protected Font overrideFont = null;
+
+ /** current state */
+ private AFPState afpState = null;
+
+ /**
+ * Main constructor.
+ * @param g2d the PSGraphics2D instance this instances is used by
+ */
+ public AFPTextHandler(AFPGraphics2D g2d) {
+ this.g2d = g2d;
+ this.afpState = g2d.getAFPInfo().getState();
+ }
+
+ /**
+ * Return the font information associated with this object
+ * @return the FontInfo object
+ */
+ public FontInfo getFontInfo() {
+ return g2d.getAFPInfo().getFontInfo();
+ }
+
+ /**
+ * Add a text string to the current data object of the AFP datastream.
+ * The text is painted using text operations.
+ * {@inheritDoc}
+ */
+ public void drawString(String str, float x, float y) throws IOException {
+ log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
+ GraphicsObject graphicsObj = g2d.getGraphicsObject();
+ Color col = g2d.getColor();
+ if (afpState.setColor(col)) {
+ graphicsObj.setColor(col);
+ }
+ if (overrideFont != null) {
+ FontInfo fontInfo = getFontInfo();
+ AFPPageFonts pageFonts = this.afpState.getPageFonts();
+ String internalFontName = overrideFont.getFontName();
+ int fontSize = overrideFont.getFontSize();
+ if (afpState.setFontName(internalFontName) || afpState.setFontSize(fontSize)) {
+ AFPFont font = (AFPFont)fontInfo.getFonts().get(internalFontName);
+ AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
+ internalFontName,
+ font,
+ fontSize
+ );
+ int fontReference = afpFontAttributes.getFontReference();
+ graphicsObj.setCharacterSet(fontReference);
+ }
+ }
+ graphicsObj.addString(str, (int)Math.round(x), (int)Math.round(y));
+ }
+
+ /**
+ * Sets the overriding font.
+ * @param overrideFont Overriding Font to set
+ */
+ public void setOverrideFont(Font overrideFont) {
+ this.overrideFont = overrideFont;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/AFPTextPainter.java b/src/java/org/apache/fop/render/afp/AFPTextPainter.java
new file mode 100644
index 000000000..66183080f
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/AFPTextPainter.java
@@ -0,0 +1,516 @@
+/*
+ * 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: PSTextPainter.java 542237 2007-05-28 14:31:24Z jeremias $ */
+
+package org.apache.fop.render.afp;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.awt.font.TextAttribute;
+import java.awt.Shape;
+import java.awt.Paint;
+import java.awt.Color;
+import java.io.IOException;
+import java.util.List;
+import java.util.Iterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.batik.dom.svg.SVGOMTextElement;
+import org.apache.batik.gvt.text.Mark;
+import org.apache.batik.gvt.TextPainter;
+import org.apache.batik.gvt.TextNode;
+import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
+import org.apache.batik.gvt.text.TextPaintInfo;
+import org.apache.batik.gvt.font.GVTFontFamily;
+import org.apache.batik.gvt.renderer.StrokingTextPainter;
+
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+
+/**
+ * Renders the attributed character iterator of a <tt>TextNode</tt>.
+ * This class draws the text directly into the AFPGraphics2D so that
+ * the text is not drawn using shapes.
+ * If the text is simple enough to draw then it sets the font and calls
+ * drawString. If the text is complex or the cannot be translated
+ * into a simple drawString the StrokingTextPainter is used instead.
+ */
+public class AFPTextPainter implements TextPainter {
+
+ /** the logger for this class */
+ protected Log log = LogFactory.getLog(AFPTextPainter.class);
+
+ private AFPTextHandler nativeTextHandler;
+ //private FontInfo fontInfo;
+
+ /**
+ * Use the stroking text painter to get the bounds and shape.
+ * Also used as a fallback to draw the string with strokes.
+ */
+ protected static final TextPainter
+ PROXY_PAINTER = StrokingTextPainter.getInstance();
+
+ /**
+ * Create a new PS text painter with the given font information.
+ * @param nativeTextHandler the NativeTextHandler instance used for text painting
+ */
+ public AFPTextPainter(AFPTextHandler nativeTextHandler) {
+ this.nativeTextHandler = nativeTextHandler;
+ }
+
+ /**
+ * Paints the specified attributed character iterator using the
+ * specified Graphics2D and context and font context.
+ * @param node the TextNode to paint
+ * @param g2d the Graphics2D to use
+ */
+ public void paint(TextNode node, Graphics2D g2d) {
+ Point2D loc = node.getLocation();
+ log.debug("painting text node " + node);
+ if (hasUnsupportedAttributes(node)) {
+ log.debug("hasunsuportedattributes");
+ PROXY_PAINTER.paint(node, g2d);
+ } else {
+ log.debug("allattributessupported");
+ paintTextRuns(node.getTextRuns(), g2d, loc);
+ }
+ }
+
+ private boolean hasUnsupportedAttributes(TextNode node) {
+ Iterator iter = node.getTextRuns().iterator();
+ while (iter.hasNext()) {
+ StrokingTextPainter.TextRun
+ run = (StrokingTextPainter.TextRun)iter.next();
+ AttributedCharacterIterator aci = run.getACI();
+ boolean hasUnsupported = hasUnsupportedAttributes(aci);
+ if (hasUnsupported) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
+ boolean hasunsupported = false;
+
+ String text = getText(aci);
+ Font font = makeFont(aci);
+ if (hasUnsupportedGlyphs(text, font)) {
+ log.trace("-> Unsupported glyphs found");
+ hasunsupported = true;
+ }
+
+ TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+ if ((tpi != null)
+ && ((tpi.strokeStroke != null && tpi.strokePaint != null)
+ || (tpi.strikethroughStroke != null)
+ || (tpi.underlineStroke != null)
+ || (tpi.overlineStroke != null))) {
+ log.trace("-> under/overlines etc. found");
+ hasunsupported = true;
+ }
+
+ //Alpha is not supported
+ Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND);
+ if (foreground instanceof Color) {
+ Color col = (Color)foreground;
+ if (col.getAlpha() != 255) {
+ log.trace("-> transparency found");
+ hasunsupported = true;
+ }
+ }
+
+ Object letSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
+ if (letSpace != null) {
+ log.trace("-> letter spacing found");
+ hasunsupported = true;
+ }
+
+ Object wordSpace = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
+ if (wordSpace != null) {
+ log.trace("-> word spacing found");
+ hasunsupported = true;
+ }
+
+ Object lengthAdjust = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
+ if (lengthAdjust != null) {
+ log.trace("-> length adjustments found");
+ hasunsupported = true;
+ }
+
+ Object writeMod = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
+ if (writeMod != null
+ && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
+ writeMod)) {
+ log.trace("-> Unsupported writing modes found");
+ hasunsupported = true;
+ }
+
+ Object vertOr = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
+ if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
+ vertOr)) {
+ log.trace("-> vertical orientation found");
+ hasunsupported = true;
+ }
+
+ Object rcDel = aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
+ //Batik 1.6 returns null here which makes it impossible to determine whether this can
+ //be painted or not, i.e. fall back to stroking. :-(
+ if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
+ log.trace("-> spans found");
+ hasunsupported = true; //Filter spans
+ }
+
+ if (hasunsupported) {
+ log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
+ }
+ return hasunsupported;
+ }
+
+ /**
+ * Paint a list of text runs on the Graphics2D at a given location.
+ * @param textRuns the list of text runs
+ * @param g2d the Graphics2D to paint to
+ * @param loc the current location of the "cursor"
+ */
+ protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) {
+ Point2D currentloc = loc;
+ Iterator i = textRuns.iterator();
+ while (i.hasNext()) {
+ StrokingTextPainter.TextRun
+ run = (StrokingTextPainter.TextRun)i.next();
+ currentloc = paintTextRun(run, g2d, currentloc);
+ }
+ }
+
+ /**
+ * Paint a single text run on the Graphics2D at a given location.
+ * @param run the text run to paint
+ * @param g2d the Graphics2D to paint to
+ * @param loc the current location of the "cursor"
+ * @return the new location of the "cursor" after painting the text run
+ */
+ protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) {
+ AttributedCharacterIterator aci = run.getACI();
+ aci.first();
+
+ updateLocationFromACI(aci, loc);
+ loc = g2d.getTransform().transform(loc, null);
+
+ // font
+ Font font = makeFont(aci);
+ nativeTextHandler.setOverrideFont(font);
+
+ // color
+ TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
+ if (tpi == null) {
+ return loc;
+ }
+ Paint foreground = tpi.fillPaint;
+ if (foreground instanceof Color) {
+ Color col = (Color)foreground;
+ g2d.setColor(col);
+ }
+ g2d.setPaint(foreground);
+
+ String txt = getText(aci);
+ float advance = getStringWidth(txt, font);
+ float tx = 0;
+ TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE);
+ if (anchor != null) {
+ switch (anchor.getType()) {
+ case TextNode.Anchor.ANCHOR_MIDDLE:
+ tx = -advance / 2;
+ break;
+ case TextNode.Anchor.ANCHOR_END:
+ tx = -advance;
+ break;
+ default: //nop
+ }
+ }
+
+ // draw string
+ try {
+ try {
+ nativeTextHandler.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY()));
+ } catch (IOException ioe) {
+ if (g2d instanceof AFPGraphics2D) {
+ ((AFPGraphics2D)g2d).handleIOException(ioe);
+ }
+ }
+ } finally {
+ nativeTextHandler.setOverrideFont(null);
+ }
+ loc.setLocation(loc.getX() + (double)advance, loc.getY());
+ return loc;
+ }
+
+ /**
+ * Extract the raw text from an ACI.
+ * @param aci ACI to inspect
+ * @return the extracted text
+ */
+ protected String getText(AttributedCharacterIterator aci) {
+ StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex());
+ for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) {
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ private void updateLocationFromACI(
+ AttributedCharacterIterator aci,
+ Point2D loc) {
+ //Adjust position of span
+ Float xpos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.X);
+ Float ypos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.Y);
+ Float dxpos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DX);
+ Float dypos = (Float)aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.DY);
+ if (xpos != null) {
+ loc.setLocation(xpos.doubleValue(), loc.getY());
+ }
+ if (ypos != null) {
+ loc.setLocation(loc.getX(), ypos.doubleValue());
+ }
+ if (dxpos != null) {
+ loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
+ }
+ if (dypos != null) {
+ loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
+ }
+ }
+
+ private String getStyle(AttributedCharacterIterator aci) {
+ Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
+ return ((posture != null) && (posture.floatValue() > 0.0))
+ ? "italic"
+ : "normal";
+ }
+
+ private int getWeight(AttributedCharacterIterator aci) {
+ Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
+ return ((taWeight != null) && (taWeight.floatValue() > 1.0))
+ ? Font.WEIGHT_BOLD
+ : Font.WEIGHT_NORMAL;
+ }
+
+ private Font makeFont(AttributedCharacterIterator aci) {
+ Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
+ if (fontSize == null) {
+ fontSize = new Float(10.0f);
+ }
+ String style = getStyle(aci);
+ int weight = getWeight(aci);
+
+ FontInfo fontInfo = nativeTextHandler.getFontInfo();
+ String fontFamily = null;
+ List gvtFonts = (List) aci.getAttribute(
+ GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
+ if (gvtFonts != null) {
+ Iterator i = gvtFonts.iterator();
+ while (i.hasNext()) {
+ GVTFontFamily fam = (GVTFontFamily) i.next();
+ /* (todo) Enable SVG Font painting
+ if (fam instanceof SVGFontFamily) {
+ PROXY_PAINTER.paint(node, g2d);
+ return;
+ }*/
+ fontFamily = fam.getFamilyName();
+ if (fontInfo.hasFont(fontFamily, style, weight)) {
+ FontTriplet triplet = fontInfo.fontLookup(
+ fontFamily, style, weight);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ return fontInfo.getFontInstance(triplet, fsize);
+ }
+ }
+ }
+ FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
+ int fsize = (int)(fontSize.floatValue() * 1000);
+ return fontInfo.getFontInstance(triplet, fsize);
+ }
+
+ private float getStringWidth(String str, Font font) {
+ float wordWidth = 0;
+ float whitespaceWidth = font.getWidth(font.mapChar(' '));
+
+ for (int i = 0; i < str.length(); i++) {
+ float charWidth;
+ char c = str.charAt(i);
+ if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+ charWidth = font.getWidth(font.mapChar(c));
+ if (charWidth <= 0) {
+ charWidth = whitespaceWidth;
+ }
+ } else {
+ charWidth = whitespaceWidth;
+ }
+ wordWidth += charWidth;
+ }
+ return wordWidth / 1000f;
+ }
+
+ private boolean hasUnsupportedGlyphs(String str, Font font) {
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) {
+ if (!font.hasChar(c)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the outline shape of the text characters.
+ * This uses the StrokingTextPainter to get the outline
+ * shape since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the outline shape of the text characters
+ */
+ public Shape getOutline(TextNode node) {
+ return PROXY_PAINTER.getOutline(node);
+ }
+
+ /**
+ * Get the bounds.
+ * This uses the StrokingTextPainter to get the bounds
+ * since in theory it should be the same.
+ *
+ * @param node the text node
+ * @return the bounds of the text
+ */
+ public Rectangle2D getBounds2D(TextNode node) {
+ /* (todo) getBounds2D() is too slow
+ * because it uses the StrokingTextPainter. We should implement this
+ * method ourselves. */
+ return PROXY_PAINTER.getBounds2D(node);
+ }
+
+ /**
+ * Get the geometry bounds.
+ * This uses the StrokingTextPainter to get the bounds
+ * since in theory it should be the same.
+ * @param node the text node
+ * @return the bounds of the text
+ */
+ public Rectangle2D getGeometryBounds(TextNode node) {
+ return PROXY_PAINTER.getGeometryBounds(node);
+ }
+
+ // Methods that have no purpose for PS
+
+ /**
+ * Get the mark.
+ * This does nothing since the output is pdf and not interactive.
+ * @param node the text node
+ * @param pos the position
+ * @param all select all
+ * @return null
+ */
+ public Mark getMark(TextNode node, int pos, boolean all) {
+ return null;
+ }
+
+ /**
+ * Select at.
+ * This does nothing since the output is pdf and not interactive.
+ * @param x the x position
+ * @param y the y position
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectAt(double x, double y, TextNode node) {
+ return null;
+ }
+
+ /**
+ * Select to.
+ * This does nothing since the output is pdf and not interactive.
+ * @param x the x position
+ * @param y the y position
+ * @param beginMark the start mark
+ * @return null
+ */
+ public Mark selectTo(double x, double y, Mark beginMark) {
+ return null;
+ }
+
+ /**
+ * Selec first.
+ * This does nothing since the output is pdf and not interactive.
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectFirst(TextNode node) {
+ return null;
+ }
+
+ /**
+ * Select last.
+ * This does nothing since the output is pdf and not interactive.
+ * @param node the text node
+ * @return null
+ */
+ public Mark selectLast(TextNode node) {
+ return null;
+ }
+
+ /**
+ * Get selected.
+ * This does nothing since the output is pdf and not interactive.
+ * @param start the start mark
+ * @param finish the finish mark
+ * @return null
+ */
+ public int[] getSelected(Mark start, Mark finish) {
+ return null;
+ }
+
+ /**
+ * Get the highlighted shape.
+ * This does nothing since the output is pdf and not interactive.
+ * @param beginMark the start mark
+ * @param endMark the end mark
+ * @return null
+ */
+ public Shape getHighlightShape(Mark beginMark, Mark endMark) {
+ return null;
+ }
+
+}
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 ba37b989e..62de923c8 100644
--- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java
+++ b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java
@@ -22,9 +22,12 @@ package org.apache.fop.render.afp.modca;
import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Iterator;
+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.fonts.AFPFont;
import org.apache.fop.render.afp.tools.StringUtils;
@@ -132,7 +135,7 @@ public class AFPDataStream {
* The outputstream for the data stream
*/
private OutputStream outputStream = null;
-
+
/**
* Default constructor for the AFPDataStream.
*/
@@ -147,7 +150,6 @@ public class AFPDataStream {
* 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);
@@ -156,7 +158,6 @@ public class AFPDataStream {
this.document = new Document();
this.outputStream = docOutputStream;
-
}
/**
@@ -168,7 +169,6 @@ public class AFPDataStream {
* throws an I/O exception of some sort has occurred
*/
public void endDocument() throws IOException {
-
if (complete) {
String msg = "Invalid state - document already ended.";
log.warn("endDocument():: " + msg);
@@ -206,19 +206,19 @@ public class AFPDataStream {
* the height of the page
* @param pageRotation
* the rotation of the page
- * @param pageWidthResolution
+ * @param pageWidthRes
* the width resolution of the page
- * @param pageHeightResolution
+ * @param pageHeightRes
* the height resolution of the page
*/
public void startPage(int pageWidth, int pageHeight, int pageRotation,
- int pageWidthResolution, int pageHeightResolution) {
+ int pageWidthRes, int pageHeightRes) {
String pageName = "PGN"
+ StringUtils.lpad(String.valueOf(pageCount++), '0', 5);
currentPageObject = new PageObject(pageName, pageWidth, pageHeight,
- pageRotation, pageWidthResolution, pageHeightResolution);
+ pageRotation, pageWidthRes, pageHeightRes);
currentPage = currentPageObject;
currentOverlay = null;
setOffsets(0, 0, 0);
@@ -265,11 +265,9 @@ public class AFPDataStream {
* Helper method to mark the end of the current overlay.
*/
public void endOverlay() {
-
currentOverlay.endPage();
currentOverlay = null;
currentPage = currentPageObject;
-
}
/**
@@ -278,7 +276,6 @@ public class AFPDataStream {
* @return current page object that was saved
*/
public PageObject savePage() {
-
PageObject pageObject = currentPageObject;
if (currentPageGroup != null) {
currentPageGroup.addPage(currentPageObject);
@@ -288,7 +285,6 @@ public class AFPDataStream {
currentPageObject = null;
currentPage = null;
return pageObject;
-
}
/**
@@ -298,10 +294,8 @@ public class AFPDataStream {
* page object
*/
public void restorePage(PageObject pageObject) {
-
currentPageObject = pageObject;
currentPage = pageObject;
-
}
/**
@@ -311,7 +305,6 @@ public class AFPDataStream {
* thrown when an I/O exception of some sort has occurred
*/
public void endPage() throws IOException {
-
currentPageObject.endPage();
if (currentPageGroup != null) {
currentPageGroup.addPage(currentPageObject);
@@ -319,10 +312,8 @@ public class AFPDataStream {
document.addPage(currentPageObject);
document.writeDataStream(this.outputStream);
}
-
currentPageObject = null;
currentPage = null;
-
}
/**
@@ -342,6 +333,21 @@ public class AFPDataStream {
}
/**
+ * Creates the given page fonts in the current page
+ * @param pageFonts a collection of AFP font attributes
+ */
+ public void addFontsToCurrentPage(Map pageFonts) {
+ Iterator iter = pageFonts.values().iterator();
+ while (iter.hasNext()) {
+ AFPFontAttributes afpFontAttributes = (AFPFontAttributes)iter.next();
+ createFont(
+ afpFontAttributes.getFontReference(),
+ afpFontAttributes.getFont(),
+ afpFontAttributes.getPointSize());
+ }
+ }
+
+ /**
* Helper method to create a map coded font object on the current page, this
* method delegates the construction of the map coded font object to the
* active environment group on the current page.
@@ -353,18 +359,17 @@ public class AFPDataStream {
* @param size
* the point size of the font
*/
- public void createFont(byte fontReference, AFPFont font, int size) {
-
+ public void createFont(int fontReference, AFPFont font, int size) {
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.
*
- * @param fontNumber
- * the font number used as the resource identifier
+ * @param fontReference
+ * the font reference used as the resource identifier
* @param x
* the x coordinate of the text
* @param y
@@ -378,81 +383,125 @@ public class AFPDataStream {
* @param data
* the text data to create
*/
- public void createText(int fontNumber, int x, int y, Color col, int vsci,
+ public void createText(int fontReference, int x, int y, Color col, int vsci,
int ica, byte[] data) {
-
- currentPage.createText(fontNumber, x + xOffset, y + yOffset, rotation,
+ 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 w
+ * @param width
* the width of the image
- * @param h
+ * @param height
* the height of the image
+ * @param widthRes
+ * the resolution width of the image
+ * @param heightRes
+ * the resolution height of the image
+ * @return
+ * a new 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;
+ }
+
+ /**
+ * Returns an GraphicObject used to create an 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
+ * @return
+ * a new 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;
+ }
+
+ /**
+ * Sets the object view port taking into account rotation.
+ *
+ * @param x
+ * the x position of the object
+ * @param y
+ * the y position of the object
+ * @param w
+ * the width of the object
+ * @param h
+ * the height of the object
* @param wr
- * the width resolution of the image
+ * the resolution width of the object
* @param hr
- * the height resolution of the image
- * @return ImageObject used to create an image in the datastream
+ * the resolution height of the object
+ * @return
+ * a new graphics object
*/
- public ImageObject getImageObject(int x, int y, int w, int h, int wr, int hr) {
-
+ private void setObjectViewPort(AbstractDataObject dataObj,
+ int x, int y, int w, int h, int wr, int hr) {
int xOrigin;
int yOrigin;
int width;
int height;
- int widthResolution;
- int heightResolution;
-
- switch (rotation) {
+ int widthRes;
+ int heightRes;
+ switch (this.rotation) {
case 90:
xOrigin = currentPage.getWidth() - y - yOffset;
yOrigin = x + xOffset;
width = h;
height = w;
- widthResolution = hr;
- heightResolution = wr;
+ widthRes = hr;
+ heightRes = wr;
break;
case 180:
xOrigin = currentPage.getWidth() - x - xOffset;
yOrigin = currentPage.getHeight() - y - yOffset;
width = w;
height = h;
- widthResolution = wr;
- heightResolution = hr;
+ widthRes = wr;
+ heightRes = hr;
break;
case 270:
xOrigin = y + yOffset;
yOrigin = currentPage.getHeight() - x - xOffset;
width = h;
height = w;
- widthResolution = hr;
- heightResolution = wr;
+ widthRes = hr;
+ heightRes = wr;
break;
default:
xOrigin = x + xOffset;
yOrigin = y + yOffset;
width = w;
height = h;
- widthResolution = wr;
- heightResolution = hr;
+ widthRes = wr;
+ heightRes = hr;
break;
}
- ImageObject io = currentPage.getImageObject();
- io.setImageViewport(xOrigin, yOrigin, width, height, rotation,
- widthResolution, heightResolution);
- return io;
-
+ dataObj.setViewport(xOrigin, yOrigin, width, height, widthRes, heightRes, rotation);
}
-
+
/**
* Method to create a line on the current page.
*
@@ -471,10 +520,8 @@ public class AFPDataStream {
*/
public void createLine(int x1, int y1, int x2, int y2, int thickness,
Color col) {
-
currentPage.createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset, y2
+ yOffset, thickness, rotation, col);
-
}
/**
@@ -499,10 +546,8 @@ public class AFPDataStream {
*/
public void createShading(int x, int y, int w, int h, int red, int green,
int blue) {
-
currentPage.createShading(x + xOffset, y + xOffset, w, h, red, green,
blue);
-
}
/**
@@ -513,12 +558,10 @@ public class AFPDataStream {
* the name of the static overlay
*/
public void createIncludePageOverlay(String name) {
-
currentPageObject.createIncludePageOverlay(name, 0, 0, rotation);
ActiveEnvironmentGroup aeg = currentPageObject
.getActiveEnvironmentGroup();
aeg.createOverlay(name);
-
}
/**
@@ -528,12 +571,10 @@ public class AFPDataStream {
* the name of the medium map
*/
public void createInvokeMediumMap(String name) {
-
if (currentPageGroup == null) {
startPageGroup();
}
currentPageGroup.createInvokeMediumMap(name);
-
}
/**
@@ -547,7 +588,6 @@ public class AFPDataStream {
* the y coordinate for the overlay
*/
public void createIncludePageSegment(String name, int x, int y) {
-
int xOrigin;
int yOrigin;
switch (rotation) {
@@ -569,7 +609,6 @@ public class AFPDataStream {
break;
}
currentPage.createIncludePageSegment(name, xOrigin, yOrigin);
-
}
/**
@@ -579,13 +618,11 @@ public class AFPDataStream {
* the array of key value pairs.
*/
public void createPageTagLogicalElement(TagLogicalElementBean[] attributes) {
-
for (int i = 0; i < attributes.length; i++) {
String name = (String) attributes[i].getKey();
String value = (String) attributes[i].getValue();
currentPage.createTagLogicalElement(name, value);
}
-
}
/**
@@ -594,15 +631,12 @@ public class AFPDataStream {
* @param attributes
* the array of key value pairs.
*/
- public void createPageGroupTagLogicalElement(
- TagLogicalElementBean[] attributes) {
-
+ public void createPageGroupTagLogicalElement(TagLogicalElementBean[] attributes) {
for (int i = 0; i < attributes.length; i++) {
String name = (String) attributes[i].getKey();
String value = (String) attributes[i].getValue();
currentPageGroup.createTagLogicalElement(name, value);
}
-
}
/**
@@ -614,13 +648,11 @@ public class AFPDataStream {
* The tag value
*/
public void createTagLogicalElement(String name, String value) {
-
if (currentPageGroup != null) {
currentPageGroup.createTagLogicalElement(name, value);
} else {
currentPage.createTagLogicalElement(name, value);
}
-
}
/**
@@ -697,5 +729,4 @@ public class AFPDataStream {
}
}
-
}
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 ef1b988c0..cd8b25810 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java
@@ -44,7 +44,7 @@ public abstract class AbstractAFPObject {
* DataStream objects must implement the writeDataStream()
* method to write its data to the given OutputStream
* @param os The outputsteam stream
- * @throws java.io.IOException
+ * @throws java.io.IOException in the event that an I/O exception occurred
*/
public abstract void writeDataStream(OutputStream os) throws IOException;
@@ -52,15 +52,14 @@ public abstract class AbstractAFPObject {
* Help method to write a set of AFPObjects to the AFP datastream.
* @param afpObjects a list of AFPObjects
* @param os The stream to write to
- * @throws java.io.IOException
+ * @throws java.io.IOException in the event that an I/O exception occurred
*/
protected void writeObjectList(List afpObjects, OutputStream os)
- throws IOException {
+ throws IOException {
- for (Iterator it = afpObjects.iterator(); it.hasNext(); ) {
+ Iterator it = afpObjects.iterator();
+ while (it.hasNext()) {
((AbstractAFPObject)it.next()).writeDataStream(os);
}
-
}
-
}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java
new file mode 100644
index 000000000..363e5c6e4
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractDataObject.java
@@ -0,0 +1,90 @@
+/*
+ * 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.goca.AbstractGraphicsContainer;
+
+/**
+ * Abstract base class used by the ImageObject and GraphicsObject which both
+ * have define an ObjectEnvironmentGroup
+ */
+public abstract class AbstractDataObject extends AbstractGraphicsContainer {
+
+ /**
+ * The object environment group
+ */
+ protected ObjectEnvironmentGroup objectEnvironmentGroup = null;
+
+ /**
+ * Named constructor
+ * @param name data object name
+ */
+ public AbstractDataObject(String name) {
+ super(name);
+ }
+
+ /**
+ * Sets the object display area position and size.
+ *
+ * @param x
+ * the x position of the object
+ * @param y
+ * the y position of the object
+ * @param width
+ * the width of the object
+ * @param height
+ * the height of the object
+ * @param widthRes
+ * the resolution width
+ * @param heightRes
+ * the resolution height
+ * @param rotation
+ * the rotation of the object
+ */
+ public void setViewport(int x, int y, int width, int height,
+ int widthRes, int heightRes, int rotation) {
+ if (objectEnvironmentGroup == null) {
+ objectEnvironmentGroup = new ObjectEnvironmentGroup();
+ }
+ objectEnvironmentGroup.setObjectArea(x, y, width, height,
+ widthRes, heightRes, rotation);
+ }
+
+ /**
+ * Sets the ObjectEnvironmentGroup.
+ * @param objectEnvironmentGroup The objectEnvironmentGroup to set
+ */
+ public void setObjectEnvironmentGroup(ObjectEnvironmentGroup objectEnvironmentGroup) {
+ this.objectEnvironmentGroup = objectEnvironmentGroup;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeContent(OutputStream os) throws IOException {
+ if (objectEnvironmentGroup != null) {
+ objectEnvironmentGroup.writeDataStream(os);
+ }
+ super.writeContent(os);
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java
index 6d827766e..29c619d32 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java
@@ -28,22 +28,22 @@ public abstract class AbstractDescriptor extends AbstractAFPObject {
/** height of this descriptor */
protected int height = 0;
/** width resolution of this descriptor */
- protected int widthResolution = 0;
+ protected int widthRes = 0;
/** height resolution of this descriptor */
- protected int heightResolution = 0;
+ protected int heightRes = 0;
/**
* Constructor a PresentationTextDescriptor for the specified
* width and height.
* @param width The width of the page.
* @param height The height of the page.
- * @param widthResolution The width resolution of the page.
- * @param heightResolution The height resolution of the page.
+ * @param widthRes The width resolution of the page.
+ * @param heightRes The height resolution of the page.
*/
- public AbstractDescriptor(int width, int height, int widthResolution, int heightResolution) {
+ public AbstractDescriptor(int width, int height, int widthRes, int heightRes) {
this.width = width;
this.height = height;
- this.widthResolution = widthResolution;
- this.heightResolution = heightResolution;
+ this.widthRes = widthRes;
+ this.heightRes = heightRes;
}
}
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 d8c99fa9a..7545ee3af 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java
@@ -25,7 +25,7 @@ import java.io.UnsupportedEncodingException;
* A named data stream object has an 8 byte EBCIDIC name.
*/
public abstract class AbstractNamedAFPObject extends AbstractAFPObject {
-
+
/**
* The actual name of the object
*/
@@ -35,35 +35,50 @@ public abstract class AbstractNamedAFPObject extends AbstractAFPObject {
* The name of the object in EBCIDIC bytes
*/
protected byte[] nameBytes;
-
+
+ /**
+ * Default constructor
+ */
+ 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) {
-
- this.name = name;
- if (name.length() < 8) {
- name = (name + " ").substring(0, 8);
- } else if (name.length() > 8) {
- log.warn("Constructor:: name truncated to 8 chars" + name);
- name = name.substring(0, 8);
+ int nameLen = getNameLength();
+ if (name.length() < nameLen) {
+ this.name = (name + " ").substring(0, nameLen);
+ } else if (name.length() > nameLen) {
+ log.warn("Constructor:: name truncated to " + nameLen + " chars: " + name);
+ this.name = name.substring(0, nameLen);
+ } else {
+ this.name = name;
}
try {
- nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
} catch (UnsupportedEncodingException usee) {
- nameBytes = name.getBytes();
+ this.nameBytes = name.getBytes();
log.warn(
"Constructor:: UnsupportedEncodingException translating the name "
+ 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 a99b28107..4ffcc4d94 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
@@ -105,13 +105,13 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
* the height of the page.
* @param rotation
* the rotation of the page.
- * @param widthResolution
+ * @param widthRes
* the width resolution of the page.
- * @param heightResolution
+ * @param heightRes
* the height resolution of the page.
*/
public AbstractPageObject(String name, int width, int height, int rotation,
- int widthResolution, int heightResolution) {
+ int widthRes, int heightRes) {
super(name);
this.width = width;
@@ -121,8 +121,7 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
/**
* Every page object must have an ActiveEnvironmentGroup
*/
- activeEnvironmentGroup = new ActiveEnvironmentGroup(width, height,
- widthResolution, heightResolution);
+ activeEnvironmentGroup = new ActiveEnvironmentGroup(width, height, widthRes, heightRes);
if (rotation != 0) {
switch (rotation) {
@@ -138,13 +137,6 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
default:
}
}
-
- /**
- * We have a presentation text object per page
- */
- presentationTextObject = new PresentationTextObject();
- objects.add(presentationTextObject);
-
}
/**
@@ -159,10 +151,8 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
* @param size
* the point size of the font
*/
- public void createFont(byte fontReference, AFPFont font, int size) {
-
+ public void createFont(int fontReference, AFPFont font, int size) {
activeEnvironmentGroup.createFont(fontReference, font, size, 0);
-
}
/**
@@ -186,20 +176,14 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
*/
public void createLine(int x1, int y1, int x2, int y2, int thickness,
int lineRotation, Color col) {
-
- if (presentationTextObject == null) {
- presentationTextObject = new PresentationTextObject();
- objects.add(presentationTextObject);
- }
- presentationTextObject.createLineData(x1, y1, x2, y2, thickness, lineRotation, col);
-
+ getPresentationTextObject().createLineData(x1, y1, x2, y2, thickness, lineRotation, col);
}
/**
* Helper method to create text on the current page, this method delegates
* to the presentation text object in order to construct the text.
*
- * @param fontNumber
+ * @param fontReference
* the font number used as the resource identifier
* @param x
* the x coordinate of the text data
@@ -216,15 +200,10 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
* @param data
* the text data to create
*/
- public void createText(int fontNumber, int x, int y, int textRotation, Color col,
+ public void createText(int fontReference, int x, int y, int textRotation, Color col,
int vsci, int ica, byte[] data) {
-
- if (presentationTextObject == null) {
- presentationTextObject = new PresentationTextObject();
- objects.add(presentationTextObject);
- }
- presentationTextObject.createTextData(fontNumber, x, y, textRotation, col, vsci, ica, data);
-
+ getPresentationTextObject().createTextData(
+ fontReference, x, y, textRotation, col, vsci, ica, data);
}
/**
@@ -232,13 +211,10 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
* sequence on the current presenation text object.
*/
public void endPage() {
-
if (presentationTextObject != null) {
presentationTextObject.endControlSequence();
}
-
complete = true;
-
}
/**
@@ -327,6 +303,19 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
}
/**
+ * Helper method to create a presentation text object
+ * on the current page and to return the object.
+ * @return the presentation text object
+ */
+ private PresentationTextObject getPresentationTextObject() {
+ if (presentationTextObject == null) {
+ this.presentationTextObject = new PresentationTextObject();
+ objects.add(this.presentationTextObject);
+ }
+ return presentationTextObject;
+ }
+
+ /**
* Helper method to create an image on the current page and to return
* the object.
* @return the image object
@@ -335,16 +324,32 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
if (presentationTextObject != null) {
presentationTextObject.endControlSequence();
+ presentationTextObject = null;
}
- presentationTextObject = null;
-
String imageName = "IMG"
+ StringUtils.lpad(String.valueOf(objects.size() + 1),
'0', 5);
+ ImageObject imageObj = new ImageObject(imageName);
+ objects.add(imageObj);
+ return imageObj;
+ }
- ImageObject io = new ImageObject(imageName);
- objects.add(io);
- return io;
+ /**
+ * 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;
}
/**
@@ -356,10 +361,8 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
* the value of the tag
*/
public void createTagLogicalElement(String name, String value) {
-
TagLogicalElement tle = new TagLogicalElement(name, value);
tagLogicalElements.add(tle);
-
}
/**
@@ -368,10 +371,8 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
* @param content the byte data
*/
public void createNoOperation(String content) {
-
NoOperation noOp = new NoOperation(content);
objects.add(noOp);
-
}
/**
@@ -380,15 +381,13 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
* @param name
* the name of the page segment
* @param xCoor
- * the x cooridinate of the page segment.
+ * the x coordinate of the page segment.
* @param yCoor
- * the y cooridinate of the page segment.
+ * the y coordinate of the page segment.
*/
public void createIncludePageSegment(String name, int xCoor, int yCoor) {
-
IncludePageSegment ips = new IncludePageSegment(name, xCoor, yCoor);
segments.add(ips);
-
}
/**
@@ -431,5 +430,4 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject {
public int getRotation() {
return rotation;
}
-
}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.java
new file mode 100644
index 000000000..bc2bf9f99
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractStructuredAFPObject.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;
+
+/**
+ * An abstract class encapsulating an MODCA structured object
+ */
+public abstract class AbstractStructuredAFPObject extends AbstractNamedAFPObject {
+
+ /**
+ * Default constructor
+ */
+ public AbstractStructuredAFPObject() {
+ super();
+ }
+
+ /**
+ * Named constructor
+ * @param name name of structured object
+ */
+ public AbstractStructuredAFPObject(String name) {
+ super(name);
+ }
+
+ /**
+ * Helper method to write the start of the Object.
+ * @param os The stream to write to
+ * @throws an I/O exception if one occurred
+ */
+ protected void writeStart(OutputStream os) throws IOException {
+ }
+
+ /**
+ * Helper method to write the contents of the Object.
+ * @param os The stream to write to
+ * @throws an I/O exception if one occurred
+ */
+ protected void writeContent(OutputStream os) throws IOException {
+ }
+
+ /**
+ * Helper method to write the end of the Object.
+ * @param os The stream to write to
+ * @throws 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 java.io.IOException in the event that an I/O exception occurred
+ */
+ public void writeDataStream(OutputStream os)
+ throws IOException {
+
+ writeStart(os);
+
+ writeContent(os);
+
+ writeEnd(os);
+ }
+}
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 3e341c735..eb537b0d7 100644
--- a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java
+++ b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java
@@ -20,7 +20,7 @@
package org.apache.fop.render.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.ArrayList;
+import java.util.List;
import org.apache.fop.render.afp.fonts.AFPFont;
@@ -47,7 +47,7 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject {
/**
* The collection of MapCodedFont objects
*/
- private ArrayList mapCodedFonts = new ArrayList();
+ private List mapCodedFonts = new java.util.ArrayList();
/**
* The Object Area Descriptor for the active environment group
@@ -72,19 +72,19 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject {
/**
* The collection of MapPageOverlay objects
*/
- private ArrayList mapPageOverlays = new ArrayList();
+ private List mapPageOverlays = new java.util.ArrayList();
/**
* Default constructor for the ActiveEnvironmentGroup.
* @param width the page width
* @param height the page height
- * @param widthResolution the page width resolution
- * @param heightResolution the page height resolution
+ * @param widthRes the page width resolution
+ * @param heightRes the page height resolution
*/
public ActiveEnvironmentGroup(int width, int height,
- int widthResolution, int heightResolution) {
+ int widthRes, int heightRes) {
- this(DEFAULT_NAME, width, height, widthResolution, heightResolution);
+ this(DEFAULT_NAME, width, height, widthRes, heightRes);
}
@@ -94,24 +94,24 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject {
* @param name the active environment group name
* @param width the page width
* @param height the page height
- * @param widthResolution the page width resolution
- * @param heightResolution the page height resolution
+ * @param widthRes the page width resolution
+ * @param heightRes the page height resolution
*/
public ActiveEnvironmentGroup(String name, int width, int height,
- int widthResolution, int heightResolution) {
+ int widthRes, int heightRes) {
super(name);
// Create PageDescriptor
- pageDescriptor = new PageDescriptor(width, height, widthResolution, heightResolution);
+ pageDescriptor = new PageDescriptor(width, height, widthRes, heightRes);
// Create ObjectAreaDescriptor
objectAreaDescriptor = new ObjectAreaDescriptor(width, height,
- widthResolution, heightResolution);
+ widthRes, heightRes);
// Create PresentationTextDataDescriptor
presentationTextDataDescriptor = new PresentationTextDescriptor(width, height,
- widthResolution, heightResolution);
+ widthRes, heightRes);
}
@@ -243,7 +243,7 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject {
* @param orientation the orientation of the font (e.g. 0, 90, 180, 270)
*/
public void createFont(
- byte fontReference,
+ int fontReference,
AFPFont font,
int size,
int orientation) {
@@ -256,7 +256,7 @@ public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject {
}
try {
-
+
mcf.addFont(
fontReference,
font,
diff --git a/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java
new file mode 100644
index 000000000..fdeb5c418
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/GraphicsDataDescriptor.java
@@ -0,0 +1,118 @@
+/*
+ * 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.tools.BinaryUtils;
+
+/**
+ * GOCA Graphics Data Descriptor
+ */
+public class GraphicsDataDescriptor extends AbstractAFPObject {
+
+ private int xlwind;
+ private int xrwind;
+ private int ybwind;
+ private int ytwind;
+ private int xresol;
+ private int yresol;
+
+ /**
+ * Main constructor
+ * @param xresol the x resolution of the graphics window
+ * @param yresol the y resolution of the graphics window
+ * @param xlwind the left edge of the graphics window
+ * @param xrwind the right edge of the graphics window
+ * @param ybwind the top edge of the graphics window
+ * @param ytwind the bottom edge of the graphics window
+ */
+ protected GraphicsDataDescriptor(int xresol, int yresol,
+ int xlwind, int xrwind, int ybwind, int ytwind) {
+ this.xresol = xresol;
+ this.yresol = yresol;
+ this.xlwind = xlwind;
+ this.xrwind = xrwind;
+ this.ybwind = ybwind;
+ this.ytwind = ytwind;
+ }
+
+ private static final int ABS = 2;
+ private static final int IMGRES = 8;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void writeDataStream(OutputStream os) throws IOException {
+ byte[] xreswind = BinaryUtils.convert(xresol * 10, 2);
+ byte[] yreswind = BinaryUtils.convert(yresol * 10, 2);
+ byte[] xlcoord = BinaryUtils.convert(xlwind, 2);
+ byte[] xrcoord = BinaryUtils.convert(xrwind, 2);
+ byte[] xbcoord = BinaryUtils.convert(ybwind, 2);
+ byte[] ytcoord = BinaryUtils.convert(ytwind, 2);
+ byte[] imxyres = xreswind;
+ byte[] data = new byte[] {
+ 0x5A,
+ 0x00,
+ 0x25,
+ (byte) 0xD3,
+ (byte) 0xA6,
+ (byte) 0xBB,
+ 0x00, // Flags
+ 0x00, // Reserved
+ 0x00, // Reserved
+
+ // Drawing order subset
+ (byte) 0xF7,
+ 7, // LENGTH
+ (byte) 0xB0, // drawing order subset
+ 0x00, // reserved (must be zero)
+ 0x00, // reserved (must be zero)
+ 0x02, // SUBLEV
+ 0x00, // VERSION 0
+ 0x01, // LENGTH (of following field)
+ 0x00, // GEOM
+
+ // Window specification
+ (byte) 0xF6,
+ 18, // LENGTH
+ (ABS + IMGRES), // FLAGS (ABS)
+ 0x00, // reserved (must be zero)
+ 0x00, // CFORMAT (coordinate format - 16bit high byte first signed)
+ 0x00, // UBASE (unit base - ten inches)
+ xreswind[0], // XRESOL
+ xreswind[1],
+ yreswind[0], // YRESOL
+ yreswind[1],
+ imxyres[0], // IMXYRES (Number of image points per ten inches
+ imxyres[1], // in X and Y directions)
+ xlcoord[0], // XLWIND
+ xlcoord[1],
+ xrcoord[0], // XRWIND
+ xrcoord[1],
+ xbcoord[0], // YBWIND
+ xbcoord[1],
+ ytcoord[0], // YTWIND
+ ytcoord[1]
+ };
+ os.write(data);
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java
new file mode 100644
index 000000000..45c9f5751
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/GraphicsObject.java
@@ -0,0 +1,321 @@
+/*
+ * 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.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;
+
+/**
+ * Top-level GOCA graphics object.
+ *
+ * Acts as container and factory of all other graphic objects
+ */
+public class GraphicsObject extends AbstractDataObject {
+
+ /**
+ * The graphics data
+ */
+ private GraphicsData graphicsData = null;
+
+ /**
+ * Default constructor
+ *
+ * @param name the name of graphics object
+ */
+ public GraphicsObject(String name) {
+ super(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setViewport(int x, int y, int width, int height,
+ int widthRes, int heightRes, int rotation) {
+ super.setViewport(x, y, width, height, widthRes, heightRes, rotation);
+ objectEnvironmentGroup.setGraphicsData(
+ widthRes, heightRes, 0, x + width, 0, y + height);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeStart(OutputStream os) throws IOException {
+ super.writeStart(os);
+ byte[] data = new byte[] {
+ 0x5A, // Structured field identifier
+ 0x00, //sfLen[0], // Length byte 1
+ 0x10, //sfLen[1], // Length byte 2
+ (byte) 0xD3, // Structured field id byte 1
+ (byte) 0xA8, // Structured field id byte 2
+ (byte) 0xBB, // Structured field id byte 3
+ 0x00, // Flags
+ 0x00, // Reserved
+ 0x00, // Reserved
+ super.nameBytes[0], // gdoName
+ super.nameBytes[1],
+ super.nameBytes[2],
+ super.nameBytes[3],
+ super.nameBytes[4],
+ super.nameBytes[5],
+ super.nameBytes[6],
+ super.nameBytes[7]
+ };
+ os.write(data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] data = new byte[] {
+ 0x5A, // Structured field identifier
+ 0x00, // sfLen[0], // Length byte 1
+ 0x10, // sfLen[1], // Length byte 2
+ (byte) 0xD3, // Structured field id byte 1
+ (byte) 0xA9, // Structured field id byte 2
+ (byte) 0xBB, // Structured field id byte 3
+ 0x00, // Flags
+ 0x00, // Reserved
+ 0x00, // Reserved
+ super.nameBytes[0], // gdoName
+ super.nameBytes[1],
+ super.nameBytes[2],
+ super.nameBytes[3],
+ super.nameBytes[4],
+ super.nameBytes[5],
+ super.nameBytes[6],
+ super.nameBytes[7]
+ };
+ os.write(data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) {
+ if (graphicsData == null
+ || (graphicsData.getDataLength() + drawingOrder.getDataLength())
+ >= GraphicsData.MAX_DATA_LEN) {
+ newData();
+ }
+ graphicsData.addDrawingOrder(drawingOrder);
+ return drawingOrder;
+ }
+
+ /**
+ * Gets the current graphics data, creating a new one if necessary
+ * @return the current graphics data
+ */
+ private GraphicsData getData() {
+ if (this.graphicsData == null) {
+ return newData();
+ }
+ return this.graphicsData;
+ }
+
+ /**
+ * Creates a new graphics data
+ * @return a newly created graphics data
+ */
+ private GraphicsData newData() {
+ this.graphicsData = new GraphicsData();
+ super.addDrawingOrder(graphicsData);
+ return graphicsData;
+ }
+
+ /**
+ * Sets the current color
+ * @param col the active color to use
+ */
+ public void setColor(Color col) {
+ addDrawingOrder(new GraphicsSetProcessColor(col));
+ }
+
+ /**
+ * Sets the current position
+ * @param coords the x and y coordinates of the current position
+ */
+ public void setCurrentPosition(int[] coords) {
+ addDrawingOrder(new GraphicsSetCurrentPosition(coords));
+ }
+
+ /**
+ * Sets the line width
+ * @param multiplier the line width multiplier
+ */
+ public void setLineWidth(int multiplier) {
+ GraphicsSetLineWidth lw = new GraphicsSetLineWidth(multiplier);
+ addDrawingOrder(lw);
+ }
+
+ /**
+ * Sets the line type
+ * @param type the line type
+ */
+ public void setLineType(byte type) {
+ GraphicsSetLineType lt = new GraphicsSetLineType(type);
+ addDrawingOrder(lt);
+ }
+
+ /**
+ * Sets whether to fill the next shape
+ * @param fill whether to fill the next shape
+ */
+ public void setFill(boolean fill) {
+ GraphicsSetPatternSymbol pat = new GraphicsSetPatternSymbol(
+ fill ? GraphicsSetPatternSymbol.SOLID_FILL
+ : GraphicsSetPatternSymbol.NO_FILL
+ );
+ addDrawingOrder(pat);
+ }
+
+ /**
+ * Sets the character set to use
+ * @param fontReference the character set (font) reference
+ */
+ public void setCharacterSet(int fontReference) {
+ addDrawingOrder(new GraphicsSetCharacterSet(fontReference));
+ }
+
+ /**
+ * Adds a line at the given x/y coordinates
+ * @param coords the x/y coordinates (can be a series)
+ */
+ public void addLine(int[] coords) {
+ addDrawingOrder(new GraphicsLine(coords));
+ }
+
+ /**
+ * Adds a box at the given coordinates
+ * @param coords the x/y coordinates
+ */
+ public void addBox(int[] coords) {
+ addDrawingOrder(new GraphicsBox(coords));
+ }
+
+ /**
+ * Adds a fillet (curve) at the given coordinates
+ * @param coords the x/y coordinates
+ */
+ public void addFillet(int[] coords) {
+ addDrawingOrder(new GraphicsFillet(coords));
+ }
+
+ /**
+ * Sets the arc parameters
+ * @param xmaj the maximum value of the x coordinate
+ * @param ymin the minimum value of the y coordinate
+ * @param xmin the minimum value of the x coordinate
+ * @param ymaj the maximum value of the y coordinate
+ */
+ public void setArcParams(int xmaj, int ymin, int xmin, int ymaj) {
+ addDrawingOrder(new GraphicsSetArcParameters(xmaj, ymin, xmin, ymaj));
+ }
+
+ /**
+ * Adds an arc
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param mh the integer portion of the multiplier
+ * @param mhr the fractional portion of the multiplier
+ */
+ public void addFullArc(int x, int y, int mh, int mhr) {
+ addDrawingOrder(new GraphicsFullArc(x, y, mh, mhr));
+ }
+
+ /**
+ * Adds an image
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the image width
+ * @param height the image height
+ * @param rawData the image data
+ */
+ public void addImage(int x, int y, int width, int height, byte[] rawData) {
+ addDrawingOrder(new GraphicsImageBegin(x, y, width, height));
+ for (int startIndex = 0;
+ startIndex <= rawData.length;
+ startIndex += GraphicsImageData.MAX_DATA_LEN) {
+ addDrawingOrder(new GraphicsImageData(rawData, startIndex));
+ }
+ addDrawingOrder(new GraphicsImageEnd());
+ }
+
+ /**
+ * Adds a string
+ * @param str the string
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public void addString(String str, int x, int y) {
+ addDrawingOrder(new GraphicsString(str, x, y));
+ }
+
+ /**
+ * Begins a graphics area (start of fill)
+ */
+ public void beginArea() {
+ if (graphicsData == null) {
+ newData();
+ }
+ graphicsData.beginArea();
+ }
+
+ /**
+ * Ends a graphics area (end of fill)
+ */
+ public void endArea() {
+ if (graphicsData != null) {
+ graphicsData.endArea();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsObject";
+ }
+
+ /**
+ * Creates a new graphics segment
+ */
+ public void newSegment() {
+ getData().newSegment();
+ }
+} \ No newline at end of file
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 e6f9f1857..e7fd538e1 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java
+++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java
@@ -18,43 +18,45 @@
/* $Id$ */
package org.apache.fop.render.afp.modca;
+
import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;
/**
+ * Image content IOCA object
*/
public class ImageContent extends AbstractAFPObject {
/**
* The image size parameter
*/
- private ImageSizeParameter _imageSizeParameter = null;
+ private ImageSizeParameter imageSizeParam = null;
/**
* The image encoding
*/
- private byte _encoding = 0x03;
+ private byte encoding = 0x03;
/**
* The image ide size
*/
- private byte _size = 1;
+ private byte size = 1;
/**
* The image compression
*/
- private byte _compression = (byte)0xC0;
+ private byte compression = (byte)0xC0;
/**
* The image color model
*/
- private byte _colorModel = 0x01;
+ private byte colorModel = 0x01;
/**
* The image data
*/
- private byte _data[] = null;
+ private byte[] data = null;
/**
* Constructor for the image content
@@ -72,60 +74,60 @@ public class ImageContent extends AbstractAFPObject {
* @param vsize The vertival size of the image.
*/
public void setImageSize(int hresol, int vresol, int hsize, int vsize) {
- _imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize);
+ this.imageSizeParam = new ImageSizeParameter(hresol, vresol, hsize, vsize);
}
/**
* Sets the image encoding.
- * @param encoding The image encoding.
+ * @param enc The image encoding.
*/
- public void setImageEncoding(byte encoding) {
- _encoding = encoding;
+ public void setImageEncoding(byte enc) {
+ this.encoding = enc;
}
/**
* Sets the image compression.
- * @param compression The image compression.
+ * @param comp The image compression.
*/
- public void setImageCompression(byte compression) {
- _compression = compression;
+ public void setImageCompression(byte comp) {
+ this.compression = comp;
}
/**
* Sets the image IDE size.
- * @param size The IDE size.
+ * @param siz The IDE size.
*/
- public void setImageIDESize(byte size) {
- _size = size;
+ public void setImageIDESize(byte siz) {
+ this.size = siz;
}
/**
* Sets the image IDE color model.
- * @param colorModel the IDE color model.
+ * @param model the IDE color model.
*/
- public void setImageIDEColorModel(byte colorModel) {
- _colorModel = colorModel;
+ public void setImageIDEColorModel(byte model) {
+ this.colorModel = model;
}
/**
* Set the data of the image.
+ * @param dat the image data
*/
- public void setImageData(byte data[]) {
- _data = data;
+ public void setImageData(byte[] dat) {
+ this.data = dat;
}
/**
* Accessor method to write the AFP datastream for the Image Content
* @param os The stream to write to
- * @throws java.io.IOException
+ * @throws java.io.IOException if an I/O exception occurs
*/
- public void writeDataStream(OutputStream os)
- throws IOException {
+ public void writeDataStream(OutputStream os) throws IOException {
writeStart(os);
- if (_imageSizeParameter != null) {
- _imageSizeParameter.writeDataStream(os);
+ if (imageSizeParam != null) {
+ imageSizeParam.writeDataStream(os);
}
os.write(getImageEncodingParameter());
@@ -136,12 +138,12 @@ public class ImageContent extends AbstractAFPObject {
os.write(getExternalAlgorithmParameter());
- if (_data != null) {
+ if (data != null) {
int off = 0;
- while (off < _data.length) {
- int len = Math.min(30000, _data.length - off);
+ while (off < data.length) {
+ int len = Math.min(30000, data.length - off);
os.write(getImageDataStart(len));
- os.write(_data, off, len);
+ os.write(data, off, len);
off += len;
}
}
@@ -154,33 +156,25 @@ public class ImageContent extends AbstractAFPObject {
* Helper method to write the start of the Image Content.
* @param os The stream to write to
*/
- private void writeStart(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
+ private void writeStart(OutputStream os) throws IOException {
+ byte[] startData = new byte[] {
(byte)0x91, // ID
0x01, // Length
(byte)0xff, // Object Type = IOCA Image Object
};
-
- os.write(data);
-
+ os.write(startData);
}
/**
* Helper method to write the end of the Image Content.
* @param os The stream to write to
*/
- private void writeEnd(OutputStream os)
- throws IOException {
-
- byte[] data = new byte[] {
+ private void writeEnd(OutputStream os) throws IOException {
+ byte[] endData = new byte[] {
(byte)0x93, // ID
0x00, // Length
};
-
- os.write(data);
-
+ os.write(endData);
}
/**
@@ -188,21 +182,16 @@ public class ImageContent extends AbstractAFPObject {
* @return byte[] The data stream.
*/
private byte[] getImageDataStart(int len) {
-
- byte[] data = new byte[] {
+ byte[] imageDataStartData = new byte[] {
(byte)0xFE, // ID
(byte)0x92, // ID
0x00, // Length
0x00, // Length
};
-
byte[] l = BinaryUtils.convert(len, 2);
- data[2] = l[0];
- data[3] = l[1];
-
-
- return data;
-
+ imageDataStartData[2] = l[0];
+ imageDataStartData[3] = l[1];
+ return imageDataStartData;
}
/**
@@ -210,16 +199,13 @@ public class ImageContent extends AbstractAFPObject {
* @return byte[] The data stream.
*/
private byte[] getImageEncodingParameter() {
-
- byte[] data = new byte[] {
+ byte[] imageEncParamData = new byte[] {
(byte)0x95, // ID
0x02, // Length
- _encoding,
+ encoding,
0x01, // RECID
};
-
- return data;
-
+ return imageEncParamData;
}
/**
@@ -227,9 +213,8 @@ public class ImageContent extends AbstractAFPObject {
* @return byte[] The data stream.
*/
private byte[] getExternalAlgorithmParameter() {
-
- if (_encoding == (byte)0x83 && _compression != 0) {
- byte[] data = new byte[] {
+ if (encoding == (byte)0x83 && compression != 0) {
+ byte[] extAlgParamData = new byte[] {
(byte)0x95, // ID
0x00, // Length
0x10, // ALGTYPE = Compression Algorithm
@@ -238,13 +223,13 @@ public class ImageContent extends AbstractAFPObject {
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
- _compression, // MARKER
+ compression, // MARKER
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
};
- data[1] = (byte)(data.length - 2);
- return data;
+ extAlgParamData[1] = (byte)(extAlgParamData.length - 2);
+ return extAlgParamData;
}
return new byte[0];
}
@@ -254,15 +239,12 @@ public class ImageContent extends AbstractAFPObject {
* @return byte[] The data stream.
*/
private byte[] getImageIDESizeParameter() {
-
- byte[] data = new byte[] {
+ byte[] imageIDESizeParamData = new byte[] {
(byte)0x96, // ID
0x01, // Length
- _size,
+ size,
};
-
- return data;
-
+ return imageIDESizeParamData;
}
/**
@@ -270,15 +252,14 @@ public class ImageContent extends AbstractAFPObject {
* @return byte[] The data stream.
*/
private byte[] getIDEStructureParameter() {
-
- if (_colorModel != 0 && _size == 24) {
- byte bits = (byte)(_size / 3);
- byte[] data = new byte[] {
+ if (colorModel != 0 && size == 24) {
+ byte bits = (byte)(size / 3);
+ byte[] ideStructParamData = new byte[] {
(byte)0x9B, // ID
0x00, // Length
0x00, // FLAGS
0x00, // Reserved
- _colorModel, // COLOR MODEL
+ colorModel, // COLOR MODEL
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
@@ -286,10 +267,9 @@ public class ImageContent extends AbstractAFPObject {
bits,
bits,
};
- data[1] = (byte)(data.length - 2);
- return data;
+ ideStructParamData[1] = (byte)(ideStructParamData.length - 2);
+ return ideStructParamData;
}
return new byte[0];
}
-
}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
index 9250f0c7f..d1c2c11c7 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
@@ -27,10 +27,17 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class ImageDataDescriptor extends AbstractAFPObject {
- private int _xresol = 0;
- private int _yresol = 0;
- private int _width = 0;
- private int _height = 0;
+ /** x resolution */
+ private int xresol = 0;
+
+ /** y resolution */
+ private int yresol = 0;
+
+ /** width */
+ private int width = 0;
+
+ /** height */
+ private int height = 0;
/**
* Constructor for a ImageDataDescriptor for the specified
@@ -41,26 +48,25 @@ public class ImageDataDescriptor extends AbstractAFPObject {
* @param height The height of the height.
*/
public ImageDataDescriptor(int xresol, int yresol, int width, int height) {
-
- _xresol = xresol;
- _yresol = yresol;
- _width = width;
- _height = height;
-
+ this.xresol = xresol;
+ this.yresol = yresol;
+ this.width = width;
+ this.height = height;
}
/**
- * Accessor method to write the AFP datastream for the Image Data Descriptor
- * @param os The stream to write to
- * @throws java.io.IOException
+ * {@inheritDoc}
*/
- public void writeDataStream(OutputStream os)
- throws IOException {
-
+ public void writeDataStream(OutputStream os) throws IOException {
+ byte[] len = BinaryUtils.convert(21, 2);
+ byte[] xres = BinaryUtils.convert(xresol, 2);
+ byte[] yres = BinaryUtils.convert(yresol, 2);
+ byte[] w = BinaryUtils.convert(width, 2);
+ byte[] h = BinaryUtils.convert(height, 2);
byte[] data = new byte[] {
0x5A,
- 0x00,
- 0x20,
+ len[0],
+ len[1],
(byte) 0xD3,
(byte) 0xA6,
(byte) 0xFB,
@@ -68,42 +74,19 @@ public class ImageDataDescriptor extends AbstractAFPObject {
0x00, // Reserved
0x00, // Reserved
0x00, // Unit base - 10 Inches
- 0x00, // XRESOL
- 0x00, //
- 0x00, // YRESOL
- 0x00, //
- 0x00, // XSIZE
- 0x00, //
- 0x00, // YSIZE
- 0x00, //
+ xres[0], // XRESOL
+ xres[1], //
+ yres[0], // YRESOL
+ yres[1], //
+ w[0], // XSIZE
+ w[1], //
+ h[0], // YSIZE
+ h[1], //
(byte)0xF7, // ID = Set IOCA Function Set
0x02, // Length
0x01, // Category = Function set identifier
0x0B, // FCNSET = IOCA FS 11
};
-
- byte[] l = BinaryUtils.convert(data.length - 1, 2);
- data[1] = l[0];
- data[2] = l[1];
-
- byte[] x = BinaryUtils.convert(_xresol, 2);
- data[10] = x[0];
- data[11] = x[1];
-
- byte[] y = BinaryUtils.convert(_yresol, 2);
- data[12] = y[0];
- data[13] = y[1];
-
- byte[] w = BinaryUtils.convert(_width, 2);
- data[14] = w[0];
- data[15] = w[1];
-
- byte[] h = BinaryUtils.convert(_height, 2);
- data[16] = h[0];
- data[17] = h[1];
-
os.write(data);
-
}
-
}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageObject.java b/src/java/org/apache/fop/render/afp/modca/ImageObject.java
index 66c46c872..c13fcbb59 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/ImageObject.java
@@ -27,12 +27,7 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
/**
* An IOCA Image Data Object
*/
-public class ImageObject extends AbstractNamedAFPObject {
-
- /**
- * The object environment group
- */
- private ObjectEnvironmentGroup objectEnvironmentGroup = null;
+public class ImageObject extends AbstractDataObject {
/**
* The image segment
@@ -45,34 +40,7 @@ public class ImageObject extends AbstractNamedAFPObject {
* @param name The name of the image.
*/
public ImageObject(String name) {
-
super(name);
-
- }
-
- /**
- * Sets the image display area position and size.
- *
- * @param x
- * the x position of the image
- * @param y
- * the y position of the image
- * @param w
- * the width of the image
- * @param h
- * the height of the image
- * @param r
- * the rotation of the image
- * @param wr
- * the width resolution of the image
- * @param hr
- * the height resolution of the image
- */
- public void setImageViewport(int x, int y, int w, int h, int r, int wr, int hr) {
- if (objectEnvironmentGroup == null) {
- objectEnvironmentGroup = new ObjectEnvironmentGroup();
- }
- objectEnvironmentGroup.setObjectArea(x, y, w, h, r, wr, hr);
}
/**
@@ -149,24 +117,16 @@ public class ImageObject extends AbstractNamedAFPObject {
}
/**
- * Sets the ObjectEnvironmentGroup.
- * @param objectEnvironmentGroup The objectEnvironmentGroup to set
- */
- public void setObjectEnvironmentGroup(ObjectEnvironmentGroup objectEnvironmentGroup) {
- this.objectEnvironmentGroup = objectEnvironmentGroup;
- }
-
- /**
* Helper method to return the start of the image object.
+ * @param len the length of this ipd start
* @return byte[] The data stream.
*/
private byte[] getIPDStart(int len) {
-
+ byte[] l = BinaryUtils.convert(len + 8, 2);
byte[] data = new byte[] {
-
0x5A, // Structured field identifier
- 0x00, // Length byte 1
- 0x10, // Length byte 2
+ l[0], // Length byte 1
+ l[1], // Length byte 2
(byte) 0xD3, // Structured field id byte 1
(byte) 0xEE, // Structured field id byte 2
(byte) 0xFB, // Structured field id byte 3
@@ -174,29 +134,14 @@ public class ImageObject extends AbstractNamedAFPObject {
0x00, // Reserved
0x00, // Reserved
};
-
- byte[] l = BinaryUtils.convert(len + 8, 2);
- data[1] = l[0];
- data[2] = l[1];
-
return data;
-
}
/**
- * Accessor method to write the AFP datastream for the Image Object
- * @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 (objectEnvironmentGroup != null) {
- objectEnvironmentGroup.writeDataStream(os);
- }
-
+ protected void writeContent(OutputStream os) throws IOException {
+ super.writeContent(os);
if (imageSegment != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
imageSegment.writeDataStream(baos);
@@ -209,20 +154,13 @@ public class ImageObject extends AbstractNamedAFPObject {
off += len;
}
}
-
- writeEnd(os);
-
}
/**
- * Helper method to write the start of the 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
@@ -232,26 +170,19 @@ public class ImageObject 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 Image Object.
* @param os The stream to write to
+ * @throws IOException in the event
*/
- 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
@@ -261,15 +192,9 @@ public class ImageObject 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/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
index 7d6cc18aa..5f8454fa8 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
+++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
@@ -18,6 +18,7 @@
/* $Id$ */
package org.apache.fop.render.afp.modca;
+
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
@@ -67,15 +68,12 @@ 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) {
@@ -162,24 +160,18 @@ public class ImageSegment extends AbstractAFPObject {
* @throws java.io.IOException if an I/O exception occurred
*/
public void writeDataStream(OutputStream os) throws IOException {
-
writeStart(os);
-
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
*/
- private void writeStart(OutputStream os)
- throws IOException {
-
+ private void writeStart(OutputStream os) throws IOException {
byte[] data = new byte[] {
0x70, // ID
0x04, // Length
@@ -188,13 +180,9 @@ public class ImageSegment extends AbstractAFPObject {
0x00, // Name byte 3
0x00, // Name byte 4
};
-
for (int i = 0; i < nameBytes.length; i++) {
-
data[2 + i] = nameBytes[i];
-
}
-
os.write(data);
}
@@ -204,7 +192,6 @@ public class ImageSegment extends AbstractAFPObject {
* @param os The stream to write to
*/
private 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/ObjectAreaDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
index 7c940148b..aa35db10e 100644
--- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
@@ -35,11 +35,11 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
* and object height.
* @param width The page width.
* @param height The page height.
- * @param widthResolution The page width resolution.
- * @param heightResolution The page height resolution.
+ * @param widthRes The page width resolution.
+ * @param heightRes The page height resolution.
*/
- public ObjectAreaDescriptor(int width, int height, int widthResolution, int heightResolution) {
- super(width, height, widthResolution, heightResolution);
+ public ObjectAreaDescriptor(int width, int height, int widthRes, int heightRes) {
+ super(width, height, widthRes, heightRes);
}
/**
@@ -47,8 +47,7 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
* @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 {
byte[] data = new byte[29];
data[0] = 0x5A;
@@ -72,12 +71,12 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
data[15] = 0x00; // YaoBase = 10 inches
// XaoUnits
- byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(this.widthRes * 10, 2);
data[16] = xdpi[0];
data[17] = xdpi[1];
// YaoUnits
- byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(this.heightRes * 10, 2);
data[18] = ydpi[0];
data[19] = ydpi[1];
@@ -85,18 +84,16 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
data[21] = 0x4C; // tid = Object Area Size
data[22] = 0x02; // Size Type
- byte[] x = BinaryUtils.convert(width, 3);
+ byte[] x = BinaryUtils.convert(this.width, 3);
data[23] = x[0];
data[24] = x[1];
data[25] = x[2];
- byte[] y = BinaryUtils.convert(height, 3);
+ byte[] y = BinaryUtils.convert(this.height, 3);
data[26] = y[0];
data[27] = y[1];
data[28] = y[2];
os.write(data);
-
}
-
} \ No newline at end of file
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 e500c1269..688288063 100644
--- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java
+++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java
@@ -30,9 +30,9 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class ObjectAreaPosition extends AbstractAFPObject {
- private int _x = 0;
- private int _y = 0;
- private int _rot = 0;
+ private int x;
+ private int y;
+ private int rotation;
/**
* Construct an object area position for the specified object y, y position.
@@ -41,24 +41,25 @@ public class ObjectAreaPosition extends AbstractAFPObject {
* @param rotation The coordinate system rotation (must be 0, 90, 180, 270).
*/
public ObjectAreaPosition(int x, int y, int rotation) {
-
- _x = x;
- _y = y;
- _rot = rotation;
+ this.x = x;
+ this.y = y;
+ this.rotation = rotation;
}
/**
* Accessor method to write the AFP datastream for the Object Area Position
* @param os The stream to write to
- * @throws java.io.IOException
+ * @throws java.io.IOException in the event that an I/O exception of some sort has occurred.
*/
- public void writeDataStream(OutputStream os)
- throws IOException {
+ public void writeDataStream(OutputStream os) throws IOException {
+ byte[] len = BinaryUtils.convert(32, 2);
+ byte[] xcoord = BinaryUtils.convert(x, 3);
+ byte[] ycoord = BinaryUtils.convert(y, 3);
byte[] data = new byte[] {
0x5A,
- 0x00, // Length
- 0x20, // Length
+ len[0], // Length
+ len[1], // Length
(byte) 0xD3,
(byte) 0xAC,
(byte) 0x6B,
@@ -67,15 +68,15 @@ public class ObjectAreaPosition extends AbstractAFPObject {
0x00, // Reserved
0x01, // OAPosID = 1
0x17, // RGLength = 23
- 0x00, // XoaOSet
- 0x00,
- 0x00,
- 0x00, // YoaOSet
- 0x00,
- 0x00,
- (byte)(_rot / 2), // XoaOrent
+ xcoord[0], // XoaOSet
+ xcoord[1],
+ xcoord[2],
+ ycoord[0], // YoaOSet
+ ycoord[1],
+ ycoord[2],
+ (byte)(rotation / 2), // XoaOrent
0x00,
- (byte)(_rot / 2 + 45), // YoaOrent
+ (byte)(rotation / 2 + 45), // YoaOrent
0x00,
0x00, // Reserved
0x00, // XocaOSet
@@ -88,23 +89,9 @@ public class ObjectAreaPosition extends AbstractAFPObject {
0x00,
0x2D, // YocaOrent
0x00,
- 0x01, // RefCSys
+ 0x00, // RefCSys
};
-
- byte[] l = BinaryUtils.convert(data.length - 1, 2);
- data[1] = l[0];
- data[2] = l[1];
-
- byte[] x = BinaryUtils.convert(_x, 3);
- data[11] = x[0];
- data[12] = x[1];
- data[13] = x[2];
-
- byte[] y = BinaryUtils.convert(_y, 3);
- data[14] = y[0];
- data[15] = y[1];
- data[16] = y[2];
-
+
os.write(data);
}
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 d6b029122..27fe7c270 100644
--- a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java
+++ b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java
@@ -18,6 +18,7 @@
/* $Id$ */
package org.apache.fop.render.afp.modca;
+
import java.io.IOException;
import java.io.OutputStream;
@@ -33,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 AbstractNamedAFPObject {
+public final class ObjectEnvironmentGroup extends AbstractStructuredAFPObject {
/**
* Default name for the object environment group
@@ -56,12 +57,15 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
private ImageDataDescriptor imageDataDescriptor = null;
/**
+ * The GraphicsDataDescriptor for the object environment group
+ */
+ private GraphicsDataDescriptor graphicsDataDescriptor = null;
+
+ /**
* Default constructor for the ObjectEnvironmentGroup.
*/
public ObjectEnvironmentGroup() {
-
this(DEFAULT_NAME);
-
}
/**
@@ -70,9 +74,7 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
* @param name the object environment group name
*/
public ObjectEnvironmentGroup(String name) {
-
super(name);
-
}
/**
@@ -82,15 +84,14 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
* @param width the object width
* @param height the object height
* @param rotation the object orientation
- * @param widthResolution the object resolution width
- * @param heightResolution the object resolution height
+ * @param widthRes the object resolution width
+ * @param heightRes the object resolution height
*/
- public void setObjectArea(int x, int y, int width, int height, int rotation,
- int widthResolution, int heightResolution) {
-
- objectAreaDescriptor = new ObjectAreaDescriptor(width, height,
- widthResolution, heightResolution);
- objectAreaPosition = new ObjectAreaPosition(x, y, rotation);
+ public void setObjectArea(int x, int y, int width, int height,
+ int widthRes, int heightRes, int rotation) {
+ this.objectAreaDescriptor = new ObjectAreaDescriptor(width, height,
+ widthRes, heightRes);
+ this.objectAreaPosition = new ObjectAreaPosition(x, y, rotation);
}
@@ -102,40 +103,28 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
* @param height the image height
*/
public void setImageData(int xresol, int yresol, int width, int height) {
- imageDataDescriptor = new ImageDataDescriptor(xresol, yresol, width, height);
+ this.imageDataDescriptor = new ImageDataDescriptor(xresol, yresol, width, height);
}
/**
- * Accessor method to obtain write the AFP datastream for
- * the object environment group.
- * @param os The stream to write to
- * @throws java.io.IOException throw if an I/O exception of some sort has occurred
+ * Set the graphics data descriptor.
+ * @param xresol the x resolution of the graphics window
+ * @param yresol the y resolution of the graphics window
+ * @param xlwind the left edge of the graphics window
+ * @param xrwind the right edge of the graphics window
+ * @param ybwind the top edge of the graphics window
+ * @param ytwind the bottom edge of the graphics window
*/
- public void writeDataStream(OutputStream os)
- throws IOException {
-
-
- writeStart(os);
-
- objectAreaDescriptor.writeDataStream(os);
-
- objectAreaPosition.writeDataStream(os);
-
- if (imageDataDescriptor != null) {
- imageDataDescriptor.writeDataStream(os);
- }
-
- writeEnd(os);
-
+ public void setGraphicsData(int xresol, int yresol,
+ int xlwind, int xrwind, int ybwind, int ytwind) {
+ this.graphicsDataDescriptor = new GraphicsDataDescriptor(xresol, yresol,
+ xlwind, xrwind, ybwind, ytwind);
}
/**
- * Helper method to write the start of the object 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[] {
0x5A, // Structured field identifier
0x00, // Length byte 1
@@ -146,53 +135,57 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
0x00, // Flags
0x00, // Reserved
0x00, // Reserved
- 0x00, // Name
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
- 0x00, //
+ nameBytes[0], // Name
+ nameBytes[1], //
+ nameBytes[2], //
+ nameBytes[3], //
+ nameBytes[4], //
+ nameBytes[5], //
+ nameBytes[6], //
+ nameBytes[7] //
};
-
- for (int i = 0; i < nameBytes.length; i++) {
-
- data[9 + i] = nameBytes[i];
-
- }
-
os.write(data);
-
}
/**
- * Helper method to write the end of the object environment group.
- * @param os The stream to write to
+ * {@inheritDoc}
*/
- private 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) 0xC7; // 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++) {
+ public void writeContent(OutputStream os) throws IOException {
+ objectAreaDescriptor.writeDataStream(os);
+ objectAreaPosition.writeDataStream(os);
- data[9 + i] = nameBytes[i];
+ if (imageDataDescriptor != null) {
+ imageDataDescriptor.writeDataStream(os);
+ }
+ if (graphicsDataDescriptor != null) {
+ graphicsDataDescriptor.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) 0xC7, // Structured field id byte 3
+ 0x00, // Flags
+ 0x00, // Reserved
+ 0x00, // Reserved
+ nameBytes[0], // Name
+ nameBytes[1], //
+ nameBytes[2], //
+ nameBytes[3], //
+ nameBytes[4], //
+ nameBytes[5], //
+ nameBytes[6], //
+ nameBytes[7], //
+ };
os.write(data);
-
}
-
-} \ No newline at end of file
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java
index 1cdec7616..ffa5f3c85 100644
--- a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java
@@ -35,11 +35,11 @@ public class PageDescriptor extends AbstractDescriptor {
* and page height.
* @param width The page width.
* @param height The page height.
- * @param widthResolution The page width resolution
- * @param heightResolution The page height resolution
+ * @param widthRes The page width resolution
+ * @param heightRes The page height resolution
*/
- public PageDescriptor(int width, int height, int widthResolution, int heightResolution) {
- super(width, height, widthResolution, heightResolution);
+ public PageDescriptor(int width, int height, int widthRes, int heightRes) {
+ super(width, height, widthRes, heightRes);
}
/**
@@ -68,12 +68,12 @@ public class PageDescriptor extends AbstractDescriptor {
data[10] = 0x00; // YpgBase = 10 inches
// XpgUnits
- byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2);
data[11] = xdpi[0];
data[12] = xdpi[1];
// YpgUnits
- byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2);
data[13] = ydpi[0];
data[14] = ydpi[1];
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 5b9a00a89..a9a4581e7 100644
--- a/src/java/org/apache/fop/render/afp/modca/PageObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java
@@ -62,15 +62,15 @@ public class PageObject extends AbstractPageObject {
* the height of the page.
* @param rotation
* the rotation of the page.
- * @param widthResolution
+ * @param widthRes
* the width resolution of the page.
- * @param heightResolution
+ * @param heightRes
* the height resolution of the page.
*/
public PageObject(String name, int width, int height, int rotation,
- int widthResolution, int heightResolution) {
+ int widthRes, int heightRes) {
- super(name, width, height, rotation, widthResolution, heightResolution);
+ super(name, width, height, rotation, widthRes, heightRes);
}
diff --git a/src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java
new file mode 100644
index 000000000..8da724f36
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/PreparedAFPObject.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * An AFP object which is able to know its own data length before write()
+ */
+public interface PreparedAFPObject {
+ /**
+ * @return the current data length of this container including
+ * all enclosed GOCA drawing objects
+ */
+ int getDataLength();
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
index 98beb96f7..30a78d6c9 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
@@ -56,42 +56,42 @@ public class PresentationTextData extends AbstractAFPObject {
/**
* The afp data relating to this presentaion text data.
*/
- private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024);
+ private ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
/**
* The current x coordinate.
*/
- private int _currentXCoordinate = -1;
+ private int currentXCoordinate = -1;
/**
* The current y cooridnate
*/
- private int _currentYCoordinate = -1;
+ private int currentYCoordinate = -1;
/**
* The current font
*/
- private String _currentFont = "";
+ private String currentFont = "";
/**
* The current orientation
*/
- private int _currentOrientation = 0;
+ private int currentOrientation = 0;
/**
* The current color
*/
- private Color _currentColor = new Color(0, 0, 0);
+ private Color currentColor = new Color(0, 0, 0);
/**
* The current variable space increment
*/
- private int _currentVariableSpaceCharacterIncrement = 0;
+ private int currentVariableSpaceCharacterIncrement = 0;
/**
* The current inter character adjustment
*/
- private int _currentInterCharacterAdjustment = 0;
+ private int currentInterCharacterAdjustment = 0;
/**
* Default constructor for the PresentationTextData.
@@ -112,7 +112,7 @@ public class PresentationTextData extends AbstractAFPObject {
*/
public PresentationTextData(boolean controlInd) {
- _baos.write(new byte[] { 0x5A, // Structured field identifier
+ baos.write(new byte[] {0x5A, // Structured field identifier
0x00, // Record length byte 1
0x00, // Record length byte 2
(byte) 0xD3, // PresentationTextData identifier byte 1
@@ -124,7 +124,7 @@ public class PresentationTextData extends AbstractAFPObject {
}, 0, 9);
if (controlInd) {
- _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2);
+ baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2);
}
}
@@ -142,13 +142,13 @@ public class PresentationTextData extends AbstractAFPObject {
private void setCodedFont(byte font, ByteArrayOutputStream afpdata) {
// Avoid unnecessary specification of the font
- if (String.valueOf(font).equals(_currentFont)) {
+ if (String.valueOf(font).equals(currentFont)) {
return;
} else {
- _currentFont = String.valueOf(font);
+ currentFont = String.valueOf(font);
}
- afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3);
+ afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3);
}
@@ -167,9 +167,9 @@ public class PresentationTextData extends AbstractAFPObject {
byte[] b = BinaryUtils.convert(coordinate, 2);
- afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4);
+ afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4);
- _currentXCoordinate = coordinate;
+ currentXCoordinate = coordinate;
}
@@ -188,9 +188,9 @@ public class PresentationTextData extends AbstractAFPObject {
byte[] b = BinaryUtils.convert(coordinate, 2);
- afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4);
+ afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4);
- _currentYCoordinate = coordinate;
+ currentYCoordinate = coordinate;
}
@@ -214,7 +214,7 @@ public class PresentationTextData extends AbstractAFPObject {
"Transparent data is longer than 253 bytes: " + data);
}
- afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, },
+ afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB},
0, 2);
afpdata.write(data, 0, data.length);
@@ -236,7 +236,7 @@ public class PresentationTextData extends AbstractAFPObject {
private void drawBaxisRule(int length, int width,
ByteArrayOutputStream afpdata) {
- afpdata.write(new byte[] { 0x07, // Length
+ afpdata.write(new byte[] {0x07, // Length
(byte) 0xE7, // Type
}, 0, 2);
@@ -266,7 +266,7 @@ public class PresentationTextData extends AbstractAFPObject {
private void drawIaxisRule(int length, int width,
ByteArrayOutputStream afpdata) {
- afpdata.write(new byte[] { 0x07, // Length
+ afpdata.write(new byte[] {0x07, // Length
(byte) 0xE5, // Type
}, 0, 2);
@@ -284,7 +284,7 @@ public class PresentationTextData extends AbstractAFPObject {
/**
* Create the presentation text data for the byte array of data.
*
- * @param fontNumber
+ * @param fontReference
* The font resource identifier.
* @param x
* The x coordinate for the text data.
@@ -300,64 +300,64 @@ public class PresentationTextData extends AbstractAFPObject {
* The inter character adjustment.
* @param data
* The text data to be created.
- * @throws MaximumSizeExceededException
+ * @throws MaximumSizeExceededException if the maximum size is exceeded
*/
- public void createTextData(int fontNumber, int x, int y, int orientation,
+ public void createTextData(int fontReference, int x, int y, int orientation,
Color col, int vsci, int ica, byte[] data)
throws MaximumSizeExceededException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
- if (_currentOrientation != orientation) {
+ if (currentOrientation != orientation) {
setTextOrientation(orientation, afpdata);
- _currentOrientation = orientation;
- _currentXCoordinate = -1;
- _currentYCoordinate = -1;
+ currentOrientation = orientation;
+ currentXCoordinate = -1;
+ currentYCoordinate = -1;
}
// Avoid unnecessary specification of the Y co-ordinate
- if (y != _currentYCoordinate) {
+ if (y != currentYCoordinate) {
absoluteMoveBaseline(y, afpdata);
- _currentXCoordinate = -1;
+ currentXCoordinate = -1;
}
// Avoid unnecessary specification of the X co-ordinate
- if (x != _currentXCoordinate) {
+ if (x != currentXCoordinate) {
absoluteMoveInline(x, afpdata);
}
// Avoid unnecessary specification of the variable space increment
- if (vsci != _currentVariableSpaceCharacterIncrement) {
+ if (vsci != currentVariableSpaceCharacterIncrement) {
setVariableSpaceCharacterIncrement(vsci, afpdata);
- _currentVariableSpaceCharacterIncrement = vsci;
+ currentVariableSpaceCharacterIncrement = vsci;
}
// Avoid unnecessary specification of the inter character adjustment
- if (ica != _currentInterCharacterAdjustment) {
+ if (ica != currentInterCharacterAdjustment) {
setInterCharacterAdjustment(ica, afpdata);
- _currentInterCharacterAdjustment = ica;
+ currentInterCharacterAdjustment = ica;
}
// Avoid unnecessary specification of the text color
- if (!col.equals(_currentColor)) {
+ if (!col.equals(currentColor)) {
setExtendedTextColor(col, afpdata);
- _currentColor = col;
+ currentColor = col;
}
- setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata);
+ setCodedFont(BinaryUtils.convert(fontReference)[0], afpdata);
addTransparentData(data, afpdata);
- _currentXCoordinate = -1;
+ currentXCoordinate = -1;
int s = afpdata.size();
- if (_baos.size() + s > MAX_SIZE) {
- _currentXCoordinate = -1;
- _currentYCoordinate = -1;
+ if (baos.size() + s > MAX_SIZE) {
+ currentXCoordinate = -1;
+ currentYCoordinate = -1;
throw new MaximumSizeExceededException();
}
byte[] outputdata = afpdata.toByteArray();
- _baos.write(outputdata, 0, outputdata.length);
+ baos.write(outputdata, 0, outputdata.length);
}
@@ -379,30 +379,31 @@ public class PresentationTextData extends AbstractAFPObject {
* The orientation of the text data.
* @param col
* The text color.
+ * @throws MaximumSizeExceededException if the maximum size is exceeded
*/
public void createLineData(int x1, int y1, int x2, int y2, int thickness,
int orientation, Color col) throws MaximumSizeExceededException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
- if (_currentOrientation != orientation) {
+ if (currentOrientation != orientation) {
setTextOrientation(orientation, afpdata);
- _currentOrientation = orientation;
+ currentOrientation = orientation;
}
// Avoid unnecessary specification of the Y coordinate
- if (y1 != _currentYCoordinate) {
+ if (y1 != currentYCoordinate) {
absoluteMoveBaseline(y1, afpdata);
}
// Avoid unnecessary specification of the X coordinate
- if (x1 != _currentXCoordinate) {
+ if (x1 != currentXCoordinate) {
absoluteMoveInline(x1, afpdata);
}
- if (!col.equals(_currentColor)) {
+ if (!col.equals(currentColor)) {
setExtendedTextColor(col, afpdata);
- _currentColor = col;
+ currentColor = col;
}
if (y1 == y2) {
@@ -415,14 +416,14 @@ public class PresentationTextData extends AbstractAFPObject {
int s = afpdata.size();
- if (_baos.size() + s > MAX_SIZE) {
- _currentXCoordinate = -1;
- _currentYCoordinate = -1;
+ if (baos.size() + s > MAX_SIZE) {
+ currentXCoordinate = -1;
+ currentYCoordinate = -1;
throw new MaximumSizeExceededException();
}
byte[] outputdata = afpdata.toByteArray();
- _baos.write(outputdata, 0, outputdata.length);
+ baos.write(outputdata, 0, outputdata.length);
}
@@ -443,7 +444,7 @@ public class PresentationTextData extends AbstractAFPObject {
private void setTextOrientation(int orientation,
ByteArrayOutputStream afpdata) {
- afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2);
+ afpdata.write(new byte[] {0x06, (byte) 0xF7}, 0, 2);
switch (orientation) {
case 90:
@@ -559,12 +560,11 @@ public class PresentationTextData extends AbstractAFPObject {
* Accessor method to write the AFP datastream for
* the text data.
* @param os The stream to write to
- * @throws java.io.IOException
+ * @throws java.io.IOException if an I/O exception occurred
*/
- public void writeDataStream(OutputStream os)
- throws IOException {
+ public void writeDataStream(OutputStream os) throws IOException {
- byte[] data = _baos.toByteArray();
+ byte[] data = baos.toByteArray();
byte[] size = BinaryUtils.convert(data.length - 1, 2);
data[1] = size[0];
data[2] = size[1];
@@ -580,7 +580,7 @@ public class PresentationTextData extends AbstractAFPObject {
* presentation text data objects, but must eventually be terminated. This
* method terminates the control sequence.
*
- * @throws MaximumSizeExceededException
+ * @throws MaximumSizeExceededException if the maximum size is exceeded
*/
public void endControlSequence() throws MaximumSizeExceededException {
@@ -588,12 +588,10 @@ public class PresentationTextData extends AbstractAFPObject {
data[0] = 0x02;
data[1] = (byte) 0xF8;
- if (data.length + _baos.size() > MAX_SIZE) {
+ if (data.length + baos.size() > MAX_SIZE) {
throw new MaximumSizeExceededException();
}
-
- _baos.write(data, 0, data.length);
-
+ baos.write(data, 0, data.length);
}
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
index 3858f4169..27b3de5ca 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
@@ -52,12 +52,11 @@ public class PresentationTextDescriptor extends AbstractDescriptor {
* width and height.
* @param width The width of the page.
* @param height The height of the page.
- * @param widthResolution The width resolution of the page.
- * @param heightResolution The height resolution of the page.
+ * @param widthRes The width resolution of the page.
+ * @param heightRes The height resolution of the page.
*/
- public PresentationTextDescriptor(int width, int height,
- int widthResolution, int heightResolution) {
- super(width, height, widthResolution, heightResolution);
+ public PresentationTextDescriptor(int width, int height, int widthRes, int heightRes) {
+ super(width, height, widthRes, heightRes);
}
/**
@@ -81,11 +80,11 @@ public class PresentationTextDescriptor extends AbstractDescriptor {
data[9] = 0x00;
data[10] = 0x00;
- byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2);
data[11] = xdpi[0]; // xdpi
data[12] = xdpi[1];
- byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2);
data[13] = ydpi[0]; // ydpi
data[14] = ydpi[1];
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 c0f06439e..901f24bb1 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
@@ -100,7 +100,7 @@ public class PresentationTextObject extends AbstractNamedAFPObject {
/**
* Create the presentation text data for the byte array of data.
*
- * @param fontNumber
+ * @param fontReference
* The font resource identifier.
* @param x
* The x coordinate for the text data.
@@ -117,7 +117,7 @@ public class PresentationTextObject extends AbstractNamedAFPObject {
* @param data
* The text data to be created.
*/
- public void createTextData(int fontNumber, int x, int y, int orientation,
+ public void createTextData(int fontReference, int x, int y, int orientation,
Color col, int vsci, int ica, byte[] data) {
if (currentPresentationTextData == null) {
@@ -126,13 +126,13 @@ public class PresentationTextObject extends AbstractNamedAFPObject {
try {
- currentPresentationTextData.createTextData(fontNumber, x, y,
+ currentPresentationTextData.createTextData(fontReference, x, y,
orientation, col, vsci, ica, data);
} catch (MaximumSizeExceededException msee) {
endPresentationTextData();
- createTextData(fontNumber, x, y, orientation, col, vsci, ica, data);
+ createTextData(fontReference, x, y, orientation, col, vsci, ica, data);
}
diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
index 29ac9eb5d..99f31ba14 100644
--- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
+++ b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
@@ -47,7 +47,7 @@ public class TagLogicalElementBean {
* @return the key
*/
public String getKey() {
- return key;
+ return this.key;
}
/**
@@ -55,7 +55,7 @@ public class TagLogicalElementBean {
* @return the value
*/
public String getValue() {
- return value;
+ return this.value;
}
}
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java
new file mode 100644
index 000000000..27a80acc4
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsContainer.java
@@ -0,0 +1,95 @@
+/*
+ * 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.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.render.afp.modca.AbstractStructuredAFPObject;
+import org.apache.fop.render.afp.modca.PreparedAFPObject;
+
+/**
+ * A base class container of GOCA structured objects
+ */
+public abstract class AbstractGraphicsContainer extends AbstractStructuredAFPObject
+implements PreparedAFPObject {
+
+ /**
+ * list of objects contained within this container
+ */
+ protected List list = null;
+
+ /**
+ * Default constructor
+ */
+ public AbstractGraphicsContainer() {
+ }
+
+ /**
+ * Named constructor
+ * @param name the name of the container
+ */
+ public AbstractGraphicsContainer(String name) {
+ super(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeContent(OutputStream os) throws IOException {
+ if (list != null) {
+ super.writeObjectList(list, os);
+ }
+ }
+
+ /**
+ * Adds a given graphics drawing order to this container
+ * @param drawingOrder the graphics drawing order
+ * @return the drawingOrder if it was added, null otherwise
+ */
+ protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) {
+ log.debug(this + " adding " + drawingOrder);
+ if (list == null) {
+ this.list = new java.util.ArrayList();
+ }
+ list.add(drawingOrder);
+ return drawingOrder;
+ }
+
+ /**
+ * @return the current data length of this container including
+ * all enclosed GOCA drawing objects (and their containers)
+ */
+ public int getDataLength() {
+ int dataLen = 0;
+ if (list != null) {
+ Iterator it = list.iterator();
+ while (it.hasNext()) {
+ Object obj = it.next();
+ if (obj instanceof PreparedAFPObject) {
+ dataLen += ((PreparedAFPObject)obj).getDataLength();
+ }
+ }
+ }
+ return dataLen;
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java
new file mode 100644
index 000000000..7378a5c07
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/AbstractGraphicsCoord.java
@@ -0,0 +1,126 @@
+/*
+ * 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.goca;
+
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * A base class encapsulating the structure of coordinate based GOCA objects
+ */
+public abstract class AbstractGraphicsCoord extends AbstractPreparedAFPObject {
+
+ /** array of x/y coordinates */
+ protected int[] coords = null;
+
+ /**
+ * @param coords the x/y coordinates for this object
+ */
+ public AbstractGraphicsCoord(int[] coords) {
+ this.coords = coords;
+ prepareData();
+ }
+
+ /**
+ * @param x the x coordinate for this object
+ * @param y the y coordinate for this object
+ */
+ public AbstractGraphicsCoord(int x, int y) {
+ this(new int[] {x, y});
+ }
+
+ /**
+ * @param x1 the x1 coordinate for this object
+ * @param y1 the y1 coordinate for this object
+ * @param x2 the x2 coordinate for this object
+ * @param y2 the y2 coordinate for this object
+ */
+ public AbstractGraphicsCoord(int x1, int y1, int x2, int y2) {
+ this(new int[] {x1, y1, x2, y2});
+ }
+
+ /**
+ * @return the order code to use
+ */
+ protected abstract byte getOrderCode();
+
+ /**
+ * @return the length of this order code
+ * (typically this is the same as the coordinate length)
+ */
+ protected int getLength() {
+ return this.coords.length * 2;
+ }
+
+ /**
+ * Creates a newly created and initialized byte data
+ * @return a newly created and initialized byte data
+ */
+ protected byte[] createData() {
+ int len = getLength();
+ byte[] data = new byte[len + 2];
+ data[0] = getOrderCode(); // ORDER CODE
+ data[1] = (byte)len; // LENGTH
+ return data;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = createData();
+ int fromIndex = data.length - getLength();
+ addCoords(data, fromIndex);
+ }
+
+ /**
+ * Adds the coordinates to the structured field data
+ * @param data the structured field data
+ * @param fromIndex the start index
+ */
+ protected void addCoords(byte[] data, int fromIndex) {
+ // X/Y POS
+ for (int i = 0; i < coords.length; i++, fromIndex += 2) {
+ byte[] coord = BinaryUtils.convert(coords[i], 2);
+ data[fromIndex] = coord[0];
+ data[fromIndex + 1] = coord[1];
+ }
+ }
+
+ /**
+ * @return the short name of this GOCA object
+ */
+ protected String getName() {
+ String className = getClass().getName();
+ return className.substring(className.lastIndexOf(".") + 1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ String coordsStr = "";
+ for (int i = 0; i < coords.length; i++) {
+ coordsStr += (i % 2 == 0) ? "x" : "y";
+ coordsStr += (i / 2) + "=" + coords[i] + ",";
+ }
+ coordsStr = coordsStr.substring(0, coordsStr.length() - 1);
+ return getName() + "(" + coordsStr + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java
new file mode 100644
index 000000000..ed10e5456
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/AbstractPreparedAFPObject.java
@@ -0,0 +1,56 @@
+/*
+ * 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.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.render.afp.modca.AbstractAFPObject;
+import org.apache.fop.render.afp.modca.PreparedAFPObject;
+
+/**
+ * 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 AbstractAFPObject
+implements PreparedAFPObject {
+
+ /** structured field data to be written */
+ protected byte[] data = null;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void writeDataStream(OutputStream os) throws IOException {
+ if (this.data != null) {
+ os.write(this.data);
+ }
+ }
+
+ /**
+ * @return the data length of this prepared AFP object
+ */
+ public int getDataLength() {
+ if (this.data != null) {
+ return this.data.length;
+ }
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java
new file mode 100644
index 000000000..c96ca2973
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsArea.java
@@ -0,0 +1,82 @@
+/*
+ * 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.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A GOCA graphics area (container for filled shapes/objects)
+ */
+public final class GraphicsArea extends AbstractGraphicsContainer {
+
+ /** draw boundary lines around this area */
+ private boolean drawBoundary = false;
+
+ /**
+ * Sets whether boundary lines are drawn
+ * @param drawBoundaryLines whether boundary lines are drawn
+ */
+ public void setDrawBoundaryLines(boolean drawBoundaryLines) {
+ this.drawBoundary = drawBoundaryLines;
+ }
+
+ private static final int RES1 = 1;
+ private static final int BOUNDARY = 2;
+ private static final int NO_BOUNDARY = 0;
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDataLength() {
+ // start len + end len + data len
+ return 4 + super.getDataLength();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeStart(OutputStream os) throws IOException {
+ super.writeStart(os);
+ byte[] data = new byte[] {
+ (byte)0x68, // GBAR order code
+ (byte)(RES1 + (drawBoundary ? BOUNDARY : NO_BOUNDARY))
+ };
+ os.write(data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeEnd(OutputStream os) throws IOException {
+ byte[] endData = new byte[] {
+ (byte)0x60, // GEAR order code
+ 0x00, // LENGTH
+ };
+ os.write(endData);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsArea";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java
new file mode 100644
index 000000000..ea4894e84
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsBox.java
@@ -0,0 +1,66 @@
+/*
+ * 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.goca;
+
+/**
+ * A GOCA graphics rectangular box
+ */
+public final class GraphicsBox extends AbstractGraphicsCoord {
+
+ /**
+ * @param coords the x/y coordinates for this object
+ */
+ public GraphicsBox(int[] coords) {
+ super(coords);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected byte getOrderCode() {
+ return (byte)0xC0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected int getLength() {
+ return 10;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = createData();
+ final int fromIndex = 4;
+ addCoords(data, fromIndex);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected byte[] createData() {
+ byte[] data = super.createData();
+ data[2] = (byte)0x20; // CONTROL draw control flags
+ data[3] = 0x00; // reserved
+ return data;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java
new file mode 100644
index 000000000..2c8f68857
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsChainedSegment.java
@@ -0,0 +1,179 @@
+/*
+ * 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.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.render.afp.modca.PreparedAFPObject;
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * A GOCA graphics segment
+ */
+public final class GraphicsChainedSegment extends AbstractGraphicsContainer {
+
+ /**
+ * The maximum segment data length
+ */
+ protected static final int MAX_DATA_LEN = 8192;
+
+ /** the current area */
+ private GraphicsArea currentArea = null;
+
+ /** the previous segment in the chain */
+ private GraphicsChainedSegment previous = null;
+
+ /** the next segment in the chain */
+ private GraphicsChainedSegment next = null;
+
+ /**
+ * Main constructor
+ *
+ * @param name
+ * the name of this graphics segment
+ */
+ public GraphicsChainedSegment(String name) {
+ super(name);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name
+ * the name of this graphics segment
+ * @param previous
+ * the previous graphics segment in this chain
+ */
+ public GraphicsChainedSegment(String name, GraphicsChainedSegment previous) {
+ super(name);
+ previous.next = this;
+ this.previous = previous;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDataLength() {
+ int dataLen = 14 + super.getDataLength();
+ if (previous == null) {
+ GraphicsChainedSegment current = this.next;
+ while (current != null) {
+ dataLen += current.getDataLength();
+ current = current.next;
+ }
+ }
+ return dataLen;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected int getNameLength() {
+ return 4;
+ }
+
+ private static final byte APPEND_NEW_SEGMENT = 0;
+
+ private static final byte PROLOG = 4;
+
+ private static final byte APPEND_TO_EXISING = 48;
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeStart(OutputStream os) throws IOException {
+ super.writeStart(os);
+ int len = super.getDataLength();
+ byte[] segLen = BinaryUtils.convert(len, 2);
+ byte[] data = new byte[] {
+ 0x70, // BEGIN_SEGMENT
+ 0x0C, // Length of following parameters
+ this.nameBytes[0],
+ this.nameBytes[1],
+ this.nameBytes[2],
+ this.nameBytes[3],
+ 0x00, // FLAG1 (ignored)
+ APPEND_NEW_SEGMENT,
+ segLen[0], // SEGL
+ segLen[1],
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ };
+ // P/S NAME (predecessor name)
+ if (previous != null) {
+ data[10] = previous.nameBytes[0];
+ data[11] = previous.nameBytes[1];
+ data[12] = previous.nameBytes[2];
+ data[13] = previous.nameBytes[3];
+ }
+ os.write(data);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeEnd(OutputStream os) throws IOException {
+ // I am the first segment in the chain so write out the rest
+ if (previous == null) {
+ GraphicsChainedSegment current = this.next;
+ while (current != null) {
+ current.writeDataStream(os);
+ current = current.next;
+ }
+ }
+ }
+
+ /**
+ * Begins a graphics area (start of fill)
+ */
+ protected void beginArea() {
+ this.currentArea = new GraphicsArea();
+ super.addDrawingOrder(currentArea);
+ }
+
+ /**
+ * Ends a graphics area (end of fill)
+ */
+ protected void endArea() {
+ this.currentArea = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) {
+ if (currentArea != null) {
+ currentArea.addDrawingOrder(drawingOrder);
+ } else {
+ super.addDrawingOrder(drawingOrder);
+ }
+ return drawingOrder;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsChainedSegment(name=" + super.name + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java
new file mode 100644
index 000000000..b660d5b9a
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsData.java
@@ -0,0 +1,147 @@
+/*
+ * 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.goca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.render.afp.modca.PreparedAFPObject;
+import org.apache.fop.render.afp.tools.BinaryUtils;
+import org.apache.fop.render.afp.tools.StringUtils;
+
+/**
+ * A GOCA graphics data
+ */
+public final class GraphicsData extends AbstractGraphicsContainer {
+
+ /**
+ * The maximum graphics data length
+ */
+ public static final int MAX_DATA_LEN = 32767;
+
+ /**
+ * Default constructor
+ */
+ public GraphicsData() {
+ }
+
+ /**
+ * The graphics segment
+ */
+ private GraphicsChainedSegment currentSegment = null;
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getDataLength() {
+ return 8 + super.getDataLength();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void writeStart(OutputStream os) throws IOException {
+ super.writeStart(os);
+ int l = getDataLength();
+ byte[] len = BinaryUtils.convert(l, 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) 0xEE, // Structured field id byte 2
+ (byte) 0xBB, // Structured field id byte 3
+ 0x00, // Flags
+ 0x00, // Reserved
+ 0x00 // Reserved
+ };
+ os.write(data);
+ }
+
+ /**
+ * Begins a graphics area (start of fill)
+ */
+ public void beginArea() {
+ getSegment().beginArea();
+ }
+
+ /**
+ * Ends a graphics area (end of fill)
+ */
+ public void endArea() {
+ getSegment().endArea();
+ }
+
+ /**
+ * Returns a new segment name
+ * @return a new segment name
+ */
+ private String createSegmentName() {
+ return StringUtils.lpad(String.valueOf(
+ (super.list != null ? super.list.size() : 0) + 1),
+ '0', 4);
+ }
+
+ /**
+ * Returns the current graphics segment, creating one if one does not exist
+ * @return the current graphics chained segment
+ */
+ GraphicsChainedSegment getSegment() {
+ if (currentSegment == null) {
+ newSegment();
+ }
+ return this.currentSegment;
+ }
+
+ /**
+ * Creates a new graphics segment
+ * @return a newly created graphics segment
+ */
+ public GraphicsChainedSegment newSegment() {
+ String name = createSegmentName();
+ if (currentSegment == null) {
+ this.currentSegment = new GraphicsChainedSegment(name);
+ } else {
+ this.currentSegment = new GraphicsChainedSegment(name, currentSegment);
+ }
+ super.addDrawingOrder(currentSegment);
+ return currentSegment;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PreparedAFPObject addDrawingOrder(PreparedAFPObject drawingOrder) {
+ if (currentSegment == null
+ || (currentSegment.getDataLength() + drawingOrder.getDataLength())
+ >= GraphicsChainedSegment.MAX_DATA_LEN) {
+ newSegment();
+ }
+ currentSegment.addDrawingOrder(drawingOrder);
+ return drawingOrder;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsData";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java
new file mode 100644
index 000000000..ab30a3d93
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFillet.java
@@ -0,0 +1,41 @@
+/*
+ * 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.goca;
+
+/**
+ * A GOCA graphics curved tangential line to a specified set of
+ * straight lines drawn from the given position or current position
+ */
+public final class GraphicsFillet extends AbstractGraphicsCoord {
+
+ /**
+ * @param coords the x/y coordinates for this object
+ */
+ public GraphicsFillet(int[] coords) {
+ super(coords);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected byte getOrderCode() {
+ return (byte)0xC5;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java
new file mode 100644
index 000000000..b0dcf9c22
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsFullArc.java
@@ -0,0 +1,81 @@
+/*
+ * 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.goca;
+
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * A GOCA graphics arc (circle/ellipse)
+ */
+public class GraphicsFullArc extends AbstractGraphicsCoord {
+ /** the integer portion of the multiplier */
+ private int mh;
+
+ /** the fractional portion of the multiplier */
+ private int mhr;
+
+ /**
+ * @param x the x coordinate of the center of the circle/ellipse
+ * @param y the y coordinate of the center of the circle/ellipse
+ * @param mh the integer portion of the multiplier
+ * @param mhr the fractional portion of the multiplier
+ */
+ public GraphicsFullArc(int x, int y, int mh, int mhr) {
+ super(x, y);
+ this.mh = mh;
+ this.mhr = mhr;
+ // integer portion of multiplier
+ data[data.length - 2] = BinaryUtils.convert(mh, 1)[0];
+ // fractional portion of multiplier
+ data[data.length - 1] = BinaryUtils.convert(mhr, 1)[0];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected byte getOrderCode() {
+ return (byte)0xC7;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected int getLength() {
+ return super.getLength() + 2;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = super.createData();
+ final int fromIndex = 2;
+ super.addCoords(data, fromIndex);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return super.getName()
+ + "(centerx=" + coords[0] + ",centery=" + coords[1]
+ + ",mh=" + mh + ",mhr=" + mhr + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java
new file mode 100644
index 000000000..f7511e54f
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageBegin.java
@@ -0,0 +1,85 @@
+/*
+ * 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.goca;
+
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * A GOCA graphics begin image object
+ */
+public final class GraphicsImageBegin extends AbstractPreparedAFPObject {
+ /** x coordinate */
+ private int x;
+
+ /** y coordinate */
+ private int y;
+
+ /** width */
+ private int width;
+
+ /** height */
+ private int height;
+
+ /**
+ * @param x the x coordinate of the image
+ * @param y the y coordinate of the image
+ * @param width the image width
+ * @param height the image height
+ */
+ public GraphicsImageBegin(int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ byte[] xcoord = BinaryUtils.convert(x, 2);
+ byte[] ycoord = BinaryUtils.convert(y, 2);
+ byte[] w = BinaryUtils.convert(width, 2);
+ byte[] h = BinaryUtils.convert(height, 2);
+ super.data = new byte[] {
+ (byte) 0xD1, // GBIMG order code
+ (byte) 0x0A, // LENGTH
+ xcoord[0],
+ xcoord[1],
+ ycoord[0],
+ ycoord[1],
+ 0x00, // FORMAT
+ 0x00, // RES
+ w[0], // WIDTH
+ w[1], //
+ h[0], // HEIGHT
+ h[1] //
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsImageBegin(x=" + x + ",y=" + y
+ + ",width=" + width + ",height=" + height + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java
new file mode 100644
index 000000000..4cb59e51a
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageData.java
@@ -0,0 +1,57 @@
+/*
+ * 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.goca;
+
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * A GOCA graphics image data
+ */
+public final class GraphicsImageData extends AbstractPreparedAFPObject {
+
+ /** the maximum image data length */
+ public static final short MAX_DATA_LEN = 255;
+
+ /**
+ * Main constructor
+ *
+ * @param imageData the image data
+ * @param startIndex the start index to read the image data from
+ */
+ public GraphicsImageData(byte[] imageData, int startIndex) {
+ int dataLen = MAX_DATA_LEN;
+ if (startIndex + MAX_DATA_LEN >= imageData.length) {
+ dataLen = imageData.length - startIndex - 1;
+ }
+ super.data = new byte[dataLen + 2];
+ data[0] = (byte) 0x92; // GIMD
+ data[1] = BinaryUtils.convert(dataLen, 1)[0]; // LENGTH
+ System.arraycopy(imageData, startIndex, data, 2, dataLen);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsImageData("
+ + (data != null ? "" + (data.length - 2) : "null")
+ + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.java
new file mode 100644
index 000000000..e365e4444
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsImageEnd.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.goca;
+
+/**
+ * A GOCA graphics image data
+ */
+public class GraphicsImageEnd extends AbstractPreparedAFPObject {
+
+ /**
+ * Default constructor
+ */
+ public GraphicsImageEnd() {
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = new byte[] {
+ (byte) 0x93, // GEIMG order code
+ 0x00 // LENGTH
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsImageEnd";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java
new file mode 100644
index 000000000..4bf396d0b
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsLine.java
@@ -0,0 +1,42 @@
+/*
+ * 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.goca;
+
+
+/**
+ * A GOCA graphics straight line drawn from the
+ * given position or current position.
+ */
+public class GraphicsLine extends AbstractGraphicsCoord {
+
+ /**
+ * @param coords the x/y coordinates for this object
+ */
+ public GraphicsLine(int[] coords) {
+ super(coords);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected byte getOrderCode() {
+ return (byte)0xC1;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java
new file mode 100644
index 000000000..6e1c7abf9
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetArcParameters.java
@@ -0,0 +1,53 @@
+/*
+ * 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.goca;
+
+/**
+ * Sets the arc parameters for a GOCA graphics arc (circle/ellipse)
+ */
+public class GraphicsSetArcParameters extends AbstractGraphicsCoord {
+
+ /**
+ * @param xmaj x coordinate of the major axis point
+ * @param ymin y coordinate of the minor axis point
+ * @param xmin x coordinate of the minor axis point
+ * @param ymaj y coordinate of the major axis point
+ */
+ public GraphicsSetArcParameters(int xmaj, int ymin, int xmin, int ymaj) {
+ super(xmaj, ymin, xmin, ymaj);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected byte getOrderCode() {
+ return 0x22;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return getName() + "(xmaj=" + coords[0]
+ + ",ymin=" + coords[1]
+ + ",xmin=" + coords[2]
+ + ",ymaj=" + coords[3] + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java
new file mode 100644
index 000000000..be244bd06
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCharacterSet.java
@@ -0,0 +1,55 @@
+/*
+ * 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.goca;
+
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * Sets the current character set (font) to be used for following graphics strings
+ */
+public class GraphicsSetCharacterSet extends AbstractPreparedAFPObject {
+ /** font character set reference */
+ private int fontReference;
+
+ /**
+ * @param fontReference character set font reference
+ */
+ public GraphicsSetCharacterSet(int fontReference) {
+ this.fontReference = fontReference;
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = new byte[] {
+ 0x38, // GSCS order code
+ BinaryUtils.convert(fontReference)[0]
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsSetCharacterSet(" + fontReference + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java
new file mode 100644
index 000000000..afa825a84
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetCurrentPosition.java
@@ -0,0 +1,41 @@
+/*
+ * 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.goca;
+
+
+/**
+ * Sets the current painting position of the graphics object
+ */
+public class GraphicsSetCurrentPosition extends AbstractGraphicsCoord {
+
+ /**
+ * @param coords the x/y coordinates for this object
+ */
+ public GraphicsSetCurrentPosition(int[] coords) {
+ super(coords);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected byte getOrderCode() {
+ return (byte)0x21;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java
new file mode 100644
index 000000000..99c2902c0
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineType.java
@@ -0,0 +1,86 @@
+/*
+ * 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.goca;
+
+/**
+ * Sets the value of the current line type attribute when stroking GOCA shapes (structured fields)
+ */
+public class GraphicsSetLineType extends AbstractPreparedAFPObject {
+ /** the default line type */
+ public static final byte DEFAULT = 0x00; // normally SOLID
+
+ /** the default line type */
+ public static final byte DOTTED = 0x01;
+
+ /** short dashed line type */
+ public static final byte SHORT_DASHED = 0x02;
+
+ /** dashed dotted line type */
+ public static final byte DASH_DOT = 0x03;
+
+ /** double dotted line type */
+ public static final byte DOUBLE_DOTTED = 0x04;
+
+ /** long dashed line type */
+ public static final byte LONG_DASHED = 0x05;
+
+ /** dash double dotted line type */
+ public static final byte DASH_DOUBLE_DOTTED = 0x06;
+
+ /** solid line type */
+ public static final byte SOLID = 0x07;
+
+ /** invisible line type */
+ public static final byte INVISIBLE = 0x08;
+
+ /** line type */
+ private byte type = DEFAULT;
+
+ /**
+ * Main constructor
+ * @param type line type
+ */
+ public GraphicsSetLineType(byte type) {
+ this.type = type;
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = new byte[] {
+ 0x18, // GSLW order code
+ type // line type
+ };
+ }
+
+ private static final String[] TYPES = {
+ "DEFAULT", "DOTTED", "SHORT_DASHED", "DASH_DOT", "DOUBLE_DOTTED",
+ "LONG_DASHED", "DASH_DOUBLE_DOTTED", "SOLID", "INVISIBLE"
+ };
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsSetLineType(type=" + TYPES[type] + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java
new file mode 100644
index 000000000..8e08d09e2
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetLineWidth.java
@@ -0,0 +1,54 @@
+/*
+ * 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.goca;
+
+/**
+ * Sets the line width to use when stroking GOCA shapes (structured fields)
+ */
+public class GraphicsSetLineWidth extends AbstractPreparedAFPObject {
+ /** line width multiplier */
+ private int multiplier = 1;
+
+ /**
+ * Main constructor
+ * @param multiplier the line width multiplier
+ */
+ public GraphicsSetLineWidth(int multiplier) {
+ this.multiplier = multiplier;
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = new byte[] {
+ 0x19, // GSLW order code
+ (byte)multiplier // MH (line-width)
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsSetLineWidth(multiplier=" + multiplier + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java
new file mode 100644
index 000000000..9a04139a2
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetPatternSymbol.java
@@ -0,0 +1,106 @@
+/*
+ * 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.goca;
+
+/**
+ * Sets the pattern symbol to use when filling following GOCA structured fields
+ */
+public class GraphicsSetPatternSymbol extends AbstractPreparedAFPObject {
+ /** dotted density 1 */
+ public static final byte DOTTED_DENSITY_1 = 0x01;
+
+ /** dotted density 2 */
+ public static final byte DOTTED_DENSITY_2 = 0x02;
+
+ /** dotted density 3 */
+ public static final byte DOTTED_DENSITY_3 = 0x03;
+
+ /** dotted density 4 */
+ public static final byte DOTTED_DENSITY_4 = 0x04;
+
+ /** dotted density 5 */
+ public static final byte DOTTED_DENSITY_5 = 0x05;
+
+ /** dotted density 6 */
+ public static final byte DOTTED_DENSITY_6 = 0x06;
+
+ /** dotted density 7 */
+ public static final byte DOTTED_DENSITY_7 = 0x07;
+
+ /** dotted density 8 */
+ public static final byte DOTTED_DENSITY_8 = 0x08;
+
+ /** dotted density 9 */
+ public static final byte VERTICAL_LINES = 0x09;
+
+ /** horizontal lines */
+ public static final byte HORIZONTAL_LINES = 0x0A;
+
+ /** diagonal lines, bottom left to top right 1 */
+ public static final byte DIAGONAL_LINES_BLTR_1 = 0x0B;
+
+ /** diagonal lines, bottom left to top right 2 */
+ public static final byte DIAGONAL_LINES_BLTR_2 = 0x0C;
+
+ /** diagonal lines, top left to bottom right 1 */
+ public static final byte DIAGONAL_LINES_TLBR_1 = 0x0D;
+
+ /** diagonal lines, top left to bottom right 2 */
+ public static final byte DIAGONAL_LINES_TLBR_2 = 0x0E;
+
+ /** no fill */
+ public static final byte NO_FILL = 0x0F;
+
+ /** solid fill */
+ public static final byte SOLID_FILL = 0x10;
+
+ /** blank (same as no fill) */
+ public static final byte BLANK = 0x40; // processed same as NO_FILL
+
+ /** the graphics pattern symbol to use */
+ private byte symbol;
+
+ /**
+ * Main constructor
+ * @param symb the pattern symbol to use
+ */
+ public GraphicsSetPatternSymbol(byte symb) {
+ this.symbol = symb;
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ super.data = new byte[] {
+ 0x28, // GSPT order code
+ symbol
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsSetPatternSymbol(fill="
+ + (symbol == SOLID_FILL ? true : false) + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java
new file mode 100644
index 000000000..47df7ba14
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsSetProcessColor.java
@@ -0,0 +1,92 @@
+/*
+ * 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.goca;
+
+import java.awt.Color;
+import java.awt.color.ColorSpace;
+
+import org.apache.fop.render.afp.modca.GraphicsObject;
+
+/**
+ * Sets the current processing color for the following GOCA structured fields
+ */
+public class GraphicsSetProcessColor extends AbstractPreparedAFPObject {
+ /** the color to set */
+ private Color col;
+
+ /**
+ * Main constructor
+ * @param col the color to set
+ */
+ public GraphicsSetProcessColor(Color col) {
+ this.col = col;
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ // COLSPCE
+ byte colspace;
+ int colSpaceType = col.getColorSpace().getType();
+ if (colSpaceType == ColorSpace.TYPE_CMYK) {
+ colspace = 0x04;
+ } else if (colSpaceType == ColorSpace.TYPE_RGB) {
+ colspace = 0x01;
+ } else {
+ GraphicsObject.log.error("unsupported colorspace " + colSpaceType);
+ colspace = 0x01;
+ }
+
+ // COLSIZE(S)
+ float[] colcomp = col.getColorComponents(null);
+ byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00};
+ for (int i = 0; i < colcomp.length; i++) {
+ colsizes[i] = (byte)8;
+ }
+
+ int len = 10 + colcomp.length;
+ super.data = new byte[len + 2];
+ data[0] = (byte)0xB2; // GSPCOL order code
+ data[1] = (byte)len; // LEN
+ data[2] = 0x00; // reserved; must be zero
+ data[3] = colspace; // COLSPCE
+ data[4] = 0x00; // reserved; must be zero
+ data[5] = 0x00; // reserved; must be zero
+ data[6] = 0x00; // reserved; must be zero
+ data[7] = 0x00; // reserved; must be zero
+ data[8] = colsizes[0]; // COLSIZE(S)
+ data[9] = colsizes[1];
+ data[10] = colsizes[2];
+ data[11] = colsizes[3];
+ // COLVALUE(S)
+ for (int i = 0; i < colcomp.length; i++) {
+ data[i + 12] = (byte)(colcomp[i] * 255);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return "GraphicsSetProcessColor(col=" + col + ")";
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java
new file mode 100644
index 000000000..1750c4348
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/modca/goca/GraphicsString.java
@@ -0,0 +1,115 @@
+/*
+ * 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.goca;
+
+import java.io.UnsupportedEncodingException;
+
+import org.apache.fop.render.afp.modca.AFPConstants;
+import org.apache.fop.render.afp.modca.GraphicsObject;
+import org.apache.fop.render.afp.tools.BinaryUtils;
+
+/**
+ * A GOCA graphics string
+ */
+public class GraphicsString extends AbstractPreparedAFPObject {
+ /** Up to 255 bytes of character data */
+ private static final int MAX_STR_LEN = 255;
+
+ /** drawn from the current position */
+ private boolean fromCurrentPosition = false;
+
+ /** the string to draw */
+ private String str = null;
+
+ /** x coordinate */
+ private int x;
+
+ /** y coordinate */
+ private int y;
+
+ /**
+ * @param str the character string
+ */
+ public GraphicsString(String str) {
+ this.str = str;
+ fromCurrentPosition = true;
+ prepareData();
+ }
+
+ /**
+ * @param str the character string
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public GraphicsString(String str, int x, int y) {
+ this.str = str;
+ this.x = x;
+ this.y = y;
+ prepareData();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void prepareData() {
+ int maxStrLen = MAX_STR_LEN - (fromCurrentPosition ? 0 : 4);
+ if (str.length() > maxStrLen) {
+ str = str.substring(0, maxStrLen);
+ log.warn("truncated character string, longer than " + maxStrLen + " chars");
+ }
+ byte[] strData = null;
+ try {
+ strData = str.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ } catch (UnsupportedEncodingException ex) {
+ GraphicsObject.log.error("unsupported encoding: " + ex.getMessage());
+ }
+ int len = strData.length;
+ if (fromCurrentPosition) {
+ data = new byte[len + 2];
+ data[0] = (byte)0x83;
+ data[1] = (byte)len;
+ System.arraycopy(strData, 0, data, 2, strData.length);
+ } else {
+ len += 4; // x/y coordinates
+ byte[] osx = BinaryUtils.convert(x, 2);
+ byte[] osy = BinaryUtils.convert(y, 2);
+ data = new byte[len + 2];
+ data[0] = (byte)0xC3;
+ data[1] = (byte)len;
+ data[2] = osx[0];
+ data[3] = osx[1];
+ data[4] = osy[0];
+ data[5] = osy[1];
+ System.arraycopy(strData, 0, data, 6, strData.length);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ String string = "GraphicsString(str='" + str + "'";
+ if (!fromCurrentPosition) {
+ string += ",x=" + x + ",y=" + y;
+ }
+ string += ")";
+ return string;
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
index e6a855b83..75ed0de52 100644
--- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
+++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
@@ -35,7 +35,7 @@ import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D;
-import org.apache.xmlgraphics.java2d.ps.TextHandler;
+import org.apache.xmlgraphics.java2d.TextHandler;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java
index f0cb140f9..5b840484d 100644
--- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java
+++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java
@@ -28,14 +28,14 @@ import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet;
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
-import org.apache.xmlgraphics.java2d.ps.TextHandler;
+import org.apache.xmlgraphics.java2d.ps.PSTextHandler;
import org.apache.xmlgraphics.ps.PSGenerator;
/**
* Specialized TextHandler implementation that the PSGraphics2D class delegates to to paint text
* using PostScript text operations.
*/
-public class NativeTextHandler implements TextHandler {
+public class NativeTextHandler implements PSTextHandler {
private PSGraphics2D g2d;
diff --git a/src/java/org/apache/fop/render/ps/PSTextPainter.java b/src/java/org/apache/fop/render/ps/PSTextPainter.java
index 955db492d..08cea6517 100644
--- a/src/java/org/apache/fop/render/ps/PSTextPainter.java
+++ b/src/java/org/apache/fop/render/ps/PSTextPainter.java
@@ -40,7 +40,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
-import org.apache.xmlgraphics.java2d.ps.TextHandler;
+import org.apache.xmlgraphics.java2d.TextHandler;
import org.apache.batik.dom.svg.SVGOMTextElement;
import org.apache.batik.gvt.text.Mark;
@@ -385,7 +385,6 @@ public class PSTextPainter implements TextPainter {
String style = getStyle(aci);
int weight = getWeight(aci);
- boolean found = false;
String fontFamily = null;
List gvtFonts = (List) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);