org.apache.pdfbox.pdmodel.graphics.shading.PDShading Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pdfbox Show documentation
Show all versions of pdfbox Show documentation
The Apache PDFBox library is an open source Java tool for working with PDF documents.
/*
* 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.graphics.shading;
import java.awt.Paint;
import java.io.IOException;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.common.COSObjectable;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.common.function.PDFunction;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.util.Matrix;
/**
* A Shading Resource.
*
*/
public abstract class PDShading implements COSObjectable
{
private final COSDictionary dictionary;
private COSArray background = null;
private PDRectangle bBox = null;
private PDColorSpace colorSpace = null;
private PDFunction function = null;
private PDFunction[] functionArray = null;
/**
* shading type 1 = function based shading.
*/
public static final int SHADING_TYPE1 = 1;
/**
* shading type 2 = axial shading.
*/
public static final int SHADING_TYPE2 = 2;
/**
* shading type 3 = radial shading.
*/
public static final int SHADING_TYPE3 = 3;
/**
* shading type 4 = Free-Form Gouraud-Shaded Triangle Meshes.
*/
public static final int SHADING_TYPE4 = 4;
/**
* shading type 5 = Lattice-Form Gouraud-Shaded Triangle Meshes.
*/
public static final int SHADING_TYPE5 = 5;
/**
* shading type 6 = Coons Patch Meshes.
*/
public static final int SHADING_TYPE6 = 6;
/**
* shading type 7 = Tensor-Product Patch Meshes.
*/
public static final int SHADING_TYPE7 = 7;
/**
* Default constructor.
*/
public PDShading()
{
dictionary = new COSDictionary();
}
/**
* Constructor using the given shading dictionary.
*
* @param shadingDictionary the dictionary for this shading
*/
public PDShading(COSDictionary shadingDictionary)
{
dictionary = shadingDictionary;
}
/**
* This will get the underlying dictionary.
*
* @return the dictionary for this shading.
*/
@Override
public COSDictionary getCOSObject()
{
return dictionary;
}
/**
* This will return the type.
*
* @return the type of object that this is
*/
public String getType()
{
return COSName.SHADING.getName();
}
/**
* This will set the shading type.
*
* @param shadingType the new shading type
*/
public void setShadingType(int shadingType)
{
dictionary.setInt(COSName.SHADING_TYPE, shadingType);
}
/**
* This will return the shading type.
*
* @return the shading typ
*/
public abstract int getShadingType();
/**
* This will set the background.
*
* @param newBackground the new background
*/
public void setBackground(COSArray newBackground)
{
background = newBackground;
dictionary.setItem(COSName.BACKGROUND, newBackground);
}
/**
* This will return the background.
*
* @return the background
*/
public COSArray getBackground()
{
if (background == null)
{
background = (COSArray) dictionary.getDictionaryObject(COSName.BACKGROUND);
}
return background;
}
/**
* An array of four numbers in the form coordinate system (see below),
* giving the coordinates of the left, bottom, right, and top edges,
* respectively, of the shading's bounding box.
*
* @return the BBox of the form
*/
public PDRectangle getBBox()
{
if (bBox == null)
{
COSArray array = (COSArray) dictionary.getDictionaryObject(COSName.BBOX);
if (array != null)
{
bBox = new PDRectangle(array);
}
}
return bBox;
}
/**
* This will set the BBox (bounding box) for this Shading.
*
* @param newBBox the new BBox
*/
public void setBBox(PDRectangle newBBox)
{
bBox = newBBox;
if (bBox == null)
{
dictionary.removeItem(COSName.BBOX);
}
else
{
dictionary.setItem(COSName.BBOX, bBox.getCOSArray());
}
}
/**
* This will set the AntiAlias value.
*
* @param antiAlias the new AntiAlias value
*/
public void setAntiAlias(boolean antiAlias)
{
dictionary.setBoolean(COSName.ANTI_ALIAS, antiAlias);
}
/**
* This will return the AntiAlias value.
*
* @return the AntiAlias value
*/
public boolean getAntiAlias()
{
return dictionary.getBoolean(COSName.ANTI_ALIAS, false);
}
/**
* This will get the color space or null if none exists.
*
* @return the color space for the shading
* @throws IOException if there is an error getting the color space
*/
public PDColorSpace getColorSpace() throws IOException
{
if (colorSpace == null)
{
COSBase colorSpaceDictionary = dictionary.getDictionaryObject(COSName.CS, COSName.COLORSPACE);
colorSpace = PDColorSpace.create(colorSpaceDictionary);
}
return colorSpace;
}
/**
* This will set the color space for the shading.
*
* @param colorSpace the color space
*/
public void setColorSpace(PDColorSpace colorSpace)
{
this.colorSpace = colorSpace;
if (colorSpace != null)
{
dictionary.setItem(COSName.COLORSPACE, colorSpace.getCOSObject());
}
else
{
dictionary.removeItem(COSName.COLORSPACE);
}
}
/**
* Create the correct PD Model shading based on the COS base shading.
*
* @param resourceDictionary the COS shading dictionary
* @return the newly created shading resources object
* @throws IOException if we are unable to create the PDShading object
*/
public static PDShading create(COSDictionary resourceDictionary) throws IOException
{
PDShading shading = null;
int shadingType = resourceDictionary.getInt(COSName.SHADING_TYPE, 0);
switch (shadingType)
{
case SHADING_TYPE1:
shading = new PDShadingType1(resourceDictionary);
break;
case SHADING_TYPE2:
shading = new PDShadingType2(resourceDictionary);
break;
case SHADING_TYPE3:
shading = new PDShadingType3(resourceDictionary);
break;
case SHADING_TYPE4:
shading = new PDShadingType4(resourceDictionary);
break;
case SHADING_TYPE5:
shading = new PDShadingType5(resourceDictionary);
break;
case SHADING_TYPE6:
shading = new PDShadingType6(resourceDictionary);
break;
case SHADING_TYPE7:
shading = new PDShadingType7(resourceDictionary);
break;
default:
throw new IOException("Error: Unknown shading type " + shadingType);
}
return shading;
}
/**
* This will set the function for the color conversion.
*
* @param newFunction the new function
*/
public void setFunction(PDFunction newFunction)
{
functionArray = null;
function = newFunction;
getCOSObject().setItem(COSName.FUNCTION, newFunction);
}
/**
* This will set the functions COSArray for the color conversion.
*
* @param newFunctions the new COSArray containing all functions
*/
public void setFunction(COSArray newFunctions)
{
functionArray = null;
function = null;
getCOSObject().setItem(COSName.FUNCTION, newFunctions);
}
/**
* This will return the function used to convert the color values.
*
* @return the function
* @throws java.io.IOException if we were not able to create the function.
*/
public PDFunction getFunction() throws IOException
{
if (function == null)
{
COSBase dictionaryFunctionObject = getCOSObject().getDictionaryObject(COSName.FUNCTION);
if (dictionaryFunctionObject != null)
{
function = PDFunction.create(dictionaryFunctionObject);
}
}
return function;
}
/**
* Provide the function(s) of the shading dictionary as array.
*
* @return an array containing the function(s).
* @throws IOException if we were unable to create a function.
*/
private PDFunction[] getFunctionsArray() throws IOException
{
if (functionArray == null)
{
COSBase functionObject = getCOSObject().getDictionaryObject(COSName.FUNCTION);
if (functionObject instanceof COSDictionary)
{
functionArray = new PDFunction[1];
functionArray[0] = PDFunction.create(functionObject);
}
else if (functionObject instanceof COSArray)
{
COSArray functionCOSArray = (COSArray) functionObject;
int numberOfFunctions = functionCOSArray.size();
functionArray = new PDFunction[numberOfFunctions];
for (int i = 0; i < numberOfFunctions; i++)
{
functionArray[i] = PDFunction.create(functionCOSArray.get(i));
}
}
else
{
throw new IOException("mandatory /Function element must be a dictionary or an array");
}
}
return functionArray;
}
/**
* Convert the input value using the functions of the shading dictionary.
*
* @param inputValue the input value
* @return the output values
* @throws IOException thrown if something went wrong
*/
public float[] evalFunction(float inputValue) throws IOException
{
return evalFunction(new float[] { inputValue });
}
/**
* Convert the input values using the functions of the shading dictionary.
*
* @param input the input values
* @return the output values
* @throws IOException thrown if something went wrong
*/
public float[] evalFunction(float[] input) throws IOException
{
PDFunction[] functions = getFunctionsArray();
int numberOfFunctions = functions.length;
float[] returnValues;
if (numberOfFunctions == 1)
{
returnValues = functions[0].eval(input);
}
else
{
returnValues = new float[numberOfFunctions];
for (int i = 0; i < numberOfFunctions; i++)
{
float[] newValue = functions[i].eval(input);
returnValues[i] = newValue[0];
}
}
// From the PDF spec:
// "If the value returned by the function for a given colour component
// is out of range, it shall be adjusted to the nearest valid value."
for (int i = 0; i < returnValues.length; ++i)
{
if (returnValues[i] < 0)
{
returnValues[i] = 0;
}
else if (returnValues[i] > 1)
{
returnValues[i] = 1;
}
}
return returnValues;
}
/**
* Returns an AWT paint which corresponds to this shading
*
* @param matrix the pattern matrix concatenated with that of the parent content stream,
* this matrix which maps the pattern's internal coordinate system to user space
* @return an AWT Paint instance
*/
public abstract Paint toPaint(Matrix matrix);
}