You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/10/27 23:06:42 UTC

svn commit: r1634701 - in /pdfbox/trunk: pdfbox/src/main/java/org/apache/pdfbox/pdmodel/ pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/ pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/ pdfbox/src/main/java/org/ap...

Author: jahewson
Date: Mon Oct 27 22:06:41 2014
New Revision: 1634701

URL: http://svn.apache.org/r1634701
Log:
PDFBOX-2423: Refactor PDAppearanceDictionary entries

Added:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceEntry.java
Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
    pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestFDF.java
    pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/annotation/AnnotationValidator.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java Mon Oct 27 22:06:41 2014
@@ -281,7 +281,7 @@ public class PDDocument implements Close
             cosObject.setItem(COSName.BBOX, new PDRectangle());
 
             ap.setNormalAppearance(aps);
-            ap.getDictionary().setDirect(true);
+            ap.getCOSObject().setDirect(true);
             signatureField.getWidget().setAppearance(ap);
         }
         else
@@ -327,7 +327,7 @@ public class PDDocument implements Close
                         // Appearance Dictionary auslesen und setzen
                         PDAppearanceDictionary ap = new PDAppearanceDictionary(
                                 (COSDictionary) cosBaseDict.getItem(COSName.AP));
-                        ap.getDictionary().setDirect(true);
+                        ap.getCOSObject().setDirect(true);
                         signatureField.getWidget().setAppearance(ap);
 
                         // AcroForm DefaultRessource auslesen und setzen

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java Mon Oct 27 22:06:41 2014
@@ -31,10 +31,9 @@ import org.apache.pdfbox.pdmodel.common.
 import org.apache.pdfbox.pdmodel.graphics.color.PDGamma;
 
 /**
- * This class represents a PDF annotation.
- * 
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
+ * A PDF annotation.
  * 
+ * @author Ben Litchfield
  */
 public abstract class PDAnnotation implements COSObjectable
 {
@@ -265,27 +264,25 @@ public abstract class PDAnnotation imple
     }
 
     /**
-     * This will get the name of the current appearance stream if any.
-     * 
-     * @return The name of the appearance stream.
+     * Returns the annotations appearance state, which selects the applicable appearance stream
+     * from an appearance subdictionary.
      */
-    public String getAppearanceStream()
+    public COSName getAppearanceState()
     {
-        String retval = null;
         COSName name = (COSName) getDictionary().getDictionaryObject(COSName.AS);
         if (name != null)
         {
-            retval = name.getName();
+            return name;
         }
-        return retval;
+        return null;
     }
 
     /**
-     * This will set the annotations appearance stream name.
+     * This will set the annotations appearance state name.
      * 
      * @param as The name of the appearance stream.
      */
