You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ms...@apache.org on 2016/05/01 21:17:25 UTC

svn commit: r1741882 - /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/AppearanceGeneratorHelper.java

Author: msahyoun
Date: Sun May  1 19:17:24 2016
New Revision: 1741882

URL: http://svn.apache.org/viewvc?rev=1741882&view=rev
Log:
PDFBOX-3333: calculate bbox and transformation matrix respecting rotation

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/AppearanceGeneratorHelper.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/AppearanceGeneratorHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/AppearanceGeneratorHelper.java?rev=1741882&r1=1741881&r2=1741882&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/AppearanceGeneratorHelper.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/AppearanceGeneratorHelper.java Sun May  1 19:17:24 2016
@@ -17,6 +17,7 @@
 package org.apache.pdfbox.pdmodel.interactive.form;
 
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -126,14 +127,28 @@ class AppearanceGeneratorHelper
                 else
                 {
                     appearanceStream = new PDAppearanceStream(field.getAcroForm().getDocument());
-                    appearanceStream.setBBox(widget.getRectangle().createRetranslatedRectangle());
+                    
+                    PDRectangle rect = widget.getRectangle();
+                    
+                    // Calculate the entries for the bounding box and the transformation matrix
+                    // settings for the appearance stream
+                    int rotation = resolveRotation(widget);
+                    Matrix matrix = Matrix.getRotateInstance(Math.toRadians(rotation), 0, 0);
+                    Point2D.Float point2D = matrix.transformPoint(rect.getWidth(), rect.getHeight());
+                    
+                    PDRectangle bbox = new PDRectangle(Math.abs((float) point2D.getX()), Math.abs((float) point2D.getY()));
+                    appearanceStream.setBBox(bbox);
+                    
+                    appearanceStream.setMatrix(calculateMatrix(bbox, rotation));
+                    appearanceStream.setFormType(1);
+
                     appearanceDict.setNormalAppearance(appearanceStream);
                     // TODO support appearances other than "normal"
                 }
                 
                 /*
                  * Adobe Acrobat always recreates the complete appearance stream if there is an appearance characteristics
-                 * entry (the widget dictionaries MK entry). In addition if there is no content yet also create the apperance
+                 * entry (the widget dictionaries MK entry). In addition if there is no content yet also create the appearance
                  * stream from the entries.
                  * 
                  */
@@ -147,7 +162,17 @@ class AppearanceGeneratorHelper
         }
     }
     
-    /**
+    private int resolveRotation(PDAnnotationWidget widget) {
+		PDAppearanceCharacteristicsDictionary  characteristicsDictionary = widget.getAppearanceCharacteristics();
+		if (characteristicsDictionary != null)
+		{
+			// 0 is the default value if the R key doesn't exist
+			return characteristicsDictionary.getRotation();
+		}
+		return 0;
+	}
+
+	/**
      * Initialize the content of the appearance stream.
      * 
      * Get settings like border style, border width and colors to be used to draw a rectangle and background color 
@@ -263,14 +288,7 @@ class AppearanceGeneratorHelper
         PDPageContentStream contents = new PDPageContentStream(field.getAcroForm().getDocument(),
                                                                appearanceStream, output);
         
-        // Set an identity transformation in case there is no Matrix entry
-        Matrix matrix = appearanceStream.getMatrix();
-        if (matrix == null)
-        {
-            appearanceStream.setMatrix(new AffineTransform());
-        }
-
-        appearanceStream.setFormType(1);
+        PDRectangle bbox = resolveBoundingBox(widget, appearanceStream);
         
         // Acrobat calculates the left and right padding dependent on the offset of the border edge
         // This calculation works for forms having been generated by Acrobat.
@@ -280,7 +298,6 @@ class AppearanceGeneratorHelper
         {
             borderWidth = widget.getBorderStyle().getWidth();
         }
-        PDRectangle bbox = resolveBoundingBox(widget, appearanceStream);
         PDRectangle clipRect = applyPadding(bbox, Math.max(1f, borderWidth));
         PDRectangle contentRect = applyPadding(clipRect, Math.max(1f, borderWidth));
         
@@ -385,7 +402,33 @@ class AppearanceGeneratorHelper
         contents.close();
     }
     
-    private boolean isMultiLine()
+    private AffineTransform calculateMatrix(PDRectangle bbox, int rotation) {
+		if (rotation == 0)
+		{
+			return new AffineTransform();
+		}
+		else
+		{
+			float tx=0, ty=0;
+			
+			if (rotation == 90)
+			{
+				tx = bbox.getUpperRightY();
+			} else if (rotation == 180)
+			{
+				tx = bbox.getUpperRightY();
+				ty = bbox.getUpperRightX();
+			} else if (rotation == 270)
+			{
+				ty = bbox.getUpperRightX();
+			}
+			
+			Matrix matrix = Matrix.getRotateInstance(Math.toRadians(rotation), tx, ty);
+			return matrix.createAffineTransform();
+		}
+	}
+
+	private boolean isMultiLine()
     {
         return field instanceof PDTextField && ((PDTextField) field).isMultiline();
     }