aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2009-01-28 11:10:51 +0000
committerJeremias Maerki <jeremias@apache.org>2009-01-28 11:10:51 +0000
commitac33a1e85b29eb7d528d14fe2fa5cff8dfd64d7d (patch)
tree131f6708a5187ffc9534ad049217794842b728a5 /src/java/org/apache/fop
parentdafacc3ff595328433b87b0c75bc706b2d451aa2 (diff)
downloadxmlgraphics-fop-ac33a1e85b29eb7d528d14fe2fa5cff8dfd64d7d.tar.gz
xmlgraphics-fop-ac33a1e85b29eb7d528d14fe2fa5cff8dfd64d7d.zip
Moved MonochromeBitmapConverter from PCL to utility package for later reuse in AFP.
Moved BitmapImageUtil to a subpackage under util. Added support for creating (hard) page segments for images when working in bi-level mode. Include Image Object (IOB) is a newer feature and not supported everywhere. Since page segments cannot be scaled, they have to be generated for each distinctive target size. Bugfix: Reduced maximum chunk sizes for GraphicsData and ImageObject to conform to interchange set 1. Bugfix: Removed PresentationSpaceResetMixingTriplet which is not allowed in interchange set 1. Bugfix: Removed invalid byte in IDE Structure Parameter. Added support for creating FS10 images for bi-level bitmaps for better interoperability. Disabled optional and unnecessary name in ImageSegment. This name is never referenced. Refactored environment groups a bit to avoid duplicate data structures due to subclassing. Added explicit MappingOptionTriplet for image scaling. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@738453 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop')
-rw-r--r--src/java/org/apache/fop/afp/AFPDataObjectInfo.java20
-rw-r--r--src/java/org/apache/fop/afp/AFPResourceInfo.java33
-rw-r--r--src/java/org/apache/fop/afp/AFPResourceManager.java146
-rw-r--r--src/java/org/apache/fop/afp/DataStream.java4
-rw-r--r--src/java/org/apache/fop/afp/goca/GraphicsData.java2
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageContent.java26
-rw-r--r--src/java/org/apache/fop/afp/ioca/ImageSegment.java7
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractDataObject.java2
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java28
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractPageObject.java7
-rw-r--r--src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java44
-rw-r--r--src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java16
-rw-r--r--src/java/org/apache/fop/afp/modca/ImageObject.java8
-rw-r--r--src/java/org/apache/fop/afp/modca/MapImageObject.java58
-rw-r--r--src/java/org/apache/fop/afp/modca/MapPageSegment.java134
-rw-r--r--src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java3
-rw-r--r--src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java32
-rw-r--r--src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java16
-rw-r--r--src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java20
-rw-r--r--src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java71
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLGenerator.java35
-rw-r--r--src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java (renamed from src/java/org/apache/fop/util/BitmapImageUtil.java)45
-rw-r--r--src/java/org/apache/fop/util/bitmap/DefaultMonochromeBitmapConverter.java (renamed from src/java/org/apache/fop/render/pcl/DefaultMonochromeBitmapConverter.java)2
-rw-r--r--src/java/org/apache/fop/util/bitmap/JAIMonochromeBitmapConverter.java (renamed from src/java/org/apache/fop/render/pcl/JAIMonochromeBitmapConverter.java)10
-rw-r--r--src/java/org/apache/fop/util/bitmap/MonochromeBitmapConverter.java (renamed from src/java/org/apache/fop/render/pcl/MonochromeBitmapConverter.java)8
25 files changed, 605 insertions, 172 deletions
diff --git a/src/java/org/apache/fop/afp/AFPDataObjectInfo.java b/src/java/org/apache/fop/afp/AFPDataObjectInfo.java
index f6ff0046a..011118683 100644
--- a/src/java/org/apache/fop/afp/AFPDataObjectInfo.java
+++ b/src/java/org/apache/fop/afp/AFPDataObjectInfo.java
@@ -21,6 +21,7 @@ package org.apache.fop.afp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.afp.modca.Registry;
/**
@@ -53,6 +54,9 @@ public class AFPDataObjectInfo {
/** the object data width resolution */
private int dataWidthRes;
+ /** controls whether to create a page segment or a simple object */
+ private boolean createPageSegment;
+
/**
* Default constructor
*/
@@ -233,6 +237,22 @@ public class AFPDataObjectInfo {
return this.data;
}
+ /**
+ * Controls whether to create a page segment or a normal object.
+ * @param value true for page segments, false for objects
+ */
+ public void setCreatePageSegment(boolean value) {
+ this.createPageSegment = value;
+ }
+
+ /**
+ * Indicates whether a page segment or a normal object shall be created.
+ * @return true for page segments, false for objects
+ */
+ public boolean isCreatePageSegment() {
+ return this.createPageSegment;
+ }
+
/** {@inheritDoc} */
public String toString() {
return "AFPDataObjectInfo{"
diff --git a/src/java/org/apache/fop/afp/AFPResourceInfo.java b/src/java/org/apache/fop/afp/AFPResourceInfo.java
index 729339fa4..99b3d7417 100644
--- a/src/java/org/apache/fop/afp/AFPResourceInfo.java
+++ b/src/java/org/apache/fop/afp/AFPResourceInfo.java
@@ -19,6 +19,8 @@
package org.apache.fop.afp;
+import java.awt.Dimension;
+
/**
* The level at which a resource is to reside in the AFP output
@@ -30,6 +32,12 @@ public class AFPResourceInfo {
/** the uri of this resource */
private String uri = null;
+ /**
+ * the image dimension in page coordinates (non-null only when page segments are
+ * generated because the cannot be scaled for painting).
+ */
+ private Dimension imageDimension = null;
+
/** the reference name of this resource */
private String name = null;
@@ -58,6 +66,26 @@ public class AFPResourceInfo {
}
/**
+ * Sets an optional image dimension (in page coordinates). This is only used if
+ * a page segment is created for this resource as page segments cannot be rescaled
+ * for painting.
+ * @param dim the image dimension (in page coordinates)
+ */
+ public void setImageDimension(Dimension dim) {
+ this.imageDimension = dim;
+ }
+
+ /**
+ * Returns an optional image dimension (in page coordinates). This is only used if
+ * a page segment is created for this resource as page segments cannot be rescaled
+ * for painting.
+ * @return the image dimension (or null if not applicable)
+ */
+ public Dimension getImageDimension() {
+ return this.imageDimension;
+ }
+
+ /**
* Sets the resource reference name
*
* @param resourceName the resource reference name
@@ -109,6 +137,8 @@ public class AFPResourceInfo {
/** {@inheritDoc} */
public String toString() {
return "AFPResourceInfo{uri=" + uri
+ + (imageDimension != null
+ ? ", " + imageDimension.width + "x" + imageDimension.height : "")
+ (name != null ? ", name=" + name : "")
+ (level != null ? ", level=" + level : "")
+ "}";
@@ -126,6 +156,8 @@ public class AFPResourceInfo {
AFPResourceInfo ri = (AFPResourceInfo)obj;
return (uri == ri.uri || uri != null && uri.equals(ri.uri))
+ && (imageDimension == ri.imageDimension
+ || (imageDimension != null && imageDimension.equals(ri.imageDimension)))
&& (name == ri.name || name != null && name.equals(ri.name))
&& (level == ri.level || level != null && level.equals(ri.level));
}
@@ -134,6 +166,7 @@ public class AFPResourceInfo {
public int hashCode() {
int hash = 7;
hash = 31 * hash + (null == uri ? 0 : uri.hashCode());
+ hash = 31 * hash + (null == imageDimension ? 0 : imageDimension.hashCode());
hash = 31 * hash + (null == name ? 0 : name.hashCode());
hash = 31 * hash + (null == level ? 0 : level.hashCode());
return hash;
diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java
index 164ebfd2d..2e36c82a0 100644
--- a/src/java/org/apache/fop/afp/AFPResourceManager.java
+++ b/src/java/org/apache/fop/afp/AFPResourceManager.java
@@ -24,7 +24,9 @@ import java.io.OutputStream;
import java.util.Map;
import org.apache.fop.afp.modca.AbstractNamedAFPObject;
+import org.apache.fop.afp.modca.AbstractPageObject;
import org.apache.fop.afp.modca.IncludeObject;
+import org.apache.fop.afp.modca.PageSegment;
import org.apache.fop.afp.modca.Registry;
import org.apache.fop.afp.modca.ResourceGroup;
@@ -45,10 +47,12 @@ public class AFPResourceManager {
/** Maintain a reference count of instream objects for referencing purposes */
private int instreamObjectCount = 0;
- /** a mapping of resourceInfo --> include name */
- private final Map/*<AFPResourceInfo,String>*/ includeNameMap
+ /** a mapping of resourceInfo --> names of includable objects */
+ private final Map/*<AFPResourceInfo,String>*/ includableObjectsMap
= new java.util.HashMap()/*<AFPResourceInfo,String>*/;
+ private Map pageSegmentMap = new java.util.HashMap();
+
/**
* Main constructor
*/
@@ -112,68 +116,106 @@ public class AFPResourceManager {
AbstractNamedAFPObject namedObj = null;
AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
- String uri = resourceInfo.getUri();
- if (uri == null) {
- uri = "/";
+ updateResourceInfoUri(resourceInfo);
+
+ String objectName = (String)includableObjectsMap.get(resourceInfo);
+ if (objectName != null) {
+ // an existing data resource so reference it by adding an include to the current page
+ includeObject(dataObjectInfo, objectName);
+ return;
}
- // if this is an instream data object adjust the uri to ensure that its unique
- if (uri.endsWith("/")) {
- uri += "#" + (++instreamObjectCount);
- resourceInfo.setUri(uri);
+
+ objectName = (String)pageSegmentMap.get(resourceInfo);
+ if (objectName != null) {
+ // an existing data resource so reference it by adding an include to the current page
+ includePageSegment(dataObjectInfo, objectName);
+ return;
}
- String objectName = (String)includeNameMap.get(resourceInfo);
- if (objectName == null) {
- boolean useInclude = true;
- Registry.ObjectType objectType = null;
-
- // new resource so create
- if (dataObjectInfo instanceof AFPImageObjectInfo) {
- AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo;
- namedObj = dataObjectFactory.createImage(imageObjectInfo);
- } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) {
- AFPGraphicsObjectInfo graphicsObjectInfo = (AFPGraphicsObjectInfo)dataObjectInfo;
- namedObj = dataObjectFactory.createGraphic(graphicsObjectInfo);
- } else {
- // natively embedded data object
- namedObj = dataObjectFactory.createObjectContainer(dataObjectInfo);
- objectType = dataObjectInfo.getObjectType();
- useInclude = objectType != null && objectType.isIncludable();
- }
+ boolean useInclude = true;
+ Registry.ObjectType objectType = null;
- AFPResourceLevel resourceLevel = resourceInfo.getLevel();
- ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel);
- useInclude &= resourceGroup != null;
- if (useInclude) {
- // if it is to reside within a resource group at print-file or external level
- if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) {
- // wrap newly created data object in a resource object
- namedObj = dataObjectFactory.createResource(namedObj, resourceInfo, objectType);
- }
+ // new resource so create
+ if (dataObjectInfo instanceof AFPImageObjectInfo) {
+ AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo;
+ namedObj = dataObjectFactory.createImage(imageObjectInfo);
+ } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) {
+ AFPGraphicsObjectInfo graphicsObjectInfo = (AFPGraphicsObjectInfo)dataObjectInfo;
+ namedObj = dataObjectFactory.createGraphic(graphicsObjectInfo);
+ } else {
+ // natively embedded data object
+ namedObj = dataObjectFactory.createObjectContainer(dataObjectInfo);
+ objectType = dataObjectInfo.getObjectType();
+ useInclude = objectType != null && objectType.isIncludable();
+ }
- // add data object into its resource group destination
- resourceGroup.addObject(namedObj);
+ AFPResourceLevel resourceLevel = resourceInfo.getLevel();
+ ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel);
+ useInclude &= resourceGroup != null;
+ if (useInclude) {
+
+ boolean usePageSegment = dataObjectInfo.isCreatePageSegment();
+
+ // if it is to reside within a resource group at print-file or external level
+ if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) {
+ if (usePageSegment) {
+ String pageSegmentName = "S10" + namedObj.getName().substring(3);
+ namedObj.setName(pageSegmentName);
+ PageSegment seg = new PageSegment(pageSegmentName);
+ seg.addObject(namedObj);
+ namedObj = seg;
+ }
- // create the include object
- objectName = namedObj.getName();
- IncludeObject includeObject
- = dataObjectFactory.createInclude(objectName, dataObjectInfo);
+ // wrap newly created data object in a resource object
+ namedObj = dataObjectFactory.createResource(namedObj, resourceInfo, objectType);
+ }
- // add an include to the current page
- dataStream.getCurrentPage().addObject(includeObject);
+ // add data object into its resource group destination
+ resourceGroup.addObject(namedObj);
- // record mapping of resource info to data object resource name
- includeNameMap.put(resourceInfo, objectName);
+ // create the include object
+ objectName = namedObj.getName();
+ if (usePageSegment) {
+ includePageSegment(dataObjectInfo, objectName);
+ pageSegmentMap.put(resourceInfo, objectName);
} else {
- // not to be included so inline data object directly into the current page
- dataStream.getCurrentPage().addObject(namedObj);
+ includeObject(dataObjectInfo, objectName);
+ // record mapping of resource info to data object resource name
+ includableObjectsMap.put(resourceInfo, objectName);
}
+
} else {
- // an existing data resource so reference it by adding an include to the current page
- IncludeObject includeObject
- = dataObjectFactory.createInclude(objectName, dataObjectInfo);
- dataStream.getCurrentPage().addObject(includeObject);
+ // not to be included so inline data object directly into the current page
+ dataStream.getCurrentPage().addObject(namedObj);
+ }
+ }
+
+ private void updateResourceInfoUri(AFPResourceInfo resourceInfo) {
+ String uri = resourceInfo.getUri();
+ if (uri == null) {
+ uri = "/";
}
+ // if this is an instream data object adjust the uri to ensure that its unique
+ if (uri.endsWith("/")) {
+ uri += "#" + (++instreamObjectCount);
+ resourceInfo.setUri(uri);
+ }
+ }
+
+ private void includeObject(AFPDataObjectInfo dataObjectInfo,
+ String objectName) {
+ IncludeObject includeObject
+ = dataObjectFactory.createInclude(objectName, dataObjectInfo);
+ dataStream.getCurrentPage().addObject(includeObject);
+ }
+
+ private void includePageSegment(AFPDataObjectInfo dataObjectInfo,
+ String pageSegmentName) {
+ int x = dataObjectInfo.getObjectAreaInfo().getX();
+ int y = dataObjectInfo.getObjectAreaInfo().getY();
+ AbstractPageObject currentPage = dataStream.getCurrentPage();
+ boolean createHardPageSegments = true;
+ currentPage.createIncludePageSegment(pageSegmentName, x, y, createHardPageSegments);
}
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/DataStream.java b/src/java/org/apache/fop/afp/DataStream.java
index ea620b867..70d7b7cb0 100644
--- a/src/java/org/apache/fop/afp/DataStream.java
+++ b/src/java/org/apache/fop/afp/DataStream.java
@@ -29,6 +29,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.AFPFontAttributes;
import org.apache.fop.afp.modca.AbstractPageObject;
@@ -464,7 +465,8 @@ public class DataStream {
yOrigin = y;
break;
}
- currentPage.createIncludePageSegment(name, xOrigin, yOrigin);
+ boolean createHardPageSegments = true;
+ currentPage.createIncludePageSegment(name, xOrigin, yOrigin, createHardPageSegments);
}
/**
diff --git a/src/java/org/apache/fop/afp/goca/GraphicsData.java b/src/java/org/apache/fop/afp/goca/GraphicsData.java
index 89be8dd94..c75057dc5 100644
--- a/src/java/org/apache/fop/afp/goca/GraphicsData.java
+++ b/src/java/org/apache/fop/afp/goca/GraphicsData.java
@@ -32,7 +32,7 @@ import org.apache.fop.afp.util.StringUtils;
public final class GraphicsData extends AbstractGraphicsDrawingOrderContainer {
/** the maximum graphics data length */
- public static final int MAX_DATA_LEN = 32767;
+ public static final int MAX_DATA_LEN = 8192;
/** the graphics segment */
private GraphicsChainedSegment currentSegment = null;
diff --git a/src/java/org/apache/fop/afp/ioca/ImageContent.java b/src/java/org/apache/fop/afp/ioca/ImageContent.java
index bdb2455d9..fe902b381 100644
--- a/src/java/org/apache/fop/afp/ioca/ImageContent.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageContent.java
@@ -155,9 +155,12 @@ public class ImageContent extends AbstractStructuredObject {
os.write(getImageIDESizeParameter());
- os.write(getIDEStructureParameter());
+ boolean useFS10 = (this.size == 1);
+ if (!useFS10) {
+ os.write(getIDEStructureParameter());
- os.write(getExternalAlgorithmParameter());
+ os.write(getExternalAlgorithmParameter());
+ }
final byte[] dataHeader = new byte[] {
(byte)0xFE, // ID
@@ -240,12 +243,15 @@ public class ImageContent extends AbstractStructuredObject {
* @return byte[] The data stream.
*/
private byte[] getImageIDESizeParameter() {
- final byte[] ideSizeData = new byte[] {
- (byte)0x96, // ID
- 0x01, // Length
- size,
- };
- return ideSizeData;
+ if (size != 1) {
+ final byte[] ideSizeData = new byte[] {
+ (byte)0x96, // ID
+ 0x01, // Length
+ size};
+ return ideSizeData;
+ } else {
+ return new byte[0];
+ }
}
/**
@@ -264,7 +270,6 @@ public class ImageContent extends AbstractStructuredObject {
(byte)0x9B, // ID
0x00, // Length
flags, // FLAGS
- 0x00, // Reserved
colorModel, // COLOR MODEL
0x00, // Reserved
0x00, // Reserved
@@ -280,12 +285,11 @@ public class ImageContent extends AbstractStructuredObject {
(byte)0x9B, // ID
0x00, // Length
flags, // FLAGS
- 0x00, // Reserved
colorModel, // COLOR MODEL
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
- 1
+ 0x01
};
ideStructData[1] = (byte)(ideStructData.length - 2);
return ideStructData;
diff --git a/src/java/org/apache/fop/afp/ioca/ImageSegment.java b/src/java/org/apache/fop/afp/ioca/ImageSegment.java
index 5ecbc63bb..d8ba38ec0 100644
--- a/src/java/org/apache/fop/afp/ioca/ImageSegment.java
+++ b/src/java/org/apache/fop/afp/ioca/ImageSegment.java
@@ -146,14 +146,17 @@ public class ImageSegment extends AbstractNamedAFPObject {
/** {@inheritDoc} */
protected void writeStart(OutputStream os) throws IOException {
- byte[] nameBytes = getNameBytes();
+ //Name disabled, it's optional and not referenced by our code
+ //byte[] nameBytes = getNameBytes();
byte[] data = new byte[] {
0x70, // ID
- 0x04, // Length
+ 0x00, // Length
+ /*
nameBytes[0], // Name byte 1
nameBytes[1], // Name byte 2
nameBytes[2], // Name byte 3
nameBytes[3], // Name byte 4
+ */
};
os.write(data);
}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractDataObject.java b/src/java/org/apache/fop/afp/modca/AbstractDataObject.java
index 4a13b4a55..fcab3cb4a 100644
--- a/src/java/org/apache/fop/afp/modca/AbstractDataObject.java
+++ b/src/java/org/apache/fop/afp/modca/AbstractDataObject.java
@@ -90,6 +90,8 @@ public abstract class AbstractDataObject extends AbstractNamedAFPObject implemen
// positional values are specified in the oaOffset of the include object
objectAreaPosition = factory.createObjectAreaPosition(0, 0, 0);
}
+ objectAreaPosition.setReferenceCoordinateSystem(
+ ObjectAreaPosition.REFCSYS_PAGE_SEGMENT_RELATIVE);
getObjectEnvironmentGroup().setObjectAreaPosition(objectAreaPosition);
}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java
index a58bba1f0..4ba9abff8 100644
--- a/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java
+++ b/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java
@@ -5,9 +5,9 @@
* 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.
@@ -29,14 +29,15 @@ import java.util.List;
*/
public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject {
- /**
- * The collection of MapPageOverlay objects
- */
+ /** the collection of MapDataResource objects */
+ protected final List mapDataResources = null;
+
+ /** the collection of MapPageOverlay objects */
protected List mapPageOverlays = null;
/**
* Main constructor
- *
+ *
* @param name the object name
*/
public AbstractEnvironmentGroup(String name) {
@@ -53,7 +54,7 @@ public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject {
/**
* Actually creates the MPO object.
* Also creates the supporting object (an IPO)
- *
+ *
* @param name the name of the overlay to be used
*/
public void createOverlay(String name) {
@@ -80,12 +81,16 @@ public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject {
/**
* Getter method for the most recent MapPageOverlay added to the
* Active Environment Group (returns null if no MapPageOverlay exist)
- *
+ *
* @return the most recent Map Coded Font
*/
private MapPageOverlay getCurrentMapPageOverlay() {
- if (mapPageOverlays != null && mapPageOverlays.size() > 0) {
- return (MapPageOverlay) mapPageOverlays.get(mapPageOverlays.size() - 1);
+ return (MapPageOverlay)getLastElement(this.mapPageOverlays);
+ }
+
+ protected Object getLastElement(List list) {
+ if (list != null && list.size() > 0) {
+ return list.get(list.size() - 1);
} else {
return null;
}
@@ -94,8 +99,5 @@ public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject {
/** {@inheritDoc} */
protected void writeContent(OutputStream os) throws IOException {
super.writeContent(os);
- if (mapPageOverlays != null) {
- writeObjects(mapPageOverlays, os);
- }
}
}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
index d17c06c6a..1c686a289 100644
--- a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
+++ b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
@@ -249,9 +249,14 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject implemen
* @param y
* the y coordinate of the page segment.
*/
- public void createIncludePageSegment(String name, int x, int y) {
+ public void createIncludePageSegment(String name, int x, int y, boolean hard) {
IncludePageSegment ips = factory.createIncludePageSegment(name, x, y);
addObject(ips);
+ if (hard) {
+ //For performance reasons, page segments can be turned into hard page segments
+ //using the Map Page Segment (MPS) structured field.
+ getActiveEnvironmentGroup().addMapPageSegment(name);
+ }
}
/**
diff --git a/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java
index ddc986be3..ecdfa0157 100644
--- a/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java
+++ b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java
@@ -45,8 +45,8 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup {
private final List/*<MapCodedFonts>*/ mapCodedFonts
= new java.util.ArrayList/*<MapCodedFonts>*/();
- /** the collection of MapDataResource objects */
- private final List mapDataResources = null;
+ /** the collection of MapPageSegments objects */
+ private List mapPageSegments = null;
/** the Object Area Descriptor for the active environment group */
private ObjectAreaDescriptor objectAreaDescriptor = null;
@@ -132,6 +132,7 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup {
writeObjects(mapCodedFonts, os);
writeObjects(mapDataResources, os);
writeObjects(mapPageOverlays, os);
+ writeObjects(mapPageSegments, os);
if (pageDescriptor != null) {
pageDescriptor.writeToStream(os);
@@ -204,18 +205,29 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup {
}
}
-// private List getMapDataResources() {
-// if (mapDataResources == null) {
-// mapDataResources = new java.util.ArrayList();
-// }
-// return mapDataResources;
-//}
-
-// /**
-// * Method to create a map data resource object
-// * @param dataObjectAccessor a data object accessor
-// */
-// protected void createMapDataResource(DataObjectAccessor dataObjectAccessor) {
-// getMapDataResources().add(new MapDataResource(dataObjectAccessor));
-// }
+ public void addMapPageSegment(String name) {
+ try {
+ needMapPageSegment().addPageSegment(name);
+ } catch (MaximumSizeExceededException e) {
+ //Should not happen, handled internally
+ throw new IllegalStateException("Internal error: " + e.getMessage());
+ }
+ }
+
+ private MapPageSegment getCurrentMapPageSegment() {
+ return (MapPageSegment)getLastElement(this.mapPageSegments);
+ }
+
+ private MapPageSegment needMapPageSegment() {
+ if (this.mapPageSegments == null) {
+ this.mapPageSegments = new java.util.ArrayList();
+ }
+ MapPageSegment seg = getCurrentMapPageSegment();
+ if (seg == null || seg.isFull()) {
+ seg = new MapPageSegment();
+ this.mapPageSegments.add(seg);
+ }
+ return seg;
+ }
+
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java
index 07976e18a..0a7b665d7 100644
--- a/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java
+++ b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java
@@ -29,6 +29,11 @@ import org.apache.fop.afp.util.BinaryUtils;
*/
public class ImageDataDescriptor extends AbstractDescriptor {
+ public static final byte FUNCTION_SET_FS10 = 0x0A;
+ public static final byte FUNCTION_SET_FS11 = 0x0B;
+
+ private byte functionSet = FUNCTION_SET_FS11; // FCNSET = IOCA FS 11
+
/**
* Constructor for a ImageDataDescriptor for the specified
* resolution, width and height.
@@ -42,6 +47,14 @@ public class ImageDataDescriptor extends AbstractDescriptor {
super(width, height, widthRes, heightRes);
}
+ /**
+ * Sets the IOCA function set to be used.
+ * @param functionSet the function set (0x0A for FS 10, 0x0B for FS 11, etc.)
+ */
+ public void setFunctionSet(byte functionSet) {
+ this.functionSet = functionSet;
+ }
+
/** {@inheritDoc} */
public void writeToStream(OutputStream os) throws IOException {
byte[] data = new byte[22];
@@ -68,10 +81,11 @@ public class ImageDataDescriptor extends AbstractDescriptor {
data[16] = h[0];
data[17] = h[1];
+ //IOCA Function Set Field
data[18] = (byte)0xF7; // ID = Set IOCA Function Set
data[19] = 0x02; // Length
data[20] = 0x01; // Category = Function set identifier
- data[21] = 0x0B; // FCNSET = IOCA FS 11
+ data[21] = functionSet;
os.write(data);
}
diff --git a/src/java/org/apache/fop/afp/modca/ImageObject.java b/src/java/org/apache/fop/afp/modca/ImageObject.java
index b11d478cc..bbbc25bea 100644
--- a/src/java/org/apache/fop/afp/modca/ImageObject.java
+++ b/src/java/org/apache/fop/afp/modca/ImageObject.java
@@ -28,13 +28,14 @@ import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPImageObjectInfo;
import org.apache.fop.afp.Factory;
import org.apache.fop.afp.ioca.ImageSegment;
+import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
/**
* An IOCA Image Data Object
*/
public class ImageObject extends AbstractDataObject {
- private static final int MAX_DATA_LEN = 32759;
+ private static final int MAX_DATA_LEN = 8192;
/** the image segment */
private ImageSegment imageSegment = null;
@@ -73,7 +74,12 @@ public class ImageObject extends AbstractDataObject {
int dataHeightRes = imageObjectInfo.getDataWidthRes();
ImageDataDescriptor imageDataDescriptor
= factory.createImageDataDescriptor(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
+ if (imageObjectInfo.getBitsPerPixel() == 1) {
+ imageDataDescriptor.setFunctionSet(ImageDataDescriptor.FUNCTION_SET_FS10);
+ }
getObjectEnvironmentGroup().setDataDescriptor(imageDataDescriptor);
+ getObjectEnvironmentGroup().setMapImageObject(
+ new MapImageObject(MappingOptionTriplet.SCALE_TO_FILL));
getImageSegment().setImageSize(dataWidth, dataHeight, dataWidthRes, dataHeightRes);
}
diff --git a/src/java/org/apache/fop/afp/modca/MapImageObject.java b/src/java/org/apache/fop/afp/modca/MapImageObject.java
new file mode 100644
index 000000000..b1e258bb0
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/MapImageObject.java
@@ -0,0 +1,58 @@
+/*
+ * 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.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Map Image Object (MIO) structured field specifies how an image data object is
+ * mapped into its object area.
+ */
+public class MapImageObject extends AbstractTripletStructuredObject {
+
+ /**
+ * Constructor for the Map Image Object.
+ * @param mappingOption the mapping option (see {@link MappingOptionTriplet}.*)
+ */
+ public MapImageObject(byte mappingOption) {
+ addTriplet(new MappingOptionTriplet(mappingOption));
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ byte[] data = new byte[11];
+ copySF(data, Type.MAP, Category.IMAGE);
+ int tripletLen = getTripletDataLength();
+
+ byte[] len = BinaryUtils.convert(10 + tripletLen, 2);
+ data[1] = len[0];
+ data[2] = len[1];
+
+ len = BinaryUtils.convert(2 + tripletLen, 2);
+ data[9] = len[0];
+ data[10] = len[1];
+ os.write(data);
+ writeTriplets(os);
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/MapPageSegment.java b/src/java/org/apache/fop/afp/modca/MapPageSegment.java
new file mode 100644
index 000000000..e2afd0257
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/MapPageSegment.java
@@ -0,0 +1,134 @@
+/*
+ * 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.modca;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.util.BinaryUtils;
+
+/**
+ * The Map Page Segment structured field identifies page segments that are required to present
+ * a page on a physical medium.
+ */
+public class MapPageSegment extends AbstractAFPObject {
+
+ private static final int MAX_SIZE = 127;
+
+ /**
+ * The collection of page segments (maximum of 127 stored as String)
+ */
+ private Set pageSegments = null;
+
+ /**
+ * Constructor for the Map Page Overlay
+ */
+ public MapPageSegment() {
+ }
+
+ private Set getPageSegments() {
+ if (pageSegments == null) {
+ this.pageSegments = new java.util.HashSet();
+ }
+ return this.pageSegments;
+ }
+
+ /**
+ * Add a page segment to to the map page segment object.
+ * @param name the name of the page segment.
+ * @throws MaximumSizeExceededException if the maximum size is reached
+ */
+ public void addPageSegment(String name) throws MaximumSizeExceededException {
+ if (getPageSegments().size() > MAX_SIZE) {
+ throw new MaximumSizeExceededException();
+ }
+ if (name.length() > 8) {
+ throw new IllegalArgumentException("The name of page segment " + name
+ + " must not be longer than 8 characters");
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("addPageSegment():: adding page segment " + name);
+ }
+ getPageSegments().add(name);
+ }
+
+ /**
+ * Indicates whether this object already contains the maximum number of
+ * page segments.
+ * @return true if the object is full
+ */
+ public boolean isFull() {
+ return this.pageSegments.size() >= MAX_SIZE;
+ }
+
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+ int count = getPageSegments().size();
+ byte groupLength = 0x0C;
+ int groupsLength = count * groupLength;
+
+ byte[] data = new byte[groupsLength + 12 + 1];
+
+ data[0] = 0x5A;
+
+ // Set the total record length
+ byte[] rl1 = BinaryUtils.convert(data.length - 1, 2); //Ignore the
+ // first byte in
+ // the length
+ data[1] = rl1[0];
+ data[2] = rl1[1];
+
+ // Structured field ID for a MPS
+ data[3] = (byte) 0xD3;
+ data[4] = Type.MIGRATION;
+ data[5] = Category.PAGE_SEGMENT;
+
+ data[6] = 0x00; // Flags
+ data[7] = 0x00; // Reserved
+ data[8] = 0x00; // Reserved
+
+ data[9] = groupLength;
+ data[10] = 0x00; // Reserved
+ data[11] = 0x00; // Reserved
+ data[12] = 0x00; // Reserved
+
+ int pos = 13;
+
+ Iterator iter = this.pageSegments.iterator();
+ while (iter.hasNext()) {
+ pos += 4;
+
+ String name = (String)iter.next();
+ try {
+ byte[] nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ System.arraycopy(nameBytes, 0, data, pos, nameBytes.length);
+ } catch (UnsupportedEncodingException usee) {
+ log.error("UnsupportedEncodingException translating the name "
+ + name);
+ }
+ pos += 8;
+ }
+ os.write(data);
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java
index 25323b864..6ab2ea734 100644
--- a/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java
+++ b/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java
@@ -25,7 +25,6 @@ import java.io.OutputStream;
import org.apache.fop.afp.modca.triplets.DescriptorPositionTriplet;
import org.apache.fop.afp.modca.triplets.MeasurementUnitsTriplet;
import org.apache.fop.afp.modca.triplets.ObjectAreaSizeTriplet;
-import org.apache.fop.afp.modca.triplets.PresentationSpaceResetMixingTriplet;
import org.apache.fop.afp.util.BinaryUtils;
/**
@@ -57,8 +56,10 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
addTriplet(new DescriptorPositionTriplet(OBJECT_AREA_POSITION_ID));
addTriplet(new MeasurementUnitsTriplet(widthRes, heightRes));
addTriplet(new ObjectAreaSizeTriplet(width, height));
+ /* not allowed in Presentation Interchange Set 1
addTriplet(new PresentationSpaceResetMixingTriplet(
PresentationSpaceResetMixingTriplet.NOT_RESET));
+ */
int tripletDataLength = getTripletDataLength();
byte[] len = BinaryUtils.convert(data.length + tripletDataLength - 1, 2);
diff --git a/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java
index 3929c1196..d40454998 100644
--- a/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java
+++ b/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java
@@ -31,11 +31,20 @@ import org.apache.fop.afp.util.BinaryUtils;
*/
public class ObjectAreaPosition extends AbstractAFPObject {
+ /**
+ * Object areas will be positioned with respect to a point that is define by the
+ * Include Page Segment (IPS) structured field.
+ */
+ public static final byte REFCSYS_PAGE_SEGMENT_RELATIVE = 0x00;
+ /** Object areas will be positioned with respect to the standard origin */
+ public static final byte REFCSYS_PAGE_RELATIVE = 0x01;
+
private final int x;
private final int y;
private final int rotation;
private int xOffset;
private int yOffset;
+ private byte refCSys = 0x01; //Page or overlay coordinate system
/**
* Construct an object area position for the specified object y, y position.
@@ -45,9 +54,30 @@ 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) {
+ this(x, y, rotation, REFCSYS_PAGE_RELATIVE);
+ }
+
+ /**
+ * Construct an object area position for the specified object y, y position.
+ *
+ * @param x The x coordinate.
+ * @param y The y coordinate.
+ * @param rotation The coordinate system rotation (must be 0, 90, 180, 270).
+ * @param refCSys the reference coordinate system (normally 0x01)
+ */
+ public ObjectAreaPosition(int x, int y, int rotation, byte refCSys) {
this.x = x;
this.y = y;
this.rotation = rotation;
+ setReferenceCoordinateSystem(refCSys);
+ }
+
+ /**
+ * Sets the reference coordinate system.
+ * @param refCSys the reference coordinate system (normally 0x01)
+ */
+ public void setReferenceCoordinateSystem(byte refCSys) {
+ this.refCSys = refCSys;
}
/** {@inheritDoc} */
@@ -94,7 +124,7 @@ public class ObjectAreaPosition extends AbstractAFPObject {
data[30] = 0x2D; // YocaOrent
data[31] = 0x00;
- data[32] = 0x01; // RefCSys
+ data[32] = this.refCSys; // RefCSys
os.write(data);
}
diff --git a/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java
index bc0cc5a63..359f68602 100644
--- a/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java
+++ b/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java
@@ -46,6 +46,9 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
/** the ObjectAreaPosition for the object environment group */
private ObjectAreaPosition objectAreaPosition;
+ /** the MapImageObject for the object environment group (optional) */
+ private MapImageObject mapImageObject;
+
/** the DataDescriptor for the object environment group */
private AbstractDescriptor dataDescriptor;
@@ -83,6 +86,15 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
this.objectAreaPosition = objectAreaPosition;
}
+ /**
+ * Sets the Map Image Object (MIO).
+ *
+ * @param mapImageObject the MIO structured field
+ */
+ public void setMapImageObject(MapImageObject mapImageObject) {
+ this.mapImageObject = mapImageObject;
+ }
+
/** {@inheritDoc} */
protected void writeStart(OutputStream os) throws IOException {
byte[] data = new byte[17];
@@ -115,6 +127,10 @@ public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {
objectAreaPosition.writeToStream(os);
}
+ if (mapImageObject != null) {
+ mapImageObject.writeToStream(os);
+ }
+
if (mapContainerData != null) {
mapContainerData.writeToStream(os);
}
diff --git a/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java
index 2e4f57314..9a898ef4d 100644
--- a/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java
+++ b/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java
@@ -34,12 +34,6 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup implement
/** default name for the resource group */
private static final String DEFAULT_NAME = "REG00001";
- /** the maps data resources contained in this resource environment group */
- private List/*<MapDataResource>*/ mapDataResources = null;
-
- /** the maps page overlays contained in this resource environment group */
- private List mapPageOverlays = null;
-
/** the pre-process presentation objects contained in this resource environment group */
private List/*<PreprocessPresentationObject>*/ preProcessPresentationObjects = null;
@@ -53,20 +47,6 @@ public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup implement
this(DEFAULT_NAME);
}
- private List/*<MapDataResource>*/ getMapDataResources() {
- if (mapDataResources == null) {
- this.mapDataResources = new java.util.ArrayList/*<MapDataResource>*/();
- }
- return this.mapDataResources;
- }
-
- private List getMapPageOverlays() {
- if (mapPageOverlays == null) {
- this.mapPageOverlays = new java.util.ArrayList();
- }
- return this.mapPageOverlays;
- }
-
private List/*<PreprocessPresentationObject>*/ getPreprocessPresentationObjects() {
if (preProcessPresentationObjects == null) {
this.preProcessPresentationObjects
diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
index 66915ec2d..ac3a5fe98 100644
--- a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
+++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
@@ -19,6 +19,7 @@
package org.apache.fop.render.afp;
+import java.awt.Dimension;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.io.IOException;
@@ -28,15 +29,18 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageInfo;
+import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
import org.apache.xmlgraphics.ps.ImageEncodingHelper;
import org.apache.xmlgraphics.util.MimeConstants;
+import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPImageObjectInfo;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
-import org.apache.fop.util.BitmapImageUtil;
+import org.apache.fop.util.bitmap.BitmapImageUtil;
/**
* PDFImageHandler implementation which handles RenderedImage instances.
@@ -62,25 +66,59 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler {
AFPInfo afpInfo = rendererContext.getInfo();
AFPPaintingState paintingState = afpInfo.getPaintingState();
int resolution = paintingState.getResolution();
-
- imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);
- imageObjectInfo.setDataHeightRes(resolution);
- imageObjectInfo.setDataWidthRes(resolution);
-
+ int maxPixelSize = paintingState.getBitsPerPixel();
+ if (paintingState.isColorImages()) {
+ maxPixelSize *= 3; //RGB only at the moment
+ }
ImageRendered imageRendered = (ImageRendered) rendererImageInfo.img;
RenderedImage renderedImage = imageRendered.getRenderedImage();
+ ImageInfo imageInfo = rendererImageInfo.getImageInfo();
+ ImageSize intrinsicSize = imageInfo.getSize();
+
+ boolean useFS10 = (maxPixelSize == 1) || BitmapImageUtil.isMonochromeImage(renderedImage);
+ boolean usePageSegments = useFS10 && !imageObjectInfo.getResourceInfo().getLevel().isInline();
+
+ ImageSize effIntrinsicSize = intrinsicSize;
+ if (usePageSegments) {
+ //Resize, optionally resample and convert image
+ Dimension resampledDim = new Dimension(
+ (int)Math.ceil(UnitConv.mpt2px(afpInfo.getWidth(), resolution)),
+ (int)Math.ceil(UnitConv.mpt2px(afpInfo.getHeight(), resolution)));
+
+ imageObjectInfo.setCreatePageSegment(true);
+ imageObjectInfo.getResourceInfo().setImageDimension(resampledDim);
+
+ //Only resample/downsample if image is smaller than its intrinsic size
+ //to make print file smaller
+ boolean resample = resampledDim.width < renderedImage.getWidth()
+ && resampledDim.height < renderedImage.getHeight();
+ if (resample) {
+ if (log.isDebugEnabled()) {
+ log.debug("Resample from " + intrinsicSize.getDimensionPx()
+ + " to " + resampledDim);
+ }
+ renderedImage = BitmapImageUtil.convertToMonochrome(renderedImage, resampledDim);
+ effIntrinsicSize = new ImageSize(resampledDim.width, resampledDim.height, resolution);
+ }
+ }
+ if (useFS10) {
+ imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS10);
+ } else {
+ imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS11);
+ }
+
+ imageObjectInfo.setDataHeightRes((int)Math.round(
+ effIntrinsicSize.getDpiHorizontal() * 10));
+ imageObjectInfo.setDataWidthRes((int)Math.round(
+ effIntrinsicSize.getDpiVertical() * 10));
+
int dataHeight = renderedImage.getHeight();
imageObjectInfo.setDataHeight(dataHeight);
int dataWidth = renderedImage.getWidth();
imageObjectInfo.setDataWidth(dataWidth);
- int maxPixelSize = paintingState.getBitsPerPixel();
- if (paintingState.isColorImages()) {
- maxPixelSize *= 3; //RGB only at the moment
- }
-
ColorModel cm = renderedImage.getColorModel();
if (log.isTraceEnabled()) {
log.trace("ColorModel: " + cm);
@@ -105,11 +143,16 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler {
if (BitmapImageUtil.getColorIndexSize(renderedImage) > 2) {
directEncode = false; //Lookup tables are not implemented, yet
}
+ if (useFS10
+ && BitmapImageUtil.isMonochromeImage(renderedImage)
+ && BitmapImageUtil.isZeroBlack(renderedImage)) {
+ directEncode = false;
+ }
if (directEncode) {
log.debug("Encoding image directly...");
imageObjectInfo.setBitsPerPixel(encodedColorModel.getPixelSize());
if (BitmapImageUtil.isMonochromeImage(renderedImage)
- && !BitmapImageUtil.isZeroBlack(renderedImage)) {
+ && BitmapImageUtil.isZeroBlack(renderedImage)) {
log.trace("set subtractive mode");
imageObjectInfo.setSubtractive(true);
}
@@ -120,6 +163,7 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler {
}
if (imageData == null) {
log.debug("Encoding image via RGB...");
+
//Convert image to 24bit RGB
ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos);
imageData = baos.toByteArray();
@@ -138,6 +182,9 @@ public class AFPImageHandlerRenderedImage extends AFPImageHandler {
ImageEncodingHelper.encodeRGBAsGrayScale(
imageData, dataWidth, dataHeight, bitsPerPixel, baos);
imageData = baos.toByteArray();
+ if (bitsPerPixel == 1) {
+ imageObjectInfo.setSubtractive(true);
+ }
}
}
diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java
index 50cf622c7..1060b9bb6 100644
--- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java
+++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java
@@ -47,7 +47,8 @@ import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.xmlgraphics.image.GraphicsUtil;
import org.apache.xmlgraphics.util.UnitConv;
-import org.apache.fop.util.BitmapImageUtil;
+import org.apache.fop.util.bitmap.BitmapImageUtil;
+import org.apache.fop.util.bitmap.MonochromeBitmapConverter;
/**
* This class provides methods for generating PCL print files.
@@ -588,31 +589,6 @@ public class PCLGenerator {
return BitmapImageUtil.isGrayscaleImage(img);
}
- private MonochromeBitmapConverter createMonochromeBitmapConverter() {
- MonochromeBitmapConverter converter = null;
- try {
- String clName = "org.apache.fop.render.pcl.JAIMonochromeBitmapConverter";
- Class clazz = Class.forName(clName);
- converter = (MonochromeBitmapConverter)clazz.newInstance();
- } catch (ClassNotFoundException cnfe) {
- // Class was not compiled so is not available. Simply ignore.
- } catch (LinkageError le) {
- // This can happen if fop was build with support for a
- // particular provider (e.g. a binary fop distribution)
- // but the required support files (i.e. JAI) are not
- // available in the current runtime environment.
- // Simply continue with the backup implementation.
- } catch (InstantiationException e) {
- // Problem instantiating the class, simply continue with the backup implementation
- } catch (IllegalAccessException e) {
- // Problem instantiating the class, simply continue with the backup implementation
- }
- if (converter == null) {
- converter = new DefaultMonochromeBitmapConverter();
- }
- return converter;
- }
-
private int calculatePCLResolution(int resolution) {
return calculatePCLResolution(resolution, false);
}
@@ -764,12 +740,11 @@ public class PCLGenerator {
if (src == null) {
src = BitmapImageUtil.convertToGrayscale(img, effDim);
}
- MonochromeBitmapConverter converter = createMonochromeBitmapConverter();
+ MonochromeBitmapConverter converter
+ = BitmapImageUtil.createDefaultMonochromeBitmapConverter();
converter.setHint("quality", "false");
- BufferedImage buf = (BufferedImage)converter.convertToMonochrome(src);
-
- RenderedImage red = buf;
+ RenderedImage red = converter.convertToMonochrome(src);
selectCurrentPattern(0, 0); //Solid black
setTransparencyMode(sourceTransparency || mask != null, true);
paintMonochromeBitmap(red, effResolution);
diff --git a/src/java/org/apache/fop/util/BitmapImageUtil.java b/src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java
index 278587b64..cb46395ca 100644
--- a/src/java/org/apache/fop/util/BitmapImageUtil.java
+++ b/src/java/org/apache/fop/util/bitmap/BitmapImageUtil.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.util;
+package org.apache.fop.util.bitmap;
import java.awt.Color;
import java.awt.Dimension;
@@ -27,6 +27,7 @@ import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
+import java.awt.image.WritableRaster;
/**
* Utility method for dealing with bitmap images.
@@ -149,6 +150,23 @@ public class BitmapImageUtil {
return target;
}
+ /**
+ * Returns a BufferedImage based on the given RenderedImage. In the easiest case,
+ * this is a simple typecast. Otherwise, the image is converted to a BufferedImage.
+ * @param img the original image
+ * @return the buffered image
+ */
+ public static BufferedImage toBufferedImage(RenderedImage img) {
+ if (img instanceof BufferedImage) {
+ return (BufferedImage)img;
+ } else {
+ WritableRaster wr = img.getColorModel().createCompatibleWritableRaster(
+ img.getWidth(), img.getHeight());
+ boolean premult = img.getColorModel().isAlphaPremultiplied();
+ return new BufferedImage(img.getColorModel(), wr, premult, null);
+ }
+ }
+
private static void transferImage(RenderedImage source, BufferedImage target) {
Graphics2D g2d = target.createGraphics();
try {
@@ -169,5 +187,30 @@ public class BitmapImageUtil {
}
}
+ public static MonochromeBitmapConverter createDefaultMonochromeBitmapConverter() {
+ MonochromeBitmapConverter converter = null;
+ try {
+ String clName = "org.apache.fop.util.bitmap.JAIMonochromeBitmapConverter";
+ Class clazz = Class.forName(clName);
+ converter = (MonochromeBitmapConverter)clazz.newInstance();
+ } catch (ClassNotFoundException cnfe) {
+ // Class was not compiled so is not available. Simply ignore.
+ } catch (LinkageError le) {
+ // This can happen if fop was build with support for a
+ // particular provider (e.g. a binary fop distribution)
+ // but the required support files (i.e. JAI) are not
+ // available in the current runtime environment.
+ // Simply continue with the backup implementation.
+ } catch (InstantiationException e) {
+ // Problem instantiating the class, simply continue with the backup implementation
+ } catch (IllegalAccessException e) {
+ // Problem instantiating the class, simply continue with the backup implementation
+ }
+ if (converter == null) {
+ converter = new DefaultMonochromeBitmapConverter();
+ }
+ return converter;
+ }
+
}
diff --git a/src/java/org/apache/fop/render/pcl/DefaultMonochromeBitmapConverter.java b/src/java/org/apache/fop/util/bitmap/DefaultMonochromeBitmapConverter.java
index 418810401..8df5603fb 100644
--- a/src/java/org/apache/fop/render/pcl/DefaultMonochromeBitmapConverter.java
+++ b/src/java/org/apache/fop/util/bitmap/DefaultMonochromeBitmapConverter.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.pcl;
+package org.apache.fop.util.bitmap;
import java.awt.RenderingHints;
import java.awt.color.ColorSpace;
diff --git a/src/java/org/apache/fop/render/pcl/JAIMonochromeBitmapConverter.java b/src/java/org/apache/fop/util/bitmap/JAIMonochromeBitmapConverter.java
index e9611edac..ab32970fc 100644
--- a/src/java/org/apache/fop/render/pcl/JAIMonochromeBitmapConverter.java
+++ b/src/java/org/apache/fop/util/bitmap/JAIMonochromeBitmapConverter.java
@@ -17,7 +17,7 @@
/* $Id$ */
-package org.apache.fop.render.pcl;
+package org.apache.fop.util.bitmap;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
@@ -56,8 +56,12 @@ public class JAIMonochromeBitmapConverter implements
/** {@inheritDoc} */
public RenderedImage convertToMonochrome(BufferedImage img) {
+ return convertToMonochromePlanarImage(img);
+ }
+
+ private PlanarImage convertToMonochromePlanarImage(BufferedImage img) {
if (img.getColorModel().getColorSpace().getNumComponents() != 1) {
- throw new IllegalArgumentException("Source image must be a grayscale image!");
+ img = BitmapImageUtil.convertToGrayscale(img, null);
}
// Load the ParameterBlock for the dithering operation
@@ -92,7 +96,7 @@ public class JAIMonochromeBitmapConverter implements
PlanarImage dst = JAI.create(opName, pb, hints);
//Convert it to a BufferedImage
- return dst.getAsBufferedImage();
+ return dst;
}
}
diff --git a/src/java/org/apache/fop/render/pcl/MonochromeBitmapConverter.java b/src/java/org/apache/fop/util/bitmap/MonochromeBitmapConverter.java
index 9a960f871..880ba0265 100644
--- a/src/java/org/apache/fop/render/pcl/MonochromeBitmapConverter.java
+++ b/src/java/org/apache/fop/util/bitmap/MonochromeBitmapConverter.java
@@ -17,13 +17,13 @@
/* $Id$ */
-package org.apache.fop.render.pcl;
+package org.apache.fop.util.bitmap;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
/**
- * Interface for converters that convert grayscale images to monochrome (1-bit) bitmap images.
+ * Interface for converters that convert images to monochrome (1-bit, bi-level) bitmap images.
*/
public interface MonochromeBitmapConverter {
@@ -35,8 +35,8 @@ public interface MonochromeBitmapConverter {
void setHint(String name, String value);
/**
- * Converts a grayscale bitmap image to a monochrome (1-bit) b/w bitmap image.
- * @param img the grayscale image
+ * Converts a bitmap image to a monochrome (1-bit) b/w bitmap image.
+ * @param img the original image
* @return the converted monochrome image
*/
RenderedImage convertToMonochrome(BufferedImage img);