-    public void setAppearanceStream(String as)
+    public void setAppearanceState(String as)
     {
         if (as == null)
         {
@@ -323,12 +320,41 @@ public abstract class PDAnnotation imple
         COSDictionary ap = null;
         if (appearance != null)
         {
-            ap = appearance.getDictionary();
+            ap = appearance.getCOSObject();
         }
         dictionary.setItem(COSName.AP, ap);
     }
 
     /**
+     * Returns the appearance stream for this annotation, if any. The annotation state is taken
+     * into account, if present.
+     */
+    public PDAppearanceStream getNormalAppearanceStream()
+    {
+        PDAppearanceDictionary appearanceDict = getAppearance();
+        if (appearanceDict == null)
+        {
+            return null;
+        }
+
+        PDAppearanceEntry normalAppearance = appearanceDict.getNormalAppearance();
+        if (normalAppearance == null)
+        {
+            return null;
+        }
+
+        if (normalAppearance.isSubDictionary())
+        {
+            COSName state = getAppearanceState();
+            return normalAppearance.getSubDictionary().get(state);
+        }
+        else
+        {
+            return normalAppearance.getAppearanceStream();
+        }
+    }
+
+    /**
      * Get the invisible flag.
      * 
      * @return The invisible flag.

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java Mon Oct 27 22:06:41 2014
@@ -230,7 +230,7 @@ public class PDAnnotationWidget extends 
     // TODO where to get acroForm from?
 //    public PDField getParent() throws IOException
 //    {
-//        COSBase parent = this.getDictionary().getDictionaryObject(COSName.PARENT);
+//        COSBase parent = this.getCOSObject().getDictionaryObject(COSName.PARENT);
 //        if (parent instanceof COSDictionary)
 //        {
 //            PDAcroForm acroForm = null;

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java Mon Oct 27 22:06:41 2014
@@ -16,37 +16,23 @@
  */
 package org.apache.pdfbox.pdmodel.interactive.annotation;
 
-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.COSObjectable;
-import org.apache.pdfbox.pdmodel.common.COSDictionaryMap;
-
-import java.util.HashMap;
-import java.util.Map;
 
 /**
- * This class represents a PDF /AP entry the appearance dictionary.
+ * An appearance dictionary specifying how the annotation shall be presented visually on the page.
  *
- * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.4 $
+ * @author Ben Litchfield
  */
 public class PDAppearanceDictionary implements COSObjectable
 {
+    private final COSDictionary dictionary;
 
     /**
-     * Log instance.
-     */
-    private static final Log LOG = LogFactory.getLog(PDAppearanceDictionary.class);
-
-    private COSDictionary dictionary;
-
-    /**
-     * Constructor.
+     * Constructor for embedding.
      */
     public PDAppearanceDictionary()
     {
@@ -56,7 +42,7 @@ public class PDAppearanceDictionary impl
     }
 
     /**
-     * Constructor.
+     * Constructor for reading.
      *
      * @param dict The annotations dictionary.
      */
@@ -65,20 +51,8 @@ public class PDAppearanceDictionary impl
         dictionary = dict;
     }
 
-    /**
-     * returns the dictionary.
-     * @return the dictionary
-     */
-    public COSDictionary getDictionary()
-    {
-        return dictionary;
-    }
-
-    /**
-     * returns the dictionary.
-     * @return the dictionary
-     */
-    public COSBase getCOSObject()
+    @Override
+    public COSDictionary getCOSObject()
     {
         return dictionary;
     }
@@ -90,38 +64,17 @@ public class PDAppearanceDictionary impl
      *
      * @return A list of key(java.lang.String) value(PDAppearanceStream) pairs
      */
-    public Map<String,PDAppearanceStream> getNormalAppearance()
+    public PDAppearanceEntry getNormalAppearance()
     {
-        COSBase ap = dictionary.getDictionaryObject( COSName.N );
-        if ( ap == null )
+        COSBase entry = dictionary.getDictionaryObject( COSName.N );
+        if ( entry == null )
         { 
             return null; 
         }
-        else if( ap instanceof COSStream )
-        {
-            COSStream aux = (COSStream) ap;
-            ap = new COSDictionary();
-            ((COSDictionary)ap).setItem(COSName.DEFAULT, aux );
-        }
-        COSDictionary map = (COSDictionary)ap;
-        Map<String, PDAppearanceStream> actuals = new HashMap<String, PDAppearanceStream>();
-        Map<String, PDAppearanceStream> retval = new COSDictionaryMap<String, PDAppearanceStream>( actuals, map );
-        for( COSName asName : map.keySet() )
+        else
         {
-            COSBase stream = map.getDictionaryObject( asName );
-            // PDFBOX-1599: this is just a workaround. The given PDF provides "null" as stream 
-            // which leads to a COSName("null") value and finally to a ClassCastExcpetion
-            if (stream instanceof COSStream)
-            {
-                COSStream as = (COSStream)stream;
-                actuals.put( asName.getName(), new PDAppearanceStream( as ) );
-            }
-            else
-            {
-                LOG.debug("non-conformance workaround: ignore null value for appearance stream.");
-            }
+            return new PDAppearanceEntry(entry);
         }
-        return retval;
     }
 
     /**
@@ -129,11 +82,11 @@ public class PDAppearanceDictionary impl
      * appearance then you should use the key "default", and when the PDF is written
      * back to the filesystem then there will only be one stream.
      *
-     * @param appearanceMap The updated map with the appearance.
+     * @param entry appearance stream or subdictionary
      */
-    public void setNormalAppearance( Map<String,PDAppearanceStream> appearanceMap )
+    public void setNormalAppearance( PDAppearanceEntry entry )
     {
-        dictionary.setItem( COSName.N, COSDictionaryMap.convert( appearanceMap ) );
+        dictionary.setItem( COSName.N, entry );
     }
 
     /**
@@ -155,42 +108,17 @@ public class PDAppearanceDictionary impl
      *
      * @return A list of key(java.lang.String) value(PDAppearanceStream) pairs
      */
-    public Map<String,PDAppearanceStream> getRolloverAppearance()
+    public PDAppearanceEntry getRolloverAppearance()
     {
-        Map<String,PDAppearanceStream> retval = null;
-        COSBase ap = dictionary.getDictionaryObject( COSName.R );
-        if( ap == null )
+        COSBase entry = dictionary.getDictionaryObject( COSName.R );
+        if( entry == null )
         {
-            retval = getNormalAppearance();
+            return getNormalAppearance();
         }
         else
         {
-            if( ap instanceof COSStream )
-            {
-                COSStream aux = (COSStream) ap;
-                ap = new COSDictionary();
-                ((COSDictionary)ap).setItem(COSName.DEFAULT, aux );
-            }
-            COSDictionary map = (COSDictionary)ap;
-            Map<String, PDAppearanceStream> actuals = new HashMap<String, PDAppearanceStream>();
-            retval = new COSDictionaryMap<String, PDAppearanceStream>( actuals, map );
-            for( COSName asName : map.keySet() )
-            {
-                COSBase stream = map.getDictionaryObject( asName );
-                // PDFBOX-1599: this is just a workaround. The given PDF provides "null" as stream 
-                // which leads to a COSName("null") value and finally to a ClassCastExcpetion
-                if (stream instanceof COSStream)
-                {
-                    COSStream as = (COSStream)stream;
-                    actuals.put( asName.getName(), new PDAppearanceStream( as ) );
-                }
-                else
-                {
-                    LOG.debug("non-conformance workaround: ignore null value for appearance stream.");
-                }
-            }
+            return new PDAppearanceEntry(entry);
         }
-        return retval;
     }
 
     /**
@@ -198,11 +126,11 @@ public class PDAppearanceDictionary impl
      * appearance then you should use the key "default", and when the PDF is written
      * back to the filesystem then there will only be one stream.
      *
-     * @param appearanceMap The updated map with the appearance.
+     * @param entry appearance stream or subdictionary
      */
-    public void setRolloverAppearance( Map<String,PDAppearanceStream> appearanceMap )
+    public void setRolloverAppearance( PDAppearanceEntry entry )
     {
-        dictionary.setItem( COSName.R, COSDictionaryMap.convert( appearanceMap ) );
+        dictionary.setItem( COSName.R, entry );
     }
 
     /**
@@ -224,43 +152,17 @@ public class PDAppearanceDictionary impl
      *
      * @return A list of key(java.lang.String) value(PDAppearanceStream) pairs
      */
-    public Map<String,PDAppearanceStream> getDownAppearance()
+    public PDAppearanceEntry getDownAppearance()
     {
-        Map<String,PDAppearanceStream> retval = null;
-        COSBase ap = dictionary.getDictionaryObject( COSName.D );
-        if( ap == null )
+        COSBase entry = dictionary.getDictionaryObject( COSName.D );
+        if( entry == null )
         {
-            retval = getNormalAppearance();
+            return getNormalAppearance();
         }
         else
         {
-            if( ap instanceof COSStream )
-            {
-                COSStream aux = (COSStream) ap;
-                ap = new COSDictionary();
-                ((COSDictionary)ap).setItem(COSName.DEFAULT, aux );
-            }
-            COSDictionary map = (COSDictionary)ap;
-            Map<String, PDAppearanceStream> actuals =
-                new HashMap<String, PDAppearanceStream>();
-            retval = new COSDictionaryMap<String, PDAppearanceStream>( actuals, map );
-            for( COSName asName : map.keySet() )
-            {
-                COSBase stream = map.getDictionaryObject( asName );
-                // PDFBOX-1599: this is just a workaround. The given PDF provides "null" as stream 
-                // which leads to a COSName("null") value and finally to a ClassCastExcpetion
-                if (stream instanceof COSStream)
-                {
-                    COSStream as = (COSStream)stream;
-                    actuals.put( asName.getName(), new PDAppearanceStream( as ) );
-                }
-                else
-                {
-                    LOG.debug("non-conformance workaround: ignore null value for appearance stream.");
-                }
-            }
+            return new PDAppearanceEntry(entry);
         }
-        return retval;
     }
 
     /**
@@ -268,11 +170,11 @@ public class PDAppearanceDictionary impl
      * appearance then you should use the key "default", and when the PDF is written
      * back to the filesystem then there will only be one stream.
      *
-     * @param appearanceMap The updated map with the appearance.
+     * @param entry appearance stream or subdictionary
      */
-    public void setDownAppearance( Map<String,PDAppearanceStream> appearanceMap )
+    public void setDownAppearance( PDAppearanceEntry entry )
     {
-        dictionary.setItem( COSName.D, COSDictionaryMap.convert( appearanceMap ) );
+        dictionary.setItem( COSName.D, entry );
     }
     
     /**
@@ -285,5 +187,4 @@ public class PDAppearanceDictionary impl
     {
         dictionary.setItem( COSName.D, ap.getStream() );
     }
-
 }

Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceEntry.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceEntry.java?rev=1634701&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceEntry.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/PDAppearanceEntry.java Mon Oct 27 22:06:41 2014
@@ -0,0 +1,116 @@
+/*
+ * 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.interactive.annotation;
+
+import java.util.HashMap;
+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;
+
+/**
+ * An entry in an appearance dictionary. May contain either a single appearance stream or an
+ * appearance subdictionary.
+ *
+ * @author John Hewson
+ */
+public class PDAppearanceEntry implements COSObjectable
+{
+    private COSBase entry;
+
+    private PDAppearanceEntry()
+    {
+    }
+
+    /**
+     * Constructor for reading.
+     * @param entry
+     */
+    public PDAppearanceEntry(COSBase entry)
+    {
+        this.entry = entry;
+    }
+
+    @Override
+    public COSBase getCOSObject()
+    {
+        return entry;
+    }
+
+    /**
+     * Returns true if this entry is an appearance subdictionary.
+     */
+    public boolean isSubDictionary()
+    {
+        return !(this.entry instanceof COSStream);
+    }
+
+    /**
+     * Returns true if this entry is an appearance stream.
+     */
+    public boolean isStream()
+    {
+        return this.entry instanceof COSStream;
+    }
+
+    /**
+     * Returns the entry as an appearance stream.
+     *
+     * @throws IllegalStateException if this entry is not an appearance stream
+     */
+    public PDAppearanceStream getAppearanceStream()
+    {
+        if (!isStream())
+        {
+            throw new IllegalStateException();
+        }
+        return new PDAppearanceStream((COSStream)entry);
+    }
+
+    /**
+     * Returns the entry as an appearance subdictionary.
+     *
+     * @throws IllegalStateException if this entry is not an appearance subdictionary
+     */
+    public Map<COSName, PDAppearanceStream> getSubDictionary()
+    {
+        if (!isSubDictionary())
+        {
+            throw new IllegalStateException();
+        }
+
+        COSDictionary dict = (COSDictionary)entry;
+        Map<COSName, PDAppearanceStream> map = new HashMap<COSName, PDAppearanceStream>();
+
+        for (COSName name : dict.keySet())
+        {
+            COSBase value = dict.getDictionaryObject(name);
+
+            // the file from PDFBOX-1599 contains /null as its entry, so we skip non-stream entries
+            if(value instanceof COSStream)
+            {
+                map.put(name, new PDAppearanceStream((COSStream)value));
+            }
+        }
+
+        return new COSDictionaryMap<COSName, PDAppearanceStream>( map, dict );
+    }
+}

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java Mon Oct 27 22:06:41 2014
@@ -24,7 +24,6 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -44,6 +43,7 @@ import org.apache.pdfbox.pdmodel.font.PD
 import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
 import org.apache.pdfbox.pdmodel.interactive.action.PDFormFieldAdditionalActions;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceEntry;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
 import org.apache.pdfbox.contentstream.operator.Operator;
@@ -228,7 +228,6 @@ public final class PDAppearanceString
             }
             else
             {
-
                 PDAppearanceDictionary appearance = widget.getAppearance();
                 if (appearance == null)
                 {
@@ -236,8 +235,8 @@ public final class PDAppearanceString
                     widget.setAppearance(appearance);
                 }
 
-                Map<String, PDAppearanceStream> normalAppearance = appearance.getNormalAppearance();
-                PDAppearanceStream appearanceStream = normalAppearance.get("default");
+                PDAppearanceEntry normalAppearance = appearance.getNormalAppearance();
+                PDAppearanceStream appearanceStream = normalAppearance.getAppearanceStream();
                 if (appearanceStream == null)
                 {
                     COSStream cosStream = acroForm.getDocument().getDocument().createCOSStream();

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java Mon Oct 27 22:06:41 2014
@@ -45,6 +45,7 @@ import org.apache.pdfbox.pdmodel.font.PD
 import org.apache.pdfbox.pdmodel.font.PDType3CharProc;
 import org.apache.pdfbox.pdmodel.graphics.image.PDImage;
 import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceEntry;
 import org.apache.pdfbox.rendering.font.CIDType0Glyph2D;
 import org.apache.pdfbox.rendering.font.Glyph2D;
 import org.apache.pdfbox.rendering.font.TTFGlyph2D;
@@ -155,103 +156,95 @@ public class PageDrawer extends PDFGraph
         // TODO use getStroke() to set the initial stroke
         graphics.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
 
-        PDPage page = getPage();
-        processPage(page);
+        processPage(getPage());
+        showAnnotations();
 
-        for (PDAnnotation annotation : page.getAnnotations())
+        graphics = null;
+    }
+
+    private void showAnnotations() throws IOException
+    {
+        for (PDAnnotation annotation : getPage().getAnnotations())
         {
-            PDRectangle rect = annotation.getRectangle();
-            String appearanceName = annotation.getAppearanceStream();
-            PDAppearanceDictionary appearDictionary = annotation.getAppearance();
-            if (appearDictionary != null)
+            PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();
+            if (appearanceStream != null)
             {
-                if (appearanceName == null)
+                saveGraphicsState();
+
+                PDRectangle rect = annotation.getRectangle();
+                Rectangle2D rect2D = new Rectangle2D.Float(
+                        rect.getLowerLeftX(),
+                        rect.getLowerLeftY(),
+                        rect.getWidth(),
+                        rect.getHeight());
+
+                Matrix matrix = appearanceStream.getMatrix();
+                if (matrix == null)
                 {
-                    appearanceName = "default";
+                    matrix = new Matrix();
                 }
-                Map<String, PDAppearanceStream> appearanceMap = appearDictionary.getNormalAppearance();
-                if (appearanceMap != null)
-                {
-                    PDAppearanceStream appearance = appearanceMap.get(appearanceName);
-                    if (appearance != null)
-                    {
-                        saveGraphicsState();
 
-                        PDRectangle bBox = appearance.getBBox();
-                        
-                        Rectangle2D rect2D = new Rectangle2D.Float(
-                                rect.getLowerLeftX(), 
-                                rect.getLowerLeftY(), 
-                                rect.getWidth(), 
-                                rect.getHeight());
-                        Matrix matrix = appearance.getMatrix();
-                        if (matrix == null)
-                        {
-                            matrix = new Matrix();
-                        }
-                        
-                        // PDF Spec 12.5.5:
-                        // a) The appearance's bounding box (specified by its BBox entry) 
-                        // shall be transformed, using Matrix, to produce a quadrilateral 
-                        // with arbitrary orientation.
-                        Point2D p1 = new Point2D.Float(bBox.getLowerLeftX(), bBox.getLowerLeftY());
-                        Point2D p2 = new Point2D.Float(bBox.getUpperRightX(), bBox.getUpperRightY());
-                        matrix.createAffineTransform().transform(p1, p1);
-                        matrix.createAffineTransform().transform(p2, p2);
-                        Rectangle2D transformedBBox = new Rectangle2D.Float(
-                                (float) Math.min(p1.getX(), p2.getX()),
-                                (float) Math.min(p1.getY(), p2.getY()),
-                                (float) Math.abs(p2.getX() - p1.getX()),
-                                (float) Math.abs(p2.getY() - p1.getY()));
-
-                        // PDF Spec 12.5.5:
-                        // b) A matrix A shall be computed that scales and translates 
-                        // the transformed appearance box to align with the edges
-                        // of the annotation's rectangle
-                        //
-                        // code inspired from
-                        // http://stackoverflow.com/a/14015713/535646
-                        AffineTransform at = new AffineTransform();
-                        at.translate(rect2D.getMinX(), rect2D.getMinY());
-                        at.scale(rect2D.getWidth() / transformedBBox.getWidth(), rect2D.getHeight() / transformedBBox.getHeight());
-                        at.translate(-transformedBBox.getMinX(), -transformedBBox.getMinY());
-                        Matrix matrixA = new Matrix();
-                        matrixA.setFromAffineTransform(at);
-                        
-                        // PDF Spec 12.5.5:
-                        // c) Matrix shall be concatenated with A to form a matrix AA 
-                        // that maps from the appearance's coordinate system to 
-                        // the annotation's rectangle in default user space
-                        Matrix matrixAA = matrix.multiply(matrixA);
-                        
-                        Point2D point = new Point2D.Float(matrixAA.getXPosition(), matrixAA.getYPosition());
-                        matrixAA.setValue(2, 0, 0);
-                        matrixAA.setValue(2, 1, 0);
-                        
-                        getGraphicsState().setCurrentTransformationMatrix(matrixAA);
-
-                        // Calculate clipping
-                        // PDF Spec 12.5.5:
-                        // a self-contained content stream that shall be rendered 
-                        // inside the annotation rectangle
-                        Rectangle2D clipRect2D = new Rectangle2D.Float(
-                                (float) (rect2D.getMinX()-point.getX()),
-                                (float) (rect2D.getMinY()-point.getY()),
-                                (float) rect2D.getWidth(),
-                                (float) rect2D.getHeight());
-                        getGraphicsState().intersectClippingPath(new Area(clipRect2D));
-
-                        graphics.translate((int) point.getX(), (int) point.getY());
-                        lastClip = null;
-                        processChildStream(appearance);
-                        graphics.translate(-(int) point.getX(), -(int) point.getY());
-                       
-                        restoreGraphicsState();
-                    }
-                }
+                // PDF Spec 12.5.5:
+                // a) The appearance's bounding box (specified by its BBox entry)
+                // shall be transformed, using Matrix, to produce a quadrilateral
+                // with arbitrary orientation.
+                PDRectangle bBox = appearanceStream.getBBox();
+                Point2D p1 = new Point2D.Float(bBox.getLowerLeftX(), bBox.getLowerLeftY());
+                Point2D p2 = new Point2D.Float(bBox.getUpperRightX(), bBox.getUpperRightY());
+                matrix.createAffineTransform().transform(p1, p1);
+                matrix.createAffineTransform().transform(p2, p2);
+                Rectangle2D transformedBBox = new Rectangle2D.Float(
+                        (float) Math.min(p1.getX(), p2.getX()),
+                        (float) Math.min(p1.getY(), p2.getY()),
+                        (float) Math.abs(p2.getX() - p1.getX()),
+                        (float) Math.abs(p2.getY() - p1.getY()));
+
+                // PDF Spec 12.5.5:
+                // b) A matrix A shall be computed that scales and translates
+                // the transformed appearance box to align with the edges
+                // of the annotation's rectangle
+                //
+                // code inspired from
+                // http://stackoverflow.com/a/14015713/535646
+                AffineTransform at = new AffineTransform();
+                at.translate(rect2D.getMinX(), rect2D.getMinY());
+                at.scale(rect2D.getWidth() / transformedBBox.getWidth(),
+                         rect2D.getHeight() / transformedBBox.getHeight());
+                at.translate(-transformedBBox.getMinX(), -transformedBBox.getMinY());
+                Matrix matrixA = new Matrix();
+                matrixA.setFromAffineTransform(at);
+
+                // PDF Spec 12.5.5:
+                // c) Matrix shall be concatenated with A to form a matrix AA
+                // that maps from the appearance's coordinate system to
+                // the annotation's rectangle in default user space
+                Matrix matrixAA = matrix.multiply(matrixA);
+
+                Point2D point = new Point2D.Float(matrixAA.getXPosition(), matrixAA.getYPosition());
+                matrixAA.setValue(2, 0, 0);
+                matrixAA.setValue(2, 1, 0);
+
+                getGraphicsState().setCurrentTransformationMatrix(matrixAA);
+
+                // Calculate clipping
+                // PDF Spec 12.5.5:
+                // a self-contained content stream that shall be rendered
+                // inside the annotation rectangle
+                Rectangle2D clipRect2D = new Rectangle2D.Float(
+                        (float) (rect2D.getMinX()-point.getX()),
+                        (float) (rect2D.getMinY()-point.getY()),
+                        (float) rect2D.getWidth(),
+                        (float) rect2D.getHeight());
+                getGraphicsState().intersectClippingPath(new Area(clipRect2D));
+
+                graphics.translate((int) point.getX(), (int) point.getY());
+                lastClip = null;
+                processChildStream(appearanceStream);
+                graphics.translate(-(int) point.getX(), -(int) point.getY());
+
+                restoreGraphicsState();
             }
         }
-        graphics = null;
     }
 
     /**

Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestFDF.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestFDF.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestFDF.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/TestFDF.java Mon Oct 27 22:06:41 2014
@@ -20,7 +20,6 @@ import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.util.List;
-import java.util.Map;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
@@ -32,6 +31,7 @@ import org.apache.pdfbox.cos.COSString;
 import org.apache.pdfbox.pdfparser.PDFStreamParser;
 import org.apache.pdfbox.pdmodel.common.COSObjectable;
 import org.apache.pdfbox.pdmodel.fdf.FDFDocument;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceEntry;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
 import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
@@ -244,8 +244,8 @@ public class TestFDF extends TestCase
     private void testContentStreamContains( PDDocument doc, PDFieldTreeNode field, String expected ) throws Exception
     {
         PDAnnotationWidget widget = field.getWidget();
-        Map<String,PDAppearanceStream> normalAppearance = widget.getAppearance().getNormalAppearance();
-        PDAppearanceStream appearanceStream = normalAppearance.get( "default" );
+        PDAppearanceEntry normalAppearance = widget.getAppearance().getNormalAppearance();
+        PDAppearanceStream appearanceStream = normalAppearance.getAppearanceStream();
         COSStream actual = appearanceStream.getStream();
 
         List<Object> actualTokens = getStreamTokens( doc, actual );
@@ -255,8 +255,8 @@ public class TestFDF extends TestCase
     private void testContentStreams( PDDocument doc, PDFieldTreeNode field, String expected ) throws Exception
     {
         PDAnnotationWidget widget = field.getWidget();
-        Map<String,PDAppearanceStream> normalAppearance = widget.getAppearance().getNormalAppearance();
-        PDAppearanceStream appearanceStream = normalAppearance.get( "default" );
+        PDAppearanceEntry normalAppearance = widget.getAppearance().getNormalAppearance();
+        PDAppearanceStream appearanceStream = normalAppearance.getAppearanceStream();
         COSStream actual = appearanceStream.getStream();
 
         List<Object> actualTokens = getStreamTokens( doc, actual );

Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/annotation/AnnotationValidator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/annotation/AnnotationValidator.java?rev=1634701&r1=1634700&r2=1634701&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/annotation/AnnotationValidator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/annotation/AnnotationValidator.java Mon Oct 27 22:06:41 2014
@@ -171,7 +171,7 @@ public abstract class AnnotationValidato
         PDAppearanceDictionary ap = this.pdAnnot.getAppearance();
         if (ap != null)
         {
-            COSDictionary apDict = ap.getDictionary();
+            COSDictionary apDict = ap.getCOSObject();
             // Only N entry is authorized
             if (apDict.getItem(COSName.D) != null || apDict.getItem(COSName.R) != null)
             {