Bug 53191 - Problems with line style when converting ppt to png

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1765196 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2016-10-16 22:48:25 +00:00
parent e3633daac5
commit bf95861693
3 changed files with 135 additions and 94 deletions

View File

@ -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;
@ -35,11 +37,20 @@ public class DrawFreeformShape extends DrawAutoShape {
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;
}

View File

@ -47,10 +47,31 @@ public class DrawShape implements Drawable {
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();
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());
}
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.) {
@ -77,7 +98,7 @@ public class DrawShape implements Drawable {
// 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")) {
if (isHSLF) {
txs = new AffineTransform(tx);
} else {
// this handling is only based on try and error ... not sure why xslf is handled differently.
@ -113,19 +134,8 @@ public class DrawShape implements Drawable {
}
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());
break;
}
//flip vertical
if (ps.getFlipVertical()) {
graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
graphics.scale(1, -1);
graphics.translate(-anchor.getX(), -anchor.getY());
}
}

View File

@ -230,12 +230,12 @@ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformSh
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 extends HSLFAutoShape implements FreeformSh
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 extends HSLFAutoShape implements FreeformSh
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 extends HSLFAutoShape implements FreeformSh
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) {