blob: 987102af7ef4e1e8287dc8f385aa41f70aa6a3ac [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
package org.apache.fop.afp;
import java.awt.geom.Rectangle2D;
import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.apache.fop.afp.ioca.IDEStructureParameter;
import org.apache.fop.afp.ioca.ImageContent;
import org.apache.fop.afp.modca.AbstractDataObject;
import org.apache.fop.afp.modca.AbstractNamedAFPObject;
import org.apache.fop.afp.modca.Document;
import org.apache.fop.afp.modca.GraphicsObject;
import org.apache.fop.afp.modca.ImageObject;
import org.apache.fop.afp.modca.IncludeObject;
import org.apache.fop.afp.modca.ObjectContainer;
import org.apache.fop.afp.modca.Overlay;
import org.apache.fop.afp.modca.PageSegment;
import org.apache.fop.afp.modca.Registry;
import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet;
/**
* Factory for high level data objects (Image/Graphics etc)
*/
public class AFPDataObjectFactory {
private final Factory factory;
/**
* Main constructor
*
* @param factory an object factory
*/
public AFPDataObjectFactory(Factory factory) {
this.factory = factory;
}
/**
* Creates and configures an ObjectContainer.
*
* @param dataObjectInfo the object container info
* @return a newly created Object Container
*/
public ObjectContainer createObjectContainer(AFPDataObjectInfo dataObjectInfo) {
ObjectContainer objectContainer = factory.createObjectContainer();
// set data object viewport (i.e. position, rotation, dimension, resolution)
objectContainer.setViewport(dataObjectInfo);
// set object classification
Registry.ObjectType objectType = dataObjectInfo.getObjectType();
AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
AFPResourceLevel resourceLevel = resourceInfo.getLevel();
final boolean dataInContainer = true;
final boolean containerHasOEG = resourceLevel.isInline();
final boolean dataInOCD = true;
objectContainer.setObjectClassification(
ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT,
objectType, dataInContainer, containerHasOEG, dataInOCD);
objectContainer.setData(dataObjectInfo.getData());
return objectContainer;
}
/**
* Creates and configures an IOCA Image Object.
*
* @param imageObjectInfo the image object info
* @return a newly created IOCA Image Object
*/
public ImageObject createImage(AFPImageObjectInfo imageObjectInfo) {
// IOCA bitmap image
ImageObject imageObj = factory.createImageObject();
// set data object viewport (i.e. position, rotation, dimension, resolution)
imageObj.setViewport(imageObjectInfo);
if (imageObjectInfo.hasCompression()) {
int compression = imageObjectInfo.getCompression();
switch (compression) {
case TIFFImage.COMP_FAX_G3_1D:
imageObj.setEncoding(ImageContent.COMPID_G3_MH);
break;
case TIFFImage.COMP_FAX_G3_2D:
imageObj.setEncoding(ImageContent.COMPID_G3_MR);
break;
case TIFFImage.COMP_FAX_G4_2D:
imageObj.setEncoding(ImageContent.COMPID_G3_MMR);
break;
case ImageContent.COMPID_JPEG:
imageObj.setEncoding((byte)compression);
break;
default:
throw new IllegalStateException(
"Invalid compression scheme: " + compression);
}
}
ImageContent content = imageObj.getImageSegment().getImageContent();
int bitsPerPixel = imageObjectInfo.getBitsPerPixel();
imageObj.setIDESize((byte) bitsPerPixel);
IDEStructureParameter ideStruct;
switch (bitsPerPixel) {
case 1:
//Skip IDE Structure Parameter
break;
case 4:
case 8:
//A grayscale image
ideStruct = content.needIDEStructureParameter();
ideStruct.setBitsPerComponent(new int[] {bitsPerPixel});
ideStruct.setColorModel(IDEStructureParameter.COLOR_MODEL_YCBCR);
break;
case 24:
ideStruct = content.needIDEStructureParameter();
ideStruct.setDefaultRGBColorModel();
break;
case 32:
ideStruct = content.needIDEStructureParameter();
ideStruct.setDefaultCMYKColorModel();
break;
default:
throw new IllegalArgumentException("Unsupported number of bits per pixel: "
+ bitsPerPixel);
}
if (bitsPerPixel > 1 && imageObjectInfo.isSubtractive()) {
ideStruct = content.needIDEStructureParameter();
ideStruct.setSubtractive(imageObjectInfo.isSubtractive());
}
imageObj.setData(imageObjectInfo.getData());
imageObj.setTransparencyMask(imageObjectInfo.getTransparencyMask());
return imageObj;
}
/**
* Creates and returns a new graphics object.
*
* @param graphicsObjectInfo the graphics object info
* @return a new graphics object
*/
public GraphicsObject createGraphic(AFPGraphicsObjectInfo graphicsObjectInfo) {
// set newly created graphics object in g2d
GraphicsObject graphicsObj = factory.createGraphicsObject();
// set data object viewport (i.e. position, rotation, dimension, resolution)
graphicsObj.setViewport(graphicsObjectInfo);
AFPGraphics2D g2d = graphicsObjectInfo.getGraphics2D();
g2d.setGraphicsObject(graphicsObj);
//set color converter (i.e. an rgb to grayscale converter)
graphicsObj.setColorConverter(g2d.getPaintingState().getColorConverter());
// paint to graphics object
Graphics2DImagePainter painter = graphicsObjectInfo.getPainter();
Rectangle2D area = graphicsObjectInfo.getArea();
g2d.scale(1, -1);
g2d.translate(0, -area.getHeight());
painter.paint(g2d, area);
graphicsObj.setComplete(true);
// return painted graphics object
return graphicsObj;
}
/**
* Creates and returns a new include object.
*
* @param includeName the include name
* @param dataObjectInfo a data object info
*
* @return a new include object
*/
public IncludeObject createInclude(String includeName, AFPDataObjectInfo dataObjectInfo) {
IncludeObject includeObj = factory.createInclude(includeName);
if (dataObjectInfo instanceof AFPImageObjectInfo) {
// IOCA image object
includeObj.setObjectType(IncludeObject.TYPE_IMAGE);
} else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) {
// graphics object
includeObj.setObjectType(IncludeObject.TYPE_GRAPHIC);
} else {
// object container
includeObj.setObjectType(IncludeObject.TYPE_OTHER);
// set mandatory object classification (type other)
Registry.ObjectType objectType = dataObjectInfo.getObjectType();
if (objectType != null) {
// set object classification
final boolean dataInContainer = true;
final boolean containerHasOEG = false; // environment parameters set in include
final boolean dataInOCD = true;
includeObj.setObjectClassification(
// object scope not defined
ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT,
objectType, dataInContainer, containerHasOEG, dataInOCD);
} else {
throw new IllegalStateException(
"Failed to set Object Classification Triplet on Object Container.");
}
}
AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
int xOffset = objectAreaInfo.getX();
int yOffset = objectAreaInfo.getY();
includeObj.setObjectAreaOffset(xOffset, yOffset);
int width = objectAreaInfo.getWidth();
int height = objectAreaInfo.getHeight();
includeObj.setObjectAreaSize(width, height);
int rotation = objectAreaInfo.getRotation();
includeObj.setObjectAreaOrientation(rotation);
int widthRes = objectAreaInfo.getWidthRes();
int heightRes = objectAreaInfo.getHeightRes();
includeObj.setMeasurementUnits(widthRes, heightRes);
includeObj.setMappingOption(MappingOptionTriplet.SCALE_TO_FIT);
return includeObj;
}
/**
* Creates a resource object wrapper for named includable data objects
*
* @param namedObj an named object
* @param resourceInfo resource information
* @param objectType the object type
* @return a new resource object wrapper
*/
public ResourceObject createResource(AbstractNamedAFPObject namedObj,
AFPResourceInfo resourceInfo, Registry.ObjectType objectType) {
ResourceObject resourceObj = null;
String resourceName = resourceInfo.getName();
if (resourceName != null) {
resourceObj = factory.createResource(resourceName);
} else {
resourceObj = factory.createResource();
}
if (namedObj instanceof Document) {
resourceObj.setType(ResourceObject.TYPE_DOCUMENT);
} else if (namedObj instanceof PageSegment) {
resourceObj.setType(ResourceObject.TYPE_PAGE_SEGMENT);
} else if (namedObj instanceof Overlay) {
resourceObj.setType(ResourceObject.TYPE_OVERLAY_OBJECT);
} else if (namedObj instanceof AbstractDataObject) {
AbstractDataObject dataObj = (AbstractDataObject)namedObj;
if (namedObj instanceof ObjectContainer) {
resourceObj.setType(ResourceObject.TYPE_OBJECT_CONTAINER);
// set object classification
final boolean dataInContainer = true;
final boolean containerHasOEG = false; // must be included
final boolean dataInOCD = true;
// mandatory triplet for object container
resourceObj.setObjectClassification(
ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT,
objectType, dataInContainer, containerHasOEG, dataInOCD);
} else if (namedObj instanceof ImageObject) {
// ioca image type
resourceObj.setType(ResourceObject.TYPE_IMAGE);
} else if (namedObj instanceof GraphicsObject) {
resourceObj.setType(ResourceObject.TYPE_GRAPHIC);
} else {
throw new UnsupportedOperationException(
"Unsupported resource object for data object type " + dataObj);
}
} else {
throw new UnsupportedOperationException(
"Unsupported resource object type " + namedObj);
}
// set the resource information/classification on the data object
resourceObj.setDataObject(namedObj);
return resourceObj;
}
}