aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Steiner <ssteiner@apache.org>2022-09-01 10:14:56 +0000
committerSimon Steiner <ssteiner@apache.org>2022-09-01 10:14:56 +0000
commitf2e542354f9783e30c72b403422beeb33de9d787 (patch)
tree29d7a1810a58eea5b484399e2fe103eee68cae94
parent02656ec73867455a217091cb60f6c8c1f25caa59 (diff)
downloadxmlgraphics-fop-f2e542354f9783e30c72b403422beeb33de9d787.tar.gz
xmlgraphics-fop-f2e542354f9783e30c72b403422beeb33de9d787.zip
FOP-3091: Add transparency color support for AFP
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1903806 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectFactory.java1
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectInfo.java10
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/AFPRectanglePainter.java111
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/ioca/ImageContent.java10
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/ioca/ImageSegment.java4
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/ioca/Tile.java48
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/ioca/TransparencyMask.java62
-rw-r--r--fop-core/src/main/java/org/apache/fop/afp/modca/ImageObject.java12
-rw-r--r--fop-core/src/main/java/org/apache/fop/render/afp/AFPDocumentHandler.java2
-rw-r--r--fop-core/src/test/java/org/apache/fop/afp/AFPRectanglePainterTestCase.java83
-rw-r--r--fop-core/src/test/java/org/apache/fop/afp/ioca/ImageContentTestCase.java48
11 files changed, 370 insertions, 21 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectFactory.java b/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectFactory.java
index 17114ebbe..987102af7 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectFactory.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectFactory.java
@@ -150,6 +150,7 @@ public class AFPDataObjectFactory {
}
imageObj.setData(imageObjectInfo.getData());
+ imageObj.setTransparencyMask(imageObjectInfo.getTransparencyMask());
return imageObj;
}
diff --git a/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectInfo.java b/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectInfo.java
index b93056f02..dc828a540 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectInfo.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/AFPDataObjectInfo.java
@@ -45,6 +45,8 @@ public class AFPDataObjectInfo {
/** the object data in a byte array */
private byte[] data;
+ private byte[] transparencyMask;
+
/** the object data height resolution */
private int dataHeightRes;
@@ -239,6 +241,14 @@ public class AFPDataObjectInfo {
return this.data;
}
+ public void setTransparencyMask(byte[] transparencyMask) {
+ this.transparencyMask = transparencyMask;
+ }
+
+ public byte[] getTransparencyMask() {
+ return transparencyMask;
+ }
+
/**
* Controls whether to create a page segment or a normal object.
* @param value true for page segments, false for objects
diff --git a/fop-core/src/main/java/org/apache/fop/afp/AFPRectanglePainter.java b/fop-core/src/main/java/org/apache/fop/afp/AFPRectanglePainter.java
index 8b598008a..009f5bc88 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/AFPRectanglePainter.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/AFPRectanglePainter.java
@@ -19,26 +19,50 @@
package org.apache.fop.afp;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferByte;
+import java.awt.image.RenderedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import org.apache.xmlgraphics.image.loader.ImageSize;
+import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives;
+import org.apache.xmlgraphics.util.MimeConstants;
+
+import org.apache.fop.util.bitmap.BitmapImageUtil;
/**
* A painter of rectangles in AFP
*/
public class AFPRectanglePainter extends AbstractAFPPainter {
+ private AFPResourceManager resourceManager;
+
/**
* Main constructor
*
* @param paintingState the AFP painting state
* @param dataStream the AFP datastream
*/
- public AFPRectanglePainter(AFPPaintingState paintingState, DataStream dataStream) {
+ public AFPRectanglePainter(AFPPaintingState paintingState, DataStream dataStream,
+ AFPResourceManager resourceManager) {
super(paintingState, dataStream);
+ this.resourceManager = resourceManager;
}
/** {@inheritDoc} */
- public void paint(PaintingInfo paintInfo) {
+ public void paint(PaintingInfo paintInfo) throws IOException {
+ Color color = paintingState.getColor();
+ if (color instanceof ColorWithAlternatives && color.getAlpha() != 255) {
+ paintAlpha(paintInfo);
+ return;
+ }
+
RectanglePaintingInfo rectanglePaintInfo = (RectanglePaintingInfo)paintInfo;
int pageWidth = dataStream.getCurrentPage().getWidth();
int pageHeight = dataStream.getCurrentPage().getHeight();
@@ -90,4 +114,87 @@ public class AFPRectanglePainter extends AbstractAFPPainter {
}
dataStream.createLine(lineDataInfo);
}
+
+ private void paintAlpha(PaintingInfo paintInfo) throws IOException {
+ RectanglePaintingInfo rectanglePaintInfo = (RectanglePaintingInfo)paintInfo;
+ if (rectanglePaintInfo.getWidth() <= 0 || rectanglePaintInfo.getHeight() <= 0) {
+ return;
+ }
+ Dimension size = new Dimension((int)rectanglePaintInfo.getWidth(), (int)rectanglePaintInfo.getHeight());
+
+ AFPImageObjectInfo imageObjectInfo = new AFPImageObjectInfo();
+ imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
+ imageObjectInfo.getResourceInfo().setLevel(new AFPResourceLevel(AFPResourceLevel.ResourceType.INLINE));
+ imageObjectInfo.getResourceInfo().setImageDimension(size);
+ imageObjectInfo.setColor(true);
+
+ int width = size.width;
+ int height = size.height;
+ int resolution = paintingState.getResolution();
+ ImageSize bitmapSize = new ImageSize(width, height, resolution);
+ imageObjectInfo.setDataHeightRes((int)Math.round(bitmapSize.getDpiHorizontal() * 10));
+ imageObjectInfo.setDataWidthRes((int)Math.round(bitmapSize.getDpiVertical() * 10));
+ imageObjectInfo.setDataWidth(width);
+ imageObjectInfo.setDataHeight(height);
+
+ Color color = paintingState.getColor();
+ byte[] image = buildImage(color, width, height);
+ imageObjectInfo.setData(image);
+ if (color instanceof ColorWithAlternatives) {
+ imageObjectInfo.setBitsPerPixel(32);
+ } else {
+ imageObjectInfo.setBitsPerPixel(24);
+ }
+
+ image = buildMaskImage(color, width, height);
+ imageObjectInfo.setTransparencyMask(image);
+
+ int rotation = paintingState.getRotation();
+ AffineTransform at = paintingState.getData().getTransform();
+ Point2D origin = at.transform(new Point2D.Float(
+ rectanglePaintInfo.getX() * 1000,
+ rectanglePaintInfo.getY() * 1000), null);
+ AFPUnitConverter unitConv = paintingState.getUnitConverter();
+ float widthf = unitConv.pt2units(rectanglePaintInfo.getWidth());
+ float heightf = unitConv.pt2units(rectanglePaintInfo.getHeight());
+ AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(
+ (int) Math.round(origin.getX()),
+ (int) Math.round(origin.getY()),
+ Math.round(widthf), Math.round(heightf), resolution, rotation);
+ imageObjectInfo.setObjectAreaInfo(objectAreaInfo);
+
+ resourceManager.createObject(imageObjectInfo);
+ }
+
+ private byte[] buildImage(Color color, int width, int height) {
+ float[] components;
+ if (color instanceof ColorWithAlternatives) {
+ components = ((ColorWithAlternatives)color).getAlternativeColors()[0].getColorComponents(null);
+ } else {
+ components = color.getColorComponents(null);
+ }
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ for (float component : components) {
+ component *= 255;
+ bos.write((byte)component);
+ }
+ }
+ }
+ return bos.toByteArray();
+ }
+
+ private byte[] buildMaskImage(Color color, int width, int height) {
+ BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics graphics = bufferedImage.getGraphics();
+ Color alpha = new Color(color.getAlpha(), color.getAlpha(), color.getAlpha());
+ graphics.setColor(alpha);
+ graphics.fillRect(0, 0, width, height);
+ graphics.dispose();
+ RenderedImage renderedImage =
+ BitmapImageUtil.convertToMonochrome(bufferedImage, new Dimension(width, height), 1);
+ DataBufferByte bufferByte = (DataBufferByte) renderedImage.getData().getDataBuffer();
+ return bufferByte.getData();
+ }
}
diff --git a/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageContent.java b/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageContent.java
index 516d4f715..b4f9645a6 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageContent.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageContent.java
@@ -182,12 +182,18 @@ public class ImageContent extends AbstractStructuredObject {
}
}
- private static final int MAX_DATA_LEN = 65535;
+ public void setTransparencyMask(byte[] transparencyMask) {
+ if (transparencyMask != null) {
+ tile.setTransparencyMask(new TransparencyMask(transparencyMask, imageSizeParameter));
+ }
+ }
+
+ private static final int MAX_DATA_LEN = 8188;
/** {@inheritDoc} */
@Override
protected void writeContent(OutputStream os) throws IOException {
- if (imageSizeParameter != null) {
+ if (imageSizeParameter != null && tile == null) {
imageSizeParameter.writeToStream(os);
}
diff --git a/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageSegment.java b/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageSegment.java
index 96afa1136..68e4dd74b 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageSegment.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/ioca/ImageSegment.java
@@ -136,6 +136,10 @@ public class ImageSegment extends AbstractNamedAFPObject {
getImageContent().setImageData(imageData);
}
+ public void setTransparencyMask(byte[] transparencyMask) {
+ getImageContent().setTransparencyMask(transparencyMask);
+ }
+
/** {@inheritDoc} */
public void writeContent(OutputStream os) throws IOException {
if (imageContent != null) {
diff --git a/fop-core/src/main/java/org/apache/fop/afp/ioca/Tile.java b/fop-core/src/main/java/org/apache/fop/afp/ioca/Tile.java
index 3e9d3d5ff..9f5f88d3a 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/ioca/Tile.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/ioca/Tile.java
@@ -31,6 +31,7 @@ public class Tile extends AbstractStructuredObject {
private TilePosition tilePosition;
private TileSize tileSize;
private BandImage bandImage;
+ private TransparencyMask transparencyMask;
private byte[] data;
private IDEStructureParameter ideStructureParameter;
@@ -50,7 +51,40 @@ public class Tile extends AbstractStructuredObject {
if (ideStructureParameter != null) {
ideStructureParameter.writeToStream(os);
}
+ if (transparencyMask != null) {
+ transparencyMask.writeToStream(os);
+ }
if (data != null) {
+ writeData(os);
+ }
+ }
+
+ private void writeData(OutputStream os) throws IOException {
+ final byte[] dataHeader = new byte[]{(byte) 0xFE, // ID
+ (byte) 0x9C, // ID
+ 0x00, // length
+ 0x00, // length
+ 0x00, // bandnum
+ 0x00, // reserved
+ 0x00 // reserved
+ };
+ final int lengthOffset = 2;
+ if (ideSize == 24) {
+ byte[] red = new byte[data.length / 3];
+ byte[] green = new byte[data.length / 3];
+ byte[] blue = new byte[data.length / 3];
+ for (int j = 0; j < data.length / 3; j++) {
+ red[j] = data[3 * j];
+ green[j] = data[3 * j + 1];
+ blue[j] = data[3 * j + 2];
+ }
+ dataHeader[4] = (byte) 0x01;
+ writeChunksToStream(red, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+ dataHeader[4] = (byte) 0x02;
+ writeChunksToStream(green, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+ dataHeader[4] = (byte) 0x03;
+ writeChunksToStream(blue, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+ } else {
byte[] c = new byte[data.length / 4];
byte[] m = new byte[data.length / 4];
byte[] y = new byte[data.length / 4];
@@ -61,15 +95,6 @@ public class Tile extends AbstractStructuredObject {
y[j] = data[4 * j + 2];
k[j] = data[4 * j + 3];
}
- final byte[] dataHeader = new byte[] {(byte) 0xFE, // ID
- (byte) 0x9C, // ID
- 0x00, // length
- 0x00, // length
- 0x00, // bandnum
- 0x00, // reserved
- 0x00 // reserved
- };
- final int lengthOffset = 2;
dataHeader[4] = (byte) 0x01;
writeChunksToStream(c, dataHeader, lengthOffset, MAX_DATA_LEN, os);
dataHeader[4] = (byte) 0x02;
@@ -116,7 +141,7 @@ public class Tile extends AbstractStructuredObject {
int numFullChunks = dataLength / maxChunkLength;
int lastChunkLength = dataLength % maxChunkLength;
- byte[] len = {(byte) 0x1f, (byte) 0xff};
+ byte[] len = BinaryUtils.convert(3 + maxChunkLength, 2);
int off = 0;
if (numFullChunks > 0) {
// write out full data chunks
@@ -173,4 +198,7 @@ public class Tile extends AbstractStructuredObject {
this.bandImage = bandImage;
}
+ public void setTransparencyMask(TransparencyMask transparencyMask) {
+ this.transparencyMask = transparencyMask;
+ }
}
diff --git a/fop-core/src/main/java/org/apache/fop/afp/ioca/TransparencyMask.java b/fop-core/src/main/java/org/apache/fop/afp/ioca/TransparencyMask.java
new file mode 100644
index 000000000..8b0582833
--- /dev/null
+++ b/fop-core/src/main/java/org/apache/fop/afp/ioca/TransparencyMask.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+package org.apache.fop.afp.ioca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.AbstractAFPObject;
+
+public class TransparencyMask extends AbstractAFPObject {
+ private static final int MAX_DATA_LEN = 8188;
+ private ImageSizeParameter imageSizeParameter;
+ private byte[] maskData;
+
+ public TransparencyMask(byte[] maskData, ImageSizeParameter imageSizeParameter) {
+ this.maskData = maskData;
+ this.imageSizeParameter = imageSizeParameter;
+ }
+
+ public void writeToStream(OutputStream os) throws IOException {
+ os.write(0x8E);
+ os.write(0);
+ imageSizeParameter.writeToStream(os);
+ os.write(getImageEncodingParameter());
+
+ final byte[] dataHeader = new byte[] {(byte) 0xFE, // ID
+ (byte) 0x92, // ID
+ 0x00, // length
+ 0x00 // length
+ };
+ final int lengthOffset = 2;
+ writeChunksToStream(maskData, dataHeader, lengthOffset, MAX_DATA_LEN, os);
+
+ os.write(0x8F);
+ os.write(0);
+ }
+
+ private byte[] getImageEncodingParameter() {
+ byte encoding = (byte) 0x03;
+ return new byte[] {(byte) 0x95, // ID
+ 0x02, // Length
+ encoding,
+ (byte) 0x01, // RECID
+ };
+ }
+}
diff --git a/fop-core/src/main/java/org/apache/fop/afp/modca/ImageObject.java b/fop-core/src/main/java/org/apache/fop/afp/modca/ImageObject.java
index 2452a9c15..0697e427c 100644
--- a/fop-core/src/main/java/org/apache/fop/afp/modca/ImageObject.java
+++ b/fop-core/src/main/java/org/apache/fop/afp/modca/ImageObject.java
@@ -79,11 +79,9 @@ public class ImageObject extends AbstractDataObject {
ImageDataDescriptor imageDataDescriptor
= factory.createImageDataDescriptor(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
- boolean setImageSize = true;
if (MimeConstants.MIME_AFP_IOCA_FS45.equals(imageObjectInfo.getMimeType())) {
imageDataDescriptor.setFunctionSet(ImageDataDescriptor.FUNCTION_SET_FS45);
if (imageObjectInfo.getBitsPerPixel() == 32) {
- setImageSize = false;
Tile tile = factory.createTile();
TilePosition tilePosition = factory.createTilePosition();
TileSize tileSize = factory.createTileSize(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
@@ -101,10 +99,8 @@ public class ImageObject extends AbstractDataObject {
getObjectEnvironmentGroup().setMapImageObject(
new MapImageObject(dataObjectInfo.getMappingOption()));
- if (setImageSize) {
- // not used for FS45
- getImageSegment().setImageSize(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
- }
+ // not used for FS45
+ getImageSegment().setImageSize(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
}
/**
@@ -164,6 +160,10 @@ public class ImageObject extends AbstractDataObject {
getImageSegment().setData(imageData);
}
+ public void setTransparencyMask(byte[] date) {
+ getImageSegment().setTransparencyMask(date);
+ }
+
/** {@inheritDoc} */
protected void writeStart(OutputStream os) throws IOException {
byte[] data = new byte[17];
diff --git a/fop-core/src/main/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/fop-core/src/main/java/org/apache/fop/render/afp/AFPDocumentHandler.java
index e80dedd87..a711282d2 100644
--- a/fop-core/src/main/java/org/apache/fop/render/afp/AFPDocumentHandler.java
+++ b/fop-core/src/main/java/org/apache/fop/render/afp/AFPDocumentHandler.java
@@ -164,7 +164,7 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
getPaintingState(), getDataStream(), getResourceManager());
} else {
return new AFPRectanglePainter(
- getPaintingState(), getDataStream());
+ getPaintingState(), getDataStream(), getResourceManager());
}
}
diff --git a/fop-core/src/test/java/org/apache/fop/afp/AFPRectanglePainterTestCase.java b/fop-core/src/test/java/org/apache/fop/afp/AFPRectanglePainterTestCase.java
new file mode 100644
index 000000000..310fff26f
--- /dev/null
+++ b/fop-core/src/test/java/org/apache/fop/afp/AFPRectanglePainterTestCase.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.afp;
+
+import java.awt.Color;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.xmlgraphics.java2d.color.ColorSpaces;
+import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives;
+
+import org.apache.fop.afp.parser.MODCAParser;
+import org.apache.fop.afp.parser.UnparsedStructuredField;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
+
+public class AFPRectanglePainterTestCase {
+ @Test
+ public void testCMYKTransparencyMask() throws Exception {
+ float cyan = 0.5f;
+ Color deviceColor = new Color(ColorSpaces.getDeviceCMYKColorSpace(), new float[]{cyan, 0, 0, 0}, 0.4f);
+ ByteArrayInputStream bis = buildAFP(new ColorWithAlternatives(0, 0, 0, 128, new Color[]{deviceColor}));
+ bis.skip(59);
+ Assert.assertEquals(bis.read(), 0x8E); //start
+ bis.skip(20);
+ Assert.assertEquals(bis.read(), 170); //mask data
+ bis.skip(1299);
+ Assert.assertEquals(bis.read(), 0x8F); //end
+ bis.skip(89);
+ Assert.assertEquals(bis.read(), 127); //cyan byte
+ }
+
+ @Test
+ public void testRGBTransparencyMask() throws Exception {
+ ByteArrayInputStream bis = buildAFP(new Color(0, 0, 0, 128));
+ Assert.assertNull(bis);
+ }
+
+ private ByteArrayInputStream buildAFP(Color color) throws Exception {
+ FOUserAgent foUserAgent = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent();
+ AFPPaintingState paintingState = new AFPPaintingState();
+ paintingState.setColor(color);
+ AFPResourceManager resourceManager = new AFPResourceManager(foUserAgent.getResourceResolver());
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DataStream stream = resourceManager.createDataStream(paintingState, bos);
+ stream.startDocument();
+ stream.startPage(100, 100, 0, 10, 10);
+ AFPRectanglePainter painter = new AFPRectanglePainter(paintingState, stream, resourceManager);
+ painter.paint(new RectanglePaintingInfo(0, 0, 100, 100));
+ stream.endPage();
+ stream.endDocument();
+ resourceManager.writeToStream();
+
+ MODCAParser parser = new MODCAParser(new ByteArrayInputStream(bos.toByteArray()));
+ UnparsedStructuredField structuredField;
+ while ((structuredField = parser.readNextStructuredField()) != null) {
+ if (structuredField.toString().endsWith("Data Image")) {
+ return new ByteArrayInputStream(structuredField.getData());
+ }
+ }
+ return null;
+ }
+}
diff --git a/fop-core/src/test/java/org/apache/fop/afp/ioca/ImageContentTestCase.java b/fop-core/src/test/java/org/apache/fop/afp/ioca/ImageContentTestCase.java
new file mode 100644
index 000000000..9a9c30c4e
--- /dev/null
+++ b/fop-core/src/test/java/org/apache/fop/afp/ioca/ImageContentTestCase.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.afp.ioca;
+
+import java.io.ByteArrayOutputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ImageContentTestCase {
+ @Test
+ public void testImageSizeParameterWritten() throws Exception {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ImageContent imageContent = new ImageContent();
+ imageContent.setImageSizeParameter(new ImageSizeParameter(1, 1, 1, 1));
+ imageContent.writeToStream(bos);
+ Assert.assertEquals(bos.size(), 20);
+ }
+
+ @Test
+ public void testImageSizeParameterNotWritten() throws Exception {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ImageContent imageContent = new ImageContent();
+ imageContent.setImageSizeParameter(new ImageSizeParameter(1, 1, 1, 1));
+ Tile tile = new Tile();
+ tile.setPosition(new TilePosition());
+ tile.setSize(new TileSize(1, 1, 1, 1));
+ imageContent.addTile(tile);
+ imageContent.writeToStream(bos);
+ Assert.assertEquals(bos.size(), 34);
+ }
+}