Author: lehmi
Date: Sun Jan 22 13:13:39 2012
New Revision: 1234506

URL: http://svn.apache.org/viewvc?rev=1234506&view=rev
Log:
PDFBOX-610: removed font caching as proposed by Peter Costello, optimized and 
simplified the handling of pdf resources

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDResources.java
    
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/edit/PDPageContentStream.java
    
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
    
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDResources.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDResources.java?rev=1234506&r1=1234505&r2=1234506&view=diff
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDResources.java 
(original)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDResources.java 
Sun Jan 22 13:13:39 2012
@@ -21,10 +21,11 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 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;
@@ -37,6 +38,7 @@ import org.apache.pdfbox.pdmodel.graphic
 import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject;
 import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
 import org.apache.pdfbox.pdmodel.markedcontent.PDPropertyList;
+import org.apache.pdfbox.util.MapUtil;
 
 /**
  * This represents a set of resources available at the page/pages/stream level.
@@ -47,6 +49,20 @@ import org.apache.pdfbox.pdmodel.markedc
 public class PDResources implements COSObjectable
 {
     private COSDictionary resources;
+    private Map<String,PDFont> fonts = null;
+    private Map<PDFont, String> fontMappings = null;
+    private Map<String,PDColorSpace> colorspaces = null;
+    private Map<String,PDXObject> xobjects = null;
+    private Map<PDXObject,String> xobjectMappings = null;
+    private HashMap<String,PDXObjectImage> images = null;
+    private Map<String,PDExtendedGraphicsState> graphicsStates = null;
+    private Map<String,PDPatternResources> patterns = null;
+    private Map<String,PDShadingResources> shadings = null;
+
+    /**
+     * Log instance.
+     */
+    private static final Log LOG = LogFactory.getLog(PDResources.class);
 
     /**
      * Default constructor.
@@ -87,84 +103,145 @@ public class PDResources implements COSO
     }
 
     /**
-     * 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.
+     * Calling this will release all cached information.
+     * 
      */
-    public Map<String,PDFont> getFonts( Map<String,PDFont> fontCache ) throws 
IOException
+    public void clear() 
     {
-        Map<String,PDFont> retval = null;
-        COSDictionary fonts = (COSDictionary)resources.getDictionaryObject( 
COSName.FONT );
-
-        if( fonts == null )
+        if (fonts != null)
         {
-            fonts = new COSDictionary();
-            resources.setItem( COSName.FONT, fonts );
+            fonts.clear();
         }
-
-        Map<String,PDFont> actuals = new HashMap<String,PDFont>();
-        retval = new COSDictionaryMap( actuals, fonts );
-        for( COSName fontName : fonts.keySet() )
+        if (colorspaces != null)
         {
-            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 ));
-            }
+            colorspaces.clear();
         }
-        return retval;
+        if (xobjects != null)
+        {
+            xobjects.clear();
+        }
+        if (images != null)
+        {
+            images.clear();
+        }
+        if (graphicsStates != null)
+        {
+            graphicsStates.clear();
+        }
+        if (patterns != null)
+        {
+            patterns.clear();
+        }
+        if (shadings != null)
+        {
+            shadings.clear();
+        }
+        resources = null;
     }
-
     /**
      * 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.
+     * 
+     * @deprecated due to some side effects font caching is no longer 
supported, use {@link #getFonts()} instead
      */
-    public Map<String,PDFont> getFonts() throws IOException
+    public Map<String,PDFont> getFonts( Map<String,PDFont> fontCache ) throws 
IOException
     {
-        return getFonts( null );
+        return getFonts();
     }
 
     /**
-     * This will get the map of PDXObjects that are in the resource dictionary.
-     *
-     * @return The map of xobjects.
+     * This will get the map of fonts. This will never return null.
      *
-     * @throws IOException If there is an error creating the xobjects.
+     * @return The map of fonts.
      */
