/*****************************************************************************
*
* 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.
*
****************************************************************************/
package org.apache.padaf.preflight.font;
import java.awt.Image;
import java.io.IOException;
import java.util.List;
import org.apache.fontbox.util.BoundingBox;
import org.apache.padaf.preflight.DocumentHandler;
import org.apache.padaf.preflight.utils.ContentStreamEngine;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSInteger;
import org.apache.pdfbox.cos.COSNumber;
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDInlinedImage;
import org.apache.pdfbox.util.ImageParameters;
import org.apache.pdfbox.util.PDFOperator;
/**
* This class is used to parse a glyph of a Type3 font program. If the glyph is
* parsed without error, the width of the glyph is accessible through the
* getWidth method.
*/
public class PDFAType3StreamParser extends ContentStreamEngine {
private boolean firstOperator = true;
private float width = 0;
private PDInlinedImage image = null;
private BoundingBox box = null;
public PDFAType3StreamParser(DocumentHandler handler) {
super(handler);
}
/**
* This will parse a type3 stream and create an image from it.
*
* @param type3Stream
* The stream containing the operators to draw the image.
*
* @return The image that was created.
*
* @throws IOException
* If there is an error processing the stream.
*/
public Image createImage(COSStream type3Stream) throws IOException {
resetEngine();
processSubStream(null, null, type3Stream);
return image.createImage();
}
/**
* This is used to handle an operation.
*
* @param operator
* The operation to perform.
* @param arguments
* The list of arguments.
*
* @throws IOException
* If there is an error processing the operation.
*/
protected void processOperator(PDFOperator operator, List arguments)
throws IOException {
super.processOperator(operator, arguments);
String operation = operator.getOperation();
if (operation.equals("BI")) {
ImageParameters params = operator.getImageParameters();
image = new PDInlinedImage();
image.setImageParameters(params);
image.setImageData(operator.getImageData());
validImageFilter(operator);
validImageColorSpace(operator);
}
if (operation.equals("d0")) {
// set glyph with for a type3 font
// COSNumber horizontalWidth = (COSNumber)arguments.get( 0 );
// COSNumber verticalWidth = (COSNumber)arguments.get( 1 );
// width = horizontalWidth.intValue();
// height = verticalWidth.intValue();
checkType3FirstOperator(arguments);
} else if (operation.equals("d1")) {
// set glyph with and bounding box for type 3 font
// COSNumber horizontalWidth = (COSNumber)arguments.get( 0 );
// COSNumber verticalWidth = (COSNumber)arguments.get( 1 );
COSNumber llx = (COSNumber) arguments.get(2);
COSNumber lly = (COSNumber) arguments.get(3);
COSNumber urx = (COSNumber) arguments.get(4);
COSNumber ury = (COSNumber) arguments.get(5);
// width = horizontalWidth.intValue();
// height = verticalWidth.intValue();
box = new BoundingBox();
box.setLowerLeftX(llx.floatValue());
box.setLowerLeftY(lly.floatValue());
box.setUpperRightX(urx.floatValue());
box.setUpperRightY(ury.floatValue());
checkType3FirstOperator(arguments);
}
checkColorOperators(operation);
validRenderingIntent(operator, arguments);
checkSetColorSpaceOperators(operator, arguments);
validNumberOfGraphicStates(operator);
firstOperator = false;
}
/**
* According to the PDF Reference, the first operator in a CharProc of a Type3
* font must be "d0" or "d1". This method process this validation. This method
* is called by the processOperator method.
*
* @param arguments
* @throws IOException
*/
private void checkType3FirstOperator(List arguments) throws IOException {
if (!firstOperator) {
throw new IOException("Type3 CharProc : First operator must be d0 or d1");
}
Object obj = arguments.get(0);
if (obj instanceof Number) {
width = ((Number) obj).intValue();
} else if (obj instanceof COSInteger) {
width = ((COSInteger) obj).floatValue();
} else if (obj instanceof COSFloat) {
width = ((COSFloat)obj).floatValue();
} else {
throw new IOException(
"Unexpected argument type. Expected : COSInteger or Number / Received : "
+ obj.getClass().getName());
}
}
/**
* @return the width of the CharProc glyph description
*/
public float getWidth() {
return this.width;
}
}