You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2016/10/16 22:48:25 UTC

svn commit: r1765196 - in /poi: site/src/documentation/content/xdocs/ trunk/src/java/org/apache/poi/sl/draw/ trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/

Author: kiwiwings
Date: Sun Oct 16 22:48:25 2016
New Revision: 1765196

URL: http://svn.apache.org/viewvc?rev=1765196&view=rev
Log:
Bug 53191 - Problems with line style when converting ppt to png

Modified:
    poi/site/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java
    poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java

Modified: poi/site/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1765196&r1=1765195&r2=1765196&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Sun Oct 16 22:48:25 2016
@@ -40,6 +40,7 @@
     </devs>
 
     <release version="3.16-beta1" date="2016-11-??">
+        <action dev="PD" type="fix" fixes-bug="53191">HSLF: Problems with line style when converting ppt to png</action>
         <action dev="PD" type="fix" fixes-bug="60255">XSSF: Check for in-use drawing part names and use next available, when creating a new sheet drawing</action>
         <action dev="PD" type="fix" fixes-bug="56781,60246">SS Common: named range validation</action>
         <action dev="PD" type="fix" fixes-bug="59907">SS Common: Regression in getting and setting anchor type introduced in 3.15</action>

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java?rev=1765196&r1=1765195&r2=1765196&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java Sun Oct 16 22:48:25 2016
@@ -18,6 +18,8 @@
 package org.apache.poi.sl.draw;
 
 import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Path2D;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -32,14 +34,23 @@ public class DrawFreeformShape extends D
     public DrawFreeformShape(FreeformShape<?,?> shape) {
         super(shape);
     }
-    
+
     protected Collection<Outline> computeOutlines(Graphics2D graphics) {
         List<Outline> lst = new ArrayList<Outline>();
-        java.awt.Shape sh = getShape().getPath();
-        FillStyle fs = getShape().getFillStyle();
-        StrokeStyle ss = getShape().getStrokeStyle();
+        FreeformShape<?,?> fsh = getShape();
+        Path2D sh = fsh.getPath();
+
+        AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);
+        if (tx == null) {
+            tx = new AffineTransform();
+        }
+
+        java.awt.Shape canvasShape = tx.createTransformedShape(sh);
+
+        FillStyle fs = fsh.getFillStyle();
+        StrokeStyle ss = fsh.getStrokeStyle();
         Path path = new Path(fs != null, ss != null);
-        lst.add(new Outline(sh, path));
+        lst.add(new Outline(canvasShape, path));
         return lst;
     }
 

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java?rev=1765196&r1=1765195&r2=1765196&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawShape.java Sun Oct 16 22:48:25 2016
@@ -47,85 +47,95 @@ public class DrawShape implements Drawab
         if (!(shape instanceof PlaceableShape)) return;
 
         PlaceableShape<?,?> ps = (PlaceableShape<?,?>)shape;
+        final boolean isHSLF = ps.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf");
         AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);
         if (tx == null) tx = new AffineTransform();
         final Rectangle2D anchor = tx.createTransformedShape(ps.getAnchor()).getBounds2D();
 
