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