-    public Map<String,PDXObject> getXObjects() throws IOException
+    public Map<String,PDFont> getFonts()
     {
-        Map<String,PDXObject> retval = null;
-        COSDictionary xobjects = (COSDictionary)resources.getDictionaryObject( 
COSName.XOBJECT );
-
-        if( xobjects == null )
+        if (fonts == null)
         {
-            xobjects = new COSDictionary();
-            resources.setItem( COSName.XOBJECT, xobjects );
+            // at least an empty map will be returned
+            // TODO we should return null instead of an empty map
+            fonts = new HashMap<String,PDFont>();
+            COSDictionary fontsDictionary = 
(COSDictionary)resources.getDictionaryObject( COSName.FONT );
+            if( fontsDictionary == null )
+            {
+                fontsDictionary = new COSDictionary();
+                resources.setItem( COSName.FONT, fontsDictionary );
+            }
+            else
+            {
+                for( COSName fontName : fontsDictionary.keySet() )
+                {
+                    COSBase font = fontsDictionary.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 )
+                    {
+                        PDFont newFont = null;
+                        try
+                        {
+                            newFont = PDFontFactory.createFont( 
(COSDictionary)font );
+                        }
+                        catch (IOException exception)
+                        {
+                            LOG.error("error while creating a font", 
exception);
+                        }
+                        if (newFont != null)
+                        {
+                            fonts.put( fontName.getName(), newFont);
+                        }
+                    }
+                }
+            }
         }
+        return fonts;
+    }
 
-        Map<String,PDXObject> actuals = new HashMap<String,PDXObject>();
-        retval = new COSDictionaryMap( actuals, xobjects );
-        for( COSName objName : xobjects.keySet() )
+    /**
+     * This will get the map of PDXObjects that are in the resource dictionary.
+     * This will never return null.
+     *
+     * @return The map of xobjects.
+     */
+    public Map<String,PDXObject> getXObjects()
+    {
+        if (xobjects == null)
         {
-            COSBase cosObject = xobjects.getDictionaryObject(objName);
-            PDXObject xobject = PDXObject.createXObject( cosObject );
-            if( xobject !=null )
+            // at least an empty map will be returned
+            // TODO we should return null instead of an empty map
+            xobjects = new HashMap<String,PDXObject>();
+            COSDictionary xobjectsDictionary = 
(COSDictionary)resources.getDictionaryObject( COSName.XOBJECT );
+            if( xobjectsDictionary == null )
+            {
+                xobjectsDictionary = new COSDictionary();
+                resources.setItem( COSName.XOBJECT, xobjectsDictionary );
+            }
+            else
             {
-                actuals.put( objName.getName(), xobject);
+                xobjects = new HashMap<String,PDXObject>();
+                for( COSName objName : xobjectsDictionary.keySet() )
+                {
+                    PDXObject xobject = null;
+                    try
+                    {
+                        xobject = PDXObject.createXObject( 
xobjectsDictionary.getDictionaryObject(objName) );
+                    }
+                    catch (IOException exception)
+                    {
+                        LOG.error("error while creating a xobject", exception);
+                    }
+                    if( xobject != null )
+                    {
+                        xobjects.put( objName.getName(), xobject);
+                    }
+                }
             }
         }
-        return retval;
+        return xobjects;
     }
 
     /**
@@ -179,42 +256,42 @@ public class PDResources implements COSO
      */
     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() )
+        if (images == null) 
         {
-            COSStream image = 
(COSStream)(images.getDictionaryObject(imageName));
-
-            COSName subType 
=(COSName)image.getDictionaryObject(COSName.SUBTYPE);
-            if( subType.equals(COSName.IMAGE) )
+            Map<String,PDXObject> allXObjects = getXObjects();
+            images = new HashMap<String,PDXObjectImage>();
+            for( String imageName : allXObjects.keySet() )
             {
-                PDXObjectImage ximage = 
(PDXObjectImage)PDXObject.createXObject( image );
-                if( ximage !=null )
+                PDXObject xobject = images.get(imageName);
+                if( xobject instanceof PDXObjectImage )
                 {
-                    actuals.put( imageName.getName(), ximage);
+                    images.put( imageName, (PDXObjectImage)xobject);
                 }
             }
         }
-        return retval;
+        return images;
     }
 
     /**
      * This will set the map of fonts.
      *
-     * @param fonts The new map of fonts.
+     * @param fontsValue The new map of fonts.
+     */
+    public void setFonts( Map<String,PDFont> fontsValue )
+    {
+        fonts = fontsValue;
+        resources.setItem( COSName.FONT, COSDictionaryMap.convert( fontsValue 
) );
+    }
+
+    /**
+     * This will set the map of xobjects.
+     *
+     * @param xobjectsValue The new map of xobjects.
      */
