diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2020-02-02 22:53:09 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2020-02-02 22:53:09 +0000 |
commit | 33fd0b22d6515bd9ec3a1ad6bf738089a0bc86b7 (patch) | |
tree | 9053465e126eff533b1a8934d0b4513fa7f40a70 /src/scratchpad | |
parent | d20e85387e8c48d70249f5349f796a7cc4db8199 (diff) | |
download | poi-33fd0b22d6515bd9ec3a1ad6bf738089a0bc86b7.tar.gz poi-33fd0b22d6515bd9ec3a1ad6bf738089a0bc86b7.zip |
Regression findings - fix missing moveto exception
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1873515 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/scratchpad')
-rw-r--r-- | src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java | 178 | ||||
-rw-r--r-- | src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java | 14 |
2 files changed, 114 insertions, 78 deletions
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java index 3b57ccb3b8..206bb1641b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java @@ -17,6 +17,9 @@ package org.apache.poi.hslf.usermodel; +import static org.apache.poi.hslf.usermodel.HSLFFreeformShape.ShapePath.CURVES_CLOSED; +import static org.apache.poi.hslf.usermodel.HSLFFreeformShape.ShapePath.LINES_CLOSED; + import java.awt.geom.Arc2D; import java.awt.geom.Path2D; import java.awt.geom.Point2D; @@ -69,22 +72,10 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, static final byte[] SEGMENTINFO_CLOSE = new byte[]{0x01, (byte)0x60}; static final byte[] SEGMENTINFO_END = new byte[]{0x00, (byte)0x80}; + private static final ObjectFactory OF = new ObjectFactory(); private static final BitField PATH_INFO = BitFieldFactory.getInstance(0xE000); private static final BitField ESCAPE_INFO = BitFieldFactory.getInstance(0x1F00); - private static final EscherPropertyTypes[] ADJUST_VALUES = { - EscherPropertyTypes.GEOMETRY__ADJUSTVALUE, - EscherPropertyTypes.GEOMETRY__ADJUST2VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST3VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST4VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST5VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST6VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST7VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST8VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST9VALUE, - EscherPropertyTypes.GEOMETRY__ADJUST10VALUE - }; - enum PathInfo { lineTo(0),curveTo(1),moveTo(2),close(3),end(4),escape(5),clientEscape(6); private final int flag; @@ -220,12 +211,11 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, } CustomGeometry getGeometry(Path2D path2D) { - final ObjectFactory of = new ObjectFactory(); - final CTCustomGeometry2D cusGeo = of.createCTCustomGeometry2D(); - cusGeo.setAvLst(of.createCTGeomGuideList()); - cusGeo.setGdLst(of.createCTGeomGuideList()); - cusGeo.setAhLst(of.createCTAdjustHandleList()); - cusGeo.setCxnLst(of.createCTConnectionSiteList()); + final CTCustomGeometry2D cusGeo = OF.createCTCustomGeometry2D(); + cusGeo.setAvLst(OF.createCTGeomGuideList()); + cusGeo.setGdLst(OF.createCTGeomGuideList()); + cusGeo.setAhLst(OF.createCTAdjustHandleList()); + cusGeo.setCxnLst(OF.createCTConnectionSiteList()); final AbstractEscherOptRecord opt = getEscherOptRecord(); @@ -249,8 +239,8 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, final int[] xyPoints = new int[2]; boolean isClosed = false; - final CTPath2DList pathLst = of.createCTPath2DList(); - final CTPath2D pathCT = of.createCTPath2D(); + final CTPath2DList pathLst = OF.createCTPath2DList(); + final CTPath2D pathCT = OF.createCTPath2D(); final List<Object> moveLst = pathCT.getCloseOrMoveToOrLnTo(); pathLst.getPath().add(pathCT); cusGeo.setPathLst(pathLst); @@ -262,46 +252,23 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, continue; } switch (pi) { - case escape: { + case escape: handleEscapeInfo(pathCT, path2D, segElem, vertIter); break; - } case moveTo: - if (vertIter.hasNext()) { - final CTPath2DMoveTo m = of.createCTPath2DMoveTo(); - m.setPt(fillPoint(vertIter.next(), xyPoints)); - moveLst.add(m); - path2D.moveTo(xyPoints[0], xyPoints[1]); - } + handleMoveTo(vertIter, xyPoints, moveLst, path2D); break; case lineTo: - if (vertIter.hasNext()) { - final CTPath2DLineTo m = of.createCTPath2DLineTo(); - m.setPt(fillPoint(vertIter.next(), xyPoints)); - moveLst.add(m); - path2D.lineTo(xyPoints[0], xyPoints[1]); - } + handleLineTo(vertIter, xyPoints, moveLst, path2D); break; - case curveTo: { - final CTPath2DCubicBezierTo m = of.createCTPath2DCubicBezierTo(); - List<CTAdjPoint2D> mLst = m.getPt(); - - int[] pts = new int[6]; - - for (int i=0; vertIter.hasNext() && i<3; i++) { - mLst.add(fillPoint(vertIter.next(), xyPoints)); - pts[i*2] = xyPoints[0]; - pts[i*2+1] = xyPoints[1]; - if (i == 2) { - moveLst.add(m); - path2D.curveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); - } - } + case curveTo: + handleCurveTo(vertIter, xyPoints, moveLst, path2D); break; - } case close: - moveLst.add(of.createCTPath2DClose()); - path2D.closePath(); + if (path2D.getCurrentPoint() != null) { + moveLst.add(OF.createCTPath2DClose()); + path2D.closePath(); + } isClosed = true; break; default: @@ -309,37 +276,106 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, } } - EscherSimpleProperty shapePath = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__SHAPEPATH); - HSLFFreeformShape.ShapePath sp = HSLFFreeformShape.ShapePath.valueOf(shapePath == null ? 1 : shapePath.getPropertyValue()); - if ((sp == HSLFFreeformShape.ShapePath.LINES_CLOSED || sp == HSLFFreeformShape.ShapePath.CURVES_CLOSED) && !isClosed) { - moveLst.add(of.createCTPath2DClose()); - path2D.closePath(); + if (!isClosed) { + handleClosedShape(opt, moveLst, path2D); } + final Rectangle2D bounds = getBounds(opt, path2D); + + pathCT.setW((int)Math.rint(bounds.getWidth())); + pathCT.setH((int)Math.rint(bounds.getHeight())); + + return new CustomGeometry(cusGeo); + } + + private static Rectangle2D getBounds(AbstractEscherOptRecord opt, Path2D path2D) { EscherSimpleProperty geoLeft = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__LEFT); EscherSimpleProperty geoRight = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__RIGHT); EscherSimpleProperty geoTop = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__TOP); EscherSimpleProperty geoBottom = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__BOTTOM); - final Rectangle2D bounds; if (geoLeft != null && geoRight != null && geoTop != null && geoBottom != null) { - bounds = new Rectangle2D.Double(); + final Rectangle2D bounds = new Rectangle2D.Double(); bounds.setFrameFromDiagonal( - new Point2D.Double(geoLeft.getPropertyValue(), geoTop.getPropertyValue()), - new Point2D.Double(geoRight.getPropertyValue(), geoBottom.getPropertyValue()) + new Point2D.Double(geoLeft.getPropertyValue(), geoTop.getPropertyValue()), + new Point2D.Double(geoRight.getPropertyValue(), geoBottom.getPropertyValue()) ); + return bounds; } else { - bounds = path2D.getBounds2D(); + return path2D.getBounds2D(); } + } - pathCT.setW((int)Math.rint(bounds.getWidth())); - pathCT.setH((int)Math.rint(bounds.getHeight())); + private static void handleClosedShape(AbstractEscherOptRecord opt, List<Object> moveLst, Path2D path2D) { + EscherSimpleProperty shapePath = getEscherProperty(opt, EscherPropertyTypes.GEOMETRY__SHAPEPATH); + HSLFFreeformShape.ShapePath sp = HSLFFreeformShape.ShapePath.valueOf(shapePath == null ? 1 : shapePath.getPropertyValue()); + if (sp == LINES_CLOSED || sp == CURVES_CLOSED) { + moveLst.add(OF.createCTPath2DClose()); + path2D.closePath(); + } + } - return new CustomGeometry(cusGeo); + private static void handleMoveTo(Iterator<byte[]> vertIter, int[] xyPoints, List<Object> moveLst, Path2D path2D) { + if (!vertIter.hasNext()) { + return; + } + final CTPath2DMoveTo m = OF.createCTPath2DMoveTo(); + m.setPt(fillPoint(vertIter.next(), xyPoints)); + moveLst.add(m); + path2D.moveTo(xyPoints[0], xyPoints[1]); + } + + private static void handleLineTo(Iterator<byte[]> vertIter, int[] xyPoints, List<Object> moveLst, Path2D path2D) { + if (!vertIter.hasNext()) { + return; + } + handleMoveTo0(moveLst, path2D); + + final CTPath2DLineTo m = OF.createCTPath2DLineTo(); + m.setPt(fillPoint(vertIter.next(), xyPoints)); + moveLst.add(m); + path2D.lineTo(xyPoints[0], xyPoints[1]); + } + + private static void handleCurveTo(Iterator<byte[]> vertIter, int[] xyPoints, List<Object> moveLst, Path2D path2D) { + if (!vertIter.hasNext()) { + return; + } + handleMoveTo0(moveLst, path2D); + + final CTPath2DCubicBezierTo m = OF.createCTPath2DCubicBezierTo(); + List<CTAdjPoint2D> mLst = m.getPt(); + + int[] pts = new int[6]; + + for (int i=0; vertIter.hasNext() && i<3; i++) { + mLst.add(fillPoint(vertIter.next(), xyPoints)); + pts[i*2] = xyPoints[0]; + pts[i*2+1] = xyPoints[1]; + if (i == 2) { + moveLst.add(m); + path2D.curveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); + } + } + } + + /** + * Sometimes the path2D is not initialized - this initializes it with the 0,0 position + */ + private static void handleMoveTo0(List<Object> moveLst, Path2D path2D) { + if (path2D.getCurrentPoint() == null) { + final CTPath2DMoveTo m = OF.createCTPath2DMoveTo(); + + CTAdjPoint2D pt = OF.createCTAdjPoint2D(); + pt.setX("0"); + pt.setY("0"); + m.setPt(pt); + moveLst.add(m); + path2D.moveTo(0, 0); + } } - private void handleEscapeInfo(CTPath2D pathCT, Path2D path2D, byte[] segElem, Iterator<byte[]> vertIter) { - final ObjectFactory of = new ObjectFactory(); + private static void handleEscapeInfo(CTPath2D pathCT, Path2D path2D, byte[] segElem, Iterator<byte[]> vertIter) { HSLFFreeformShape.EscapeInfo ei = getEscapeInfo(segElem); if (ei == null) { return; @@ -376,7 +412,7 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, path2D.append(arc2D, true); - CTPath2DArcTo arcTo = of.createCTPath2DArcTo(); + CTPath2DArcTo arcTo = OF.createCTPath2DArcTo(); arcTo.setHR(d2s(bounds.getHeight()/2.0)); arcTo.setWR(d2s(bounds.getWidth()/2.0)); @@ -451,7 +487,7 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, } - private CTAdjPoint2D fillPoint(byte[] xyMaster, int[] xyPoints) { + private static CTAdjPoint2D fillPoint(byte[] xyMaster, int[] xyPoints) { if (xyMaster == null || xyPoints == null) { LOG.log(POILogger.WARN, "Master bytes or points not set - ignore point"); return null; @@ -477,7 +513,7 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape, } private static CTAdjPoint2D toPoint(int[] xyPoints) { - CTAdjPoint2D pt = new CTAdjPoint2D(); + CTAdjPoint2D pt = OF.createCTAdjPoint2D(); pt.setX(Integer.toString(xyPoints[0])); pt.setY(Integer.toString(xyPoints[1])); return pt; diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java index dd7afa4f9a..097342ffe8 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java @@ -62,7 +62,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H public final static double DEFAULT_LINE_WIDTH = 0.75; - private static final EscherPropertyTypes[] ADJUST_VALUES = { + protected static final EscherPropertyTypes[] ADJUST_VALUES = { EscherPropertyTypes.GEOMETRY__ADJUSTVALUE, EscherPropertyTypes.GEOMETRY__ADJUST2VALUE, EscherPropertyTypes.GEOMETRY__ADJUST3VALUE, @@ -79,7 +79,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H * Hyperlink */ protected HSLFHyperlink _hyperlink; - + /** * Create a SimpleShape object and initialize it from the supplied Record container. * @@ -563,8 +563,8 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H public HSLFShapePlaceholderDetails getPlaceholderDetails() { return new HSLFShapePlaceholderDetails(this); } - - + + @Override public Placeholder getPlaceholder() { return getPlaceholderDetails().getPlaceholder(); @@ -604,7 +604,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H public HSLFHyperlink getHyperlink(){ return _hyperlink; } - + @Override public HSLFHyperlink createHyperlink() { if (_hyperlink == null) { @@ -612,7 +612,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H } return _hyperlink; } - + /** * Sets the hyperlink - used when the document is parsed * @@ -621,7 +621,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H protected void setHyperlink(HSLFHyperlink link) { _hyperlink = link; } - + @Override public boolean isPlaceholder() { // currently we only identify TextShapes as placeholders |