diff options
author | Yegor Kozlov <yegor@apache.org> | 2008-04-16 08:44:07 +0000 |
---|---|---|
committer | Yegor Kozlov <yegor@apache.org> | 2008-04-16 08:44:07 +0000 |
commit | 8a1c9fc08c853498f9906b1296c30498a8c15b6c (patch) | |
tree | 55ae8f2ed7bb6d0fc58bdf1dc0a3bbece1aa85b5 /src | |
parent | 5319125c39204257b8f5ee22bc6a70ec94f107b3 (diff) | |
download | poi-8a1c9fc08c853498f9906b1296c30498a8c15b6c.tar.gz poi-8a1c9fc08c853498f9906b1296c30498a8c15b6c.zip |
Misc improvements in Freeform shape
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@648624 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rwxr-xr-x | src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java | 110 | ||||
-rwxr-xr-x | src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java | 80 |
2 files changed, 180 insertions, 10 deletions
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java b/src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java index e34d651b3d..28e41f8b09 100755 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java @@ -19,9 +19,11 @@ package org.apache.poi.hslf.model; import org.apache.poi.ddf.*;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger;
+import org.apache.poi.util.HexDump;
import java.awt.geom.*;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* A "Freeform" shape.
@@ -33,6 +35,16 @@ import java.util.ArrayList; * @author Yegor Kozlov
*/
public class Freeform extends AutoShape {
+
+ public static final byte[] SEGMENTINFO_MOVETO = new byte[]{0x00, 0x40};
+ public static final byte[] SEGMENTINFO_LINETO = new byte[]{0x00, (byte)0xAC};
+ public static final byte[] SEGMENTINFO_ESCAPE = new byte[]{0x01, 0x00};
+ public static final byte[] SEGMENTINFO_ESCAPE2 = new byte[]{0x01, 0x20};
+ public static final byte[] SEGMENTINFO_CUBICTO = new byte[]{0x00, (byte)0xAD};
+ public static final byte[] SEGMENTINFO_CUBICTO2 = new byte[]{0x00, (byte)0xB3}; //OpenOffice inserts 0xB3 instead of 0xAD.
+ public static final byte[] SEGMENTINFO_CLOSE = new byte[]{0x01, (byte)0x60};
+ public static final byte[] SEGMENTINFO_END = new byte[]{0x00, (byte)0x80};
+
/**
* Create a Freeform object and initialize it from the supplied Record container.
*
@@ -82,36 +94,37 @@ public class Freeform extends AutoShape { switch (type) {
case PathIterator.SEG_MOVETO:
pntInfo.add(new Point2D.Double(vals[0], vals[1]));
- segInfo.add(new byte[]{0x00, 0x40});
+ segInfo.add(SEGMENTINFO_MOVETO);
break;
case PathIterator.SEG_LINETO:
pntInfo.add(new Point2D.Double(vals[0], vals[1]));
- segInfo.add(new byte[]{0x00, (byte)0xAC});
- segInfo.add(new byte[]{0x01, 0x00 });
+ segInfo.add(SEGMENTINFO_LINETO);
+ segInfo.add(SEGMENTINFO_ESCAPE);
break;
case PathIterator.SEG_CUBICTO:
pntInfo.add(new Point2D.Double(vals[0], vals[1]));
pntInfo.add(new Point2D.Double(vals[2], vals[3]));
pntInfo.add(new Point2D.Double(vals[4], vals[5]));
- segInfo.add(new byte[]{0x00, (byte)0xAD});
- segInfo.add(new byte[]{0x01, 0x20 });
+ segInfo.add(SEGMENTINFO_CUBICTO);
+ segInfo.add(SEGMENTINFO_ESCAPE2);
break;
case PathIterator.SEG_QUADTO:
+ //TODO: figure out how to convert SEG_QUADTO into SEG_CUBICTO
logger.log(POILogger.WARN, "SEG_QUADTO is not supported");
break;
case PathIterator.SEG_CLOSE:
pntInfo.add(pntInfo.get(0));
- segInfo.add(new byte[]{0x00, (byte)0xAC});
- segInfo.add(new byte[]{0x01, 0x00 });
- segInfo.add(new byte[]{0x00, (byte)0xAC});
- segInfo.add(new byte[]{0x01, (byte)0x60});
+ segInfo.add(SEGMENTINFO_LINETO);
+ segInfo.add(SEGMENTINFO_ESCAPE);
+ segInfo.add(SEGMENTINFO_LINETO);
+ segInfo.add(SEGMENTINFO_CLOSE);
isClosed = true;
break;
}
it.next();
}
- if(!isClosed) segInfo.add(new byte[]{0x00, (byte)0xAC});
+ if(!isClosed) segInfo.add(SEGMENTINFO_LINETO);
segInfo.add(new byte[]{0x00, (byte)0x80});
EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
@@ -147,4 +160,81 @@ public class Freeform extends AutoShape { setAnchor(bounds);
}
+
+ /**
+ * Gets the freeform path
+ *
+ * @return the freeform path
+ */
+ public GeneralPath getPath(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 0x4));
+
+ EscherArrayProperty verticesProp = (EscherArrayProperty)getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__VERTICES + 0x4000));
+ if(verticesProp == null) verticesProp = (EscherArrayProperty)getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__VERTICES));
+
+ EscherArrayProperty segmentsProp = (EscherArrayProperty)getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__SEGMENTINFO + 0x4000));
+ if(segmentsProp == null) segmentsProp = (EscherArrayProperty)getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__SEGMENTINFO));
+
+ //sanity check
+ if(verticesProp == null) {
+ logger.log(POILogger.WARN, "Freeform is missing GEOMETRY__VERTICES ");
+ return null;
+ }
+ if(segmentsProp == null) {
+ logger.log(POILogger.WARN, "Freeform is missing GEOMETRY__SEGMENTINFO ");
+ return null;
+ }
+
+ Rectangle2D bounds = getAnchor2D();
+ float right = (float)bounds.getX();
+ float bottom = (float)bounds.getY();
+
+ GeneralPath path = new GeneralPath();
+ int numPoints = verticesProp.getNumberOfElementsInArray();
+ int numSegments = segmentsProp.getNumberOfElementsInArray();
+ for (int i = 0, j = 0; i < numSegments && j < numPoints; i++) {
+ byte[] elem = segmentsProp.getElement(i);
+ if(Arrays.equals(elem, SEGMENTINFO_MOVETO)){
+ byte[] p = verticesProp.getElement(j++);
+ short x = LittleEndian.getShort(p, 0);
+ short y = LittleEndian.getShort(p, 2);
+ path.moveTo(
+ ((float)x*POINT_DPI/MASTER_DPI + right),
+ ((float)y*POINT_DPI/MASTER_DPI + bottom));
+ } else if (Arrays.equals(elem, SEGMENTINFO_CUBICTO) || Arrays.equals(elem, SEGMENTINFO_CUBICTO2)){
+ i++;
+ byte[] p1 = verticesProp.getElement(j++);
+ short x1 = LittleEndian.getShort(p1, 0);
+ short y1 = LittleEndian.getShort(p1, 2);
+ byte[] p2 = verticesProp.getElement(j++);
+ short x2 = LittleEndian.getShort(p2, 0);
+ short y2 = LittleEndian.getShort(p2, 2);
+ byte[] p3 = verticesProp.getElement(j++);
+ short x3 = LittleEndian.getShort(p3, 0);
+ short y3 = LittleEndian.getShort(p3, 2);
+ path.curveTo(
+ ((float)x1*POINT_DPI/MASTER_DPI + right), ((float)y1*POINT_DPI/MASTER_DPI + bottom),
+ ((float)x2*POINT_DPI/MASTER_DPI + right), ((float)y2*POINT_DPI/MASTER_DPI + bottom),
+ ((float)x3*POINT_DPI/MASTER_DPI + right), ((float)y3*POINT_DPI/MASTER_DPI + bottom));
+
+ } else if (Arrays.equals(elem, SEGMENTINFO_LINETO)){
+ i++;
+ byte[] pnext = segmentsProp.getElement(i);
+ if(Arrays.equals(pnext, SEGMENTINFO_ESCAPE)){
+ if(j + 1 < numPoints){
+ byte[] p = verticesProp.getElement(j++);
+ short x = LittleEndian.getShort(p, 0);
+ short y = LittleEndian.getShort(p, 2);
+ path.lineTo(
+ ((float)x*POINT_DPI/MASTER_DPI + right), ((float)y*POINT_DPI/MASTER_DPI + bottom));
+ }
+ } else if (Arrays.equals(pnext, SEGMENTINFO_CLOSE)){
+ path.closePath();
+ }
+ }
+ }
+
+ return path;
+ }
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java new file mode 100755 index 0000000000..5e7e7cc4b7 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java @@ -0,0 +1,80 @@ +/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.hslf.model;
+
+import junit.framework.TestCase;
+import org.apache.poi.hslf.usermodel.SlideShow;
+import org.apache.poi.hslf.usermodel.RichTextRun;
+import org.apache.poi.hslf.HSLFSlideShow;
+
+import java.awt.*;
+import java.awt.Rectangle;
+import java.awt.geom.*;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Test Freeform object.
+ * The Freeform shape is constructed from java.awt.GeneralPath.
+ * Check that the get/set path accessors are consistent.
+ * (TODO: verification of Bezier curves is more difficult due to rounding error. Figure out a test approach for that)
+ *
+ * @author Yegor Kozlov
+ */
+public class TestFreeform extends TestCase {
+
+ public void testClosedPath() throws Exception {
+
+ GeneralPath path1 = new GeneralPath();
+ path1.moveTo(100, 100);
+ path1.lineTo(200, 100);
+ path1.lineTo(200, 200);
+ path1.lineTo(100, 200);
+ path1.closePath();
+
+ Freeform p = new Freeform();
+ p.setPath(path1);
+
+ GeneralPath path2 = p.getPath();
+ assertTrue(new Area(path1).equals(new Area(path2)));
+ }
+
+ public void testLine() throws Exception {
+
+ GeneralPath path1 = new GeneralPath(new Line2D.Double(100, 100, 200, 100));
+
+ Freeform p = new Freeform();
+ p.setPath(path1);
+
+ GeneralPath path2 = p.getPath();
+ assertTrue(new Area(path1).equals(new Area(path2)));
+ }
+
+ public void testRectangle() throws Exception {
+
+ GeneralPath path1 = new GeneralPath(new Rectangle2D.Double(100, 100, 200, 50));
+
+ Freeform p = new Freeform();
+ p.setPath(path1);
+
+ GeneralPath path2 = p.getPath();
+ assertTrue(new Area(path1).equals(new Area(path2)));
+ }
+}
|