-    public void setFonts( Map<String,PDFont> fonts )
+    public void setXObjects( Map<String,PDXObject> xobjectsValue )
     {
-        resources.setItem( COSName.FONT, COSDictionaryMap.convert( fonts ) );
+        xobjects = xobjectsValue;
+        resources.setItem( COSName.XOBJECT, COSDictionaryMap.convert( 
xobjectsValue ) );
     }
 
     /**
@@ -223,35 +300,46 @@ public class PDResources implements COSO
      * 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
+    public Map<String,PDColorSpace> getColorSpaces()
     {
-        Map<String,PDColorSpace> retval = null;
-        COSDictionary colorspaces = 
(COSDictionary)resources.getDictionaryObject( COSName.COLORSPACE );
-
-        if( colorspaces != null )
+        if (colorspaces == null) 
         {
-            Map<String,PDColorSpace> actuals = new 
HashMap<String,PDColorSpace>();
-            retval = new COSDictionaryMap( actuals, colorspaces );
-            for( COSName csName : colorspaces.keySet() )
+            COSDictionary csDictionary = 
(COSDictionary)resources.getDictionaryObject( COSName.COLORSPACE );
+            if( csDictionary != null )
             {
-                COSBase cs = colorspaces.getDictionaryObject( csName );
-                actuals.put( csName.getName(), 
PDColorSpaceFactory.createColorSpace( cs ) );
+                colorspaces = new HashMap<String,PDColorSpace>();
+                for( COSName csName : csDictionary.keySet() )
+                {
+                    COSBase cs = csDictionary.getDictionaryObject( csName );
+                    PDColorSpace colorspace = null;
+                    try 
+                    {
+                        colorspace = PDColorSpaceFactory.createColorSpace( cs 
);
+                    }
+                    catch (IOException exception)
+                    {
+                        LOG.error("error while creating a colorspace", 
exception);
+                    }
+                    if (colorspace != null)
+                    {
+                        colorspaces.put( csName.getName(), colorspace );
+                    }
+                }
             }
         }
-        return retval;
+        return colorspaces;
     }
 
     /**
      * This will set the map of colorspaces.
      *
-     * @param colorspaces The new map of colorspaces.
+     * @param csValue The new map of colorspaces.
      */
