]> source.dussan.org Git - poi.git/commitdiff
Patch 53176 - Fixed auto shapes render problem in pptx files
authorYegor Kozlov <yegor@apache.org>
Sat, 9 Nov 2013 11:32:55 +0000 (11:32 +0000)
committerYegor Kozlov <yegor@apache.org>
Sat, 9 Nov 2013 11:32:55 +0000 (11:32 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1540290 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java

index c22d0fdf70ad7a0adad929985fc1195180e4e85c..19034e08365fad43afad19ea9a06b97f4e15b332 100644 (file)
@@ -141,11 +141,42 @@ public abstract class XSLFShape {
         double rotation = getRotation();\r
         if (rotation != 0.) {\r
             // PowerPoint rotates shapes relative to the geometric center\r
-            double centerX = anchor.getX() + anchor.getWidth() / 2;\r
-            double centerY = anchor.getY() + anchor.getHeight() / 2;\r
-\r
+            double centerX = anchor.getCenterX();\r
+            double centerY = anchor.getCenterY();\r
+\r
+            // normalize rotation\r
+            rotation = (360.+(rotation%360.))%360.;\r
+            int quadrant = (((int)rotation+45)/90)%4;\r
+            double scaleX = 1.0, scaleY = 1.0;\r
+\r
+            // scale to bounding box (bug #53176)\r
+            if (quadrant == 1 || quadrant == 3) {\r
+                // In quadrant 1 and 3, which is basically a shape in a more or less portrait orientation (45°-135° and 225°-315°),\r
+                // we need to first rotate the shape by a multiple of 90° and then resize the bounding box  \r
+                // to its original bbox. After that we can rotate the shape to the exact rotation amount.\r
+                // It's strange that you'll need to rotate the shape back and forth again, but you can\r
+                // think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might\r
+                // be already (differently) scaled, so you can paint the shape in its default orientation\r
+                // and later on, turn it around again to compare it with its original size ...\r
+                AffineTransform txg = new AffineTransform(); // graphics coordinate space\r
+                AffineTransform txs = new AffineTransform(tx); // shape coordinate space\r
+                txg.translate(centerX, centerY);\r
+                txg.rotate(Math.toRadians(quadrant*90));\r
+                txg.translate(-centerX, -centerY);\r
+                txs.translate(centerX, centerY);\r
+                txs.rotate(Math.toRadians(-quadrant*90));\r
+                txs.translate(-centerX, -centerY);\r
+                txg.concatenate(txs);\r
+                Rectangle2D anchor2 = txg.createTransformedShape(getAnchor()).getBounds2D();\r
+                scaleX = anchor.getWidth() == 0. ? 1.0 : anchor.getWidth() / anchor2.getWidth();\r
+                scaleY = anchor.getHeight() == 0. ? 1.0 : anchor.getHeight() / anchor2.getHeight();\r
+            }\r
+\r
+            // transformation is applied reversed ...\r
             graphics.translate(centerX, centerY);\r
-            graphics.rotate(Math.toRadians(rotation));\r
+            graphics.rotate(Math.toRadians(rotation-(double)(quadrant*90)));\r
+            graphics.scale(scaleX, scaleY);\r
+            graphics.rotate(Math.toRadians(quadrant*90));\r
             graphics.translate(-centerX, -centerY);\r
         }\r
 \r