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)
{