/*
* 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;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.pdmodel.common.COSDictionaryMap;
import org.apache.pdfbox.pdmodel.common.COSObjectable;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDFontFactory;
import org.apache.pdfbox.pdmodel.graphics.PDExtendedGraphicsState;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpaceFactory;
import org.apache.pdfbox.pdmodel.graphics.pattern.PDPatternResources;
import org.apache.pdfbox.pdmodel.graphics.shading.PDShadingResources;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
import org.apache.pdfbox.pdmodel.markedcontent.PDPropertyList;
/**
* This represents a set of resources available at the page/pages/stream level.
*
* @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
* @version $Revision: 1.16 $
*/
public class PDResources implements COSObjectable
{
private COSDictionary resources;
/**
* Default constructor.
*/
public PDResources()
{
resources = new COSDictionary();
}
/**
* Prepopulated resources.
*
* @param resourceDictionary The cos dictionary for this resource.
*/
public PDResources( COSDictionary resourceDictionary )
{
resources = resourceDictionary;
}
/**
* This will get the underlying dictionary.
*
* @return The dictionary for these resources.
*/
public COSDictionary getCOSDictionary()
{
return resources;
}
/**
* Convert this standard java object to a COS object.
*
* @return The cos object that matches this Java object.
*/
public COSBase getCOSObject()
{
return resources;
}
/**
* This will get the map of fonts. This will never return null. The keys are string
* and the values are PDFont objects.
*
* @param fontCache A map of existing PDFont objects to reuse.
* @return The map of fonts.
*
* @throws IOException If there is an error getting the fonts.
*/
public Map<String,PDFont> getFonts( Map<String,PDFont> fontCache ) throws IOException
{
Map<String,PDFont> retval = null;
COSDictionary fonts = (COSDictionary)resources.getDictionaryObject( COSName.FONT );
if( fonts == null )
{
fonts = new COSDictionary();
resources.setItem( COSName.FONT, fonts );
}
Map<String,PDFont> actuals = new HashMap<String,PDFont>();
retval = new COSDictionaryMap( actuals, fonts );
for( COSName fontName : fonts.keySet() )
{
COSBase font = fonts.getDictionaryObject( fontName );
//data-000174.pdf contains a font that is a COSArray, looks to be an error in the
//PDF, we will just ignore entries that are not dictionaries.
if( font instanceof COSDictionary )
{
COSDictionary fontDictionary = (COSDictionary)font;
actuals.put( fontName.getName(), PDFontFactory.createFont( fontDictionary, fontCache ));
}
}
return retval;
}
/**
* This will get the map of fonts. This will never return null. The keys are string
* and the values are PDFont objects.
*
* @return The map of fonts.
*
* @throws IOException If there is an error getting the fonts.
*/
public Map<String,PDFont> getFonts() throws IOException
{
return getFonts( null );
}
/**
* This will get the map of PDXObjects that are in the resource dictionary.
*
* @return The map of xobjects.
*
* @throws IOException If there is an error creating the xobjects.
*/
public Map<String,PDXObject> getXObjects() throws IOException
{
Map<String,PDXObject> retval = null;
COSDictionary xobjects = (COSDictionary)resources.getDictionaryObject( COSName.XOBJECT );
if( xobjects == null )
{
xobjects = new COSDictionary();
resources.setItem( COSName.XOBJECT, xobjects );
}
Map<String,PDXObject> actuals = new HashMap<String,PDXObject>();
retval = new COSDictionaryMap( actuals, xobjects );
for( COSName objName : xobjects.keySet() )
{
COSBase cosObject = xobjects.getDictionaryObject(objName);
PDXObject xobject = PDXObject.createXObject( cosObject );
if( xobject !=null )
{
actuals.put( objName.getName(), xobject);
}
}
return retval;
}
/**
* This will get the map of images. An empty map will be returned if there
* are no underlying images.
* So far the keys are COSName of the image
* and the value is the corresponding PDXObjectImage.
*
* @author By BM
* @return The map of images.
* @throws IOException If there is an error writing the picture.
*/
public Map<String,PDXObjectImage> getImages() throws IOException
{
Map<String,PDXObjectImage> retval = null;
COSDictionary images = (COSDictionary)resources.getDictionaryObject( COSName.XOBJECT );
if( images == null )
{
images = new COSDictionary();
resources.setItem( COSName.XOBJECT, images );
}
Map<String,PDXObjectImage> actuals = new HashMap<String,PDXObjectImage>();
retval = new COSDictionaryMap( actuals, images );
for( COSName imageName : images.keySet() )
{
COSStream image = (COSStream)(images.getDictionaryObject(imageName));
COSName subType =(COSName)image.getDictionaryObject(COSName.SUBTYPE);
if( subType.equals(COSName.IMAGE) )
{
PDXObjectImage ximage = (PDXObjectImage)PDXObject.createXObject( image );
if( ximage !=null )
{
actuals.put( imageName.getName(), ximage);
}
}
}
return retval;
}
/**
* This will set the map of fonts.
*
* @param fonts The new map of fonts.
*/
public void setFonts( Map<String,PDFont> fonts )
{
resources.setItem( COSName.FONT, COSDictionaryMap.convert( fonts ) );
}
/**
* This will get the map of colorspaces. This will return null if the underlying
* resources dictionary does not have a colorspace dictionary. The keys are string
* and the values are PDColorSpace objects.
*
* @return The map of colorspaces.
*
* @throws IOException If there is an error getting the colorspaces.
*/
public Map<String,PDColorSpace> getColorSpaces() throws IOException
{
Map<String,PDColorSpace> retval = null;
COSDictionary colorspaces = (COSDictionary)resources.getDictionaryObject( COSName.COLORSPACE );
if( colorspaces != null )
{
Map<String,PDColorSpace> actuals = new HashMap<String,PDColorSpace>();
retval = new COSDictionaryMap( actuals, colorspaces );
for( COSName csName : colorspaces.keySet() )
{
COSBase cs = colorspaces.getDictionaryObject( csName );
actuals.put( csName.getName(), PDColorSpaceFactory.createColorSpace( cs ) );
}
}
return retval;
}
/**
* This will set the map of colorspaces.
*
* @param colorspaces The new map of colorspaces.
*/
public void setColorSpaces( Map<String,PDColorSpace> colorspaces )
{
resources.setItem( COSName.COLORSPACE, COSDictionaryMap.convert( colorspaces ) );
}
/**
* This will get the map of graphic states. This will return null if the underlying
* resources dictionary does not have a graphics dictionary. The keys are the graphic state
* name as a String and the values are PDExtendedGraphicsState objects.
*
* @return The map of extended graphic state objects.
*/
public Map<String,PDExtendedGraphicsState> getGraphicsStates()
{
Map<String,PDExtendedGraphicsState> retval = null;
COSDictionary states = (COSDictionary)resources.getDictionaryObject( COSName.EXT_G_STATE );
if( states != null )
{
Map<String,PDExtendedGraphicsState> actuals = new HashMap<String,PDExtendedGraphicsState>();
retval = new COSDictionaryMap( actuals, states );
for( COSName name : states.keySet() )
{
COSDictionary dictionary = (COSDictionary)states.getDictionaryObject( name );
actuals.put( name.getName(), new PDExtendedGraphicsState( dictionary ) );
}
}
return retval;
}
/**
* This will set the map of graphics states.
*
* @param states The new map of states.
*/
public void setGraphicsStates( Map<String,PDExtendedGraphicsState> states )
{
Iterator<String> iter = states.keySet().iterator();
COSDictionary dic = new COSDictionary();
while( iter.hasNext() )
{
String name = (String)iter.next();
PDExtendedGraphicsState state = states.get( name );
dic.setItem( COSName.getPDFName( name ), state.getCOSObject() );
}
resources.setItem( COSName.EXT_G_STATE, dic );
}
/**
* Returns the dictionary mapping resource names to property list dictionaries for marked
* content.
* @return the property list
*/
public PDPropertyList getProperties()
{
PDPropertyList retval = null;
COSDictionary props = (COSDictionary)resources.getDictionaryObject(COSName.PROPERTIES);
if (props != null)
{
retval = new PDPropertyList(props);
}
return retval;
}
/**
* Sets the dictionary mapping resource names to property list dictionaries for marked
* content.
* @param props the property list
*/
public void setProperties(PDPropertyList props)
{
resources.setItem(COSName.PROPERTIES, props.getCOSObject());
}
/**
* This will get the map of patterns. This will return null if the underlying
* resources dictionary does not have a patterns dictionary. The keys are the pattern
* name as a String and the values are PDPatternResources objects.
*
* @return The map of pattern resources objects.
*
* @throws IOException If there is an error getting the pattern resources.
*/
public Map<String,PDPatternResources> getPatterns() throws IOException
{
Map<String,PDPatternResources> retval = null;
COSDictionary patterns = (COSDictionary)resources.getDictionaryObject( COSName.PATTERN );
if( patterns != null )
{
Map<String,PDPatternResources> actuals = new HashMap<String,PDPatternResources>();
retval = new COSDictionaryMap( actuals, patterns );
for( COSName name : patterns.keySet() )
{
COSDictionary dictionary = (COSDictionary)patterns.getDictionaryObject( name );
actuals.put( name.getName(), PDPatternResources.create( dictionary ) );
}
}
return retval;
}
/**
* This will set the map of patterns.
*
* @param patterns The new map of patterns.
*/
public void setPatterns( Map<String,PDPatternResources> patterns )
{
Iterator<String> iter = patterns.keySet().iterator();
COSDictionary dic = new COSDictionary();
while( iter.hasNext() )
{
String name = iter.next();
PDPatternResources pattern = patterns.get( name );
dic.setItem( COSName.getPDFName( name ), pattern.getCOSObject() );
}
resources.setItem( COSName.PATTERN, dic );
}
/**
* This will get the map of shadings. This will return null if the underlying
* resources dictionary does not have a shading dictionary. The keys are the shading
* name as a String and the values are PDShadingResources objects.
*
* @return The map of shading resources objects.
*
* @throws IOException If there is an error getting the shading resources.
*/
public Map<String,PDShadingResources> getShadings() throws IOException
{
Map<String,PDShadingResources> retval = null;
COSDictionary shadings = (COSDictionary)resources.getDictionaryObject( COSName.SHADING );
if( shadings != null )
{
Map<String,PDShadingResources> actuals = new HashMap<String,PDShadingResources>();
retval = new COSDictionaryMap( actuals, shadings );
for( COSName name : shadings.keySet() )
{
COSDictionary dictionary = (COSDictionary)shadings.getDictionaryObject( name );
actuals.put( name.getName(), PDShadingResources.create( dictionary ) );
}
}
return retval;
}
/**
* This will set the map of shadings.
*
* @param shadings The new map of shadings.
*/
public void setShadings( Map<String,PDShadingResources> shadings )
{
Iterator<String> iter = shadings.keySet().iterator();
COSDictionary dic = new COSDictionary();
while( iter.hasNext() )
{
String name = iter.next();
PDShadingResources shading = shadings.get( name );
dic.setItem( COSName.getPDFName( name ), shading.getCOSObject() );
}
resources.setItem( COSName.SHADING, dic );
}
}