-        // rotation
-        double rotation = ps.getRotation();
-        if (rotation != 0.) {
-            // PowerPoint rotates shapes relative to the geometric center
-            double centerX = anchor.getCenterX();
-            double centerY = anchor.getCenterY();
-
-            // normalize rotation
-            rotation %= 360.;
-            if (rotation < 0) rotation += 360.;
-
-            int quadrant = (((int)rotation+45)/90)%4;
-            double scaleX = 1.0, scaleY = 1.0;
-
-            // scale to bounding box (bug #53176)
-            if (quadrant == 1 || quadrant == 3) {
-                // In quadrant 1 and 3, which is basically a shape in a more or less portrait orientation
-                // (45-135 degrees and 225-315 degrees), we need to first rotate the shape by a multiple
-                // of 90 degrees and then resize the bounding box to its original bbox. After that we can
-                // rotate the shape to the exact rotation amount.
-                // It's strange that you'll need to rotate the shape back and forth again, but you can
-                // think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might
-                // be already (differently) scaled, so you can paint the shape in its default orientation
-                // and later on, turn it around again to compare it with its original size ...
-
-                AffineTransform txs;
-                if (ps.getClass().getCanonicalName().toLowerCase(Locale.ROOT).contains("hslf")) {
-                    txs = new AffineTransform(tx);
-                } else {
-                    // this handling is only based on try and error ... not sure why xslf is handled differently.
-                    txs = new AffineTransform();
-                    txs.translate(centerX, centerY);
-                    txs.rotate(Math.PI/2.); // actually doesn't matter if +/- 90 degrees
-                    txs.translate(-centerX, -centerY);
-                    txs.concatenate(tx);
+        char cmds[] = isHSLF ? new char[]{ 'h','v','r' } : new char[]{ 'r','h','v' };
+        for (char ch : cmds) {
+            switch (ch) {
+            case 'h':
+                //flip horizontal
+                if (ps.getFlipHorizontal()) {
+                    graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
+                    graphics.scale(-1, 1);
+                    graphics.translate(-anchor.getX(), -anchor.getY());
                 }
-
-                txs.translate(centerX, centerY);
-                txs.rotate(Math.PI/2.);
-                txs.translate(-centerX, -centerY);
-
-                Rectangle2D anchor2 = txs.createTransformedShape(ps.getAnchor()).getBounds2D();
-
-                scaleX = safeScale(anchor.getWidth(), anchor2.getWidth());
-                scaleY = safeScale(anchor.getHeight(), anchor2.getHeight());
-            } else {
-                quadrant = 0;
-            }
-
-            // transformation is applied reversed ...
-            graphics.translate(centerX, centerY);
-            double rot = Math.toRadians(rotation-quadrant*90.);
-            if (rot != 0) {
-                graphics.rotate(rot);
-            }
-            graphics.scale(scaleX, scaleY);
-            rot = Math.toRadians(quadrant*90);
-            if (rot != 0) {
-                graphics.rotate(rot);
+                break;
+            case 'v':
+                //flip vertical
+                if (ps.getFlipVertical()) {
+                    graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
+                    graphics.scale(1, -1);
+                    graphics.translate(-anchor.getX(), -anchor.getY());
+                }
+                break;
+            case 'r':
+                // rotation
+                double rotation = ps.getRotation();
+                if (rotation != 0.) {
+                    // PowerPoint rotates shapes relative to the geometric center
+                    double centerX = anchor.getCenterX();
+                    double centerY = anchor.getCenterY();
+
+                    // normalize rotation
+                    rotation %= 360.;
+                    if (rotation < 0) rotation += 360.;
+
+                    int quadrant = (((int)rotation+45)/90)%4;
+                    double scaleX = 1.0, scaleY = 1.0;
+
+                    // scale to bounding box (bug #53176)
+                    if (quadrant == 1 || quadrant == 3) {
+                        // In quadrant 1 and 3, which is basically a shape in a more or less portrait orientation
+                        // (45-135 degrees and 225-315 degrees), we need to first rotate the shape by a multiple
+                        // of 90 degrees and then resize the bounding box to its original bbox. After that we can
+                        // rotate the shape to the exact rotation amount.
+                        // It's strange that you'll need to rotate the shape back and forth again, but you can
+                        // think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might
+                        // be already (differently) scaled, so you can paint the shape in its default orientation
+                        // and later on, turn it around again to compare it with its original size ...
+
+                        AffineTransform txs;
+                        if (isHSLF) {
+                            txs = new AffineTransform(tx);
+                        } else {
+                            // this handling is only based on try and error ... not sure why xslf is handled differently.
+                            txs = new AffineTransform();
+                            txs.translate(centerX, centerY);
+                            txs.rotate(Math.PI/2.); // actually doesn't matter if +/- 90 degrees
+                            txs.translate(-centerX, -centerY);
+                            txs.concatenate(tx);
+                        }
+
+                        txs.translate(centerX, centerY);
+                        txs.rotate(Math.PI/2.);
+                        txs.translate(-centerX, -centerY);
+
+                        Rectangle2D anchor2 = txs.createTransformedShape(ps.getAnchor()).getBounds2D();
+
+                        scaleX = safeScale(anchor.getWidth(), anchor2.getWidth());
+                        scaleY = safeScale(anchor.getHeight(), anchor2.getHeight());
+                    } else {
+                        quadrant = 0;
+                    }
+
+                    // transformation is applied reversed ...
+                    graphics.translate(centerX, centerY);
+                    double rot = Math.toRadians(rotation-quadrant*90.);
+                    if (rot != 0) {
+                        graphics.rotate(rot);
+                    }
+                    graphics.scale(scaleX, scaleY);
+                    rot = Math.toRadians(quadrant*90);
+                    if (rot != 0) {
+                        graphics.rotate(rot);
+                    }
+                    graphics.translate(-centerX, -centerY);
+                }
+                break;
             }
-            graphics.translate(-centerX, -centerY);
-        }
-
-        //flip horizontal
-        if (ps.getFlipHorizontal()) {
-            graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
-            graphics.scale(-1, 1);
-            graphics.translate(-anchor.getX(), -anchor.getY());
-        }
-
-        //flip vertical
-        if (ps.getFlipVertical()) {
-            graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
-            graphics.scale(1, -1);
-            graphics.translate(-anchor.getX(), -anchor.getY());
         }
     }
 

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java?rev=1765196&r1=1765195&r2=1765196&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java Sun Oct 16 22:48:25 2016
@@ -230,12 +230,12 @@ public final class HSLFFreeformShape ext
         EscherArrayProperty verticesProp = new EscherArrayProperty((short)(EscherProperties.GEOMETRY__VERTICES + 0x4000), false, null);
         verticesProp.setNumberOfElementsInArray(pntInfo.size());
         verticesProp.setNumberOfElementsInMemory(pntInfo.size());
-        verticesProp.setSizeOfElements(0xFFF0);
+        verticesProp.setSizeOfElements(8);
         for (int i = 0; i < pntInfo.size(); i++) {
             Point2D.Double pnt = pntInfo.get(i);
-            byte[] data = new byte[4];
-            LittleEndian.putShort(data, 0, (short)Units.pointsToMaster(pnt.getX() - bounds.getX()));
-            LittleEndian.putShort(data, 2, (short)Units.pointsToMaster(pnt.getY() - bounds.getY()));
+            byte[] data = new byte[8];
+            LittleEndian.putInt(data, 0, Units.pointsToMaster(pnt.getX() - bounds.getX()));
+            LittleEndian.putInt(data, 4, Units.pointsToMaster(pnt.getY() - bounds.getY()));
             verticesProp.setElement(i, data);
         }
         opt.addEscherProperty(verticesProp);
@@ -282,6 +282,7 @@ public final class HSLFFreeformShape ext
 
         Iterator<byte[]> vertIter = verticesProp.iterator();
         Iterator<byte[]> segIter = segmentsProp.iterator();
+        double xyPoints[] = new double[2];
         
         while (vertIter.hasNext() && segIter.hasNext()) {
             byte[] segElem = segIter.next();
@@ -292,30 +293,30 @@ public final class HSLFFreeformShape ext
                     break;
                 }
                 case moveTo: {
-                    byte[] p = vertIter.next();
-                    double x = Units.masterToPoints(LittleEndian.getShort(p, 0));
-                    double y = Units.masterToPoints(LittleEndian.getShort(p, 2));
+                    fillPoint(vertIter.next(), xyPoints);
+                    double x = xyPoints[0];
+                    double y = xyPoints[1];
                     path.moveTo(x,y);
                     break;
                 }
                 case curveTo: {
-                    byte[] p1 = vertIter.next();
-                    double x1 = Units.masterToPoints(LittleEndian.getShort(p1, 0));
-                    double y1 = Units.masterToPoints(LittleEndian.getShort(p1, 2));
-                    byte[] p2 = vertIter.next();
-                    double x2 = Units.masterToPoints(LittleEndian.getShort(p2, 0));
-                    double y2 = Units.masterToPoints(LittleEndian.getShort(p2, 2));
-                    byte[] p3 = vertIter.next();
-                    double x3 = Units.masterToPoints(LittleEndian.getShort(p3, 0));
-                    double y3 = Units.masterToPoints(LittleEndian.getShort(p3, 2));
+                    fillPoint(vertIter.next(), xyPoints);
+                    double x1 = xyPoints[0];
+                    double y1 = xyPoints[1];
+                    fillPoint(vertIter.next(), xyPoints);
+                    double x2 = xyPoints[0];
+                    double y2 = xyPoints[1];
+                    fillPoint(vertIter.next(), xyPoints);
+                    double x3 = xyPoints[0];
+                    double y3 = xyPoints[1];
                     path.curveTo(x1,y1,x2,y2,x3,y3);
                     break;
                 }
                 case lineTo:
                     if (vertIter.hasNext()) {
-                        byte[] p = vertIter.next();
-                        double x = Units.masterToPoints(LittleEndian.getShort(p, 0));
-                        double y = Units.masterToPoints(LittleEndian.getShort(p, 2));
+                        fillPoint(vertIter.next(), xyPoints);
+                        double x = xyPoints[0];
+                        double y = xyPoints[1];
                         path.lineTo(x,y);
                     }
                     break;
@@ -344,6 +345,25 @@ public final class HSLFFreeformShape ext
         return new Path2D.Double(at.createTransformedShape(path));
     }
     
+    private void fillPoint(byte xyMaster[], double xyPoints[]) {
+        if (xyMaster == null || xyPoints == null || (xyMaster.length != 4 && xyMaster.length != 8) || xyPoints.length != 2) {
+            logger.log(POILogger.WARN, "Invalid number of master bytes for a single point - ignore point");
+            return;
+        }
+        
+        int x, y;
+        if (xyMaster.length == 4) {
+            x = LittleEndian.getShort(xyMaster, 0);
+            y = LittleEndian.getShort(xyMaster, 2);
+        } else {
+            x = LittleEndian.getInt(xyMaster, 0);
+            y = LittleEndian.getInt(xyMaster, 4);
+        }
+        
+        xyPoints[0] = Units.masterToPoints(x);
+        xyPoints[1] = Units.masterToPoints(y);
+    }
+    
     private static <T extends EscherProperty> T getShapeProp(AbstractEscherOptRecord opt, int propId) {
         T prop = getEscherProperty(opt, (short)(propId + 0x4000));
         if (prop == null) {



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org