is, without being decoded and encoded. It also allows lossy JPEG compression. Patch by Jeremias Maerki and Mehdi Houshmand. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1195952 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_1rc1old
</p> | </p> | ||||
<source><![CDATA[ | <source><![CDATA[ | ||||
<images mode="b+w" bits-per-pixel="1" dithering-quality="maximum"/>]]></source> | <images mode="b+w" bits-per-pixel="1" dithering-quality="maximum"/>]]></source> | ||||
<p> | |||||
By default, JPEG images are rasterized to a bitmap and the bitmap is included in the AFP doc. | |||||
However it is possible to encode in a lossless way to maintain maximum quality. But due | |||||
to lack of support for compression schemes like LZW (patent concerns), bitmap data is currently | |||||
not compressed resulting in large AFP files. Using the "allow-embedding" attribute on jpeg child | |||||
element allows the user to pass the JPEG as is in the document. The default is set to "false" since | |||||
there are compatibility concerns as some AFP printers don't support JPEG decoding. Using the | |||||
"bitmap-encoding-quality" attribute it is possible to enable lossy compression (JPEG baseline | |||||
DCT). The default is "1.0" which means lossless encoding. Setting a value lower than 1.0, JPEG | |||||
compression is enabled and the setting is used as the quality setting when encoding bitmap data. | |||||
Note that this setting does not always have an effect. Bi-level (1 bit) bitmaps are not compressed | |||||
using JPEG. Example: | |||||
</p> | |||||
<source><![CDATA[ | |||||
<images mode="color" cmyk="true"> | |||||
<jpeg allow-embedding="false" bitmap-encoding-quality="0.8"/> | |||||
</images>]]></source> | |||||
</section> | </section> | ||||
<section id="afp-goca-config"> | <section id="afp-goca-config"> | ||||
<title>GOCA (Vector Graphics)</title> | <title>GOCA (Vector Graphics)</title> |
org.apache.fop.render.afp.AFPImageHandlerGraphics2D | org.apache.fop.render.afp.AFPImageHandlerGraphics2D | ||||
org.apache.fop.render.afp.AFPImageHandlerRawStream | org.apache.fop.render.afp.AFPImageHandlerRawStream | ||||
org.apache.fop.render.afp.AFPImageHandlerRawCCITTFax | org.apache.fop.render.afp.AFPImageHandlerRawCCITTFax | ||||
org.apache.fop.render.afp.AFPImageHandlerRawJPEG | |||||
org.apache.fop.render.afp.AFPImageHandlerSVG | org.apache.fop.render.afp.AFPImageHandlerSVG |
case TIFFImage.COMP_FAX_G4_2D: | case TIFFImage.COMP_FAX_G4_2D: | ||||
imageObj.setEncoding(ImageContent.COMPID_G3_MMR); | imageObj.setEncoding(ImageContent.COMPID_G3_MMR); | ||||
break; | break; | ||||
case ImageContent.COMPID_JPEG: | |||||
imageObj.setEncoding((byte)compression); | |||||
break; | |||||
default: | default: | ||||
throw new IllegalStateException( | throw new IllegalStateException( | ||||
"Invalid compression scheme: " + compression); | "Invalid compression scheme: " + compression); |
imageObjectInfo.setData(dither); | imageObjectInfo.setData(dither); | ||||
//Positioning | //Positioning | ||||
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(); | |||||
int rotation = paintingState.getRotation(); | int rotation = paintingState.getRotation(); | ||||
AffineTransform at = paintingState.getData().getTransform(); | AffineTransform at = paintingState.getData().getTransform(); | ||||
Point2D origin = at.transform(new Point2D.Float( | Point2D origin = at.transform(new Point2D.Float( | ||||
rectanglePaintInfo.getX() * 1000, | rectanglePaintInfo.getX() * 1000, | ||||
rectanglePaintInfo.getY() * 1000), null); | rectanglePaintInfo.getY() * 1000), null); | ||||
objectAreaInfo.setX((int)Math.round(origin.getX())); | |||||
objectAreaInfo.setY((int)Math.round(origin.getY())); | |||||
AFPUnitConverter unitConv = paintingState.getUnitConverter(); | AFPUnitConverter unitConv = paintingState.getUnitConverter(); | ||||
float width = unitConv.pt2units(rectanglePaintInfo.getWidth()); | float width = unitConv.pt2units(rectanglePaintInfo.getWidth()); | ||||
float height = unitConv.pt2units(rectanglePaintInfo.getHeight()); | float height = unitConv.pt2units(rectanglePaintInfo.getHeight()); | ||||
objectAreaInfo.setWidth(Math.round(width)); | |||||
objectAreaInfo.setHeight(Math.round(height)); | |||||
objectAreaInfo.setHeightRes(resolution); | |||||
objectAreaInfo.setWidthRes(resolution); | |||||
objectAreaInfo.setRotation(rotation); | |||||
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo( | |||||
(int) Math.round(origin.getX()), | |||||
(int) Math.round(origin.getY()), | |||||
Math.round(width), Math.round(height), resolution, rotation); | |||||
imageObjectInfo.setObjectAreaInfo(objectAreaInfo); | imageObjectInfo.setObjectAreaInfo(objectAreaInfo); | ||||
//Create rectangle | //Create rectangle |
* @return true if this image uses compression | * @return true if this image uses compression | ||||
*/ | */ | ||||
public boolean hasCompression() { | public boolean hasCompression() { | ||||
return compression > -1; | |||||
return compression != -1; | |||||
} | } | ||||
/** | /** | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
public String toString() { | public String toString() { | ||||
return "AFPImageObjectInfo{" + super.toString() | return "AFPImageObjectInfo{" + super.toString() | ||||
+ ", compression=" + compression | + ", compression=" + compression |
* dimensions and resolutions of data objects. | * dimensions and resolutions of data objects. | ||||
*/ | */ | ||||
public class AFPObjectAreaInfo { | public class AFPObjectAreaInfo { | ||||
private int x; | |||||
private int y; | |||||
private int width; | |||||
private int height; | |||||
private final int x; | |||||
private final int y; | |||||
private final int width; | |||||
private final int height; | |||||
private int widthRes; | private int widthRes; | ||||
private int heightRes; | private int heightRes; | ||||
private int rotation = 0; | |||||
private final int rotation; | |||||
/** | /** | ||||
* Sets the x position of the data object | |||||
* Constructor | |||||
* | * | ||||
* @param x the x position of the data object | |||||
* @param x the x coordinate | |||||
* @param y the y coordinate | |||||
* @param width the width | |||||
* @param height the height | |||||
* @param resolution the resolution (sets both width and height resolutions) | |||||
* @param rotation the rotation angle | |||||
*/ | */ | ||||
public void setX(int x) { | |||||
public AFPObjectAreaInfo(int x, int y, int width, int height, int resolution, int rotation) { | |||||
this.x = x; | this.x = x; | ||||
} | |||||
/** | |||||
* Sets the y position of the data object | |||||
* | |||||
* @param y the y position of the data object | |||||
*/ | |||||
public void setY(int y) { | |||||
this.y = y; | this.y = y; | ||||
} | |||||
/** | |||||
* Sets the data object width | |||||
* | |||||
* @param width the width of the data object | |||||
*/ | |||||
public void setWidth(int width) { | |||||
this.width = width; | this.width = width; | ||||
this.height = height; | |||||
this.rotation = rotation; | |||||
this.widthRes = resolution; | |||||
this.heightRes = resolution; | |||||
} | } | ||||
/** | /** | ||||
* Sets the data object height | |||||
* Sets both the width and the height resolutions. | |||||
* | * | ||||
* @param height the height of the data object | |||||
* @param resolution the resolution | |||||
*/ | */ | ||||
public void setHeight(int height) { | |||||
this.height = height; | |||||
public void setResolution(int resolution) { | |||||
this.widthRes = resolution; | |||||
this.heightRes = resolution; | |||||
} | } | ||||
/** | /** | ||||
* Sets the width resolution | |||||
* Sets the width resolution. | |||||
* | * | ||||
* @param widthRes the width resolution | |||||
* @param resolution the resolution | |||||
*/ | */ | ||||
public void setWidthRes(int widthRes) { | |||||
this.widthRes = widthRes; | |||||
public void setWidthRes(int resolution) { | |||||
this.widthRes = resolution; | |||||
} | } | ||||
/** | /** | ||||
* Sets the height resolution | |||||
* Sets the height resolution. | |||||
* | * | ||||
* @param heightRes the height resolution | |||||
* @param resolution the resolution | |||||
*/ | */ | ||||
public void setHeightRes(int heightRes) { | |||||
this.heightRes = heightRes; | |||||
public void setHeightRes(int resolution) { | |||||
this.heightRes = resolution; | |||||
} | } | ||||
/** | /** | ||||
/** | /** | ||||
* Returns the width resolution of this data object | * Returns the width resolution of this data object | ||||
* | * | ||||
* @return the width resolution of this data object | |||||
* @return the resolution of this data object | |||||
*/ | */ | ||||
public int getWidthRes() { | public int getWidthRes() { | ||||
return widthRes; | return widthRes; | ||||
/** | /** | ||||
* Returns the height resolution of this data object | * Returns the height resolution of this data object | ||||
* | * | ||||
* @return the height resolution of this data object | |||||
* @return the resolution of this data object | |||||
*/ | */ | ||||
public int getHeightRes() { | public int getHeightRes() { | ||||
return heightRes; | return heightRes; | ||||
return rotation; | return rotation; | ||||
} | } | ||||
/** | |||||
* Sets the data object rotation | |||||
* | |||||
* @param rotation the data object rotation | |||||
*/ | |||||
public void setRotation(int rotation) { | |||||
this.rotation = rotation; | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public String toString() { | public String toString() { | ||||
return "x=" + x | return "x=" + x | ||||
+ ", y=" + y | |||||
+ ", width=" + width | |||||
+ ", height=" + height | |||||
+ ", widthRes=" + widthRes | |||||
+ ", heightRes=" + heightRes | |||||
+ ", rotation=" + rotation; | |||||
+ ", y=" + y | |||||
+ ", width=" + width | |||||
+ ", height=" + height | |||||
+ ", widthRes=" + widthRes | |||||
+ ", heigtRes=" + heightRes | |||||
+ ", rotation=" + rotation; | |||||
} | } | ||||
} | } |
/** dithering quality setting (0.0f..1.0f) */ | /** dithering quality setting (0.0f..1.0f) */ | ||||
private float ditheringQuality; | private float ditheringQuality; | ||||
/** image encoding quality setting (0.0f..1.0f) */ | |||||
private float bitmapEncodingQuality; | |||||
/** color image handler */ | /** color image handler */ | ||||
private ColorConverter colorConverter = GrayScaleColorConverter.getInstance(); | private ColorConverter colorConverter = GrayScaleColorConverter.getInstance(); | ||||
* format. | * format. | ||||
*/ | */ | ||||
private boolean nativeImagesSupported = false; | private boolean nativeImagesSupported = false; | ||||
private boolean canEmbedJpeg = false; | |||||
/** | /** | ||||
* true if CMYK images (requires IOCA FS45 suppport on the target platform) | * true if CMYK images (requires IOCA FS45 suppport on the target platform) | ||||
* may be generated | * may be generated | ||||
return this.nativeImagesSupported; | return this.nativeImagesSupported; | ||||
} | } | ||||
/** | |||||
* Set whether or not JPEG images can be embedded within an AFP document. | |||||
* | |||||
* @param canEmbed true if the JPEG image can be embedded | |||||
*/ | |||||
public void setCanEmbedJpeg(boolean canEmbed) { | |||||
canEmbedJpeg = canEmbed; | |||||
} | |||||
/** | |||||
* Returns true if JPEGs can be embedded in an AFP document. | |||||
* | |||||
* @return true if JPEG embedding is allowed | |||||
*/ | |||||
public boolean canEmbedJpeg() { | |||||
return canEmbedJpeg; | |||||
} | |||||
/** | /** | ||||
* Controls whether CMYK images (IOCA FS45) are enabled. By default, support | * Controls whether CMYK images (IOCA FS45) are enabled. By default, support | ||||
* is disabled for wider compatibility. When disabled, any CMYK image is | * is disabled for wider compatibility. When disabled, any CMYK image is | ||||
this.ditheringQuality = quality; | this.ditheringQuality = quality; | ||||
} | } | ||||
/** | |||||
* Gets the image encoding quality setting to use when encoding bitmap images. | |||||
* @return the encoding quality (a value between 0.0f and 1.0f, 1.0 meaning loss-less) | |||||
*/ | |||||
public float getBitmapEncodingQuality() { | |||||
return this.bitmapEncodingQuality; | |||||
} | |||||
/** | |||||
* Sets the image encoding quality setting to use when encoding bitmap images. | |||||
* @param quality Defines the desired quality level for the conversion. | |||||
* Valid values: a value between 0.0f (lowest) and 1.0f (best, loss-less) | |||||
*/ | |||||
public void setBitmapEncodingQuality(float quality) { | |||||
quality = Math.max(quality, 0.0f); | |||||
quality = Math.min(quality, 1.0f); | |||||
this.bitmapEncodingQuality = quality; | |||||
} | |||||
/** | /** | ||||
* Sets the output/device resolution | * Sets the output/device resolution | ||||
* | * |
private void includeObject(AFPDataObjectInfo dataObjectInfo, | private void includeObject(AFPDataObjectInfo dataObjectInfo, | ||||
String objectName) { | String objectName) { | ||||
IncludeObject includeObject | |||||
= dataObjectFactory.createInclude(objectName, dataObjectInfo); | |||||
IncludeObject includeObject = dataObjectFactory.createInclude(objectName, dataObjectInfo); | |||||
dataStream.getCurrentPage().addObject(includeObject); | dataStream.getCurrentPage().addObject(includeObject); | ||||
} | } | ||||
import java.util.List; | import java.util.List; | ||||
import org.apache.fop.fonts.FontTriplet; | |||||
/** | /** | ||||
* FontInfo contains meta information on fonts | * FontInfo contains meta information on fonts | ||||
public class AFPFontInfo { | public class AFPFontInfo { | ||||
private AFPFont font; | private AFPFont font; | ||||
private List/*<FontTriplet>*/ tripletList; | |||||
private List<FontTriplet> tripletList; | |||||
/** | /** | ||||
* Main constructor | * Main constructor | ||||
* @param afpFont The AFP Font | * @param afpFont The AFP Font | ||||
* @param tripletList List of font triplets to associate with this font | * @param tripletList List of font triplets to associate with this font | ||||
*/ | */ | ||||
public AFPFontInfo(AFPFont afpFont, List/*<FontTriplet>*/ tripletList) { | |||||
public AFPFontInfo(AFPFont afpFont, List<FontTriplet> tripletList) { | |||||
this.font = afpFont; | this.font = afpFont; | ||||
this.tripletList = tripletList; | this.tripletList = tripletList; | ||||
} | } | ||||
* | * | ||||
* @return List of font triplets | * @return List of font triplets | ||||
*/ | */ | ||||
public List/*<FontTriplet>*/ getFontTriplets() { | |||||
public List<FontTriplet> getFontTriplets() { | |||||
return tripletList; | return tripletList; | ||||
} | } | ||||
*/ | */ | ||||
public static final byte COMPID_G3_MMR = (byte)0x82; | public static final byte COMPID_G3_MMR = (byte)0x82; | ||||
/** JPEG algorithms (usually baseline DCT). */ | |||||
public static final byte COMPID_JPEG = (byte)0x83; | |||||
/** the image size parameter */ | /** the image size parameter */ | ||||
private ImageSizeParameter imageSizeParameter = null; | private ImageSizeParameter imageSizeParameter = null; | ||||
private byte ideSize = 1; | private byte ideSize = 1; | ||||
/** the image compression */ | /** the image compression */ | ||||
private byte compression = (byte)0xC0; | |||||
private byte compression = (byte)0xC0; //Baseline DCT in case of JPEG compression | |||||
/** the image data */ | /** the image data */ | ||||
private byte[] data; | private byte[] data; | ||||
* @param color the IDE color model. | * @param color the IDE color model. | ||||
* @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead | * @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead | ||||
*/ | */ | ||||
@Deprecated | |||||
public void setImageIDEColorModel(byte color) { | public void setImageIDEColorModel(byte color) { | ||||
needIDEStructureParameter().setColorModel(color); | needIDEStructureParameter().setColorModel(color); | ||||
} | } | ||||
* @param subtractive true for subtractive mode, false for additive mode | * @param subtractive true for subtractive mode, false for additive mode | ||||
* @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead | * @deprecated use {@link #setIDEStructureParameter(IDEStructureParameter)} instead | ||||
*/ | */ | ||||
@Deprecated | |||||
public void setSubtractive(boolean subtractive) { | public void setSubtractive(boolean subtractive) { | ||||
needIDEStructureParameter().setSubtractive(subtractive); | needIDEStructureParameter().setSubtractive(subtractive); | ||||
} | } | ||||
private static final int MAX_DATA_LEN = 65535; | private static final int MAX_DATA_LEN = 65535; | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
protected void writeContent(OutputStream os) throws IOException { | protected void writeContent(OutputStream os) throws IOException { | ||||
if (imageSizeParameter != null) { | if (imageSizeParameter != null) { | ||||
imageSizeParameter.writeToStream(os); | imageSizeParameter.writeToStream(os); | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
protected void writeStart(OutputStream os) throws IOException { | protected void writeStart(OutputStream os) throws IOException { | ||||
final byte[] startData = new byte[] { | final byte[] startData = new byte[] { | ||||
(byte)0x91, // ID | (byte)0x91, // ID | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
protected void writeEnd(OutputStream os) throws IOException { | protected void writeEnd(OutputStream os) throws IOException { | ||||
final byte[] endData = new byte[] { | final byte[] endData = new byte[] { | ||||
(byte)0x93, // ID | (byte)0x93, // ID | ||||
(byte)0x95, // ID | (byte)0x95, // ID | ||||
0x02, // Length | 0x02, // Length | ||||
encoding, | encoding, | ||||
0x01, // RECID | |||||
(byte)(encoding == COMPID_JPEG ? 0xFE : 0x01), // RECID | |||||
}; | }; | ||||
return encodingData; | return encodingData; | ||||
} | } | ||||
* @return byte[] The data stream. | * @return byte[] The data stream. | ||||
*/ | */ | ||||
private byte[] getExternalAlgorithmParameter() { | private byte[] getExternalAlgorithmParameter() { | ||||
if (encoding == (byte)0x83 && compression != 0) { | |||||
if (encoding == COMPID_JPEG && compression != 0) { | |||||
final byte[] extAlgData = new byte[] { | final byte[] extAlgData = new byte[] { | ||||
(byte)0x95, // ID | |||||
(byte)0x9F, // ID | |||||
0x00, // Length | 0x00, // Length | ||||
0x10, // ALGTYPE = Compression Algorithm | 0x10, // ALGTYPE = Compression Algorithm | ||||
0x00, // Reserved | 0x00, // Reserved | ||||
(byte)0x83, // COMPRID = JPEG | |||||
COMPID_JPEG, // COMPRID = JPEG | |||||
0x00, // Reserved | 0x00, // Reserved | ||||
0x00, // Reserved | 0x00, // Reserved | ||||
0x00, // Reserved | 0x00, // Reserved | ||||
compression, // MARKER | |||||
compression, // MARKER | |||||
0x00, // Reserved | 0x00, // Reserved | ||||
0x00, // Reserved | 0x00, // Reserved | ||||
0x00, // Reserved | 0x00, // Reserved |
int height = objectAreaInfo.getHeight(); | int height = objectAreaInfo.getHeight(); | ||||
int widthRes = objectAreaInfo.getWidthRes(); | int widthRes = objectAreaInfo.getWidthRes(); | ||||
int heightRes = objectAreaInfo.getHeightRes(); | int heightRes = objectAreaInfo.getHeightRes(); | ||||
ObjectAreaDescriptor objectAreaDescriptor | |||||
= factory.createObjectAreaDescriptor(width, height, widthRes, heightRes); | |||||
ObjectAreaDescriptor objectAreaDescriptor = factory.createObjectAreaDescriptor(width, | |||||
height, widthRes, heightRes); | |||||
getObjectEnvironmentGroup().setObjectAreaDescriptor(objectAreaDescriptor); | getObjectEnvironmentGroup().setObjectAreaDescriptor(objectAreaDescriptor); | ||||
// object area position | // object area position |
final int leftEdge = 0; | final int leftEdge = 0; | ||||
final int topEdge = 0; | final int topEdge = 0; | ||||
GraphicsDataDescriptor graphicsDataDescriptor = factory.createGraphicsDataDescriptor( | GraphicsDataDescriptor graphicsDataDescriptor = factory.createGraphicsDataDescriptor( | ||||
leftEdge, width, topEdge, height, widthRes, heightRes); | |||||
leftEdge, width, topEdge, height, widthRes, heightRes); | |||||
getObjectEnvironmentGroup().setDataDescriptor(graphicsDataDescriptor); | getObjectEnvironmentGroup().setDataDescriptor(graphicsDataDescriptor); | ||||
} | } |
ContainerDataDescriptor containerDataDescriptor | ContainerDataDescriptor containerDataDescriptor | ||||
= factory.createContainerDataDescriptor( | = factory.createContainerDataDescriptor( | ||||
dataWidth, dataHeight, widthRes, heightRes); | |||||
dataWidth, dataHeight, widthRes, heightRes); | |||||
getObjectEnvironmentGroup().setDataDescriptor(containerDataDescriptor); | getObjectEnvironmentGroup().setDataDescriptor(containerDataDescriptor); | ||||
} | } | ||||
} | } |
package org.apache.fop.afp.modca; | package org.apache.fop.afp.modca; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.HashMap; | |||||
import org.apache.xmlgraphics.util.MimeConstants; | import org.apache.xmlgraphics.util.MimeConstants; | ||||
private static final byte COMPID_TRUETYPE_OPENTYPE_FONT_COLLECTION_RESOURCE_OBJECT = 53; | private static final byte COMPID_TRUETYPE_OPENTYPE_FONT_COLLECTION_RESOURCE_OBJECT = 53; | ||||
/** mime type entry mapping */ | /** mime type entry mapping */ | ||||
private final java.util.Map/*<String, ObjectType>*/ mimeObjectTypeMap | |||||
= Collections.synchronizedMap( | |||||
new java.util.HashMap/*<String, ObjectType>*/()); | |||||
private final java.util.Map<String, ObjectType> mimeObjectTypeMap | |||||
= Collections.synchronizedMap(new HashMap<String, ObjectType>()); | |||||
/** singleton instance */ | /** singleton instance */ | ||||
private static Registry instance = null; | private static Registry instance = null; | ||||
* @return the MOD:CA object type | * @return the MOD:CA object type | ||||
*/ | */ | ||||
public ObjectType getObjectType(String mimeType) { | public ObjectType getObjectType(String mimeType) { | ||||
return (ObjectType)mimeObjectTypeMap.get(mimeType); | |||||
return mimeObjectTypeMap.get(mimeType); | |||||
} | } | ||||
/** | /** |
/** the logger */ | /** the logger */ | ||||
private static Log log = LogFactory.getLog(ImageHandlerRegistry.class); | private static Log log = LogFactory.getLog(ImageHandlerRegistry.class); | ||||
private static final Comparator HANDLER_COMPARATOR = new Comparator() { | |||||
public int compare(Object o1, Object o2) { | |||||
ImageHandler h1 = (ImageHandler)o1; | |||||
ImageHandler h2 = (ImageHandler)o2; | |||||
private static final Comparator<ImageHandler> HANDLER_COMPARATOR | |||||
= new Comparator<ImageHandler>() { | |||||
public int compare(ImageHandler o1, ImageHandler o2) { | |||||
ImageHandler h1 = o1; | |||||
ImageHandler h2 = o2; | |||||
return h1.getPriority() - h2.getPriority(); | return h1.getPriority() - h2.getPriority(); | ||||
} | } | ||||
}; | }; | ||||
/** Map containing image handlers for various {@link Image} subclasses. */ | /** Map containing image handlers for various {@link Image} subclasses. */ | ||||
private Map handlers = new java.util.HashMap(); | |||||
private Map<Class<? extends Image>, ImageHandler> handlers | |||||
= new java.util.HashMap<Class<? extends Image>, ImageHandler>(); | |||||
/** List containing the same handlers as above but ordered by priority */ | /** List containing the same handlers as above but ordered by priority */ | ||||
private List handlerList = new java.util.LinkedList(); | |||||
private List<ImageHandler> handlerList = new java.util.LinkedList<ImageHandler>(); | |||||
private int handlerRegistrations; | private int handlerRegistrations; | ||||
* @param handler the ImageHandler instance | * @param handler the ImageHandler instance | ||||
*/ | */ | ||||
public synchronized void addHandler(ImageHandler handler) { | public synchronized void addHandler(ImageHandler handler) { | ||||
Class imageClass = handler.getSupportedImageClass(); | |||||
Class<? extends Image> imageClass = handler.getSupportedImageClass(); | |||||
//List | //List | ||||
this.handlers.put(imageClass, handler); | this.handlers.put(imageClass, handler); | ||||
//Sorted insert (sort by priority) | //Sorted insert (sort by priority) | ||||
ListIterator iter = this.handlerList.listIterator(); | |||||
ListIterator<ImageHandler> iter = this.handlerList.listIterator(); | |||||
while (iter.hasNext()) { | while (iter.hasNext()) { | ||||
ImageHandler h = (ImageHandler)iter.next(); | |||||
ImageHandler h = iter.next(); | |||||
if (HANDLER_COMPARATOR.compare(handler, h) < 0) { | if (HANDLER_COMPARATOR.compare(handler, h) < 0) { | ||||
iter.previous(); | iter.previous(); | ||||
break; | break; | ||||
* @return the image handler responsible for handling the image or null if none is available | * @return the image handler responsible for handling the image or null if none is available | ||||
*/ | */ | ||||
public ImageHandler getHandler(RenderingContext targetContext, Image image) { | public ImageHandler getHandler(RenderingContext targetContext, Image image) { | ||||
ListIterator iter = this.handlerList.listIterator(); | |||||
while (iter.hasNext()) { | |||||
ImageHandler h = (ImageHandler)iter.next(); | |||||
for (ImageHandler h : this.handlerList) { | |||||
if (h.isCompatible(targetContext, image)) { | if (h.isCompatible(targetContext, image)) { | ||||
//Return the first handler in the prioritized list that is compatible | //Return the first handler in the prioritized list that is compatible | ||||
return h; | return h; | ||||
*/ | */ | ||||
public synchronized ImageFlavor[] getSupportedFlavors(RenderingContext context) { | public synchronized ImageFlavor[] getSupportedFlavors(RenderingContext context) { | ||||
//Extract all ImageFlavors into a single array | //Extract all ImageFlavors into a single array | ||||
List flavors = new java.util.ArrayList(); | |||||
Iterator iter = this.handlerList.iterator(); | |||||
while (iter.hasNext()) { | |||||
ImageHandler handler = (ImageHandler)iter.next(); | |||||
List<ImageFlavor> flavors = new java.util.ArrayList<ImageFlavor>(); | |||||
for (ImageHandler handler : this.handlerList) { | |||||
if (handler.isCompatible(context, null)) { | if (handler.isCompatible(context, null)) { | ||||
ImageFlavor[] f = handler.getSupportedImageFlavors(); | ImageFlavor[] f = handler.getSupportedImageFlavors(); | ||||
for (int i = 0; i < f.length; i++) { | for (int i = 0; i < f.length; i++) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]); | |||||
return flavors.toArray(new ImageFlavor[flavors.size()]); | |||||
} | } | ||||
/** | /** |
*/ | */ | ||||
void setDitheringQuality(float quality); | void setDitheringQuality(float quality); | ||||
/** | |||||
* Sets the image encoding quality setting to use when encoding bitmap images. | |||||
* The default setting is 1.0 which means loss-less encoding. Settings of less than 1.0 | |||||
* allow loss-less encoding schemes like JPEG. The value serves as quality setting for | |||||
* the encoders in that case. | |||||
* @param quality Defines the desired quality level. | |||||
* Valid values: a value between 0.0f (lowest) and 1.0f (best, loss-less) | |||||
*/ | |||||
void setBitmapEncodingQuality(float quality); | |||||
/** | /** | ||||
* Sets the output/device resolution | * Sets the output/device resolution | ||||
* | * | ||||
*/ | */ | ||||
void setResourceLevelDefaults(AFPResourceLevelDefaults defaults); | void setResourceLevelDefaults(AFPResourceLevelDefaults defaults); | ||||
/** | |||||
* Sets whether or not to JPEG images can be embedded in the AFP document. | |||||
* | |||||
* @param canEmbed whether or not to embed JPEG image | |||||
*/ | |||||
void canEmbedJpeg(boolean canEmbed); | |||||
} | } |
this.paintingState.setDitheringQuality(quality); | this.paintingState.setDitheringQuality(quality); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
public void setBitmapEncodingQuality(float quality) { | |||||
this.paintingState.setBitmapEncodingQuality(quality); | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public void setShadingMode(AFPShadingMode shadingMode) { | public void setShadingMode(AFPShadingMode shadingMode) { | ||||
this.shadingMode = shadingMode; | this.shadingMode = shadingMode; | ||||
return pageSegmentMap.get(uri); | return pageSegmentMap.get(uri); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
public void canEmbedJpeg(boolean canEmbed) { | |||||
paintingState.setCanEmbedJpeg(canEmbed); | |||||
} | |||||
} | } |
*/ | */ | ||||
public static AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState, | public static AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState, | ||||
Rectangle targetRect) { | Rectangle targetRect) { | ||||
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(); | |||||
AFPUnitConverter unitConv = paintingState.getUnitConverter(); | AFPUnitConverter unitConv = paintingState.getUnitConverter(); | ||||
int[] coords = unitConv.mpts2units(new float[] {targetRect.x, targetRect.y}); | int[] coords = unitConv.mpts2units(new float[] {targetRect.x, targetRect.y}); | ||||
objectAreaInfo.setX(coords[X]); | |||||
objectAreaInfo.setY(coords[Y]); | |||||
int width = Math.round(unitConv.mpt2units(targetRect.width)); | int width = Math.round(unitConv.mpt2units(targetRect.width)); | ||||
objectAreaInfo.setWidth(width); | |||||
int height = Math.round(unitConv.mpt2units(targetRect.height)); | int height = Math.round(unitConv.mpt2units(targetRect.height)); | ||||
objectAreaInfo.setHeight(height); | |||||
int resolution = paintingState.getResolution(); | int resolution = paintingState.getResolution(); | ||||
objectAreaInfo.setHeightRes(resolution); | |||||
objectAreaInfo.setWidthRes(resolution); | |||||
objectAreaInfo.setRotation(paintingState.getRotation()); | |||||
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(coords[X], coords[Y], width, | |||||
height, resolution, paintingState.getRotation()); | |||||
return objectAreaInfo; | return objectAreaInfo; | ||||
} | } | ||||
package org.apache.fop.render.afp; | package org.apache.fop.render.afp; | ||||
import java.awt.Rectangle; | |||||
import java.io.IOException; | |||||
import org.apache.commons.logging.Log; | |||||
import org.apache.commons.logging.LogFactory; | |||||
import org.apache.xmlgraphics.image.loader.Image; | import org.apache.xmlgraphics.image.loader.Image; | ||||
import org.apache.xmlgraphics.image.loader.ImageFlavor; | import org.apache.xmlgraphics.image.loader.ImageFlavor; | ||||
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; | import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; | ||||
ImageFlavor.RAW_CCITTFAX, | ImageFlavor.RAW_CCITTFAX, | ||||
}; | }; | ||||
/** logging instance */ | |||||
private final Log log = LogFactory.getLog(AFPImageHandlerRawJPEG.class); | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
protected void setAdditionalParameters(AFPDataObjectInfo dataObjectInfo, | protected void setAdditionalParameters(AFPDataObjectInfo dataObjectInfo, | ||||
ImageRawStream image) { | ImageRawStream image) { | ||||
AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo; | AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
public void handleImage(RenderingContext context, Image image, Rectangle pos) | |||||
throws IOException { | |||||
log.debug("Embedding undecoded CCITT data as data container..."); | |||||
super.handleImage(context, image, pos); | |||||
} | |||||
/** {@inheritDoc} */ | |||||
@Override | |||||
protected AFPDataObjectInfo createDataObjectInfo() { | protected AFPDataObjectInfo createDataObjectInfo() { | ||||
return new AFPImageObjectInfo(); | return new AFPImageObjectInfo(); | ||||
} | } |
/* | |||||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||||
* contributor license agreements. See the NOTICE file distributed with | |||||
* this work for additional information regarding copyright ownership. | |||||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
* (the "License"); you may not use this file except in compliance with | |||||
* the License. You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
*/ | |||||
/* $Id$ */ | |||||
package org.apache.fop.render.afp; | |||||
import java.awt.Rectangle; | |||||
import java.awt.color.ColorSpace; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import org.apache.commons.io.IOUtils; | |||||
import org.apache.commons.logging.Log; | |||||
import org.apache.commons.logging.LogFactory; | |||||
import org.apache.xmlgraphics.image.loader.Image; | |||||
import org.apache.xmlgraphics.image.loader.ImageFlavor; | |||||
import org.apache.xmlgraphics.image.loader.ImageSize; | |||||
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; | |||||
import org.apache.xmlgraphics.image.loader.impl.JPEGConstants; | |||||
import org.apache.xmlgraphics.util.MimeConstants; | |||||
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.afp.AFPResourceInfo; | |||||
import org.apache.fop.afp.AFPResourceManager; | |||||
import org.apache.fop.afp.ioca.ImageContent; | |||||
import org.apache.fop.afp.modca.ResourceObject; | |||||
import org.apache.fop.render.ImageHandler; | |||||
import org.apache.fop.render.RenderingContext; | |||||
/** | |||||
* {@link ImageHandler} implementation which handles ImageRawJPEG instances. JPEG data is | |||||
* embedded directly (not decoded) into IOCA images (FS11 or FS45). | |||||
*/ | |||||
public class AFPImageHandlerRawJPEG extends AFPImageHandler implements ImageHandler { | |||||
/** logging instance */ | |||||
private final Log log = LogFactory.getLog(AFPImageHandlerRawJPEG.class); | |||||
private void setDefaultResourceLevel(AFPImageObjectInfo imageObjectInfo, | |||||
AFPResourceManager resourceManager) { | |||||
AFPResourceInfo resourceInfo = imageObjectInfo.getResourceInfo(); | |||||
if (!resourceInfo.levelChanged()) { | |||||
resourceInfo.setLevel(resourceManager.getResourceLevelDefaults() | |||||
.getDefaultResourceLevel(ResourceObject.TYPE_IMAGE)); | |||||
} | |||||
} | |||||
/** {@inheritDoc} */ | |||||
@Override | |||||
protected AFPDataObjectInfo createDataObjectInfo() { | |||||
return new AFPImageObjectInfo(); | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public int getPriority() { | |||||
return 150; | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public Class<?> getSupportedImageClass() { | |||||
return ImageRawJPEG.class; | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public ImageFlavor[] getSupportedImageFlavors() { | |||||
return new ImageFlavor[] {ImageFlavor.RAW_JPEG}; | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public void handleImage(RenderingContext context, Image image, Rectangle pos) | |||||
throws IOException { | |||||
AFPRenderingContext afpContext = (AFPRenderingContext)context; | |||||
AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)createDataObjectInfo(); | |||||
AFPPaintingState paintingState = afpContext.getPaintingState(); | |||||
// set resource information | |||||
setResourceInformation(imageObjectInfo, | |||||
image.getInfo().getOriginalURI(), | |||||
afpContext.getForeignAttributes()); | |||||
setDefaultResourceLevel(imageObjectInfo, afpContext.getResourceManager()); | |||||
// Positioning | |||||
imageObjectInfo.setObjectAreaInfo(createObjectAreaInfo(paintingState, pos)); | |||||
updateIntrinsicSize(imageObjectInfo, paintingState, image.getSize()); | |||||
// Image content | |||||
ImageRawJPEG jpeg = (ImageRawJPEG)image; | |||||
imageObjectInfo.setCompression(ImageContent.COMPID_JPEG); | |||||
ColorSpace cs = jpeg.getColorSpace(); | |||||
switch (cs.getType()) { | |||||
case ColorSpace.TYPE_GRAY: | |||||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS11); | |||||
imageObjectInfo.setColor(false); | |||||
imageObjectInfo.setBitsPerPixel(8); | |||||
break; | |||||
case ColorSpace.TYPE_RGB: | |||||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS11); | |||||
imageObjectInfo.setColor(true); | |||||
imageObjectInfo.setBitsPerPixel(24); | |||||
break; | |||||
case ColorSpace.TYPE_CMYK: | |||||
imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45); | |||||
imageObjectInfo.setColor(true); | |||||
imageObjectInfo.setBitsPerPixel(32); | |||||
break; | |||||
default: | |||||
throw new IllegalStateException( | |||||
"Color space of JPEG image not supported: " + cs); | |||||
} | |||||
boolean included = afpContext.getResourceManager().tryIncludeObject(imageObjectInfo); | |||||
if (!included) { | |||||
log.debug("Embedding undecoded JPEG as IOCA image..."); | |||||
InputStream inputStream = jpeg.createInputStream(); | |||||
try { | |||||
imageObjectInfo.setData(IOUtils.toByteArray(inputStream)); | |||||
} finally { | |||||
IOUtils.closeQuietly(inputStream); | |||||
} | |||||
// Create image | |||||
afpContext.getResourceManager().createObject(imageObjectInfo); | |||||
} | |||||
} | |||||
private void updateIntrinsicSize(AFPImageObjectInfo imageObjectInfo, | |||||
AFPPaintingState paintingState, ImageSize targetSize) { | |||||
//Update image object info | |||||
imageObjectInfo.setDataHeightRes((int)Math.round( | |||||
targetSize.getDpiHorizontal() * 10)); | |||||
imageObjectInfo.setDataWidthRes((int)Math.round( | |||||
targetSize.getDpiVertical() * 10)); | |||||
imageObjectInfo.setDataHeight(targetSize.getHeightPx()); | |||||
imageObjectInfo.setDataWidth(targetSize.getWidthPx()); | |||||
// set object area info | |||||
int resolution = paintingState.getResolution(); | |||||
AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo(); | |||||
objectAreaInfo.setResolution(resolution); | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public boolean isCompatible(RenderingContext targetContext, Image image) { | |||||
if (!(targetContext instanceof AFPRenderingContext)) { | |||||
return false; //AFP-specific image handler | |||||
} | |||||
AFPRenderingContext context = (AFPRenderingContext)targetContext; | |||||
AFPPaintingState paintingState = context.getPaintingState(); | |||||
if (!paintingState.canEmbedJpeg()) { | |||||
return false; | |||||
} | |||||
if (paintingState.getBitsPerPixel() < 8) { | |||||
return false; //This would stand in the way of dithering and cause exceptions | |||||
} | |||||
if (image == null) { | |||||
return true; //Don't know the image format, yet | |||||
} | |||||
if (image instanceof ImageRawJPEG) { | |||||
ImageRawJPEG jpeg = (ImageRawJPEG)image; | |||||
ColorSpace cs = jpeg.getColorSpace(); | |||||
switch (cs.getType()) { | |||||
case ColorSpace.TYPE_GRAY: | |||||
case ColorSpace.TYPE_RGB: | |||||
//ok | |||||
break; | |||||
case ColorSpace.TYPE_CMYK: | |||||
if (!paintingState.isCMYKImagesSupported()) { | |||||
return false; //CMYK is disabled | |||||
//Note: you may need to disable this image handler through configuration | |||||
//if you want to paint a CMYK JPEG on 24bit and less configurations. | |||||
} | |||||
break; | |||||
default: | |||||
return false; //not supported | |||||
} | |||||
if (jpeg.getSOFType() != JPEGConstants.SOF0) { | |||||
return false; //We'll let only baseline DCT through. | |||||
} | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
} |
package org.apache.fop.render.afp; | package org.apache.fop.render.afp; | ||||
import java.awt.Rectangle; | |||||
import java.io.IOException; | |||||
import org.apache.commons.logging.Log; | |||||
import org.apache.commons.logging.LogFactory; | |||||
import org.apache.xmlgraphics.image.loader.Image; | import org.apache.xmlgraphics.image.loader.Image; | ||||
import org.apache.xmlgraphics.image.loader.ImageFlavor; | import org.apache.xmlgraphics.image.loader.ImageFlavor; | ||||
import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS; | import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS; | ||||
ImageFlavor.RAW_EPS, | ImageFlavor.RAW_EPS, | ||||
}; | }; | ||||
/** logging instance */ | |||||
private final Log log = LogFactory.getLog(AFPImageHandlerRawJPEG.class); | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getPriority() { | public int getPriority() { | ||||
return 200; | return 200; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
@Override | |||||
protected AFPDataObjectInfo createDataObjectInfo() { | protected AFPDataObjectInfo createDataObjectInfo() { | ||||
return new AFPDataObjectInfo(); | return new AFPDataObjectInfo(); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | |||||
public void handleImage(RenderingContext context, Image image, Rectangle pos) | |||||
throws IOException { | |||||
if (log.isDebugEnabled()) { | |||||
log.debug("Embedding undecoded image data (" + image.getInfo().getMimeType() | |||||
+ ") as data container..."); | |||||
} | |||||
super.handleImage(context, image, pos); | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public boolean isCompatible(RenderingContext targetContext, Image image) { | public boolean isCompatible(RenderingContext targetContext, Image image) { | ||||
if (targetContext instanceof AFPRenderingContext) { | if (targetContext instanceof AFPRenderingContext) { |
import java.awt.image.Raster; | import java.awt.image.Raster; | ||||
import java.awt.image.RenderedImage; | import java.awt.image.RenderedImage; | ||||
import java.awt.image.SampleModel; | import java.awt.image.SampleModel; | ||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.OutputStream; | import java.io.OutputStream; | ||||
import org.apache.commons.io.output.ByteArrayOutputStream; | |||||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.xmlgraphics.image.loader.ImageInfo; | import org.apache.xmlgraphics.image.loader.ImageInfo; | ||||
import org.apache.xmlgraphics.image.loader.ImageSize; | import org.apache.xmlgraphics.image.loader.ImageSize; | ||||
import org.apache.xmlgraphics.image.loader.impl.ImageRendered; | import org.apache.xmlgraphics.image.loader.impl.ImageRendered; | ||||
import org.apache.xmlgraphics.image.writer.ImageWriter; | |||||
import org.apache.xmlgraphics.image.writer.ImageWriterParams; | |||||
import org.apache.xmlgraphics.image.writer.ImageWriterRegistry; | |||||
import org.apache.xmlgraphics.ps.ImageEncodingHelper; | import org.apache.xmlgraphics.ps.ImageEncodingHelper; | ||||
import org.apache.xmlgraphics.util.MimeConstants; | import org.apache.xmlgraphics.util.MimeConstants; | ||||
import org.apache.xmlgraphics.util.UnitConv; | import org.apache.xmlgraphics.util.UnitConv; | ||||
import org.apache.fop.afp.AFPPaintingState; | import org.apache.fop.afp.AFPPaintingState; | ||||
import org.apache.fop.afp.AFPResourceInfo; | import org.apache.fop.afp.AFPResourceInfo; | ||||
import org.apache.fop.afp.AFPResourceManager; | import org.apache.fop.afp.AFPResourceManager; | ||||
import org.apache.fop.afp.ioca.ImageContent; | |||||
import org.apache.fop.afp.modca.ResourceObject; | import org.apache.fop.afp.modca.ResourceObject; | ||||
import org.apache.fop.render.ImageHandler; | import org.apache.fop.render.ImageHandler; | ||||
import org.apache.fop.render.RenderingContext; | import org.apache.fop.render.RenderingContext; | ||||
functionSet = 45; //IOCA FS45 required for CMYK | functionSet = 45; //IOCA FS45 required for CMYK | ||||
} | } | ||||
helper.encode(baos); | |||||
//Lossy or loss-less? | |||||
if (!paintingState.canEmbedJpeg() | |||||
&& paintingState.getBitmapEncodingQuality() < 1.0f) { | |||||
try { | |||||
if (log.isDebugEnabled()) { | |||||
log.debug("Encoding using baseline DCT (JPEG, q=" | |||||
+ paintingState.getBitmapEncodingQuality() + ")..."); | |||||
} | |||||
encodeToBaselineDCT(renderedImage, | |||||
paintingState.getBitmapEncodingQuality(), | |||||
paintingState.getResolution(), | |||||
baos); | |||||
imageObjectInfo.setCompression(ImageContent.COMPID_JPEG); | |||||
} catch (IOException ioe) { | |||||
//Some JPEG codecs cannot encode CMYK | |||||
helper.encode(baos); | |||||
} | |||||
} else { | |||||
helper.encode(baos); | |||||
} | |||||
imageData = baos.toByteArray(); | imageData = baos.toByteArray(); | ||||
} | } | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
} | |||||
private void encodeToBaselineDCT(RenderedImage image, | |||||
float quality, int resolution, OutputStream out) throws IOException { | |||||
ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor("image/jpeg"); | |||||
ImageWriterParams params = new ImageWriterParams(); | |||||
params.setJPEGQuality(quality, true); | |||||
params.setResolution(resolution); | |||||
writer.writeImage(image, out, params); | |||||
} | |||||
} | |||||
} | } |
import java.io.IOException; | import java.io.IOException; | ||||
import java.net.URI; | import java.net.URI; | ||||
import java.net.URISyntaxException; | import java.net.URISyntaxException; | ||||
import java.util.ArrayList; | |||||
import java.util.List; | import java.util.List; | ||||
import org.apache.avalon.framework.configuration.Configuration; | import org.apache.avalon.framework.configuration.Configuration; | ||||
import org.apache.avalon.framework.configuration.ConfigurationException; | import org.apache.avalon.framework.configuration.ConfigurationException; | ||||
import org.apache.fop.afp.AFPResourceLevel; | import org.apache.fop.afp.AFPResourceLevel; | ||||
import org.apache.fop.afp.AFPResourceLevelDefaults; | import org.apache.fop.afp.AFPResourceLevelDefaults; | ||||
import org.apache.fop.afp.fonts.AFPFont; | import org.apache.fop.afp.fonts.AFPFont; | ||||
log.error("Mandatory font configuration element '<font-triplet...' is missing"); | log.error("Mandatory font configuration element '<font-triplet...' is missing"); | ||||
return null; | return null; | ||||
} | } | ||||
for (int j = 0; j < triple.length; j++) { | |||||
int weight = FontUtil.parseCSS2FontWeight(triple[j].getAttribute("weight")); | |||||
FontTriplet triplet = new FontTriplet(triple[j].getAttribute("name"), | |||||
triple[j].getAttribute("style"), | |||||
for (Configuration config : triple) { | |||||
int weight = FontUtil.parseCSS2FontWeight(config.getAttribute("weight")); | |||||
FontTriplet triplet = new FontTriplet(config.getAttribute("name"), | |||||
config.getAttribute("style"), | |||||
weight); | weight); | ||||
tripletList.add(triplet); | tripletList.add(triplet); | ||||
} | } | ||||
if (base14 != null) { | if (base14 != null) { | ||||
try { | try { | ||||
Class<?> clazz = Class.forName( | |||||
"org.apache.fop.fonts.base14." + base14); | |||||
Class<? extends Typeface> clazz = Class.forName( | |||||
"org.apache.fop.fonts.base14." + base14).asSubclass(Typeface.class); | |||||
try { | try { | ||||
Typeface tf = (Typeface)clazz.newInstance(); | |||||
Typeface tf = clazz.newInstance(); | |||||
font.addCharacterSet(sizeMpt, | font.addCharacterSet(sizeMpt, | ||||
CharacterSetBuilder.getInstance() | CharacterSetBuilder.getInstance() | ||||
.build(characterset, codepage, encoding, tf)); | .build(characterset, codepage, encoding, tf)); | ||||
String base14 = afpFontCfg.getAttribute("base14-font", null); | String base14 = afpFontCfg.getAttribute("base14-font", null); | ||||
if (base14 != null) { | if (base14 != null) { | ||||
try { | try { | ||||
Class<?> clazz = Class.forName("org.apache.fop.fonts.base14." | |||||
+ base14); | |||||
Class<? extends Typeface> clazz = Class.forName("org.apache.fop.fonts.base14." | |||||
+ base14).asSubclass(Typeface.class); | |||||
try { | try { | ||||
Typeface tf = (Typeface)clazz.newInstance(); | |||||
Typeface tf = clazz.newInstance(); | |||||
characterSet = CharacterSetBuilder.getInstance() | characterSet = CharacterSetBuilder.getInstance() | ||||
.build(characterset, codepage, encoding, tf); | .build(characterset, codepage, encoding, tf); | ||||
} catch (Exception ie) { | } catch (Exception ie) { | ||||
if (log.isDebugEnabled()) { | if (log.isDebugEnabled()) { | ||||
log.debug("Adding font " + afi.getAFPFont().getFontName()); | log.debug("Adding font " + afi.getAFPFont().getFontName()); | ||||
} | } | ||||
List/*<FontTriplet>*/ fontTriplets = afi.getFontTriplets(); | |||||
List<FontTriplet> fontTriplets = afi.getFontTriplets(); | |||||
for (int j = 0; j < fontTriplets.size(); ++j) { | for (int j = 0; j < fontTriplets.size(); ++j) { | ||||
FontTriplet triplet = (FontTriplet) fontTriplets.get(j); | FontTriplet triplet = (FontTriplet) fontTriplets.get(j); | ||||
if (log.isDebugEnabled()) { | if (log.isDebugEnabled()) { | ||||
boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false); | boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false); | ||||
customizable.setNativeImagesSupported(nativeImageSupport); | customizable.setNativeImagesSupported(nativeImageSupport); | ||||
Configuration jpegConfig = imagesCfg.getChild("jpeg"); | |||||
boolean allowEmbedding = false; | |||||
float ieq = 1.0f; | |||||
if (jpegConfig != null) { | |||||
allowEmbedding = jpegConfig.getAttributeAsBoolean("allow-embedding", false); | |||||
String bitmapEncodingQuality = jpegConfig.getAttribute("bitmap-encoding-quality", null); | |||||
if (bitmapEncodingQuality != null) { | |||||
try { | |||||
ieq = Float.parseFloat(bitmapEncodingQuality); | |||||
} catch (NumberFormatException nfe) { | |||||
//ignore and leave the default above | |||||
} | |||||
} | |||||
} | |||||
customizable.canEmbedJpeg(allowEmbedding); | |||||
customizable.setBitmapEncodingQuality(ieq); | |||||
// shading (filled rectangles) | // shading (filled rectangles) | ||||
Configuration shadingCfg = cfg.getChild("shading"); | Configuration shadingCfg = cfg.getChild("shading"); | ||||
AFPShadingMode shadingMode = AFPShadingMode.valueOf( | AFPShadingMode shadingMode = AFPShadingMode.valueOf( | ||||
public void setupFontInfo(IFDocumentHandler documentHandler, FontInfo fontInfo) | public void setupFontInfo(IFDocumentHandler documentHandler, FontInfo fontInfo) | ||||
throws FOPException { | throws FOPException { | ||||
FontManager fontManager = userAgent.getFactory().getFontManager(); | FontManager fontManager = userAgent.getFactory().getFontManager(); | ||||
List<FontCollection> fontCollections = new java.util.ArrayList<FontCollection>(); | |||||
List<AFPFontCollection> fontCollections = new ArrayList<AFPFontCollection>(); | |||||
Configuration cfg = super.getRendererConfig(documentHandler.getMimeType()); | Configuration cfg = super.getRendererConfig(documentHandler.getMimeType()); | ||||
if (cfg != null) { | if (cfg != null) { |
private AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState, | private AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState, | ||||
int x, int y, int width, int height, int resolution) { | int x, int y, int width, int height, int resolution) { | ||||
// set the data object parameters | // set the data object parameters | ||||
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(); | |||||
AffineTransform at = paintingState.getData().getTransform(); | AffineTransform at = paintingState.getData().getTransform(); | ||||
at.translate(x, y); | at.translate(x, y); | ||||
objectAreaInfo.setX((int)Math.round(at.getTranslateX())); | |||||
objectAreaInfo.setY((int)Math.round(at.getTranslateY())); | |||||
objectAreaInfo.setWidthRes(resolution); | |||||
objectAreaInfo.setHeightRes(resolution); | |||||
AFPUnitConverter unitConv = paintingState.getUnitConverter(); | AFPUnitConverter unitConv = paintingState.getUnitConverter(); | ||||
objectAreaInfo.setWidth(Math.round(unitConv.mpt2units(width))); | |||||
objectAreaInfo.setHeight(Math.round(unitConv.mpt2units(height))); | |||||
int rotation = paintingState.getRotation(); | int rotation = paintingState.getRotation(); | ||||
objectAreaInfo.setRotation(rotation); | |||||
int objX = (int) Math.round(at.getTranslateX()); | |||||
int objY = (int) Math.round(at.getTranslateY()); | |||||
int objWidth = Math.round(unitConv.mpt2units(width)); | |||||
int objHeight = Math.round(unitConv.mpt2units(height)); | |||||
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(objX, objY, objWidth, objHeight, | |||||
resolution, rotation); | |||||
return objectAreaInfo; | return objectAreaInfo; | ||||
} | } | ||||
AFPPaintingState paintingState = afpContext.getPaintingState(); | AFPPaintingState paintingState = afpContext.getPaintingState(); | ||||
int resolution = paintingState.getResolution(); | int resolution = paintingState.getResolution(); | ||||
AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); | AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); | ||||
objectAreaInfo.setWidthRes(resolution); | |||||
objectAreaInfo.setHeightRes(resolution); | |||||
objectAreaInfo.setResolution(resolution); | |||||
// Image content | // Image content | ||||
ImageRawStream imageStream = (ImageRawStream)image; | ImageRawStream imageStream = (ImageRawStream)image; |
documents. Example: the fix of marks layering will be such a case when it's done. | documents. Example: the fix of marks layering will be such a case when it's done. | ||||
--> | --> | ||||
<release version="FOP Trunk" date="TBD"> | <release version="FOP Trunk" date="TBD"> | ||||
<action context="Code" dev="PH" type="add" fixes-bug="52089" due-to="JM, Mehdi Houshmand"> | |||||
Allow JPEG images to be embedded in an AFP document as is, without being decoded and | |||||
encoded. | |||||
</action> | |||||
<action context="Code" dev="PH" type="add" fixes-bug="52010" due-to="Mehdi Houshmand"> | <action context="Code" dev="PH" type="add" fixes-bug="52010" due-to="Mehdi Houshmand"> | ||||
Simplification of the build: Reduced code duplication and layout engine tests. | Simplification of the build: Reduced code duplication and layout engine tests. | ||||
</action> | </action> |
/* | |||||
* 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 static org.junit.Assert.assertEquals; | |||||
import org.junit.Before; | |||||
import org.junit.Test; | |||||
/** | |||||
* Test case for {@link AFPObjectAreaInfo}. | |||||
*/ | |||||
public class AFPObjectAreaInfoTestCase { | |||||
private AFPObjectAreaInfo sut; | |||||
/** | |||||
* Instantiate the system under test | |||||
*/ | |||||
@Before | |||||
public void setUp() { | |||||
sut = new AFPObjectAreaInfo(1, 2, 3, 4, 5, 6); | |||||
} | |||||
/** | |||||
* Test the getter functions with arbitrary data. | |||||
*/ | |||||
@Test | |||||
public void testGetters() { | |||||
assertEquals(1, sut.getX()); | |||||
assertEquals(2, sut.getY()); | |||||
assertEquals(3, sut.getWidth()); | |||||
assertEquals(4, sut.getHeight()); | |||||
assertEquals(5, sut.getWidthRes()); | |||||
assertEquals(5, sut.getHeightRes()); | |||||
assertEquals(6, sut.getRotation()); | |||||
} | |||||
/** | |||||
* Test the resolution setters with arbitrary data. | |||||
*/ | |||||
@Test | |||||
public void testSetters() { | |||||
assertEquals(5, sut.getWidthRes()); | |||||
assertEquals(5, sut.getHeightRes()); | |||||
sut.setResolution(20); | |||||
assertEquals(20, sut.getWidthRes()); | |||||
assertEquals(20, sut.getHeightRes()); | |||||
sut.setHeightRes(10); | |||||
assertEquals(20, sut.getWidthRes()); | |||||
assertEquals(10, sut.getHeightRes()); | |||||
sut.setWidthRes(9); | |||||
assertEquals(9, sut.getWidthRes()); | |||||
assertEquals(10, sut.getHeightRes()); | |||||
} | |||||
} |
/* | |||||
* 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 static org.junit.Assert.assertEquals; | |||||
import org.junit.Before; | |||||
import org.junit.Test; | |||||
/** | |||||
* Test case for {@link AFPPaintingState}. | |||||
*/ | |||||
public class AFPPaintingStateTestCase { | |||||
private AFPPaintingState sut; | |||||
/** | |||||
* Set up the system under test | |||||
*/ | |||||
@Before | |||||
public void setUp() { | |||||
sut = new AFPPaintingState(); | |||||
} | |||||
/** | |||||
* Test {get,set}BitmapEncodingQuality() | |||||
*/ | |||||
@Test | |||||
public void testGetSetBitmapEncodingQuality() { | |||||
sut.setBitmapEncodingQuality(0.5f); | |||||
assertEquals(0.5f, sut.getBitmapEncodingQuality(), 0.01f); | |||||
sut.setBitmapEncodingQuality(0.9f); | |||||
assertEquals(0.9f, sut.getBitmapEncodingQuality(), 0.01f); | |||||
} | |||||
/** | |||||
* Test {,set}CanEmbedJpeg | |||||
*/ | |||||
public void testGetSetCanEmbedJpeg() { | |||||
assertEquals(false, sut.canEmbedJpeg()); | |||||
sut.setCanEmbedJpeg(true); | |||||
assertEquals(true, sut.canEmbedJpeg()); | |||||
} | |||||
} |
/* | |||||
* 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 static org.junit.Assert.assertFalse; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | |||||
import org.junit.Before; | |||||
import org.junit.Test; | |||||
import org.apache.xmlgraphics.util.MimeConstants; | |||||
/** | |||||
* Test case for {@link AFPResourceManager}. | |||||
*/ | |||||
public class AFPResourceManagerTestCase { | |||||
private AFPResourceManager sut; | |||||
@Before | |||||
public void setUp() throws IOException { | |||||
sut = new AFPResourceManager(); | |||||
AFPPaintingState paintingState = new AFPPaintingState(); | |||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream(); | |||||
DataStream stream = sut.createDataStream(paintingState, outStream); | |||||
stream.startPage(0, 0, 0, 10, 10); | |||||
} | |||||
/** | |||||
* Ensures that if tryIncludeObject() is called with a new object, it returns false suggesting | |||||
* that we have to create said object. However, if it is called with an object that has already | |||||
* been created, it returns true suggesting that we don't have to create that object again. | |||||
* Page-segment is false. | |||||
* | |||||
* @throws IOException if an I/O error occurs | |||||
*/ | |||||
@Test | |||||
public void testTryIncludeObjectWithPageSegFalse() throws IOException { | |||||
AFPDataObjectInfo dataInfo = createAFPDataObjectInfo(); | |||||
// An empty object needs to be created every time! | |||||
assertFalse(sut.tryIncludeObject(dataInfo)); | |||||
sut.createObject(dataInfo); | |||||
assertTrue(sut.tryIncludeObject(dataInfo)); | |||||
} | |||||
/** | |||||
* {@code testTryIncludeObjectWithPageSegFalse()} but with page-segment true. | |||||
* | |||||
* @throws IOException if an I/O error occurs | |||||
*/ | |||||
@Test | |||||
public void testTryIncludeObjectWithPageSegTrue() throws IOException { | |||||
AFPDataObjectInfo dataInfo = createAFPDataObjectInfo(); | |||||
dataInfo.setCreatePageSegment(true); | |||||
// An empty object needs to be created every time! | |||||
assertFalse(sut.tryIncludeObject(dataInfo)); | |||||
sut.createObject(dataInfo); | |||||
assertTrue(sut.tryIncludeObject(dataInfo)); | |||||
} | |||||
private AFPDataObjectInfo createAFPDataObjectInfo() { | |||||
AFPDataObjectInfo dataInfo = new AFPDataObjectInfo(); | |||||
dataInfo.setMimeType(MimeConstants.MIME_TIFF); | |||||
dataInfo.setData(new byte[1]); | |||||
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(0, 0, 10, 10, 1, 0); | |||||
dataInfo.setObjectAreaInfo(objectAreaInfo); | |||||
return dataInfo; | |||||
} | |||||
} |
package org.apache.fop.afp; | package org.apache.fop.afp; | ||||
import org.apache.fop.afp.modca.IncludeObjectTestCase; | |||||
import org.junit.runner.RunWith; | import org.junit.runner.RunWith; | ||||
import org.junit.runners.Suite; | import org.junit.runners.Suite; | ||||
import org.junit.runners.Suite.SuiteClasses; | import org.junit.runners.Suite.SuiteClasses; | ||||
import org.apache.fop.afp.modca.IncludeObjectTestCase; | |||||
/** | /** | ||||
* Test suite for FOP's AFP classes. | * Test suite for FOP's AFP classes. | ||||
*/ | */ | ||||
@RunWith(Suite.class) | @RunWith(Suite.class) | ||||
@SuiteClasses({ | @SuiteClasses({ | ||||
IncludeObjectTestCase.class, | |||||
AFPResourceUtilTestCase.class | |||||
IncludeObjectTestCase.class, | |||||
AFPResourceUtilTestCase.class, | |||||
AFPObjectAreaInfoTestCase.class, | |||||
AFPPaintingStateTestCase.class | |||||
}) | }) | ||||
public class AFPTestSuite { | public class AFPTestSuite { | ||||
} | } |
/* | |||||
* 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 static org.junit.Assert.assertEquals; | |||||
import static org.junit.Assert.fail; | |||||
import java.io.IOException; | |||||
import org.junit.BeforeClass; | |||||
import org.junit.Test; | |||||
import org.xml.sax.SAXException; | |||||
import org.apache.fop.afp.AFPPaintingState; | |||||
import org.apache.fop.apps.FOPException; | |||||
import org.apache.fop.apps.FOUserAgent; | |||||
import org.apache.fop.apps.FopFactory; | |||||
/** | |||||
* Test case for {@link AFPRendererConfigurator}. | |||||
*/ | |||||
public class AFPRendererConfiguratorTestCase { | |||||
private static FOUserAgent userAgent; | |||||
private AFPRendererConfigurator sut; | |||||
/** | |||||
* The FOUserAgent only needs to be created once. | |||||
*/ | |||||
@BeforeClass | |||||
public static void createUserAgent() { | |||||
userAgent = FopFactory.newInstance().newFOUserAgent(); | |||||
} | |||||
/** | |||||
* Assigns an FOUserAgen with a config file at <code>uri</code> | |||||
* | |||||
* @param uri the URI of the config file | |||||
*/ | |||||
private void setConfigFile(String uri) { | |||||
String confTestsDir = "test/resources/conf/afp/"; | |||||
try { | |||||
userAgent.getFactory().setUserConfig(confTestsDir + uri); | |||||
sut = new AFPRendererConfigurator(userAgent); | |||||
} catch (IOException ioe) { | |||||
fail("IOException: " + ioe); | |||||
} catch (SAXException se) { | |||||
fail("SAXException: " + se); | |||||
} | |||||
} | |||||
/** | |||||
* Test several config files relating to JPEG images in AFP. | |||||
* | |||||
* @throws FOPException if an error is thrown | |||||
*/ | |||||
@Test | |||||
public void testJpegImageConfig() throws FOPException { | |||||
testJpegSettings("no_image_config.xconf", 1.0f, false); | |||||
testJpegSettings("can_embed_jpeg.xconf", 1.0f, true); | |||||
testJpegSettings("bitmap_encode_quality.xconf", 0.5f, false); | |||||
} | |||||
private void testJpegSettings(String uri, float bitmapEncodingQual, boolean canEmbed) | |||||
throws FOPException { | |||||
AFPDocumentHandler docHandler = new AFPDocumentHandler(); | |||||
setConfigFile(uri); | |||||
sut.configure(docHandler); | |||||
AFPPaintingState paintingState = docHandler.getPaintingState(); | |||||
assertEquals(bitmapEncodingQual, paintingState.getBitmapEncodingQuality(), 0.01f); | |||||
assertEquals(canEmbed, paintingState.canEmbedJpeg()); | |||||
} | |||||
} |
* Test suite for FOP's AFP output. | * Test suite for FOP's AFP output. | ||||
*/ | */ | ||||
@RunWith(Suite.class) | @RunWith(Suite.class) | ||||
@SuiteClasses({ NoOperationTestCase.class }) | |||||
@SuiteClasses({ | |||||
NoOperationTestCase.class, | |||||
AFPRendererConfiguratorTestCase.class }) | |||||
public class AFPTestSuite { | public class AFPTestSuite { | ||||
} | } |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<fop version="1.0"> | |||||
<base>.</base> | |||||
<source-resolution>72</source-resolution> | |||||
<target-resolution>72</target-resolution> | |||||
<image-loading> | |||||
</image-loading> | |||||
<default-page-settings height="11in" width="8.26in"/> | |||||
<renderers> | |||||
<renderer mime="application/x-afp"> | |||||
<images> | |||||
<jpeg allow-embedding="false" bitmap-encoding-quality="0.5"/> | |||||
</images> | |||||
</renderer> | |||||
</renderers> | |||||
</fop> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<fop version="1.0"> | |||||
<base>.</base> | |||||
<source-resolution>72</source-resolution> | |||||
<target-resolution>72</target-resolution> | |||||
<image-loading> | |||||
</image-loading> | |||||
<default-page-settings height="11in" width="8.26in"/> | |||||
<renderers> | |||||
<renderer mime="application/x-afp"> | |||||
<images> | |||||
<jpeg allow-embedding="true"/> | |||||
</images> | |||||
</renderer> | |||||
</renderers> | |||||
</fop> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<fop version="1.0"> | |||||
<base>.</base> | |||||
<source-resolution>72</source-resolution> | |||||
<target-resolution>72</target-resolution> | |||||
<image-loading> | |||||
</image-loading> | |||||
<default-page-settings height="11in" width="8.26in"/> | |||||
<renderers> | |||||
<renderer mime="application/x-afp"> | |||||
</renderer> | |||||
</renderers> | |||||
</fop> |