# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: pdfviewer/PageDrawer.java
--- pdfviewer/PageDrawer.java Base (BASE)
+++ pdfviewer/PageDrawer.java Locally Modified (Based On LOCAL)
@@ -29,6 +29,7 @@
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Point2D;
 import java.awt.Image;
+import java.awt.geom.Rectangle2D;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
@@ -66,6 +67,7 @@
 import org.apache.pdfbox.util.ResourceLoader;
 import org.apache.pdfbox.util.TextPosition;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
 
 
 /**
@@ -138,6 +140,11 @@
             PDResources resources = page.findResources();
             processStream( page, resources, page.getContents().getStream() );
         }
+        else
+        {
+            initStream (page);
+        }
+        
         List<PDAnnotation> annotations = page.getAnnotations();
         for( int i=0; i<annotations.size(); i++ )
         {
@@ -158,17 +165,85 @@
                         (PDAppearanceStream)appearanceMap.get( appearanceName ); 
                     if( appearance != null ) 
                     { 
-                        Point2D point = new Point2D.Float(rect.getLowerLeftX(), rect.getLowerLeftY());
+                        //saveGraphicsState
+                        getGraphicsStack().push( (PDGraphicsState)getGraphicsState().clone() );
+
+                        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)
                         {
-                            // transform the rectangle using the given matrix 
-                            AffineTransform at = matrix.createAffineTransform();
-                            at.transform(point, point);
+                            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());
+                        
+                        Area currentArea = new Area(getGraphicsState().getCurrentClippingPath());
+                        Area newArea = new Area(clipRect2D);
+                        currentArea.intersect(newArea);
+                        // something isn't correct here, probably lower x and y wrong
+                //        getGraphicsState().setCurrentClippingPath(currentArea);
+
                         g.translate( (int)point.getX(), -(int)point.getY() );
+                        g.setClip(null);
                         processSubStream( page, appearance.getResources(), appearance.getStream() ); 
                         g.translate( -(int)point.getX(), (int)point.getY() ); 
+                       
+                        // restoreGraphicsState
+                        setGraphicsState( (PDGraphicsState)getGraphicsStack().pop() );
                     }
                 }
             }
Index: util/PDFStreamEngine.java
--- util/PDFStreamEngine.java Base (BASE)
+++ util/PDFStreamEngine.java Locally Modified (Based On LOCAL)
@@ -195,6 +195,15 @@
         totalCharCnt = 0;
     }
 
+    protected void initStream(PDPage aPage)
+    {
+        graphicsState = new PDGraphicsState(aPage.findCropBox());
+        textMatrix = null;
+        textLineMatrix = null;
+        graphicsStack.clear();
+        streamResourcesStack.clear();
+    }    
+
     /**
      * This will process the contents of the stream.
      *
@@ -207,11 +216,7 @@
      */
     public void processStream( PDPage aPage, PDResources resources, COSStream cosStream ) throws IOException
     {
-        graphicsState = new PDGraphicsState(aPage.findCropBox());
-        textMatrix = null;
-        textLineMatrix = null;
-        graphicsStack.clear();
-        streamResourcesStack.clear();
+        initStream(aPage);
         processSubStream( aPage, resources, cosStream );
     }
 
