FOP-2739: Avoid rastering PDF with Smask to image

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop-pdf-images/trunk@1808727 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/xmlgraphics-commons-svn-trunk.jar b/lib/xmlgraphics-commons-svn-trunk.jar
index 4b3afff..fe78fa4 100644
--- a/lib/xmlgraphics-commons-svn-trunk.jar
+++ b/lib/xmlgraphics-commons-svn-trunk.jar
Binary files differ
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java b/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java
index e63a6eb..c7d9a47 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java
@@ -39,7 +39,6 @@
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.graphics.PDXObject;
 import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
-import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
 import org.apache.pdfbox.pdmodel.graphics.shading.PDShading;
 import org.apache.pdfbox.rendering.PDFRenderer;
 
@@ -202,11 +201,6 @@
                                     && pageHasTransparency(formRes)) {
                                 return true;
                             }
-                        } else if (pdxObject instanceof PDImageXObject) {
-                            if (pdxObject.getCOSStream().containsKey(COSName.SMASK)
-                                    || ((PDImageXObject) pdxObject).isStencil()) {
-                                return true;
-                            }
                         }
                     }
                 }
diff --git a/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java b/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java
index ad7c847..761d363 100644
--- a/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java
+++ b/src/java/org/apache/fop/render/pdf/pdfbox/PSPDFGraphics2D.java
@@ -27,7 +27,10 @@
 import java.awt.Paint;
 import java.awt.PaintContext;
 import java.awt.Rectangle;
+import java.awt.TexturePaint;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
 import java.awt.image.DataBufferInt;
@@ -148,9 +151,43 @@
                     handleIOException(ioe);
                 }
             }
+        } else if (paint.getClass().getSimpleName().equals("TilingPaint")) {
+            try {
+                Field f = paint.getClass().getDeclaredField("paint");
+                f.setAccessible(true);
+                TexturePaint texturePaint = (TexturePaint) f.get(paint);
+                f = paint.getClass().getDeclaredField("patternMatrix");
+                f.setAccessible(true);
+                Matrix matrix = (Matrix) f.get(paint);
+                Rectangle2D rect = getTransformedRect(matrix, texturePaint.getAnchorRect());
+                texturePaint = new TexturePaint(texturePaint.getImage(), rect);
+                super.applyPaint(texturePaint, fill);
+            } catch (NoSuchFieldException e) {
+                throw new RuntimeException(e);
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
         }
     }
 
+    private static Rectangle2D getTransformedRect(Matrix matrix, Rectangle2D anchorRect) {
+        double x = anchorRect.getX();
+        double y = anchorRect.getY();
+        double width = anchorRect.getWidth();
+        double height = anchorRect.getHeight();
+        AffineTransform at = matrix.createAffineTransform();
+        Point2D p1 = new Point2D.Double(x, y);
+        Point2D p2 = new Point2D.Double(x + width, y + height);
+        at.transform(p1, p1);
+        at.transform(p2, p2);
+        Rectangle2D rectangle = new Rectangle2D.Float(
+                (float) Math.min(p1.getX(), p2.getX()),
+                (float) Math.min(p1.getY(), p2.getY()),
+                (float) Math.abs(width),
+                (float) Math.abs(height));
+        return rectangle;
+    }
+
     private void transformCoords(float[] coords, Paint paint, boolean axialShading) {
         try {
             Field f = paint.getClass().getDeclaredField("matrix");
diff --git a/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java b/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
index e18ea45..a8507cb 100644
--- a/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
+++ b/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
@@ -112,6 +112,7 @@
     private static final String LOOP = "test/resources/loop.pdf";
     private static final String ERROR = "test/resources/error.pdf";
     private static final String LIBREOFFICE = "test/resources/libreoffice.pdf";
+    private static final String SMASK = "test/resources/smask.pdf";
 
     private static PDFPage getPDFPage(PDFDocument doc) {
         final Rectangle2D r = new Rectangle2D.Double();
@@ -299,7 +300,7 @@
         pdfToPS(TTSubset3);
         pdfToPS(TTSubset5);
         stream = pdfToPS(CFFCID1);
-        Assert.assertEquals(countString(stream.toString("UTF-8"), "%AXGBeginBitmap:"), 1);
+        Assert.assertEquals(countString(stream.toString("UTF-8"), "%AXGBeginBitmap:"), 2);
         pdfToPS(CFFCID2);
         pdfToPS(Type1Subset1);
         pdfToPS(Type1Subset2);
@@ -360,6 +361,13 @@
     }
 
     @Test
+    public void testSmask() throws IOException, ImageException {
+        ByteArrayOutputStream ps = pdfToPS(SMASK);
+        Assert.assertTrue(ps.toString("UTF-8").contains("/Pattern"));
+        Assert.assertTrue(ps.toString("UTF-8").contains("{<\nf1f1f1"));
+    }
+
+    @Test
     public void testPCL() throws IOException, ImageException {
         String ex = "";
         try {
diff --git a/test/resources/smask.pdf b/test/resources/smask.pdf
new file mode 100644
index 0000000..9407e10
--- /dev/null
+++ b/test/resources/smask.pdf
Binary files differ