-    public void setColorSpaces( Map<String,PDColorSpace> colorspaces )
+    public void setColorSpaces( Map<String,PDColorSpace> csValue )
     {
-        resources.setItem( COSName.COLORSPACE, COSDictionaryMap.convert( 
colorspaces ) );
+        colorspaces = csValue;
+        resources.setItem( COSName.COLORSPACE, COSDictionaryMap.convert( 
csValue ) );
     }
 
     /**
@@ -263,20 +351,20 @@ public class PDResources implements COSO
      */
     public Map<String,PDExtendedGraphicsState> getGraphicsStates()
     {
-        Map<String,PDExtendedGraphicsState> retval = null;
-        COSDictionary states = (COSDictionary)resources.getDictionaryObject( 
COSName.EXT_G_STATE );
-
-        if( states != null )
+        if (graphicsStates == null)
         {
-            Map<String,PDExtendedGraphicsState> actuals = new 
HashMap<String,PDExtendedGraphicsState>();
-            retval = new COSDictionaryMap( actuals, states );
-            for( COSName name : states.keySet() )
+            COSDictionary states = 
(COSDictionary)resources.getDictionaryObject( COSName.EXT_G_STATE );
+            if( states != null )
             {
-                COSDictionary dictionary = 
(COSDictionary)states.getDictionaryObject( name );
-                actuals.put( name.getName(), new PDExtendedGraphicsState( 
dictionary ) );
+                graphicsStates = new HashMap<String,PDExtendedGraphicsState>();
+                for( COSName name : states.keySet() )
+                {
+                    COSDictionary dictionary = 
(COSDictionary)states.getDictionaryObject( name );
+                    graphicsStates.put( name.getName(), new 
PDExtendedGraphicsState( dictionary ) );
+                }
             }
         }
-        return retval;
+        return graphicsStates;
     }
 
     /**
@@ -286,6 +374,7 @@ public class PDResources implements COSO
      */
     public void setGraphicsStates( Map<String,PDExtendedGraphicsState> states )
     {
+        graphicsStates = states;
         Iterator<String> iter = states.keySet().iterator();
         COSDictionary dic = new COSDictionary();
         while( iter.hasNext() )
@@ -335,35 +424,36 @@ public class PDResources implements COSO
      */
     public Map<String,PDPatternResources> getPatterns() throws IOException
     {
-        Map<String,PDPatternResources> retval = null;
-        COSDictionary patterns = (COSDictionary)resources.getDictionaryObject( 
COSName.PATTERN );
-
-        if( patterns != null )
+        if (patterns == null)
         {
-            Map<String,PDPatternResources> actuals = new 
HashMap<String,PDPatternResources>();
-            retval = new COSDictionaryMap( actuals, patterns );
-            for( COSName name : patterns.keySet() )
+            COSDictionary patternsDictionary = 
(COSDictionary)resources.getDictionaryObject( COSName.PATTERN );
+            if( patternsDictionary != null )
             {
-                COSDictionary dictionary = 
(COSDictionary)patterns.getDictionaryObject( name );
-                actuals.put( name.getName(), PDPatternResources.create( 
dictionary ) );
+                patterns = new HashMap<String,PDPatternResources>();
+                for( COSName name : patternsDictionary.keySet() )
+                {
+                    COSDictionary dictionary = 
(COSDictionary)patternsDictionary.getDictionaryObject( name );
+                    patterns.put( name.getName(), PDPatternResources.create( 
dictionary ) );
+                }
             }
         }
-        return retval;
+        return patterns;
     }
 
     /**
      * This will set the map of patterns.
      *
-     * @param patterns The new map of patterns.
+     * @param patternsValue The new map of patterns.
      */
-    public void setPatterns( Map<String,PDPatternResources> patterns )
+    public void setPatterns( Map<String,PDPatternResources> patternsValue )
     {
-        Iterator<String> iter = patterns.keySet().iterator();
+        patterns = patternsValue;
+        Iterator<String> iter = patternsValue.keySet().iterator();
         COSDictionary dic = new COSDictionary();
         while( iter.hasNext() )
         {
             String name = iter.next();
-            PDPatternResources pattern = patterns.get( name );
+            PDPatternResources pattern = patternsValue.get( name );
             dic.setItem( COSName.getPDFName( name ), pattern.getCOSObject() );
         }
         resources.setItem( COSName.PATTERN, dic );
@@ -380,37 +470,113 @@ public class PDResources implements COSO
      */
     public Map<String,PDShadingResources> getShadings() throws IOException
     {
-        Map<String,PDShadingResources> retval = null;
-        COSDictionary shadings = (COSDictionary)resources.getDictionaryObject( 
COSName.SHADING );
-
-        if( shadings != null )
+        if (shadings == null)
         {
-            Map<String,PDShadingResources> actuals = new 
HashMap<String,PDShadingResources>();
-            retval = new COSDictionaryMap( actuals, shadings );
-            for( COSName name : shadings.keySet() )
+            COSDictionary shadingsDictionary = 
(COSDictionary)resources.getDictionaryObject( COSName.SHADING );
+            if( shadingsDictionary != null )
             {
-                COSDictionary dictionary = 
(COSDictionary)shadings.getDictionaryObject( name );
-                actuals.put( name.getName(), PDShadingResources.create( 
dictionary ) );
+                shadings = new HashMap<String,PDShadingResources>();
+                for( COSName name : shadingsDictionary.keySet() )
+                {
+                    COSDictionary dictionary = 
(COSDictionary)shadingsDictionary.getDictionaryObject( name );
+                    shadings.put( name.getName(), PDShadingResources.create( 
dictionary ) );
+                }
             }
         }
-        return retval;
+        return shadings;
     }
 
     /**
      * This will set the map of shadings.
      *
-     * @param shadings The new map of shadings.
+     * @param shadingsValue The new map of shadings.
      */
-    public void setShadings( Map<String,PDShadingResources> shadings )
+    public void setShadings( Map<String,PDShadingResources> shadingsValue )
     {
-        Iterator<String> iter = shadings.keySet().iterator();
+        shadings = shadingsValue;
+        Iterator<String> iter = shadingsValue.keySet().iterator();
         COSDictionary dic = new COSDictionary();
         while( iter.hasNext() )
         {
             String name = iter.next();
-            PDShadingResources shading = shadings.get( name );
+            PDShadingResources shading = shadingsValue.get( name );
             dic.setItem( COSName.getPDFName( name ), shading.getCOSObject() );
         }
         resources.setItem( COSName.SHADING, dic );
     }
+
+    /**
+     * Adds the given font to the resources of the current the page.
+     * 
+     * @param font the font to be added
+     * @return the font name to be used within the content stream.
+     */
+    public String addFont(PDFont font) 
+    {
+        if (fonts == null) 
+        {
+            fonts = new HashMap<String,PDFont>();
+            fontMappings = reverseMap(fonts, PDFont.class);
+            setFonts(fonts);
+        }
+        String fontMapping = fontMappings.get( font );
+        if( fontMapping == null )
+        {
+            fontMapping = MapUtil.getNextUniqueKey( fonts, "F" );
+            fontMappings.put( font, fontMapping );
+            fonts.put( fontMapping, font );
+            addFontToDictionary(font, fontMapping);
+        }
+        return fontMapping;
+    }
+
+    private void addFontToDictionary(PDFont font, String fontName)
+    {
+        COSDictionary fontsDictionary = 
(COSDictionary)resources.getDictionaryObject(COSName.FONT);
+        fontsDictionary.setItem(fontName, font);
+    }
+    /**
+     * Adds the given XObject to the resources of the current the page.
+     * 
+     * @param xobject the XObject to be added
+     * @param prefix the prefix to be used for the name
+     * 
+     * @return the XObject name to be used within the content stream.
+     */
+    public String addXObject(PDXObject xobject, String prefix) 
+    {
+        if (xobjects == null) 
+        {
+            xobjects = new HashMap<String,PDXObject>();
+            xobjectMappings = reverseMap(xobjects, PDXObject.class);
+            setXObjects(xobjects);
+        }
+        String objMapping = xobjectMappings.get( xobject );
+        if( objMapping == null )
+        {
+            objMapping = MapUtil.getNextUniqueKey( xobjects, prefix );
+            xobjectMappings.put( xobject, objMapping );
+            xobjects.put( objMapping, xobject );
+            addXObjectToDictionary(xobject, objMapping);
+        }
+        return objMapping;
+    }
+
+    private void addXObjectToDictionary(PDXObject xobject, String xobjectName)
+    {
+        COSDictionary fontsDictionary = 
(COSDictionary)resources.getDictionaryObject(COSName.XOBJECT);
+        fontsDictionary.setItem(xobjectName, xobject);
+    }
+
+    private <T> Map<T, String> reverseMap(Map<String, T> map, Class<T> 
keyClass)
+    {
+        Map<T, String> reversed = new java.util.HashMap<T, String>();
+        for (Map.Entry<String, T> entry : map.entrySet())
+        {
+            reversed.put(keyClass.cast(entry.getValue()), 
(String)entry.getKey());
+        }
+        return reversed;
+    }
+
+
 }

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/edit/PDPageContentStream.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/edit/PDPageContentStream.java?rev=1234506&r1=1234505&r2=1234506&view=diff
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/edit/PDPageContentStream.java
 (original)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/edit/PDPageContentStream.java
 Sun Jan 22 13:13:39 2012
@@ -27,7 +27,6 @@ import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -51,11 +50,10 @@ import org.apache.pdfbox.pdmodel.graphic
 import org.apache.pdfbox.pdmodel.graphics.color.PDSeparation;
 import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject;
 import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
-import org.apache.pdfbox.util.MapUtil;
 
 
 /**
- * This class will is a convenience for creating page content streams.  You 
MUST
+ * This class is a convenience for creating page content streams.  You MUST
  * call close() when you are finished with this object.
  *
  * @author <a href="mailto:[email protected]";>Ben Litchfield</a>
@@ -71,11 +69,7 @@ public class PDPageContentStream
     private PDPage page;
     private OutputStream output;
     private boolean inTextMode = false;
-    private Map<PDFont,String> fontMappings;
-    private Map<PDXObject,String> xobjectMappings;
     private PDResources resources;
-    private Map<String,PDFont> fonts;
-    private Map<String,PDXObject> xobjects;
 
     private PDColorSpace currentStrokingColorSpace = new PDDeviceGray();
     private PDColorSpace currentNonStrokingColorSpace = new PDDeviceGray();
@@ -187,14 +181,6 @@ public class PDPageContentStream
             page.setResources( resources );
         }
 
-        //Fonts including reverse lookup
-        fonts = resources.getFonts();
-        fontMappings = reverseMap(fonts, PDFont.class);
-
-        //XObjects including reverse lookup
-        xobjects = resources.getXObjects();
-        xobjectMappings = reverseMap(xobjects, PDXObject.class);
-
         // Get the pdstream from the source page instead of creating a new one
         PDStream contents = sourcePage.getContents();
         boolean hasContent = contents != null;
@@ -278,17 +264,6 @@ public class PDPageContentStream
         formatDecimal.setGroupingUsed( false );
     }
 
-    private <T> Map<T, String> reverseMap(Map map, Class<T> keyClass)
-    {
-        Map<T, String> reversed = new java.util.HashMap<T, String>();
-        for (Object o : map.entrySet())
-        {
-            Map.Entry entry = (Map.Entry)o;
-            reversed.put(keyClass.cast(entry.getValue()), 
(String)entry.getKey());
-        }
-        return reversed;
-    }
-
     /**
      * Begin some text operations.
      *
@@ -330,13 +305,7 @@ public class PDPageContentStream
      */
     public void setFont( PDFont font, float fontSize ) throws IOException
     {
-        String fontMapping = fontMappings.get( font );
-        if( fontMapping == null )
-        {
-            fontMapping = MapUtil.getNextUniqueKey( fonts, "F" );
-            fontMappings.put( font, fontMapping );
-            fonts.put( fontMapping, font );
-        }
+        String fontMapping = resources.addFont(font);
         appendRawCommands( "/");
         appendRawCommands( fontMapping );
         appendRawCommands( SPACE );
@@ -395,14 +364,7 @@ public class PDPageContentStream
         {
             xObjectPrefix = "Form";
         }
-
-        String objMapping = xobjectMappings.get( xobject );
-        if( objMapping == null )
-        {
-            objMapping = MapUtil.getNextUniqueKey( xobjects, xObjectPrefix );
-            xobjectMappings.put( xobject, objMapping );
-            xobjects.put( objMapping, xobject );
-        }
+        String objMapping = resources.addXObject(xobject, xObjectPrefix);
         saveGraphicsState();
         appendRawCommands( SPACE );
         concatenate2CTM(transform);
@@ -1180,6 +1142,8 @@ public class PDPageContentStream
     /**
      * Fill the path.
      * 
+     * @param windingRule the winding rule to be used for filling 
+     * 
      * @throws IOException If there is an error while filling the path.
      */
     public void fill(int windingRule) throws IOException
@@ -1212,6 +1176,8 @@ public class PDPageContentStream
     /**
      * Clip path.
      * 
+     * @param windingRule the winding rule to be used for clipping
+     *  
      * @throws IOException If there is an error while clipping the path.
      */
     public void clipPath(int windingRule) throws IOException

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java?rev=1234506&r1=1234505&r2=1234506&view=diff
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
 (original)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFontFactory.java
 Sun Jan 22 13:13:39 2012
@@ -42,7 +42,7 @@ public class PDFontFactory
     /**
      * Logger instance.
      */
-    private static final Log log = LogFactory.getLog(PDFontFactory.class);
+    private static final Log LOG = LogFactory.getLog(PDFontFactory.class);
     
     /**
      * This will create the correct font based on information in the 
dictionary.
@@ -54,33 +54,13 @@ public class PDFontFactory
      * @return The corrent implementation for the font.
      *
      * @throws IOException If the dictionary is not valid.
+     * 
+     * @deprecated due to some side effects font caching is no longer 
supported, 
+     * use {@link #createFont(COSDictionary)} instead
      */
     public static PDFont createFont(COSDictionary dic, Map fontCache) throws 
IOException
     {
-        PDFont retval = null;
-        if (fontCache != null) 
-        {
-            String fontKey = dic.getNameAsString(COSName.BASE_FONT) + 
dic.getNameAsString(COSName.NAME)
-                                + dic.getNameAsString(COSName.SUBTYPE);
-            if (dic.getItem(COSName.ENCODING) != null)
-            {
-                fontKey += dic.getItem(COSName.ENCODING).toString();
-            }
-            if (fontCache.containsKey(fontKey))
-            {
-                retval = (PDFont)fontCache.get(fontKey);
-            }
-            else 
-            {
-                retval = PDFontFactory.createFont( dic );
-                fontCache.put(fontKey, retval);
-            }
-        }
-        else
-        {
-            retval = PDFontFactory.createFont( dic );
-        }
-        return retval;
+        return createFont(dic);
     }
 
     /**
@@ -133,8 +113,8 @@ public class PDFontFactory
         }
         else
         {
-            log.warn("Substituting TrueType for unknown font subtype=" + 
dic.getDictionaryObject( COSName.SUBTYPE ).toString());
-            //throw new IOException( "Unknown font subtype=" + subType );
+            LOG.warn("Substituting TrueType for unknown font subtype=" + 
+                    dic.getDictionaryObject( COSName.SUBTYPE ).toString());
             retval = new PDTrueTypeFont( dic );
         }
         return retval;

Modified: 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java
URL: 
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java?rev=1234506&r1=1234505&r2=1234506&view=diff
==============================================================================
--- 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java 
(original)
+++ 
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java 
Sun Jan 22 13:13:39 2012
@@ -66,7 +66,7 @@ public class PDFStreamEngine
     /**
      * Log instance.
      */
-    private static final Log log = LogFactory.getLog(PDFStreamEngine.class);
+    private static final Log LOG = LogFactory.getLog(PDFStreamEngine.class);
 
     /**
      * The PDF operators that are ignored by this engine.
@@ -83,12 +83,10 @@ public class PDFStreamEngine
 
     private Map<String,OperatorProcessor> operators = new 
HashMap<String,OperatorProcessor>();
 
-    private Stack<StreamResources> streamResourcesStack = new 
Stack<StreamResources>();
+    private Stack<PDResources> streamResourcesStack = new Stack<PDResources>();
 
     private PDPage page;
 
-    private Map<String,PDFont> documentFontCache = new 
HashMap<String,PDFont>();
-    
     private int validCharCnt;
     private int totalCharCnt;
 
@@ -98,22 +96,6 @@ public class PDFStreamEngine
     private boolean forceParsing = false;
 
     /**
-     * This is a simple internal class used by the Stream engine to handle the
-     * resources stack.
-     */
-    private static class StreamResources
-    {
-        private Map<String,PDFont> fonts;
-        private Map<String,PDColorSpace> colorSpaces;
-        private Map<String,PDXObject> xobjects;
-        private Map<String,PDExtendedGraphicsState> graphicsStates;
-        private PDResources resources;
-        
-        private StreamResources()
-        {};
-    }
-
-    /**
      * Constructor.
      */
     public PDFStreamEngine()
@@ -170,12 +152,24 @@ public class PDFStreamEngine
         totalCharCnt = 0;
     }
 
-    public boolean isForceParsing() {
+    /**
+     * Indicates if force parsing is activated.
+     * 
+     * @return true if force parsing is active
+     */
+    public boolean isForceParsing() 
+    {
         return forceParsing;
     }
 
-    public void setForceParsing(boolean forceParsing) {
-        this.forceParsing = forceParsing;
+    /**
+     * Enable/Disable force parsing.
+     * 
+     * @param forceParsingValue true activates force parsing
+     */
+    public void setForceParsing(boolean forceParsingValue) 
+    {
+        forceParsing = forceParsingValue;
     }
 
     /**
@@ -199,7 +193,6 @@ public class PDFStreamEngine
      */
     public void resetEngine()
     {
-        documentFontCache.clear();
         validCharCnt = 0;
         totalCharCnt = 0;
     }
@@ -221,7 +214,6 @@ public class PDFStreamEngine
         textLineMatrix = null;
         graphicsStack.clear();
         streamResourcesStack.clear();
-
         processSubStream( aPage, resources, cosStream );
     }
 
@@ -234,50 +226,58 @@ public class PDFStreamEngine
      *
      * @throws IOException If there is an exception while processing the 
stream.
      */
-    public void processSubStream(
-            PDPage aPage, PDResources resources, COSStream cosStream)
-            throws IOException {
+    public void processSubStream(PDPage aPage, PDResources resources, 
COSStream cosStream) throws IOException 
+    {
         page = aPage;
-        if (resources != null) {
-            StreamResources sr = new StreamResources();
-            sr.fonts = resources.getFonts( documentFontCache );
-            sr.colorSpaces = resources.getColorSpaces();
-            sr.xobjects = resources.getXObjects();
-            sr.graphicsStates = resources.getGraphicsStates();
-            sr.resources = resources;
-
-            streamResourcesStack.push(sr);
-            try {
+        if (resources != null)
+        {
+            streamResourcesStack.push(resources);
+            try
+            {
                 processSubStream(cosStream);
-            } finally {
-                streamResourcesStack.pop();
             }
-        } else {
+            finally
+            {
+                streamResourcesStack.pop().clear();
+            }
+        }
+        else
+        {
             processSubStream(cosStream);
         }
     }
 
-    private void processSubStream(COSStream cosStream) throws IOException {
+    private void processSubStream(COSStream cosStream) throws IOException 
+    {
         List<COSBase> arguments = new ArrayList<COSBase>();
         PDFStreamParser parser = new PDFStreamParser(cosStream, forceParsing);
-        try {
+        try 
+        {
             Iterator<Object> iter = parser.getTokenIterator();
-
-            while (iter.hasNext()) {
+            while (iter.hasNext()) 
+            {
                 Object next = iter.next();
-                if (log.isDebugEnabled()) {
-                    log.debug("processing substream token: " + next);
+                if (LOG.isDebugEnabled()) 
+                {
+                    LOG.debug("processing substream token: " + next);
                 }
-                if (next instanceof COSObject) {
+                if (next instanceof COSObject) 
+                {
                     arguments.add(((COSObject) next).getObject());
-                } else if (next instanceof PDFOperator) {
+                }
+                else if (next instanceof PDFOperator) 
+                {
                     processOperator((PDFOperator) next, arguments);
                     arguments = new ArrayList<COSBase>();
-                } else {
+                }
+                else
+                {
                     arguments.add((COSBase) next);
                 }
             }
-        } finally {
+        }
+        finally
+        {
             parser.close();
         }
     }
@@ -358,7 +358,7 @@ public class PDFStreamEngine
         }
         catch (Throwable exception)
         {
-            log.warn( exception, exception);
+            LOG.warn( exception, exception);
         }
         
         if( spaceWidthText == 0 )
@@ -400,7 +400,8 @@ public class PDFStreamEngine
             }
 
             // the space width has to be transformed into display units
-            float spaceWidthDisp = spaceWidthText * fontSizeText * 
horizontalScalingText * textMatrix.getValue(0, 0) * ctm.getValue(0, 0);
+            float spaceWidthDisp = spaceWidthText * fontSizeText * 
horizontalScalingText 
+                                    * textMatrix.getValue(0, 0) * 
ctm.getValue(0, 0);
 
             //todo, handle horizontal displacement
             // get the width and height of this character in text units 
@@ -464,7 +465,8 @@ public class PDFStreamEngine
             final float endYPosition = textMatrixEnd.getYPosition();
 
             // add some spacing to the text matrix (see comment above)
-            tx = 
((characterHorizontalDisplacementText)*fontSizeText+characterSpacingText+spacingText)*horizontalScalingText;
+            tx = 
((characterHorizontalDisplacementText)*fontSizeText+characterSpacingText+spacingText)
+                    *horizontalScalingText;
             td.setValue( 2, 0, tx );
             textMatrix = td.multiply(textMatrix, textMatrix );
             
@@ -527,7 +529,7 @@ public class PDFStreamEngine
         }
         catch (IOException e)
         {
-            log.warn(e, e);
+            LOG.warn(e, e);
         }
     }
 
@@ -554,14 +556,14 @@ public class PDFStreamEngine
             {
                 if (!unsupportedOperators.contains(operation)) 
                 {
-                    log.info("unsupported/disabled operation: " + operation);
+                    LOG.info("unsupported/disabled operation: " + operation);
                     unsupportedOperators.add(operation);
                 }
             }
         }
         catch (Exception e)
         {
-            log.warn(e, e);
+            LOG.warn(e, e);
         }
     }
 
@@ -570,7 +572,7 @@ public class PDFStreamEngine
      */
     public Map<String,PDColorSpace> getColorSpaces()
     {
-        return streamResourcesStack.peek().colorSpaces;
+        return streamResourcesStack.peek().getColorSpaces();
     }
 
     /**
@@ -578,7 +580,7 @@ public class PDFStreamEngine
      */
     public Map<String,PDXObject> getXObjects()
     {
-        return streamResourcesStack.peek().xobjects;
+        return streamResourcesStack.peek().getXObjects();
     }
 
     /**
@@ -586,21 +588,21 @@ public class PDFStreamEngine
      */
     public void setColorSpaces(Map<String,PDColorSpace> value)
     {
-        streamResourcesStack.peek().colorSpaces = value;
+        streamResourcesStack.peek().setColorSpaces(value);
     }
     /**
      * @return Returns the fonts.
      */
     public Map<String,PDFont> getFonts()
     {
-        return streamResourcesStack.peek().fonts;
+        return streamResourcesStack.peek().getFonts();
     }
     /**
      * @param value The fonts to set.
      */
     public void setFonts(Map<String,PDFont> value)
     {
-        streamResourcesStack.peek().fonts = value;
+        streamResourcesStack.peek().setFonts(value);
     }
     /**
      * @return Returns the graphicsStack.
@@ -635,14 +637,14 @@ public class PDFStreamEngine
      */
     public Map<String,PDExtendedGraphicsState> getGraphicsStates()
     {
-        return streamResourcesStack.peek().graphicsStates;
+        return streamResourcesStack.peek().getGraphicsStates();
     }
     /**
      * @param value The graphicsStates to set.
      */
     public void setGraphicsStates(Map<String,PDExtendedGraphicsState> value)
     {
-        ((StreamResources) streamResourcesStack.peek()).graphicsStates = value;
+        streamResourcesStack.peek().setGraphicsStates(value);
     }
     /**
      * @return Returns the textLineMatrix.
@@ -677,7 +679,7 @@ public class PDFStreamEngine
      */
     public PDResources getResources()
     {
-        return streamResourcesStack.peek().resources;
+        return streamResourcesStack.peek();
     }
 
     /**


Reply via email to