From c2761bf4523deb05338672efeb2587107dd0b619 Mon Sep 17 00:00:00 2001 From: Nick Burch <nick@apache.org> Date: Sun, 7 Sep 2008 18:32:51 +0000 Subject: [PATCH] Patch from bug #45738 - Initial HWPF support for Office Art Shapes git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@692918 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 5 +- src/documentation/content/xdocs/status.xml | 5 +- .../src/org/apache/poi/hwpf/HWPFDocument.java | 12 +++ .../apache/poi/hwpf/model/ShapesTable.java | 54 ++++++++++++ .../org/apache/poi/hwpf/usermodel/Shape.java | 74 ++++++++++++++++ .../apache/poi/hwpf/data/WithArtShapes.doc | Bin 0 -> 53760 bytes .../apache/poi/hwpf/usermodel/TestShapes.java | 83 ++++++++++++++++++ 7 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 src/scratchpad/src/org/apache/poi/hwpf/model/ShapesTable.java create mode 100644 src/scratchpad/src/org/apache/poi/hwpf/usermodel/Shape.java create mode 100644 src/scratchpad/testcases/org/apache/poi/hwpf/data/WithArtShapes.doc create mode 100644 src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestShapes.java diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index fe18530168..57934cb893 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,8 +37,9 @@ <!-- Don't forget to update status.xml too! --> <release version="3.1.1-alpha1" date="2008-??-??"> - <action dev="POI-DEVELOPERS" type="fix">45720 Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action> - <action dev="POI-DEVELOPERS" type="fix">45728 Fix for SlideShow.reorderSlide in HSLF</action> + <action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action> + <action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action> + <action dev="POI-DEVELOPERS" type="fix">45728 - Fix for SlideShow.reorderSlide in HSLF</action> <action dev="POI-DEVELOPERS" type="add">Initial support for embedded movies and controls in HSLF</action> <action dev="POI-DEVELOPERS" type="fix">45358 - signed/unsigned error when parsing 3-d area refs, performance problem evaluating area refs, and ClassCastExcecption in IF()</action> <action dev="POI-DEVELOPERS" type="add">Support for HPBF Publisher hyperlinks, including during text extraction</action> diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 0cc173d6b8..9cbedfcaf0 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,8 +34,9 @@ <!-- Don't forget to update changes.xml too! --> <changes> <release version="3.1.1-alpha1" date="2008-??-??"> - <action dev="POI-DEVELOPERS" type="fix">45720 Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action> - <action dev="POI-DEVELOPERS" type="fix">45728 Fix for SlideShow.reorderSlide in HSLF</action> + <action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action> + <action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action> + <action dev="POI-DEVELOPERS" type="fix">45728 - Fix for SlideShow.reorderSlide in HSLF</action> <action dev="POI-DEVELOPERS" type="add">Initial support for embedded movies and controls in HSLF</action> <action dev="POI-DEVELOPERS" type="fix">45358 - signed/unsigned error when parsing 3-d area refs, performance problem evaluating area refs, and ClassCastExcecption in IF()</action> <action dev="POI-DEVELOPERS" type="add">Support for HPBF Publisher hyperlinks, including during text extraction</action> diff --git a/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java b/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java index daf1c8e172..f1898c082b 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java @@ -103,6 +103,9 @@ public class HWPFDocument extends POIDocument /** Escher Drawing Group information */ protected EscherRecordHolder _dgg; + /** Holds Office Art objects */ + protected ShapesTable _officeArts; + protected HWPFDocument() { super(null, null); @@ -252,6 +255,8 @@ public class HWPFDocument extends POIDocument // read in the pictures stream _pictures = new PicturesTable(this, _dataStream, _mainStream, _fspa, _dgg); + // And the art shapes stream + _officeArts = new ShapesTable(_tableStream, _fib); _st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin, _tpt, _cpSplit); _ss = new StyleSheet(_tableStream, _fib.getFcStshf()); @@ -392,6 +397,13 @@ public class HWPFDocument extends POIDocument public PicturesTable getPicturesTable() { return _pictures; } + + /** + * @return ShapesTable object, that is able to extract office are shapes from this document + */ + public ShapesTable getShapesTable() { + return _officeArts; + } /** * Writes out the word file that is represented by an instance of this class. diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/ShapesTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/ShapesTable.java new file mode 100644 index 0000000000..998ea2d8fe --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/ShapesTable.java @@ -0,0 +1,54 @@ +/* ==================================================================== + 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.hwpf.model; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.hwpf.usermodel.Shape; + +public class ShapesTable { + private List _shapes; + private List _shapesVisibili; //holds visible shapes + + public ShapesTable(byte [] tblStream, FileInformationBlock fib) { + PlexOfCps binTable = new PlexOfCps(tblStream, + fib.getFcPlcspaMom(), fib.getLcbPlcspaMom(), 26); + + _shapes = new ArrayList(); + _shapesVisibili = new ArrayList(); + + + for(int i = 0; i < binTable.length(); i++) { + GenericPropertyNode nodo = binTable.getProperty(i); + + Shape sh = new Shape(nodo); + _shapes.add(sh); + if(sh.isWithinDocument()) + _shapesVisibili.add(sh); + } + } + + public List getAllShapes() { + return _shapes; + } + + public List getVisibleShapes() { + return _shapesVisibili; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Shape.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Shape.java new file mode 100644 index 0000000000..1f798b620c --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Shape.java @@ -0,0 +1,74 @@ +/* ==================================================================== + 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.hwpf.usermodel; + +import org.apache.poi.hwpf.model.GenericPropertyNode; +import org.apache.poi.util.LittleEndian; + +public class Shape { + int _id, _left, _right, _top, _bottom; + /** + * true if the Shape bounds are within document (for + * example, it's false if the image left corner is outside the doc, like for + * embedded documents) + */ + boolean _inDoc; + + public Shape(GenericPropertyNode nodo) { + byte [] contenuto = nodo.getBytes(); + _id = LittleEndian.getInt(contenuto); + _left = LittleEndian.getInt(contenuto, 4); + _top = LittleEndian.getInt(contenuto, 8); + _right = LittleEndian.getInt(contenuto, 12); + _bottom = LittleEndian.getInt(contenuto, 16); + _inDoc = (_left >= 0 && _right >= 0 && _top >= 0 && _bottom >= +0); + } + + public int getId() { + return _id; + } + + public int getLeft() { + return _left; + } + + public int getRight() { + return _right; + } + + public int getTop() { + return _top; + } + + public int getBottom() { + return _bottom; + } + + public int getWidth() { + return _right - _left + 1; + } + + public int getHeight() { + return _bottom - _top + 1; + } + + public boolean isWithinDocument() { + return _inDoc; + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/WithArtShapes.doc b/src/scratchpad/testcases/org/apache/poi/hwpf/data/WithArtShapes.doc new file mode 100644 index 0000000000000000000000000000000000000000..27793c37a4605ddb4f206acf2134b088f8f5f4b7 GIT binary patch literal 53760 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 literal 0 HcmV?d00001 diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestShapes.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestShapes.java new file mode 100644 index 0000000000..273a03432b --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestShapes.java @@ -0,0 +1,83 @@ +/* +* 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.hwpf.usermodel; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.poi.hwpf.HWPFDocument; + +/** + * Test the shapes handling + */ +public class TestShapes extends TestCase { + private String dirname = System.getProperty("HWPF.testdata.path"); + + /** + * two shapes, second is a group + */ + public void testShapes() throws Exception { + HWPFDocument doc = new HWPFDocument(new FileInputStream(dirname + "/WithArtShapes.doc")); + + List shapes = doc.getShapesTable().getAllShapes(); + List vshapes = doc.getShapesTable().getVisibleShapes(); + + assertEquals(2, shapes.size()); + assertEquals(2, vshapes.size()); + + Shape s1 = (Shape)shapes.get(0); + Shape s2 = (Shape)shapes.get(1); + + assertEquals(3616, s1.getWidth()); + assertEquals(1738, s1.getHeight()); + assertEquals(true, s1.isWithinDocument()); + + assertEquals(4817, s2.getWidth()); + assertEquals(2164, s2.getHeight()); + assertEquals(true, s2.isWithinDocument()); + + + // Re-serialisze, check still there + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + doc.write(baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + doc = new HWPFDocument(bais); + + shapes = doc.getShapesTable().getAllShapes(); + vshapes = doc.getShapesTable().getVisibleShapes(); + + assertEquals(2, shapes.size()); + assertEquals(2, vshapes.size()); + + s1 = (Shape)shapes.get(0); + s2 = (Shape)shapes.get(1); + + assertEquals(3616, s1.getWidth()); + assertEquals(1738, s1.getHeight()); + assertEquals(true, s1.isWithinDocument()); + + assertEquals(4817, s2.getWidth()); + assertEquals(2164, s2.getHeight()); + assertEquals(true, s2.isWithinDocument()); + + } +}