/* * 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.pdfbox.pdmodel.common.function; import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSBase; import org.apache.pdfbox.cos.COSFloat; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.cos.COSNumber; import org.apache.pdfbox.pdmodel.common.PDRange; import java.io.IOException; /** * This class represents a type 3 function in a PDF document. * * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a> * @version $Revision: 1.2 $ */ public class PDFunctionType3 extends PDFunction { private COSArray functions = null; private COSArray encode = null; private COSArray bounds = null; /** * Constructor. * * @param functionStream The function . */ public PDFunctionType3(COSBase function) { super( function ); } /** * {@inheritDoc} */ public int getFunctionType() { return 3; } /** * {@inheritDoc} */ public COSArray eval(COSArray input) throws IOException { //This function is known as a "stitching" function. Based on the input, it decides which child function to call. //See PDF Reference section 3.9.3. PDFunction function = null; float x = ((COSNumber)input.get(0)).floatValue(); PDRange domain = getDomainForInput(1); // clip input value to domain x = clipToRange(x, domain.getMin(), domain.getMax()); float[] boundsValues = getBounds().toFloatArray(); int boundsSize = boundsValues.length; if (boundsSize == 0 || x < boundsValues[0]) { function = PDFunction.create(getFunctions().get(0)); PDRange encode = getEncodeForParameter(0); if (boundsSize == 0) { x = interpolate(x, domain.getMin(), domain.getMax(), encode.getMin(), encode.getMax()); } else { x = interpolate(x, domain.getMin(), boundsValues[0], encode.getMin(), encode.getMax()); } } else { for (int i=0; i<boundsSize-1; i++) { if ( x >= boundsValues[i] && x < boundsValues[i+1] ) { function = PDFunction.create(getFunctions().get(i+1)); PDRange encode = getEncodeForParameter(i+1); x = interpolate(x, boundsValues[i], boundsValues[i+1], encode.getMin(), encode.getMax()); break; } } if(function==null) //must be in last partition { function = PDFunction.create(getFunctions().get(boundsSize+1)); PDRange encode = getEncodeForParameter(boundsSize+1); x = interpolate(x, boundsValues[boundsSize-1], domain.getMax(), encode.getMin(), encode.getMax()); } } COSArray functionValues = new COSArray(); functionValues.add(new COSFloat(x)); COSArray functionResult = function.eval(functionValues); // clip to range if available return clipToRange(functionResult); } /** * Returns all functions values as COSArray. * * @return the functions array. */ public COSArray getFunctions() { if (functions == null) { functions = (COSArray)(getDictionary().getDictionaryObject( COSName.FUNCTIONS )); } return functions; } /** * Returns all bounds values as COSArray. * * @return the bounds array. */ public COSArray getBounds() { if (bounds == null) { bounds = (COSArray)(getDictionary().getDictionaryObject( COSName.BOUNDS )); } return bounds; } /** * Returns all encode values as COSArray. * * @return the encode array. */ public COSArray getEncode() { if (encode == null) { encode = (COSArray)(getDictionary().getDictionaryObject( COSName.ENCODE )); } return encode; } /** * Get the encode for the input parameter. * * @param paramNum The function parameter number. * * @return The encode parameter range or null if none is set. */ private PDRange getEncodeForParameter(int n) { COSArray encodeValues = getEncode(); return new PDRange( encodeValues, n ); } }