You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2014/08/30 16:21:06 UTC
svn commit: r1621462 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
Author: tilman
Date: Sat Aug 30 14:21:05 2014
New Revision: 1621462
URL: http://svn.apache.org/r1621462
Log:
PDFBOX-2283: correct transform / clipping for appearance streams
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
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=1621462&r1=1621461&r2=1621462&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 Sat Aug 30 14:21:05 2014
@@ -183,16 +183,74 @@ public class PageDrawer extends PDFGraph
PDAppearanceStream appearance = appearanceMap.get(appearanceName);
if (appearance != null)
{
- Point2D point = new Point2D.Float(rect.getLowerLeftX(), rect.getLowerLeftY());
+ saveGraphicsState();
+
+ PDRectangle bBox = appearance.getBoundingBox();
+
+ Rectangle2D rect2D = new Rectangle2D.Float(
+ rect.getLowerLeftX(),
+ rect.getLowerLeftY(),
+ rect.getWidth(),
+ rect.getHeight());
Matrix matrix = appearance.getMatrix();
- if (matrix != null)
+ if (matrix == null)
{
- matrix.createAffineTransform().transform(point, point);
+ matrix = new Matrix();
}
+ // 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()));
+
+ // 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);
+
+ // 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
+ // As per spec: "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;
processSubStream(appearance.getResources(), appearance.getStream());
graphics.translate(-(int) point.getX(), -(int) point.getY());
+
+ restoreGraphicsState();
}
}
}