From 4d59f7214184e9a4ef6258b706a4ab4ea518d539 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Tue, 22 May 2012 12:47:11 +0000 Subject: [PATCH 01/32] branch for gsoc2012 git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1341450 13f79535-47bb-0310-9956-ffa450edef68 From c3739d5be475ad449fe5cd4c8379462e95b0accc Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Mon, 28 May 2012 12:15:16 +0000 Subject: [PATCH 02/32] Bugzilla 53302: fixed EscherAggregate to correctly handle Continue records in drawing blocks git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1343218 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../apache/poi/hssf/model/InternalSheet.java | 46 +- .../poi/hssf/record/EscherAggregate.java | 24 + .../poi/hssf/model/TestDrawingAggregate.java | 1802 +++++++++++++++++ test-data/spreadsheet/45129.xls | Bin 0 -> 47616 bytes test-data/spreadsheet/dg-text.xls | Bin 0 -> 33792 bytes 6 files changed, 1836 insertions(+), 37 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java create mode 100755 test-data/spreadsheet/45129.xls create mode 100755 test-data/spreadsheet/dg-text.xls diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index d73559ac54..d27c150ac1 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 53302 - Fixed EscherAggregate to correctly handle Continue records in drawing blocks 53025 - Updatad documentation and example on using Data Validations 53227 - Corrected AddDimensionedImage.java to support XSSF/SXSSF 53058 - Utility for representing drawings contained in a binary Excel file as a XML tree diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index cbacbc0ca1..75ea355e50 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -21,43 +21,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.apache.poi.hssf.record.BOFRecord; -import org.apache.poi.hssf.record.CFHeaderRecord; -import org.apache.poi.hssf.record.CalcCountRecord; -import org.apache.poi.hssf.record.CalcModeRecord; -import org.apache.poi.hssf.record.CellValueRecordInterface; -import org.apache.poi.hssf.record.ColumnInfoRecord; -import org.apache.poi.hssf.record.DVALRecord; -import org.apache.poi.hssf.record.DefaultColWidthRecord; -import org.apache.poi.hssf.record.DefaultRowHeightRecord; -import org.apache.poi.hssf.record.DeltaRecord; -import org.apache.poi.hssf.record.DimensionsRecord; -import org.apache.poi.hssf.record.DrawingRecord; -import org.apache.poi.hssf.record.EOFRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.FeatHdrRecord; -import org.apache.poi.hssf.record.FeatRecord; -import org.apache.poi.hssf.record.GridsetRecord; -import org.apache.poi.hssf.record.GutsRecord; -import org.apache.poi.hssf.record.IndexRecord; -import org.apache.poi.hssf.record.IterationRecord; -import org.apache.poi.hssf.record.MergeCellsRecord; -import org.apache.poi.hssf.record.NoteRecord; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.PaneRecord; -import org.apache.poi.hssf.record.PrintGridlinesRecord; -import org.apache.poi.hssf.record.PrintHeadersRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.RecordBase; -import org.apache.poi.hssf.record.RefModeRecord; -import org.apache.poi.hssf.record.RowRecord; -import org.apache.poi.hssf.record.SCLRecord; -import org.apache.poi.hssf.record.SaveRecalcRecord; -import org.apache.poi.hssf.record.SelectionRecord; -import org.apache.poi.hssf.record.TextObjectRecord; -import org.apache.poi.hssf.record.UncalcedRecord; -import org.apache.poi.hssf.record.WSBoolRecord; -import org.apache.poi.hssf.record.WindowTwoRecord; +import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate; import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate; import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; @@ -1553,6 +1517,14 @@ public final class InternalSheet { { loc += 2; if (records.get( loc ) instanceof NoteRecord) loc ++; + while ( loc + 1 < records.size() + && records.get( loc ) instanceof ContinueRecord + && (records.get( loc + 1 ) instanceof ObjRecord || + records.get( loc + 1 ) instanceof TextObjectRecord) ) + { + loc += 2; + if (records.get( loc ) instanceof NoteRecord) loc ++; + } } int endloc = loc-1; diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 6cbec15016..0ac0d04729 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -373,6 +373,13 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { { dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length; loc += 2; + while ( loc + 1 < records.size() + && sid( records, loc ) == ContinueRecord.sid + && isObjectRecord( records, loc + 1 ) ) + { + dataSize += ( (ContinueRecord) records.get( loc ) ).getData().length; + loc += 2; + } } // Create one big buffer @@ -387,6 +394,15 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length ); offset += drawingRecord.getData().length; loc += 2; + while ( loc + 1 < records.size() + && sid( records, loc ) == ContinueRecord.sid + && isObjectRecord( records, loc + 1 ) ) + { + ContinueRecord continueRecord = (ContinueRecord) records.get( loc ); + System.arraycopy( continueRecord.getData(), 0, buffer, offset, continueRecord.getData().length ); + offset += continueRecord.getData().length; + loc += 2; + } } // Decode the shapes @@ -411,6 +427,14 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { Record objRecord = (Record) records.get( loc + 1 ); agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord ); loc += 2; + while ( loc + 1 < records.size() + && sid( records, loc ) == ContinueRecord.sid + && isObjectRecord( records, loc + 1 ) ) + { + objRecord = (Record) records.get( loc + 1 ); + agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord ); + loc += 2; + } } return agg; diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java new file mode 100644 index 0000000000..43fe4b482c --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -0,0 +1,1802 @@ +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherDggRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.ContinueRecord; +import org.apache.poi.hssf.record.DrawingRecord; +import org.apache.poi.hssf.record.EOFRecord; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordBase; +import org.apache.poi.hssf.record.RecordFactory; +import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.hssf.record.WindowTwoRecord; +import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFTestHelper; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.util.HexRead; + +import java.io.ByteArrayInputStream; +import java.util.List; + +/** + * @author Yegor Kozlov + * @author Evgeniy Berlog + */ +public class TestDrawingAggregate extends TestCase { + /** + * test reading drawing aggregate from a test file from Bugzilla 45129 + */ + public void test45129() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("45129.xls"); + HSSFSheet sh = wb.getSheetAt(0); + + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + List records = isheet.getRecords(); + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 394, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(19, 388); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == TextObjectRecord.sid); + } + + // the first record after the drawing block + assertTrue( + "records.get(389) is expected to be Window2", + records.get(389) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 388] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate ag = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 25, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); + + // TODO figure out why serialization fails + // byte[] bytes = ag.serialize(); + } + + public void testFileWithPictures() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ContinueRecordProblem.xls"); + HSSFSheet sh = wb.getSheetAt(0); + + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + List records = isheet.getRecords(); + + for (RecordBase recordBase : records) { + System.out.println(recordBase.toString()); + } + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 315, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(21) is expected to be RowRecordsAggregate but was " + records.get(21).getClass().getSimpleName(), + records.get(21) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(22, 299); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == TextObjectRecord.sid); + } + + // the first record after the drawing block + assertTrue( + "records.get(300) is expected to be Window2", + records.get(300) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 388] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate ag = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 38, records.size()); + assertTrue( + "records.get(21) is expected to be RowRecordsAggregate but was " + records.get(21).getClass().getSimpleName(), + records.get(21) instanceof RowRecordsAggregate); + assertTrue("records.get(22) is expected to be EscherAggregate but was " + records.get(22).getClass().getSimpleName(), + records.get(22) instanceof EscherAggregate); + assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(), + records.get(23) instanceof WindowTwoRecord); + } + + public void testUnhandledContinue() { + String data = + " EC 00 1C 08 0F 00 02 F0 66 27 00 " + + " 00 10 00 08 F0 08 00 00 00 06 00 00 00 13 04 00 " + + " 00 0F 00 03 F0 4E 27 00 00 0F 00 04 F0 28 00 00 " + + " 00 01 00 09 F0 10 00 00 00 00 00 00 00 00 00 00 " + + " 00 00 00 00 00 00 00 00 00 02 00 0A F0 08 00 00 " + + " 00 00 04 00 00 05 00 00 00 0F 00 04 F0 CC 07 00 " + + " 00 A2 0C 0A F0 08 00 00 00 0F 04 00 00 00 0A 00 " + + " 00 93 00 0B F0 4A 00 00 00 7F 00 00 00 04 00 80 " + + " 00 C0 D5 9A 02 85 00 02 00 00 00 8B 00 02 00 00 " + + " 00 BF 00 1A 00 1F 00 BF 01 01 00 11 00 FF 01 00 " + + " 00 08 00 80 C3 14 00 00 00 BF 03 00 00 02 00 54 " + + " 00 65 00 78 00 74 00 42 00 6F 00 78 00 20 00 31 " + + " 00 00 00 13 00 22 F1 38 07 00 00 A9 C3 32 07 00 " + + " 00 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 F0 " + + " F7 8A BB FD 00 00 00 E2 01 00 00 13 00 00 00 5B " + + " 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 " + + " 6D 6C 94 91 CD 4A C4 30 10 C7 EF 82 EF 10 E6 2A " + + " 6D AA 07 11 69 BA 07 AB 47 15 5D 1F 60 48 A6 6D " + + " D8 36 09 99 58 77 DF DE 74 3F 2E E2 0A 1E 67 E6 " + + " FF F1 23 A9 57 DB 69 14 33 45 B6 DE 29 B8 2E 2B " + + " 10 E4 B4 37 D6 F5 0A 3E D6 4F C5 1D 08 4E E8 0C " + + " 8E DE 91 82 1D 31 AC 9A CB 8B 7A BD 0B C4 22 BB " + + " 1D 2B 18 52 0A F7 52 B2 1E 68 42 2E 7D 20 97 2F " + + " 9D 8F 13 A6 3C C6 5E 06 D4 1B EC 49 DE 54 D5 AD " + + " D4 DE 25 72 A9 48 4B 06 34 75 4B 1D 7E 8E 49 3C " + + " 6E F3 FA 40 12 69 64 10 0F 07 E1 D2 A5 00 43 18 " + + " AD C6 94 49 E5 EC CC 8F 96 E2 D8 50 66 E7 5E C3 " + + " 83 0D 7C 95 31 40 FE DA B0 5C CE 17 1C 7D 2F F9 " + + " 69 A2 35 24 5E 31 A6 67 9C 32 86 34 91 25 0F 18 " + + " 28 6B CA BF 53 16 CC 89 0B DF 75 56 53 D9 46 7E " + + " 5F 7C 27 A8 73 E1 C6 7F B9 48 F3 7F B3 DB 6C 7B " + + " A3 F9 94 2E F7 3F D4 7C 03 00 00 FF FF 03 00 50 " + + " 4B 03 04 14 00 06 00 08 00 00 00 21 00 31 DD 5F " + + " 61 D2 00 00 00 8F 01 00 00 0B 00 00 00 5F 72 65 " + + " 6C 73 2F 2E 72 65 6C 73 A4 90 C1 6A C3 30 0C 86 " + + " EF 83 BD 83 D1 BD 71 DA 43 19 A3 4E 6F 85 5E 4B " + + " 07 BB 0A 5B 49 4C 63 CB 58 26 6D DF BE A6 30 58 " + + " 46 6F 3B EA 17 FA 3E F1 EF F6 B7 30 A9 99 B2 78 " + + " 8E 06 D6 4D 0B 8A A2 65 E7 E3 60 E0 EB 7C 58 7D " + + " 80 92 82 D1 E1 C4 91 0C DC 49 60 DF BD BF ED 4E " + + " 34 61 A9 47 32 FA 24 AA 52 A2 18 18 4B 49 9F 5A " + + " 8B 1D 29 A0 34 9C 28 D6 4D CF 39 60 A9 63 1E 74 " + + " 42 7B C1 81 F4 A6 6D B7 3A FF 66 40 B7 60 AA A3 " + + " 33 90 8F 6E 03 EA 7C 4F D5 FC 87 1D BC CD 2C DC " + + " 97 C6 72 D0 DC F7 DE BE A2 6A C7 D7 78 A2 B9 52 " + + " 30 0F 54 0C B8 2C CF 30 D3 DC D4 E7 40 BF F6 AE " + + " FF E9 95 11 13 7D 57 FE 42 FC 4C AB F5 C7 AC 17 " + + " 35 76 0F 00 00 00 FF FF 03 00 50 4B 03 04 14 00 " + + " 06 00 08 00 00 00 21 00 AE B1 05 56 77 02 00 00 " + + " 1B 07 00 00 10 00 00 00 64 72 73 2F 73 68 61 70 " + + " 65 78 6D 6C 2E 78 6D 6C BC 55 4B 6F DB 30 0C BE " + + " 0F D8 7F 10 74 4F FD 58 9D 87 11 BB E8 52 74 97 " + + " 61 0D 92 E6 07 A8 B2 9C 18 93 25 43 52 13 A7 BF " + + " 7E A4 E4 A4 5D 0F 3B 34 43 2F 0A 43 4A FC C8 8F " + + " 0F CF 6F FA 56 92 BD 30 B6 D1 AA A0 C9 55 4C 89 " + + " 50 5C 57 8D DA 16 74 F3 78 3F 9A 52 62 1D 53 15 " + + " 93 5A 89 82 1E 85 A5 37 E5 D7 2F F3 BE 32 39 53 " + + " 7C A7 0D 01 17 CA E6 A0 28 E8 CE B9 2E 8F 22 CB " + + " 77 A2 65 F6 4A 77 42 81 B5 D6 A6 65 0E FE 9A 6D " + + " 54 19 76 00 E7 AD 8C D2 38 1E 47 B6 33 82 55 76 " + + " 27 84 BB 0B 16 5A 7A DF 80 B6 10 52 DE 7A 88 A0 " + + " AA 8D 6E 83 C4 B5 2C 93 79 84 31 A0 E8 1F 80 F0 " + + " 50 D7 65 1A CF B2 2C 3E DB 50 E5 CD 46 1F CA 6F " + + " 41 8D E2 49 87 F6 64 1A CF 26 D9 D9 E6 9F 78 DF " + + " AF 80 A2 77 84 F7 05 CD D2 2C 8D 81 12 7E 2C 68 " + + " 3A BE CE C6 31 8D 82 2F DB 91 96 71 A3 0B 4A 89 " + + " 83 EB B2 51 BF 41 0E 46 B5 5F 77 4B 13 64 FE 6B " + + " BF 34 A4 A9 C0 01 25 8A B5 40 EA 23 DC FF AE 7B " + + " 92 9C 9C C1 1D 7C 40 5C 0F 6A 28 0B EA 7D 44 6F " + + " 1D 59 EF 92 E5 7D 6D DA A1 06 EC 03 15 68 59 A3 " + + " 20 4C 96 EB BA 26 00 36 4D 66 49 06 6D 00 19 4E " + + " B2 F4 7A 92 21 38 CB FF CD 40 14 C2 C0 8B 9D B1 " + + " EE 87 D0 17 87 44 D0 51 41 8D E0 CE 87 C7 F6 3F " + + " AD 43 1E 5E 21 10 4E E9 FB 46 CA 4B F3 3F F1 1B " + + " 38 C5 BE B2 EE 28 05 02 48 B5 12 40 8C EF F1 0F " + + " F3 0B F5 06 6A 63 9F 88 E5 66 FB B4 90 86 C0 BC " + + " 00 CF 30 67 70 3E E1 19 B2 F3 80 88 5C 43 62 9F " + + " 8C 3D 40 22 BA A8 6B A0 FE 93 F1 CF A0 3E 7F AD " + + " FE 1F 7E DB 28 6D 06 FE 61 39 09 2C C0 9E C9 82 " + + " BA 3E 8C 17 F0 1D F0 86 51 1B 1A 00 7B 01 C7 B0 " + + " 3A 62 48 4F F0 0B 73 79 69 37 C0 C2 75 0F 70 D4 " + + " 52 1F 0A CA 65 D3 51 02 9B F4 E5 BD EE 60 58 57 " + + " 50 05 BB 90 12 E3 E4 42 43 BC D0 2C 61 EF 42 E8 " + + " 21 9F EE F6 D9 C1 14 0C C3 11 42 C4 60 A5 75 6B " + + " EC E2 4B C3 F5 F3 DF 5D EA 05 23 32 FE 00 02 25 " + + " C3 EF 8B 50 A3 CD 1A BE 2F 2F B0 E2 92 D8 F7 3F " + + " CB 5D 89 EB 73 04 EB 1D 65 3C FD 2B A1 AA 25 33 " + + " 6C 75 7E 6C 9E 47 AB CD DF 8F 71 35 0C D5 3B 95 " + + " CC 6F 4D 0B 5A FF AD 90 8D 50 EE 8E 39 76 9A F7 " + + " 77 5F 19 7F 3B B0 5B FE 01 00 00 FF FF 03 00 50 " + + " 4B 03 04 14 00 06 00 08 00 00 00 21 00 44 8B 69 " + + " 1E 2C 01 00 00 AB 01 00 00 0F 00 00 00 64 72 73 " + + " 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C 5C 50 D1 4E " + + " C2 30 14 7D 37 F1 1F 9A 6B E2 9B 74 0C 36 07 52 " + + " C8 62 42 C4 04 D1 21 89 AF 65 6D D9 E2 DA CE B6 " + + " C0 F0 EB ED 46 0C C6 C7 73 EE 39 E7 DE 73 27 B3 " + + " 46 56 E8 C0 8D 2D B5 22 D0 EF 05 80 B8 CA 35 2B " + + " D5 8E C0 E6 7D 7E 97 00 B2 8E 2A 46 2B AD 38 81 " + + " 13 B7 30 9B 5E 5F 4D E8 98 E9 A3 CA F8 61 ED 76 " + + " C8 87 28 3B A6 04 0A E7 EA 31 C6 36 2F B8 A4 B6 " + + " A7 6B AE FC 4C 68 23 A9 F3 D0 EC 30 33 F4 E8 C3 " + + " 65 85 C3 20 88 B1 A4 A5 F2 1B 0A 5A F3 C7 82 E7 " + + " 9F EB BD 24 B0 64 E2 E5 63 58 CE 9F A9 F8 4A 17 " + + " C3 2C 89 0E AF 2C 22 E4 F6 A6 49 1F 00 39 DE B8 " + + " 8B B8 DE AB 55 B8 5C 6E DF 36 E9 AF A0 8B 5B 30 " + + " 02 21 20 F1 74 DA 9A 92 65 D4 3A 6E 08 F8 7E BE " + + " AD 6F 0A 53 5F A1 A9 52 95 17 DA 20 91 71 5B 7E " + + " FB 7E 67 5E 18 2D 91 D1 47 02 03 40 B9 AE 5A BE " + + " C5 2B 21 2C 77 1E 25 C1 E8 3E EA 46 BF 54 18 8C " + + " A2 28 00 DC C6 3A 7D 36 9F 15 DD 19 7F CC 71 1C " + + " FF F3 F6 C3 41 12 46 AD 17 5F 6E EA C0 E5 C7 D3 " + + " 1F 00 00 00 FF FF 03 00 50 4B 01 02 2D 00 14 00 " + + " 06 00 08 00 00 00 21 00 F0 F7 8A BB FD 00 00 00 " + + " E2 01 00 00 13 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 00 00 00 00 00 5B 43 6F 6E 74 65 6E 74 5F 54 " + + " 79 70 65 73 5D 2E 78 6D 6C 50 4B 01 02 2D 00 14 " + + " 00 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 00 " + + " 00 8F 01 00 00 0B 00 00 00 00 00 00 00 00 00 00 " + + " 00 00 00 2E 01 00 00 5F 72 65 6C 73 2F 2E 72 65 " + + " 6C 73 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 " + + " 21 00 AE B1 05 56 77 02 00 00 1B 07 00 00 10 00 " + + " 00 00 00 00 00 00 00 00 00 00 00 00 29 02 00 00 " + + " 64 72 73 2F 73 68 61 70 65 78 6D 6C 2E 78 6D 6C " + + " 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 21 00 " + + " 44 8B 69 1E 2C 01 00 00 AB 01 00 00 0F 00 00 00 " + + " 00 00 00 00 00 00 00 00 00 00 CE 04 00 00 64 72 " + + " 73 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C 50 4B 05 " + + " 06 00 00 00 00 04 00 04 00 F5 00 00 00 27 06 00 " + + " 00 00 00 00 00 10 F0 12 00 00 00 02 00 01 00 60 " + + " 01 03 00 F3 00 02 00 D0 00 05 00 5A 00 00 00 11 " + + " F0 00 00 00 00 5D 00 1A 00 15 00 12 00 06 00 0F " + + " 00 11 60 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 00 00 EC 00 08 00 00 00 0D F0 00 00 00 00 B6 " + + " 01 12 00 12 02 00 00 00 00 00 00 00 00 06 00 10 " + + " 00 00 00 00 00 3C 00 07 00 00 74 65 78 74 2D 31 " + + " 3C 00 10 00 00 00 16 00 00 00 00 00 06 00 00 00 " + + " 00 00 00 00 EC 00 CB 07 0F 00 04 F0 CB 07 00 00 " + + " A2 0C 0A F0 08 00 00 00 10 04 00 00 00 0A 00 00 " + + " 93 00 0B F0 4A 00 00 00 7F 00 00 00 04 00 80 00 " + + " 00 65 53 02 85 00 02 00 00 00 8B 00 02 00 00 00 " + + " BF 00 1A 00 1F 00 BF 01 01 00 11 00 FF 01 00 00 " + + " 08 00 80 C3 14 00 00 00 BF 03 00 00 02 00 54 00 " + + " 65 00 78 00 74 00 42 00 6F 00 78 00 20 00 32 00 " + + " 00 00 13 00 22 F1 37 07 00 00 A9 C3 31 07 00 00 " + + " 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 F0 F7 " + + " 8A BB FD 00 00 00 E2 01 00 00 13 00 00 00 5B 43 " + + " 6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D " + + " 6C 94 91 CD 4A C4 30 10 C7 EF 82 EF 10 E6 2A 6D " + + " AA 07 11 69 BA 07 AB 47 15 5D 1F 60 48 A6 6D D8 " + + " 36 09 99 58 77 DF DE 74 3F 2E E2 0A 1E 67 E6 FF " + + " F1 23 A9 57 DB 69 14 33 45 B6 DE 29 B8 2E 2B 10 " + + " E4 B4 37 D6 F5 0A 3E D6 4F C5 1D 08 4E E8 0C 8E " + + " DE 91 82 1D 31 AC 9A CB 8B 7A BD 0B C4 22 BB 1D " + + " 2B 18 52 0A F7 52 B2 1E 68 42 2E 7D 20 97 2F 9D " + + " 8F 13 A6 3C C6 5E 06 D4 1B EC 49 DE 54 D5 AD D4 " + + " DE 25 72 A9 48 4B 06 34 75 4B 1D 7E 8E 49 3C 6E " + + " F3 FA 40 12 69 64 10 0F 07 E1 D2 A5 00 43 18 AD " + + " C6 94 49 E5 EC CC 8F 96 E2 D8 50 66 E7 5E C3 83 " + + " 0D 7C 95 31 40 FE DA B0 5C CE 17 1C 7D 2F F9 69 " + + " A2 35 24 5E 31 A6 67 9C 32 86 34 91 25 0F 18 28 " + + " 6B CA BF 53 16 CC 89 0B DF 75 56 53 D9 46 7E 5F " + + " 7C 27 A8 73 E1 C6 7F B9 48 F3 7F B3 DB 6C 7B A3 " + + " F9 94 2E F7 3F D4 7C 03 00 00 FF FF 03 00 50 4B " + + " 03 04 14 00 06 00 08 00 00 00 21 00 31 DD 5F 61 " + + " D2 00 00 00 8F 01 00 00 0B 00 00 00 5F 72 65 6C " + + " 73 2F 2E 72 65 6C 73 A4 90 C1 6A C3 30 0C 86 EF " + + " 83 BD 83 D1 BD 71 DA 43 19 A3 4E 6F 85 5E 4B 07 " + + " BB 0A 5B 49 4C 63 CB 58 26 6D DF BE A6 30 58 46 " + + " 6F 3B EA 17 FA 3E F1 EF F6 B7 30 A9 99 B2 78 8E " + + " 06 D6 4D 0B 8A A2 65 E7 E3 60 E0 EB 7C 58 7D 80 " + + " 92 82 D1 E1 C4 91 0C DC 49 60 DF BD BF ED 4E 34 " + + " 61 A9 47 32 FA 24 AA 52 A2 18 18 4B 49 9F 5A 8B " + + " 1D 29 A0 34 9C 28 D6 4D CF 39 60 A9 63 1E 74 42 " + + " 7B C1 81 F4 A6 6D B7 3A FF 66 40 B7 60 AA A3 33 " + + " 90 8F 6E 03 EA 7C 4F D5 FC 87 1D BC CD 2C DC 97 " + + " C6 72 D0 DC F7 DE BE A2 6A C7 D7 78 A2 B9 52 30 " + + " 0F 54 0C B8 2C CF 30 D3 DC D4 E7 40 BF F6 AE FF " + + " E9 95 11 13 7D 57 FE 42 FC 4C AB F5 C7 AC 17 35 " + + " 76 0F 00 00 00 FF FF 03 00 50 4B 03 04 14 00 06 " + + " 00 08 00 00 00 21 00 99 C9 E2 87 75 02 00 00 1B " + + " 07 00 00 10 00 00 00 64 72 73 2F 73 68 61 70 65 " + + " 78 6D 6C 2E 78 6D 6C BC 55 CD 6E E2 30 10 BE AF " + + " D4 77 B0 7C A7 F9 E9 82 20 C2 A9 5A AA EE 65 B5 " + + " 45 50 1E C0 24 0E 44 EB D8 91 ED 42 E8 D3 EF 8C " + + " 9D D0 6E 0F 7B 28 AB 5E 1C 67 C6 33 DF F8 9B 1F " + + " CF 6F BB 46 92 83 30 B6 D6 8A D1 E4 3A A6 44 A8 " + + " 42 97 B5 DA 31 BA 79 7E 1C 4D 29 B1 8E AB 92 4B " + + " AD 04 A3 27 61 E9 6D 7E F5 6D DE 95 26 E3 AA D8 " + + " 6B 43 C0 85 B2 19 08 18 DD 3B D7 66 51 64 8B BD " + + " 68 B8 BD D6 AD 50 A0 AD B4 69 B8 83 5F B3 8B 4A " + + " C3 8F E0 BC 91 51 1A C7 93 C8 B6 46 F0 D2 EE 85 " + + " 70 0F 41 43 73 EF 1B D0 16 42 CA 3B 0F 11 44 95 " + + " D1 4D D8 15 5A E6 C9 3C C2 18 70 EB 0D 60 F3 54 " + + " 55 79 1A CF C6 E3 F8 AC 43 91 57 1B 7D CC 27 41 " + + " 8C DB 41 86 FA D9 38 1D 2C 40 E5 2D BC EB 37 3C " + + " D1 39 52 74 8C C2 C1 34 06 46 8A 13 A3 E9 E4 FB " + + " 78 12 D3 28 B8 B2 2D 69 78 61 34 A3 94 38 38 2E " + + " 6B F5 1B F6 41 A9 0E EB 76 69 C2 BE F8 75 58 1A " + + " 52 97 8C DE 50 A2 78 03 9C 3E C3 F9 7B DD 91 74 " + + " 70 06 67 D0 80 B8 0E C4 90 15 94 FB 88 DE 3B B2 " + + " DE 25 CF BA CA 34 7D 0A F8 27 12 D0 F0 5A 41 98 " + + " 3C D3 55 45 00 6C 9A CC 92 31 54 01 DC 30 49 6F " + + " A6 C0 0C A2 F3 EC DF 14 44 21 0E 3C D8 1A EB 7E " + + " 08 7D 71 4C 04 1D 31 6A 44 E1 7C 7C FC F0 D3 3A " + + " 24 E2 0D 02 E1 94 7E AC A5 BC 94 80 81 E0 40 2A " + + " D6 95 75 27 29 10 40 AA 95 00 66 7C 8D 7F 9A 60 " + + " 48 38 70 1B FB 8B D8 C2 EC B6 0B 69 08 F4 0B 10 " + + " 0D 7D 06 EB 16 D7 70 3B 0F 88 C8 15 5C EC 8B B1 " + + " 7B 48 44 17 55 05 D4 7F 31 FE 19 D4 DF 5F AB FF " + + " 87 DF D4 4A 9B 9E 7F 18 4E 02 13 70 E0 92 51 D7 " + + " 85 FE 02 BE 03 5E DF 6B 7D 01 60 2D 60 1F 96 27 " + + " 0C 69 0B 5F 68 CC 4B AB 01 06 AE 7B 82 A5 92 FA " + + " C8 68 21 EB 96 12 98 A4 AF 1F 65 47 C3 5B 46 15 " + + " CC 42 4A 8C 93 0B 0D F1 42 B1 84 B9 0B A1 87 FB " + + " B4 77 2F 0E BA A0 6F 8E 10 22 06 2B AD 5B 63 15 " + + " 5F 1A AE EF FF F6 52 2F 18 91 F1 0B 10 28 39 BE " + + " 2F 42 8D 36 6B 78 5F 5E 61 D6 24 71 3F 68 5C 8E " + + " F3 73 94 62 A3 3B DF EE DE 4A A8 72 C9 0D 5F 9D " + + " 8D CD CB 68 B5 F9 DB 18 47 43 9F BD 21 65 7E 6C " + + " 5A 90 FA B7 42 D6 42 B9 07 EE F8 D0 EF 1F 5E 19 " + + " 7F 3A B0 9B FF 01 00 00 FF FF 03 00 50 4B 03 04 " + + " 14 00 06 00 08 00 00 00 21 00 56 84 64 08 2D 01 " + + " 00 00 AB 01 00 00 0F 00 00 00 64 72 73 2F 64 6F " + + " 77 6E 72 65 76 2E 78 6D 6C 5C 90 5F 4F C2 30 14 " + + " C5 DF 4D FC 0E CD 35 F1 4D B6 15 C6 3F 29 64 31 " + + " 21 62 82 E2 90 C4 D7 B2 B6 6C BA B6 B3 AD 30 F8 " + + " F4 76 20 21 FA 78 CE BD BF D3 7B 3A 9A D4 B2 44 " + + " 5B 6E 6C A1 15 81 A8 15 02 E2 2A D3 AC 50 1B 02 " + + " AB B7 E9 5D 1F 90 75 54 31 5A 6A C5 09 EC B9 85 " + + " C9 F8 FA 6A 44 87 4C EF 54 CA B7 4B B7 41 3E 44 " + + " D9 21 25 90 3B 57 0D 83 C0 66 39 97 D4 B6 74 C5 " + + " 95 9F 09 6D 24 75 5E 9A 4D C0 0C DD F9 70 59 06 " + + " 38 0C BB 81 A4 85 F2 2F E4 B4 E2 0F 39 CF 3E 97 " + + " DF 92 C0 9C 89 E7 F7 4E 31 7D A2 E2 2B 99 75 D2 " + + " 7E BC 5D B0 98 90 DB 9B 3A B9 07 E4 78 ED 2E CB " + + " 55 FE B1 C0 F3 F9 FA 75 95 9C 17 8E 71 33 46 A0 " + + " 0D 48 3C EE D7 A6 60 29 B5 8E 1B 02 BE 9F 6F EB " + + " 9B C2 D8 57 A8 CB 44 65 B9 36 48 A4 DC 16 07 DF " + + " EF E4 0B A3 25 32 7A 47 A0 0B 28 D3 65 E3 37 FA " + + " 45 08 CB 1D 81 41 8C 63 9F E4 27 67 07 87 83 D8 " + + " 5B 41 93 EA F4 89 ED FD B2 F8 0F 1B F5 A2 CE 3F " + + " 38 C2 ED 3E 8E 1B 38 B8 DC 74 14 97 3F 1E FF 00 " + + " 00 00 FF FF 03 00 50 4B 01 02 2D 00 14 00 06 00 " + + " 08 00 00 00 21 00 F0 F7 8A BB FD 00 00 00 E2 01 " + + " 00 00 13 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 00 00 00 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 " + + " 65 73 5D 2E 78 6D 6C 50 4B 01 02 2D 00 14 00 06 " + + " 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 00 00 8F " + + " 01 00 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 2E 01 00 00 5F 72 65 6C 73 2F 2E 72 65 6C 73 " + + " 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 21 00 " + + " 99 C9 E2 87 75 02 00 00 1B 07 00 00 10 00 00 00 " + + " 00 00 00 00 00 00 00 00 00 00 29 02 00 00 64 72 " + + " 73 2F 73 68 61 70 65 78 6D 6C 2E 78 6D 6C 50 4B " + + " 01 02 2D 00 14 00 06 00 08 00 00 00 21 00 56 84 " + + " 64 08 2D 01 00 00 AB 01 00 00 0F 00 00 00 00 00 " + + " 00 00 00 00 00 00 00 00 CC 04 00 00 64 72 73 2F " + + " 64 6F 77 6E 72 65 76 2E 78 6D 6C 50 4B 05 06 00 " + + " 00 00 00 04 00 04 00 F5 00 00 00 26 06 00 00 00 " + + " 00 00 00 10 F0 12 00 00 00 02 00 01 00 60 01 06 " + + " 00 80 00 02 00 D0 00 07 00 E6 00 00 00 11 F0 00 " + + " 00 00 00 5D 00 1A 00 15 00 12 00 06 00 10 00 11 " + + " 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 EC 00 08 00 00 00 0D F0 00 00 00 00 B6 01 12 " + + " 00 12 02 00 00 00 00 00 00 00 00 06 00 10 00 00 " + + " 00 00 00 3C 00 07 00 00 74 65 78 74 2D 32 3C 00 " + + " 10 00 00 00 16 00 00 00 00 00 06 00 00 00 00 00 " + + " 00 00 EC 00 CB 07 0F 00 04 F0 CB 07 00 00 A2 0C " + + " 0A F0 08 00 00 00 11 04 00 00 00 0A 00 00 93 00 " + + " 0B F0 4A 00 00 00 7F 00 00 00 04 00 80 00 00 D1 " + + " 53 02 85 00 02 00 00 00 8B 00 02 00 00 00 BF 00 " + + " 1A 00 1F 00 BF 01 01 00 11 00 FF 01 00 00 08 00 " + + " 80 C3 14 00 00 00 BF 03 00 00 02 00 54 00 65 00 " + + " 78 00 74 00 42 00 6F 00 78 00 20 00 33 00 00 00 " + + " 13 00 22 F1 37 07 00 00 A9 C3 31 07 00 00 50 4B " + + " 03 04 14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB " + + " FD 00 00 00 E2 01 00 00 13 00 00 00 5B 43 6F 6E " + + " 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D 6C 94 " + + " 91 CD 4A C4 30 10 C7 EF 82 EF 10 E6 2A 6D AA 07 " + + " 11 69 BA 07 AB 47 15 5D 1F 60 48 A6 6D D8 36 09 " + + " 99 58 77 DF DE 74 3F 2E E2 0A 1E 67 E6 FF F1 23 " + + " A9 57 DB 69 14 33 45 B6 DE 29 B8 2E 2B 10 E4 B4 " + + " 37 D6 F5 0A 3E D6 4F C5 1D 08 4E E8 0C 8E DE 91 " + + " 82 1D 31 AC 9A CB 8B 7A BD 0B C4 22 BB 1D 2B 18 " + + " 52 0A F7 52 B2 1E 68 42 2E 7D 20 97 2F 9D 8F 13 " + + " A6 3C C6 5E 06 D4 1B EC 49 DE 54 D5 AD D4 DE 25 " + + " 72 A9 48 4B 06 34 75 4B 1D 7E 8E 49 3C 6E F3 FA " + + " 40 12 69 64 10 0F 07 E1 D2 A5 00 43 18 AD C6 94 " + + " 49 E5 EC CC 8F 96 E2 D8 50 66 E7 5E C3 83 0D 7C " + + " 95 31 40 FE DA B0 5C CE 17 1C 7D 2F F9 69 A2 35 " + + " 24 5E 31 A6 67 9C 32 86 34 91 25 0F 18 28 6B CA " + + " BF 53 16 CC 89 0B DF 75 56 53 D9 46 7E 5F 7C 27 " + + " A8 73 E1 C6 7F B9 48 F3 7F B3 DB 6C 7B A3 F9 94 " + + " 2E F7 3F D4 7C 03 00 00 FF FF 03 00 50 4B 03 04 " + + " 14 00 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 " + + " 00 00 8F 01 00 00 0B 00 00 00 5F 72 65 6C 73 2F " + + " 2E 72 65 6C 73 A4 90 C1 6A C3 30 0C 86 EF 83 BD " + + " 83 D1 BD 71 DA 43 19 A3 4E 6F 85 5E 4B 07 BB 0A " + + " 5B 49 4C 63 CB 58 26 6D DF BE A6 30 58 46 6F 3B " + + " EA 17 FA 3E F1 EF F6 B7 30 A9 99 B2 78 8E 06 D6 " + + " 4D 0B 8A A2 65 E7 E3 60 E0 EB 7C 58 7D 80 92 82 " + + " D1 E1 C4 91 0C DC 49 60 DF BD BF ED 4E 34 61 A9 " + + " 47 32 FA 24 AA 52 A2 18 18 4B 49 9F 5A 8B 1D 29 " + + " A0 34 9C 28 D6 4D CF 39 60 A9 63 1E 74 42 7B C1 " + + " 81 F4 A6 6D B7 3A FF 66 40 B7 60 AA A3 33 90 8F " + + " 6E 03 EA 7C 4F D5 FC 87 1D BC CD 2C DC 97 C6 72 " + + " D0 DC F7 DE BE A2 6A C7 D7 78 A2 B9 52 30 0F 54 " + + " 0C B8 2C CF 30 D3 DC D4 E7 40 BF F6 AE FF E9 95 " + + " 11 13 7D 57 FE 42 FC 4C AB F5 C7 AC 17 35 76 0F " + + " 00 00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 08 " + + " 00 00 00 21 00 49 0D 41 2E 77 02 00 00 1A 07 00 " + + " 00 10 00 00 00 64 72 73 2F 73 68 61 70 65 78 6D " + + " 6C 2E 78 6D 6C BC 55 4D 73 DB 20 10 BD 77 A6 FF " + + " 81 E1 EE E8 23 96 1B 6B 8C 32 A9 33 E9 A5 D3 78 " + + " EC F8 07 60 09 D9 9A 22 D0 00 B1 E5 FC FA EE 82 " + + " EC A4 39 F4 10 77 72 41 68 17 F6 3D 1E BB CB EC " + + " B6 6F 25 D9 0B 63 1B AD 18 4D AE 62 4A 84 2A 75 " + + " D5 A8 2D A3 EB A7 87 D1 0D 25 D6 71 55 71 A9 95 " + + " 60 F4 28 2C BD 2D BE 7E 99 F5 95 C9 B9 2A 77 DA " + + " 10 08 A1 6C 0E 06 46 77 CE 75 79 14 D9 72 27 5A " + + " 6E AF 74 27 14 78 6B 6D 5A EE E0 D7 6C A3 CA F0 " + + " 03 04 6F 65 94 C6 F1 24 B2 9D 11 BC B2 3B 21 DC " + + " 7D F0 D0 C2 C7 06 B4 B9 90 F2 CE 43 04 53 6D 74 " + + " 1B 66 A5 96 45 32 8B 90 03 4E FD 06 98 3C D6 75 " + + " 91 C6 D3 2C 8B CF 3E 34 79 B7 D1 87 62 1A CC 38 " + + " 3D D9 D0 3F CD D2 EC EC F1 1B 7C E4 57 38 D1 3B " + + " 52 F6 8C C2 BA 34 06 41 CA 23 A3 E9 64 9C 4D 62 " + + " 1A 85 48 B6 23 2D 2F 8D 66 94 12 07 CB 65 A3 7E " + + " C3 3C 38 D5 7E D5 2D 4C 98 97 BF F6 0B 43 9A 8A " + + " D1 31 25 8A B7 20 E9 13 AC FF AE 7B 72 7D 0A 06 " + + " 6B 70 03 71 3D 98 E1 52 D0 EE 19 BD 0D 64 7D 48 " + + " 9E F7 B5 69 87 1B E0 1F D0 BF E5 8D 02 9A 3C D7 " + + " 75 4D 00 EC 26 99 26 19 24 01 9C 30 F9 96 8E E3 " + + " 34 43 74 9E FF 5B 82 28 F0 C0 85 9D B1 EE 87 D0 " + + " 17 73 22 18 88 51 23 4A E7 F9 F1 FD 4F EB 50 88 " + + " 57 08 84 53 FA A1 91 F2 52 01 4E 02 07 51 31 AD " + + " AC 3B 4A 81 00 52 2D 05 28 E3 53 FC C3 02 C3 85 " + + " 83 B6 B1 3F 88 2D CD 76 33 97 86 40 B9 80 D0 50 " + + " 66 30 6E 70 0C A7 F3 80 88 5C C3 C1 3E 19 7B 80 " + + " 44 74 51 D7 20 FD 27 E3 9F 41 FD F9 B5 FA 7F F8 " + + " 6D A3 B4 19 F4 87 DE 24 F0 02 F6 5C 32 EA FA 50 " + + " 5F A0 77 C0 1B 6A 6D 48 00 CC 05 AC C3 EA 88 94 " + + " 36 F0 85 C2 BC 34 1B A0 DF BA 47 18 6A A9 0F 8C " + + " 96 B2 E9 28 81 46 FA F2 DE 76 30 BC 63 54 41 2B " + + " A4 C4 38 39 D7 C0 17 92 25 B4 5D A0 1E CE D3 DD " + + " 3D 3B A8 82 A1 38 02 45 24 2B AD 5B 61 16 5F 4A " + + " D7 D7 7F 77 69 14 64 64 FC 00 02 4A 8E CF 8B 50 " + + " A3 F5 0A 9E 97 17 E8 35 49 EC F3 9F E7 AE C0 FE " + + " 39 BA C6 42 77 BE DC FD 2E A1 AA 05 37 7C 79 DE " + + " 6C 9E 47 CB F5 DF 9B B1 35 0C B7 77 BA 32 DF 36 " + + " 2D 58 FD 53 21 1B A1 DC 3D 77 FC 54 EF EF 1E 19 " + + " BF 3A A8 5B FC 01 00 00 FF FF 03 00 50 4B 03 04 " + + " 14 00 06 00 08 00 00 00 21 00 79 45 76 AD 2B 01 " + + " 00 00 AA 01 00 00 0F 00 00 00 64 72 73 2F 64 6F " + + " 77 6E 72 65 76 2E 78 6D 6C 5C 90 51 4F C2 30 14 " + + " 85 DF 4D FC 0F CD 35 F1 4D 3A 26 D5 81 14 B2 98 " + + " 10 31 99 E2 90 C4 D7 B2 B6 6C 71 6D 67 5B 61 F8 " + + " EB 2D 23 84 E8 E3 39 F7 7E E7 F6 74 3C 6D 55 8D " + + " B6 C2 BA CA 68 0A FD 5E 04 48 E8 C2 F0 4A 6F 28 " + + " AC DE 67 37 09 20 E7 99 E6 AC 36 5A 50 D8 0B 07 " + + " D3 C9 E5 C5 98 8D B8 D9 E9 5C 6C 97 7E 83 42 88 " + + " 76 23 46 A1 F4 BE 19 61 EC 8A 52 28 E6 7A A6 11 " + + " 3A CC A4 B1 8A F9 20 ED 06 73 CB 76 21 5C D5 38 " + + " 8E A2 3B AC 58 A5 C3 85 92 35 E2 B1 14 C5 E7 F2 " + + " 5B 51 C8 B8 7C F9 18 54 B3 67 26 BF D2 F9 20 4F " + + " C8 76 C1 09 A5 D7 57 6D FA 00 C8 8B D6 9F 97 1B " + + " 2B 17 71 96 AD DF 56 E9 69 A1 8B 9B 73 0A 03 40 " + + " F2 69 BF B6 15 CF 99 F3 C2 52 08 FD 42 DB D0 14 " + + " 26 A1 42 5B A7 BA 28 8D 45 32 17 AE FA 09 FD 8E " + + " BE B4 46 21 6B 76 14 86 80 0A 53 1F FC 83 7E 95 " + + " D2 09 1F 5C 12 93 6E 70 32 E2 68 48 48 04 F8 10 " + + " EA CD 11 ED 87 5B 1D 1B FF 61 13 72 FF 0F EE C7 " + + " B7 49 B0 02 8C CF 4F EA C4 F9 8B 27 BF 00 00 00 " + + " FF FF 03 00 50 4B 01 02 2D 00 14 00 06 00 08 00 " + + " 00 00 21 00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 " + + " 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 00 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 " + + " 5D 2E 78 6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 " + + " 00 00 00 21 00 31 DD 5F 61 D2 00 00 00 8F 01 00 " + + " 00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 2E " + + " 01 00 00 5F 72 65 6C 73 2F 2E 72 65 6C 73 50 4B " + + " 01 02 2D 00 14 00 06 00 08 00 00 00 21 00 49 0D " + + " 41 2E 77 02 00 00 1A 07 00 00 10 00 00 00 00 00 " + + " 00 00 00 00 00 00 00 00 29 02 00 00 64 72 73 2F " + + " 73 68 61 70 65 78 6D 6C 2E 78 6D 6C 50 4B 01 02 " + + " 2D 00 14 00 06 00 08 00 00 00 21 00 79 45 76 AD " + + " 2B 01 00 00 AA 01 00 00 0F 00 00 00 00 00 00 00 " + + " 00 00 00 00 00 00 CE 04 00 00 64 72 73 2F 64 6F " + + " 77 6E 72 65 76 2E 78 6D 6C 50 4B 05 06 00 00 00 " + + " 00 04 00 04 00 F5 00 00 00 26 06 00 00 00 00 00 " + + " 00 10 F0 12 00 00 00 02 00 01 00 60 01 09 00 0D " + + " 00 02 00 D0 00 0A 00 73 00 00 00 11 F0 00 00 00 " + + " 00 5D 00 1A 00 15 00 12 00 06 00 11 00 11 60 00 " + + " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 EC " + + " 00 08 00 00 00 0D F0 00 00 00 00 B6 01 12 00 12 " + + " 02 00 00 00 00 00 00 00 00 06 00 10 00 00 00 00 " + + " 00 3C 00 07 00 00 74 65 78 74 2D 33 3C 00 10 00 " + + " 00 00 16 00 00 00 00 00 06 00 00 00 00 00 00 00 " + + " EC 00 CC 07 0F 00 04 F0 CC 07 00 00 A2 0C 0A F0 " + + " 08 00 00 00 12 04 00 00 00 0A 00 00 93 00 0B F0 " + + " 4A 00 00 00 7F 00 00 00 04 00 80 00 00 36 9A 02 " + + " 85 00 02 00 00 00 8B 00 02 00 00 00 BF 00 1A 00 " + + " 1F 00 BF 01 01 00 11 00 FF 01 00 00 08 00 80 C3 " + + " 14 00 00 00 BF 03 00 00 02 00 54 00 65 00 78 00 " + + " 74 00 42 00 6F 00 78 00 20 00 34 00 00 00 13 00 " + + " 22 F1 38 07 00 00 A9 C3 32 07 00 00 50 4B 03 04 " + + " 14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB FD 00 " + + " 00 00 E2 01 00 00 13 00 00 00 5B 43 6F 6E 74 65 " + + " 6E 74 5F 54 79 70 65 73 5D 2E 78 6D 6C 94 91 CD " + + " 4A C4 30 10 C7 EF 82 EF 10 E6 2A 6D AA 07 11 69 " + + " BA 07 AB 47 15 5D 1F 60 48 A6 6D D8 36 09 99 58 " + + " 77 DF DE 74 3F 2E E2 0A 1E 67 E6 FF F1 23 A9 57 " + + " DB 69 14 33 45 B6 DE 29 B8 2E 2B 10 E4 B4 37 D6 " + + " F5 0A 3E D6 4F C5 1D 08 4E E8 0C 8E DE 91 82 1D " + + " 31 AC 9A CB 8B 7A BD 0B C4 22 BB 1D 2B 18 52 0A " + + " F7 52 B2 1E 68 42 2E 7D 20 97 2F 9D 8F 13 A6 3C " + + " C6 5E 06 D4 1B EC 49 DE 54 D5 AD D4 DE 25 72 A9 " + + " 48 4B 06 34 75 4B 1D 7E 8E 49 3C 6E F3 FA 40 12 " + + " 69 64 10 0F 07 E1 D2 A5 00 43 18 AD C6 94 49 E5 " + + " EC CC 8F 96 E2 D8 50 66 E7 5E C3 83 0D 7C 95 31 " + + " 40 FE DA B0 5C CE 17 1C 7D 2F F9 69 A2 35 24 5E " + + " 31 A6 67 9C 32 86 34 91 25 0F 18 28 6B CA BF 53 " + + " 16 CC 89 0B DF 75 56 53 D9 46 7E 5F 7C 27 A8 73 " + + " E1 C6 7F B9 48 F3 7F B3 DB 6C 7B A3 F9 94 2E F7 " + + " 3F D4 7C 03 00 00 FF FF 03 00 50 4B 03 04 14 00 " + + " 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 00 00 " + + " 8F 01 00 00 0B 00 00 00 5F 72 65 6C 73 2F 2E 72 " + + " 65 6C 73 A4 90 C1 6A C3 30 0C 86 EF 83 BD 83 D1 " + + " BD 71 DA 43 19 A3 4E 6F 85 5E 4B 07 BB 0A 5B 49 " + + " 4C 63 CB 58 26 6D DF BE A6 30 58 46 6F 3B EA 17 " + + " FA 3E F1 EF F6 B7 30 A9 99 B2 78 8E 06 D6 4D 0B " + + " 8A A2 65 E7 E3 60 E0 EB 7C 58 7D 80 92 82 D1 E1 " + + " C4 91 0C DC 49 60 DF BD BF ED 4E 34 61 A9 47 32 " + + " FA 24 AA 52 A2 18 18 4B 49 9F 5A 8B 1D 29 A0 34 " + + " 9C 28 D6 4D CF 39 60 A9 63 1E 74 42 7B C1 81 F4 " + + " A6 6D B7 3A FF 66 40 B7 60 AA A3 33 90 8F 6E 03 " + + " EA 7C 4F D5 FC 87 1D BC CD 2C DC 97 C6 72 D0 DC " + + " F7 DE BE A2 6A C7 D7 78 A2 B9 52 30 0F 54 0C B8 " + + " 2C CF 30 D3 DC D4 E7 40 BF F6 AE FF E9 95 11 13 " + + " 7D 57 FE 42 FC 4C AB F5 C7 AC 17 35 76 0F 00 00 " + + " 00 FF FF 03 00 50 4B 03 04 14 00 06 00 08 00 00 " + + " 00 21 00 5B 36 01 DE 77 02 00 00 1D 07 00 00 10 " + + " 00 00 00 64 72 73 2F 73 68 61 70 65 78 6D 6C 2E " + + " 78 6D 6C BC 55 4D 53 DB 30 10 BD 77 A6 FF 41 A3 " + + " 7B B0 9D 26 99 90 C1 66 28 0C BD 74 0A 93 C0 0F " + + " 10 B6 9C 78 2A 4B 1E 49 24 0E BF BE 6F 25 27 50 " + + " 0E 3D 90 0E 17 59 5E 69 F7 ED BE FD D0 C5 65 DF " + + " 2A B6 95 D6 35 46 E7 3C 3B 4B 39 93 BA 34 55 A3 " + + " D7 39 7F 7C B8 1D CD 39 73 5E E8 4A 28 A3 65 CE " + + " F7 D2 F1 CB E2 EB 97 8B BE B2 0B A1 CB 8D B1 0C " + + " 26 B4 5B 40 90 F3 8D F7 DD 22 49 5C B9 91 AD 70 " + + " 67 A6 93 1A A7 B5 B1 AD F0 F8 B5 EB A4 B2 62 07 " + + " E3 AD 4A C6 69 3A 4B 5C 67 A5 A8 DC 46 4A 7F 13 " + + " 4F 78 11 6C 03 ED 5A 2A 75 15 20 A2 A8 B6 A6 8D " + + " BB D2 A8 22 BB 48 C8 07 DA 06 05 6C EE EA BA 18 " + + " A7 E7 D3 69 7A 3C 23 51 38 B6 66 57 64 83 0E ED " + + " 0F 42 BA 90 65 93 6F E9 A0 83 B3 A0 13 8C BF 22 " + + " CA DE B3 B2 CF F9 74 3C 1D A7 E0 A4 DC E7 7C 3C " + + " 9B 4C 67 29 4F A2 2D D7 B1 56 94 D6 E4 9C 33 8F " + + " EB AA D1 BF B1 8F 87 7A BB EA EE 6D DC 97 BF B6 " + + " F7 96 35 15 8C 71 A6 45 0B 56 1F 70 FF BB E9 D9 " + + " E4 60 0C 77 48 81 F9 1E 62 E4 85 E4 C1 A3 B7 86 " + + " 5C 30 29 16 7D 6D DB 21 09 E2 03 29 68 45 A3 E1 " + + " A6 58 98 BA 66 00 9B 67 E7 D9 14 75 40 11 82 CD " + + " 79 1A 42 14 8B 7F 53 90 44 3F C8 4E 67 9D FF 21 " + + " CD C9 3E 31 32 94 73 2B 4B 1F FC 13 DB 9F CE 13 " + + " 11 AF 10 04 A7 CD 6D A3 D4 A9 04 1C 08 8E A4 52 " + + " 65 39 BF 57 92 00 94 5E 4A 30 13 AA FC C3 04 23 " + + " E1 E0 36 0D 81 B8 D2 AE 9F AE 95 65 E8 18 10 8D " + + " 4E C3 FA 44 6B 8C 2E 00 12 72 8D C0 3E 19 7B 80 " + + " 24 74 59 D7 A0 FE 93 F1 8F A0 21 7E A3 FF 1F 7E " + + " DB 68 63 07 FE 31 9E 24 25 60 2B 54 CE 7D 1F FB " + + " 0B 7C 47 BC A1 D7 86 02 A0 5A A0 3E AC F6 E4 D2 " + + " 13 BE 68 CC 53 AB 01 23 D7 DF 61 A9 95 D9 E5 BC " + + " 54 4D C7 19 66 E9 CB 7B D9 CE 8A 2E E7 1A D3 90 " + + " 33 EB D5 B5 81 BF 28 96 38 79 E1 7A 8C A7 BB 7A " + + " F6 E8 82 A1 39 A2 8B E4 AC 72 7E 45 55 7C AA BB " + + " 28 4B F4 DC A9 56 C8 88 0D 0B 08 54 82 5E 18 A9 " + + " 47 8F 2B BC 30 2F 98 71 D9 61 D0 F8 82 E6 E7 68 " + + " 42 8D EE 43 BB 07 2D A9 AB 7B 61 C5 F2 A8 6C 9F " + + " 47 CB C7 BF 95 69 34 0C D9 3B A4 2C 8C 4D 07 69 " + + " 78 2D 54 23 B5 BF 11 5E 1C FA FD DD 3B 13 6E 47 " + + " 76 8B 3F 00 00 00 FF FF 03 00 50 4B 03 04 14 00 " + + " 06 00 08 00 00 00 21 00 DB CE 2D F9 2C 01 00 00 " + + " AE 01 00 00 0F 00 00 00 64 72 73 2F 64 6F 77 6E " + + " 72 65 76 2E 78 6D 6C 5C 50 5D 4F C2 30 14 7D 37 " + + " F1 3F 34 D7 C4 37 E9 18 D4 00 52 C8 62 42 C4 64 " + + " 7E 0C 49 7C 2D 6B CB 16 D7 76 B6 75 0C 7F BD 1D " + + " 42 30 3E DD 9C 73 EE 39 ED B9 D3 79 AB 2A D4 08 " + + " EB 4A A3 29 F4 7B 11 20 A1 73 C3 4B BD A5 B0 7E " + + " 5B DC 8C 00 39 CF 34 67 95 D1 82 C2 5E 38 98 CF " + + " 2E 2F A6 6C C2 CD 4E 67 A2 59 F9 2D 0A 21 DA 4D " + + " 18 85 C2 FB 7A 82 B1 CB 0B A1 98 EB 99 5A E8 A0 " + + " 49 63 15 F3 01 DA 2D E6 96 ED 42 B8 AA 70 1C 45 " + + " B7 58 B1 52 87 17 0A 56 8B FB 42 E4 1F AB 2F 45 " + + " 21 E5 F2 E9 7D 58 2E 1E 99 FC 4C 96 C3 6C 44 9A " + + " 17 4E 28 BD BE 6A 93 3B 40 5E B4 FE BC 5C 37 36 " + + " 8D D3 74 F3 BA 4E 4E 0B 87 B8 25 A7 40 00 C9 87 " + + " FD C6 96 3C 63 CE 0B 4B 21 F4 0B 6D 43 53 98 85 " + + " 0A 6D 95 E8 BC 30 16 C9 4C B8 F2 3B F4 FB E5 A5 " + + " 35 0A 59 B3 0B B8 0F 28 37 55 27 74 C4 B3 94 4E " + + " F8 8E 1E 0E A2 90 15 A4 13 15 47 63 42 22 C0 5D " + + " AE 37 47 77 7C 74 87 F9 D7 3D 8E C8 3F 77 3F 1E " + + " 8C 62 D2 B9 F1 F9 5B 07 70 3E F3 EC 07 00 00 FF " + + " FF 03 00 50 4B 01 02 2D 00 14 00 06 00 08 00 00 " + + " 00 21 00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 13 " + + " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D " + + " 2E 78 6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 00 " + + " 00 00 21 00 31 DD 5F 61 D2 00 00 00 8F 01 00 00 " + + " 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 2E 01 " + + " 00 00 5F 72 65 6C 73 2F 2E 72 65 6C 73 50 4B 01 " + + " 02 2D 00 14 00 06 00 08 00 00 00 21 00 5B 36 01 " + + " DE 77 02 00 00 1D 07 00 00 10 00 00 00 00 00 00 " + + " 00 00 00 00 00 00 00 29 02 00 00 64 72 73 2F 73 " + + " 68 61 70 65 78 6D 6C 2E 78 6D 6C 50 4B 01 02 2D " + + " 00 14 00 06 00 08 00 00 00 21 00 DB CE 2D F9 2C " + + " 01 00 00 AE 01 00 00 0F 00 00 00 00 00 00 00 00 " + + " 00 00 00 00 00 CE 04 00 00 64 72 73 2F 64 6F 77 " + + " 6E 72 65 76 2E 78 6D 6C 50 4B 05 06 00 00 00 00 " + + " 04 00 04 00 F5 00 00 00 27 06 00 00 00 00 00 00 " + + " 10 F0 12 00 00 00 02 00 01 00 60 01 0B 00 9A 00 " + + " 02 00 D0 00 0C 00 00 01 00 00 11 F0 00 00 00 00 " + + " 5D 00 1A 00 15 00 12 00 06 00 12 00 11 60 00 00 " + + " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 EC 00 " + + " 08 00 00 00 0D F0 00 00 00 00 B6 01 12 00 12 02 " + + " 00 00 00 00 00 00 00 00 06 00 10 00 00 00 00 00 " + + " 3C 00 07 00 00 74 65 78 74 2D 34 3C 00 10 00 00 " + + " 00 16 00 00 00 00 00 06 00 00 00 00 00 00 00 3C " + + " 00 C8 07 0F 00 04 F0 C8 07 00 00 A2 0C 0A F0 08 " + + " 00 00 00 13 04 00 00 00 0A 00 00 93 00 0B F0 4A " + + " 00 00 00 7F 00 00 00 04 00 80 00 80 33 9A 02 85 " + + " 00 02 00 00 00 8B 00 02 00 00 00 BF 00 1A 00 1F " + + " 00 BF 01 01 00 11 00 FF 01 00 00 08 00 80 C3 14 " + + " 00 00 00 BF 03 00 00 02 00 54 00 65 00 78 00 74 " + + " 00 42 00 6F 00 78 00 20 00 35 00 00 00 13 00 22 " + + " F1 34 07 00 00 A9 C3 2E 07 00 00 50 4B 03 04 14 " + + " 00 06 00 08 00 00 00 21 00 F0 F7 8A BB FD 00 00 " + + " 00 E2 01 00 00 13 00 00 00 5B 43 6F 6E 74 65 6E " + + " 74 5F 54 79 70 65 73 5D 2E 78 6D 6C 94 91 CD 4A " + + " C4 30 10 C7 EF 82 EF 10 E6 2A 6D AA 07 11 69 BA " + + " 07 AB 47 15 5D 1F 60 48 A6 6D D8 36 09 99 58 77 " + + " DF DE 74 3F 2E E2 0A 1E 67 E6 FF F1 23 A9 57 DB " + + " 69 14 33 45 B6 DE 29 B8 2E 2B 10 E4 B4 37 D6 F5 " + + " 0A 3E D6 4F C5 1D 08 4E E8 0C 8E DE 91 82 1D 31 " + + " AC 9A CB 8B 7A BD 0B C4 22 BB 1D 2B 18 52 0A F7 " + + " 52 B2 1E 68 42 2E 7D 20 97 2F 9D 8F 13 A6 3C C6 " + + " 5E 06 D4 1B EC 49 DE 54 D5 AD D4 DE 25 72 A9 48 " + + " 4B 06 34 75 4B 1D 7E 8E 49 3C 6E F3 FA 40 12 69 " + + " 64 10 0F 07 E1 D2 A5 00 43 18 AD C6 94 49 E5 EC " + + " CC 8F 96 E2 D8 50 66 E7 5E C3 83 0D 7C 95 31 40 " + + " FE DA B0 5C CE 17 1C 7D 2F F9 69 A2 35 24 5E 31 " + + " A6 67 9C 32 86 34 91 25 0F 18 28 6B CA BF 53 16 " + + " CC 89 0B DF 75 56 53 D9 46 7E 5F 7C 27 A8 73 E1 " + + " C6 7F B9 48 F3 7F B3 DB 6C 7B A3 F9 94 2E F7 3F " + + " D4 7C 03 00 00 FF FF 03 00 50 4B 03 04 14 00 06 " + + " 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 00 00 8F " + + " 01 00 00 0B 00 00 00 5F 72 65 6C 73 2F 2E 72 65 " + + " 6C 73 A4 90 C1 6A C3 30 0C 86 EF 83 BD 83 D1 BD " + + " 71 DA 43 19 A3 4E 6F 85 5E 4B 07 BB 0A 5B 49 4C " + + " 63 CB 58 26 6D DF BE A6 30 58 46 6F 3B EA 17 FA " + + " 3E F1 EF F6 B7 30 A9 99 B2 78 8E 06 D6 4D 0B 8A " + + " A2 65 E7 E3 60 E0 EB 7C 58 7D 80 92 82 D1 E1 C4 " + + " 91 0C DC 49 60 DF BD BF ED 4E 34 61 A9 47 32 FA " + + " 24 AA 52 A2 18 18 4B 49 9F 5A 8B 1D 29 A0 34 9C " + + " 28 D6 4D CF 39 60 A9 63 1E 74 42 7B C1 81 F4 A6 " + + " 6D B7 3A FF 66 40 B7 60 AA A3 33 90 8F 6E 03 EA " + + " 7C 4F D5 FC 87 1D BC CD 2C DC 97 C6 72 D0 DC F7 " + + " DE BE A2 6A C7 D7 78 A2 B9 52 30 0F 54 0C B8 2C " + + " CF 30 D3 DC D4 E7 40 BF F6 AE FF E9 95 11 13 7D " + + " 57 FE 42 FC 4C AB F5 C7 AC 17 35 76 0F 00 00 00 " + + " FF FF 03 00 50 4B 03 04 14 00 06 00 08 00 00 00 " + + " 21 00 C4 6F 3F 83 76 02 00 00 1C 07 00 00 10 00 " + + " 00 00 64 72 73 2F 73 68 61 70 65 78 6D 6C 2E 78 " + + " 6D 6C BC 55 CD 6E DB 30 0C BE 0F D8 3B 08 BA A7 " + + " B6 83 3A 4D 8D C8 45 97 A2 BB 0C 6B 90 34 0F A0 " + + " C8 72 62 4C 96 0C 49 4D 9C 3E FD 48 C9 49 B7 1E " + + " 76 68 86 5E 64 9A 12 F9 51 1F 7F 34 BB EB 5B 45 " + + " F6 D2 BA C6 68 46 B3 AB 94 12 A9 85 A9 1A BD 65 " + + " 74 FD FC 38 9A 52 E2 3C D7 15 57 46 4B 46 8F D2 " + + " D1 BB F2 EB 97 59 5F D9 82 6B B1 33 96 80 0B ED " + + " 0A 50 30 BA F3 BE 2B 92 C4 89 9D 6C B9 BB 32 9D " + + " D4 B0 5B 1B DB 72 0F BF 76 9B 54 96 1F C0 79 AB " + + " 92 71 9A 4E 12 D7 59 C9 2B B7 93 D2 3F C4 1D 5A " + + " 06 DF 80 36 97 4A DD 07 88 A8 AA AD 69 A3 24 8C " + + " 2A B3 59 82 31 A0 18 0C 40 78 AA EB 72 9C DE E6 " + + " 79 7A DE 43 55 D8 B6 E6 50 66 D7 51 8F F2 49 19 " + + " 6C A6 F9 4D 7E DE 0A 26 C1 F7 1B A0 EC 3D 11 3D " + + " A3 F9 38 1F A7 40 89 38 32 3A 9E 5C E7 93 94 26 " + + " D1 95 EB 48 CB 85 35 8C 52 E2 E1 B8 6A F4 2F 90 " + + " E3 A6 DE AF BA 85 8D B2 F8 B9 5F 58 D2 54 8C 4E " + + " 28 D1 BC 05 52 9F E1 FC 37 D3 93 FC E4 0C CE A0 " + + " 01 F1 3D A8 21 2D A8 0F 11 FD E9 C8 05 97 BC E8 " + + " 6B DB 0E 39 E0 1F C8 40 CB 1B 0D 61 F2 C2 D4 35 " + + " 01 B0 69 76 9B E5 50 06 E1 86 C0 E5 4D 88 8A 17 " + + " FF A6 20 89 71 A0 9F CE 3A FF 5D 9A 8B 63 22 E8 " + + " 88 51 2B 85 0F F1 F1 FD 0F E7 91 88 37 08 84 D3 " + + " E6 B1 51 EA 52 02 4E 04 47 52 B1 B0 9C 3F 2A 89 " + + " 00 4A 2F 25 30 13 8A FC C3 04 43 C2 81 DB 34 5C " + + " C4 09 BB DD CC 95 25 D0 30 40 34 34 1A AC 1B 5C " + + " E3 ED 02 20 22 D7 70 B1 4F C6 1E 20 11 5D D6 35 " + + " 50 FF C9 F8 67 D0 70 7F A3 FF 1F 7E DB 68 63 07 " + + " FE 61 3A 49 4C C0 9E 2B 46 7D 1F FB 0B F8 8E 78 " + + " 43 AF 0D 05 80 B5 80 7D 58 1D 31 A4 0D 7C A1 31 " + + " 2F AD 06 98 B8 FE 09 96 5A 99 03 A3 42 35 1D 25 " + + " 30 4A 5F DF EB 0E 96 77 8C 6A 18 86 94 58 AF E6 " + + " 06 E2 85 62 89 83 17 42 8F F7 E9 EE 5F 3C 74 C1 " + + " D0 1C 31 44 0C 56 39 BF C2 2A BE 34 5C 28 4B E8 " + + " B9 4B BD A0 13 1B 16 20 50 71 7C 60 A4 1E AD 57 " + + " F0 C0 BC C2 8C CB D2 50 FF BC F0 25 CE CF 11 0C " + + " 64 94 71 0D 56 52 57 0B 6E F9 F2 6C 6C 5F 46 CB " + + " F5 DF C6 38 1A 86 EC 9D 52 16 C6 A6 03 6D 78 2C " + + " 54 23 B5 7F E0 9E 9F FA FD DD 33 13 4E 47 76 CB " + + " DF 00 00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 " + + " 08 00 00 00 21 00 AF 34 70 A0 29 01 00 00 AD 01 " + + " 00 00 0F 00 00 00 64 72 73 2F 64 6F 77 6E 72 65 " + + " 76 2E 78 6D 6C 5C 50 5D 4F C2 30 14 7D 37 F1 3F " + + " 34 D7 C4 37 D9 98 2B 4C A4 90 C5 84 88 C9 FC 18 " + + " 92 F0 5A D6 96 2D AE ED 6C 2B 0C 7F BD 1D A8 44 " + + " 1F CF 67 EF E9 78 DA CA 1A 6D B9 B1 95 56 04 FA " + + " BD 10 10 57 85 66 95 DA 10 58 BE CE AE 12 40 D6 " + + " 51 C5 68 AD 15 27 B0 E7 16 A6 93 F3 B3 31 1D 31 " + + " BD 53 39 DF 2E DC 06 F9 12 65 47 94 40 E9 5C 33 " + + " 0A 02 5B 94 5C 52 DB D3 0D 57 5E 13 DA 48 EA 3C " + + " 34 9B 80 19 BA F3 E5 B2 0E A2 30 1C 04 92 56 CA " + + " BF 50 D2 86 DF 95 BC 78 5B 7C 48 02 19 13 8F AB " + + " B8 9A 3D 50 F1 9E CE E3 3C C1 DB 67 86 09 B9 BC " + + " 68 D3 5B 40 8E B7 EE 64 6E EA 55 16 65 D9 FA 65 " + + " 99 FE 18 0E 75 73 46 60 00 48 DC EF D7 A6 62 39 " + + " B5 8E 1B 02 7E 9F 5F EB 97 C2 C4 4F 68 EB 54 15 " + + " A5 36 48 E4 DC 56 9F 7E DF 91 17 46 4B 64 F4 CE " + + " E3 18 50 A1 EB 4E E8 88 27 21 2C 77 04 A2 04 0F " + + " F1 41 F9 65 C2 1B 8C 43 08 BA 5A A7 BF C3 47 8B " + + " B7 FF 09 F7 C3 78 F8 2F DD 8F AE 93 08 77 E9 E0 " + + " 74 D5 01 9C 7E 79 F2 05 00 00 FF FF 03 00 50 4B " + + " 01 02 2D 00 14 00 06 00 08 00 00 00 21 00 F0 F7 " + + " 8A BB FD 00 00 00 E2 01 00 00 13 00 00 00 00 00 " + + " 00 00 00 00 00 00 00 00 00 00 00 00 5B 43 6F 6E " + + " 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D 6C 50 " + + " 4B 01 02 2D 00 14 00 06 00 08 00 00 00 21 00 31 " + + " DD 5F 61 D2 00 00 00 8F 01 00 00 0B 00 00 00 00 " + + " 00 00 00 00 00 00 00 00 00 2E 01 00 00 5F 72 65 " + + " 6C 73 2F 2E 72 65 6C 73 50 4B 01 02 2D 00 14 00 " + + " 06 00 08 00 00 00 21 00 C4 6F 3F 83 76 02 00 00 " + + " 1C 07 00 00 10 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 00 29 02 00 00 64 72 73 2F 73 68 61 70 65 78 " + + " 6D 6C 2E 78 6D 6C 50 4B 01 02 2D 00 14 00 06 00 " + + " 08 00 00 00 21 00 AF 34 70 A0 29 01 00 00 AD 01 " + + " 00 00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + " CD 04 00 00 64 72 73 2F 64 6F 77 6E 72 65 76 2E " + + " 78 6D 6C 50 4B 05 06 00 00 00 00 04 00 04 00 F5 " + + " 00 00 00 23 06 00 00 00 00 00 00 10 F0 12 00 00 " + + " 00 02 00 01 00 60 01 0E 00 26 00 02 00 D0 00 0F " + + " 00 8D 00 00 00 11 F0 00 00 00 00 5D 00 1A 00 15 " + + " 00 12 00 06 00 13 00 11 60 00 00 00 00 00 00 00 " + + " 00 00 00 00 00 00 00 00 00 3C 00 08 00 00 00 0D " + + " F0 00 00 00 00 B6 01 12 00 12 02 00 00 00 00 00 " + + " 00 00 00 06 00 10 00 00 00 00 00 3C 00 07 00 00 " + + " 74 65 78 74 2D 35 3C 00 10 00 00 00 16 00 00 00 " + + " 00 00 06 00 00 00 00 00 00 00 " + + " "; + + byte[] dgBytes = HexRead.readFromString(data); + List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); + assertEquals(20, dgRecords.size()); + + short[] expectedSids = { + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + TextObjectRecord.sid, + ContinueRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + TextObjectRecord.sid + }; + for (int i = 0; i < expectedSids.length; i++) { + assertEquals("unexpected record.sid and index[" + i + "]", expectedSids[i], dgRecords.get(i).getSid()); + } + DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); + + // create a dummy sheet consisting of our test data + InternalSheet sheet = InternalSheet.createSheet(); + List records = sheet.getRecords(); + records.clear(); + records.addAll(dgRecords); + records.add(EOFRecord.instance); + + + sheet.aggregateDrawingRecords(drawingManager, false); + assertEquals("drawing was not fully aggregated", 2, records.size()); + assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); + assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); + EscherAggregate agg = (EscherAggregate) records.get(0); + + // TODO figure out why serialization fails +// byte[] writtenBytes = agg.serialize(); + } + + public void testUnhandledContinue2() { + String data = "EC 00 38 08 0F 00 02 F0 97 37 00 00 10 00 " + + "08 F0 08 00 00 00 08 00 00 00 07 04 00 00 0F 00 " + + "03 F0 7F 37 00 00 0F 00 04 F0 28 00 00 00 01 00 " + + "09 F0 10 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 00 02 00 0A F0 08 00 00 00 00 04 " + + "00 00 05 00 00 00 0F 00 04 F0 E0 07 00 00 12 00 " + + "0A F0 08 00 00 00 01 04 00 00 00 0A 00 00 83 00 " + + "0B F0 50 00 00 00 BF 00 18 00 1F 00 81 01 4F 81 " + + "BD 00 BF 01 10 00 10 00 C0 01 38 5D 8A 00 CB 01 " + + "38 63 00 00 FF 01 08 00 08 00 80 C3 20 00 00 00 " + + "BF 03 00 00 02 00 1F 04 40 04 4F 04 3C 04 3E 04 " + + "43 04 33 04 3E 04 3B 04 4C 04 3D 04 38 04 3A 04 " + + "20 00 31 00 00 00 23 00 22 F1 4E 07 00 00 FF 01 " + + "00 00 40 00 A9 C3 42 07 00 00 50 4B 03 04 14 00 " + + "06 00 08 00 00 00 21 00 F0 F7 8A BB FD 00 00 00 " + + "E2 01 00 00 13 00 00 00 5B 43 6F 6E 74 65 6E 74 " + + "5F 54 79 70 65 73 5D 2E 78 6D 6C 94 91 CD 4A C4 " + + "30 10 C7 EF 82 EF 10 E6 2A 6D AA 07 11 69 BA 07 " + + "AB 47 15 5D 1F 60 48 A6 6D D8 36 09 99 58 77 DF " + + "DE 74 3F 2E E2 0A 1E 67 E6 FF F1 23 A9 57 DB 69 " + + "14 33 45 B6 DE 29 B8 2E 2B 10 E4 B4 37 D6 F5 0A " + + "3E D6 4F C5 1D 08 4E E8 0C 8E DE 91 82 1D 31 AC " + + "9A CB 8B 7A BD 0B C4 22 BB 1D 2B 18 52 0A F7 52 " + + "B2 1E 68 42 2E 7D 20 97 2F 9D 8F 13 A6 3C C6 5E " + + "06 D4 1B EC 49 DE 54 D5 AD D4 DE 25 72 A9 48 4B " + + "06 34 75 4B 1D 7E 8E 49 3C 6E F3 FA 40 12 69 64 " + + "10 0F 07 E1 D2 A5 00 43 18 AD C6 94 49 E5 EC CC " + + "8F 96 E2 D8 50 66 E7 5E C3 83 0D 7C 95 31 40 FE " + + "DA B0 5C CE 17 1C 7D 2F F9 69 A2 35 24 5E 31 A6 " + + "67 9C 32 86 34 91 25 0F 18 28 6B CA BF 53 16 CC " + + "89 0B DF 75 56 53 D9 46 7E 5F 7C 27 A8 73 E1 C6 " + + "7F B9 48 F3 7F B3 DB 6C 7B A3 F9 94 2E F7 3F D4 " + + "7C 03 00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 " + + "08 00 00 00 21 00 31 DD 5F 61 D2 00 00 00 8F 01 " + + "00 00 0B 00 00 00 5F 72 65 6C 73 2F 2E 72 65 6C " + + "73 A4 90 C1 6A C3 30 0C 86 EF 83 BD 83 D1 BD 71 " + + "DA 43 19 A3 4E 6F 85 5E 4B 07 BB 0A 5B 49 4C 63 " + + "CB 58 26 6D DF BE A6 30 58 46 6F 3B EA 17 FA 3E " + + "F1 EF F6 B7 30 A9 99 B2 78 8E 06 D6 4D 0B 8A A2 " + + "65 E7 E3 60 E0 EB 7C 58 7D 80 92 82 D1 E1 C4 91 " + + "0C DC 49 60 DF BD BF ED 4E 34 61 A9 47 32 FA 24 " + + "AA 52 A2 18 18 4B 49 9F 5A 8B 1D 29 A0 34 9C 28 " + + "D6 4D CF 39 60 A9 63 1E 74 42 7B C1 81 F4 A6 6D " + + "B7 3A FF 66 40 B7 60 AA A3 33 90 8F 6E 03 EA 7C " + + "4F D5 FC 87 1D BC CD 2C DC 97 C6 72 D0 DC F7 DE " + + "BE A2 6A C7 D7 78 A2 B9 52 30 0F 54 0C B8 2C CF " + + "30 D3 DC D4 E7 40 BF F6 AE FF E9 95 11 13 7D 57 " + + "FE 42 FC 4C AB F5 C7 AC 17 35 76 0F 00 00 00 FF " + + "FF 03 00 50 4B 03 04 14 00 06 00 08 00 00 00 21 " + + "00 B5 19 FD 5B 97 02 00 00 FC 06 00 00 10 00 00 " + + "00 64 72 73 2F 73 68 61 70 65 78 6D 6C 2E 78 6D " + + "6C AC 55 49 6E DB 30 14 DD 17 E8 1D 08 EE 13 0D " + + "B6 12 47 B0 14 B4 0E DA 4D D1 18 4E 73 00 56 A2 " + + "6C A1 14 29 90 AC 2D 67 55 A0 DB 02 3D 42 0F D1 " + + "4D D1 21 67 90 6F D4 4F 52 52 DA 74 58 C4 F6 42 " + + "A6 DE 17 FF 7B 7F 22 A7 E7 4D C5 D0 9A 4A 55 0A " + + "9E E0 E0 D8 C7 88 F2 4C E4 25 5F 26 F8 FA D5 B3 " + + "A3 09 46 4A 13 9E 13 26 38 4D F0 96 2A 7C 9E 3E " + + "7E 34 6D 72 19 13 9E AD 84 44 E0 82 AB 18 80 04 " + + "AF B4 AE 63 CF 53 D9 8A 56 44 1D 8B 9A 72 B0 16 " + + "42 56 44 C3 AB 5C 7A B9 24 1B 70 5E 31 2F F4 FD " + + "13 4F D5 92 92 5C AD 28 D5 17 CE 82 53 EB 5B 6F " + + "C4 8C 32 F6 C4 52 38 A8 90 A2 72 AB 4C B0 34 9C " + + "7A 46 83 59 DA 0D B0 B8 2C 8A 74 14 8C 47 61 34 " + + "D8 0C 64 CD 52 6C D2 91 83 CD B2 C7 8C 3D 88 C2 " + + "B1 EF 0F 36 BB C5 FA BE 23 D4 62 20 49 C7 83 F3 " + + "01 33 5B A2 49 E0 FF 8B 38 E8 C4 DE 67 3E 8B FA " + + "1D 60 B9 E3 ED D9 54 8D 2A 92 49 91 60 8C 34 6D " + + "34 2B F9 1B 58 3B 5A BE BE AA E7 B2 93 F0 72 3D " + + "97 A8 CC 13 1C 62 C4 49 05 85 6A 3F ED DE ED 3E " + + "B6 DF DB DB DD FB F6 73 7B DB 7E DB 7D 68 7F B4 " + + "5F DA AF 28 C0 DE B0 CD F8 80 37 1B EE AF 1E 95 " + + "F5 4D E2 A6 90 55 57 60 F2 80 F2 56 A4 E4 A0 97 " + + "C4 A2 28 50 03 0D 16 8D 46 10 33 46 DB 04 9F 86 " + + "A3 33 DF 37 5A 48 0C C1 A1 CC D8 C7 93 C8 80 28 " + + "83 0F 82 E8 34 38 81 8F 8D 3E A7 C4 7C 5A 4B A5 " + + "9F 53 B1 B7 2A 64 1C 25 58 D2 4C 5B 85 64 FD 42 " + + "69 47 D5 53 74 79 71 B9 30 CD A6 F4 96 51 23 82 " + + "F1 05 85 80 6C E3 3F 38 2F 50 30 08 39 B4 EC 76 " + + "62 E8 8C 49 B4 26 2C C1 24 CB 28 D7 81 33 AD 48 " + + "4E 1D 1C F9 F0 EB F2 31 EC B0 D9 B1 82 8C B2 A2 " + + "64 EC 60 DA 3A 01 66 9A FF D4 E6 72 D5 F1 D9 22 " + + "16 05 24 F3 60 E4 FE FF 12 E3 C8 69 CF 68 23 17 " + + "FC 70 E4 55 C9 85 FC 9B 00 06 55 E9 22 77 7C 7D " + + "93 B8 D6 30 5D A2 9B A7 22 DF 1A 49 AF E1 1F 06 " + + "73 DF 3E 81 F3 59 5F C2 A3 60 62 93 E0 8C 95 35 " + + "46 70 F0 DE DC C7 A4 66 33 01 DD 03 F3 E3 8E E6 " + + "04 6B 37 5F 4C E9 2B 23 70 5F 29 10 39 4C E0 BE " + + "5E AC 13 C8 0B 61 4B B8 74 98 93 48 79 3E 27 92 " + + "2C 00 67 C4 DC 3E F2 ED D1 E2 1A 6E 9F 1B 38 09 " + + "82 A1 ED EB 2E DF 7D 92 ED C9 A5 00 B5 97 01 2B " + + "61 6C 2E 88 26 A6 44 B6 16 BF 5F 23 16 73 B9 49 " + + "7F 02 00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 " + + "08 00 00 00 21 00 CA 39 EE E5 1C 01 00 00 8E 01 " + + "00 00 0F 00 00 00 64 72 73 2F 64 6F 77 6E 72 65 " + + "76 2E 78 6D 6C 4C 90 CB 4E C3 30 10 45 F7 48 FC " + + "83 35 48 6C 10 75 9E 28 94 3A 55 41 42 65 53 44 " + + "DA B2 60 67 12 E7 21 62 3B B2 4D 93 FE 3D 93 96 " + + "AA DD F9 CE DC 33 33 D7 B3 F9 20 5B B2 13 C6 36 " + + "5A 31 F0 27 1E 10 A1 72 5D 34 AA 62 B0 DD BC DE " + + "27 40 AC E3 AA E0 AD 56 82 C1 5E 58 98 A7 D7 57 " + + "33 3E 2D 74 AF 32 B1 5B BB 8A E0 10 65 A7 9C 41 " + + "ED 5C 37 A5 D4 E6 B5 90 DC 4E 74 27 14 F6 4A 6D " + + "24 77 28 4D 45 0B C3 7B 1C 2E 5B 1A 78 DE 03 95 " + + "BC 51 B8 A1 E6 9D 78 A9 45 FE B3 FE 95 B8 E4 43 " + + "7E 6E F5 73 F2 B5 A2 77 DB 3E 5B 6E 92 26 0E 13 " + + "C6 6E 6F 86 C5 13 10 27 06 77 36 FF D3 6F 05 83 " + + "00 48 B9 DC 7F 9B A6 C8 B8 75 C2 30 C0 38 18 0E " + + "83 41 8A 17 0F ED 42 E5 B5 36 E3 BB 34 5A 12 A3 " + + "7B 06 21 90 5C B7 07 1A F5 7B 59 5A E1 90 88 83 " + + "C8 43 1C 5B A7 52 E8 47 61 10 03 1D 71 A7 8F B0 " + + "8F 3B 0F 74 04 63 E1 64 7D 8C D1 78 C9 C6 89 EF " + + "1D 59 7A 79 07 8A F3 37 A6 7F 00 00 00 FF FF 03 " + + "00 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 21 " + + "00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 13 00 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B " + + "43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 " + + "6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 " + + "21 00 31 DD 5F 61 D2 00 00 00 8F 01 00 00 0B 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 2E 01 00 00 " + + "5F 72 65 6C 73 2F 2E 72 65 6C 73 50 4B 01 02 2D " + + "00 14 00 06 00 08 00 00 00 21 00 B5 19 FD 5B 97 " + + "02 00 00 FC 06 00 00 10 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 29 02 00 00 64 72 73 2F 73 68 61 " + + "70 65 78 6D 6C 2E 78 6D 6C 50 4B 01 02 2D 00 14 " + + "00 06 00 08 00 00 00 21 00 CA 39 EE E5 1C 01 00 " + + "00 8E 01 00 00 0F 00 00 00 00 00 00 00 00 00 00 " + + "00 00 00 EE 04 00 00 64 72 73 2F 64 6F 77 6E 72 " + + "65 76 2E 78 6D 6C 50 4B 05 06 00 00 00 00 04 00 " + + "04 00 F5 00 00 00 37 06 00 00 00 00 00 00 10 F0 " + + "12 00 00 00 00 00 02 00 10 02 03 00 CD 00 04 00 " + + "D0 03 0C 00 0D 00 00 00 11 F0 00 00 00 00 5D 00 " + + "1A 00 15 00 12 00 02 00 01 00 11 60 00 00 00 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 EC 00 E8 07 " + + "0F 00 04 F0 E0 07 00 00 12 00 0A F0 08 00 00 00 " + + "02 04 00 00 00 0A 00 00 83 00 0B F0 50 00 00 00 " + + "BF 00 18 00 1F 00 81 01 4F 81 BD 00 BF 01 10 00 " + + "10 00 C0 01 38 5D 8A 00 CB 01 38 63 00 00 FF 01 " + + "08 00 08 00 80 C3 20 00 00 00 BF 03 00 00 02 00 " + + "1F 04 40 04 4F 04 3C 04 3E 04 43 04 33 04 3E 04 " + + "3B 04 4C 04 3D 04 38 04 3A 04 20 00 32 00 00 00 " + + "23 00 22 F1 4E 07 00 00 FF 01 00 00 40 00 A9 C3 " + + "42 07 00 00 50 4B 03 04 14 00 06 00 08 00 00 00 " + + "21 00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 13 00 " + + "00 00 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 " + + "5D 2E 78 6D 6C 94 91 CD 4A C4 30 10 C7 EF 82 EF " + + "10 E6 2A 6D AA 07 11 69 BA 07 AB 47 15 5D 1F 60 " + + "48 A6 6D D8 36 09 99 58 77 DF DE 74 3F 2E E2 0A " + + "1E 67 E6 FF F1 23 A9 57 DB 69 14 33 45 B6 DE 29 " + + "B8 2E 2B 10 E4 B4 37 D6 F5 0A 3E D6 4F C5 1D 08 " + + "4E E8 0C 8E DE 91 82 1D 31 AC 9A CB 8B 7A BD 0B " + + "C4 22 BB 1D 2B 18 52 0A F7 52 B2 1E 68 42 2E 7D " + + "20 97 2F 9D 8F 13 A6 3C C6 5E 06 D4 1B EC 49 DE " + + "54 D5 AD D4 DE 25 72 A9 48 4B 06 34 75 4B 1D 7E " + + "8E 49 3C 6E F3 FA 40 12 69 64 10 0F 07 E1 D2 A5 " + + "00 43 18 AD C6 94 49 E5 EC CC 8F 96 E2 D8 50 66 " + + "E7 5E C3 83 0D 7C 95 31 40 FE DA B0 5C CE 17 1C " + + "7D 2F F9 69 A2 35 24 5E 31 A6 67 9C 32 86 34 91 " + + "25 0F 18 28 6B CA BF 53 16 CC 89 0B DF 75 56 53 " + + "D9 46 7E 5F 7C 27 A8 73 E1 C6 7F B9 48 F3 7F B3 " + + "DB 6C 7B A3 F9 94 2E F7 3F D4 7C 03 00 00 FF FF " + + "03 00 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 " + + "31 DD 5F 61 D2 00 00 00 8F 01 00 00 0B 00 00 00 " + + "5F 72 65 6C 73 2F 2E 72 65 6C 73 A4 90 C1 6A C3 " + + "30 0C 86 EF 83 BD 83 D1 BD 71 DA 43 19 A3 4E 6F " + + "85 5E 4B 07 BB 0A 5B 49 4C 63 CB 58 26 6D DF BE " + + "A6 30 58 46 6F 3B EA 17 FA 3E F1 EF F6 B7 30 A9 " + + "99 B2 78 8E 06 D6 4D 0B 8A A2 65 E7 E3 60 E0 EB " + + "7C 58 7D 80 92 82 D1 E1 C4 91 0C DC 49 60 DF BD " + + "BF ED 4E 34 61 A9 47 32 FA 24 AA 52 A2 18 18 4B " + + "49 9F 5A 8B 1D 29 A0 34 9C 28 D6 4D CF 39 60 A9 " + + "63 1E 74 42 7B C1 81 F4 A6 6D B7 3A FF 66 40 B7 " + + "60 AA A3 33 90 8F 6E 03 EA 7C 4F D5 FC 87 1D BC " + + "CD 2C DC 97 C6 72 D0 DC F7 DE BE A2 6A C7 D7 78 " + + "A2 B9 52 30 0F 54 0C B8 2C CF 30 D3 DC D4 E7 40 " + + "BF F6 AE FF E9 95 11 13 7D 57 FE 42 FC 4C AB F5 " + + "C7 AC 17 35 76 0F 00 00 00 FF FF 03 00 50 4B 03 " + + "04 14 00 06 00 08 00 00 00 21 00 54 76 AD 8A 97 " + + "02 00 00 FE 06 00 00 10 00 00 00 64 72 73 2F 73 " + + "68 61 70 65 78 6D 6C 2E 78 6D 6C AC 55 CD 8E D3 " + + "30 10 BE 23 F1 0E 96 EF BB F9 69 9B 2D 51 93 15 " + + "74 05 17 C4 56 5D F6 01 4C E2 B4 11 8E 1D D9 A6 " + + "3F 7B 42 E2 8A B4 8F C0 43 70 41 FC EC 33 A4 6F " + + "C4 D8 4E 52 60 81 C3 B6 3D A4 CE 4C 3C DF 37 DF " + + "CC D8 93 F3 4D C5 D0 8A 4A 55 0A 9E E0 E0 D4 C7 " + + "88 F2 4C E4 25 5F 24 F8 FA F5 F3 93 31 46 4A 13 " + + "9E 13 26 38 4D F0 96 2A 7C 9E 3E 7E 34 D9 E4 32 " + + "26 3C 5B 0A 89 20 04 57 31 18 12 BC D4 BA 8E 3D " + + "4F 65 4B 5A 11 75 2A 6A CA C1 5B 08 59 11 0D AF " + + "72 E1 E5 92 AC 21 78 C5 BC D0 F7 23 4F D5 92 92 " + + "5C 2D 29 D5 17 CE 83 53 1B 5B AF C5 94 32 F6 D4 " + + "42 38 53 21 45 E5 56 99 60 69 38 F1 0C 07 B3 B4 " + + "1B 60 71 59 14 E9 30 8A CE C2 51 EF 33 26 EB 96 " + + "62 9D 0E 9D D9 2C 3B 9B F1 07 C1 70 E0 FB BD CF " + + "6E B1 B1 F7 80 5A F4 20 E9 3E 78 6F B3 51 C2 C1 " + + "F8 5F C0 41 4B F6 1E 72 14 3C E9 F6 80 6F 8F DC " + + "E1 A9 1A 55 24 93 22 C1 18 69 BA D1 AC E4 6F 61 " + + "ED 80 F9 EA AA 9E C9 96 C4 AB D5 4C A2 32 4F F0 " + + "00 23 4E 2A 28 55 F3 69 F7 7E 77 DB 7C 6F EE 76 " + + "1F 9A CF CD 5D F3 6D F7 B1 F9 D1 7C 69 BE A2 10 " + + "7B FD 36 13 03 DE 6C C2 BF 46 54 36 36 89 37 85 " + + "AC DA 12 93 07 14 B8 22 25 07 BE 24 16 45 81 36 " + + "D0 62 D1 78 04 39 63 B4 4D F0 F8 2C 02 E1 0D 17 " + + "12 43 72 28 33 FE 21 F8 C1 88 32 F8 20 18 9D 05 " + + "11 7C 6C F8 39 26 E6 D3 5A 2A FD 82 8A 83 59 21 " + + "13 28 C1 92 66 DA 32 24 AB 97 4A 3B A8 0E A2 D5 " + + "C5 69 61 DA 4D E9 2D A3 86 04 E3 73 0A 09 D9 D6 " + + "7F B0 2E 50 30 48 39 B4 E8 76 66 E8 94 49 B4 22 " + + "2C C1 24 CB 28 D7 81 73 2D 49 4E 9D 79 E4 C3 AF " + + "D5 A3 DF 61 D5 B1 84 0C B3 A2 64 EC 68 DC 5A 02 " + + "66 9E EF 73 73 5A B5 78 B6 88 45 01 62 1E 0D DC " + + "FF 9F 30 0E 9C 76 88 36 73 C1 8F 07 5E 95 5C C8 " + + "BF 11 60 50 95 36 73 87 D7 35 89 6B 0D D3 25 7A " + + "F3 4C E4 5B 43 E9 0D FC C3 60 1E DA 27 70 42 EB " + + "4B 78 14 4C AC 13 9C B1 B2 C6 08 8E DE 9B 3F 6D " + + "52 B3 A9 80 EE 81 F9 71 87 73 82 B5 9B 2F A6 F4 " + + "95 21 78 28 15 C8 1C 26 F0 D0 28 36 08 E8 42 D8 " + + "02 AE 1D E6 28 52 9E CF 88 24 73 B0 33 62 EE 1F " + + "F9 EE 64 7E 0D F7 CF 0D 9C 04 41 DF F6 75 AB 77 " + + "27 B2 3D B9 14 58 ED 75 C0 4A 18 9B 0B A2 89 29 " + + "91 AD C5 EF 17 89 B5 39 6D D2 9F 00 00 00 FF FF " + + "03 00 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 " + + "88 BE 95 E9 1C 01 00 00 90 01 00 00 0F 00 00 00 " + + "64 72 73 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C 54 " + + "90 4D 4F C3 30 0C 86 EF 48 FC 87 C8 48 5C 10 4B " + + "3F D6 52 CA B2 69 20 A1 71 01 B1 AD 1C B8 85 26 " + + "5D 2B 9A A4 4A C2 DA FD 7B 3C 06 DA B8 F9 B5 FD " + + "D8 7E 3D 99 0D AA 25 5B 69 5D 63 34 83 70 14 00 " + + "91 BA 34 A2 D1 1B 06 C5 FA F1 3A 03 E2 3C D7 82 " + + "B7 46 4B 06 3B E9 60 36 3D 3F 9B F0 5C 98 5E 2F " + + "E5 76 E5 37 04 87 68 97 73 06 B5 F7 5D 4E A9 2B " + + "6B A9 B8 1B 99 4E 6A AC 55 C6 2A EE 51 DA 0D 15 " + + "96 F7 38 5C B5 34 0A 82 94 2A DE 68 DC 50 F3 4E " + + "3E D4 B2 FC 5C 7D 29 5C F2 AA DE 0A 73 9F BD 3F " + + "D3 AB A2 5F 2E D6 59 93 C4 19 63 97 17 C3 FC 0E " + + "88 97 83 3F 36 FF D2 4F 82 41 0C A4 5A EC 3E 6C " + + "23 96 DC 79 69 19 A0 1D 34 87 C6 60 8A 17 0F ED " + + "5C 97 B5 B1 FB B8 B2 46 11 6B 7A 06 63 20 A5 69 " + + "19 44 B0 D7 2F 55 E5 A4 47 22 1C C7 01 E2 58 FA " + + "4B 8D D3 F4 26 4A 80 EE 71 6F 0E 70 88 D4 0F 9D " + + "FC A7 D3 F0 16 5B 4F E9 30 8A B3 03 4D 4F 2F 41 " + + "71 7C E4 F4 1B 00 00 FF FF 03 00 50 4B 01 02 2D " + + "00 14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB FD " + + "00 00 00 E2 01 00 00 13 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 00 00 00 00 5B 43 6F 6E 74 65 6E " + + "74 5F 54 79 70 65 73 5D 2E 78 6D 6C 50 4B 01 02 " + + "2D 00 14 00 06 00 08 00 00 00 21 00 31 DD 5F 61 " + + "D2 00 00 00 8F 01 00 00 0B 00 00 00 00 00 00 00 " + + "00 00 00 00 00 00 2E 01 00 00 5F 72 65 6C 73 2F " + + "2E 72 65 6C 73 50 4B 01 02 2D 00 14 00 06 00 08 " + + "00 00 00 21 00 54 76 AD 8A 97 02 00 00 FE 06 00 " + + "00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 29 " + + "02 00 00 64 72 73 2F 73 68 61 70 65 78 6D 6C 2E " + + "78 6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 00 00 " + + "00 21 00 88 BE 95 E9 1C 01 00 00 90 01 00 00 0F " + + "00 00 00 00 00 00 00 00 00 00 00 00 00 EE 04 00 " + + "00 64 72 73 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C " + + "50 4B 05 06 00 00 00 00 04 00 04 00 F5 00 00 00 " + + "37 06 00 00 00 00 00 00 10 F0 12 00 00 00 00 00 " + + "02 00 10 03 04 00 9A 00 05 00 D0 00 0C 00 DA 00 " + + "00 00 11 F0 00 00 00 00 5D 00 1A 00 15 00 12 00 " + + "02 00 02 00 11 60 00 00 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 00 EC 00 E3 07 0F 00 04 F0 DB 07 " + + "00 00 12 00 0A F0 08 00 00 00 03 04 00 00 00 0A " + + "00 00 83 00 0B F0 50 00 00 00 BF 00 18 00 1F 00 " + + "81 01 4F 81 BD 00 BF 01 10 00 10 00 C0 01 38 5D " + + "8A 00 CB 01 38 63 00 00 FF 01 08 00 08 00 80 C3 " + + "20 00 00 00 BF 03 00 00 02 00 1F 04 40 04 4F 04 " + + "3C 04 3E 04 43 04 33 04 3E 04 3B 04 4C 04 3D 04 " + + "38 04 3A 04 20 00 33 00 00 00 23 00 22 F1 49 07 " + + "00 00 FF 01 00 00 40 00 A9 C3 3D 07 00 00 50 4B " + + "03 04 14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB " + + "FD 00 00 00 E2 01 00 00 13 00 00 00 5B 43 6F 6E " + + "74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D 6C 94 " + + "91 CD 4A C4 30 10 C7 EF 82 EF 10 E6 2A 6D AA 07 " + + "11 69 BA 07 AB 47 15 5D 1F 60 48 A6 6D D8 36 09 " + + "99 58 77 DF DE 74 3F 2E E2 0A 1E 67 E6 FF F1 23 " + + "A9 57 DB 69 14 33 45 B6 DE 29 B8 2E 2B 10 E4 B4 " + + "37 D6 F5 0A 3E D6 4F C5 1D 08 4E E8 0C 8E DE 91 " + + "82 1D 31 AC 9A CB 8B 7A BD 0B C4 22 BB 1D 2B 18 " + + "52 0A F7 52 B2 1E 68 42 2E 7D 20 97 2F 9D 8F 13 " + + "A6 3C C6 5E 06 D4 1B EC 49 DE 54 D5 AD D4 DE 25 " + + "72 A9 48 4B 06 34 75 4B 1D 7E 8E 49 3C 6E F3 FA " + + "40 12 69 64 10 0F 07 E1 D2 A5 00 43 18 AD C6 94 " + + "49 E5 EC CC 8F 96 E2 D8 50 66 E7 5E C3 83 0D 7C " + + "95 31 40 FE DA B0 5C CE 17 1C 7D 2F F9 69 A2 35 " + + "24 5E 31 A6 67 9C 32 86 34 91 25 0F 18 28 6B CA " + + "BF 53 16 CC 89 0B DF 75 56 53 D9 46 7E 5F 7C 27 " + + "A8 73 E1 C6 7F B9 48 F3 7F B3 DB 6C 7B A3 F9 94 " + + "2E F7 3F D4 7C 03 00 00 FF FF 03 00 50 4B 03 04 " + + "14 00 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 " + + "00 00 8F 01 00 00 0B 00 00 00 5F 72 65 6C 73 2F " + + "2E 72 65 6C 73 A4 90 C1 6A C3 30 0C 86 EF 83 BD " + + "83 D1 BD 71 DA 43 19 A3 4E 6F 85 5E 4B 07 BB 0A " + + "5B 49 4C 63 CB 58 26 6D DF BE A6 30 58 46 6F 3B " + + "EA 17 FA 3E F1 EF F6 B7 30 A9 99 B2 78 8E 06 D6 " + + "4D 0B 8A A2 65 E7 E3 60 E0 EB 7C 58 7D 80 92 82 " + + "D1 E1 C4 91 0C DC 49 60 DF BD BF ED 4E 34 61 A9 " + + "47 32 FA 24 AA 52 A2 18 18 4B 49 9F 5A 8B 1D 29 " + + "A0 34 9C 28 D6 4D CF 39 60 A9 63 1E 74 42 7B C1 " + + "81 F4 A6 6D B7 3A FF 66 40 B7 60 AA A3 33 90 8F " + + "6E 03 EA 7C 4F D5 FC 87 1D BC CD 2C DC 97 C6 72 " + + "D0 DC F7 DE BE A2 6A C7 D7 78 A2 B9 52 30 0F 54 " + + "0C B8 2C CF 30 D3 DC D4 E7 40 BF F6 AE FF E9 95 " + + "11 13 7D 57 FE 42 FC 4C AB F5 C7 AC 17 35 76 0F " + + "00 00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 08 " + + "00 00 00 21 00 B1 89 CE 0F 93 02 00 00 FC 06 00 " + + "00 10 00 00 00 64 72 73 2F 73 68 61 70 65 78 6D " + + "6C 2E 78 6D 6C AC 55 4B 6E DB 30 10 DD 17 E8 1D " + + "08 EE 13 7D 1C D9 8A 60 29 68 1D B4 9B A2 31 9C " + + "E6 00 AC 44 D9 42 29 52 20 59 7F B2 2A D0 6D 81 " + + "1E A1 87 E8 A6 E8 27 67 90 6F D4 21 29 B9 8D FB " + + "59 C4 F6 C2 1E CF 70 E6 BD F9 91 E3 8B 75 CD D0 " + + "92 4A 55 09 9E E2 E0 D4 C7 88 F2 5C 14 15 9F A7 " + + "F8 E6 D5 B3 93 18 23 A5 09 2F 08 13 9C A6 78 43 " + + "15 BE C8 1E 3F 1A AF 0B 99 10 9E 2F 84 44 10 82 " + + "AB 04 14 29 5E 68 DD 24 9E A7 F2 05 AD 89 3A 15 " + + "0D E5 60 2D 85 AC 89 86 BF 72 EE 15 92 AC 20 78 " + + "CD BC D0 F7 87 9E 6A 24 25 85 5A 50 AA 2F 9D 05 " + + "67 36 B6 5E 89 09 65 EC 89 85 70 AA 52 8A DA 49 " + + "B9 60 D9 60 EC 19 0E 46 B4 0E 20 5C 95 65 76 1E " + + "85 D1 CE 62 14 D6 28 C5 2A EB D4 46 EC 75 C6 3E " + + "1A 02 11 E7 01 26 EB 61 03 FF 42 D3 62 87 D0 07 " + + "D9 47 0D 21 CA BF 70 83 8E E9 3E 70 10 0E E2 DE " + + "E7 1E 72 8F A7 1A 54 93 5C 8A 14 63 A4 E9 5A B3 " + + "8A BF 01 D9 91 E1 CB EB 66 2A 3B 62 2F 97 53 89 " + + "AA 22 C5 67 18 71 52 43 9F DA 4F DB 77 DB 8F ED " + + "F7 F6 6E FB BE FD DC DE B5 DF B6 1F DA 1F ED 97 " + + "F6 2B 1A 60 6F E7 66 62 C0 3F 9B F0 EF 11 95 8D " + + "4D 92 75 29 EB AE BF E4 01 DD AD 49 C5 81 2F 49 " + + "44 59 A2 35 CC 57 3C 88 07 61 84 D1 06 64 3F 8C " + + "47 BE 6F C8 90 04 B2 43 B9 39 70 16 47 E7 A0 44 " + + "B9 39 11 8D 82 21 9C 36 04 1D 15 73 B4 91 4A 3F " + + "A7 E2 60 5A C8 04 4A B1 A4 B9 B6 14 C9 F2 85 D2 " + + "0E AA 87 E8 0A E3 8A 61 86 4D E9 0D A3 86 04 E3 " + + "33 0A 19 D9 C1 7F 70 61 A0 63 90 72 68 D1 ED C6 " + + "D0 09 93 68 49 58 8A 49 9E 53 AE 03 67 5A 90 82 " + + "3A 75 E4 C3 A7 AB C7 CE C3 56 C7 12 32 CC CA 8A " + + "B1 A3 71 EB 08 98 6D FE 93 9B AB 55 87 67 9B 58 " + + "96 50 CC A3 81 FB FF 2B 8C 03 A7 3D A2 CD 5C F0 " + + "E3 81 D7 15 17 F2 6F 04 18 74 A5 CB DC E1 F5 43 " + + "E2 46 C3 4C 89 5E 3F 15 C5 C6 50 7A 0D BF B0 99 " + + "87 CE 09 DC CF FA 0A BE 4A 26 56 29 CE 59 D5 60 " + + "04 17 EF ED BE 4E 6A 36 11 30 3D B0 3F EE 6A 4E " + + "B1 76 FB C5 94 BE 36 04 0F A5 02 99 C3 06 1E 1A " + + "C5 06 81 BA 10 36 87 47 87 39 8A 94 17 53 22 C9 " + + "0C F4 8C 98 D7 47 BE 3D 99 DD C0 EB 73 0B 37 41 " + + "B0 1B FB A6 AB 77 5F 64 7B 75 29 D0 DA C7 80 55 " + + "B0 36 97 44 13 D3 22 DB 8B FB CF 88 D5 B9 DA 64 " + + "3F 01 00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 " + + "08 00 00 00 21 00 48 FA 47 DC 1B 01 00 00 8D 01 " + + "00 00 0F 00 00 00 64 72 73 2F 64 6F 77 6E 72 65 " + + "76 2E 78 6D 6C 4C 90 CB 4E C3 30 10 45 F7 48 FC " + + "83 35 48 6C 10 75 92 92 12 42 9D AA 20 A1 B2 01 " + + "91 36 2C D8 99 C4 79 88 D8 8E 6C D3 A4 7F CF A4 " + + "A5 6A 77 BE BE 73 EE 3C E6 8B 41 B6 64 2B 8C 6D " + + "B4 62 E0 4F 3C 20 42 E5 BA 68 54 C5 20 DB BC DC " + + "46 40 AC E3 AA E0 AD 56 82 C1 4E 58 58 24 97 17 " + + "73 1E 17 BA 57 A9 D8 AE 5D 45 30 44 D9 98 33 A8 " + + "9D EB 62 4A 6D 5E 0B C9 ED 44 77 42 A1 57 6A 23 " + + "B9 43 69 2A 5A 18 DE 63 B8 6C 69 E0 79 33 2A 79 " + + "A3 B0 43 CD 3B F1 5C 8B FC 67 FD 2B B1 C9 87 FC " + + "CC F4 53 F4 F5 46 6F B2 3E 5D 6D A2 26 9C 46 8C " + + "5D 5F 0D CB 47 20 4E 0C EE 54 FC 4F BF 16 0C EE " + + "80 94 AB DD B7 69 8A 94 5B 27 0C 03 5C 07 97 C3 " + + "C5 20 C1 89 87 76 A9 F2 5A 9B F1 5D 1A 2D 89 D1 " + + "3D 83 10 48 AE 5B 06 53 18 F5 7B 59 5A E1 18 DC " + + "CF 70 BE BD 73 FC 79 08 83 10 E8 C8 3A 7D 20 7D " + + "44 F6 28 46 9C A1 7E 30 8D B0 74 B4 8E 6C 80 71 " + + "07 9A 9E 8F 81 E2 74 C5 E4 0F 00 00 FF FF 03 00 " + + "50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 21 00 " + + "F0 F7 8A BB FD 00 00 00 E2 01 00 00 13 00 00 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B 43 " + + "6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D " + + "6C 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 21 " + + "00 31 DD 5F 61 D2 00 00 00 8F 01 00 00 0B 00 00 " + + "00 00 00 00 00 00 00 00 00 00 00 2E 01 00 00 5F " + + "72 65 6C 73 2F 2E 72 65 6C 73 50 4B 01 02 2D 00 " + + "14 00 06 00 08 00 00 00 21 00 B1 89 CE 0F 93 02 " + + "00 00 FC 06 00 00 10 00 00 00 00 00 00 00 00 00 " + + "00 00 00 00 29 02 00 00 64 72 73 2F 73 68 61 70 " + + "65 78 6D 6C 2E 78 6D 6C 50 4B 01 02 2D 00 14 00 " + + "06 00 08 00 00 00 21 00 48 FA 47 DC 1B 01 00 00 " + + "8D 01 00 00 0F 00 00 00 00 00 00 00 00 00 00 00 " + + "00 00 EA 04 00 00 64 72 73 2F 64 6F 77 6E 72 65 " + + "76 2E 78 6D 6C 50 4B 05 06 00 00 00 00 04 00 04 " + + "00 F5 00 00 00 32 06 00 00 00 00 00 00 10 F0 12 " + + "00 00 00 00 00 03 00 10 00 05 00 66 00 05 00 D0 " + + "01 0D 00 A6 00 00 00 11 F0 00 00 00 00 5D 00 1A " + + "00 15 00 12 00 02 00 03 00 11 60 00 00 00 00 00 " + + "00 00 00 00 00 00 00 00 00 00 00 EC 00 E8 07 0F " + + "00 04 F0 E0 07 00 00 12 00 0A F0 08 00 00 00 04 " + + "04 00 00 00 0A 00 00 83 00 0B F0 50 00 00 00 BF " + + "00 18 00 1F 00 81 01 4F 81 BD 00 BF 01 10 00 10 " + + "00 C0 01 38 5D 8A 00 CB 01 38 63 00 00 FF 01 08 " + + "00 08 00 80 C3 20 00 00 00 BF 03 00 00 02 00 1F " + + "04 40 04 4F 04 3C 04 3E 04 43 04 33 04 3E 04 3B " + + "04 4C 04 3D 04 38 04 3A 04 20 00 34 00 00 00 23 " + + "00 22 F1 4E 07 00 00 FF 01 00 00 40 00 A9 C3 42 " + + "07 00 00 50 4B 03 04 14 00 06 00 08 00 00 00 21 " + + "00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 13 00 00 " + + "00 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D " + + "2E 78 6D 6C 94 91 CD 4A C4 30 10 C7 EF 82 EF 10 " + + "E6 2A 6D AA 07 11 69 BA 07 AB 47 15 5D 1F 60 48 " + + "A6 6D D8 36 09 99 58 77 DF DE 74 3F 2E E2 0A 1E " + + "67 E6 FF F1 23 A9 57 DB 69 14 33 45 B6 DE 29 B8 " + + "2E 2B 10 E4 B4 37 D6 F5 0A 3E D6 4F C5 1D 08 4E " + + "E8 0C 8E DE 91 82 1D 31 AC 9A CB 8B 7A BD 0B C4 " + + "22 BB 1D 2B 18 52 0A F7 52 B2 1E 68 42 2E 7D 20 " + + "97 2F 9D 8F 13 A6 3C C6 5E 06 D4 1B EC 49 DE 54 " + + "D5 AD D4 DE 25 72 A9 48 4B 06 34 75 4B 1D 7E 8E " + + "49 3C 6E F3 FA 40 12 69 64 10 0F 07 E1 D2 A5 00 " + + "43 18 AD C6 94 49 E5 EC CC 8F 96 E2 D8 50 66 E7 " + + "5E C3 83 0D 7C 95 31 40 FE DA B0 5C CE 17 1C 7D " + + "2F F9 69 A2 35 24 5E 31 A6 67 9C 32 86 34 91 25 " + + "0F 18 28 6B CA BF 53 16 CC 89 0B DF 75 56 53 D9 " + + "46 7E 5F 7C 27 A8 73 E1 C6 7F B9 48 F3 7F B3 DB " + + "6C 7B A3 F9 94 2E F7 3F D4 7C 03 00 00 FF FF 03 " + + "00 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 31 " + + "DD 5F 61 D2 00 00 00 8F 01 00 00 0B 00 00 00 5F " + + "72 65 6C 73 2F 2E 72 65 6C 73 A4 90 C1 6A C3 30 " + + "0C 86 EF 83 BD 83 D1 BD 71 DA 43 19 A3 4E 6F 85 " + + "5E 4B 07 BB 0A 5B 49 4C 63 CB 58 26 6D DF BE A6 " + + "30 58 46 6F 3B EA 17 FA 3E F1 EF F6 B7 30 A9 99 " + + "B2 78 8E 06 D6 4D 0B 8A A2 65 E7 E3 60 E0 EB 7C " + + "58 7D 80 92 82 D1 E1 C4 91 0C DC 49 60 DF BD BF " + + "ED 4E 34 61 A9 47 32 FA 24 AA 52 A2 18 18 4B 49 " + + "9F 5A 8B 1D 29 A0 34 9C 28 D6 4D CF 39 60 A9 63 " + + "1E 74 42 7B C1 81 F4 A6 6D B7 3A FF 66 40 B7 60 " + + "AA A3 33 90 8F 6E 03 EA 7C 4F D5 FC 87 1D BC CD " + + "2C DC 97 C6 72 D0 DC F7 DE BE A2 6A C7 D7 78 A2 " + + "B9 52 30 0F 54 0C B8 2C CF 30 D3 DC D4 E7 40 BF " + + "F6 AE FF E9 95 11 13 7D 57 FE 42 FC 4C AB F5 C7 " + + "AC 17 35 76 0F 00 00 00 FF FF 03 00 50 4B 03 04 " + + "14 00 06 00 08 00 00 00 21 00 CC C2 D3 C8 98 02 " + + "00 00 FD 06 00 00 10 00 00 00 64 72 73 2F 73 68 " + + "61 70 65 78 6D 6C 2E 78 6D 6C AC 55 4B 6E DB 30 " + + "10 DD 17 E8 1D 08 EE 13 49 8E E5 C8 82 A5 A0 75 " + + "D0 6E 8A C6 70 9A 03 B0 12 65 0B A5 48 81 64 FD " + + "C9 AA 40 B7 05 7A 84 1E A2 9B A2 9F 9C 41 BE 51 " + + "87 A4 24 37 FD 2D 62 7B 61 D3 33 E4 BC 37 6F 66 " + + "C8 C9 C5 A6 62 68 45 A5 2A 05 4F 70 70 EA 63 44 " + + "79 26 F2 92 2F 12 7C F3 EA D9 49 84 91 D2 84 E7 " + + "84 09 4E 13 BC A5 0A 5F A4 8F 1F 4D 36 B9 8C 09 " + + "CF 96 42 22 08 C1 55 0C 86 04 2F B5 AE 63 CF 53 " + + "D9 92 56 44 9D 8A 9A 72 F0 16 42 56 44 C3 5F B9 " + + "F0 72 49 D6 10 BC 62 DE C0 F7 47 9E AA 25 25 B9 " + + "5A 52 AA 2F 9D 07 A7 36 B6 5E 8B 29 65 EC 89 85 " + + "70 A6 42 8A CA AD 32 C1 D2 B3 89 67 38 98 A5 3D " + + "00 8B AB A2 48 83 51 30 1E 84 BD CF 98 AC 5B 8A " + + "75 3A 72 66 B3 EC 6C C6 7F 16 05 BE DF BB EC 09 " + + "1B 7A 8F A7 45 8F 91 EE 63 F7 36 73 64 38 88 46 " + + "FF C2 0D 86 7D F4 7B C0 51 78 DE 1D 01 4E 7B E0 " + + "0E 4E D5 A8 22 99 14 09 C6 48 D3 8D 66 25 7F 03 " + + "6B 17 83 AF AE EB 99 6C 39 BC 5C CD 24 2A F3 04 " + + "87 18 71 52 41 A1 9A 4F BB 77 BB 8F CD F7 E6 6E " + + "F7 BE F9 DC DC 35 DF 76 1F 9A 1F CD 97 E6 2B 1A " + + "62 AF 3F 66 62 C0 3F 9B EF AF 11 95 8D 4D E2 4D " + + "21 AB B6 C0 E4 01 E5 AD 48 C9 81 2F 89 45 51 A0 " + + "0D 34 D8 78 EC 43 CE 18 6D 61 1D 44 01 08 6F C8 " + + "90 18 B2 43 99 D9 30 8C C2 31 18 51 66 76 84 E7 " + + "01 88 6A 76 78 8E 8A D9 5A 4B A5 9F 53 71 30 2D " + + "64 02 25 58 D2 4C 5B 8A 64 F5 42 69 07 D5 41 B4 " + + "C2 38 31 4C B7 29 BD 65 D4 90 60 7C 4E 21 23 DB " + + "F9 0F 16 06 2A 06 29 0F 2C BA 1D 19 3A 65 12 AD " + + "08 4B 30 C9 32 CA 75 E0 5C 4B 92 53 67 0E 7D F8 " + + "B4 7A F4 27 AC 3A 96 90 61 56 94 8C 1D 8D 5B 4B " + + "C0 8C F3 9F DC 9C 56 2D 9E 2D 62 51 80 98 47 03 " + + "F7 FF 27 8C 03 A7 1D A2 CD 5C F0 E3 81 57 25 17 " + + "F2 6F 04 18 54 A5 CD DC E1 75 4D E2 5A C3 74 89 " + + "DE 3C 15 F9 D6 50 7A 0D BF 30 99 87 F6 09 5C D0 " + + "FA 0A BE 0A 26 D6 09 CE 58 59 63 04 37 EF ED EF " + + "36 A9 D9 54 40 F7 C0 FC B8 BB 39 C1 DA CD 17 53 " + + "FA DA 10 3C 94 0A 64 0E 13 78 68 14 1B 04 74 21 " + + "6C 01 AF 0E 73 14 29 CF 67 44 92 39 D8 19 31 CF " + + "8F 7C 7B 32 BF 81 E7 E7 D6 DC 15 7D DB D7 AD DE " + + "9D C8 F6 EA 52 60 B5 AF 01 2B 61 6C 2E 89 26 A6 " + + "44 B6 16 F7 DF 11 6B 73 DA A4 3F 01 00 00 FF FF " + + "03 00 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 " + + "A9 7A 63 39 1B 01 00 00 8E 01 00 00 0F 00 00 00 " + + "64 72 73 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C 4C " + + "90 CD 4E C3 30 10 84 EF 48 BC 83 B5 48 5C 10 75 " + + "D2 36 C1 84 BA 55 41 42 ED 05 44 DA 70 E0 66 12 " + + "E7 47 C4 76 65 9B 26 7D 7B 36 6A 51 7B F3 78 F7 " + + "DB D9 D9 D9 A2 57 2D D9 4B EB 1A A3 39 84 A3 00 " + + "88 D4 B9 29 1A 5D 71 C8 B6 AF F7 0C 88 F3 42 17 " + + "A2 35 5A 72 38 48 07 8B F9 F5 D5 4C 24 85 E9 74 " + + "2A F7 1B 5F 11 1C A2 5D 22 38 D4 DE EF 12 4A 5D " + + "5E 4B 25 DC C8 EC A4 C6 5A 69 AC 12 1E A5 AD 68 " + + "61 45 87 C3 55 4B C7 41 10 53 25 1A 8D 0E B5 D8 " + + "C9 97 5A E6 3F 9B 5F 85 26 1F EA 33 33 CF EC EB " + + "8D DE 65 5D BA DA B2 26 9A 30 CE 6F 6F FA E5 13 " + + "10 2F 7B 7F 6E 3E D1 EB 82 43 04 A4 5C 1D BE 6D " + + "53 A4 C2 79 69 39 60 1C 0C 87 C1 60 8E 1B F7 ED " + + "52 E7 B5 B1 C3 BB B4 46 11 6B 3A 0E 31 90 DC B4 " + + "1C 26 30 E8 F7 B2 74 D2 A3 62 61 80 34 56 FE 7F " + + "C2 38 7C 1C 47 40 07 DA 9B 23 1B 4E 4F 30 5A 5F " + + "C0 2C 7A C0 CE 4B 78 3A 66 F1 11 A6 97 7B A0 38 " + + "9F 71 FE 07 00 00 FF FF 03 00 50 4B 01 02 2D 00 " + + "14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB FD 00 " + + "00 00 E2 01 00 00 13 00 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 00 00 00 5B 43 6F 6E 74 65 6E 74 " + + "5F 54 79 70 65 73 5D 2E 78 6D 6C 50 4B 01 02 2D " + + "00 14 00 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 " + + "00 00 00 8F 01 00 00 0B 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 2E 01 00 00 5F 72 65 6C 73 2F 2E " + + "72 65 6C 73 50 4B 01 02 2D 00 14 00 06 00 08 00 " + + "00 00 21 00 CC C2 D3 C8 98 02 00 00 FD 06 00 00 " + + "10 00 00 00 00 00 00 00 00 00 00 00 00 00 29 02 " + + "00 00 64 72 73 2F 73 68 61 70 65 78 6D 6C 2E 78 " + + "6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 " + + "21 00 A9 7A 63 39 1B 01 00 00 8E 01 00 00 0F 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 EF 04 00 00 " + + "64 72 73 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C 50 " + + "4B 05 06 00 00 00 00 04 00 04 00 F5 00 00 00 37 " + + "06 00 00 00 00 00 00 10 F0 12 00 00 00 00 00 03 " + + "00 10 01 06 00 33 00 05 00 D0 02 0E 00 73 00 00 " + + "00 11 F0 00 00 00 00 5D 00 1A 00 15 00 12 00 02 " + + "00 04 00 11 60 00 00 00 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 3C 00 E5 07 0F 00 04 F0 DD 07 00 " + + "00 12 00 0A F0 08 00 00 00 05 04 00 00 00 0A 00 " + + "00 83 00 0B F0 50 00 00 00 BF 00 18 00 1F 00 81 " + + "01 4F 81 BD 00 BF 01 10 00 10 00 C0 01 38 5D 8A " + + "00 CB 01 38 63 00 00 FF 01 08 00 08 00 80 C3 20 " + + "00 00 00 BF 03 00 00 02 00 1F 04 40 04 4F 04 3C " + + "04 3E 04 43 04 33 04 3E 04 3B 04 4C 04 3D 04 38 " + + "04 3A 04 20 00 35 00 00 00 23 00 22 F1 4B 07 00 " + + "00 FF 01 00 00 40 00 A9 C3 3F 07 00 00 50 4B 03 " + + "04 14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB FD " + + "00 00 00 E2 01 00 00 13 00 00 00 5B 43 6F 6E 74 " + + "65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D 6C 94 91 " + + "CD 4A C4 30 10 C7 EF 82 EF 10 E6 2A 6D AA 07 11 " + + "69 BA 07 AB 47 15 5D 1F 60 48 A6 6D D8 36 09 99 " + + "58 77 DF DE 74 3F 2E E2 0A 1E 67 E6 FF F1 23 A9 " + + "57 DB 69 14 33 45 B6 DE 29 B8 2E 2B 10 E4 B4 37 " + + "D6 F5 0A 3E D6 4F C5 1D 08 4E E8 0C 8E DE 91 82 " + + "1D 31 AC 9A CB 8B 7A BD 0B C4 22 BB 1D 2B 18 52 " + + "0A F7 52 B2 1E 68 42 2E 7D 20 97 2F 9D 8F 13 A6 " + + "3C C6 5E 06 D4 1B EC 49 DE 54 D5 AD D4 DE 25 72 " + + "A9 48 4B 06 34 75 4B 1D 7E 8E 49 3C 6E F3 FA 40 " + + "12 69 64 10 0F 07 E1 D2 A5 00 43 18 AD C6 94 49 " + + "E5 EC CC 8F 96 E2 D8 50 66 E7 5E C3 83 0D 7C 95 " + + "31 40 FE DA B0 5C CE 17 1C 7D 2F F9 69 A2 35 24 " + + "5E 31 A6 67 9C 32 86 34 91 25 0F 18 28 6B CA BF " + + "53 16 CC 89 0B DF 75 56 53 D9 46 7E 5F 7C 27 A8 " + + "73 E1 C6 7F B9 48 F3 7F B3 DB 6C 7B A3 F9 94 2E " + + "F7 3F D4 7C 03 00 00 FF FF 03 00 50 4B 03 04 14 " + + "00 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 00 " + + "00 8F 01 00 00 0B 00 00 00 5F 72 65 6C 73 2F 2E " + + "72 65 6C 73 A4 90 C1 6A C3 30 0C 86 EF 83 BD 83 " + + "D1 BD 71 DA 43 19 A3 4E 6F 85 5E 4B 07 BB 0A 5B " + + "49 4C 63 CB 58 26 6D DF BE A6 30 58 46 6F 3B EA " + + "17 FA 3E F1 EF F6 B7 30 A9 99 B2 78 8E 06 D6 4D " + + "0B 8A A2 65 E7 E3 60 E0 EB 7C 58 7D 80 92 82 D1 " + + "E1 C4 91 0C DC 49 60 DF BD BF ED 4E 34 61 A9 47 " + + "32 FA 24 AA 52 A2 18 18 4B 49 9F 5A 8B 1D 29 A0 " + + "34 9C 28 D6 4D CF 39 60 A9 63 1E 74 42 7B C1 81 " + + "F4 A6 6D B7 3A FF 66 40 B7 60 AA A3 33 90 8F 6E " + + "03 EA 7C 4F D5 FC 87 1D BC CD 2C DC 97 C6 72 D0 " + + "DC F7 DE BE A2 6A C7 D7 78 A2 B9 52 30 0F 54 0C " + + "B8 2C CF 30 D3 DC D4 E7 40 BF F6 AE FF E9 95 11 " + + "13 7D 57 FE 42 FC 4C AB F5 C7 AC 17 35 76 0F 00 " + + "00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 08 00 " + + "00 00 21 00 D1 22 B3 C1 96 02 00 00 F9 06 00 00 " + + "10 00 00 00 64 72 73 2F 73 68 61 70 65 78 6D 6C " + + "2E 78 6D 6C AC 55 4B 6E DB 30 10 DD 17 E8 1D 08 " + + "EE 13 49 96 E5 B8 82 A5 A0 75 D0 6E 8A C6 70 9A " + + "03 B0 12 65 0B A5 48 81 64 FD C9 AA 40 B7 05 72 " + + "84 1E A2 9B A2 9F 9C 41 BE 51 87 A4 24 B7 E9 67 " + + "11 7B 63 53 33 9C 79 8F 6F 66 C8 C9 F9 A6 62 68 " + + "45 A5 2A 05 4F 70 70 EA 63 44 79 26 F2 92 2F 12 " + + "7C FD FA F9 C9 18 23 A5 09 CF 09 13 9C 26 78 4B " + + "15 3E 4F 1F 3F 9A 6C 72 19 13 9E 2D 85 44 90 82 " + + "AB 18 0C 09 5E 6A 5D C7 9E A7 B2 25 AD 88 3A 15 " + + "35 E5 E0 2D 84 AC 88 86 4F B9 F0 72 49 D6 90 BC " + + "62 DE C0 F7 47 9E AA 25 25 B9 5A 52 AA 2F 9C 07 " + + "A7 36 B7 5E 8B 29 65 EC A9 85 70 A6 42 8A CA AD " + + "32 C1 D2 70 E2 19 0E 66 69 03 60 71 59 14 69 18 " + + "0C C3 41 D4 FB 8C C9 BA A5 58 A7 67 CE 6C 96 9D " + + "CD F8 FD DE 6C 77 DB B4 7B 2C 2D FA FC E9 3E 6F " + + "6F 33 21 D1 38 F0 FF 85 19 B4 31 F7 41 87 67 A3 " + + "2E 04 5C 7B E0 0E 4E D5 A8 22 99 14 09 C6 48 D3 " + + "8D 66 25 7F 0B 6B 87 CB 57 57 F5 4C B6 1C 5E AD " + + "66 12 95 79 82 47 18 71 52 41 91 9A 4F BB F7 BB " + + "DB E6 7B 73 B7 FB D0 7C 6E EE 9A 6F BB 8F CD 8F " + + "E6 4B F3 15 45 D8 EB C3 4C 0E F8 B2 E7 FD 35 A3 " + + "B2 B9 49 BC 29 64 D5 16 97 3C A0 B4 15 29 39 F0 " + + "25 B1 28 0A B4 49 F0 00 2A 13 0C 22 8C B6 D0 68 " + + "61 18 46 BE 6F C8 90 18 4E 87 32 D8 10 0C C7 D1 " + + "13 30 A2 CC EC 88 CE 02 50 C8 EC F0 1C 15 B3 B5 " + + "96 4A BF A0 E2 60 5A C8 24 4A B0 A4 99 B6 14 C9 " + + "EA A5 D2 0E AA 83 68 85 71 62 98 4E 53 7A CB A8 " + + "21 C1 F8 9C C2 89 6C D7 3F 58 18 A8 98 D1 C4 A2 " + + "DB 71 A1 53 26 D1 8A B0 04 93 2C A3 5C 07 CE B5 " + + "24 39 75 66 D0 CB 29 06 7A F4 11 56 1D 4B C8 30 " + + "2B 4A C6 8E C6 AD 25 60 46 F9 4F 6E 4E AB 16 CF " + + "16 B1 28 40 CC A3 81 FB FF 13 C6 81 D3 0E D1 9E " + + "5C F0 E3 81 57 25 17 F2 6F 04 18 54 A5 3D B9 C3 " + + "EB 9A C4 B5 86 E9 12 BD 79 26 F2 AD A1 F4 06 FE " + + "61 32 0F ED 13 B8 9C F5 25 FC 14 4C AC 13 9C B1 " + + "B2 C6 08 6E DD 9B FB 36 A9 D9 54 40 F7 C0 FC B8 " + + "7B 39 C1 DA CD 17 53 FA CA 10 3C 94 0A 9C 1C 26 " + + "F0 D0 2C 36 09 E8 42 D8 02 5E 1C D6 5E 01 3C 9F " + + "11 49 E6 60 67 C4 3C 3D F2 DD C9 FC 1A 9E 9E 1B " + + "B8 09 82 BE ED EB 56 EF 4E 64 7B 75 29 B0 DA 97 " + + "80 95 30 36 17 44 13 53 22 5B 8B DF DF 10 6B 73 " + + "DA A4 3F 01 00 00 FF FF 03 00 50 4B 03 04 14 00 " + + "06 00 08 00 00 00 21 00 EA 0B 8D A0 1A 01 00 00 " + + "8A 01 00 00 0F 00 00 00 64 72 73 2F 64 6F 77 6E " + + "72 65 76 2E 78 6D 6C 4C 90 5F 4F C2 30 14 C5 DF " + + "4D FC 0E CD 35 F1 C5 48 37 C6 60 99 74 04 4D 0C " + + "BE 68 04 E6 83 6F 75 EB FE C4 B5 5D DA CA C6 B7 " + + "E7 4E 20 F0 D4 9E DB FB 3B F7 9E CE 17 BD 6C C8 " + + "4E 18 5B 6B C5 C0 1F 79 40 84 CA 74 5E AB 92 41 " + + "BA 7D 7D 8C 80 58 C7 55 CE 1B AD 04 83 BD B0 B0 " + + "48 6E 6F E6 3C CE 75 A7 D6 62 B7 71 25 41 13 65 " + + "63 CE A0 72 AE 8D 29 B5 59 25 24 B7 23 DD 0A 85 " + + "6F 85 36 92 3B 94 A6 A4 B9 E1 1D 9A CB 86 8E 3D " + + "6F 4A 25 AF 15 4E A8 78 2B 5E 2A 91 FD 6E FE 24 " + + "0E F9 94 5F A9 7E 8E BE DF E9 43 DA AD 57 DB A8 " + + "0E 83 88 B1 FB BB 7E F9 04 C4 89 DE 5D 9A 4F F4 " + + "5B CE 60 0A A4 58 ED 7F 4C 9D AF B9 75 C2 30 C0 " + + "38 18 0E 83 41 82 1B F7 CD 52 65 95 36 C3 BD 30 " + + "5A 12 A3 3B 06 33 20 99 6E 18 04 30 E8 8F A2 B0 " + + "C2 FD 93 58 3D AB C0 9F 04 E3 10 E8 40 3A 7D E4 " + + "FC F0 04 E2 79 05 4E 66 53 EC 1C 2C CF 70 18 F9 " + + "DE 11 A6 D7 3B A0 B8 7C 61 72 00 00 00 FF FF 03 " + + "00 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 21 " + + "00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 13 00 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5B " + + "43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 " + + "6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 " + + "21 00 31 DD 5F 61 D2 00 00 00 8F 01 00 00 0B 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 2E 01 00 00 " + + "5F 72 65 6C 73 2F 2E 72 65 6C 73 50 4B 01 02 2D " + + "00 14 00 06 00 08 00 00 00 21 00 D1 22 B3 C1 96 " + + "02 00 00 F9 06 00 00 10 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 29 02 00 00 64 72 73 2F 73 68 61 " + + "70 65 78 6D 6C 2E 78 6D 6C 50 4B 01 02 2D 00 14 " + + "00 06 00 08 00 00 00 21 00 EA 0B 8D A0 1A 01 00 " + + "00 8A 01 00 00 0F 00 00 00 00 00 00 00 00 00 00 " + + "00 00 00 ED 04 00 00 64 72 73 2F 64 6F 77 6E 72 " + + "65 76 2E 78 6D 6C 50 4B 05 06 00 00 00 00 04 00 " + + "04 00 F5 00 00 00 34 06 00 00 00 00 00 00 10 F0 " + + "12 00 00 00 00 00 03 00 10 02 07 00 00 00 05 00 " + + "D0 03 0F 00 40 00 00 00 11 F0 00 00 00 00 5D 00 " + + "1A 00 15 00 12 00 02 00 05 00 11 60 00 00 00 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 3C 00 E7 07 " + + "0F 00 04 F0 DF 07 00 00 12 00 0A F0 08 00 00 00 " + + "06 04 00 00 00 0A 00 00 83 00 0B F0 50 00 00 00 " + + "BF 00 18 00 1F 00 81 01 4F 81 BD 00 BF 01 10 00 " + + "10 00 C0 01 38 5D 8A 00 CB 01 38 63 00 00 FF 01 " + + "08 00 08 00 80 C3 20 00 00 00 BF 03 00 00 02 00 " + + "1F 04 40 04 4F 04 3C 04 3E 04 43 04 33 04 3E 04 " + + "3B 04 4C 04 3D 04 38 04 3A 04 20 00 36 00 00 00 " + + "23 00 22 F1 4D 07 00 00 FF 01 00 00 40 00 A9 C3 " + + "41 07 00 00 50 4B 03 04 14 00 06 00 08 00 00 00 " + + "21 00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 13 00 " + + "00 00 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 " + + "5D 2E 78 6D 6C 94 91 CD 4A C4 30 10 C7 EF 82 EF " + + "10 E6 2A 6D AA 07 11 69 BA 07 AB 47 15 5D 1F 60 " + + "48 A6 6D D8 36 09 99 58 77 DF DE 74 3F 2E E2 0A " + + "1E 67 E6 FF F1 23 A9 57 DB 69 14 33 45 B6 DE 29 " + + "B8 2E 2B 10 E4 B4 37 D6 F5 0A 3E D6 4F C5 1D 08 " + + "4E E8 0C 8E DE 91 82 1D 31 AC 9A CB 8B 7A BD 0B " + + "C4 22 BB 1D 2B 18 52 0A F7 52 B2 1E 68 42 2E 7D " + + "20 97 2F 9D 8F 13 A6 3C C6 5E 06 D4 1B EC 49 DE " + + "54 D5 AD D4 DE 25 72 A9 48 4B 06 34 75 4B 1D 7E " + + "8E 49 3C 6E F3 FA 40 12 69 64 10 0F 07 E1 D2 A5 " + + "00 43 18 AD C6 94 49 E5 EC CC 8F 96 E2 D8 50 66 " + + "E7 5E C3 83 0D 7C 95 31 40 FE DA B0 5C CE 17 1C " + + "7D 2F F9 69 A2 35 24 5E 31 A6 67 9C 32 86 34 91 " + + "25 0F 18 28 6B CA BF 53 16 CC 89 0B DF 75 56 53 " + + "D9 46 7E 5F 7C 27 A8 73 E1 C6 7F B9 48 F3 7F B3 " + + "DB 6C 7B A3 F9 94 2E F7 3F D4 7C 03 00 00 FF FF " + + "03 00 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 " + + "31 DD 5F 61 D2 00 00 00 8F 01 00 00 0B 00 00 00 " + + "5F 72 65 6C 73 2F 2E 72 65 6C 73 A4 90 C1 6A C3 " + + "30 0C 86 EF 83 BD 83 D1 BD 71 DA 43 19 A3 4E 6F " + + "85 5E 4B 07 BB 0A 5B 49 4C 63 CB 58 26 6D DF BE " + + "A6 30 58 46 6F 3B EA 17 FA 3E F1 EF F6 B7 30 A9 " + + "99 B2 78 8E 06 D6 4D 0B 8A A2 65 E7 E3 60 E0 EB " + + "7C 58 7D 80 92 82 D1 E1 C4 91 0C DC 49 60 DF BD " + + "BF ED 4E 34 61 A9 47 32 FA 24 AA 52 A2 18 18 4B " + + "49 9F 5A 8B 1D 29 A0 34 9C 28 D6 4D CF 39 60 A9 " + + "63 1E 74 42 7B C1 81 F4 A6 6D B7 3A FF 66 40 B7 " + + "60 AA A3 33 90 8F 6E 03 EA 7C 4F D5 FC 87 1D BC " + + "CD 2C DC 97 C6 72 D0 DC F7 DE BE A2 6A C7 D7 78 " + + "A2 B9 52 30 0F 54 0C B8 2C CF 30 D3 DC D4 E7 40 " + + "BF F6 AE FF E9 95 11 13 7D 57 FE 42 FC 4C AB F5 " + + "C7 AC 17 35 76 0F 00 00 00 FF FF 03 00 50 4B 03 " + + "04 14 00 06 00 08 00 00 00 21 00 9D C5 0E FA 96 " + + "02 00 00 FD 06 00 00 10 00 00 00 64 72 73 2F 73 " + + "68 61 70 65 78 6D 6C 2E 78 6D 6C AC 55 4B 6E DB " + + "30 10 DD 17 E8 1D 08 EE 13 49 8E E5 8F 60 29 68 " + + "1D B4 9B A2 31 9C E6 00 AC 44 D9 42 29 52 20 59 " + + "5B CE AA 40 B7 05 7A 84 1E A2 9B A2 9F 9C 41 BE " + + "51 87 A4 A4 B4 E9 67 11 DB 0B 9B 9E 21 E7 BD 79 " + + "33 43 CE CE EB 92 A1 0D 95 AA 10 3C C6 C1 A9 8F " + + "11 E5 A9 C8 0A BE 8A F1 F5 AB 67 27 13 8C 94 26 " + + "3C 23 4C 70 1A E3 1D 55 F8 3C 79 FC 68 56 67 32 " + + "22 3C 5D 0B 89 20 04 57 11 18 62 BC D6 BA 8A 3C " + + "4F A5 6B 5A 12 75 2A 2A CA C1 9B 0B 59 12 0D 7F " + + "E5 CA CB 24 D9 42 F0 92 79 03 DF 1F 79 AA 92 94 " + + "64 6A 4D A9 BE 70 1E 9C D8 D8 7A 2B E6 94 B1 27 " + + "16 C2 99 72 29 4A B7 4A 05 4B CE 66 9E E1 60 96 " + + "F6 00 2C 2E F3 3C 19 8E 46 E3 41 D8 FB 8C C9 BA " + + "A5 D8 26 63 67 36 CB CE 66 FC 41 38 18 FA 7E EF " + + "B3 47 6C EC 3B 40 2D 7A 90 64 D4 07 EF 6D 36 CA " + + "E0 6C F2 2F E0 A0 3D 73 1F 79 1A 76 27 C0 73 87 " + + "DB A1 A9 0A 95 24 95 22 C6 18 69 5A 6B 56 F0 37 " + + "B0 76 B0 7C 73 55 2D 64 4B E1 E5 66 21 51 91 C5 " + + "78 8C 11 27 25 14 AA F9 B4 7F B7 FF D8 7C 6F 6E " + + "F7 EF 9B CF CD 6D F3 6D FF A1 F9 D1 7C 69 BE A2 " + + "11 F6 FA 63 26 06 FC B3 E9 FE 1A 51 D9 D8 24 AA " + + "73 59 B6 05 26 0F 28 6F 49 0A 0E 7C 49 24 F2 1C " + + "D5 31 1E 0C A6 21 E4 8C D1 0E 9A 6D 38 09 A7 BE " + + "6F C8 90 08 B2 43 29 6C E8 8C 28 35 3B C2 71 30 " + + "82 DD 86 A0 A3 62 B6 56 52 E9 E7 54 1C 4C 0B 99 " + + "40 31 96 34 D5 96 22 D9 BC 50 DA 41 75 10 AD 30 " + + "4E 0C D3 6D 4A EF 18 35 24 18 5F 52 C8 C8 76 FE " + + "83 85 81 8A 19 4D 2C BA 1D 19 3A 67 12 6D 08 8B " + + "31 49 53 CA 75 E0 5C 6B 92 51 67 0E 7D F8 B4 7A " + + "F4 27 AC 3A 96 90 61 96 17 8C 1D 8D 5B 4B C0 8C " + + "F3 9F DC 9C 56 2D 9E 2D 62 9E 83 98 47 03 F7 FF " + + "27 8C 03 A7 1D A2 CD 5C F0 E3 81 97 05 17 F2 6F " + + "04 18 54 A5 CD DC E1 75 4D E2 5A C3 74 89 AE 9F " + + "8A 6C 67 28 BD 86 5F 98 CC 43 FB 04 2E 68 7D 09 " + + "5F 39 13 DB 18 A7 AC A8 30 82 9B F7 E6 BE 4D 6A " + + "36 17 D0 3D 70 8B BB BB 39 C6 DA CD 17 53 FA CA " + + "10 3C 94 0A 64 0E 13 78 68 14 1B 04 74 21 6C 05 " + + "AF 0E 73 14 29 CF 16 44 92 25 D8 19 31 CF 8F 7C " + + "7B B2 BC 86 E7 E7 06 6E 82 A0 6F FB AA D5 BB 13 " + + "D9 5E 5D 0A AC F6 35 60 05 8C CD 05 D1 C4 94 C8 " + + "D6 E2 F7 77 C4 DA 9C 36 C9 4F 00 00 00 FF FF 03 " + + "00 50 4B 03 04 14 00 06 00 08 00 00 00 21 00 A3 " + + "9B 83 A2 1C 01 00 00 8E 01 00 00 0F 00 00 00 64 " + + "72 73 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C 4C 90 " + + "CD 4E C3 30 10 84 EF 48 BC 83 B5 48 5C 10 75 9A " + + "34 69 08 75 AA 82 84 DA 0B 88 B6 E1 C0 CD 24 CE " + + "8F 88 ED CA 36 4D FA F6 6C 5B 50 73 B2 C7 3B DF " + + "EE 8E 67 F3 5E B6 64 2F 8C 6D B4 62 30 1E 79 40 " + + "84 CA 75 D1 A8 8A 41 B6 7D B9 8F 81 58 C7 55 C1 " + + "5B AD 04 83 83 B0 30 4F AF AF 66 3C 29 74 A7 D6 " + + "62 BF 71 15 C1 26 CA 26 9C 41 ED DC 2E A1 D4 E6 " + + "B5 90 DC 8E F4 4E 28 AC 95 DA 48 EE 50 9A 8A 16 " + + "86 77 D8 5C B6 D4 F7 BC 88 4A DE 28 9C 50 F3 9D " + + "78 AE 45 FE BD F9 91 38 E4 5D 7E 64 FA 29 FE 7C " + + "A5 77 59 B7 5E 6E E3 26 0C 62 C6 6E 6F FA C5 23 " + + "10 27 7A 77 31 FF D1 AB 82 C1 14 48 B9 3C 7C 99 " + + "A6 58 73 EB 84 61 80 71 30 1C 06 83 14 37 EE DB " + + "85 CA 6B 6D 8E F7 D2 68 49 8C EE 4E 54 AE 5B 06 " + + "01 1C F5 5B 59 5A E1 90 08 FD 89 87 38 96 FE 9F " + + "26 51 34 F5 43 A0 47 DC E9 33 3C 8E 4E 16 06 78 " + + "0E E8 87 10 8D 43 76 EC 07 F1 99 A5 C3 3D 50 5C " + + "BE 31 FD 05 00 00 FF FF 03 00 50 4B 01 02 2D 00 " + + "14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB FD 00 " + + "00 00 E2 01 00 00 13 00 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 00 00 00 5B 43 6F 6E 74 65 6E 74 " + + "5F 54 79 70 65 73 5D 2E 78 6D 6C 50 4B 01 02 2D " + + "00 14 00 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 " + + "00 00 00 8F 01 00 00 0B 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 2E 01 00 00 5F 72 65 6C 73 2F 2E " + + "72 65 6C 73 50 4B 01 02 2D 00 14 00 06 00 08 00 " + + "00 00 21 00 9D C5 0E FA 96 02 00 00 FD 06 00 00 " + + "10 00 00 00 00 00 00 00 00 00 00 00 00 00 29 02 " + + "00 00 64 72 73 2F 73 68 61 70 65 78 6D 6C 2E 78 " + + "6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 00 00 00 " + + "21 00 A3 9B 83 A2 1C 01 00 00 8E 01 00 00 0F 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 ED 04 00 00 " + + "64 72 73 2F 64 6F 77 6E 72 65 76 2E 78 6D 6C 50 " + + "4B 05 06 00 00 00 00 04 00 04 00 F5 00 00 00 36 " + + "06 00 00 00 00 00 00 10 F0 12 00 00 00 00 00 03 " + + "00 10 03 07 00 CD 00 06 00 D0 00 10 00 0D 00 00 " + + "00 11 F0 00 00 00 00 5D 00 1A 00 15 00 12 00 02 " + + "00 06 00 11 60 00 00 00 00 00 00 00 00 00 00 00 " + + "00 00 00 00 00 3C 00 E8 07 0F 00 04 F0 E0 07 00 " + + "00 12 00 0A F0 08 00 00 00 07 04 00 00 00 0A 00 " + + "00 83 00 0B F0 50 00 00 00 BF 00 18 00 1F 00 81 " + + "01 4F 81 BD 00 BF 01 10 00 10 00 C0 01 38 5D 8A " + + "00 CB 01 38 63 00 00 FF 01 08 00 08 00 80 C3 20 " + + "00 00 00 BF 03 00 00 02 00 1F 04 40 04 4F 04 3C " + + "04 3E 04 43 04 33 04 3E 04 3B 04 4C 04 3D 04 38 " + + "04 3A 04 20 00 37 00 00 00 23 00 22 F1 4E 07 00 " + + "00 FF 01 00 00 40 00 A9 C3 42 07 00 00 50 4B 03 " + + "04 14 00 06 00 08 00 00 00 21 00 F0 F7 8A BB FD " + + "00 00 00 E2 01 00 00 13 00 00 00 5B 43 6F 6E 74 " + + "65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D 6C 94 91 " + + "CD 4A C4 30 10 C7 EF 82 EF 10 E6 2A 6D AA 07 11 " + + "69 BA 07 AB 47 15 5D 1F 60 48 A6 6D D8 36 09 99 " + + "58 77 DF DE 74 3F 2E E2 0A 1E 67 E6 FF F1 23 A9 " + + "57 DB 69 14 33 45 B6 DE 29 B8 2E 2B 10 E4 B4 37 " + + "D6 F5 0A 3E D6 4F C5 1D 08 4E E8 0C 8E DE 91 82 " + + "1D 31 AC 9A CB 8B 7A BD 0B C4 22 BB 1D 2B 18 52 " + + "0A F7 52 B2 1E 68 42 2E 7D 20 97 2F 9D 8F 13 A6 " + + "3C C6 5E 06 D4 1B EC 49 DE 54 D5 AD D4 DE 25 72 " + + "A9 48 4B 06 34 75 4B 1D 7E 8E 49 3C 6E F3 FA 40 " + + "12 69 64 10 0F 07 E1 D2 A5 00 43 18 AD C6 94 49 " + + "E5 EC CC 8F 96 E2 D8 50 66 E7 5E C3 83 0D 7C 95 " + + "31 40 FE DA B0 5C CE 17 1C 7D 2F F9 69 A2 35 24 " + + "5E 31 A6 67 9C 32 86 34 91 25 0F 18 28 6B CA BF " + + "53 16 CC 89 0B DF 75 56 53 D9 46 7E 5F 7C 27 A8 " + + "73 E1 C6 7F B9 48 F3 7F B3 DB 6C 7B A3 F9 94 2E " + + "F7 3F D4 7C 03 00 00 FF FF 03 00 50 4B 03 04 14 " + + "00 06 00 08 00 00 00 21 00 31 DD 5F 61 D2 00 00 " + + "00 8F 01 00 00 0B 00 00 00 5F 72 65 6C 73 2F 2E " + + "72 65 6C 73 A4 90 C1 6A C3 30 0C 86 EF 83 BD 83 " + + "D1 BD 71 DA 43 19 A3 4E 6F 85 5E 4B 07 BB 0A 5B " + + "49 4C 63 CB 58 26 6D DF BE A6 30 58 46 6F 3B EA " + + "17 FA 3E F1 EF F6 B7 30 A9 99 B2 78 8E 06 D6 4D " + + "0B 8A A2 65 E7 E3 60 E0 EB 7C 58 7D 80 92 82 D1 " + + "E1 C4 91 0C DC 49 60 DF BD BF ED 4E 34 61 A9 47 " + + "32 FA 24 AA 52 A2 18 18 4B 49 9F 5A 8B 1D 29 A0 " + + "34 9C 28 D6 4D CF 39 60 A9 63 1E 74 42 7B C1 81 " + + "F4 A6 6D B7 3A FF 66 40 B7 60 AA A3 33 90 8F 6E " + + "03 EA 7C 4F D5 FC 87 1D BC CD 2C DC 97 C6 72 D0 " + + "DC F7 DE BE A2 6A C7 D7 78 A2 B9 52 30 0F 54 0C " + + "B8 2C CF 30 D3 DC D4 E7 40 BF F6 AE FF E9 95 11 " + + "13 7D 57 FE 42 FC 4C AB F5 C7 AC 17 35 76 0F 00 " + + "00 00 FF FF 03 00 50 4B 03 04 14 00 06 00 08 00 " + + "00 00 21 00 33 C2 C5 D0 98 02 00 00 FD 06 00 00 " + + "10 00 00 00 64 72 73 2F 73 68 61 70 65 78 6D 6C " + + "2E 78 6D 6C AC 55 CD 8E D3 30 10 BE 23 F1 0E 96 " + + "EF BB 49 BA 6D DA 46 4D 56 D0 15 5C 10 5B 75 D9 " + + "07 30 89 D3 46 38 76 64 9B 36 DD 13 12 57 24 1E " + + "81 87 E0 82 F8 D9 67 48 DF 88 B1 9D 64 81 05 0E " + + "DB F6 D0 BA 33 F6 7C DF 7C 33 63 CF CE EB 92 A1 " + + "0D 95 AA 10 3C C6 C1 A9 8F 11 E5 A9 C8 0A BE 8A " + + "F1 F5 AB 67 27 13 8C 94 26 3C 23 4C 70 1A E3 1D " + + "55 F8 3C 79 FC 68 56 67 32 22 3C 5D 0B 89 20 04 " + + "57 11 18 62 BC D6 BA 8A 3C 4F A5 6B 5A 12 75 2A " + + "2A CA C1 9B 0B 59 12 0D 7F E5 CA CB 24 D9 42 F0 " + + "92 79 03 DF 0F 3D 55 49 4A 32 B5 A6 54 5F 38 0F " + + "4E 6C 6C BD 15 73 CA D8 13 0B E1 4C B9 14 A5 5B " + + "A5 82 25 C3 99 67 38 98 A5 3D 00 8B CB 3C 4F A6 " + + "A3 C1 A8 F7 18 83 75 4A B1 4D 26 CE 6C 96 9D CD " + + "F8 83 60 78 E6 FB BD CF 1E B1 91 EF E0 B4 E8 21 " + + "92 B0 0F DE DB CC 91 C1 38 1C FC 0B 38 68 CF DC " + + "43 0E 83 69 77 06 7C 77 C8 1D 9E AA 50 49 52 29 " + + "62 8C 91 A6 B5 66 05 7F 03 6B 07 CC 37 57 D5 42 " + + "B6 24 5E 6E 16 12 15 59 8C A1 5C 9C 94 50 A8 E6 " + + "D3 FE DD FE 63 F3 BD B9 DD BF 6F 3E 37 B7 CD B7 " + + "FD 87 E6 47 F3 A5 F9 8A C6 D8 EB 8F 99 18 F0 CF " + + "26 FC 6B 44 65 63 93 A8 CE 65 D9 16 98 3C A0 BC " + + "25 29 38 F0 25 91 C8 73 54 C7 78 30 1C 8E 21 67 " + + "8C 76 D0 6C E1 D9 04 94 37 64 48 04 D9 A1 14 36 " + + "04 C3 C9 68 0A 46 94 9A 1D A3 71 10 C2 6E 43 D0 " + + "51 31 5B 2B A9 F4 73 2A 0E A6 85 4C A0 18 4B 9A " + + "6A 4B 91 6C 5E 28 ED A0 3A 88 56 18 27 86 E9 36 " + + "A5 77 8C 1A 12 8C 2F 29 64 64 3B FF C1 C2 40 C5 " + + "8C 26 16 DD 8E 0C 9D 33 89 36 84 C5 98 A4 29 E5 " + + "3A 70 AE 35 C9 A8 33 8F 7C F8 B4 7A F4 27 AC 3A " + + "96 90 61 96 17 8C 1D 8D 5B 4B C0 8C F3 7D 6E 4E " + + "AB 16 CF 16 31 CF 41 CC A3 81 FB FF 13 C6 81 D3 " + + "0E D1 66 2E F8 F1 C0 CB 82 0B F9 37 02 0C AA D2 " + + "66 EE F0 BA 26 71 AD 61 BA 44 D7 4F 45 B6 33 94 " + + "5E C3 2F 4C E6 A1 7D 02 17 B4 BE 84 AF 9C 89 6D " + + "8C 53 56 54 18 C1 CD 7B F3 A7 4D 6A 36 17 D0 3D " + + "30 3F EE 6E 8E B1 76 F3 C5 94 BE 32 04 0F A5 02 " + + "99 C3 04 1E 1A C5 06 01 5D 08 5B C1 AB C3 1C 45 " + + "CA B3 05 91 64 09 76 46 CC F3 23 DF 9E 2C AF E1 " + + "F9 B9 81 9B 20 E8 DB BE 6A F5 EE 44 B6 57 97 02 " + + "AB 7D 0D 58 01 63 73 41 34 31 25 B2 B5 F8 FD 1D " + + "B1 36 A7 4D F2 13 00 00 FF FF 03 00 50 4B 03 04 " + + "14 00 06 00 08 00 00 00 21 00 6F E2 C1 89 1B 01 " + + "00 00 8E 01 00 00 0F 00 00 00 64 72 73 2F 64 6F " + + "77 6E 72 65 76 2E 78 6D 6C 4C 90 CD 4E C3 30 10 " + + "84 EF 48 BC 43 B4 48 5C 10 75 92 36 21 0D 75 AA " + + "82 84 DA 0B 88 B4 E1 C0 CD 24 CE 8F 88 ED C8 36 " + + "4D FA F6 6C 5A 50 7B B2 C7 BB DF EE 8C 17 CB 41 " + + "B4 CE 9E 6B D3 28 49 C1 9B B8 E0 70 99 AB A2 91 " + + "15 85 6C F7 72 1F 81 63 2C 93 05 6B 95 E4 14 0E " + + "DC C0 32 B9 BE 5A B0 B8 50 BD 4C F9 7E 6B 2B 07 " + + "87 48 13 33 0A B5 B5 5D 4C 88 C9 6B 2E 98 99 A8 " + + "8E 4B AC 95 4A 0B 66 51 EA 8A 14 9A F5 38 5C B4 " + + "C4 77 DD 90 08 D6 48 DC 50 B3 8E 3F D7 3C FF DE " + + "FE 08 5C F2 2E 3E 32 F5 14 7D BE 92 BB AC 4F D7 " + + "BB A8 09 A6 11 A5 B7 37 C3 EA 11 1C CB 07 7B 6E " + + "FE A3 37 05 05 F4 5A AE 0F 5F BA 29 52 66 2C D7 " + + "14 30 0E 86 C3 60 90 A0 E3 A1 5D C9 BC 56 7A BC " + + "97 5A 09 47 AB FE 48 E5 AA A5 30 83 51 BF 95 A5 " + + "E1 16 09 6F 36 75 11 C7 D2 FF D3 3C F0 03 20 23 " + + "6C D5 09 F5 C2 63 03 05 3C 2F D9 D0 9B 63 EB 25 " + + "EB 3F 84 FE 89 26 97 3E 50 9C BF 31 F9 05 00 00 " + + "FF FF 03 00 50 4B 01 02 2D 00 14 00 06 00 08 00 " + + "00 00 21 00 F0 F7 8A BB FD 00 00 00 E2 01 00 00 " + + "13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + "00 00 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 " + + "5D 2E 78 6D 6C 50 4B 01 02 2D 00 14 00 06 00 08 " + + "00 00 00 21 00 31 DD 5F 61 D2 00 00 00 8F 01 00 " + + "00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 2E " + + "01 00 00 5F 72 65 6C 73 2F 2E 72 65 6C 73 50 4B " + + "01 02 2D 00 14 00 06 00 08 00 00 00 21 00 33 C2 " + + "C5 D0 98 02 00 00 FD 06 00 00 10 00 00 00 00 00 " + + "00 00 00 00 00 00 00 00 29 02 00 00 64 72 73 2F " + + "73 68 61 70 65 78 6D 6C 2E 78 6D 6C 50 4B 01 02 " + + "2D 00 14 00 06 00 08 00 00 00 21 00 6F E2 C1 89 " + + "1B 01 00 00 8E 01 00 00 0F 00 00 00 00 00 00 00 " + + "00 00 00 00 00 00 EF 04 00 00 64 72 73 2F 64 6F " + + "77 6E 72 65 76 2E 78 6D 6C 50 4B 05 06 00 00 00 " + + "00 04 00 04 00 F5 00 00 00 37 06 00 00 00 00 00 " + + "00 10 F0 12 00 00 00 00 00 04 00 10 00 08 00 9A " + + "00 06 00 D0 01 10 00 DA 00 00 00 11 F0 00 00 00 " + + "00 5D 00 1A 00 15 00 12 00 02 00 07 00 11 60 00 " + + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"; + + + byte[] dgBytes = HexRead.readFromString(data); + List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); + assertEquals(14, dgRecords.size()); + + short[] expectedSids = { + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + DrawingRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + ObjRecord.sid, + ContinueRecord.sid, + ObjRecord.sid + }; + + for (int i = 0; i < expectedSids.length; i++) { + assertEquals("unexpected record.sid and index[" + i + "]", expectedSids[i], dgRecords.get(i).getSid()); + } + DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); + + // create a dummy sheet consisting of our test data + InternalSheet sheet = InternalSheet.createSheet(); + List records = sheet.getRecords(); + records.clear(); + records.addAll(dgRecords); + records.add(EOFRecord.instance); + + + sheet.aggregateDrawingRecords(drawingManager, false); + assertEquals("drawing was not fully aggregated", 2, records.size()); + assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); + assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); + } +} diff --git a/test-data/spreadsheet/45129.xls b/test-data/spreadsheet/45129.xls new file mode 100755 index 0000000000000000000000000000000000000000..c3c3a8af279b27dbd952af43bbc7d6cebdc40633 GIT binary patch literal 47616 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 literal 0 HcmV?d00001 From fca6f83f8c991506abdfc5b343fef399017ce939 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Thu, 31 May 2012 09:47:17 +0000 Subject: [PATCH 03/32] more tests and fixes, see patch from May 30 in Bugzilla 53010 git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1344621 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/ddf/EscherArrayProperty.java | 3 + .../apache/poi/hssf/record/DrawingRecord.java | 4 + .../poi/hssf/record/EscherAggregate.java | 8 +- .../poi/hssf/model/TestDrawingAggregate.java | 173 +++++++++++++++--- .../poi/hssf/record/HSSFRecordTestHelper.java | 34 ++++ 5 files changed, 197 insertions(+), 25 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java diff --git a/src/java/org/apache/poi/ddf/EscherArrayProperty.java b/src/java/org/apache/poi/ddf/EscherArrayProperty.java index 6faec52321..01e2f5c365 100644 --- a/src/java/org/apache/poi/ddf/EscherArrayProperty.java +++ b/src/java/org/apache/poi/ddf/EscherArrayProperty.java @@ -62,6 +62,9 @@ public final class EscherArrayProperty extends EscherComplexProperty { } public int getNumberOfElementsInArray() { + if (emptyComplexPart){ + return 0; + } return LittleEndian.getUShort(_complexData, 0); } diff --git a/src/java/org/apache/poi/hssf/record/DrawingRecord.java b/src/java/org/apache/poi/hssf/record/DrawingRecord.java index 9ba18aee03..7b94e26c16 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingRecord.java @@ -64,6 +64,10 @@ public final class DrawingRecord extends StandardRecord { return recordData; } + public byte[] getRecordData(){ + return recordData; + } + public void setData(byte[] thedata) { if (thedata == null) { throw new IllegalArgumentException("data must not be null"); diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 0ac0d04729..e2ca3dd475 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -288,7 +288,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { protected HSSFPatriarch patriarch; /** Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */ - private Map shapeToObj = new HashMap(); + Map shapeToObj = new HashMap(); private DrawingManager2 drawingManager; private short drawingGroupId; @@ -371,7 +371,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { && sid( records, loc ) == DrawingRecord.sid && isObjectRecord( records, loc + 1 ) ) { - dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length; + dataSize += ( (DrawingRecord) records.get( loc ) ).getRecordData().length; loc += 2; while ( loc + 1 < records.size() && sid( records, loc ) == ContinueRecord.sid @@ -391,8 +391,8 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { && isObjectRecord( records, loc + 1 ) ) { DrawingRecord drawingRecord = (DrawingRecord) records.get( loc ); - System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length ); - offset += drawingRecord.getData().length; + System.arraycopy( drawingRecord.getRecordData(), 0, buffer, offset, drawingRecord.getRecordData().length ); + offset += drawingRecord.getRecordData().length; loc += 2; while ( loc + 1 < records.size() && sid( records, loc ) == ContinueRecord.sid diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index 43fe4b482c..c5aa5855a9 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -1,18 +1,29 @@ +/* ==================================================================== + 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.hssf.model; import junit.framework.TestCase; +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherDggRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.ContinueRecord; -import org.apache.poi.hssf.record.DrawingRecord; -import org.apache.poi.hssf.record.EOFRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.RecordBase; -import org.apache.poi.hssf.record.RecordFactory; -import org.apache.poi.hssf.record.TextObjectRecord; -import org.apache.poi.hssf.record.WindowTwoRecord; +import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFTestHelper; @@ -20,13 +31,125 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.util.HexRead; import java.io.ByteArrayInputStream; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; /** * @author Yegor Kozlov * @author Evgeniy Berlog */ public class TestDrawingAggregate extends TestCase { + /** + * Serialize escher aggregate, read back and assert that the drawing data is preserved. + * + * @param agg the aggregate to test + * @return verified aggregate (serialized and read back) + */ + public static EscherAggregate assertWriteAndReadBack(EscherAggregate agg) { + byte[] dgBytes = agg.serialize(); + + + List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); + + DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); + + // create a dummy sheet consisting of our test data + InternalSheet sheet = InternalSheet.createSheet(); + List records = sheet.getRecords(); + records.clear(); + records.addAll(dgRecords); + records.add(EOFRecord.instance); + + + sheet.aggregateDrawingRecords(drawingManager, false); + assertEquals("drawing was not fully aggregated", 2, records.size()); + assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); + assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); + EscherAggregate agg2 = (EscherAggregate) records.get(0); + + assertEquals(agg.getEscherRecords().size(), agg2.getEscherRecords().size()); + + // assert that both pre- and after- serialize aggregates have the same xml representation + for (int i = 0; i < agg.getEscherRecords().size(); i++) { + EscherRecord r1 = agg.getEscherRecords().get(i); + EscherRecord r2 = agg2.getEscherRecords().get(i); + + assertEquals(r1.toXml(), r2.toXml()); + } + + return agg2; + } + + /** + * assert that mapping of Obj records to escher shape containers is the same in both aggregates + */ + public static void assertObjectMappingSame(EscherAggregate agg1, EscherAggregate agg2) { + + // map EscherClientDataRecord and EscherTextboxRecord to their parents + Map map1 = new LinkedHashMap(); + for (EscherRecord r : agg1.getEscherRecords()) mapShapeContainers(r, map1); + + Map map2 = new LinkedHashMap(); + for (EscherRecord r : agg2.getEscherRecords()) mapShapeContainers(r, map2); + + assertEquals("aggregates have different number of shapes", map1.size(), map2.size()); + + // for each EscherClientDataRecord get parent SP_CONTAINER and corresponding ObjRecord + // verify that ObjRecord to + List l1 = new ArrayList(map1.keySet()); + List l2 = new ArrayList(map2.keySet()); + for (int i = 0; i < l1.size(); i++) { + EscherRecord e1 = l1.get(i); + EscherRecord e2 = l2.get(i); + ObjRecord obj1 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg1).get(e1); + ObjRecord obj2 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg2).get(e2); + + CommonObjectDataSubRecord cmo1 = (CommonObjectDataSubRecord) obj1.getSubRecords().get(0); + CommonObjectDataSubRecord cmo2 = (CommonObjectDataSubRecord) obj2.getSubRecords().get(0); + + assertEquals(cmo1.getObjectId(), cmo2.getObjectId()); + assertEquals(obj1.toString(), obj2.toString()); + + // test that obj parents have the same shapeId, that is, that shape is the same + EscherContainerRecord p1 = map1.get(e1); + EscherContainerRecord p2 = map2.get(e2); + EscherSpRecord sp1 = (EscherSpRecord) p1.getChildById(EscherSpRecord.RECORD_ID); + EscherSpRecord sp2 = (EscherSpRecord) p2.getChildById(EscherSpRecord.RECORD_ID); + assertEquals(sp1.getShapeId(), sp2.getShapeId()); + + assertEquals("wrong shape2obj mapping", sp1.getShapeId() % 1024, cmo1.getObjectId()); + assertEquals(p1.toXml(), p2.toXml()); + } + } + + /** + * recursively map EscherClientDataRecords to their parent shape containers: + *

+ * EscherClientDataRecord1 --> EscherContainerRecord1 + * EscherClientDataRecord2 --> EscherContainerRecord2 + * ... + *

+ * TODO: YK: this method can be avoided if we have EscherRecord.getParent() + */ + private static void mapShapeContainers(EscherRecord parent, Map map) { + if (parent.isContainerRecord()) { + if (parent.getRecordId() == EscherContainerRecord.SP_CONTAINER) { + // iterate over shape's children and search for EscherClientDataRecord + for (EscherRecord r : parent.getChildRecords()) { + if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) { + map.put(r, (EscherContainerRecord) parent); + } + } + } else { + for (EscherRecord ch : parent.getChildRecords()) { + mapShapeContainers(ch, map); + } + } + } + } + /** * test reading drawing aggregate from a test file from Bugzilla 45129 */ @@ -69,7 +192,7 @@ public class TestDrawingAggregate extends TestCase { // The subrange [19, 388] is expected to be replaced with a EscherAggregate object DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); int loc = isheet.aggregateDrawingRecords(drawingManager, false); - EscherAggregate ag = (EscherAggregate) records.get(loc); + EscherAggregate agg = (EscherAggregate) records.get(loc); assertEquals("wrong size of the aggregated sheet records stream", 25, records.size()); assertTrue( @@ -80,8 +203,9 @@ public class TestDrawingAggregate extends TestCase { assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), records.get(20) instanceof WindowTwoRecord); - // TODO figure out why serialization fails - // byte[] bytes = ag.serialize(); + EscherAggregate agg2 = assertWriteAndReadBack(agg); + + assertObjectMappingSame(agg, agg2); } public void testFileWithPictures() { @@ -93,10 +217,6 @@ public class TestDrawingAggregate extends TestCase { List records = isheet.getRecords(); - for (RecordBase recordBase : records) { - System.out.println(recordBase.toString()); - } - // the sheet's drawing is not aggregated assertEquals("wrong size of sheet records stream", 315, records.size()); // the last record before the drawing block @@ -127,7 +247,7 @@ public class TestDrawingAggregate extends TestCase { // The subrange [19, 388] is expected to be replaced with a EscherAggregate object DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); int loc = isheet.aggregateDrawingRecords(drawingManager, false); - EscherAggregate ag = (EscherAggregate) records.get(loc); + EscherAggregate agg = (EscherAggregate) records.get(loc); assertEquals("wrong size of the aggregated sheet records stream", 38, records.size()); assertTrue( @@ -137,6 +257,10 @@ public class TestDrawingAggregate extends TestCase { records.get(22) instanceof EscherAggregate); assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(), records.get(23) instanceof WindowTwoRecord); + + EscherAggregate agg2 = assertWriteAndReadBack(agg); + + assertObjectMappingSame(agg, agg2); } public void testUnhandledContinue() { @@ -848,8 +972,10 @@ public class TestDrawingAggregate extends TestCase { assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); EscherAggregate agg = (EscherAggregate) records.get(0); - // TODO figure out why serialization fails -// byte[] writtenBytes = agg.serialize(); + // serialize, read back and assert that the drawing data is preserved + EscherAggregate agg2 = assertWriteAndReadBack(agg); + + assertObjectMappingSame(agg, agg2); } public void testUnhandledContinue2() { @@ -1793,10 +1919,15 @@ public class TestDrawingAggregate extends TestCase { records.addAll(dgRecords); records.add(EOFRecord.instance); - sheet.aggregateDrawingRecords(drawingManager, false); assertEquals("drawing was not fully aggregated", 2, records.size()); assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); + + EscherAggregate agg = (EscherAggregate) records.get(0); + + EscherAggregate agg2 = assertWriteAndReadBack(agg); + + assertObjectMappingSame(agg, agg2); } } diff --git a/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java b/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java new file mode 100644 index 0000000000..4eed03d5e5 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java @@ -0,0 +1,34 @@ +/* + * 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.hssf.record; + +import org.apache.poi.ddf.EscherRecord; + +import java.util.Map; + +/** + * @author Evgeniy Berlog + * date: 30.05.12 + */ +public class HSSFRecordTestHelper { + + public static Map getShapeToObjForTest(EscherAggregate agg){ + return agg.shapeToObj; + } + +} From de28fe9aff1aa6cd00689310643acd3b6b428abc Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Mon, 4 Jun 2012 08:08:47 +0000 Subject: [PATCH 04/32] Bugzilla 53010, patch from June 3: improved support for Continue records in drawing blocks git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1345858 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/model/InternalSheet.java | 25 +- .../apache/poi/hssf/record/DrawingRecord.java | 45 +- .../poi/hssf/record/EscherAggregate.java | 1753 +++++++++-------- .../hssf/record/RecordFactoryInputStream.java | 16 +- .../poi/hssf/model/TestDrawingAggregate.java | 313 +-- .../poi/hssf/record/HSSFRecordTestHelper.java | 34 - .../poi/hssf/record/TestDrawingRecord.java | 13 +- test-data/spreadsheet/DrawingAndComments.xls | Bin 0 -> 43520 bytes test-data/spreadsheet/DrawingContinue.xls | Bin 0 -> 68608 bytes 9 files changed, 1106 insertions(+), 1093 deletions(-) delete mode 100644 src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java create mode 100755 test-data/spreadsheet/DrawingAndComments.xls create mode 100755 test-data/spreadsheet/DrawingContinue.xls diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index 75ea355e50..1e0af24530 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -1508,31 +1508,10 @@ public final class InternalSheet { return loc; } List records = getRecords(); - EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager ); - int startloc = loc; - while ( loc + 1 < records.size() - && records.get( loc ) instanceof DrawingRecord - && (records.get( loc + 1 ) instanceof ObjRecord || - records.get( loc + 1 ) instanceof TextObjectRecord) ) - { - loc += 2; - if (records.get( loc ) instanceof NoteRecord) loc ++; - while ( loc + 1 < records.size() - && records.get( loc ) instanceof ContinueRecord - && (records.get( loc + 1 ) instanceof ObjRecord || - records.get( loc + 1 ) instanceof TextObjectRecord) ) - { - loc += 2; - if (records.get( loc ) instanceof NoteRecord) loc ++; - } - } - int endloc = loc-1; - for(int i = 0; i < (endloc - startloc + 1); i++) - records.remove(startloc); - records.add(startloc, r); + EscherAggregate.createAggregate( records, loc, drawingManager ); - return startloc; + return loc; } /** diff --git a/src/java/org/apache/poi/hssf/record/DrawingRecord.java b/src/java/org/apache/poi/hssf/record/DrawingRecord.java index 7b94e26c16..9e104de59e 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingRecord.java @@ -20,22 +20,21 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndianOutput; /** * DrawingRecord (0x00EC)

- * */ public final class DrawingRecord extends StandardRecord { public static final short sid = 0x00EC; - private static final byte[] EMPTY_BYTE_ARRAY = { }; + private static final byte[] EMPTY_BYTE_ARRAY = {}; private byte[] recordData; private byte[] contd; public DrawingRecord() { - recordData = EMPTY_BYTE_ARRAY; + recordData = EMPTY_BYTE_ARRAY; } public DrawingRecord(RecordInputStream in) { - recordData = in.readRemainder(); + recordData = in.readRemainder(); } public void processContinueRecord(byte[] record) { @@ -46,6 +45,7 @@ public final class DrawingRecord extends StandardRecord { public void serialize(LittleEndianOutput out) { out.write(recordData); } + protected int getDataSize() { return recordData.length; } @@ -55,12 +55,12 @@ public final class DrawingRecord extends StandardRecord { } public byte[] getData() { - if(contd != null) { - byte[] newBuffer = new byte[ recordData.length + contd.length ]; - System.arraycopy( recordData, 0, newBuffer, 0, recordData.length ); - System.arraycopy( contd, 0, newBuffer, recordData.length, contd.length); - return newBuffer; - } +// if (continueData.size() != 0) { +// byte[] newBuffer = new byte[recordData.length + continueData.size()]; +// System.arraycopy(recordData, 0, newBuffer, 0, recordData.length); +// System.arraycopy(continueData.toByteArray(), 0, newBuffer, recordData.length, continueData.size()); +// return newBuffer; +// } return recordData; } @@ -69,21 +69,20 @@ public final class DrawingRecord extends StandardRecord { } public void setData(byte[] thedata) { - if (thedata == null) { - throw new IllegalArgumentException("data must not be null"); - } + if (thedata == null) { + throw new IllegalArgumentException("data must not be null"); + } recordData = thedata; } public Object clone() { - DrawingRecord rec = new DrawingRecord(); - - rec.recordData = recordData.clone(); - if (contd != null) { - // TODO - this code probably never executes - rec.contd = contd.clone(); - } - - return rec; + DrawingRecord rec = new DrawingRecord(); + rec.recordData = recordData.clone(); + if (contd != null) { + // TODO - this code probably never executes + rec.contd = contd.clone(); + } + + return rec; } -} \ No newline at end of file +} diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index e2ca3dd475..3bb7127356 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -17,11 +17,9 @@ package org.apache.poi.hssf.record; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.*; import org.apache.poi.ddf.DefaultEscherRecordFactory; import org.apache.poi.ddf.EscherBoolProperty; @@ -65,884 +63,912 @@ import org.apache.poi.util.POILogger; * combination of MSODRAWING -> OBJ -> MSODRAWING -> OBJ records * but the escher records are serialized _across_ the MSODRAWING * records. - *

+ *

* It gets even worse when you start looking at TXO records. - *

+ *

* So what we do with this class is aggregate lazily. That is * we don't aggregate the MSODRAWING -> OBJ records unless we * need to modify them. + *

+ * At first document contains 4 types of records which belong to drawing layer. + * There are can be such sequence of record: + *

+ * DrawingRecord + * ContinueRecord + * ... + * ContinueRecord + * ObjRecord | TextObjectRecord + * ..... + * ContinueRecord + * ... + * ContinueRecord + * ObjRecord | TextObjectRecord + * NoteRecord + * ... + * NoteRecord + *

+ * To work with shapes we have to read data from Drawing and Continue records into single array of bytes and + * build escher(office art) records tree from this array. + * Each shape in drawing layer matches corresponding ObjRecord + * Each textbox matches corresponding TextObjectRecord * + * ObjRecord contains information about shape. Thus each ObjRecord corresponds EscherContainerRecord(SPGR) + * + * EscherAggrefate contains also NoteRecords + * NoteRecords must be serial * * @author Glen Stampoultzis (glens at apache.org) */ + public final class EscherAggregate extends AbstractEscherHolderRecord { - public static final short sid = 9876; // not a real sid - dummy value - private static POILogger log = POILogFactory.getLogger(EscherAggregate.class); + public static final short sid = 9876; // not a real sid - dummy value + private static POILogger log = POILogFactory.getLogger(EscherAggregate.class); - public static final short ST_MIN = (short) 0; - public static final short ST_NOT_PRIMATIVE = ST_MIN; - public static final short ST_RECTANGLE = (short) 1; - public static final short ST_ROUNDRECTANGLE = (short) 2; - public static final short ST_ELLIPSE = (short) 3; - public static final short ST_DIAMOND = (short) 4; - public static final short ST_ISOCELESTRIANGLE = (short) 5; - public static final short ST_RIGHTTRIANGLE = (short) 6; - public static final short ST_PARALLELOGRAM = (short) 7; - public static final short ST_TRAPEZOID = (short) 8; - public static final short ST_HEXAGON = (short) 9; - public static final short ST_OCTAGON = (short) 10; - public static final short ST_PLUS = (short) 11; - public static final short ST_STAR = (short) 12; - public static final short ST_ARROW = (short) 13; - public static final short ST_THICKARROW = (short) 14; - public static final short ST_HOMEPLATE = (short) 15; - public static final short ST_CUBE = (short) 16; - public static final short ST_BALLOON = (short) 17; - public static final short ST_SEAL = (short) 18; - public static final short ST_ARC = (short) 19; - public static final short ST_LINE = (short) 20; - public static final short ST_PLAQUE = (short) 21; - public static final short ST_CAN = (short) 22; - public static final short ST_DONUT = (short) 23; - public static final short ST_TEXTSIMPLE = (short) 24; - public static final short ST_TEXTOCTAGON = (short) 25; - public static final short ST_TEXTHEXAGON = (short) 26; - public static final short ST_TEXTCURVE = (short) 27; - public static final short ST_TEXTWAVE = (short) 28; - public static final short ST_TEXTRING = (short) 29; - public static final short ST_TEXTONCURVE = (short) 30; - public static final short ST_TEXTONRING = (short) 31; - public static final short ST_STRAIGHTCONNECTOR1 = (short) 32; - public static final short ST_BENTCONNECTOR2 = (short) 33; - public static final short ST_BENTCONNECTOR3 = (short) 34; - public static final short ST_BENTCONNECTOR4 = (short) 35; - public static final short ST_BENTCONNECTOR5 = (short) 36; - public static final short ST_CURVEDCONNECTOR2 = (short) 37; - public static final short ST_CURVEDCONNECTOR3 = (short) 38; - public static final short ST_CURVEDCONNECTOR4 = (short) 39; - public static final short ST_CURVEDCONNECTOR5 = (short) 40; - public static final short ST_CALLOUT1 = (short) 41; - public static final short ST_CALLOUT2 = (short) 42; - public static final short ST_CALLOUT3 = (short) 43; - public static final short ST_ACCENTCALLOUT1 = (short) 44; - public static final short ST_ACCENTCALLOUT2 = (short) 45; - public static final short ST_ACCENTCALLOUT3 = (short) 46; - public static final short ST_BORDERCALLOUT1 = (short) 47; - public static final short ST_BORDERCALLOUT2 = (short) 48; - public static final short ST_BORDERCALLOUT3 = (short) 49; - public static final short ST_ACCENTBORDERCALLOUT1 = (short) 50; - public static final short ST_ACCENTBORDERCALLOUT2 = (short) 51; - public static final short ST_ACCENTBORDERCALLOUT3 = (short) 52; - public static final short ST_RIBBON = (short) 53; - public static final short ST_RIBBON2 = (short) 54; - public static final short ST_CHEVRON = (short) 55; - public static final short ST_PENTAGON = (short) 56; - public static final short ST_NOSMOKING = (short) 57; - public static final short ST_SEAL8 = (short) 58; - public static final short ST_SEAL16 = (short) 59; - public static final short ST_SEAL32 = (short) 60; - public static final short ST_WEDGERECTCALLOUT = (short) 61; - public static final short ST_WEDGERRECTCALLOUT = (short) 62; - public static final short ST_WEDGEELLIPSECALLOUT = (short) 63; - public static final short ST_WAVE = (short) 64; - public static final short ST_FOLDEDCORNER = (short) 65; - public static final short ST_LEFTARROW = (short) 66; - public static final short ST_DOWNARROW = (short) 67; - public static final short ST_UPARROW = (short) 68; - public static final short ST_LEFTRIGHTARROW = (short) 69; - public static final short ST_UPDOWNARROW = (short) 70; - public static final short ST_IRREGULARSEAL1 = (short) 71; - public static final short ST_IRREGULARSEAL2 = (short) 72; - public static final short ST_LIGHTNINGBOLT = (short) 73; - public static final short ST_HEART = (short) 74; - public static final short ST_PICTUREFRAME = (short) 75; - public static final short ST_QUADARROW = (short) 76; - public static final short ST_LEFTARROWCALLOUT = (short) 77; - public static final short ST_RIGHTARROWCALLOUT = (short) 78; - public static final short ST_UPARROWCALLOUT = (short) 79; - public static final short ST_DOWNARROWCALLOUT = (short) 80; - public static final short ST_LEFTRIGHTARROWCALLOUT = (short) 81; - public static final short ST_UPDOWNARROWCALLOUT = (short) 82; - public static final short ST_QUADARROWCALLOUT = (short) 83; - public static final short ST_BEVEL = (short) 84; - public static final short ST_LEFTBRACKET = (short) 85; - public static final short ST_RIGHTBRACKET = (short) 86; - public static final short ST_LEFTBRACE = (short) 87; - public static final short ST_RIGHTBRACE = (short) 88; - public static final short ST_LEFTUPARROW = (short) 89; - public static final short ST_BENTUPARROW = (short) 90; - public static final short ST_BENTARROW = (short) 91; - public static final short ST_SEAL24 = (short) 92; - public static final short ST_STRIPEDRIGHTARROW = (short) 93; - public static final short ST_NOTCHEDRIGHTARROW = (short) 94; - public static final short ST_BLOCKARC = (short) 95; - public static final short ST_SMILEYFACE = (short) 96; - public static final short ST_VERTICALSCROLL = (short) 97; - public static final short ST_HORIZONTALSCROLL = (short) 98; - public static final short ST_CIRCULARARROW = (short) 99; - public static final short ST_NOTCHEDCIRCULARARROW = (short) 100; - public static final short ST_UTURNARROW = (short) 101; - public static final short ST_CURVEDRIGHTARROW = (short) 102; - public static final short ST_CURVEDLEFTARROW = (short) 103; - public static final short ST_CURVEDUPARROW = (short) 104; - public static final short ST_CURVEDDOWNARROW = (short) 105; - public static final short ST_CLOUDCALLOUT = (short) 106; - public static final short ST_ELLIPSERIBBON = (short) 107; - public static final short ST_ELLIPSERIBBON2 = (short) 108; - public static final short ST_FLOWCHARTPROCESS = (short) 109; - public static final short ST_FLOWCHARTDECISION = (short) 110; - public static final short ST_FLOWCHARTINPUTOUTPUT = (short) 111; - public static final short ST_FLOWCHARTPREDEFINEDPROCESS = (short) 112; - public static final short ST_FLOWCHARTINTERNALSTORAGE = (short) 113; - public static final short ST_FLOWCHARTDOCUMENT = (short) 114; - public static final short ST_FLOWCHARTMULTIDOCUMENT = (short) 115; - public static final short ST_FLOWCHARTTERMINATOR = (short) 116; - public static final short ST_FLOWCHARTPREPARATION = (short) 117; - public static final short ST_FLOWCHARTMANUALINPUT = (short) 118; - public static final short ST_FLOWCHARTMANUALOPERATION = (short) 119; - public static final short ST_FLOWCHARTCONNECTOR = (short) 120; - public static final short ST_FLOWCHARTPUNCHEDCARD = (short) 121; - public static final short ST_FLOWCHARTPUNCHEDTAPE = (short) 122; - public static final short ST_FLOWCHARTSUMMINGJUNCTION = (short) 123; - public static final short ST_FLOWCHARTOR = (short) 124; - public static final short ST_FLOWCHARTCOLLATE = (short) 125; - public static final short ST_FLOWCHARTSORT = (short) 126; - public static final short ST_FLOWCHARTEXTRACT = (short) 127; - public static final short ST_FLOWCHARTMERGE = (short) 128; - public static final short ST_FLOWCHARTOFFLINESTORAGE = (short) 129; - public static final short ST_FLOWCHARTONLINESTORAGE = (short) 130; - public static final short ST_FLOWCHARTMAGNETICTAPE = (short) 131; - public static final short ST_FLOWCHARTMAGNETICDISK = (short) 132; - public static final short ST_FLOWCHARTMAGNETICDRUM = (short) 133; - public static final short ST_FLOWCHARTDISPLAY = (short) 134; - public static final short ST_FLOWCHARTDELAY = (short) 135; - public static final short ST_TEXTPLAINTEXT = (short) 136; - public static final short ST_TEXTSTOP = (short) 137; - public static final short ST_TEXTTRIANGLE = (short) 138; - public static final short ST_TEXTTRIANGLEINVERTED = (short) 139; - public static final short ST_TEXTCHEVRON = (short) 140; - public static final short ST_TEXTCHEVRONINVERTED = (short) 141; - public static final short ST_TEXTRINGINSIDE = (short) 142; - public static final short ST_TEXTRINGOUTSIDE = (short) 143; - public static final short ST_TEXTARCHUPCURVE = (short) 144; - public static final short ST_TEXTARCHDOWNCURVE = (short) 145; - public static final short ST_TEXTCIRCLECURVE = (short) 146; - public static final short ST_TEXTBUTTONCURVE = (short) 147; - public static final short ST_TEXTARCHUPPOUR = (short) 148; - public static final short ST_TEXTARCHDOWNPOUR = (short) 149; - public static final short ST_TEXTCIRCLEPOUR = (short) 150; - public static final short ST_TEXTBUTTONPOUR = (short) 151; - public static final short ST_TEXTCURVEUP = (short) 152; - public static final short ST_TEXTCURVEDOWN = (short) 153; - public static final short ST_TEXTCASCADEUP = (short) 154; - public static final short ST_TEXTCASCADEDOWN = (short) 155; - public static final short ST_TEXTWAVE1 = (short) 156; - public static final short ST_TEXTWAVE2 = (short) 157; - public static final short ST_TEXTWAVE3 = (short) 158; - public static final short ST_TEXTWAVE4 = (short) 159; - public static final short ST_TEXTINFLATE = (short) 160; - public static final short ST_TEXTDEFLATE = (short) 161; - public static final short ST_TEXTINFLATEBOTTOM = (short) 162; - public static final short ST_TEXTDEFLATEBOTTOM = (short) 163; - public static final short ST_TEXTINFLATETOP = (short) 164; - public static final short ST_TEXTDEFLATETOP = (short) 165; - public static final short ST_TEXTDEFLATEINFLATE = (short) 166; - public static final short ST_TEXTDEFLATEINFLATEDEFLATE = (short) 167; - public static final short ST_TEXTFADERIGHT = (short) 168; - public static final short ST_TEXTFADELEFT = (short) 169; - public static final short ST_TEXTFADEUP = (short) 170; - public static final short ST_TEXTFADEDOWN = (short) 171; - public static final short ST_TEXTSLANTUP = (short) 172; - public static final short ST_TEXTSLANTDOWN = (short) 173; - public static final short ST_TEXTCANUP = (short) 174; - public static final short ST_TEXTCANDOWN = (short) 175; - public static final short ST_FLOWCHARTALTERNATEPROCESS = (short) 176; - public static final short ST_FLOWCHARTOFFPAGECONNECTOR = (short) 177; - public static final short ST_CALLOUT90 = (short) 178; - public static final short ST_ACCENTCALLOUT90 = (short) 179; - public static final short ST_BORDERCALLOUT90 = (short) 180; - public static final short ST_ACCENTBORDERCALLOUT90 = (short) 181; - public static final short ST_LEFTRIGHTUPARROW = (short) 182; - public static final short ST_SUN = (short) 183; - public static final short ST_MOON = (short) 184; - public static final short ST_BRACKETPAIR = (short) 185; - public static final short ST_BRACEPAIR = (short) 186; - public static final short ST_SEAL4 = (short) 187; - public static final short ST_DOUBLEWAVE = (short) 188; - public static final short ST_ACTIONBUTTONBLANK = (short) 189; - public static final short ST_ACTIONBUTTONHOME = (short) 190; - public static final short ST_ACTIONBUTTONHELP = (short) 191; - public static final short ST_ACTIONBUTTONINFORMATION = (short) 192; - public static final short ST_ACTIONBUTTONFORWARDNEXT = (short) 193; - public static final short ST_ACTIONBUTTONBACKPREVIOUS = (short) 194; - public static final short ST_ACTIONBUTTONEND = (short) 195; - public static final short ST_ACTIONBUTTONBEGINNING = (short) 196; - public static final short ST_ACTIONBUTTONRETURN = (short) 197; - public static final short ST_ACTIONBUTTONDOCUMENT = (short) 198; - public static final short ST_ACTIONBUTTONSOUND = (short) 199; - public static final short ST_ACTIONBUTTONMOVIE = (short) 200; - public static final short ST_HOSTCONTROL = (short) 201; - public static final short ST_TEXTBOX = (short) 202; - public static final short ST_NIL = (short) 0x0FFF; + public static final short ST_MIN = (short) 0; + public static final short ST_NOT_PRIMATIVE = ST_MIN; + public static final short ST_RECTANGLE = (short) 1; + public static final short ST_ROUNDRECTANGLE = (short) 2; + public static final short ST_ELLIPSE = (short) 3; + public static final short ST_DIAMOND = (short) 4; + public static final short ST_ISOCELESTRIANGLE = (short) 5; + public static final short ST_RIGHTTRIANGLE = (short) 6; + public static final short ST_PARALLELOGRAM = (short) 7; + public static final short ST_TRAPEZOID = (short) 8; + public static final short ST_HEXAGON = (short) 9; + public static final short ST_OCTAGON = (short) 10; + public static final short ST_PLUS = (short) 11; + public static final short ST_STAR = (short) 12; + public static final short ST_ARROW = (short) 13; + public static final short ST_THICKARROW = (short) 14; + public static final short ST_HOMEPLATE = (short) 15; + public static final short ST_CUBE = (short) 16; + public static final short ST_BALLOON = (short) 17; + public static final short ST_SEAL = (short) 18; + public static final short ST_ARC = (short) 19; + public static final short ST_LINE = (short) 20; + public static final short ST_PLAQUE = (short) 21; + public static final short ST_CAN = (short) 22; + public static final short ST_DONUT = (short) 23; + public static final short ST_TEXTSIMPLE = (short) 24; + public static final short ST_TEXTOCTAGON = (short) 25; + public static final short ST_TEXTHEXAGON = (short) 26; + public static final short ST_TEXTCURVE = (short) 27; + public static final short ST_TEXTWAVE = (short) 28; + public static final short ST_TEXTRING = (short) 29; + public static final short ST_TEXTONCURVE = (short) 30; + public static final short ST_TEXTONRING = (short) 31; + public static final short ST_STRAIGHTCONNECTOR1 = (short) 32; + public static final short ST_BENTCONNECTOR2 = (short) 33; + public static final short ST_BENTCONNECTOR3 = (short) 34; + public static final short ST_BENTCONNECTOR4 = (short) 35; + public static final short ST_BENTCONNECTOR5 = (short) 36; + public static final short ST_CURVEDCONNECTOR2 = (short) 37; + public static final short ST_CURVEDCONNECTOR3 = (short) 38; + public static final short ST_CURVEDCONNECTOR4 = (short) 39; + public static final short ST_CURVEDCONNECTOR5 = (short) 40; + public static final short ST_CALLOUT1 = (short) 41; + public static final short ST_CALLOUT2 = (short) 42; + public static final short ST_CALLOUT3 = (short) 43; + public static final short ST_ACCENTCALLOUT1 = (short) 44; + public static final short ST_ACCENTCALLOUT2 = (short) 45; + public static final short ST_ACCENTCALLOUT3 = (short) 46; + public static final short ST_BORDERCALLOUT1 = (short) 47; + public static final short ST_BORDERCALLOUT2 = (short) 48; + public static final short ST_BORDERCALLOUT3 = (short) 49; + public static final short ST_ACCENTBORDERCALLOUT1 = (short) 50; + public static final short ST_ACCENTBORDERCALLOUT2 = (short) 51; + public static final short ST_ACCENTBORDERCALLOUT3 = (short) 52; + public static final short ST_RIBBON = (short) 53; + public static final short ST_RIBBON2 = (short) 54; + public static final short ST_CHEVRON = (short) 55; + public static final short ST_PENTAGON = (short) 56; + public static final short ST_NOSMOKING = (short) 57; + public static final short ST_SEAL8 = (short) 58; + public static final short ST_SEAL16 = (short) 59; + public static final short ST_SEAL32 = (short) 60; + public static final short ST_WEDGERECTCALLOUT = (short) 61; + public static final short ST_WEDGERRECTCALLOUT = (short) 62; + public static final short ST_WEDGEELLIPSECALLOUT = (short) 63; + public static final short ST_WAVE = (short) 64; + public static final short ST_FOLDEDCORNER = (short) 65; + public static final short ST_LEFTARROW = (short) 66; + public static final short ST_DOWNARROW = (short) 67; + public static final short ST_UPARROW = (short) 68; + public static final short ST_LEFTRIGHTARROW = (short) 69; + public static final short ST_UPDOWNARROW = (short) 70; + public static final short ST_IRREGULARSEAL1 = (short) 71; + public static final short ST_IRREGULARSEAL2 = (short) 72; + public static final short ST_LIGHTNINGBOLT = (short) 73; + public static final short ST_HEART = (short) 74; + public static final short ST_PICTUREFRAME = (short) 75; + public static final short ST_QUADARROW = (short) 76; + public static final short ST_LEFTARROWCALLOUT = (short) 77; + public static final short ST_RIGHTARROWCALLOUT = (short) 78; + public static final short ST_UPARROWCALLOUT = (short) 79; + public static final short ST_DOWNARROWCALLOUT = (short) 80; + public static final short ST_LEFTRIGHTARROWCALLOUT = (short) 81; + public static final short ST_UPDOWNARROWCALLOUT = (short) 82; + public static final short ST_QUADARROWCALLOUT = (short) 83; + public static final short ST_BEVEL = (short) 84; + public static final short ST_LEFTBRACKET = (short) 85; + public static final short ST_RIGHTBRACKET = (short) 86; + public static final short ST_LEFTBRACE = (short) 87; + public static final short ST_RIGHTBRACE = (short) 88; + public static final short ST_LEFTUPARROW = (short) 89; + public static final short ST_BENTUPARROW = (short) 90; + public static final short ST_BENTARROW = (short) 91; + public static final short ST_SEAL24 = (short) 92; + public static final short ST_STRIPEDRIGHTARROW = (short) 93; + public static final short ST_NOTCHEDRIGHTARROW = (short) 94; + public static final short ST_BLOCKARC = (short) 95; + public static final short ST_SMILEYFACE = (short) 96; + public static final short ST_VERTICALSCROLL = (short) 97; + public static final short ST_HORIZONTALSCROLL = (short) 98; + public static final short ST_CIRCULARARROW = (short) 99; + public static final short ST_NOTCHEDCIRCULARARROW = (short) 100; + public static final short ST_UTURNARROW = (short) 101; + public static final short ST_CURVEDRIGHTARROW = (short) 102; + public static final short ST_CURVEDLEFTARROW = (short) 103; + public static final short ST_CURVEDUPARROW = (short) 104; + public static final short ST_CURVEDDOWNARROW = (short) 105; + public static final short ST_CLOUDCALLOUT = (short) 106; + public static final short ST_ELLIPSERIBBON = (short) 107; + public static final short ST_ELLIPSERIBBON2 = (short) 108; + public static final short ST_FLOWCHARTPROCESS = (short) 109; + public static final short ST_FLOWCHARTDECISION = (short) 110; + public static final short ST_FLOWCHARTINPUTOUTPUT = (short) 111; + public static final short ST_FLOWCHARTPREDEFINEDPROCESS = (short) 112; + public static final short ST_FLOWCHARTINTERNALSTORAGE = (short) 113; + public static final short ST_FLOWCHARTDOCUMENT = (short) 114; + public static final short ST_FLOWCHARTMULTIDOCUMENT = (short) 115; + public static final short ST_FLOWCHARTTERMINATOR = (short) 116; + public static final short ST_FLOWCHARTPREPARATION = (short) 117; + public static final short ST_FLOWCHARTMANUALINPUT = (short) 118; + public static final short ST_FLOWCHARTMANUALOPERATION = (short) 119; + public static final short ST_FLOWCHARTCONNECTOR = (short) 120; + public static final short ST_FLOWCHARTPUNCHEDCARD = (short) 121; + public static final short ST_FLOWCHARTPUNCHEDTAPE = (short) 122; + public static final short ST_FLOWCHARTSUMMINGJUNCTION = (short) 123; + public static final short ST_FLOWCHARTOR = (short) 124; + public static final short ST_FLOWCHARTCOLLATE = (short) 125; + public static final short ST_FLOWCHARTSORT = (short) 126; + public static final short ST_FLOWCHARTEXTRACT = (short) 127; + public static final short ST_FLOWCHARTMERGE = (short) 128; + public static final short ST_FLOWCHARTOFFLINESTORAGE = (short) 129; + public static final short ST_FLOWCHARTONLINESTORAGE = (short) 130; + public static final short ST_FLOWCHARTMAGNETICTAPE = (short) 131; + public static final short ST_FLOWCHARTMAGNETICDISK = (short) 132; + public static final short ST_FLOWCHARTMAGNETICDRUM = (short) 133; + public static final short ST_FLOWCHARTDISPLAY = (short) 134; + public static final short ST_FLOWCHARTDELAY = (short) 135; + public static final short ST_TEXTPLAINTEXT = (short) 136; + public static final short ST_TEXTSTOP = (short) 137; + public static final short ST_TEXTTRIANGLE = (short) 138; + public static final short ST_TEXTTRIANGLEINVERTED = (short) 139; + public static final short ST_TEXTCHEVRON = (short) 140; + public static final short ST_TEXTCHEVRONINVERTED = (short) 141; + public static final short ST_TEXTRINGINSIDE = (short) 142; + public static final short ST_TEXTRINGOUTSIDE = (short) 143; + public static final short ST_TEXTARCHUPCURVE = (short) 144; + public static final short ST_TEXTARCHDOWNCURVE = (short) 145; + public static final short ST_TEXTCIRCLECURVE = (short) 146; + public static final short ST_TEXTBUTTONCURVE = (short) 147; + public static final short ST_TEXTARCHUPPOUR = (short) 148; + public static final short ST_TEXTARCHDOWNPOUR = (short) 149; + public static final short ST_TEXTCIRCLEPOUR = (short) 150; + public static final short ST_TEXTBUTTONPOUR = (short) 151; + public static final short ST_TEXTCURVEUP = (short) 152; + public static final short ST_TEXTCURVEDOWN = (short) 153; + public static final short ST_TEXTCASCADEUP = (short) 154; + public static final short ST_TEXTCASCADEDOWN = (short) 155; + public static final short ST_TEXTWAVE1 = (short) 156; + public static final short ST_TEXTWAVE2 = (short) 157; + public static final short ST_TEXTWAVE3 = (short) 158; + public static final short ST_TEXTWAVE4 = (short) 159; + public static final short ST_TEXTINFLATE = (short) 160; + public static final short ST_TEXTDEFLATE = (short) 161; + public static final short ST_TEXTINFLATEBOTTOM = (short) 162; + public static final short ST_TEXTDEFLATEBOTTOM = (short) 163; + public static final short ST_TEXTINFLATETOP = (short) 164; + public static final short ST_TEXTDEFLATETOP = (short) 165; + public static final short ST_TEXTDEFLATEINFLATE = (short) 166; + public static final short ST_TEXTDEFLATEINFLATEDEFLATE = (short) 167; + public static final short ST_TEXTFADERIGHT = (short) 168; + public static final short ST_TEXTFADELEFT = (short) 169; + public static final short ST_TEXTFADEUP = (short) 170; + public static final short ST_TEXTFADEDOWN = (short) 171; + public static final short ST_TEXTSLANTUP = (short) 172; + public static final short ST_TEXTSLANTDOWN = (short) 173; + public static final short ST_TEXTCANUP = (short) 174; + public static final short ST_TEXTCANDOWN = (short) 175; + public static final short ST_FLOWCHARTALTERNATEPROCESS = (short) 176; + public static final short ST_FLOWCHARTOFFPAGECONNECTOR = (short) 177; + public static final short ST_CALLOUT90 = (short) 178; + public static final short ST_ACCENTCALLOUT90 = (short) 179; + public static final short ST_BORDERCALLOUT90 = (short) 180; + public static final short ST_ACCENTBORDERCALLOUT90 = (short) 181; + public static final short ST_LEFTRIGHTUPARROW = (short) 182; + public static final short ST_SUN = (short) 183; + public static final short ST_MOON = (short) 184; + public static final short ST_BRACKETPAIR = (short) 185; + public static final short ST_BRACEPAIR = (short) 186; + public static final short ST_SEAL4 = (short) 187; + public static final short ST_DOUBLEWAVE = (short) 188; + public static final short ST_ACTIONBUTTONBLANK = (short) 189; + public static final short ST_ACTIONBUTTONHOME = (short) 190; + public static final short ST_ACTIONBUTTONHELP = (short) 191; + public static final short ST_ACTIONBUTTONINFORMATION = (short) 192; + public static final short ST_ACTIONBUTTONFORWARDNEXT = (short) 193; + public static final short ST_ACTIONBUTTONBACKPREVIOUS = (short) 194; + public static final short ST_ACTIONBUTTONEND = (short) 195; + public static final short ST_ACTIONBUTTONBEGINNING = (short) 196; + public static final short ST_ACTIONBUTTONRETURN = (short) 197; + public static final short ST_ACTIONBUTTONDOCUMENT = (short) 198; + public static final short ST_ACTIONBUTTONSOUND = (short) 199; + public static final short ST_ACTIONBUTTONMOVIE = (short) 200; + public static final short ST_HOSTCONTROL = (short) 201; + public static final short ST_TEXTBOX = (short) 202; + public static final short ST_NIL = (short) 0x0FFF; - protected HSSFPatriarch patriarch; + protected HSSFPatriarch patriarch; - /** Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */ - Map shapeToObj = new HashMap(); - private DrawingManager2 drawingManager; - private short drawingGroupId; + /** + * Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} + */ + private final Map shapeToObj = new HashMap(); + private DrawingManager2 drawingManager; + private short drawingGroupId; - /** - * list of "tail" records that need to be serialized after all drawing group records - */ - private List tailRec = new ArrayList(); + /** + * list of "tail" records that need to be serialized after all drawing group records + */ + private List tailRec = new ArrayList(); - public EscherAggregate( DrawingManager2 drawingManager ) - { - this.drawingManager = drawingManager; - } + public EscherAggregate(DrawingManager2 drawingManager) { + this.drawingManager = drawingManager; + } - /** - * @return Returns the current sid. - */ - public short getSid() - { - return sid; - } + /** + * @return Returns the current sid. + */ + public short getSid() { + return sid; + } - /** - * Calculates the string representation of this record. This is - * simply a dump of all the records. - */ - public String toString() - { - String nl = System.getProperty( "line.separtor" ); + /** + * Calculates the string representation of this record. This is + * simply a dump of all the records. + */ + public String toString() { + String nl = System.getProperty("line.separtor"); - StringBuffer result = new StringBuffer(); - result.append( '[' ).append( getRecordName() ).append( ']' + nl ); - for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) - { - EscherRecord escherRecord = (EscherRecord) iterator.next(); - result.append( escherRecord.toString() ); - } - result.append( "[/" ).append( getRecordName() ).append( ']' + nl ); + StringBuffer result = new StringBuffer(); + result.append('[').append(getRecordName()).append(']' + nl); + for (Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) { + EscherRecord escherRecord = (EscherRecord) iterator.next(); + result.append(escherRecord.toString()); + } + result.append("[/").append(getRecordName()).append(']' + nl); - return result.toString(); - } - - public String toXml(String tab){ + return result.toString(); + } + + public String toXml(String tab) { StringBuilder builder = new StringBuilder(); builder.append(tab).append("<").append(getRecordName()).append(">\n"); - for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) - { + for (Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) { EscherRecord escherRecord = (EscherRecord) iterator.next(); - builder.append( escherRecord.toXml(tab+"\t") ); + builder.append(escherRecord.toXml(tab + "\t")); } builder.append(tab).append("\n"); return builder.toString(); } - /** - * Collapses the drawing records into an aggregate. - */ - public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager2 drawingManager ) - { - // Keep track of any shape records created so we can match them back to the object id's. - // Textbox objects are also treated as shape objects. - final List shapeRecords = new ArrayList(); - EscherRecordFactory recordFactory = new DefaultEscherRecordFactory() - { - public EscherRecord createRecord( byte[] data, int offset ) - { - EscherRecord r = super.createRecord( data, offset ); - if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID ) - { - shapeRecords.add( r ); - } - return r; - } - }; + private static boolean isDrawingLayerRecord(final short sid) { + return sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == TextObjectRecord.sid; + } - // Calculate the size of the buffer - EscherAggregate agg = new EscherAggregate(drawingManager); - int loc = locFirstDrawingRecord; - int dataSize = 0; - while ( loc + 1 < records.size() - && sid( records, loc ) == DrawingRecord.sid - && isObjectRecord( records, loc + 1 ) ) - { - dataSize += ( (DrawingRecord) records.get( loc ) ).getRecordData().length; - loc += 2; - while ( loc + 1 < records.size() - && sid( records, loc ) == ContinueRecord.sid - && isObjectRecord( records, loc + 1 ) ) - { - dataSize += ( (ContinueRecord) records.get( loc ) ).getData().length; - loc += 2; + /** + * Collapses the drawing records into an aggregate. + * read Drawing and Continue records into single byte array, create Escher tree from byte array, create map + */ + public static EscherAggregate createAggregate(List records, int locFirstDrawingRecord, DrawingManager2 drawingManager) { + // Keep track of any shape records created so we can match them back to the object id's. + // Textbox objects are also treated as shape objects. + final List shapeRecords = new ArrayList(); + EscherRecordFactory recordFactory = new DefaultEscherRecordFactory() { + public EscherRecord createRecord(byte[] data, int offset) { + EscherRecord r = super.createRecord(data, offset); + if (r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID) { + shapeRecords.add(r); + } + return r; } - } + }; - // Create one big buffer - byte buffer[] = new byte[dataSize]; - int offset = 0; - loc = locFirstDrawingRecord; - while ( loc + 1 < records.size() - && sid( records, loc ) == DrawingRecord.sid - && isObjectRecord( records, loc + 1 ) ) - { - DrawingRecord drawingRecord = (DrawingRecord) records.get( loc ); - System.arraycopy( drawingRecord.getRecordData(), 0, buffer, offset, drawingRecord.getRecordData().length ); - offset += drawingRecord.getRecordData().length; - loc += 2; - while ( loc + 1 < records.size() - && sid( records, loc ) == ContinueRecord.sid - && isObjectRecord( records, loc + 1 ) ) - { - ContinueRecord continueRecord = (ContinueRecord) records.get( loc ); - System.arraycopy( continueRecord.getData(), 0, buffer, offset, continueRecord.getData().length ); - offset += continueRecord.getData().length; - loc += 2; + // Create one big buffer + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + EscherAggregate agg = new EscherAggregate(drawingManager); + int loc = locFirstDrawingRecord; + while (loc + 1 < records.size() + && (isDrawingLayerRecord(sid(records, loc)))) { + try { + if (!(sid(records, loc) == DrawingRecord.sid || sid(records, loc) == ContinueRecord.sid)) { + loc++; + continue; + } + if (sid(records, loc) == DrawingRecord.sid) { + buffer.write(((DrawingRecord) records.get(loc)).getRecordData()); + } else { + buffer.write(((ContinueRecord) records.get(loc)).getData()); + } + } catch (IOException e) { + throw new RuntimeException("Couldn't get data from drawing/continue records", e); } - } + loc++; + } - // Decode the shapes - // agg.escherRecords = new ArrayList(); - int pos = 0; - while ( pos < dataSize ) - { - EscherRecord r = recordFactory.createRecord( buffer, pos ); - int bytesRead = r.fillFields( buffer, pos, recordFactory ); - agg.addEscherRecord( r ); - pos += bytesRead; - } + // Decode the shapes + // agg.escherRecords = new ArrayList(); + int pos = 0; + while (pos < buffer.size()) { + EscherRecord r = recordFactory.createRecord(buffer.toByteArray(), pos); + int bytesRead = r.fillFields(buffer.toByteArray(), pos, recordFactory); + agg.addEscherRecord(r); + pos += bytesRead; + } - // Associate the object records with the shapes - loc = locFirstDrawingRecord; - int shapeIndex = 0; - agg.shapeToObj = new HashMap(); - while ( loc + 1 < records.size() - && sid( records, loc ) == DrawingRecord.sid - && isObjectRecord( records, loc + 1 ) ) - { - Record objRecord = (Record) records.get( loc + 1 ); - agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord ); - loc += 2; - while ( loc + 1 < records.size() - && sid( records, loc ) == ContinueRecord.sid - && isObjectRecord( records, loc + 1 ) ) - { - objRecord = (Record) records.get( loc + 1 ); - agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord ); - loc += 2; + // Associate the object records with the shapes + loc = locFirstDrawingRecord + 1; + int shapeIndex = 0; + while (loc < records.size() + && (isDrawingLayerRecord(sid(records, loc)))) { + if (!isObjectRecord(records, loc)) { + loc++; + continue; } - } + Record objRecord = (Record) records.get(loc); + agg.shapeToObj.put(shapeRecords.get(shapeIndex++), objRecord); + loc++; + } - return agg; + // any NoteRecords that follow the drawing block must be aggregated and and saved in the tailRec collection + // TODO remove this logic. 'tail' records should be inserted in the main record stream + while (loc < records.size()) { + if (sid(records, loc) == NoteRecord.sid) { + NoteRecord r = (NoteRecord) records.get(loc); + agg.tailRec.add(r); + } else { + break; + } + loc++; + } - } - - /** - * Serializes this aggregate to a byte array. Since this is an aggregate - * record it will effectively serialize the aggregated records. - * - * @param offset The offset into the start of the array. - * @param data The byte array to serialize to. - * @return The number of bytes serialized. - */ - public int serialize( int offset, byte[] data ) - { - convertUserModelToRecords(); - - // Determine buffer size - List records = getEscherRecords(); - int size = getEscherRecordSize( records ); - byte[] buffer = new byte[size]; + int locLastDrawingRecord = loc; + // replace drawing block with the created EscherAggregate + records.subList(locFirstDrawingRecord, locLastDrawingRecord).clear(); + records.add(locFirstDrawingRecord, agg); - // Serialize escher records into one big data structure and keep note of ending offsets. - final List spEndingOffsets = new ArrayList(); - final List shapes = new ArrayList(); - int pos = 0; - for ( Iterator iterator = records.iterator(); iterator.hasNext(); ) - { - EscherRecord e = (EscherRecord) iterator.next(); - pos += e.serialize( pos, buffer, new EscherSerializationListener() - { - public void beforeRecordSerialize( int offset, short recordId, EscherRecord record ) - { - } + return agg; + } - public void afterRecordSerialize( int offset, short recordId, int size, EscherRecord record ) - { - if ( recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID ) - { - spEndingOffsets.add( Integer.valueOf( offset ) ); - shapes.add( record ); - } - } - } ); - } - // todo: fix this - shapes.add( 0, null ); - spEndingOffsets.add( 0, null ); + /** + * Serializes this aggregate to a byte array. Since this is an aggregate + * record it will effectively serialize the aggregated records. + * + * @param offset The offset into the start of the array. + * @param data The byte array to serialize to. + * @return The number of bytes serialized. + */ + public int serialize(int offset, byte[] data) { + convertUserModelToRecords(); - // Split escher records into separate MSODRAWING and OBJ, TXO records. (We don't break on - // the first one because it's the patriach). - pos = offset; - for ( int i = 1; i < shapes.size(); i++ ) - { - int endOffset = ( (Integer) spEndingOffsets.get( i ) ).intValue() - 1; - int startOffset; - if ( i == 1 ) - startOffset = 0; - else - startOffset = ( (Integer) spEndingOffsets.get( i - 1 ) ).intValue(); + // Determine buffer size + List records = getEscherRecords(); + int size = getEscherRecordSize(records); + byte[] buffer = new byte[size]; - // Create and write a new MSODRAWING record - DrawingRecord drawing = new DrawingRecord(); - byte[] drawingData = new byte[endOffset - startOffset + 1]; - System.arraycopy( buffer, startOffset, drawingData, 0, drawingData.length ); - drawing.setData( drawingData ); - int temp = drawing.serialize( pos, data ); - pos += temp; - // Write the matching OBJ record - Record obj = shapeToObj.get( shapes.get( i ) ); - temp = obj.serialize( pos, data ); - pos += temp; + // Serialize escher records into one big data structure and keep note of ending offsets. + final List spEndingOffsets = new ArrayList(); + final List shapes = new ArrayList(); + int pos = 0; + for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { + EscherRecord e = (EscherRecord) iterator.next(); + pos += e.serialize(pos, buffer, new EscherSerializationListener() { + public void beforeRecordSerialize(int offset, short recordId, EscherRecord record) { + } - } + public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) { + if (recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID) { + spEndingOffsets.add(Integer.valueOf(offset)); + shapes.add(record); + } + } + }); + } + // todo: fix this + shapes.add(0, null); + spEndingOffsets.add(0, null); - // write records that need to be serialized after all drawing group records - for ( int i = 0; i < tailRec.size(); i++ ) - { - Record rec = (Record)tailRec.get(i); - pos += rec.serialize( pos, data ); - } + // Split escher records into separate MSODRAWING and OBJ, TXO records. (We don't break on + // the first one because it's the patriach). + pos = offset; + int writtenEscherBytes = 0; + for (int i = 1; i < shapes.size(); i++) { + int endOffset = ((Integer) spEndingOffsets.get(i)).intValue() - 1; + int startOffset; + if (i == 1) + startOffset = 0; + else + startOffset = ((Integer) spEndingOffsets.get(i - 1)).intValue(); - int bytesWritten = pos - offset; - if ( bytesWritten != getRecordSize() ) - throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() ); - return bytesWritten; - } - /** - * How many bytes do the raw escher records contain. - * @param records List of escher records - * @return the number of bytes - */ - private int getEscherRecordSize( List records ) - { - int size = 0; - for ( Iterator iterator = records.iterator(); iterator.hasNext(); ) - size += ( (EscherRecord) iterator.next() ).getRecordSize(); - return size; - } + byte[] drawingData = new byte[endOffset - startOffset + 1]; + System.arraycopy(buffer, startOffset, drawingData, 0, drawingData.length); + int temp = 0; - public int getRecordSize() { - // TODO - convert this to RecordAggregate - convertUserModelToRecords(); - List records = getEscherRecords(); - int rawEscherSize = getEscherRecordSize( records ); - int drawingRecordSize = rawEscherSize + ( shapeToObj.size() ) * 4; - int objRecordSize = 0; - for ( Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); ) - { - Record r = (Record) iterator.next(); - objRecordSize += r.getRecordSize(); - } - int tailRecordSize = 0; - for ( Iterator iterator = tailRec.iterator(); iterator.hasNext(); ) - { - Record r = (Record) iterator.next(); - tailRecordSize += r.getRecordSize(); - } - return drawingRecordSize + objRecordSize + tailRecordSize; - } + //First record in drawing layer MUST be DrawingRecord + if (writtenEscherBytes + drawingData.length > RecordInputStream.MAX_RECORD_DATA_SIZE && i != 1) { + for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { + ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + temp += drawing.serialize(pos + temp, data); + } + } else { + for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { + if (j == 0) { + DrawingRecord drawing = new DrawingRecord(); + drawing.setData(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + temp += drawing.serialize(pos + temp, data); + } else { + ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + temp += drawing.serialize(pos + temp, data); + } + } - /** - * Associates an escher record to an OBJ record or a TXO record. - */ - Object associateShapeToObjRecord( EscherRecord r, ObjRecord objRecord ) - { - return shapeToObj.put( r, objRecord ); - } + } - public HSSFPatriarch getPatriarch() - { - return patriarch; - } + pos += temp; + writtenEscherBytes += drawingData.length; - public void setPatriarch( HSSFPatriarch patriarch ) - { - this.patriarch = patriarch; - } + // Write the matching OBJ record + Record obj = shapeToObj.get(shapes.get(i)); + temp = obj.serialize(pos, data); + pos += temp; - /** - * Converts the Records into UserModel - * objects on the bound HSSFPatriarch - */ - public void convertRecordsToUserModel() { - if(patriarch == null) { - throw new IllegalStateException("Must call setPatriarch() first"); - } + } - // The top level container ought to have - // the DgRecord and the container of one container - // per shape group (patriach overall first) - EscherContainerRecord topContainer = getEscherContainer(); - if(topContainer == null) { - return; - } - topContainer = topContainer.getChildContainers().get(0); + // write records that need to be serialized after all drawing group records + for (int i = 0; i < tailRec.size(); i++) { + Record rec = (Record) tailRec.get(i); + pos += rec.serialize(pos, data); + } - List tcc = topContainer.getChildContainers(); - if(tcc.size() == 0) { - throw new IllegalStateException("No child escher containers at the point that should hold the patriach data, and one container per top level shape!"); - } + int bytesWritten = pos - offset; + if (bytesWritten != getRecordSize()) + throw new RecordFormatException(bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize()); + return bytesWritten; + } - // First up, get the patriach position - // This is in the first EscherSpgrRecord, in - // the first container, with a EscherSRecord too - EscherContainerRecord patriachContainer = - (EscherContainerRecord)tcc.get(0); - EscherSpgrRecord spgr = null; - for(Iterator it = patriachContainer.getChildIterator(); it.hasNext();) { - EscherRecord r = it.next(); - if(r instanceof EscherSpgrRecord) { - spgr = (EscherSpgrRecord)r; - break; - } - } - if(spgr != null) { - patriarch.setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); - } + /** + * How many bytes do the raw escher records contain. + * + * @param records List of escher records + * @return the number of bytes + */ + private int getEscherRecordSize(List records) { + int size = 0; + for (Iterator iterator = records.iterator(); iterator.hasNext(); ) + size += ((EscherRecord) iterator.next()).getRecordSize(); + return size; + } - convertRecordsToUserModelRecursive(tcc, patriarch, null); + public int getRecordSize() { + // TODO - convert this to RecordAggregate + convertUserModelToRecords(); + // To determine size of aggregate record we have to know size of each DrawingRecord because if DrawingRecord + // is split into several continue records we have to add header size to total EscherAggregate size + int continueRecordsHeadersSize = 0; + // Determine buffer size + List records = getEscherRecords(); + int rawEscherSize = getEscherRecordSize(records); + byte[] buffer = new byte[rawEscherSize]; + final List spEndingOffsets = new ArrayList(); + int pos = 0; + for (EscherRecord e : records) { + pos += e.serialize(pos, buffer, new EscherSerializationListener() { + public void beforeRecordSerialize(int offset, short recordId, EscherRecord record) { + } - // Now, clear any trace of what records make up - // the patriarch - // Otherwise, everything will go horribly wrong - // when we try to write out again.... + public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) { + if (recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID) { + spEndingOffsets.add(offset); + } + } + }); + } + spEndingOffsets.add(0, 0); + + for (int i = 1; i < spEndingOffsets.size(); i++) { + if (spEndingOffsets.get(i) - spEndingOffsets.get(i - 1) <= RecordInputStream.MAX_RECORD_DATA_SIZE){ + continue; + } + continueRecordsHeadersSize += ((spEndingOffsets.get(i) - spEndingOffsets.get(i - 1)) / RecordInputStream.MAX_RECORD_DATA_SIZE)*4; + } + + int drawingRecordSize = rawEscherSize + (shapeToObj.size()) * 4; + int objRecordSize = 0; + for (Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); ) { + Record r = (Record) iterator.next(); + objRecordSize += r.getRecordSize(); + } + int tailRecordSize = 0; + for (Iterator iterator = tailRec.iterator(); iterator.hasNext(); ) { + Record r = (Record) iterator.next(); + tailRecordSize += r.getRecordSize(); + } + return drawingRecordSize + objRecordSize + tailRecordSize +continueRecordsHeadersSize; + } + + /** + * Associates an escher record to an OBJ record or a TXO record. + */ + Object associateShapeToObjRecord(EscherRecord r, ObjRecord objRecord) { + return shapeToObj.put(r, objRecord); + } + + public HSSFPatriarch getPatriarch() { + return patriarch; + } + + public void setPatriarch(HSSFPatriarch patriarch) { + this.patriarch = patriarch; + } + + /** + * Converts the Records into UserModel + * objects on the bound HSSFPatriarch + */ + public void convertRecordsToUserModel() { + if (patriarch == null) { + throw new IllegalStateException("Must call setPatriarch() first"); + } + + // The top level container ought to have + // the DgRecord and the container of one container + // per shape group (patriach overall first) + EscherContainerRecord topContainer = getEscherContainer(); + if (topContainer == null) { + return; + } + topContainer = topContainer.getChildContainers().get(0); + + List tcc = topContainer.getChildContainers(); + if (tcc.size() == 0) { + throw new IllegalStateException("No child escher containers at the point that should hold the patriach data, and one container per top level shape!"); + } + + // First up, get the patriach position + // This is in the first EscherSpgrRecord, in + // the first container, with a EscherSRecord too + EscherContainerRecord patriachContainer = + (EscherContainerRecord) tcc.get(0); + EscherSpgrRecord spgr = null; + for (Iterator it = patriachContainer.getChildIterator(); it.hasNext(); ) { + EscherRecord r = it.next(); + if (r instanceof EscherSpgrRecord) { + spgr = (EscherSpgrRecord) r; + break; + } + } + if (spgr != null) { + patriarch.setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + } + + convertRecordsToUserModelRecursive(tcc, patriarch, null); + + // Now, clear any trace of what records make up + // the patriarch + // Otherwise, everything will go horribly wrong + // when we try to write out again.... // clearEscherRecords(); - drawingManager.getDgg().setFileIdClusters(new EscherDggRecord.FileIdCluster[0]); + drawingManager.getDgg().setFileIdClusters(new EscherDggRecord.FileIdCluster[0]); - // TODO: Support converting our records - // back into shapes - // log.log(POILogger.WARN, "Not processing objects into Patriarch!"); - } + // TODO: Support converting our records + // back into shapes + // log.log(POILogger.WARN, "Not processing objects into Patriarch!"); + } - private static void convertRecordsToUserModelRecursive(List tcc, HSSFShapeContainer container, HSSFShape parent) { - // Now process the containers for each group - // and objects - for(int i=1; i 0) - { - HSSFShapeGroup group = new HSSFShapeGroup( parent, new HSSFClientAnchor() ); - addToParentOrContainer(group, container, parent); + // Could be a group, or a base object + if (shapeContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { + // Group + final int shapeChildren = shapeContainer.getChildRecords().size(); + if (shapeChildren > 0) { + HSSFShapeGroup group = new HSSFShapeGroup(parent, new HSSFClientAnchor()); + addToParentOrContainer(group, container, parent); - EscherContainerRecord groupContainer = (EscherContainerRecord) shapeContainer.getChild( 0 ); - convertRecordsToUserModel( groupContainer, group ); - - if (shapeChildren>1){ - convertRecordsToUserModelRecursive(shapeContainer.getChildRecords(), container, group); - } - } else - { - log.log( POILogger.WARN, - "Found drawing group without children." ); - } + EscherContainerRecord groupContainer = (EscherContainerRecord) shapeContainer.getChild(0); + convertRecordsToUserModel(groupContainer, group); - } else if (shapeContainer.getRecordId() == EscherContainerRecord.SP_CONTAINER) - { - EscherSpRecord spRecord = shapeContainer - .getChildById( EscherSpRecord.RECORD_ID ); - int type = spRecord.getShapeType(); + if (shapeChildren > 1) { + convertRecordsToUserModelRecursive(shapeContainer.getChildRecords(), container, group); + } + } else { + log.log(POILogger.WARN, + "Found drawing group without children."); + } - switch (type) - { - case ST_TEXTBOX: - HSSFTextbox box = new HSSFTextbox( parent, - new HSSFClientAnchor() ); - addToParentOrContainer(box, container, parent); + } else if (shapeContainer.getRecordId() == EscherContainerRecord.SP_CONTAINER) { + EscherSpRecord spRecord = shapeContainer + .getChildById(EscherSpRecord.RECORD_ID); + int type = spRecord.getShapeType(); - convertRecordsToUserModel( shapeContainer, box ); - break; - case ST_PICTUREFRAME: - // Duplicated from - // org.apache.poi.hslf.model.Picture.getPictureIndex() - EscherOptRecord opt = (EscherOptRecord) getEscherChild( - shapeContainer, EscherOptRecord.RECORD_ID ); - EscherSimpleProperty prop = (EscherSimpleProperty)opt.lookup( - EscherProperties.BLIP__BLIPTODISPLAY ); - if (prop == null) - { - log.log( POILogger.WARN, - "Picture index for picture shape not found." ); - } else - { - int pictureIndex = prop.getPropertyValue(); + switch (type) { + case ST_TEXTBOX: + HSSFTextbox box = new HSSFTextbox(parent, + new HSSFClientAnchor()); + addToParentOrContainer(box, container, parent); - EscherClientAnchorRecord anchorRecord = (EscherClientAnchorRecord) getEscherChild( - shapeContainer, - EscherClientAnchorRecord.RECORD_ID ); + convertRecordsToUserModel(shapeContainer, box); + break; + case ST_PICTUREFRAME: + // Duplicated from + // org.apache.poi.hslf.model.Picture.getPictureIndex() + EscherOptRecord opt = (EscherOptRecord) getEscherChild( + shapeContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty) opt.lookup( + EscherProperties.BLIP__BLIPTODISPLAY); + if (prop == null) { + log.log(POILogger.WARN, + "Picture index for picture shape not found."); + } else { + int pictureIndex = prop.getPropertyValue(); - EscherChildAnchorRecord childRecord = (EscherChildAnchorRecord) getEscherChild( - shapeContainer, - EscherChildAnchorRecord.RECORD_ID ); + EscherClientAnchorRecord anchorRecord = (EscherClientAnchorRecord) getEscherChild( + shapeContainer, + EscherClientAnchorRecord.RECORD_ID); - if (anchorRecord!=null && childRecord!=null){ - log.log( POILogger.WARN, "Picture with both CLIENT and CHILD anchor: "+ type ); - } - - HSSFAnchor anchor; - if (anchorRecord!=null){ - anchor = toClientAnchor(anchorRecord); - }else{ - anchor = toChildAnchor(childRecord); - } + EscherChildAnchorRecord childRecord = (EscherChildAnchorRecord) getEscherChild( + shapeContainer, + EscherChildAnchorRecord.RECORD_ID); - HSSFPicture picture = new HSSFPicture( parent, anchor ); - picture.setPictureIndex( pictureIndex ); + if (anchorRecord != null && childRecord != null) { + log.log(POILogger.WARN, "Picture with both CLIENT and CHILD anchor: " + type); + } - addToParentOrContainer(picture, container, parent); - } - break; - default: - final HSSFSimpleShape shape = new HSSFSimpleShape( parent, - new HSSFClientAnchor() ); - addToParentOrContainer(shape, container, parent); - convertRecordsToUserModel( shapeContainer, shape); - - log.log( POILogger.WARN, "Unhandled shape type: " - + type ); - break; - } - } else - { - log.log( POILogger.WARN, "Unexpected record id of shape group." ); - } + HSSFAnchor anchor; + if (anchorRecord != null) { + anchor = toClientAnchor(anchorRecord); + } else { + anchor = toChildAnchor(childRecord); + } - } - } + HSSFPicture picture = new HSSFPicture(parent, anchor); + picture.setPictureIndex(pictureIndex); + + addToParentOrContainer(picture, container, parent); + } + break; + default: + final HSSFSimpleShape shape = new HSSFSimpleShape(parent, + new HSSFClientAnchor()); + addToParentOrContainer(shape, container, parent); + convertRecordsToUserModel(shapeContainer, shape); + + log.log(POILogger.WARN, "Unhandled shape type: " + + type); + break; + } + } else { + log.log(POILogger.WARN, "Unexpected record id of shape group."); + } + + } + } private static void addToParentOrContainer(HSSFShape shape, HSSFShapeContainer container, HSSFShape parent) { - if (parent instanceof HSSFShapeGroup) - ((HSSFShapeGroup) parent).addShape(shape); - else if (container instanceof HSSFPatriarch) - ((HSSFPatriarch) container).addShape(shape); - else - container.getChildren().add(shape); - } + if (parent instanceof HSSFShapeGroup) + ((HSSFShapeGroup) parent).addShape(shape); + else if (container instanceof HSSFPatriarch) + ((HSSFPatriarch) container).addShape(shape); + else + container.getChildren().add(shape); + } - private static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord){ + private static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) { HSSFClientAnchor anchor = new HSSFClientAnchor(); anchor.setAnchorType(anchorRecord.getFlag()); - anchor.setCol1( anchorRecord.getCol1() ); - anchor.setCol2( anchorRecord.getCol2() ); - anchor.setDx1( anchorRecord.getDx1() ); - anchor.setDx2( anchorRecord.getDx2() ); - anchor.setDy1( anchorRecord.getDy1() ); - anchor.setDy2( anchorRecord.getDy2() ); - anchor.setRow1( anchorRecord.getRow1() ); - anchor.setRow2( anchorRecord.getRow2() ); + anchor.setCol1(anchorRecord.getCol1()); + anchor.setCol2(anchorRecord.getCol2()); + anchor.setDx1(anchorRecord.getDx1()); + anchor.setDx2(anchorRecord.getDx2()); + anchor.setDy1(anchorRecord.getDy1()); + anchor.setDy2(anchorRecord.getDy2()); + anchor.setRow1(anchorRecord.getRow1()); + anchor.setRow2(anchorRecord.getRow2()); return anchor; } - private static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord){ + private static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) { HSSFChildAnchor anchor = new HSSFChildAnchor(); // anchor.setAnchorType(anchorRecord.getFlag()); // anchor.setCol1( anchorRecord.getCol1() ); // anchor.setCol2( anchorRecord.getCol2() ); - anchor.setDx1( anchorRecord.getDx1() ); - anchor.setDx2( anchorRecord.getDx2() ); - anchor.setDy1( anchorRecord.getDy1() ); - anchor.setDy2( anchorRecord.getDy2() ); + anchor.setDx1(anchorRecord.getDx1()); + anchor.setDx2(anchorRecord.getDx2()); + anchor.setDy1(anchorRecord.getDy1()); + anchor.setDy2(anchorRecord.getDy2()); // anchor.setRow1( anchorRecord.getRow1() ); // anchor.setRow2( anchorRecord.getRow2() ); return anchor; } - private static void convertRecordsToUserModel(EscherContainerRecord shapeContainer, Object model) { - for(Iterator it = shapeContainer.getChildIterator(); it.hasNext();) { - EscherRecord r = it.next(); - if(r instanceof EscherSpgrRecord) { - // This may be overriden by a later EscherClientAnchorRecord - EscherSpgrRecord spgr = (EscherSpgrRecord)r; + private static void convertRecordsToUserModel(EscherContainerRecord shapeContainer, Object model) { + for (Iterator it = shapeContainer.getChildIterator(); it.hasNext(); ) { + EscherRecord r = it.next(); + if (r instanceof EscherSpgrRecord) { + // This may be overriden by a later EscherClientAnchorRecord + EscherSpgrRecord spgr = (EscherSpgrRecord) r; - if(model instanceof HSSFShapeGroup) { - HSSFShapeGroup g = (HSSFShapeGroup)model; - g.setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); - } else { - throw new IllegalStateException("Got top level anchor but not processing a group"); - } - } - else if(r instanceof EscherClientAnchorRecord) { - EscherClientAnchorRecord car = (EscherClientAnchorRecord)r; + if (model instanceof HSSFShapeGroup) { + HSSFShapeGroup g = (HSSFShapeGroup) model; + g.setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + } else { + throw new IllegalStateException("Got top level anchor but not processing a group"); + } + } else if (r instanceof EscherClientAnchorRecord) { + EscherClientAnchorRecord car = (EscherClientAnchorRecord) r; - if(model instanceof HSSFShape) { - HSSFShape g = (HSSFShape)model; - g.getAnchor().setDx1(car.getDx1()); - g.getAnchor().setDx2(car.getDx2()); - g.getAnchor().setDy1(car.getDy1()); - g.getAnchor().setDy2(car.getDy2()); - } else { - throw new IllegalStateException("Got top level anchor but not processing a group or shape"); - } - } - else if(r instanceof EscherTextboxRecord) { - EscherTextboxRecord tbr = (EscherTextboxRecord)r; + if (model instanceof HSSFShape) { + HSSFShape g = (HSSFShape) model; + g.getAnchor().setDx1(car.getDx1()); + g.getAnchor().setDx2(car.getDx2()); + g.getAnchor().setDy1(car.getDy1()); + g.getAnchor().setDy2(car.getDy2()); + } else { + throw new IllegalStateException("Got top level anchor but not processing a group or shape"); + } + } else if (r instanceof EscherTextboxRecord) { + EscherTextboxRecord tbr = (EscherTextboxRecord) r; - // Also need to find the TextObjectRecord too - // TODO - } - else if(r instanceof EscherSpRecord) { - // Use flags if needed - final EscherSpRecord spr = (EscherSpRecord) r; - if (model instanceof HSSFShape){ - final HSSFShape s = (HSSFShape) model; - } - } - else if(r instanceof EscherOptRecord) { - // Use properties if needed - } - else { - //System.err.println(r); - } - } - } + // Also need to find the TextObjectRecord too + // TODO + } else if (r instanceof EscherSpRecord) { + // Use flags if needed + final EscherSpRecord spr = (EscherSpRecord) r; + if (model instanceof HSSFShape) { + final HSSFShape s = (HSSFShape) model; + } + } else if (r instanceof EscherOptRecord) { + // Use properties if needed + } else { + //System.err.println(r); + } + } + } - public void clear() - { - clearEscherRecords(); - shapeToObj.clear(); + public void clear() { + clearEscherRecords(); + shapeToObj.clear(); // lastShapeId = 1024; - } + } - protected String getRecordName() - { - return "ESCHERAGGREGATE"; - } + protected String getRecordName() { + return "ESCHERAGGREGATE"; + } - // =============== Private methods ======================== + // =============== Private methods ======================== - private static boolean isObjectRecord( List records, int loc ) - { - return sid( records, loc ) == ObjRecord.sid || sid( records, loc ) == TextObjectRecord.sid; - } + private static boolean isObjectRecord(List records, int loc) { + return sid(records, loc) == ObjRecord.sid || sid(records, loc) == TextObjectRecord.sid; + } - private void convertUserModelToRecords() - { - if ( patriarch != null ) - { - shapeToObj.clear(); - tailRec.clear(); - clearEscherRecords(); - if ( patriarch.getChildren().size() != 0 ) - { - convertPatriarch( patriarch ); - EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord( 0 ); - EscherContainerRecord spgrContainer = null; - Iterator iter = dgContainer.getChildIterator(); - while (iter.hasNext()) { - EscherRecord child = iter.next(); - if (child.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - spgrContainer = (EscherContainerRecord) child; - } - } - convertShapes( patriarch, spgrContainer, shapeToObj ); + private void convertUserModelToRecords() { + if (patriarch != null) { + shapeToObj.clear(); + tailRec.clear(); + clearEscherRecords(); + if (patriarch.getChildren().size() != 0) { + convertPatriarch(patriarch); + EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord(0); + EscherContainerRecord spgrContainer = null; + Iterator iter = dgContainer.getChildIterator(); + while (iter.hasNext()) { + EscherRecord child = iter.next(); + if (child.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { + spgrContainer = (EscherContainerRecord) child; + } + } + convertShapes(patriarch, spgrContainer, shapeToObj); - patriarch = null; - } - } - } + patriarch = null; + } + } + } - private void convertShapes( HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj ) - { - if ( escherParent == null ) throw new IllegalArgumentException( "Parent record required" ); + private void convertShapes(HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj) { + if (escherParent == null) throw new IllegalArgumentException("Parent record required"); - List shapes = parent.getChildren(); - for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); ) - { - HSSFShape shape = (HSSFShape) iterator.next(); - if ( shape instanceof HSSFShapeGroup ) - { - convertGroup( (HSSFShapeGroup) shape, escherParent, shapeToObj ); - } - else - { - AbstractShape shapeModel = AbstractShape.createShape( - shape, - drawingManager.allocateShapeId(drawingGroupId) ); - shapeToObj.put( findClientData( shapeModel.getSpContainer() ), shapeModel.getObjRecord() ); - if ( shapeModel instanceof TextboxShape ) - { - EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox(); - shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() ); - // escherParent.addChildRecord(escherTextbox); + List shapes = parent.getChildren(); + for (Iterator iterator = shapes.iterator(); iterator.hasNext(); ) { + HSSFShape shape = (HSSFShape) iterator.next(); + if (shape instanceof HSSFShapeGroup) { + convertGroup((HSSFShapeGroup) shape, escherParent, shapeToObj); + } else { + AbstractShape shapeModel = AbstractShape.createShape( + shape, + drawingManager.allocateShapeId(drawingGroupId)); + shapeToObj.put(findClientData(shapeModel.getSpContainer()), shapeModel.getObjRecord()); + if (shapeModel instanceof TextboxShape) { + EscherRecord escherTextbox = ((TextboxShape) shapeModel).getEscherTextbox(); + shapeToObj.put(escherTextbox, ((TextboxShape) shapeModel).getTextObjectRecord()); + // escherParent.addChildRecord(escherTextbox); - if ( shapeModel instanceof CommentShape ){ - CommentShape comment = (CommentShape)shapeModel; - tailRec.add(comment.getNoteRecord()); - } + if (shapeModel instanceof CommentShape) { + CommentShape comment = (CommentShape) shapeModel; + tailRec.add(comment.getNoteRecord()); + } - } - escherParent.addChildRecord( shapeModel.getSpContainer() ); - } - } + } + escherParent.addChildRecord(shapeModel.getSpContainer()); + } + } // drawingManager.newCluster( (short)1 ); // drawingManager.newCluster( (short)2 ); - } + } - private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj ) - { - EscherContainerRecord spgrContainer = new EscherContainerRecord(); - EscherContainerRecord spContainer = new EscherContainerRecord(); - EscherSpgrRecord spgr = new EscherSpgrRecord(); - EscherSpRecord sp = new EscherSpRecord(); - EscherOptRecord opt = new EscherOptRecord(); - EscherRecord anchor; - EscherClientDataRecord clientData = new EscherClientDataRecord(); + private void convertGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj) { + EscherContainerRecord spgrContainer = new EscherContainerRecord(); + EscherContainerRecord spContainer = new EscherContainerRecord(); + EscherSpgrRecord spgr = new EscherSpgrRecord(); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherRecord anchor; + EscherClientDataRecord clientData = new EscherClientDataRecord(); - spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER ); - spgrContainer.setOptions( (short) 0x000F ); - spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); - spContainer.setOptions( (short) 0x000F ); - spgr.setRecordId( EscherSpgrRecord.RECORD_ID ); - spgr.setOptions( (short) 0x0001 ); - spgr.setRectX1( shape.getX1() ); - spgr.setRectY1( shape.getY1() ); - spgr.setRectX2( shape.getX2() ); - spgr.setRectY2( shape.getY2() ); - sp.setRecordId( EscherSpRecord.RECORD_ID ); - sp.setOptions( (short) 0x0002 ); - int shapeId = drawingManager.allocateShapeId(drawingGroupId); - sp.setShapeId( shapeId ); - if (shape.getAnchor() instanceof HSSFClientAnchor) - sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR ); - else - sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD ); - opt.setRecordId( EscherOptRecord.RECORD_ID ); - opt.setOptions( (short) 0x0023 ); - opt.addEscherProperty( new EscherBoolProperty( EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004 ) ); - opt.addEscherProperty( new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x00080000 ) ); + spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); + spgrContainer.setOptions((short) 0x000F); + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + spgr.setRecordId(EscherSpgrRecord.RECORD_ID); + spgr.setOptions((short) 0x0001); + spgr.setRectX1(shape.getX1()); + spgr.setRectY1(shape.getY1()); + spgr.setRectX2(shape.getX2()); + spgr.setRectY2(shape.getY2()); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) 0x0002); + int shapeId = drawingManager.allocateShapeId(drawingGroupId); + sp.setShapeId(shapeId); + if (shape.getAnchor() instanceof HSSFClientAnchor) + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR); + else + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD); + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.setOptions((short) 0x0023); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); - anchor = ConvertAnchor.createAnchor( shape.getAnchor() ); + anchor = ConvertAnchor.createAnchor(shape.getAnchor()); // clientAnchor.setCol1( ( (HSSFClientAnchor) shape.getAnchor() ).getCol1() ); // clientAnchor.setRow1( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow1() ); // clientAnchor.setDx1( (short) shape.getAnchor().getDx1() ); @@ -951,113 +977,108 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { // clientAnchor.setRow2( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow2() ); // clientAnchor.setDx2( (short) shape.getAnchor().getDx2() ); // clientAnchor.setDy2( (short) shape.getAnchor().getDy2() ); - clientData.setRecordId( EscherClientDataRecord.RECORD_ID ); - clientData.setOptions( (short) 0x0000 ); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); - spgrContainer.addChildRecord( spContainer ); - spContainer.addChildRecord( spgr ); - spContainer.addChildRecord( sp ); - spContainer.addChildRecord( opt ); - spContainer.addChildRecord( anchor ); - spContainer.addChildRecord( clientData ); + spgrContainer.addChildRecord(spContainer); + spContainer.addChildRecord(spgr); + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); - ObjRecord obj = new ObjRecord(); - CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); - cmo.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_GROUP ); - cmo.setObjectId( shapeId ); - cmo.setLocked( true ); - cmo.setPrintable( true ); - cmo.setAutofill( true ); - cmo.setAutoline( true ); - GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); - EndSubRecord end = new EndSubRecord(); - obj.addSubRecord( cmo ); - obj.addSubRecord( gmo ); - obj.addSubRecord( end ); - shapeToObj.put( clientData, obj ); + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); + cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP); + cmo.setObjectId(shapeId); + cmo.setLocked(true); + cmo.setPrintable(true); + cmo.setAutofill(true); + cmo.setAutoline(true); + GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); + EndSubRecord end = new EndSubRecord(); + obj.addSubRecord(cmo); + obj.addSubRecord(gmo); + obj.addSubRecord(end); + shapeToObj.put(clientData, obj); - escherParent.addChildRecord( spgrContainer ); + escherParent.addChildRecord(spgrContainer); - convertShapes( shape, spgrContainer, shapeToObj ); + convertShapes(shape, spgrContainer, shapeToObj); - } + } - private EscherRecord findClientData( EscherContainerRecord spContainer ) - { - for (Iterator iterator = spContainer.getChildIterator(); iterator.hasNext();) { - EscherRecord r = iterator.next(); - if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) { - return r; - } - } - throw new IllegalArgumentException( "Can not find client data record" ); - } + private EscherRecord findClientData(EscherContainerRecord spContainer) { + for (Iterator iterator = spContainer.getChildIterator(); iterator.hasNext(); ) { + EscherRecord r = iterator.next(); + if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) { + return r; + } + } + throw new IllegalArgumentException("Can not find client data record"); + } - private void convertPatriarch( HSSFPatriarch patriarch ) - { - EscherContainerRecord dgContainer = new EscherContainerRecord(); - EscherDgRecord dg; - EscherContainerRecord spgrContainer = new EscherContainerRecord(); - EscherContainerRecord spContainer1 = new EscherContainerRecord(); - EscherSpgrRecord spgr = new EscherSpgrRecord(); - EscherSpRecord sp1 = new EscherSpRecord(); + private void convertPatriarch(HSSFPatriarch patriarch) { + EscherContainerRecord dgContainer = new EscherContainerRecord(); + EscherDgRecord dg; + EscherContainerRecord spgrContainer = new EscherContainerRecord(); + EscherContainerRecord spContainer1 = new EscherContainerRecord(); + EscherSpgrRecord spgr = new EscherSpgrRecord(); + EscherSpRecord sp1 = new EscherSpRecord(); - dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER ); - dgContainer.setOptions( (short) 0x000F ); - dg = drawingManager.createDgRecord(); - drawingGroupId = dg.getDrawingGroupId(); + dgContainer.setRecordId(EscherContainerRecord.DG_CONTAINER); + dgContainer.setOptions((short) 0x000F); + dg = drawingManager.createDgRecord(); + drawingGroupId = dg.getDrawingGroupId(); // dg.setOptions( (short) ( drawingId << 4 ) ); // dg.setNumShapes( getNumberOfShapes( patriarch ) ); // dg.setLastMSOSPID( 0 ); // populated after all shape id's are assigned. - spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER ); - spgrContainer.setOptions( (short) 0x000F ); - spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER ); - spContainer1.setOptions( (short) 0x000F ); - spgr.setRecordId( EscherSpgrRecord.RECORD_ID ); - spgr.setOptions( (short) 0x0001 ); // version - spgr.setRectX1( patriarch.getX1() ); - spgr.setRectY1( patriarch.getY1() ); - spgr.setRectX2( patriarch.getX2() ); - spgr.setRectY2( patriarch.getY2() ); - sp1.setRecordId( EscherSpRecord.RECORD_ID ); - sp1.setOptions( (short) 0x0002 ); - sp1.setShapeId( drawingManager.allocateShapeId(dg.getDrawingGroupId()) ); - sp1.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH ); + spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); + spgrContainer.setOptions((short) 0x000F); + spContainer1.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer1.setOptions((short) 0x000F); + spgr.setRecordId(EscherSpgrRecord.RECORD_ID); + spgr.setOptions((short) 0x0001); // version + spgr.setRectX1(patriarch.getX1()); + spgr.setRectY1(patriarch.getY1()); + spgr.setRectX2(patriarch.getX2()); + spgr.setRectY2(patriarch.getY2()); + sp1.setRecordId(EscherSpRecord.RECORD_ID); + sp1.setOptions((short) 0x0002); + sp1.setShapeId(drawingManager.allocateShapeId(dg.getDrawingGroupId())); + sp1.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH); - dgContainer.addChildRecord( dg ); - dgContainer.addChildRecord( spgrContainer ); - spgrContainer.addChildRecord( spContainer1 ); - spContainer1.addChildRecord( spgr ); - spContainer1.addChildRecord( sp1 ); + dgContainer.addChildRecord(dg); + dgContainer.addChildRecord(spgrContainer); + spgrContainer.addChildRecord(spContainer1); + spContainer1.addChildRecord(spgr); + spContainer1.addChildRecord(sp1); - addEscherRecord( dgContainer ); - } + addEscherRecord(dgContainer); + } - private static short sid( List records, int loc ) - { - return ( (Record) records.get( loc ) ).getSid(); - } + private static short sid(List records, int loc) { + return ((Record) records.get(loc)).getSid(); + } - // Duplicated from org.apache.poi.hslf.model.Shape + // Duplicated from org.apache.poi.hslf.model.Shape - /** - * Helper method to return escher child by record ID - * - * @return escher record or null if not found. - */ - private static EscherRecord getEscherChild(EscherContainerRecord owner, - int recordId) - { - for (Iterator iterator = owner.getChildRecords().iterator(); iterator - .hasNext();) - { - EscherRecord escherRecord = (EscherRecord) iterator.next(); - if (escherRecord.getRecordId() == recordId) - return escherRecord; - } - return null; - } + /** + * Helper method to return escher child by record ID + * + * @return escher record or null if not found. + */ + private static EscherRecord getEscherChild(EscherContainerRecord owner, + int recordId) { + for (Iterator iterator = owner.getChildRecords().iterator(); iterator + .hasNext(); ) { + EscherRecord escherRecord = (EscherRecord) iterator.next(); + if (escherRecord.getRecordId() == recordId) + return escherRecord; + } + return null; + } } diff --git a/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java b/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java index 344ad07ef3..aac88b80c9 100644 --- a/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java +++ b/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java @@ -338,14 +338,14 @@ public final class RecordFactoryInputStream { } if (_lastRecord instanceof DrawingGroupRecord) { ((DrawingGroupRecord) _lastRecord).processContinueRecord(contRec.getData()); - return null; - } - if (_lastRecord instanceof DrawingRecord) { - ((DrawingRecord) _lastRecord).processContinueRecord(contRec.getData()); - return null; - } - if (_lastRecord instanceof UnknownRecord) { - //Gracefully handle records that we don't know about, + return null; + } + if (_lastRecord instanceof DrawingRecord) { +// ((DrawingRecord) _lastRecord).appendContinueRecord(contRec.getData()); + return contRec; + } + if (_lastRecord instanceof UnknownRecord) { + //Gracefully handle records that we don't know about, //that happen to be continued return record; } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index c5aa5855a9..a22ce4a0cc 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -17,11 +17,7 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; @@ -30,125 +26,27 @@ import org.apache.poi.hssf.usermodel.HSSFTestHelper; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.util.HexRead; -import java.io.ByteArrayInputStream; -import java.util.ArrayList; -import java.util.LinkedHashMap; +import java.io.*; +import java.util.Arrays; import java.util.List; -import java.util.Map; /** * @author Yegor Kozlov * @author Evgeniy Berlog */ public class TestDrawingAggregate extends TestCase { - /** - * Serialize escher aggregate, read back and assert that the drawing data is preserved. - * - * @param agg the aggregate to test - * @return verified aggregate (serialized and read back) - */ - public static EscherAggregate assertWriteAndReadBack(EscherAggregate agg) { - byte[] dgBytes = agg.serialize(); - - - List dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes)); - - DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); - - // create a dummy sheet consisting of our test data - InternalSheet sheet = InternalSheet.createSheet(); - List records = sheet.getRecords(); - records.clear(); - records.addAll(dgRecords); - records.add(EOFRecord.instance); - - - sheet.aggregateDrawingRecords(drawingManager, false); - assertEquals("drawing was not fully aggregated", 2, records.size()); - assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate); - assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); - EscherAggregate agg2 = (EscherAggregate) records.get(0); - - assertEquals(agg.getEscherRecords().size(), agg2.getEscherRecords().size()); - - // assert that both pre- and after- serialize aggregates have the same xml representation - for (int i = 0; i < agg.getEscherRecords().size(); i++) { - EscherRecord r1 = agg.getEscherRecords().get(i); - EscherRecord r2 = agg2.getEscherRecords().get(i); - - assertEquals(r1.toXml(), r2.toXml()); - } - - return agg2; - } - - /** - * assert that mapping of Obj records to escher shape containers is the same in both aggregates - */ - public static void assertObjectMappingSame(EscherAggregate agg1, EscherAggregate agg2) { - - // map EscherClientDataRecord and EscherTextboxRecord to their parents - Map map1 = new LinkedHashMap(); - for (EscherRecord r : agg1.getEscherRecords()) mapShapeContainers(r, map1); - - Map map2 = new LinkedHashMap(); - for (EscherRecord r : agg2.getEscherRecords()) mapShapeContainers(r, map2); - - assertEquals("aggregates have different number of shapes", map1.size(), map2.size()); - - // for each EscherClientDataRecord get parent SP_CONTAINER and corresponding ObjRecord - // verify that ObjRecord to - List l1 = new ArrayList(map1.keySet()); - List l2 = new ArrayList(map2.keySet()); - for (int i = 0; i < l1.size(); i++) { - EscherRecord e1 = l1.get(i); - EscherRecord e2 = l2.get(i); - ObjRecord obj1 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg1).get(e1); - ObjRecord obj2 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg2).get(e2); - - CommonObjectDataSubRecord cmo1 = (CommonObjectDataSubRecord) obj1.getSubRecords().get(0); - CommonObjectDataSubRecord cmo2 = (CommonObjectDataSubRecord) obj2.getSubRecords().get(0); - - assertEquals(cmo1.getObjectId(), cmo2.getObjectId()); - assertEquals(obj1.toString(), obj2.toString()); - - // test that obj parents have the same shapeId, that is, that shape is the same - EscherContainerRecord p1 = map1.get(e1); - EscherContainerRecord p2 = map2.get(e2); - EscherSpRecord sp1 = (EscherSpRecord) p1.getChildById(EscherSpRecord.RECORD_ID); - EscherSpRecord sp2 = (EscherSpRecord) p2.getChildById(EscherSpRecord.RECORD_ID); - assertEquals(sp1.getShapeId(), sp2.getShapeId()); - - assertEquals("wrong shape2obj mapping", sp1.getShapeId() % 1024, cmo1.getObjectId()); - assertEquals(p1.toXml(), p2.toXml()); - } - } - - /** - * recursively map EscherClientDataRecords to their parent shape containers: - *

- * EscherClientDataRecord1 --> EscherContainerRecord1 - * EscherClientDataRecord2 --> EscherContainerRecord2 - * ... - *

- * TODO: YK: this method can be avoided if we have EscherRecord.getParent() - */ - private static void mapShapeContainers(EscherRecord parent, Map map) { - if (parent.isContainerRecord()) { - if (parent.getRecordId() == EscherContainerRecord.SP_CONTAINER) { - // iterate over shape's children and search for EscherClientDataRecord - for (EscherRecord r : parent.getChildRecords()) { - if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) { - map.put(r, (EscherContainerRecord) parent); - } + private static byte[] toByteArray(List records){ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for(RecordBase rb : records) { + Record r = (Record)rb; + try { + out.write(r.serialize()); + } catch (IOException e){ + throw new RuntimeException(e); + } } - } else { - for (EscherRecord ch : parent.getChildRecords()) { - mapShapeContainers(ch, map); - } - } + return out.toByteArray(); } - } /** * test reading drawing aggregate from a test file from Bugzilla 45129 @@ -170,7 +68,10 @@ public class TestDrawingAggregate extends TestCase { records.get(18) instanceof RowRecordsAggregate); // records to be aggregated - List dgRecords = records.subList(19, 388); + List dgRecords = records.subList(19, 389); + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + for (RecordBase rb : dgRecords) { Record r = (Record) rb; short sid = r.getSid(); @@ -203,11 +104,162 @@ public class TestDrawingAggregate extends TestCase { assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), records.get(20) instanceof WindowTwoRecord); - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } + /** + * Try to check file with such record sequence + * ... + * DrawingRecord + * ContinueRecord + * ObjRecord | TextObjRecord + * ... + */ + public void testSerializeDrawingBigger8k() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls"); + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + + List records = isheet.getRecords(); + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 32, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(19, 26); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == NoteRecord.sid || + sid == TextObjectRecord.sid); + } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + + // the first record after the drawing block + assertTrue( + "records.get(26) is expected to be Window2", + records.get(26) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 38] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 26, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + + + } + + + public void testSerializeDrawingBigger8k_noAggregation() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingContinue.xls"); + + InternalSheet isheet = HSSFTestHelper.getSheetForTest(wb.getSheetAt(0)); + List records = isheet.getRecords(); + + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb); + InternalSheet isheet2 = HSSFTestHelper.getSheetForTest( wb2.getSheetAt(0)); + List records2 = isheet2.getRecords(); + + assertEquals(records.size(), records2.size()); + for(int i = 0; i < records.size(); i++) { + RecordBase r1 = records.get(i); + RecordBase r2 = records2.get(i); + assertTrue(r1.getClass() == r2.getClass()); + assertEquals(r1.getRecordSize(), r2.getRecordSize()); + if(r1 instanceof Record ){ + assertEquals(((Record)r1).getSid(), ((Record)r2).getSid()); + assertTrue(Arrays.equals(((Record) r1).serialize(), ((Record) r2).serialize())); + } + } + + } + + public void testSerializeDrawingWithComments() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("DrawingAndComments.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalWorkbook iworkbook = HSSFTestHelper.getWorkbookForTest(wb); + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sh); + + List records = isheet.getRecords(); + + // the sheet's drawing is not aggregated + assertEquals("wrong size of sheet records stream", 46, records.size()); + // the last record before the drawing block + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + + // records to be aggregated + List dgRecords = records.subList(19, 39); + for (RecordBase rb : dgRecords) { + Record r = (Record) rb; + short sid = r.getSid(); + // we expect that drawing block consists of either + // DrawingRecord or ContinueRecord or ObjRecord or TextObjectRecord + assertTrue( + sid == DrawingRecord.sid || + sid == ContinueRecord.sid || + sid == ObjRecord.sid || + sid == NoteRecord.sid || + sid == TextObjectRecord.sid); + } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); + + // the first record after the drawing block + assertTrue( + "records.get(39) is expected to be Window2", + records.get(39) instanceof WindowTwoRecord); + + // aggregate drawing records. + // The subrange [19, 38] is expected to be replaced with a EscherAggregate object + DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); + int loc = isheet.aggregateDrawingRecords(drawingManager, false); + EscherAggregate agg = (EscherAggregate) records.get(loc); + + assertEquals("wrong size of the aggregated sheet records stream", 27, records.size()); + assertTrue( + "records.get(18) is expected to be RowRecordsAggregate but was " + records.get(18).getClass().getSimpleName(), + records.get(18) instanceof RowRecordsAggregate); + assertTrue("records.get(19) is expected to be EscherAggregate but was " + records.get(19).getClass().getSimpleName(), + records.get(19) instanceof EscherAggregate); + assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(), + records.get(20) instanceof WindowTwoRecord); + + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + } + + public void testFileWithPictures() { HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ContinueRecordProblem.xls"); HSSFSheet sh = wb.getSheetAt(0); @@ -225,7 +277,7 @@ public class TestDrawingAggregate extends TestCase { records.get(21) instanceof RowRecordsAggregate); // records to be aggregated - List dgRecords = records.subList(22, 299); + List dgRecords = records.subList(22, 300); for (RecordBase rb : dgRecords) { Record r = (Record) rb; short sid = r.getSid(); @@ -237,6 +289,8 @@ public class TestDrawingAggregate extends TestCase { sid == ObjRecord.sid || sid == TextObjectRecord.sid); } + // collect drawing records into a byte buffer. + byte[] dgBytes = toByteArray(dgRecords); // the first record after the drawing block assertTrue( @@ -244,7 +298,7 @@ public class TestDrawingAggregate extends TestCase { records.get(300) instanceof WindowTwoRecord); // aggregate drawing records. - // The subrange [19, 388] is expected to be replaced with a EscherAggregate object + // The subrange [19, 299] is expected to be replaced with a EscherAggregate object DrawingManager2 drawingManager = iworkbook.findDrawingGroup(); int loc = isheet.aggregateDrawingRecords(drawingManager, false); EscherAggregate agg = (EscherAggregate) records.get(loc); @@ -258,9 +312,9 @@ public class TestDrawingAggregate extends TestCase { assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(), records.get(23) instanceof WindowTwoRecord); - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } public void testUnhandledContinue() { @@ -972,10 +1026,9 @@ public class TestDrawingAggregate extends TestCase { assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord); EscherAggregate agg = (EscherAggregate) records.get(0); - // serialize, read back and assert that the drawing data is preserved - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } public void testUnhandledContinue2() { @@ -1926,8 +1979,8 @@ public class TestDrawingAggregate extends TestCase { EscherAggregate agg = (EscherAggregate) records.get(0); - EscherAggregate agg2 = assertWriteAndReadBack(agg); - - assertObjectMappingSame(agg, agg2); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } } diff --git a/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java b/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java deleted file mode 100644 index 4eed03d5e5..0000000000 --- a/src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.hssf.record; - -import org.apache.poi.ddf.EscherRecord; - -import java.util.Map; - -/** - * @author Evgeniy Berlog - * date: 30.05.12 - */ -public class HSSFRecordTestHelper { - - public static Map getShapeToObjForTest(EscherAggregate agg){ - return agg.shapeToObj; - } - -} diff --git a/src/testcases/org/apache/poi/hssf/record/TestDrawingRecord.java b/src/testcases/org/apache/poi/hssf/record/TestDrawingRecord.java index f207a0046d..38992c0bdf 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestDrawingRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestDrawingRecord.java @@ -49,17 +49,12 @@ public final class TestDrawingRecord extends TestCase { out.write(cn.serialize()); List rec = RecordFactory.createRecords(new ByteArrayInputStream(out.toByteArray())); - assertEquals(1, rec.size()); + assertEquals(2, rec.size()); assertTrue(rec.get(0) instanceof DrawingRecord); + assertTrue(rec.get(1) instanceof ContinueRecord); - //DrawingRecord.getData() should return concatenated data1 and data2 - byte[] tmp = new byte[data1.length + data2.length]; - System.arraycopy(data1, 0, tmp, 0, data1.length); - System.arraycopy(data2, 0, tmp, data1.length, data2.length); - - DrawingRecord dg2 = (DrawingRecord)rec.get(0); - assertEquals(data1.length + data2.length, dg2.getData().length); - assertTrue(Arrays.equals(tmp, dg2.getData())); + assertTrue(Arrays.equals(data1, ((DrawingRecord)rec.get(0)).getData())); + assertTrue(Arrays.equals(data2, ((ContinueRecord)rec.get(1)).getData())); } diff --git a/test-data/spreadsheet/DrawingAndComments.xls b/test-data/spreadsheet/DrawingAndComments.xls new file mode 100755 index 0000000000000000000000000000000000000000..8be6c9e5269041068944e7938873b19c0198d2ac GIT binary patch literal 43520 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


4O4MRZC0ezb-GXSn)S1g`$12{+2x! z+oIKWZeoh_H5?MH|FGEpA#=70f64F(6BFYBhboV-5)uDT?BdsT1G^VUiw;Q^8NJ!|{_Tocy2r_m1NP44+^!3PB$YEY+?xC^u`g>4 zo}StrH(mX>O?0-^`Tb98J_fmHb9gibSf$=o+%w$Kqfl`5vYwCQ!K-Y69NYBj>R7i6 zsTl40=69huXiv|PB$>pe?c9Mi^Bk6)TsGx;qV#)<y3Mg!ML zuW+$_4;MDQyzxl8c?0(bt%57l!Y?1VCc4pUPG`l`RKx9L@{*z_%=wl5`)RiYIb`p& z<=GHfy^Ui^mkp=V^t)3<0;aBzoNE4K016vw4Ieetv$kt-@mFDQd3e@d-%Mxaq2& zM=Kv8D(~T3EO+nnduySUN`*0(w#dxZ>eKW3{PxGo_-g6rJr8yJS&Z_!lLK}|ElZX3 zx}LsGwdR!6(t`|{>z!M}Ij`M6<+O6~0soeUH>C@voSts2xaYGHY4CiKM{7{25{-U! zzrfP)a>)zg<&kyszpo3iKMgmo?2@(O_spsZz7tlbc(OY?(=9YA{MM&TJ0X?#>a{!0 zZBOj=H2g92ZMor(+P==B?+r&QrY7V(jW!Y0^AhK%?9xY1ASKk(a`cOe>Z2sSB$jk# zW*+)7t3}+ttMW-)Vpo4rf7g>P^w2kP%L4X0Ltj?(f7}tIOHgio_CEjhMne%5 z5@zBKT}>-rUOV-uX0Ld4W?}r`s)648h96Pd$3h2&^}8f$6*9kcRrh?YFMn3iFj!Jv znRBpqOT&Oh_0tTEEvFrpbDS+TZu=X=~G;@`lzh7!O@MDy@NVk=R6{{Z#J}~R_G@A-x6|p zcyWrgo!gOi|6}u0>QqwrTaEH;4lHXcewlS-W0zfS`-KP|<+kUu;+nnJ@v>ePjAE$L zZ>!tKH#MZeHT%s}pVJyYdd0ThY%|>+`YEbz5$mz9Mm>=kIj!!EtRA8Qb#$>6!L9l> z`(3R$dMs3?oqwb5a{Ry%|GQ?E-gmVbk2{HyR@D7aNVk11Nn>=^ZDI2@woBJOnmtO~ zbhl)Flu>W_iVilNA0=CP5{>1{eo1oldyZq@mPcSCj{nXVCC6^W_)S&`HTyrkC^=RK zewThF^^Y$~YRgc-f4?ZnNlS}<6N3R3(elDal*#q;V;z(iC7IC21-KUdCPBFqMV}YI zpF+VeSfZ~G{QO!1`t@BN^j;;_T$-`T_;V=uRm2g{rZn7eksc#7$0v07g#he8Uv%5S zNQqO zVN=ZipT7c!zr%xU0TLemBO}?8hADji{tl0q`hWI2JQPg$Otc3PH7CxL)1U1@gML7n z@(mmWfpq{M|E2B0z3G2@d!Wz9{wKeSL=h)G|If6?Z+d_4{wE|bg!(Q$pTr0%3g?fxi;?D}lcf_$z_G68I~D zzY_Q>fxi;?D}lcf_$h(O=KnMgY9FMli*W8qL-T*tfm3+?--rVK3O!yQa6|#G`n#im zK2nRm%}x1oX%M>Nxq1W&c-|k40{(W&W)$#xz)lqK`oIMgMy?0owFG=n=I)dQRvgD) zL&e9~t2iQpVextd<;P5Z-)jH9odT=~5EH_S2zZ^g`qjtY??lnR%LGUqe~-Ts_$z_G z68I~DzY_Q>fxi;?D}lcf_$z_G68I~D|N9ca^LRWp#uH&Y|Hj**@Dv%(sqyo7Jl98` znyx5 zULDFb9DVl(BvFt;K^g@a6l775LqQ$|1r!ufP(nc&1r-!jQBXrc9R&>(G*Qq(0e_=v z3JU0>tms#m0sS5&Wh<5ex*DQ@epD0vST3NSs|A>f0{-nAGZf5Gn1;d-+MhKYU1y+R ziNZ`2W}z?}1uGPAz74wCqF{%DJqiveIHKT$0?z+|0>1ulJDkxkdE%dql|(hizug&z zeqQ!Ja_|EkvA+%18|#rIBR&IMBhG{;6w1>N3_6yj30ylME$KX;h*&XKTAFa0ssI2 literal 0 HcmV?d00001 diff --git a/test-data/spreadsheet/DrawingContinue.xls b/test-data/spreadsheet/DrawingContinue.xls new file mode 100755 index 0000000000000000000000000000000000000000..131c18cc9b09c2d6286e9a2da104bd0d504bfb51 GIT binary patch literal 68608 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ⅆaQ$vI-l_@<|2XHEW2bq`@%G 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

-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 z Date: Fri, 8 Jun 2012 17:47:37 +0000 Subject: [PATCH 05/32] initial support for reading shapes, see patch from June 8 in Bugzilla 53372 git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1348168 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/record/EscherAggregate.java | 50 ++++-- .../poi/hssf/usermodel/HSSFChildAnchor.java | 9 + .../poi/hssf/usermodel/HSSFClientAnchor.java | 8 + .../poi/hssf/usermodel/HSSFPatriarch.java | 21 +++ .../poi/hssf/usermodel/HSSFRectangle.java | 15 ++ .../apache/poi/hssf/usermodel/HSSFShape.java | 22 ++- .../hssf/usermodel/HSSFShapeContainer.java | 11 ++ .../poi/hssf/usermodel/HSSFShapeFactory.java | 157 ++++++++++++++++++ .../poi/hssf/usermodel/HSSFShapeGroup.java | 40 +++++ .../apache/poi/hssf/usermodel/HSSFSheet.java | 8 +- .../poi/hssf/usermodel/HSSFUnknownShape.java | 33 ++++ .../hssf/usermodel/drawing/HSSFShapeType.java | 29 ++++ .../poi/hssf/model/TestDrawingAggregate.java | 110 +++++++++--- .../poi/hssf/usermodel/HSSFTestHelper.java | 5 + .../spreadsheet/SolverContainerAfterSPGR.xls | Bin 0 -> 26112 bytes 15 files changed, 476 insertions(+), 42 deletions(-) create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java create mode 100644 src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java create mode 100755 test-data/spreadsheet/SolverContainerAfterSPGR.xls diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 3bb7127356..1d48ff751f 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -43,16 +43,7 @@ import org.apache.poi.hssf.model.CommentShape; import org.apache.poi.hssf.model.ConvertAnchor; import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.model.TextboxShape; -import org.apache.poi.hssf.usermodel.HSSFAnchor; -import org.apache.poi.hssf.usermodel.HSSFChildAnchor; -import org.apache.poi.hssf.usermodel.HSSFClientAnchor; -import org.apache.poi.hssf.usermodel.HSSFPatriarch; -import org.apache.poi.hssf.usermodel.HSSFPicture; -import org.apache.poi.hssf.usermodel.HSSFShape; -import org.apache.poi.hssf.usermodel.HSSFShapeContainer; -import org.apache.poi.hssf.usermodel.HSSFShapeGroup; -import org.apache.poi.hssf.usermodel.HSSFSimpleShape; -import org.apache.poi.hssf.usermodel.HSSFTextbox; +import org.apache.poi.hssf.usermodel.*; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -322,7 +313,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { /** * list of "tail" records that need to be serialized after all drawing group records */ - private List tailRec = new ArrayList(); + private List tailRec = new ArrayList(); public EscherAggregate(DrawingManager2 drawingManager) { this.drawingManager = drawingManager; @@ -413,7 +404,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } // Decode the shapes - // agg.escherRecords = new ArrayList(); + // agg.escherRecords = new ArrayList(); int pos = 0; while (pos < buffer.size()) { EscherRecord r = recordFactory.createRecord(buffer.toByteArray(), pos); @@ -486,7 +477,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) { if (recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID) { - spEndingOffsets.add(Integer.valueOf(offset)); + spEndingOffsets.add(offset); shapes.add(record); } } @@ -501,12 +492,17 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { pos = offset; int writtenEscherBytes = 0; for (int i = 1; i < shapes.size(); i++) { - int endOffset = ((Integer) spEndingOffsets.get(i)).intValue() - 1; + int endOffset; + if (i == shapes.size()-1){ + endOffset = buffer.length - 1; + } else { + endOffset = (Integer) spEndingOffsets.get(i) - 1; + } int startOffset; if (i == 1) startOffset = 0; else - startOffset = ((Integer) spEndingOffsets.get(i - 1)).intValue(); + startOffset = (Integer) spEndingOffsets.get(i - 1); byte[] drawingData = new byte[endOffset - startOffset + 1]; @@ -790,7 +786,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { container.getChildren().add(shape); } - private static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) { + public static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) { HSSFClientAnchor anchor = new HSSFClientAnchor(); anchor.setAnchorType(anchorRecord.getFlag()); anchor.setCol1(anchorRecord.getCol1()); @@ -804,7 +800,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return anchor; } - private static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) { + public static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) { HSSFChildAnchor anchor = new HSSFChildAnchor(); // anchor.setAnchorType(anchorRecord.getFlag()); // anchor.setCol1( anchorRecord.getCol1() ); @@ -1081,4 +1077,24 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return null; } + /** + * Returns the mapping of {@link EscherClientDataRecord} and {@link EscherTextboxRecord} + * to their {@link TextObjectRecord} or {@link ObjRecord} . + * + * We need to access it outside of EscherAggregate when building shapes + * + * @return + */ + public Map getShapeToObjMapping(){ + return Collections.unmodifiableMap(shapeToObj); + } + + /** + * + * @return tails records. We need to access them when building shapes. + * Every HSSFComment shape has a link to a NoteRecord from the tailRec collection. + */ + public List getTailRecords(){ + return Collections.unmodifiableList(tailRec); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java index 513ac619f4..ccd0e620cf 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java @@ -18,7 +18,16 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherChildAnchorRecord; + public final class HSSFChildAnchor extends HSSFAnchor { + + private EscherChildAnchorRecord escherChildAnchorRecord; + + public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) { + this.escherChildAnchorRecord = escherChildAnchorRecord; + } + public HSSFChildAnchor() { } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java index cffb00cd55..a040144c27 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java @@ -17,6 +17,7 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherClientAnchorRecord; import org.apache.poi.ss.usermodel.ClientAnchor; @@ -33,6 +34,13 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { int row2; int anchorType; + private EscherClientAnchorRecord escherClientAnchorRecord; + + public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) { + this.escherClientAnchorRecord = escherClientAnchorRecord; + //TODO set properties or read properties from EscherRecord ? + } + /** * Creates a new client anchor and defaults all the anchor positions to 0. */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 672f82cc73..71549bbf31 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -22,9 +22,11 @@ import java.util.Iterator; import java.util.List; import org.apache.poi.ddf.EscherComplexProperty; +import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherProperty; import org.apache.poi.ddf.EscherBSERecord; +import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.ss.usermodel.Chart; import org.apache.poi.util.StringUtil; @@ -314,4 +316,23 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { throw new RuntimeException("NotImplemented"); } + + void buildShapeTree(){ + EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer(); + EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0); + List spgrChildren = spgrConrainer.getChildContainers(); + + for(int i = 0; i < spgrChildren.size(); i++){ + EscherContainerRecord spContainer = spgrChildren.get(i); + if (i == 0){ + EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); + setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + } else { + HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this); + } + } + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java new file mode 100644 index 0000000000..0a0468c144 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java @@ -0,0 +1,15 @@ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.record.ObjRecord; + +/** + * @author Evgeniy Berlog + * @date 08.06.12 + */ +public class HSSFRectangle extends HSSFShape{ + + public HSSFRectangle(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 3c586340fe..7ffdfdb9ba 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -17,6 +17,9 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.record.ObjRecord; + /** * An abstract shape. * @@ -40,7 +43,7 @@ public abstract class HSSFShape { public static final int LINESTYLE_NONE = -1; // TODO - make all these fields private - final HSSFShape parent; + HSSFShape parent; HSSFAnchor anchor; HSSFPatriarch _patriarch; private int _lineStyleColor = 0x08000040; @@ -49,15 +52,30 @@ public abstract class HSSFShape { private int _lineStyle = LINESTYLE_SOLID; private boolean _noFill = false; + private EscherContainerRecord spContainer; + private ObjRecord objRecord; + + public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord){ + this.spContainer = spContainer; + this.objRecord = objRecord; + } /** * Create a new shape with the specified parent and anchor. */ - HSSFShape( HSSFShape parent, HSSFAnchor anchor ) + public HSSFShape( HSSFShape parent, HSSFAnchor anchor ) { this.parent = parent; this.anchor = anchor; } + public EscherContainerRecord getSpContainer() { + return spContainer; + } + + public ObjRecord getObjRecord() { + return objRecord; + } + /** * Gets the parent shape. */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java index 99e6a5de6a..181b3d17a9 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java @@ -31,4 +31,15 @@ public interface HSSFShapeContainer */ List getChildren(); + /** + * add shape to the list of child records + * @param shape + */ + public void addShape(HSSFShape shape); + + /** + * set coordinates of this group relative to the parent + */ + void setCoordinates( int x1, int y1, int x2, int y2 ); + } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java new file mode 100644 index 0000000000..fc88a2a16d --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -0,0 +1,157 @@ +/* + * 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.hssf.usermodel; + +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.ddf.EscherSpgrRecord; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hssf.model.TextboxShape; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.NoteRecord; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author evgeniy + * date: 05.06.12 + */ +public class HSSFShapeFactory { + + private static final Map shapeTypeToClass = new HashMap(HSSFShapeType.values().length); + private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass); + + static { + for (HSSFShapeType type: HSSFShapeType.values()){ + shapeTypeToClass.put(type.getType(), type.getShape()); + } + } + + private static class ReflectionConstructorShapeCreator { + + private final Map shapeTypeToClass; + + private ReflectionConstructorShapeCreator(Map shapeTypeToClass) { + this.shapeTypeToClass = shapeTypeToClass; + } + + public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord){ + if (!shapeTypeToClass.containsKey(type)){ + return new HSSFUnknownShape(spContainer, objRecord); + } + Class clazz = shapeTypeToClass.get(type); + if (null == clazz){ + System.out.println("No class attached to shape type: "+type); + return new HSSFUnknownShape(spContainer, objRecord); + } + try{ + Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class}); + return (HSSFShape) constructor.newInstance(spContainer, objRecord); + } catch (NoSuchMethodException e) { + throw new IllegalStateException(clazz.getName() +" doesn't have required for shapes constructor"); + } catch (Exception e) { + throw new IllegalStateException("Couldn't create new instance of " + clazz.getName()); + } + } + } + + public static HSSFShape createShape(EscherRecord container, ObjRecord objRecord){ + if (0 == container.getChildRecords().size()){ + throw new IllegalArgumentException("Couldn't create shape from empty escher container"); + } + if (container.getChild(0) instanceof EscherSpgrRecord){ + return new HSSFShapeGroup((EscherContainerRecord) container, objRecord); + } + + //TODO implement cases for all shapes + return new HSSFUnknownShape(container, objRecord); + } + + public static HSSFShapeGroup createShapeGroup(){ + return null; + } + + public static HSSFShapeGroup createSimpleShape(EscherRecord container, ObjRecord objRecord){ + return null; + } + + public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){ + if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ + HSSFShapeGroup group = new HSSFShapeGroup(container, + null /* shape containers don't have a associated Obj record*/); + List children = container.getChildContainers(); + // skip the first child record, it is group descriptor + for(int i = 0; i < children.size(); i++) { + EscherContainerRecord spContainer = children.get(i); + if(i == 0){ + EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); + group.setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + } else { + createShapeTree(spContainer, agg, group); + } + } + out.addShape(group); + } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER){ + Map shapeToObj = agg.getShapeToObjMapping(); + EscherSpRecord spRecord = null; + ObjRecord objRecord = null; + TextObjectRecord txtRecord = null; + + for(EscherRecord record : container.getChildRecords()) { + switch(record.getRecordId()) { + case EscherSpRecord.RECORD_ID: + spRecord = (EscherSpRecord)record; + break; + case EscherClientDataRecord.RECORD_ID: + objRecord = (ObjRecord)shapeToObj.get(record); + break; + case EscherTextboxRecord.RECORD_ID: + txtRecord = (TextObjectRecord)shapeToObj.get(record); + break; + } + } + if (null != objRecord){ + HSSFShape shape = shapeCreator.createNewShape(spRecord.getShapeType(), container, objRecord); + out.addShape(shape); + } + if (null != txtRecord){ + //TODO resolve textbox +// TextboxShape shape = new TextboxShape(container, txtRecord); +// out.a + } +// +// //TODO decide what shape to create based on ObjRecord / EscherSpRecord +// HSSFShape shape = new HSSFUnknownShape(container, objRecord); +// out.addShape(shape); + } + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 905dad3fc2..7cab3e493d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -17,6 +17,15 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherSpgrRecord; +import org.apache.poi.hssf.model.TextboxShape; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.ObjRecord; + import java.util.ArrayList; import java.util.List; import java.util.Iterator; @@ -37,6 +46,32 @@ public class HSSFShapeGroup int x2 = 1023; int y2 = 255; + public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) { + super(spgrContainer, objRecord); + + // read internal and external coordinates from spgrContainer + EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0); + for(EscherRecord ch : spContainer.getChildRecords()){ + switch(ch.getRecordId()) { + case EscherSpgrRecord.RECORD_ID: + EscherSpgrRecord spgr = (EscherSpgrRecord)ch; + setCoordinates( + spgr.getRectX1(), spgr.getRectY1(), + spgr.getRectX2(), spgr.getRectY2() + ); + break; + case EscherClientAnchorRecord.RECORD_ID: + this.anchor = EscherAggregate.toClientAnchor((EscherClientAnchorRecord)ch); + // TODO anchor = new HSSFClientAnchor((EscherChildAnchorRecord)ch); + break; + case EscherChildAnchorRecord.RECORD_ID: + this.anchor = EscherAggregate.toChildAnchor((EscherChildAnchorRecord)ch); + // TODO anchor = new HSSFChildAnchor((EscherClientAnchorRecord)ch); + break; + } + } + + } public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor ) { @@ -61,6 +96,11 @@ public class HSSFShapeGroup shapes.add(shape); } + public void addTextBox(TextboxShape textboxShape){ +// HSSFTextbox shape = new HSSFTextbox(this, textboxShape.geanchor); +// shapes.add(textboxShape); + } + /** * Create a new simple shape under this group. * @param anchor the position of the shape. diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index fe332eb83e..da7a404b28 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -1738,12 +1738,16 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { if(agg == null) return null; _patriarch = new HSSFPatriarch(this, agg); - agg.setPatriarch(_patriarch); + _patriarch.buildShapeTree(); + + //HSSFShapeFactory.createShapeTree(); + //agg.setPatriarch(_patriarch); + //EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg); // Have it process the records into high level objects // as best it can do (this step may eat anything // that isn't supported, you were warned...) - agg.convertRecordsToUserModel(); +// agg.convertRecordsToUserModel(); // Return what we could cope with return _patriarch; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java new file mode 100644 index 0000000000..d4cac9be9a --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java @@ -0,0 +1,33 @@ +/* + * 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.hssf.usermodel; + +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.hssf.record.ObjRecord; + +/** + * @author Evgeniy Berlog + * date: 05.06.12 + */ +public class HSSFUnknownShape extends HSSFShape { + + public HSSFUnknownShape(EscherRecord spContainer, ObjRecord objRecord) { + super((EscherContainerRecord) spContainer, objRecord); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java new file mode 100644 index 0000000000..2818687921 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -0,0 +1,29 @@ +package org.apache.poi.hssf.usermodel.drawing; + +import org.apache.poi.hssf.usermodel.HSSFRectangle; + +/** + * @author Evgeniy Berlog + * date: 08.06.12 + */ +public enum HSSFShapeType { + NOT_PRIMITIVE(0x0, null), + RECTANGLE(0x1, HSSFRectangle.class), + ROUND_RECTANGLE(0x2, null); + + private Short type; + private Class shape; + + HSSFShapeType(Integer type, Class shape) { + this.type = type.shortValue(); + this.shape = shape; + } + + public Short getType() { + return type; + } + + public Class getShape() { + return shape; + } +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index a22ce4a0cc..0608c0eb18 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -17,13 +17,13 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; +import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherDggRecord; +import org.apache.poi.ddf.EscherRecord; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFTestHelper; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hssf.usermodel.*; import org.apache.poi.util.HexRead; import java.io.*; @@ -35,18 +35,84 @@ import java.util.List; * @author Evgeniy Berlog */ public class TestDrawingAggregate extends TestCase { - private static byte[] toByteArray(List records){ - ByteArrayOutputStream out = new ByteArrayOutputStream(); - for(RecordBase rb : records) { - Record r = (Record)rb; - try { - out.write(r.serialize()); - } catch (IOException e){ - throw new RuntimeException(e); - } - } - return out.toByteArray(); + + private int spgrCount = 0; + private int spCount = 0; + private int shapeCount = 0; + private int shGroupCount = 0; + + /* + * EscherAggregate must have for each SpgrContainer HSSFShapeGroup and for each SpContainer HSSFShape + */ + private void checkEscherAndShapesCount(EscherAggregate agg, HSSFSheet sheet) { + /* + HSSFPatriarch patriarch = HSSFTestHelper.createTestPatriarch(sheet, agg); + agg.setPatriarch(patriarch); + EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg); + EscherContainerRecord mainContainer = EscherAggregate.getMainSpgrContainer(agg); + calculateShapesCount(agg.getPatriarch()); + calculateEscherContainersCount(mainContainer); + + assertEquals(spgrCount, shGroupCount); + assertEquals(spCount - spgrCount - 1, shapeCount); + */ + } + + private void calculateEscherContainersCount(EscherContainerRecord spgr) { + for (EscherRecord record : spgr.getChildRecords()) { + if (EscherContainerRecord.SP_CONTAINER == record.getRecordId()) { + spCount++; + continue; + } + if (EscherContainerRecord.SPGR_CONTAINER == record.getRecordId()) { + spgrCount++; + calculateEscherContainersCount((EscherContainerRecord) record); + } } + } + + private void calculateShapesCount(HSSFShapeContainer group) { + for (HSSFShape shape : (List) group.getChildren()) { + if (shape instanceof HSSFShapeGroup) { + shGroupCount++; + calculateShapesCount((HSSFShapeGroup) shape); + } else { + shapeCount++; + } + } + } + + + private static byte[] toByteArray(List records) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (RecordBase rb : records) { + Record r = (Record) rb; + try { + out.write(r.serialize()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return out.toByteArray(); + } + + public void testSolverContainerMustBeSavedDuringSerialization(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SolverContainerAfterSPGR.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + sh.getDrawingPatriarch(); + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); + assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER); + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + sh.getDrawingPatriarch(); + ish = HSSFTestHelper.getSheetForTest(sh); + agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); + assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER); + + } /** * test reading drawing aggregate from a test file from Bugzilla 45129 @@ -107,6 +173,7 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize(); assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + checkEscherAndShapesCount(agg, sh); } /** @@ -174,7 +241,7 @@ public class TestDrawingAggregate extends TestCase { assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - + checkEscherAndShapesCount(agg, sh); } @@ -185,21 +252,20 @@ public class TestDrawingAggregate extends TestCase { List records = isheet.getRecords(); HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb); - InternalSheet isheet2 = HSSFTestHelper.getSheetForTest( wb2.getSheetAt(0)); + InternalSheet isheet2 = HSSFTestHelper.getSheetForTest(wb2.getSheetAt(0)); List records2 = isheet2.getRecords(); assertEquals(records.size(), records2.size()); - for(int i = 0; i < records.size(); i++) { + for (int i = 0; i < records.size(); i++) { RecordBase r1 = records.get(i); RecordBase r2 = records2.get(i); assertTrue(r1.getClass() == r2.getClass()); assertEquals(r1.getRecordSize(), r2.getRecordSize()); - if(r1 instanceof Record ){ - assertEquals(((Record)r1).getSid(), ((Record)r2).getSid()); + if (r1 instanceof Record) { + assertEquals(((Record) r1).getSid(), ((Record) r2).getSid()); assertTrue(Arrays.equals(((Record) r1).serialize(), ((Record) r2).serialize())); } } - } public void testSerializeDrawingWithComments() throws IOException { @@ -257,6 +323,7 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize(); assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + checkEscherAndShapesCount(agg, sh); } @@ -314,7 +381,8 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize(); assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + checkEscherAndShapesCount(agg, sh); } public void testUnhandledContinue() { diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 7c5a88bd45..0b79eae50e 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; +import org.apache.poi.hssf.record.EscherAggregate; /** * Helper class for HSSF tests that aren't within the @@ -34,4 +35,8 @@ public class HSSFTestHelper { public static InternalSheet getSheetForTest(HSSFSheet sheet) { return sheet.getSheet(); } + + public static HSSFPatriarch createTestPatriarch(HSSFSheet sheet, EscherAggregate agg){ + return new HSSFPatriarch(sheet, agg); + } } diff --git a/test-data/spreadsheet/SolverContainerAfterSPGR.xls b/test-data/spreadsheet/SolverContainerAfterSPGR.xls new file mode 100755 index 0000000000000000000000000000000000000000..57a1b17048f306fd02d23f60ce5599783310400a GIT binary patch literal 26112 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 Date: Tue, 12 Jun 2012 11:07:20 +0000 Subject: [PATCH 06/32] added file for tests(check commit rights) git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1349253 13f79535-47bb-0310-9956-ffa450edef68 --- test-data/spreadsheet/text.xls | Bin 0 -> 21504 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test-data/spreadsheet/text.xls diff --git a/test-data/spreadsheet/text.xls b/test-data/spreadsheet/text.xls new file mode 100644 index 0000000000000000000000000000000000000000..18df2914a0246df2a5051524af47090505129744 GIT binary patch literal 21504 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 literal 0 HcmV?d00001 From 39c271cde0d37d7805fbbbe8489cf8e690b1e0ac Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Thu, 14 Jun 2012 15:36:34 +0000 Subject: [PATCH 07/32] fixed EscherAggregate to correctly write records with trailing solver container git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1350298 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/poi/ddf/EscherRecord.java | 2 +- .../apache/poi/hssf/record/DrawingRecord.java | 5 + .../poi/hssf/record/EscherAggregate.java | 82 +++--- .../poi/hssf/usermodel/HSSFShapeFactory.java | 2 +- .../poi/hssf/model/TestDrawingAggregate.java | 237 ++++++++++++++---- .../poi/hssf/usermodel/HSSFTestHelper.java | 4 + 6 files changed, 246 insertions(+), 86 deletions(-) diff --git a/src/java/org/apache/poi/ddf/EscherRecord.java b/src/java/org/apache/poi/ddf/EscherRecord.java index cad6be171d..382333ba32 100644 --- a/src/java/org/apache/poi/ddf/EscherRecord.java +++ b/src/java/org/apache/poi/ddf/EscherRecord.java @@ -311,7 +311,7 @@ public abstract class EscherRecord { protected String formatXmlRecordHeader(String className, String recordId, String version, String instance){ StringBuilder builder = new StringBuilder(); builder.append("<").append(className).append(" recordId=\"0x").append(recordId).append("\" version=\"0x") - .append(version).append("\" instance=\"0x").append(instance).append("\">\n"); + .append(version).append("\" instance=\"0x").append(instance).append("\" size=\"").append(getRecordSize()).append("\">\n"); return builder.toString(); } diff --git a/src/java/org/apache/poi/hssf/record/DrawingRecord.java b/src/java/org/apache/poi/hssf/record/DrawingRecord.java index 9e104de59e..89a8072784 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingRecord.java @@ -85,4 +85,9 @@ public final class DrawingRecord extends StandardRecord { return rec; } + + @Override + public String toString() { + return "DrawingRecord["+recordData.length+"]"; + } } diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 1d48ff751f..e65fd0333d 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -82,9 +82,9 @@ import org.apache.poi.util.POILogger; * build escher(office art) records tree from this array. * Each shape in drawing layer matches corresponding ObjRecord * Each textbox matches corresponding TextObjectRecord - * + *

* ObjRecord contains information about shape. Thus each ObjRecord corresponds EscherContainerRecord(SPGR) - * + *

* EscherAggrefate contains also NoteRecords * NoteRecords must be serial * @@ -492,51 +492,28 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { pos = offset; int writtenEscherBytes = 0; for (int i = 1; i < shapes.size(); i++) { - int endOffset; - if (i == shapes.size()-1){ - endOffset = buffer.length - 1; - } else { - endOffset = (Integer) spEndingOffsets.get(i) - 1; - } + int endOffset = (Integer) spEndingOffsets.get(i) - 1; int startOffset; if (i == 1) startOffset = 0; else startOffset = (Integer) spEndingOffsets.get(i - 1); - byte[] drawingData = new byte[endOffset - startOffset + 1]; System.arraycopy(buffer, startOffset, drawingData, 0, drawingData.length); - int temp = 0; + pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); - //First record in drawing layer MUST be DrawingRecord - if (writtenEscherBytes + drawingData.length > RecordInputStream.MAX_RECORD_DATA_SIZE && i != 1) { - for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { - ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); - temp += drawing.serialize(pos + temp, data); - } - } else { - for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { - if (j == 0) { - DrawingRecord drawing = new DrawingRecord(); - drawing.setData(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); - temp += drawing.serialize(pos + temp, data); - } else { - ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); - temp += drawing.serialize(pos + temp, data); - } - } - - } - - pos += temp; writtenEscherBytes += drawingData.length; // Write the matching OBJ record Record obj = shapeToObj.get(shapes.get(i)); - temp = obj.serialize(pos, data); - pos += temp; + pos += obj.serialize(pos, data); + if (i == shapes.size() - 1 && endOffset < buffer.length - 1) { + drawingData = new byte[buffer.length - endOffset - 1]; + System.arraycopy(buffer, endOffset + 1, drawingData, 0, drawingData.length); + pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); + } } // write records that need to be serialized after all drawing group records @@ -544,13 +521,34 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { Record rec = (Record) tailRec.get(i); pos += rec.serialize(pos, data); } - int bytesWritten = pos - offset; if (bytesWritten != getRecordSize()) throw new RecordFormatException(bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize()); return bytesWritten; } + private int writeDataIntoDrawingRecord(int temp, byte[] drawingData, int writtenEscherBytes, int pos, byte[] data, int i) { + //First record in drawing layer MUST be DrawingRecord + if (writtenEscherBytes + drawingData.length > RecordInputStream.MAX_RECORD_DATA_SIZE && i != 1) { + for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { + ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + temp += drawing.serialize(pos + temp, data); + } + } else { + for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { + if (j == 0) { + DrawingRecord drawing = new DrawingRecord(); + drawing.setData(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + temp += drawing.serialize(pos + temp, data); + } else { + ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + temp += drawing.serialize(pos + temp, data); + } + } + } + return temp; + } + /** * How many bytes do the raw escher records contain. * @@ -591,10 +589,13 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { spEndingOffsets.add(0, 0); for (int i = 1; i < spEndingOffsets.size(); i++) { - if (spEndingOffsets.get(i) - spEndingOffsets.get(i - 1) <= RecordInputStream.MAX_RECORD_DATA_SIZE){ + if (i == spEndingOffsets.size() - 1 && spEndingOffsets.get(i) < pos) { + continueRecordsHeadersSize += 4; + } + if (spEndingOffsets.get(i) - spEndingOffsets.get(i - 1) <= RecordInputStream.MAX_RECORD_DATA_SIZE) { continue; } - continueRecordsHeadersSize += ((spEndingOffsets.get(i) - spEndingOffsets.get(i - 1)) / RecordInputStream.MAX_RECORD_DATA_SIZE)*4; + continueRecordsHeadersSize += ((spEndingOffsets.get(i) - spEndingOffsets.get(i - 1)) / RecordInputStream.MAX_RECORD_DATA_SIZE) * 4; } int drawingRecordSize = rawEscherSize + (shapeToObj.size()) * 4; @@ -608,13 +609,13 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { Record r = (Record) iterator.next(); tailRecordSize += r.getRecordSize(); } - return drawingRecordSize + objRecordSize + tailRecordSize +continueRecordsHeadersSize; + return drawingRecordSize + objRecordSize + tailRecordSize + continueRecordsHeadersSize; } /** * Associates an escher record to an OBJ record or a TXO record. */ - Object associateShapeToObjRecord(EscherRecord r, ObjRecord objRecord) { + public Object associateShapeToObjRecord(EscherRecord r, ObjRecord objRecord) { return shapeToObj.put(r, objRecord); } @@ -624,6 +625,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public void setPatriarch(HSSFPatriarch patriarch) { this.patriarch = patriarch; + convertPatriarch(patriarch); } /** @@ -1080,12 +1082,12 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { /** * Returns the mapping of {@link EscherClientDataRecord} and {@link EscherTextboxRecord} * to their {@link TextObjectRecord} or {@link ObjRecord} . - * + *

* We need to access it outside of EscherAggregate when building shapes * * @return */ - public Map getShapeToObjMapping(){ + public Map getShapeToObjMapping() { return Collections.unmodifiableMap(shapeToObj); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index fc88a2a16d..4a10a8d07a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -67,7 +67,7 @@ public class HSSFShapeFactory { } Class clazz = shapeTypeToClass.get(type); if (null == clazz){ - System.out.println("No class attached to shape type: "+type); + //System.out.println("No class attached to shape type: "+type); return new HSSFUnknownShape(spContainer, objRecord); } try{ diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index 0608c0eb18..baa5f66c08 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -19,16 +19,35 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherRecord; import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.record.ContinueRecord; +import org.apache.poi.hssf.record.DrawingRecord; +import org.apache.poi.hssf.record.EOFRecord; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.NoteRecord; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordBase; +import org.apache.poi.hssf.record.RecordFactory; +import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.hssf.record.WindowTwoRecord; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; -import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.hssf.usermodel.HSSFPatriarch; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFTestHelper; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.util.HexRead; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @author Yegor Kozlov @@ -36,52 +55,158 @@ import java.util.List; */ public class TestDrawingAggregate extends TestCase { - private int spgrCount = 0; - private int spCount = 0; - private int shapeCount = 0; - private int shGroupCount = 0; - /* - * EscherAggregate must have for each SpgrContainer HSSFShapeGroup and for each SpContainer HSSFShape + /** + * information about drawing aggregate in a worksheet */ - private void checkEscherAndShapesCount(EscherAggregate agg, HSSFSheet sheet) { - /* - HSSFPatriarch patriarch = HSSFTestHelper.createTestPatriarch(sheet, agg); - agg.setPatriarch(patriarch); - EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg); - EscherContainerRecord mainContainer = EscherAggregate.getMainSpgrContainer(agg); - calculateShapesCount(agg.getPatriarch()); - calculateEscherContainersCount(mainContainer); + private static class DrawingAggregateInfo { + /** + * start and end indices of the aggregate in the worksheet stream + */ + private int startRecordIndex, endRecordIndex; + /** + * the records being aggregated + */ + private List aggRecords; - assertEquals(spgrCount, shGroupCount); - assertEquals(spCount - spgrCount - 1, shapeCount); - */ + /** + * @return aggregate info or null if the sheet does not contain drawing objects + */ + static DrawingAggregateInfo get(HSSFSheet sheet){ + DrawingAggregateInfo info = null; + InternalSheet isheet = HSSFTestHelper.getSheetForTest(sheet); + List records = isheet.getRecords(); + for(int i = 0; i < records.size(); i++){ + RecordBase rb = records.get(i); + if((rb instanceof DrawingRecord) && info == null) { + info = new DrawingAggregateInfo(); + info.startRecordIndex = i; + info.endRecordIndex = i; + } else if (info != null && ( + rb instanceof DrawingRecord + || rb instanceof ObjRecord + || rb instanceof TextObjectRecord + || rb instanceof ContinueRecord + || rb instanceof NoteRecord + )){ + info.endRecordIndex = i; + } else { + if(rb instanceof EscherAggregate) + throw new IllegalStateException("Drawing data already aggregated. " + + "You should cal this method before the first invocation of HSSFSheet#getDrawingPatriarch()"); + if (info != null) break; + } + } + if(info != null){ + info.aggRecords = new ArrayList( + records.subList(info.startRecordIndex, info.endRecordIndex + 1)); + } + return info; + } + + /** + * @return the raw data being aggregated + */ + byte[] getRawBytes(){ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (RecordBase rb : aggRecords) { + Record r = (Record) rb; + try { + out.write(r.serialize()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return out.toByteArray(); + } } - private void calculateEscherContainersCount(EscherContainerRecord spgr) { - for (EscherRecord record : spgr.getChildRecords()) { - if (EscherContainerRecord.SP_CONTAINER == record.getRecordId()) { - spCount++; + /** + * iterate over all sheets, aggregate drawing records (if there are any) + * and remember information about the aggregated data. + * Then serialize the workbook, read back and assert that the aggregated data is preserved. + * + * The assertion is strict meaning that the drawing data before and after save must be equal. + */ + private static void assertWriteAndReadBack(HSSFWorkbook wb){ + // map aggregate info by sheet index + Map aggs = new HashMap(); + for(int i = 0; i < wb.getNumberOfSheets(); i++){ + HSSFSheet sheet = wb.getSheetAt(i); + DrawingAggregateInfo info = DrawingAggregateInfo.get(sheet); + if(info != null) { + aggs.put(i, info); + HSSFPatriarch p = sheet.getDrawingPatriarch(); + + // compare aggregate.serialize() with raw bytes from the record stream + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(p); + + byte[] dgBytes1 = info.getRawBytes(); + byte[] dgBytes2 = agg.serialize(); + + assertEquals("different size of raw data ande aggregate.serialize()", dgBytes1.length, dgBytes2.length); + assertTrue("raw drawing data ("+dgBytes1.length+" bytes) and aggregate.serialize() are different.", + Arrays.equals(dgBytes1, dgBytes2)); + } + } + + if(aggs.size() != 0){ + HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb); + for(int i = 0; i < wb2.getNumberOfSheets(); i++){ + DrawingAggregateInfo info1 = aggs.get(i); + if(info1 != null) { + HSSFSheet sheet2 = wb2.getSheetAt(i); + DrawingAggregateInfo info2 = DrawingAggregateInfo.get(sheet2); + byte[] dgBytes1 = info1.getRawBytes(); + byte[] dgBytes2 = info2.getRawBytes(); + assertEquals("different size of drawing data before and after save", dgBytes1.length, dgBytes2.length); + assertTrue("drawing data ("+dgBytes1.length+" bytes) before and after save is different.", + Arrays.equals(dgBytes1, dgBytes2)); + } + } + } + } + + /** + * test that we correctly read and write drawing aggregates + * in all .xls files in POI test samples + */ + public void testAllTestSamples(){ + File[] xls = new File(System.getProperty("POI.testdata.path"), "spreadsheet").listFiles( + new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".xls"); + } + } + ); + for(File file : xls) { + HSSFWorkbook wb; + try { + wb = HSSFTestDataSamples.openSampleWorkbook(file.getName()); + } catch (Throwable e){ + // don't bother about files we cannot read - they are different bugs + // System.out.println("[WARN] Cannot read " + file.getName()); continue; } - if (EscherContainerRecord.SPGR_CONTAINER == record.getRecordId()) { - spgrCount++; - calculateEscherContainersCount((EscherContainerRecord) record); + try { + assertWriteAndReadBack(wb); + } catch (Throwable e){ + //e.printStackTrace(); + System.err.println("[ERROR] assertion failed for " + file.getName() + ": " + e.getMessage()); } } } - private void calculateShapesCount(HSSFShapeContainer group) { - for (HSSFShape shape : (List) group.getChildren()) { - if (shape instanceof HSSFShapeGroup) { - shGroupCount++; - calculateShapesCount((HSSFShapeGroup) shape); - } else { - shapeCount++; - } - } - } + /** + * TODO: figure out why it fails with "RecordFormatException: 0 bytes written but getRecordSize() reports 80" + */ + public void testFailing(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("15573.xls"); + HSSFSheet sh = wb.getSheetAt(0); + sh.getDrawingPatriarch(); + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + } private static byte[] toByteArray(List records) { ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -96,10 +221,14 @@ public class TestDrawingAggregate extends TestCase { return out.toByteArray(); } - public void testSolverContainerMustBeSavedDuringSerialization(){ + public void testSolverContainerMustBeSavedDuringSerialization() throws IOException{ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SolverContainerAfterSPGR.xls"); HSSFSheet sh = wb.getSheetAt(0); InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 22); + byte[] dgBytes = toByteArray(dgRecords); sh.getDrawingPatriarch(); EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); @@ -112,6 +241,29 @@ public class TestDrawingAggregate extends TestCase { assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3); assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER); + + // collect drawing records into a byte buffer. + agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + } + + public void testFileWithTextbox() throws IOException{ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("text.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 23); + byte[] dgBytes = toByteArray(dgRecords); + sh.getDrawingPatriarch(); + + // collect drawing records into a byte buffer. + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } /** @@ -172,8 +324,7 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize(); assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); - assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - checkEscherAndShapesCount(agg, sh); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } /** @@ -241,7 +392,6 @@ public class TestDrawingAggregate extends TestCase { assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - checkEscherAndShapesCount(agg, sh); } @@ -323,7 +473,6 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize(); assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - checkEscherAndShapesCount(agg, sh); } @@ -382,7 +531,6 @@ public class TestDrawingAggregate extends TestCase { byte[] dgBytesAfterSave = agg.serialize(); assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); - checkEscherAndShapesCount(agg, sh); } public void testUnhandledContinue() { @@ -2051,4 +2199,5 @@ public class TestDrawingAggregate extends TestCase { assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } + } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 0b79eae50e..2d6b14b79a 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -39,4 +39,8 @@ public class HSSFTestHelper { public static HSSFPatriarch createTestPatriarch(HSSFSheet sheet, EscherAggregate agg){ return new HSSFPatriarch(sheet, agg); } + + public static EscherAggregate getEscherAggregate(HSSFPatriarch patriarch){ + return patriarch._getBoundAggregate(); + } } From 25ceb36664b1ca6eab23ff981551236d933158b4 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Mon, 18 Jun 2012 12:02:36 +0000 Subject: [PATCH 08/32] fixed bug in EscherAggregate if sheet contains no shapes git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1351309 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/record/EscherAggregate.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index e65fd0333d..f1b470398f 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -491,7 +491,8 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { // the first one because it's the patriach). pos = offset; int writtenEscherBytes = 0; - for (int i = 1; i < shapes.size(); i++) { + int i; + for (i = 1; i < shapes.size(); i++) { int endOffset = (Integer) spEndingOffsets.get(i) - 1; int startOffset; if (i == 1) @@ -515,10 +516,15 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); } } + if ((pos - offset) < buffer.length-1){ + byte[] drawingData = new byte[buffer.length - (pos - offset)]; + System.arraycopy(buffer, (pos - offset), drawingData, 0, drawingData.length); + pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); + } // write records that need to be serialized after all drawing group records - for (int i = 0; i < tailRec.size(); i++) { - Record rec = (Record) tailRec.get(i); + for (i = 0; i < tailRec.size(); i++) { + Record rec = tailRec.get(i); pos += rec.serialize(pos, data); } int bytesWritten = pos - offset; @@ -599,6 +605,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } int drawingRecordSize = rawEscherSize + (shapeToObj.size()) * 4; + if (rawEscherSize != 0 && spEndingOffsets.size()==1/**EMPTY**/){ + continueRecordsHeadersSize +=4; + } int objRecordSize = 0; for (Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); ) { Record r = (Record) iterator.next(); From 0e8a727b3580b518d3db0a73cf0faf3ed7a5a2d1 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Mon, 18 Jun 2012 20:59:32 +0000 Subject: [PATCH 09/32] Added such improvements: 1. Each shape contains EscherContainerRecord(SpContainer). Shapes get and set all properties into EscherOptRecord. 2. HSSFShapeGroup takes coordinates from EscherSpgrRecord. 3. Added tests for creating new HSSFSimpleShape from scratch and reading from existing file 4. Improved work with anchors. git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1351484 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ddf/EscherClientAnchorRecord.java | 9 +- .../org/apache/poi/ddf/EscherRGBProperty.java | 4 + .../apache/poi/ddf/EscherSimpleProperty.java | 4 + .../apache/poi/hssf/usermodel/HSSFAnchor.java | 68 +++-- .../poi/hssf/usermodel/HSSFChildAnchor.java | 99 +++++-- .../poi/hssf/usermodel/HSSFClientAnchor.java | 267 ++++++++++-------- .../poi/hssf/usermodel/HSSFComment.java | 2 +- .../poi/hssf/usermodel/HSSFPicture.java | 16 +- .../poi/hssf/usermodel/HSSFRectangle.java | 15 - .../apache/poi/hssf/usermodel/HSSFShape.java | 171 +++++++---- .../poi/hssf/usermodel/HSSFShapeFactory.java | 36 +-- .../poi/hssf/usermodel/HSSFShapeGroup.java | 38 ++- .../poi/hssf/usermodel/HSSFSimpleShape.java | 12 +- .../hssf/usermodel/drawing/HSSFShapeType.java | 14 +- .../poi/hssf/model/TestDrawingShapes.java | 160 +++++++++++ .../apache/poi/hssf/model/TestHSSFAnchor.java | 209 ++++++++++++++ test-data/spreadsheet/drawings.xls | Bin 0 -> 32256 bytes 17 files changed, 829 insertions(+), 295 deletions(-) delete mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java create mode 100644 src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java create mode 100644 src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java create mode 100644 test-data/spreadsheet/drawings.xls diff --git a/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java b/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java index fbca0fb87d..ffc9170c43 100644 --- a/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java +++ b/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -38,6 +37,14 @@ public class EscherClientAnchorRecord public static final short RECORD_ID = (short) 0xF010; public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor"; + /** + * bit[0] - fMove (1 bit): A bit that specifies whether the shape will be kept intact when the cells are moved. + * bit[1] - fSize (1 bit): A bit that specifies whether the shape will be kept intact when the cells are resized. If fMove is 1, the value MUST be 1. + * bit[2-4] - reserved, MUST be 0 and MUST be ignored + * bit[5-15]- Undefined and MUST be ignored. + * + * it can take values: 0, 2, 3 + */ private short field_1_flag; private short field_2_col1; private short field_3_dx1; diff --git a/src/java/org/apache/poi/ddf/EscherRGBProperty.java b/src/java/org/apache/poi/ddf/EscherRGBProperty.java index 5d23addfb5..e28b97b500 100644 --- a/src/java/org/apache/poi/ddf/EscherRGBProperty.java +++ b/src/java/org/apache/poi/ddf/EscherRGBProperty.java @@ -38,6 +38,10 @@ public class EscherRGBProperty return propertyValue; } + public void setRgbColor(int color){ + this.propertyValue = color; + } + public byte getRed() { return (byte) ( propertyValue & 0xFF ); diff --git a/src/java/org/apache/poi/ddf/EscherSimpleProperty.java b/src/java/org/apache/poi/ddf/EscherSimpleProperty.java index 78fb642034..efc392dcfa 100644 --- a/src/java/org/apache/poi/ddf/EscherSimpleProperty.java +++ b/src/java/org/apache/poi/ddf/EscherSimpleProperty.java @@ -80,6 +80,10 @@ public class EscherSimpleProperty extends EscherProperty return propertyValue; } + public void setPropertyValue(int propertyValue) { + this.propertyValue = propertyValue; + } + /** * Returns true if one escher property is equal to another. */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java index 6a87806100..2fe36130cf 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java @@ -18,40 +18,64 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; + /** * An anchor is what specifics the position of a shape within a client object * or within another containing shape. * * @author Glen Stampoultzis (glens at apache.org) */ -public abstract class HSSFAnchor -{ - int dx1; - int dy1; - int dx2; - int dy2; +public abstract class HSSFAnchor { - public HSSFAnchor() - { + public HSSFAnchor() { + createEscherAnchor(); } - public HSSFAnchor( int dx1, int dy1, int dx2, int dy2 ) - { - this.dx1 = dx1; - this.dy1 = dy1; - this.dx2 = dx2; - this.dy2 = dy2; + public HSSFAnchor(int dx1, int dy1, int dx2, int dy2) { + createEscherAnchor(); + setDx1(dx1); + setDy1(dy1); + setDx2(dx2); + setDy2(dy2); } - public int getDx1(){ return dx1; } - public void setDx1( int dx1 ){ this.dx1 = dx1; } - public int getDy1(){ return dy1; } - public void setDy1( int dy1 ){ this.dy1 = dy1; } - public int getDy2(){ return dy2; } - public void setDy2( int dy2 ){ this.dy2 = dy2; } - public int getDx2(){ return dx2; } - public void setDx2( int dx2 ){ this.dx2 = dx2; } + public static HSSFAnchor createAnchorFromEscher(EscherContainerRecord container){ + if (null != container.getChildById(EscherChildAnchorRecord.RECORD_ID)){ + return new HSSFChildAnchor((EscherChildAnchorRecord) container.getChildById(EscherChildAnchorRecord.RECORD_ID)); + } else { + if (null != container.getChildById(EscherClientAnchorRecord.RECORD_ID)){ + return new HSSFClientAnchor((EscherClientAnchorRecord) container.getChildById(EscherClientAnchorRecord.RECORD_ID)); + } + return null; +// throw new IllegalArgumentException("continer must have anchor record"); + } + } + + public abstract int getDx1(); + + public abstract void setDx1(int dx1); + + public abstract int getDy1(); + + public abstract void setDy1(int dy1); + + public abstract int getDy2(); + + public abstract void setDy2(int dy2); + + public abstract int getDx2(); + + public abstract void setDx2(int dx2); public abstract boolean isHorizontallyFlipped(); + public abstract boolean isVerticallyFlipped(); + + public abstract EscherRecord getEscherAnchor(); + + protected abstract void createEscherAnchor(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java index ccd0e620cf..38c4f5f0e2 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java @@ -19,39 +19,100 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherRecord; public final class HSSFChildAnchor extends HSSFAnchor { - private EscherChildAnchorRecord escherChildAnchorRecord; + private EscherChildAnchorRecord _escherChildAnchor; public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) { - this.escherChildAnchorRecord = escherChildAnchorRecord; + this._escherChildAnchor = escherChildAnchorRecord; } - public HSSFChildAnchor() - { + public HSSFChildAnchor() { + _escherChildAnchor = new EscherChildAnchorRecord(); } - public HSSFChildAnchor( int dx1, int dy1, int dx2, int dy2 ) - { - super( dx1, dy1, dx2, dy2 ); + public HSSFChildAnchor(int dx1, int dy1, int dx2, int dy2) { + super(dx1, dy1, dx2, dy2); } - public void setAnchor(int dx1, int dy1, int dx2, int dy2) - { - this.dx1 = dx1; - this.dy1 = dy1; - this.dx2 = dx2; - this.dy2 = dy2; + @Override + public int getDx1() { + return _escherChildAnchor.getDx1(); } - public boolean isHorizontallyFlipped() - { - return dx1 > dx2; + @Override + public void setDx1(int dx1) { + _escherChildAnchor.setDx1(dx1); } - public boolean isVerticallyFlipped() - { - return dy1 > dy2; + @Override + public int getDy1() { + return _escherChildAnchor.getDy1(); + } + + @Override + public void setDy1(int dy1) { + _escherChildAnchor.setDy1(dy1); + } + + @Override + public int getDy2() { + return _escherChildAnchor.getDy2(); + } + + @Override + public void setDy2(int dy2) { + _escherChildAnchor.setDy2(dy2); + } + + @Override + public int getDx2() { + return _escherChildAnchor.getDx2(); + } + + @Override + public void setDx2(int dx2) { + _escherChildAnchor.setDx2(dx2); + } + + public void setAnchor(int dx1, int dy1, int dx2, int dy2) { + setDx1(dx1); + setDy1(dy1); + setDx2(dx2); + setDy2(dy2); + } + + public boolean isHorizontallyFlipped() { + return getDx1() > getDx2(); + } + + public boolean isVerticallyFlipped() { + return getDy1() > getDy2(); + } + + @Override + public EscherRecord getEscherAnchor() { + return _escherChildAnchor; + } + + @Override + protected void createEscherAnchor() { + _escherChildAnchor = new EscherChildAnchorRecord(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (obj == this) + return true; + if (obj.getClass() != getClass()) + return false; + HSSFChildAnchor anchor = (HSSFChildAnchor) obj; + + return anchor.getDx1() == getDx1() && anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() + && anchor.getDy2() == getDy2(); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java index a040144c27..49e20a42f1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java @@ -18,9 +18,9 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ss.usermodel.ClientAnchor; - /** * A client anchor is attached to an excel worksheet. It anchors against a * top-left and buttom-right cell. @@ -28,42 +28,34 @@ import org.apache.poi.ss.usermodel.ClientAnchor; * @author Glen Stampoultzis (glens at apache.org) */ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { - short col1; - int row1; - short col2; - int row2; - int anchorType; - private EscherClientAnchorRecord escherClientAnchorRecord; + private EscherClientAnchorRecord _escherClientAnchor; public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) { - this.escherClientAnchorRecord = escherClientAnchorRecord; - //TODO set properties or read properties from EscherRecord ? + this._escherClientAnchor = escherClientAnchorRecord; } /** * Creates a new client anchor and defaults all the anchor positions to 0. */ - public HSSFClientAnchor() - { + public HSSFClientAnchor() { } /** * Creates a new client anchor and sets the top-left and bottom-right * coordinates of the anchor. * - * @param dx1 the x coordinate within the first cell. - * @param dy1 the y coordinate within the first cell. - * @param dx2 the x coordinate within the second cell. - * @param dy2 the y coordinate within the second cell. - * @param col1 the column (0 based) of the first cell. - * @param row1 the row (0 based) of the first cell. - * @param col2 the column (0 based) of the second cell. - * @param row2 the row (0 based) of the second cell. + * @param dx1 the x coordinate within the first cell. + * @param dy1 the y coordinate within the first cell. + * @param dx2 the x coordinate within the second cell. + * @param dy2 the y coordinate within the second cell. + * @param col1 the column (0 based) of the first cell. + * @param row1 the row (0 based) of the first cell. + * @param col2 the column (0 based) of the second cell. + * @param row2 the row (0 based) of the second cell. */ - public HSSFClientAnchor( int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2 ) - { - super( dx1, dy1, dx2, dy2 ); + public HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2) { + super(dx1, dy1, dx2, dy2); checkRange(dx1, 0, 1023, "dx1"); checkRange(dx2, 0, 1023, "dx2"); @@ -74,35 +66,30 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { checkRange(row1, 0, 255 * 256, "row1"); checkRange(row2, 0, 255 * 256, "row2"); - this.col1 = col1; - this.row1 = row1; - this.col2 = col2; - this.row2 = row2; + setCol1(col1); + setCol2(col2); + setRow1(row1); + setRow2(row2); } /** * Calculates the height of a client anchor in points. * - * @param sheet the sheet the anchor will be attached to - * @return the shape height. + * @param sheet the sheet the anchor will be attached to + * @return the shape height. */ - public float getAnchorHeightInPoints(HSSFSheet sheet ) - { + public float getAnchorHeightInPoints(HSSFSheet sheet) { int y1 = getDy1(); int y2 = getDy2(); - int row1 = Math.min( getRow1(), getRow2() ); - int row2 = Math.max( getRow1(), getRow2() ); + int row1 = Math.min(getRow1(), getRow2()); + int row2 = Math.max(getRow1(), getRow2()); float points = 0; - if (row1 == row2) - { + if (row1 == row2) { points = ((y2 - y1) / 256.0f) * getRowHeightInPoints(sheet, row2); - } - else - { + } else { points += ((256.0f - y1) / 256.0f) * getRowHeightInPoints(sheet, row1); - for (int i = row1 + 1; i < row2; i++) - { + for (int i = row1 + 1; i < row2; i++) { points += getRowHeightInPoints(sheet, i); } points += (y2 / 256.0f) * getRowHeightInPoints(sheet, row2); @@ -111,8 +98,7 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { return points; } - private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) - { + private float getRowHeightInPoints(HSSFSheet sheet, int rowNum) { HSSFRow row = sheet.getRow(rowNum); if (row == null) { return sheet.getDefaultRowHeightInPoints(); @@ -120,55 +106,48 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { return row.getHeightInPoints(); } - public short getCol1() - { - return col1; + public short getCol1() { + return _escherClientAnchor.getCol1(); } - public void setCol1( short col1 ) - { + public void setCol1(short col1) { checkRange(col1, 0, 255, "col1"); - this.col1 = col1; - } - public void setCol1( int col1 ){ - setCol1((short)col1); + _escherClientAnchor.setCol1(col1); } - public short getCol2() - { - return col2; + public void setCol1(int col1) { + setCol1((short) col1); } - public void setCol2( short col2 ) - { + public short getCol2() { + return _escherClientAnchor.getCol2(); + } + + public void setCol2(short col2) { checkRange(col2, 0, 255, "col2"); - this.col2 = col2; + _escherClientAnchor.setCol2(col2); } - public void setCol2( int col2 ){ - setCol2((short)col2); + public void setCol2(int col2) { + setCol2((short) col2); } - public int getRow1() - { - return row1; + public int getRow1() { + return _escherClientAnchor.getRow1(); } - public void setRow1( int row1 ) - { + public void setRow1(int row1) { checkRange(row1, 0, 256 * 256, "row1"); - this.row1 = row1; + _escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue()); } - public int getRow2() - { - return row2; + public int getRow2() { + return _escherClientAnchor.getRow2(); } - public void setRow2( int row2 ) - { + public void setRow2(int row2) { checkRange(row2, 0, 256 * 256, "row2"); - this.row2 = row2; + _escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue()); } /** @@ -179,79 +158,139 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { * @param y1 the y coordinate within the first cell. * @param x2 the x coordinate within the second cell. * @param y2 the y coordinate within the second cell. - * @param col1 the column (0 based) of the first cell. - * @param row1 the row (0 based) of the first cell. - * @param col2 the column (0 based) of the second cell. - * @param row2 the row (0 based) of the second cell. + * @param col1 the column (0 based) of the first cell. + * @param row1 the row (0 based) of the first cell. + * @param col2 the column (0 based) of the second cell. + * @param row2 the row (0 based) of the second cell. */ - public void setAnchor( short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2 ) - { - checkRange(dx1, 0, 1023, "dx1"); - checkRange(dx2, 0, 1023, "dx2"); - checkRange(dy1, 0, 255, "dy1"); - checkRange(dy2, 0, 255, "dy2"); - checkRange(col1, 0, 255, "col1"); - checkRange(col2, 0, 255, "col2"); - checkRange(row1, 0, 255 * 256, "row1"); - checkRange(row2, 0, 255 * 256, "row2"); + public void setAnchor(short col1, int row1, int x1, int y1, short col2, int row2, int x2, int y2) { + checkRange(getDx1(), 0, 1023, "dx1"); + checkRange(getDx2(), 0, 1023, "dx2"); + checkRange(getDy1(), 0, 255, "dy1"); + checkRange(getDy2(), 0, 255, "dy2"); + checkRange(getCol1(), 0, 255, "col1"); + checkRange(getCol2(), 0, 255, "col2"); + checkRange(getRow1(), 0, 255 * 256, "row1"); + checkRange(getRow2(), 0, 255 * 256, "row2"); - this.col1 = col1; - this.row1 = row1; - this.dx1 = x1; - this.dy1 = y1; - this.col2 = col2; - this.row2 = row2; - this.dx2 = x2; - this.dy2 = y2; + setCol1(col1); + setRow1(row1); + setDx1(x1); + setDy1(y1); + setCol2(col2); + setRow2(row2); + setDx2(x2); + setDy2(y2); } /** - * @return true if the anchor goes from right to left. + * @return true if the anchor goes from right to left. */ - public boolean isHorizontallyFlipped() - { - if (col1 == col2) { - return dx1 > dx2; + public boolean isHorizontallyFlipped() { + if (getCol1() == getCol2()) { + return getDx1() > getDx2(); } - return col1 > col2; + return getCol1() > getCol2(); } /** - * @return true if the anchor goes from bottom to top. + * @return true if the anchor goes from bottom to top. */ - public boolean isVerticallyFlipped() - { - if (row1 == row2) { - return dy1 > dy2; + public boolean isVerticallyFlipped() { + if (getRow1() == getRow2()) { + return getDy1() > getDy2(); } - return row1 > row2; + return getRow1() > getRow2(); + } + + @Override + public EscherRecord getEscherAnchor() { + return _escherClientAnchor; + } + + @Override + protected void createEscherAnchor() { + _escherClientAnchor = new EscherClientAnchorRecord(); } /** * Gets the anchor type - *

+ *

* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. */ - public int getAnchorType() - { - return anchorType; + public int getAnchorType() { + return _escherClientAnchor.getFlag(); } /** * Sets the anchor type - *

+ *

* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. */ - public void setAnchorType( int anchorType ) - { - this.anchorType = anchorType; + public void setAnchorType(int anchorType) { +// if (0 != anchorType && 2 != anchorType && 3 != anchorType){ +// throw new IllegalArgumentException("Anchor type of shape can take only such values: 0, 2, 3"); +// } + _escherClientAnchor.setFlag(Integer.valueOf(anchorType).shortValue()); } - private void checkRange( int value, int minRange, int maxRange, String varName ) - { + private void checkRange(int value, int minRange, int maxRange, String varName) { if (value < minRange || value > maxRange) throw new IllegalArgumentException(varName + " must be between " + minRange + " and " + maxRange); } + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (obj == this) + return true; + if (obj.getClass() != getClass()) + return false; + HSSFClientAnchor anchor = (HSSFClientAnchor) obj; + return anchor.getCol1() == getCol1() && anchor.getCol2() == getCol2() && anchor.getDx1() == getDx1() + && anchor.getDx2() == getDx2() && anchor.getDy1() == getDy1() && anchor.getDy2() == getDy2() + && anchor.getRow1() == getRow1() && anchor.getRow2() == getRow2() && anchor.getAnchorType() == getAnchorType(); + } + + @Override + public int getDx1() { + return _escherClientAnchor.getDx1(); + } + + @Override + public void setDx1(int dx1) { + _escherClientAnchor.setDx1(Integer.valueOf(dx1).shortValue()); + } + + @Override + public int getDy1() { + return _escherClientAnchor.getDy1(); + } + + @Override + public void setDy1(int dy1) { + _escherClientAnchor.setDy1(Integer.valueOf(dy1).shortValue()); + } + + @Override + public int getDy2() { + return _escherClientAnchor.getDy2(); + } + + @Override + public void setDy2(int dy2) { + _escherClientAnchor.setDy2(Integer.valueOf(dy2).shortValue()); + } + + @Override + public int getDx2() { + return _escherClientAnchor.getDx2(); + } + + @Override + public void setDx2(int dx2) { + _escherClientAnchor.setDx2(Integer.valueOf(dx2).shortValue()); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 225e6da0e9..2216971e68 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -57,7 +57,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { setShapeType(OBJECT_TYPE_COMMENT); //default color for comments - _fillColor = 0x08000050; + setFillColor(0x08000050); //by default comments are hidden _visible = false; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index d4a7205c73..5aeb40b188 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -145,8 +145,8 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { float w = 0; //space in the leftmost cell - w += getColumnWidthInPixels(anchor.col1)*(1 - (float)anchor.dx1/1024); - short col2 = (short)(anchor.col1 + 1); + w += getColumnWidthInPixels(anchor.getCol1())*(1 - (float)anchor.getDx1()/1024); + short col2 = (short)(anchor.getCol1() + 1); int dx2 = 0; while(w < scaledWidth){ @@ -160,12 +160,12 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { double delta = w - scaledWidth; dx2 = (int)((cw-delta)/cw*1024); } - anchor.col2 = col2; - anchor.dx2 = dx2; + anchor.setCol2(col2); + anchor.setDx2(dx2); float h = 0; - h += (1 - (float)anchor.dy1/256)* getRowHeightInPixels(anchor.row1); - int row2 = anchor.row1 + 1; + h += (1 - (float)anchor.getDy1()/256)* getRowHeightInPixels(anchor.getRow1()); + int row2 = anchor.getRow1() + 1; int dy2 = 0; while(h < scaledHeight){ @@ -177,8 +177,8 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { double delta = h - scaledHeight; dy2 = (int)((ch-delta)/ch*256); } - anchor.row2 = row2; - anchor.dy2 = dy2; + anchor.setRow2(row2); + anchor.setDy2(dy2); return anchor; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java deleted file mode 100644 index 0a0468c144..0000000000 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.apache.poi.hssf.usermodel; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.hssf.record.ObjRecord; - -/** - * @author Evgeniy Berlog - * @date 08.06.12 - */ -public class HSSFRectangle extends HSSFShape{ - - public HSSFRectangle(EscherContainerRecord spContainer, ObjRecord objRecord) { - super(spContainer, objRecord); - } -} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 7ffdfdb9ba..c9bf922cb7 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -17,7 +17,7 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.ObjRecord; /** @@ -28,6 +28,8 @@ import org.apache.poi.hssf.record.ObjRecord; public abstract class HSSFShape { public static final int LINEWIDTH_ONE_PT = 12700; public static final int LINEWIDTH_DEFAULT = 9525; + public static final int LINESTYLE__COLOR_DEFAULT = 0x08000040; + public static final int FILL__FILLCOLOR_DEFAULT = 0x08000009; public static final int LINESTYLE_SOLID = 0; // Solid (continuous) pen public static final int LINESTYLE_DASHSYS = 1; // PS_DASH system dash style @@ -45,50 +47,53 @@ public abstract class HSSFShape { // TODO - make all these fields private HSSFShape parent; HSSFAnchor anchor; - HSSFPatriarch _patriarch; - private int _lineStyleColor = 0x08000040; - int _fillColor = 0x08000009; - private int _lineWidth = LINEWIDTH_DEFAULT; // 12700 = 1pt - private int _lineStyle = LINESTYLE_SOLID; - private boolean _noFill = false; + HSSFPatriarch _patriarch; - private EscherContainerRecord spContainer; - private ObjRecord objRecord; + protected EscherContainerRecord _escherContainer; + protected ObjRecord _objRecord; + protected final EscherOptRecord _optRecord; - public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord){ - this.spContainer = spContainer; - this.objRecord = objRecord; + public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord) { + this._escherContainer = spContainer; + this._objRecord = objRecord; + this._optRecord = spContainer.getChildById(EscherOptRecord.RECORD_ID); + this.anchor = HSSFAnchor.createAnchorFromEscher(spContainer); } + /** * Create a new shape with the specified parent and anchor. */ - public HSSFShape( HSSFShape parent, HSSFAnchor anchor ) - { + public HSSFShape(HSSFShape parent, HSSFAnchor anchor) { this.parent = parent; this.anchor = anchor; + this._escherContainer = new EscherContainerRecord(); + _optRecord = new EscherOptRecord(); + _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + _optRecord.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + _optRecord.addEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + _optRecord.addEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); } - public EscherContainerRecord getSpContainer() { - return spContainer; + public EscherContainerRecord getEscherContainer() { + return _escherContainer; } public ObjRecord getObjRecord() { - return objRecord; + return _objRecord; } /** * Gets the parent shape. */ - public HSSFShape getParent() - { + public HSSFShape getParent() { return parent; } /** - * @return the anchor that is used by this shape. + * @return the anchor that is used by this shape. */ - public HSSFAnchor getAnchor() - { + public HSSFAnchor getAnchor() { return anchor; } @@ -96,26 +101,29 @@ public abstract class HSSFShape { * Sets a particular anchor. A top-level shape must have an anchor of * HSSFClientAnchor. A child anchor must have an anchor of HSSFChildAnchor * - * @param anchor the anchor to use. - * @throws IllegalArgumentException when the wrong anchor is used for - * this particular shape. - * + * @param anchor the anchor to use. + * @throws IllegalArgumentException when the wrong anchor is used for + * this particular shape. * @see HSSFChildAnchor * @see HSSFClientAnchor */ - public void setAnchor( HSSFAnchor anchor ) - { - if ( parent == null ) - { - if ( anchor instanceof HSSFChildAnchor ) - throw new IllegalArgumentException( "Must use client anchors for shapes directly attached to sheet." ); + public void setAnchor(HSSFAnchor anchor) { + if (parent == null) { + if (anchor instanceof HSSFChildAnchor) + throw new IllegalArgumentException("Must use client anchors for shapes directly attached to sheet."); + EscherClientAnchorRecord anch = _escherContainer.getChildById(EscherClientAnchorRecord.RECORD_ID); + if (null != anch) { + _escherContainer.removeChildRecord(anch); + } + } else { + if (anchor instanceof HSSFClientAnchor) + throw new IllegalArgumentException("Must use child anchors for shapes attached to groups."); + EscherChildAnchorRecord anch = _escherContainer.getChildById(EscherChildAnchorRecord.RECORD_ID); + if (null != anch) { + _escherContainer.removeChildRecord(anch); + } } - else - { - if ( anchor instanceof HSSFClientAnchor ) - throw new IllegalArgumentException( "Must use child anchors for shapes attached to groups." ); - } - + _escherContainer.addChildRecord(anchor.getEscherAnchor()); this.anchor = anchor; } @@ -123,92 +131,141 @@ public abstract class HSSFShape { * The color applied to the lines of this shape. */ public int getLineStyleColor() { - return _lineStyleColor; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); + return rgbProperty == null ? LINESTYLE__COLOR_DEFAULT : rgbProperty.getRgbColor(); } /** * The color applied to the lines of this shape. */ public void setLineStyleColor(int lineStyleColor) { - _lineStyleColor = lineStyleColor; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(lineStyleColor); + } } /** * The color applied to the lines of this shape. */ public void setLineStyleColor(int red, int green, int blue) { - this._lineStyleColor = ((blue) << 16) | ((green) << 8) | red; + int lineStyleColor = ((blue) << 16) | ((green) << 8) | red; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(lineStyleColor); + } } /** * The color used to fill this shape. */ - public int getFillColor() - { - return _fillColor; + public int getFillColor() { + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); + return rgbProperty == null ? FILL__FILLCOLOR_DEFAULT : rgbProperty.getRgbColor(); } /** * The color used to fill this shape. */ public void setFillColor(int fillColor) { - _fillColor = fillColor; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(fillColor); + } } /** * The color used to fill this shape. */ - public void setFillColor( int red, int green, int blue ) - { - this._fillColor = ((blue) << 16) | ((green) << 8) | red; + public void setFillColor(int red, int green, int blue) { + int fillColor = ((blue) << 16) | ((green) << 8) | red; + EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); + if (null == rgbProperty) { + rgbProperty = new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor); + _optRecord.addEscherProperty(rgbProperty); + } else { + rgbProperty.setRgbColor(fillColor); + } } /** - * @return returns with width of the line in EMUs. 12700 = 1 pt. + * @return returns with width of the line in EMUs. 12700 = 1 pt. */ public int getLineWidth() { - return _lineWidth; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH); + return property.getPropertyValue(); } /** * Sets the width of the line. 12700 = 1 pt. * * @param lineWidth width in EMU's. 12700EMU's = 1 pt - * * @see HSSFShape#LINEWIDTH_ONE_PT */ public void setLineWidth(int lineWidth) { - _lineWidth = lineWidth; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH); + if (null == property) { + property = new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, lineWidth); + _optRecord.addEscherProperty(property); + } else { + property.setPropertyValue(lineWidth); + } } /** * @return One of the constants in LINESTYLE_* */ public int getLineStyle() { - return _lineStyle; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING); + if (null == property){ + return -1; + } + return property.getPropertyValue(); } /** * Sets the line style. * - * @param lineStyle One of the constants in LINESTYLE_* + * @param lineStyle One of the constants in LINESTYLE_* */ public void setLineStyle(int lineStyle) { - _lineStyle = lineStyle; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING); + if (null == property) { + property = new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle); + _optRecord.addEscherProperty(property); + } else { + property.setPropertyValue(lineStyle); + } } /** * @return true if this shape is not filled with a color. */ public boolean isNoFill() { - return _noFill; + EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST); + return property.isTrue(); } /** * Sets whether this shape is filled or transparent. */ public void setNoFill(boolean noFill) { - _noFill = noFill; + EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST); + if (null == property) { + property = new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? 1 : 0); + _optRecord.addEscherProperty(property); + } else { + property.setPropertyValue(noFill ? 1 : 0); + } } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 4a10a8d07a..68f410d173 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -39,25 +39,25 @@ import java.util.List; import java.util.Map; /** - * @author evgeniy + * @author Evgeniy Berlog * date: 05.06.12 */ public class HSSFShapeFactory { - private static final Map shapeTypeToClass = new HashMap(HSSFShapeType.values().length); + private static final Map shapeTypeToClass = new HashMap(HSSFShapeType.values().length); private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass); static { for (HSSFShapeType type: HSSFShapeType.values()){ - shapeTypeToClass.put(type.getType(), type.getShape()); + shapeTypeToClass.put(type.getType(), type); } } private static class ReflectionConstructorShapeCreator { - private final Map shapeTypeToClass; + private final Map shapeTypeToClass; - private ReflectionConstructorShapeCreator(Map shapeTypeToClass) { + private ReflectionConstructorShapeCreator(Map shapeTypeToClass) { this.shapeTypeToClass = shapeTypeToClass; } @@ -65,7 +65,7 @@ public class HSSFShapeFactory { if (!shapeTypeToClass.containsKey(type)){ return new HSSFUnknownShape(spContainer, objRecord); } - Class clazz = shapeTypeToClass.get(type); + Class clazz = shapeTypeToClass.get(type).getShape(); if (null == clazz){ //System.out.println("No class attached to shape type: "+type); return new HSSFUnknownShape(spContainer, objRecord); @@ -81,26 +81,6 @@ public class HSSFShapeFactory { } } - public static HSSFShape createShape(EscherRecord container, ObjRecord objRecord){ - if (0 == container.getChildRecords().size()){ - throw new IllegalArgumentException("Couldn't create shape from empty escher container"); - } - if (container.getChild(0) instanceof EscherSpgrRecord){ - return new HSSFShapeGroup((EscherContainerRecord) container, objRecord); - } - - //TODO implement cases for all shapes - return new HSSFUnknownShape(container, objRecord); - } - - public static HSSFShapeGroup createShapeGroup(){ - return null; - } - - public static HSSFShapeGroup createSimpleShape(EscherRecord container, ObjRecord objRecord){ - return null; - } - public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){ if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ HSSFShapeGroup group = new HSSFShapeGroup(container, @@ -111,10 +91,6 @@ public class HSSFShapeFactory { EscherContainerRecord spContainer = children.get(i); if(i == 0){ EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); - group.setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); } else { createShapeTree(spContainer, agg, group); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 7cab3e493d..b3209467ae 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -41,32 +41,23 @@ public class HSSFShapeGroup implements HSSFShapeContainer { List shapes = new ArrayList(); - int x1 = 0; - int y1 = 0 ; - int x2 = 1023; - int y2 = 255; + private EscherSpgrRecord _spgrRecord; public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) { super(spgrContainer, objRecord); // read internal and external coordinates from spgrContainer EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0); + _spgrRecord = (EscherSpgrRecord) spContainer.getChild(0); for(EscherRecord ch : spContainer.getChildRecords()){ switch(ch.getRecordId()) { case EscherSpgrRecord.RECORD_ID: - EscherSpgrRecord spgr = (EscherSpgrRecord)ch; - setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); break; case EscherClientAnchorRecord.RECORD_ID: - this.anchor = EscherAggregate.toClientAnchor((EscherClientAnchorRecord)ch); - // TODO anchor = new HSSFClientAnchor((EscherChildAnchorRecord)ch); + anchor = new HSSFClientAnchor((EscherClientAnchorRecord)ch); break; case EscherChildAnchorRecord.RECORD_ID: - this.anchor = EscherAggregate.toChildAnchor((EscherChildAnchorRecord)ch); - // TODO anchor = new HSSFChildAnchor((EscherClientAnchorRecord)ch); + anchor = new HSSFChildAnchor((EscherChildAnchorRecord)ch); break; } } @@ -76,6 +67,11 @@ public class HSSFShapeGroup public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor ) { super( parent, anchor ); + _spgrRecord = new EscherSpgrRecord(); + _spgrRecord.setRectX1(0); + _spgrRecord.setRectX2(1023); + _spgrRecord.setRectY1(0); + _spgrRecord.setRectY2(255); } /** @@ -171,10 +167,10 @@ public class HSSFShapeGroup */ public void setCoordinates( int x1, int y1, int x2, int y2 ) { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; + _spgrRecord.setRectX1(x1); + _spgrRecord.setRectX2(x2); + _spgrRecord.setRectY1(y1); + _spgrRecord.setRectY2(y2); } /** @@ -182,7 +178,7 @@ public class HSSFShapeGroup */ public int getX1() { - return x1; + return _spgrRecord.getRectX1(); } /** @@ -190,7 +186,7 @@ public class HSSFShapeGroup */ public int getY1() { - return y1; + return _spgrRecord.getRectY1(); } /** @@ -198,7 +194,7 @@ public class HSSFShapeGroup */ public int getX2() { - return x2; + return _spgrRecord.getRectX2(); } /** @@ -206,7 +202,7 @@ public class HSSFShapeGroup */ public int getY2() { - return y2; + return _spgrRecord.getRectY2(); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index ee8522929d..6e0df0fd54 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -17,6 +17,10 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.ObjRecord; + /** * Represents a simple shape such as a line, rectangle or oval. * @@ -52,7 +56,13 @@ public class HSSFSimpleShape int shapeType = OBJECT_TYPE_LINE; - public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor ) + public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); + setShapeType(cod.getObjectType()); + } + + public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) { super( parent, anchor ); } diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java index 2818687921..29741c90f8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -1,22 +1,24 @@ package org.apache.poi.hssf.usermodel.drawing; -import org.apache.poi.hssf.usermodel.HSSFRectangle; +import org.apache.poi.hssf.usermodel.HSSFSimpleShape; /** * @author Evgeniy Berlog * date: 08.06.12 */ public enum HSSFShapeType { - NOT_PRIMITIVE(0x0, null), - RECTANGLE(0x1, HSSFRectangle.class), - ROUND_RECTANGLE(0x2, null); + NOT_PRIMITIVE((short)0x0, null, (short)0), + RECTANGLE((short)0x1, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_RECTANGLE), + ROUND_RECTANGLE((short)0x2, null, null); private Short type; private Class shape; + private Short objectId; - HSSFShapeType(Integer type, Class shape) { - this.type = type.shortValue(); + private HSSFShapeType(Short type, Class shape, Short objectId) { + this.type = type; this.shape = shape; + this.objectId = objectId; } public Short getType() { diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java new file mode 100644 index 0000000000..f276cba391 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -0,0 +1,160 @@ +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.util.HexDump; + +import java.io.IOException; + +import static junit.framework.Assert.assertEquals; + +/** + * @author Evgeniy Berlog + * date: 12.06.12 + */ +public class TestDrawingShapes extends TestCase{ + + /** + * HSSFShape tree bust be built correctly + * Check file with such records structure: + * -patriarch + * --shape + * --group + * ---group + * ----shape + * ----shape + * ---shape + * ---group + * ----shape + * ----shape + */ + public void testDrawingGroups(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("groups"); + HSSFPatriarch patriarch = sheet.getDrawingPatriarch(); + assertEquals(patriarch.getChildren().size(), 2); + HSSFShapeGroup group = (HSSFShapeGroup) patriarch.getChildren().get(1); + assertEquals(3, group.getChildren().size()); + HSSFShapeGroup group1 = (HSSFShapeGroup) group.getChildren().get(0); + assertEquals(2, group1.getChildren().size()); + group1 = (HSSFShapeGroup) group.getChildren().get(2); + assertEquals(2, group1.getChildren().size()); + } + + public void testHSSFShapeCompatibility() { + HSSFShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor()); + assertEquals(0x08000040, shape.getLineStyleColor()); + assertEquals(0x08000009, shape.getFillColor()); + assertEquals(HSSFShape.LINEWIDTH_DEFAULT, shape.getLineWidth()); + assertEquals(HSSFShape.LINESTYLE_SOLID, shape.getLineStyle()); + assertFalse(shape.isNoFill()); + + AbstractShape sp = AbstractShape.createShape(shape, 1); + EscherContainerRecord spContainer = sp.getSpContainer(); + EscherOptRecord opt = + spContainer.getChildById(EscherOptRecord.RECORD_ID); + + assertEquals(7, opt.getEscherProperties().size()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE)).isTrue()); + assertEquals(0x00000004, + ((EscherSimpleProperty)opt.lookup(EscherProperties.GEOMETRY__SHAPEPATH)).getPropertyValue()); + assertEquals(0x08000009, + ((EscherSimpleProperty)opt.lookup(EscherProperties.FILL__FILLCOLOR)).getPropertyValue()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.FILL__NOFILLHITTEST)).isTrue()); + assertEquals(0x08000040, + ((EscherSimpleProperty)opt.lookup(EscherProperties.LINESTYLE__COLOR)).getPropertyValue()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.LINESTYLE__NOLINEDRAWDASH)).isTrue()); + assertEquals(true, + ((EscherBoolProperty)opt.lookup(EscherProperties.GROUPSHAPE__PRINT)).isTrue()); + } + /** + * create a rectangle, save the workbook, read back and verify that all shape properties are there + */ + public void testReadWriteRectangle() throws IOException { + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + + HSSFPatriarch drawing = sheet.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15); + anchor.setAnchorType(2); + assertEquals(anchor.getAnchorType(), 2); + + HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + rectangle.setLineWidth(10000); + rectangle.setFillColor(777); + assertEquals(rectangle.getFillColor(), 777); + assertEquals(10000, rectangle.getLineWidth()); + rectangle.setLineStyle(10); + assertEquals(10, rectangle.getLineStyle()); + rectangle.setLineStyleColor(1111); + rectangle.setNoFill(true); + assertEquals(rectangle.getLineStyleColor(), 1111); + assertEquals(rectangle.isNoFill(), true); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + HSSFSimpleShape rectangle2 = + (HSSFSimpleShape)drawing.getChildren().get(0); + assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, + rectangle2.getShapeType()); + assertEquals(10000, rectangle2.getLineWidth()); + assertEquals(10, rectangle2.getLineStyle()); + assertEquals(anchor, rectangle2.getAnchor()); + assertEquals(rectangle2.getLineStyleColor(), 1111); + assertEquals(rectangle2.getFillColor(), 777); + assertEquals(rectangle2.isNoFill(), true); + + rectangle2.setFillColor(3333); + rectangle2.setLineStyle(9); + rectangle2.setLineStyleColor(4444); + rectangle2.setNoFill(false); + rectangle2.setLineWidth(77); + rectangle2.getAnchor().setDx1(2); + rectangle2.getAnchor().setDx2(3); + rectangle2.getAnchor().setDy1(4); + rectangle2.getAnchor().setDy2(5); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + rectangle2 = (HSSFSimpleShape)drawing.getChildren().get(0); + assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, rectangle2.getShapeType()); + assertEquals(77, rectangle2.getLineWidth()); + assertEquals(9, rectangle2.getLineStyle()); + assertEquals(rectangle2.getLineStyleColor(), 4444); + assertEquals(rectangle2.getFillColor(), 3333); + assertEquals(rectangle2.getAnchor().getDx1(), 2); + assertEquals(rectangle2.getAnchor().getDx2(), 3); + assertEquals(rectangle2.getAnchor().getDy1(), 4); + assertEquals(rectangle2.getAnchor().getDy2(), 5); + assertEquals(rectangle2.isNoFill(), false); + } + + + /* assert shape properties when reading shapes from a existing workbook */ + public void testReadExistingRectangle() { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("rectangles"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + for(HSSFShape shape : drawing.getChildren()){ + assertEquals(shape.isNoFill(), true); + assertEquals(shape.getLineStyle(), HSSFShape.LINESTYLE_DASHDOTGEL); + assertEquals(shape.getLineStyleColor(), 0x616161); + assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D); + assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT*2); + } + } +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java new file mode 100644 index 0000000000..ef90f01f40 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -0,0 +1,209 @@ +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.usermodel.*; + +/** + * @author Evgeniy Berlog + * @date 12.06.12 + */ +public class TestHSSFAnchor extends TestCase { + + public void testCreateClientAnchorFromContainer(){ + EscherContainerRecord container = new EscherContainerRecord(); + EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); + escher.setFlag((short) 3); + escher.setCol1((short)11); + escher.setCol2((short)12); + escher.setRow1((short)13); + escher.setRow2((short) 14); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + container.addChildRecord(escher); + + HSSFClientAnchor anchor = (HSSFClientAnchor) HSSFAnchor.createAnchorFromEscher(container); + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 12); + assertEquals(escher.getCol2(), 12); + assertEquals(anchor.getRow1(), 13); + assertEquals(escher.getRow1(), 13); + assertEquals(anchor.getRow2(), 14); + assertEquals(escher.getRow2(), 14); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testCreateChildAnchorFromContainer(){ + EscherContainerRecord container = new EscherContainerRecord(); + EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + container.addChildRecord(escher); + + HSSFChildAnchor anchor = (HSSFChildAnchor) HSSFAnchor.createAnchorFromEscher(container); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testShapeEscherMustHaveAnchorRecord(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + + HSSFPatriarch drawing = sheet.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15); + anchor.setAnchorType(2); + + HSSFSimpleShape rectangle = drawing.createSimpleShape(anchor); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + rectangle.setAnchor(anchor); + + assertNotNull(anchor.getEscherAnchor()); + assertNotNull(rectangle.getEscherContainer()); + assertTrue(anchor.getEscherAnchor().equals(rectangle.getEscherContainer().getChildById(EscherClientAnchorRecord.RECORD_ID))); + } + + public void testClientAnchorFromEscher(){ + EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); + escher.setCol1((short)11); + escher.setCol2((short)12); + escher.setRow1((short)13); + escher.setRow2((short) 14); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + + HSSFClientAnchor anchor = new HSSFClientAnchor(escher); + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 12); + assertEquals(escher.getCol2(), 12); + assertEquals(anchor.getRow1(), 13); + assertEquals(escher.getRow1(), 13); + assertEquals(anchor.getRow2(), 14); + assertEquals(escher.getRow2(), 14); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testClientAnchorFromScratch(){ + HSSFClientAnchor anchor = new HSSFClientAnchor(); + EscherClientAnchorRecord escher = (EscherClientAnchorRecord) anchor.getEscherAnchor(); + anchor.setAnchor((short)11, 12, 13, 14, (short)15, 16, 17, 18); + + assertEquals(anchor.getCol1(), 11); + assertEquals(escher.getCol1(), 11); + assertEquals(anchor.getCol2(), 15); + assertEquals(escher.getCol2(), 15); + assertEquals(anchor.getRow1(), 12); + assertEquals(escher.getRow1(), 12); + assertEquals(anchor.getRow2(), 16); + assertEquals(escher.getRow2(), 16); + assertEquals(anchor.getDx1(), 13); + assertEquals(escher.getDx1(), 13); + assertEquals(anchor.getDx2(), 17); + assertEquals(escher.getDx2(), 17); + assertEquals(anchor.getDy1(), 14); + assertEquals(escher.getDy1(), 14); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + + anchor.setCol1(111); + assertEquals(anchor.getCol1(), 111); + assertEquals(escher.getCol1(), 111); + anchor.setCol2(112); + assertEquals(anchor.getCol2(), 112); + assertEquals(escher.getCol2(), 112); + anchor.setRow1(113); + assertEquals(anchor.getRow1(), 113); + assertEquals(escher.getRow1(), 113); + anchor.setRow2(114); + assertEquals(anchor.getRow2(), 114); + assertEquals(escher.getRow2(), 114); + anchor.setDx1(115); + assertEquals(anchor.getDx1(), 115); + assertEquals(escher.getDx1(), 115); + anchor.setDx2(116); + assertEquals(anchor.getDx2(), 116); + assertEquals(escher.getDx2(), 116); + anchor.setDy1(117); + assertEquals(anchor.getDy1(), 117); + assertEquals(escher.getDy1(), 117); + anchor.setDy2(118); + assertEquals(anchor.getDy2(), 118); + assertEquals(escher.getDy2(), 118); + } + + public void testChildAnchorFromEscher(){ + EscherChildAnchorRecord escher = new EscherChildAnchorRecord(); + escher.setDx1((short) 15); + escher.setDx2((short) 16); + escher.setDy1((short) 17); + escher.setDy2((short) 18); + + HSSFChildAnchor anchor = new HSSFChildAnchor(escher); + assertEquals(anchor.getDx1(), 15); + assertEquals(escher.getDx1(), 15); + assertEquals(anchor.getDx2(), 16); + assertEquals(escher.getDx2(), 16); + assertEquals(anchor.getDy1(), 17); + assertEquals(escher.getDy1(), 17); + assertEquals(anchor.getDy2(), 18); + assertEquals(escher.getDy2(), 18); + } + + public void testChildAnchorFromScratch(){ + HSSFChildAnchor anchor = new HSSFChildAnchor(); + EscherChildAnchorRecord escher = (EscherChildAnchorRecord) anchor.getEscherAnchor(); + anchor.setAnchor(11, 12, 13, 14); + + assertEquals(anchor.getDx1(), 11); + assertEquals(escher.getDx1(), 11); + assertEquals(anchor.getDx2(), 13); + assertEquals(escher.getDx2(), 13); + assertEquals(anchor.getDy1(), 12); + assertEquals(escher.getDy1(), 12); + assertEquals(anchor.getDy2(), 14); + assertEquals(escher.getDy2(), 14); + + anchor.setDx1(115); + assertEquals(anchor.getDx1(), 115); + assertEquals(escher.getDx1(), 115); + anchor.setDx2(116); + assertEquals(anchor.getDx2(), 116); + assertEquals(escher.getDx2(), 116); + anchor.setDy1(117); + assertEquals(anchor.getDy1(), 117); + assertEquals(escher.getDy1(), 117); + anchor.setDy2(118); + assertEquals(anchor.getDy2(), 118); + assertEquals(escher.getDy2(), 118); + } +} diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls new file mode 100644 index 0000000000000000000000000000000000000000..ccbcc8cb4a10b6031f4b49711e404707fb947ba2 GIT binary patch literal 32256 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≧kj9{T|)tUKDL)G*@?Xoe!tEeZ0m`{`a3U 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 Dlx&6B literal 0 HcmV?d00001 From 0c5bf44cba0905d68de068a745c9666f8d028375 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Tue, 19 Jun 2012 21:00:04 +0000 Subject: [PATCH 10/32] improved aggregating drawing records in documents with charts, fixed reading EscherContainer records from byte array git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1351850 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ddf/DefaultEscherRecordFactory.java | 16 +++- .../apache/poi/ddf/EscherContainerRecord.java | 32 +++++++- .../poi/hssf/model/TestDrawingAggregate.java | 76 +++++++++++++++-- .../hssf/model/TestEscherRecordFactory.java | 82 +++++++++++++++++++ 4 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java diff --git a/src/java/org/apache/poi/ddf/DefaultEscherRecordFactory.java b/src/java/org/apache/poi/ddf/DefaultEscherRecordFactory.java index 4b39b81599..cf48a38d84 100644 --- a/src/java/org/apache/poi/ddf/DefaultEscherRecordFactory.java +++ b/src/java/org/apache/poi/ddf/DefaultEscherRecordFactory.java @@ -65,8 +65,7 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory { // However, EscherTextboxRecord are containers of records for the // host application, not of other Escher records, so treat them // differently - if ( ( options & (short) 0x000F ) == (short) 0x000F - && recordId != EscherTextboxRecord.RECORD_ID ) { + if (isContainer(options, recordId)) { EscherContainerRecord r = new EscherContainerRecord(); r.setRecordId( recordId ); r.setOptions( options ); @@ -145,4 +144,17 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory { } return result; } + + public static boolean isContainer(short options, short recordId){ + if(recordId >= EscherContainerRecord.DGG_CONTAINER && recordId + <= EscherContainerRecord.SOLVER_CONTAINER){ + return true; + } else { + if (recordId == EscherTextboxRecord.RECORD_ID) { + return false; + } else { + return ( options & (short) 0x000F ) == (short) 0x000F; + } + } + } } diff --git a/src/java/org/apache/poi/ddf/EscherContainerRecord.java b/src/java/org/apache/poi/ddf/EscherContainerRecord.java index 4190594b54..860edd8071 100644 --- a/src/java/org/apache/poi/ddf/EscherContainerRecord.java +++ b/src/java/org/apache/poi/ddf/EscherContainerRecord.java @@ -25,6 +25,8 @@ import java.util.NoSuchElementException; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; /** * Escher container records store other escher records as children. @@ -42,6 +44,32 @@ public final class EscherContainerRecord extends EscherRecord { public static final short SP_CONTAINER = (short)0xF004; public static final short SOLVER_CONTAINER = (short)0xF005; + private static POILogger log = POILogFactory.getLogger(EscherContainerRecord.class); + + /** + * in case if document contains any charts we have such document structure: + * BOF + * ... + * DrawingRecord + * ... + * ObjRecord|TxtObjRecord + * ... + * EOF + * ... + * BOF(Chart begin) + * ... + * DrawingRecord + * ... + * ObjRecord|TxtObjRecord + * ... + * EOF + * So, when we call EscherAggregate.createAggregate() we have not all needed data. + * When we got warning "WARNING: " + bytesRemaining + " bytes remaining but no space left" + * we should save value of bytesRemaining + * and add it to container size when we serialize it + */ + private int _remainingLength; + private final List _childRecords = new ArrayList(); public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory) { @@ -56,7 +84,8 @@ public final class EscherContainerRecord extends EscherRecord { bytesRemaining -= childBytesWritten; addChildRecord(child); if (offset >= data.length && bytesRemaining > 0) { - System.out.println("WARNING: " + bytesRemaining + " bytes remaining but no space left"); + _remainingLength = bytesRemaining; + log.log(POILogger.WARN, "Not enough Escher data: " + bytesRemaining + " bytes remaining but no space left"); } } return bytesWritten; @@ -74,6 +103,7 @@ public final class EscherContainerRecord extends EscherRecord { EscherRecord r = iterator.next(); remainingBytes += r.getRecordSize(); } + remainingBytes += _remainingLength; LittleEndian.putInt(data, offset+4, remainingBytes); int pos = offset+8; iterator = _childRecords.iterator(); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index baa5f66c08..43cdd8b856 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -17,8 +17,7 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherDggRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.record.ContinueRecord; import org.apache.poi.hssf.record.DrawingRecord; @@ -36,6 +35,7 @@ import org.apache.poi.hssf.usermodel.HSSFPatriarch; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFTestHelper; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.util.HexDump; import org.apache.poi.util.HexRead; import java.io.ByteArrayInputStream; @@ -188,15 +188,53 @@ public class TestDrawingAggregate extends TestCase { // System.out.println("[WARN] Cannot read " + file.getName()); continue; } - try { - assertWriteAndReadBack(wb); - } catch (Throwable e){ - //e.printStackTrace(); - System.err.println("[ERROR] assertion failed for " + file.getName() + ": " + e.getMessage()); - } + assertWriteAndReadBack(wb); } } + /** + * when reading incomplete data ensure that the serialized bytes + match the source + */ + public void testIncompleteData(){ + //EscherDgContainer and EscherSpgrContainer length exceeds the actual length of the data + String hex = + " 0F 00 02 F0 30 03 00 00 10 00 08 F0 08 00 00 " + + " 00 07 00 00 00 B2 04 00 00 0F 00 03 F0 18 03 00 " + + " 00 0F 00 04 F0 28 00 00 00 01 00 09 F0 10 00 00 " + + " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + + " 00 02 00 0A F0 08 00 00 00 00 04 00 00 05 00 00 " + + " 00 0F 00 04 F0 74 00 00 00 92 0C 0A F0 08 00 00 " + + " 00 AD 04 00 00 00 0A 00 00 63 00 0B F0 3A 00 00 " + + " 00 7F 00 04 01 E5 01 BF 00 08 00 08 00 81 01 4E " + + " 00 00 08 BF 01 10 00 10 00 80 C3 16 00 00 00 BF " + + " 03 00 00 02 00 44 00 69 00 61 00 67 00 72 00 61 " + + " 00 6D 00 6D 00 20 00 32 00 00 00 00 00 10 F0 12 " + + " 00 00 00 00 00 05 00 00 00 01 00 00 00 0B 00 00 " + + " 00 0F 00 66 00 00 00 11 F0 00 00 00 00 "; + byte[] buffer = HexRead.readFromString(hex); + + List records = new ArrayList(); + EscherRecordFactory recordFactory = new DefaultEscherRecordFactory(); + int pos = 0; + while (pos < buffer.length) { + EscherRecord r = recordFactory.createRecord(buffer, pos); + int bytesRead = r.fillFields(buffer, pos, recordFactory); + records.add(r); + pos += bytesRead; + } + assertEquals("data was not fully read", buffer.length, pos); + + // serialize to byte array + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + for(EscherRecord r : records) out.write(r.serialize()); + } catch (IOException e){ + throw new RuntimeException(e); + } + assertEquals(HexDump.toHex(buffer, 10), HexDump.toHex(out.toByteArray(), 10)); + } + /** * TODO: figure out why it fails with "RecordFormatException: 0 bytes written but getRecordSize() reports 80" */ @@ -266,6 +304,28 @@ public class TestDrawingAggregate extends TestCase { assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); } + public void testFileWithCharts(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49581.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 21); + byte[] dgBytes = toByteArray(dgRecords); + sh.getDrawingPatriarch(); + + // collect drawing records into a byte buffer. + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + for (int i=0; i< dgBytes.length; i++){ + if (dgBytes[i] != dgBytesAfterSave[i]){ + System.out.println("pos = " + i); + } + } + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + } + /** * test reading drawing aggregate from a test file from Bugzilla 45129 */ diff --git a/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java b/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java new file mode 100644 index 0000000000..9b37d43c68 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java @@ -0,0 +1,82 @@ +package org.apache.poi.hssf.model; + +import junit.framework.TestCase; +import org.apache.poi.ddf.DefaultEscherRecordFactory; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordBase; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFTestHelper; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +/** + * @author Evgeniy Berlog + * @date 18.06.12 + */ +public class TestEscherRecordFactory extends TestCase{ + + private static byte[] toByteArray(List records) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (RecordBase rb : records) { + Record r = (Record) rb; + try { + out.write(r.serialize()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return out.toByteArray(); + } + + public void testDetectContainer() { + Random rnd = new Random(); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DG_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SOLVER_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SP_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.DGG_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.BSTORE_CONTAINER)); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x0, EscherContainerRecord.SPGR_CONTAINER)); + + for (Short i=EscherContainerRecord.DGG_CONTAINER; i<= EscherContainerRecord.SOLVER_CONTAINER; i++){ + assertEquals(true, DefaultEscherRecordFactory.isContainer(Integer.valueOf(rnd.nextInt(Short.MAX_VALUE)).shortValue(), i)); + } + + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x0, Integer.valueOf(EscherContainerRecord.SOLVER_CONTAINER+1).shortValue())); + + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0x000F, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(true, DefaultEscherRecordFactory.isContainer((short) 0xFFFF, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000C, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, Integer.valueOf(EscherContainerRecord.DGG_CONTAINER-1).shortValue())); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0x000F, EscherTextboxRecord.RECORD_ID)); + assertEquals(false, DefaultEscherRecordFactory.isContainer((short) 0xCCCC, EscherTextboxRecord.RECORD_ID)); + } + + public void testDgContainerMustBeRootOfHSSFSheetEscherRecords() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("47251.xls"); + HSSFSheet sh = wb.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + List records = ish.getRecords(); + // records to be aggregated + List dgRecords = records.subList(19, 23); + byte[] dgBytes = toByteArray(dgRecords); + sh.getDrawingPatriarch(); + EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + assertEquals(true, agg.getEscherRecords().get(0) instanceof EscherContainerRecord); + assertEquals(EscherContainerRecord.DG_CONTAINER, agg.getEscherRecords().get(0).getRecordId()); + assertEquals((short) 0x0, agg.getEscherRecords().get(0).getOptions()); + agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid); + byte[] dgBytesAfterSave = agg.serialize(); + assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length); + assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave)); + } +} From 93b0bb98bfcd57fd0bbc3acc663296c77aea085b Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Wed, 20 Jun 2012 08:57:38 +0000 Subject: [PATCH 11/32] Utility to test that POI produces readable output after re-saving xls files git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1351998 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/poi/hssf/dev/ReSave.java | 63 ++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100755 src/java/org/apache/poi/hssf/dev/ReSave.java diff --git a/src/java/org/apache/poi/hssf/dev/ReSave.java b/src/java/org/apache/poi/hssf/dev/ReSave.java new file mode 100755 index 0000000000..2a111832aa --- /dev/null +++ b/src/java/org/apache/poi/hssf/dev/ReSave.java @@ -0,0 +1,63 @@ +/* + * 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.hssf.dev; + +import org.apache.poi.hssf.usermodel.HSSFPatriarch; +import org.apache.poi.hssf.usermodel.HSSFShape; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +import java.io.FileInputStream; +import java.io.FileOutputStream; + +/** + * Utility to test that POI produces readable output + * after re-saving xls files. + * + * Usage: ReSave [-dg] input.xls + * -dg initialize drawings, causes to re-build escher aggregates in all sheets + */ +public class ReSave { + public static void main(String[] args) throws Exception { + boolean initDrawing = false; + for(String arg : args) { + if(arg.equals("-dg")) initDrawing = true; + else { + System.out.print("reading " + arg + "..."); + FileInputStream is = new FileInputStream(arg); + HSSFWorkbook wb = new HSSFWorkbook(is); + is.close(); + System.out.println("done"); + + for(int i = 0; i < wb.getNumberOfSheets(); i++){ + HSSFSheet sheet = wb.getSheetAt(i); + if(initDrawing) { + HSSFPatriarch dg = sheet.getDrawingPatriarch(); + } + } + + String outputFile = arg.replace(".xls", "-saved.xls"); + System.out.print("saving to " + outputFile + "..."); + FileOutputStream out = new FileOutputStream(outputFile); + wb.write(out); + out.close(); + System.out.println("done"); + } + } + } +} From 7efc80c3e8945546bb7fa4fa019e9f6449e5b55b Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Fri, 22 Jun 2012 09:37:17 +0000 Subject: [PATCH 12/32] added support for HSSFPicture in HSSFShapeFactory, fixed bugs, added tests git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1352818 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/ddf/EscherRGBProperty.java | 4 - .../apache/poi/ddf/EscherSimpleProperty.java | 4 - .../poi/hssf/record/EscherAggregate.java | 42 ++++- .../poi/hssf/usermodel/HSSFPicture.java | 20 +- .../apache/poi/hssf/usermodel/HSSFShape.java | 97 +++++----- .../hssf/usermodel/drawing/HSSFShapeType.java | 2 + .../poi/hssf/model/TestDrawingAggregate.java | 36 ++++ .../poi/hssf/model/TestDrawingShapes.java | 94 ++++++++++ .../apache/poi/hssf/model/TestHSSFAnchor.java | 175 +++++++++++++++++- test-data/spreadsheet/drawings.xls | Bin 32256 -> 815104 bytes 10 files changed, 405 insertions(+), 69 deletions(-) diff --git a/src/java/org/apache/poi/ddf/EscherRGBProperty.java b/src/java/org/apache/poi/ddf/EscherRGBProperty.java index e28b97b500..5d23addfb5 100644 --- a/src/java/org/apache/poi/ddf/EscherRGBProperty.java +++ b/src/java/org/apache/poi/ddf/EscherRGBProperty.java @@ -38,10 +38,6 @@ public class EscherRGBProperty return propertyValue; } - public void setRgbColor(int color){ - this.propertyValue = color; - } - public byte getRed() { return (byte) ( propertyValue & 0xFF ); diff --git a/src/java/org/apache/poi/ddf/EscherSimpleProperty.java b/src/java/org/apache/poi/ddf/EscherSimpleProperty.java index efc392dcfa..78fb642034 100644 --- a/src/java/org/apache/poi/ddf/EscherSimpleProperty.java +++ b/src/java/org/apache/poi/ddf/EscherSimpleProperty.java @@ -80,10 +80,6 @@ public class EscherSimpleProperty extends EscherProperty return propertyValue; } - public void setPropertyValue(int propertyValue) { - this.propertyValue = propertyValue; - } - /** * Returns true if one escher property is equal to another. */ diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index f1b470398f..fb16037a37 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -315,6 +315,10 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { */ private List tailRec = new ArrayList(); + public EscherAggregate() { + buildBaseTree(); + } + public EscherAggregate(DrawingManager2 drawingManager) { this.drawingManager = drawingManager; } @@ -634,7 +638,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public void setPatriarch(HSSFPatriarch patriarch) { this.patriarch = patriarch; - convertPatriarch(patriarch); } /** @@ -1025,6 +1028,43 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { throw new IllegalArgumentException("Can not find client data record"); } + private void buildBaseTree(){ + EscherContainerRecord dgContainer = new EscherContainerRecord(); + EscherContainerRecord spgrContainer = new EscherContainerRecord(); + EscherContainerRecord spContainer1 = new EscherContainerRecord(); + EscherSpgrRecord spgr = new EscherSpgrRecord(); + EscherSpRecord sp1 = new EscherSpRecord(); + dgContainer.setRecordId(EscherContainerRecord.DG_CONTAINER); + dgContainer.setOptions((short) 0x000F); + EscherDgRecord dg = new EscherDgRecord(); + dg.setRecordId( EscherDgRecord.RECORD_ID ); + short dgId = 1; + dg.setOptions( (short) ( dgId << 4 ) ); + dg.setNumShapes( 1 ); + dg.setLastMSOSPID( 1024 ); + drawingGroupId = dg.getDrawingGroupId(); + spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); + spgrContainer.setOptions((short) 0x000F); + spContainer1.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer1.setOptions((short) 0x000F); + spgr.setRecordId(EscherSpgrRecord.RECORD_ID); + spgr.setOptions((short) 0x0001); // version + spgr.setRectX1(0); + spgr.setRectY1(0); + spgr.setRectX2(1023); + spgr.setRectY2(255); + sp1.setRecordId(EscherSpRecord.RECORD_ID); + sp1.setOptions((short) 0x0002); + sp1.setShapeId(1024); + sp1.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH); + dgContainer.addChildRecord(dg); + dgContainer.addChildRecord(spgrContainer); + spgrContainer.addChildRecord(spContainer1); + spContainer1.addChildRecord(spgr); + spContainer1.addChildRecord(sp1); + addEscherRecord(dgContainer); + } + private void convertPatriarch(HSSFPatriarch patriarch) { EscherContainerRecord dgContainer = new EscherContainerRecord(); EscherDgRecord dg; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 5aeb40b188..985bb8f177 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -20,8 +20,8 @@ package org.apache.poi.hssf.usermodel; import java.awt.Dimension; import java.io.ByteArrayInputStream; -import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.ddf.EscherBlipRecord; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.ss.usermodel.Picture; import org.apache.poi.ss.util.ImageUtils; import org.apache.poi.hssf.model.InternalWorkbook; @@ -54,7 +54,9 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { */ private static final int PX_ROW = 15; - private int _pictureIndex; + public HSSFPicture(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); + } /** * Constructs a picture object. @@ -67,12 +69,16 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { public int getPictureIndex() { - return _pictureIndex; + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.BLIP__BLIPTODISPLAY); + if (null == property){ + return -1; + } + return property.getPropertyValue(); } public void setPictureIndex( int pictureIndex ) { - this._pictureIndex = pictureIndex; + setPropertyValue(new EscherSimpleProperty( EscherProperties.BLIP__BLIPTODISPLAY, false, true, pictureIndex)); } /** @@ -215,7 +221,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { * @return image dimension */ public Dimension getImageDimension(){ - EscherBSERecord bse = _patriarch._sheet._book.getBSERecord(_pictureIndex); + EscherBSERecord bse = _patriarch._sheet._book.getBSERecord(getPictureIndex()); byte[] data = bse.getBlipRecord().getPicturedata(); int type = bse.getBlipTypeWin32(); return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type); @@ -228,7 +234,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { */ public HSSFPictureData getPictureData(){ InternalWorkbook iwb = _patriarch._sheet.getWorkbook().getWorkbook(); - EscherBlipRecord blipRecord = iwb.getBSERecord(_pictureIndex).getBlipRecord(); + EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord(); return new HSSFPictureData(blipRecord); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index c9bf922cb7..33dfd68643 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -30,6 +30,7 @@ public abstract class HSSFShape { public static final int LINEWIDTH_DEFAULT = 9525; public static final int LINESTYLE__COLOR_DEFAULT = 0x08000040; public static final int FILL__FILLCOLOR_DEFAULT = 0x08000009; + public static final boolean NO_FILL_DEFAULT = true; public static final int LINESTYLE_SOLID = 0; // Solid (continuous) pen public static final int LINESTYLE_DASHSYS = 1; // PS_DASH system dash style @@ -44,6 +45,8 @@ public abstract class HSSFShape { public static final int LINESTYLE_LONGDASHDOTDOTGEL = 10; // long dash short dash short dash public static final int LINESTYLE_NONE = -1; + public static final int LINESTYLE_DEFAULT = LINESTYLE_NONE; + // TODO - make all these fields private HSSFShape parent; HSSFAnchor anchor; @@ -108,11 +111,20 @@ public abstract class HSSFShape { * @see HSSFClientAnchor */ public void setAnchor(HSSFAnchor anchor) { + int i = 0; + int recordId = -1; if (parent == null) { if (anchor instanceof HSSFChildAnchor) throw new IllegalArgumentException("Must use client anchors for shapes directly attached to sheet."); EscherClientAnchorRecord anch = _escherContainer.getChildById(EscherClientAnchorRecord.RECORD_ID); if (null != anch) { + for (i=0; i< _escherContainer.getChildRecords().size(); i++){ + if (_escherContainer.getChild(i).getRecordId() == EscherClientAnchorRecord.RECORD_ID){ + if (i != _escherContainer.getChildRecords().size() -1){ + recordId = _escherContainer.getChild(i+1).getRecordId(); + } + } + } _escherContainer.removeChildRecord(anch); } } else { @@ -120,10 +132,21 @@ public abstract class HSSFShape { throw new IllegalArgumentException("Must use child anchors for shapes attached to groups."); EscherChildAnchorRecord anch = _escherContainer.getChildById(EscherChildAnchorRecord.RECORD_ID); if (null != anch) { + for (i=0; i< _escherContainer.getChildRecords().size(); i++){ + if (_escherContainer.getChild(i).getRecordId() == EscherChildAnchorRecord.RECORD_ID){ + if (i != _escherContainer.getChildRecords().size() -1){ + recordId = _escherContainer.getChild(i+1).getRecordId(); + } + } + } _escherContainer.removeChildRecord(anch); } } - _escherContainer.addChildRecord(anchor.getEscherAnchor()); + if (-1 == recordId){ + _escherContainer.addChildRecord(anchor.getEscherAnchor()); + } else { + _escherContainer.addChildBefore(anchor.getEscherAnchor(), recordId); + } this.anchor = anchor; } @@ -139,13 +162,7 @@ public abstract class HSSFShape { * The color applied to the lines of this shape. */ public void setLineStyleColor(int lineStyleColor) { - EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); - if (null == rgbProperty) { - rgbProperty = new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor); - _optRecord.addEscherProperty(rgbProperty); - } else { - rgbProperty.setRgbColor(lineStyleColor); - } + setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor)); } /** @@ -153,13 +170,7 @@ public abstract class HSSFShape { */ public void setLineStyleColor(int red, int green, int blue) { int lineStyleColor = ((blue) << 16) | ((green) << 8) | red; - EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.LINESTYLE__COLOR); - if (null == rgbProperty) { - rgbProperty = new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor); - _optRecord.addEscherProperty(rgbProperty); - } else { - rgbProperty.setRgbColor(lineStyleColor); - } + setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, lineStyleColor)); } /** @@ -174,13 +185,7 @@ public abstract class HSSFShape { * The color used to fill this shape. */ public void setFillColor(int fillColor) { - EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); - if (null == rgbProperty) { - rgbProperty = new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor); - _optRecord.addEscherProperty(rgbProperty); - } else { - rgbProperty.setRgbColor(fillColor); - } + setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor)); } /** @@ -188,13 +193,7 @@ public abstract class HSSFShape { */ public void setFillColor(int red, int green, int blue) { int fillColor = ((blue) << 16) | ((green) << 8) | red; - EscherRGBProperty rgbProperty = _optRecord.lookup(EscherProperties.FILL__FILLCOLOR); - if (null == rgbProperty) { - rgbProperty = new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor); - _optRecord.addEscherProperty(rgbProperty); - } else { - rgbProperty.setRgbColor(fillColor); - } + setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, fillColor)); } /** @@ -202,7 +201,7 @@ public abstract class HSSFShape { */ public int getLineWidth() { EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH); - return property.getPropertyValue(); + return property == null ? LINEWIDTH_DEFAULT: property.getPropertyValue(); } /** @@ -212,13 +211,7 @@ public abstract class HSSFShape { * @see HSSFShape#LINEWIDTH_ONE_PT */ public void setLineWidth(int lineWidth) { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEWIDTH); - if (null == property) { - property = new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, lineWidth); - _optRecord.addEscherProperty(property); - } else { - property.setPropertyValue(lineWidth); - } + setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, lineWidth)); } /** @@ -227,7 +220,7 @@ public abstract class HSSFShape { public int getLineStyle() { EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING); if (null == property){ - return -1; + return LINESTYLE_DEFAULT; } return property.getPropertyValue(); } @@ -238,13 +231,7 @@ public abstract class HSSFShape { * @param lineStyle One of the constants in LINESTYLE_* */ public void setLineStyle(int lineStyle) { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.LINESTYLE__LINEDASHING); - if (null == property) { - property = new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle); - _optRecord.addEscherProperty(property); - } else { - property.setPropertyValue(lineStyle); - } + setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle)); } /** @@ -252,19 +239,29 @@ public abstract class HSSFShape { */ public boolean isNoFill() { EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST); - return property.isTrue(); + return property == null ? NO_FILL_DEFAULT : property.isTrue(); } /** * Sets whether this shape is filled or transparent. */ public void setNoFill(boolean noFill) { - EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST); - if (null == property) { - property = new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? 1 : 0); + setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? 1 : 0)); + } + + protected void setPropertyValue(EscherProperty property){ + if (null == _optRecord.lookup(property.getId())){ _optRecord.addEscherProperty(property); } else { - property.setPropertyValue(noFill ? 1 : 0); + int i=0; + for (EscherProperty prop: _optRecord.getEscherProperties()){ + if (prop.getId() == property.getId()){ + _optRecord.getEscherProperties().remove(i); + break; + } + i++; + } + _optRecord.addEscherProperty(property); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java index 29741c90f8..c63a08b7e5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -1,5 +1,6 @@ package org.apache.poi.hssf.usermodel.drawing; +import org.apache.poi.hssf.usermodel.HSSFPicture; import org.apache.poi.hssf.usermodel.HSSFSimpleShape; /** @@ -9,6 +10,7 @@ import org.apache.poi.hssf.usermodel.HSSFSimpleShape; public enum HSSFShapeType { NOT_PRIMITIVE((short)0x0, null, (short)0), RECTANGLE((short)0x1, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_RECTANGLE), + PICTURE((short)0x004B, HSSFPicture.class, HSSFSimpleShape.OBJECT_TYPE_PICTURE), ROUND_RECTANGLE((short)0x2, null, null); private Short type; diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index 43cdd8b856..18572d6ec1 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -43,6 +43,8 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -192,6 +194,40 @@ public class TestDrawingAggregate extends TestCase { } } + public void testBuildBaseTree(){ + EscherAggregate agg = new EscherAggregate(); + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + + HSSFPatriarch drawing = sheet.createDrawingPatriarch(); + EscherAggregate agg1 = HSSFTestHelper.getEscherAggregate(drawing); + callConvertPatriarch(agg1); + agg1.setPatriarch(null); + + agg.setPatriarch(null); + + byte[] aggS = agg.serialize(); + byte []agg1S = agg1.serialize(); + + assertEquals(aggS.length, agg1S.length); + assertTrue(Arrays.equals(aggS, agg1S)); + } + + private static void callConvertPatriarch(EscherAggregate agg) { + Method method = null; + try { + method = agg.getClass().getDeclaredMethod("convertPatriarch", HSSFPatriarch.class); + method.setAccessible(true); + method.invoke(agg, agg.getPatriarch()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + /** * when reading incomplete data ensure that the serialized bytes match the source diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index f276cba391..097d5d01ee 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -3,6 +3,9 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; import org.apache.poi.ddf.*; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.util.HexDump; @@ -72,6 +75,38 @@ public class TestDrawingShapes extends TestCase{ assertEquals(true, ((EscherBoolProperty)opt.lookup(EscherProperties.GROUPSHAPE__PRINT)).isTrue()); } + + public void testDefaultPictureSettings(){ + HSSFPicture picture = new HSSFPicture(null, new HSSFClientAnchor()); + assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); + assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT); + assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_SOLID); + assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT); + assertEquals(picture.isNoFill(), false); + assertEquals(picture.getPictureIndex(), -1);//not set yet + } + + /** + * No NullPointerException should appear + */ + public void testDefaultSettingsWithEmptyContainer(){ + EscherContainerRecord container = new EscherContainerRecord(); + EscherOptRecord opt = new EscherOptRecord(); + opt.setRecordId(EscherOptRecord.RECORD_ID); + container.addChildRecord(opt); + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord cod = new CommonObjectDataSubRecord(); + cod.setObjectType(HSSFSimpleShape.OBJECT_TYPE_PICTURE); + obj.addSubRecord(cod); + HSSFPicture picture = new HSSFPicture(container, obj); + + assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); + assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT); + assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT); + assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT); + assertEquals(picture.isNoFill(), HSSFShape.NO_FILL_DEFAULT); + assertEquals(picture.getPictureIndex(), -1);//not set yet + } /** * create a rectangle, save the workbook, read back and verify that all shape properties are there */ @@ -139,6 +174,28 @@ public class TestDrawingShapes extends TestCase{ assertEquals(rectangle2.getAnchor().getDy1(), 4); assertEquals(rectangle2.getAnchor().getDy2(), 5); assertEquals(rectangle2.isNoFill(), false); + + HSSFSimpleShape rect3 = drawing.createSimpleShape(new HSSFClientAnchor()); + rect3.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + + drawing = wb.getSheetAt(0).getDrawingPatriarch(); + assertEquals(drawing.getChildren().size(), 2); + } + + public void testReadExistingImage(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("pictures"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); + + assertEquals(picture.getPictureIndex(), 1); + assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT); + assertEquals(picture.getFillColor(), 0x5DC943); + assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); + assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT); + assertEquals(picture.isNoFill(), true); } @@ -157,4 +214,41 @@ public class TestDrawingShapes extends TestCase{ assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT*2); } } + + public void testShapeIds() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet1 = wb.createSheet(); + HSSFPatriarch patriarch1 = sheet1.createDrawingPatriarch(); + for(int i = 0; i < 2; i++) { + patriarch1.createSimpleShape(new HSSFClientAnchor()); + } + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet1 = wb.getSheetAt(0); + patriarch1 = sheet1.getDrawingPatriarch(); + + EscherAggregate agg1 = HSSFTestHelper.getEscherAggregate(patriarch1); + // last shape ID cached in EscherDgRecord + EscherDgRecord dg1 = + agg1.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); + assertEquals(1026, dg1.getLastMSOSPID()); + + // iterate over shapes and check shapeId + EscherContainerRecord spgrContainer = + agg1.getEscherContainer().getChildContainers().get(0); + // root spContainer + 2 spContainers for shapes + assertEquals(3, spgrContainer.getChildRecords().size()); + + EscherSpRecord sp0 = + ((EscherContainerRecord)spgrContainer.getChild(0)).getChildById(EscherSpRecord.RECORD_ID); + assertEquals(1024, sp0.getShapeId()); + + EscherSpRecord sp1 = + ((EscherContainerRecord)spgrContainer.getChild(1)).getChildById(EscherSpRecord.RECORD_ID); + assertEquals(1025, sp1.getShapeId()); + + EscherSpRecord sp2 = + ((EscherContainerRecord)spgrContainer.getChild(2)).getChildById(EscherSpRecord.RECORD_ID); + assertEquals(1026, sp2.getShapeId()); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index ef90f01f40..248247266a 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -1,10 +1,10 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; -import org.apache.poi.ddf.EscherChildAnchorRecord; -import org.apache.poi.ddf.EscherClientAnchorRecord; -import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.util.HexDump; /** * @author Evgeniy Berlog @@ -12,6 +12,63 @@ import org.apache.poi.hssf.usermodel.*; */ public class TestHSSFAnchor extends TestCase { + public void testDefaultValues(){ + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(); + assertEquals(clientAnchor.getAnchorType(), 0); + assertEquals(clientAnchor.getCol1(), 0); + assertEquals(clientAnchor.getCol2(), 0); + assertEquals(clientAnchor.getDx1(), 0); + assertEquals(clientAnchor.getDx2(), 0); + assertEquals(clientAnchor.getDy1(), 0); + assertEquals(clientAnchor.getDy2(), 0); + assertEquals(clientAnchor.getRow1(), 0); + assertEquals(clientAnchor.getRow2(), 0); + + clientAnchor = new HSSFClientAnchor(new EscherClientAnchorRecord()); + assertEquals(clientAnchor.getAnchorType(), 0); + assertEquals(clientAnchor.getCol1(), 0); + assertEquals(clientAnchor.getCol2(), 0); + assertEquals(clientAnchor.getDx1(), 0); + assertEquals(clientAnchor.getDx2(), 0); + assertEquals(clientAnchor.getDy1(), 0); + assertEquals(clientAnchor.getDy2(), 0); + assertEquals(clientAnchor.getRow1(), 0); + assertEquals(clientAnchor.getRow2(), 0); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(); + assertEquals(childAnchor.getDx1(), 0); + assertEquals(childAnchor.getDx2(), 0); + assertEquals(childAnchor.getDy1(), 0); + assertEquals(childAnchor.getDy2(), 0); + + childAnchor = new HSSFChildAnchor(new EscherChildAnchorRecord()); + assertEquals(childAnchor.getDx1(), 0); + assertEquals(childAnchor.getDx2(), 0); + assertEquals(childAnchor.getDy1(), 0); + assertEquals(childAnchor.getDy2(), 0); + } + + public void testCorrectOrderInSpContainer(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("pictures"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + + HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + assertEquals(rectangle.getEscherContainer().getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); + assertEquals(rectangle.getEscherContainer().getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); + assertEquals(" " + HexDump.toHex(rectangle.getEscherContainer().getChild(2).getRecordId()) + " ", rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(rectangle.getEscherContainer().getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); + + rectangle.setAnchor(new HSSFClientAnchor()); + + assertEquals(rectangle.getEscherContainer().getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); + assertEquals(rectangle.getEscherContainer().getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); + assertEquals(" " + HexDump.toHex(rectangle.getEscherContainer().getChild(2).getRecordId()) + " ", rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(rectangle.getEscherContainer().getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); + } + public void testCreateClientAnchorFromContainer(){ EscherContainerRecord container = new EscherContainerRecord(); EscherClientAnchorRecord escher = new EscherClientAnchorRecord(); @@ -206,4 +263,116 @@ public class TestHSSFAnchor extends TestCase { assertEquals(anchor.getDy2(), 118); assertEquals(escher.getDy2(), 118); } + + public void testEqualsToSelf(){ + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertEquals(clientAnchor, clientAnchor); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); + assertEquals(childAnchor, childAnchor); + } + + public void testPassIncompatibleTypeIsFalse(){ + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertNotSame(clientAnchor, "wrongType"); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); + assertNotSame(childAnchor, "wrongType"); + } + + public void testNullReferenceIsFalse() { + HSSFClientAnchor clientAnchor = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertFalse("Passing null to equals should return false", clientAnchor.equals(null)); + + HSSFChildAnchor childAnchor = new HSSFChildAnchor(0, 1, 2, 3); + assertFalse("Passing null to equals should return false", childAnchor.equals(null)); + } + + public void testEqualsIsReflexiveIsSymmetric() { + HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + + assertTrue(clientAnchor1.equals(clientAnchor2)); + assertTrue(clientAnchor1.equals(clientAnchor2)); + + HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3); + HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3); + + assertTrue(childAnchor1.equals(childAnchor2)); + assertTrue(childAnchor2.equals(childAnchor1)); + } + + public void testEqualsValues(){ + HSSFClientAnchor clientAnchor1 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + HSSFClientAnchor clientAnchor2 = new HSSFClientAnchor(0, 1, 2, 3, (short)4, 5, (short)6, 7); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDx1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDx1(0); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDy1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDy1(1); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDx2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDx2(2); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setDy2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setDy2(3); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setCol1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setCol1(4); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setRow1(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setRow1(5); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setCol2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setCol2(6); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setRow2(10); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setRow2(7); + assertEquals(clientAnchor1, clientAnchor2); + + clientAnchor2.setAnchorType(3); + assertNotSame(clientAnchor1, clientAnchor2); + clientAnchor2.setAnchorType(0); + assertEquals(clientAnchor1, clientAnchor2); + + HSSFChildAnchor childAnchor1 = new HSSFChildAnchor(0, 1, 2, 3); + HSSFChildAnchor childAnchor2 = new HSSFChildAnchor(0, 1, 2, 3); + + childAnchor1.setDx1(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor1.setDx1(0); + assertEquals(childAnchor1, childAnchor2); + + childAnchor2.setDy1(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor2.setDy1(1); + assertEquals(childAnchor1, childAnchor2); + + childAnchor2.setDx2(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor2.setDx2(2); + assertEquals(childAnchor1, childAnchor2); + + childAnchor2.setDy2(10); + assertNotSame(childAnchor1, childAnchor2); + childAnchor2.setDy2(3); + assertEquals(childAnchor1, childAnchor2); + } } diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index ccbcc8cb4a10b6031f4b49711e404707fb947ba2..27de3b575db9c9d8b04567a1a410b869785263b3 100644 GIT binary patch literal 815104 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

3fiI3#uke-itFyOZy0 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%0AAn}be!pX70(XexjRS~= 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 =s17_5Z=f_B_{wH+hwXz@w;! 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 t|!Y#T%Xr1pkq+=E~x*m>kv644pkt+4u4I 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%0Ad~hc89q!x6aL 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%0AV`! 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

-p@;yMP{{U(CNK0vC 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�Kn;ywo?A-fgPMhR8gH|Dc!Zgzi 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€!zcNY$Czl120R*Gu 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 eBL125i2h^$XCnT|IREMO|75m*I@;Hc{fYHSO delta 827 zcmYjPUr3Wt6hHU-zI~H@hf*0CHAwN_HfOnSg=CuyVr99&k&>jz%4DOtRa!j+)fCdF zU^(y*LHH;X)Cl^(mrS9DKuCHCf)b;5dnv-y&UKT#@VkG0_nhDP-OI_Y__KdS&Q~V@ zKw^881GMo*o;SC)wu&Tx1WSRNg)u`+X;&-fCqrY?9ZMpf z{kEDrwP1Sx77MfS;+w-LxZ<2XA;9h zqYq&Z+?VR0Lt^Cm?Hl>p*3)g*U@ySh6-k4>=H^+jV~tm2C=5C54EX}NO71X&CL3`< zZ4UrFGx0h7cB4}O4FoVkF%Rw&Iwd{W>C($M)&cMdjI|7JA22k?0`$c+syT{I>$?Y) zGSs0WF1hLt%>VS`5f-R1@vfQ+fyEUL3eik+0amP+&RB7g6_dLZXM19r#fr;zqn^d& zab_Sk9l>Vu2GJA^bSa3VMuRNGBd(?COAt?rMmiM2n?_@apRuLsX$WhDkKTr`N^_Tt z_F85;F6!vxILU=O6E+eNY-eBL2<}(AiVrfaM-g1mu~~Xx4x+_4A5BKFQn+PsmG&_; ztIFq_#L-S`J&G@NbaRTlh@aX?Sv}9jJ<{MYI@^sw!?WYkk*3Gp?9y9w3BASYy_UNN z-|Og=am Date: Tue, 26 Jun 2012 11:21:13 +0000 Subject: [PATCH 13/32] implemented creating shapes in existing files git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1353960 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/record/EscherAggregate.java | 12 +- .../poi/hssf/usermodel/HSSFComment.java | 4 +- .../poi/hssf/usermodel/HSSFPatriarch.java | 38 ++- .../poi/hssf/usermodel/HSSFPolygon.java | 13 ++ .../apache/poi/hssf/usermodel/HSSFShape.java | 20 ++ .../poi/hssf/usermodel/HSSFShapeFactory.java | 40 +++- .../poi/hssf/usermodel/HSSFShapeGroup.java | 10 + .../poi/hssf/usermodel/HSSFSimpleShape.java | 79 ++++++- .../poi/hssf/usermodel/HSSFTextbox.java | 216 ++++++++++++------ .../poi/hssf/usermodel/HSSFUnknownShape.java | 10 + .../hssf/usermodel/drawing/HSSFShapeType.java | 13 +- .../poi/hssf/model/HSSFTestModelHelper.java | 13 ++ .../poi/hssf/model/TestDrawingShapes.java | 37 +++ .../poi/hssf/usermodel/HSSFTestHelper.java | 4 + .../apache/poi/hssf/usermodel/TestText.java | 186 +++++++++++++++ test-data/spreadsheet/drawings.xls | Bin 815104 -> 817664 bytes test-data/spreadsheet/empty.xls | Bin 0 -> 24576 bytes 17 files changed, 592 insertions(+), 103 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestText.java create mode 100644 test-data/spreadsheet/empty.xls diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index fb16037a37..ee75870bb8 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -323,6 +323,10 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { this.drawingManager = drawingManager; } + public DrawingManager2 getDrawingManager() { + return drawingManager; + } + /** * @return Returns the current sid. */ @@ -628,7 +632,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { /** * Associates an escher record to an OBJ record or a TXO record. */ - public Object associateShapeToObjRecord(EscherRecord r, ObjRecord objRecord) { + public Object associateShapeToObjRecord(EscherRecord r, Record objRecord) { return shapeToObj.put(r, objRecord); } @@ -1039,9 +1043,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { EscherDgRecord dg = new EscherDgRecord(); dg.setRecordId( EscherDgRecord.RECORD_ID ); short dgId = 1; - dg.setOptions( (short) ( dgId << 4 ) ); - dg.setNumShapes( 1 ); - dg.setLastMSOSPID( 1024 ); + dg.setOptions((short) (dgId << 4)); + dg.setNumShapes(1); + dg.setLastMSOSPID(1024); drawingGroupId = dg.getDrawingGroupId(); spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); spgrContainer.setOptions((short) 0x000F); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 2216971e68..f949e59fb0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -66,7 +66,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { } protected HSSFComment(NoteRecord note, TextObjectRecord txo) { - this((HSSFShape) null, (HSSFAnchor) null); + this(null, new HSSFClientAnchor()); _txo = txo; _note = note; } @@ -185,7 +185,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { /** * Returns the underlying Text record */ - protected TextObjectRecord getTextObjectRecord() { + public TextObjectRecord getTextObjectRecord() { return _txo; } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 71549bbf31..137086d9b8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -21,12 +21,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.apache.poi.ddf.EscherComplexProperty; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperty; -import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.ddf.EscherSpgrRecord; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.ss.usermodel.Chart; import org.apache.poi.util.StringUtil; @@ -93,6 +89,8 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); shape.anchor = anchor; addShape(shape); + //open existing file + onCreate(shape); return shape; } @@ -109,6 +107,8 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { shape.setPictureIndex( pictureIndex ); shape.anchor = anchor; addShape(shape); + //open existing file + onCreate(shape); EscherBSERecord bse = _sheet.getWorkbook().getWorkbook().getBSERecord(pictureIndex); bse.setRef(bse.getRef() + 1); @@ -147,6 +147,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFTextbox shape = new HSSFTextbox(null, anchor); shape.anchor = anchor; addShape(shape); + onCreate(shape); return shape; } @@ -200,6 +201,20 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { _shapes.add(shape); } + private void onCreate(HSSFShape shape){ + if(_boundAggregate.getPatriarch() == null){ + EscherContainerRecord spgrContainer = + _boundAggregate.getEscherContainer().getChildContainers().get(0); + + EscherContainerRecord spContainer = shape.getEscherContainer(); + int shapeId = newShapeId(); + shape.setShapeId(shapeId); + + spgrContainer.addChildRecord(spContainer); + shape.afterInsert(this); + } + } + /** * Total count of all children and their children's children. */ @@ -222,6 +237,17 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { _y2 = y2; } + int newShapeId() { + if (_boundAggregate.getEscherContainer() == null){ + throw new IllegalStateException("We can use this method for only existing files"); + } + DrawingManager2 dm = _boundAggregate.getDrawingManager(); + EscherDgRecord dg = + _boundAggregate.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); + short drawingGroupId = dg.getDrawingGroupId(); + return dm.allocateShapeId(drawingGroupId, dg); + } + /** * Does this HSSFPatriarch contain a chart? * (Technically a reference to a chart, since they diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index 6027fb8be7..c6dc9d7f0a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -17,6 +17,9 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.record.ObjRecord; + /** * @author Glen Stampoultzis (glens at superlinksoftware.com) */ @@ -33,6 +36,16 @@ public class HSSFPolygon super( parent, anchor ); } + @Override + protected EscherContainerRecord createSpContainer() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected ObjRecord createObjRecord() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + public int[] getXPoints() { return xPoints; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 33dfd68643..975453ad01 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.ObjRecord; /** @@ -71,6 +72,7 @@ public abstract class HSSFShape { this.anchor = anchor; this._escherContainer = new EscherContainerRecord(); _optRecord = new EscherOptRecord(); + _optRecord.setRecordId( EscherOptRecord.RECORD_ID ); _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); _optRecord.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); @@ -78,6 +80,24 @@ public abstract class HSSFShape { _optRecord.addEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); } + protected abstract EscherContainerRecord createSpContainer(); + + protected abstract ObjRecord createObjRecord(); + + void setShapeId(int shapeId){ + EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); + spRecord.setShapeId(shapeId); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + cod.setObjectId((short) (shapeId-1024)); + } + + int getShapeId(){ + return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); + } + + void afterInsert(HSSFPatriarch patriarch){ + } + public EscherContainerRecord getEscherContainer() { return _escherContainer; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 68f410d173..5c1be44b4d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -115,19 +115,37 @@ public class HSSFShapeFactory { break; } } - if (null != objRecord){ - HSSFShape shape = shapeCreator.createNewShape(spRecord.getShapeType(), container, objRecord); + CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); + HSSFShape shape = null; + switch (cmo.getObjectType()) { + case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE: + shape = new HSSFPicture(container, objRecord); + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: + shape = new HSSFSimpleShape(container, objRecord); + break; + case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: + shape = new HSSFTextbox(container, objRecord, txtRecord); + break; + default: + shape = new HSSFSimpleShape(container, objRecord); + } + if (null != shape){ out.addShape(shape); } - if (null != txtRecord){ - //TODO resolve textbox -// TextboxShape shape = new TextboxShape(container, txtRecord); -// out.a - } -// -// //TODO decide what shape to create based on ObjRecord / EscherSpRecord -// HSSFShape shape = new HSSFUnknownShape(container, objRecord); -// out.addShape(shape); +// if (null != objRecord){ +// HSSFShape shape = shapeCreator.createNewShape(spRecord.getShapeType(), container, objRecord); +// out.addShape(shape); +// } +// if (null != txtRecord){ +// //TODO resolve textbox +//// TextboxShape shape = new TextboxShape(container, txtRecord); +//// out.a +// } +//// +//// //TODO decide what shape to create based on ObjRecord / EscherSpRecord +//// HSSFShape shape = new HSSFUnknownShape(container, objRecord); +//// out.addShape(shape); } } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index b3209467ae..96b39daceb 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -74,6 +74,16 @@ public class HSSFShapeGroup _spgrRecord.setRectY2(255); } + @Override + protected EscherContainerRecord createSpContainer() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected ObjRecord createObjRecord() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + /** * Create another group under this group. * @param anchor the position of the new group. diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 6e0df0fd54..e7b2c718c6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -19,7 +19,13 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.EndSubRecord; +import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; + +import java.util.HashMap; +import java.util.Map; /** * Represents a simple shape such as a line, rectangle or oval. @@ -56,17 +62,69 @@ public class HSSFSimpleShape int shapeType = OBJECT_TYPE_LINE; + private static final Map objTypeToShapeType = new HashMap(); + + static { + objTypeToShapeType.put(OBJECT_TYPE_RECTANGLE, HSSFShapeType.RECTANGLE.getType()); + objTypeToShapeType.put(OBJECT_TYPE_PICTURE, HSSFShapeType.PICTURE.getType()); + objTypeToShapeType.put(OBJECT_TYPE_LINE, HSSFShapeType.LINE.getType()); + } + public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { super(spContainer, objRecord); - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); - setShapeType(cod.getObjectType()); } public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) { super( parent, anchor ); + _escherContainer = createSpContainer(); + _objRecord = createObjRecord(); + setShapeType(OBJECT_TYPE_LINE); } + @Override + protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spContainer = new EscherContainerRecord(); + spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); + spContainer.setOptions( (short) 0x000F ); + + EscherSpRecord sp = new EscherSpRecord(); + sp.setRecordId( EscherSpRecord.RECORD_ID ); + sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE ); + + EscherClientDataRecord clientData = new EscherClientDataRecord(); + clientData.setRecordId( EscherClientDataRecord.RECORD_ID ); + clientData.setOptions( (short) 0x0000 ); + + spContainer.addChildRecord(sp); + spContainer.addChildRecord(_optRecord); + spContainer.addChildRecord(anchor.getEscherAnchor()); + spContainer.addChildRecord(clientData); + return spContainer; + } + + @Override + protected ObjRecord createObjRecord() { + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setLocked(true); + c.setPrintable(true); + c.setAutofill(true); + c.setAutoline(true); + EndSubRecord e = new EndSubRecord(); + + obj.addSubRecord(c); + obj.addSubRecord(e); + return obj; + } + + @Override + void afterInsert(HSSFPatriarch patriarch){ + EscherAggregate agg = patriarch._getBoundAggregate(); + agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + } + + /** * Gets the shape type. * @return One of the OBJECT_TYPE_* constants. @@ -77,7 +135,10 @@ public class HSSFSimpleShape * @see #OBJECT_TYPE_PICTURE * @see #OBJECT_TYPE_COMMENT */ - public int getShapeType() { return shapeType; } + public int getShapeType() { + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + return cod.getObjectType(); + } /** * Sets the shape types. @@ -90,6 +151,14 @@ public class HSSFSimpleShape * @see #OBJECT_TYPE_PICTURE * @see #OBJECT_TYPE_COMMENT */ - public void setShapeType( int shapeType ){ this.shapeType = shapeType; } - + public void setShapeType( int shapeType ){ + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + cod.setObjectType((short) shapeType); + EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); + if (null == objTypeToShapeType.get((short)shapeType)){ + System.out.println("Unknown shape type: "+shapeType); + return; + } + spRecord.setShapeType(objTypeToShapeType.get((short)shapeType)); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 2548bf5114..00dfe9590c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -17,6 +17,8 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.*; import org.apache.poi.ss.usermodel.RichTextString; /** @@ -24,163 +26,233 @@ import org.apache.poi.ss.usermodel.RichTextString; * * @author Glen Stampoultzis (glens at apache.org) */ -public class HSSFTextbox - extends HSSFSimpleShape -{ - public final static short OBJECT_TYPE_TEXT = 6; +public class HSSFTextbox extends HSSFSimpleShape { + public final static short OBJECT_TYPE_TEXT = 6; /** * How to align text horizontally */ - public final static short HORIZONTAL_ALIGNMENT_LEFT = 1; - public final static short HORIZONTAL_ALIGNMENT_CENTERED = 2; - public final static short HORIZONTAL_ALIGNMENT_RIGHT = 3; - public final static short HORIZONTAL_ALIGNMENT_JUSTIFIED = 4; - public final static short HORIZONTAL_ALIGNMENT_DISTRIBUTED = 7; + public final static short HORIZONTAL_ALIGNMENT_LEFT = 1; + public final static short HORIZONTAL_ALIGNMENT_CENTERED = 2; + public final static short HORIZONTAL_ALIGNMENT_RIGHT = 3; + public final static short HORIZONTAL_ALIGNMENT_JUSTIFIED = 4; + public final static short HORIZONTAL_ALIGNMENT_DISTRIBUTED = 7; /** * How to align text vertically */ - public final static short VERTICAL_ALIGNMENT_TOP = 1; - public final static short VERTICAL_ALIGNMENT_CENTER = 2; - public final static short VERTICAL_ALIGNMENT_BOTTOM = 3; - public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4; - public final static short VERTICAL_ALIGNMENT_DISTRIBUTED= 7; + public final static short VERTICAL_ALIGNMENT_TOP = 1; + public final static short VERTICAL_ALIGNMENT_CENTER = 2; + public final static short VERTICAL_ALIGNMENT_BOTTOM = 3; + public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4; + public final static short VERTICAL_ALIGNMENT_DISTRIBUTED = 7; int marginLeft, marginRight, marginTop, marginBottom; short halign, valign; + private TextObjectRecord _textObjectRecord; + + public HSSFTextbox(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) { + super(spContainer, objRecord); + this._textObjectRecord = textObjectRecord; + } + HSSFRichTextString string = new HSSFRichTextString(""); /** * Construct a new textbox with the given parent and anchor. + * * @param parent - * @param anchor One of HSSFClientAnchor or HSSFChildAnchor + * @param anchor One of HSSFClientAnchor or HSSFChildAnchor */ - public HSSFTextbox( HSSFShape parent, HSSFAnchor anchor ) - { - super( parent, anchor ); - setShapeType(OBJECT_TYPE_TEXT); + public HSSFTextbox(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); + _textObjectRecord = createTextObjRecord(); + setHorizontalAlignment(HORIZONTAL_ALIGNMENT_LEFT); + setVerticalAlignment(VERTICAL_ALIGNMENT_TOP); + setString(new HSSFRichTextString("")); - halign = HORIZONTAL_ALIGNMENT_LEFT; - valign = VERTICAL_ALIGNMENT_TOP; + } + + protected TextObjectRecord createTextObjRecord(){ + TextObjectRecord obj = new TextObjectRecord(); + obj.setTextLocked(true); + obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE); + return obj; + } + + @Override + protected ObjRecord createObjRecord() { + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setObjectType(OBJECT_TYPE_TEXT); + c.setLocked( true ); + c.setPrintable( true ); + c.setAutofill( true ); + c.setAutoline( true ); + EndSubRecord e = new EndSubRecord(); + obj.addSubRecord( c ); + obj.addSubRecord( e ); + return obj; + } + + @Override + protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spContainer = new EscherContainerRecord(); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherClientDataRecord clientData = new EscherClientDataRecord(); + EscherTextboxRecord escherTextbox = new EscherTextboxRecord(); + + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) ((EscherAggregate.ST_TEXTBOX << 4) | 0x2)); + + sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTID, 0)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, getMarginLeft())); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, getMarginRight())); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, getMarginBottom())); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, getMarginTop())); + + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, 0)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__ANCHORTEXT, 0)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); + + EscherRecord anchor = getAnchor().getEscherAnchor(); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); + escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID); + escherTextbox.setOptions((short) 0x0000); + + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); + spContainer.addChildRecord(escherTextbox); + + return spContainer; + } + + @Override + void afterInsert(HSSFPatriarch patriarch){ + EscherAggregate agg = patriarch._getBoundAggregate(); + agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord()); } /** - * @return the rich text string for this textbox. + * @return the rich text string for this textbox. */ - public HSSFRichTextString getString() - { - return string; + public HSSFRichTextString getString() { + return _textObjectRecord.getStr(); } /** - * @param string Sets the rich text string used by this object. + * @param string Sets the rich text string used by this object. */ - public void setString( RichTextString string ) - { - HSSFRichTextString rtr = (HSSFRichTextString)string; - + public void setString(RichTextString string) { + HSSFRichTextString rtr = (HSSFRichTextString) string; // If font is not set we must set the default one - if (rtr.numFormattingRuns() == 0) rtr.applyFont((short)0); - - this.string = rtr; + if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); + _textObjectRecord.setStr(rtr); } /** - * @return Returns the left margin within the textbox. + * @return Returns the left margin within the textbox. */ - public int getMarginLeft() - { - return marginLeft; + public int getMarginLeft() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTLEFT); + return property == null ? 0: property.getPropertyValue(); } /** * Sets the left margin within the textbox. */ - public void setMarginLeft( int marginLeft ) - { - this.marginLeft = marginLeft; + public void setMarginLeft(int marginLeft) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, marginLeft)); } /** - * @return returns the right margin within the textbox. + * @return returns the right margin within the textbox. */ - public int getMarginRight() - { - return marginRight; + public int getMarginRight() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTRIGHT); + return property == null ? 0: property.getPropertyValue(); } /** * Sets the right margin within the textbox. */ - public void setMarginRight( int marginRight ) - { - this.marginRight = marginRight; + public void setMarginRight(int marginRight) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, marginRight)); } /** - * @return returns the top margin within the textbox. + * @return returns the top margin within the textbox. */ - public int getMarginTop() - { - return marginTop; + public int getMarginTop() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTTOP); + return property == null ? 0: property.getPropertyValue(); } /** * Sets the top margin within the textbox. */ - public void setMarginTop( int marginTop ) - { - this.marginTop = marginTop; + public void setMarginTop(int marginTop) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, marginTop)); } /** * Gets the bottom margin within the textbox. */ - public int getMarginBottom() - { - return marginBottom; + public int getMarginBottom() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTBOTTOM); + return property == null ? 0: property.getPropertyValue(); } /** * Sets the bottom margin within the textbox. */ - public void setMarginBottom( int marginBottom ) - { - this.marginBottom = marginBottom; + public void setMarginBottom(int marginBottom) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, marginBottom)); } /** * Gets the horizontal alignment. */ - public short getHorizontalAlignment() - { - return halign; + public short getHorizontalAlignment() { + return (short) _textObjectRecord.getHorizontalTextAlignment(); } /** * Sets the horizontal alignment. */ - public void setHorizontalAlignment( short align ) - { - this.halign = align; + public void setHorizontalAlignment(short align) { + _textObjectRecord.setHorizontalTextAlignment(align); } /** * Gets the vertical alignment. */ - public short getVerticalAlignment() - { - return valign; + public short getVerticalAlignment() { + return (short) _textObjectRecord.getVerticalTextAlignment(); } /** * Sets the vertical alignment. */ - public void setVerticalAlignment( short align ) - { - this.valign = align; + public void setVerticalAlignment(short align) { + _textObjectRecord.setVerticalTextAlignment(align); } + + public TextObjectRecord getTextObjectRecord() { + return _textObjectRecord; + } + + @Override + public void setShapeType(int shapeType) {/**DO NOTHING**/} } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java index d4cac9be9a..406dfe7219 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java @@ -30,4 +30,14 @@ public class HSSFUnknownShape extends HSSFShape { public HSSFUnknownShape(EscherRecord spContainer, ObjRecord objRecord) { super((EscherContainerRecord) spContainer, objRecord); } + + @Override + protected EscherContainerRecord createSpContainer() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected ObjRecord createObjRecord() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java index c63a08b7e5..2e2b64eeb4 100644 --- a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -2,6 +2,7 @@ package org.apache.poi.hssf.usermodel.drawing; import org.apache.poi.hssf.usermodel.HSSFPicture; import org.apache.poi.hssf.usermodel.HSSFSimpleShape; +import org.apache.poi.hssf.usermodel.HSSFTextbox; /** * @author Evgeniy Berlog @@ -11,16 +12,18 @@ public enum HSSFShapeType { NOT_PRIMITIVE((short)0x0, null, (short)0), RECTANGLE((short)0x1, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_RECTANGLE), PICTURE((short)0x004B, HSSFPicture.class, HSSFSimpleShape.OBJECT_TYPE_PICTURE), + LINE((short)0x14, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_LINE), + TEXT((short)202, HSSFTextbox.class, HSSFTextbox.OBJECT_TYPE_TEXT), ROUND_RECTANGLE((short)0x2, null, null); private Short type; private Class shape; - private Short objectId; + private Short objectType; - private HSSFShapeType(Short type, Class shape, Short objectId) { + private HSSFShapeType(Short type, Class shape, Short objectType) { this.type = type; this.shape = shape; - this.objectId = objectId; + this.objectType = objectType; } public Short getType() { @@ -30,4 +33,8 @@ public enum HSSFShapeType { public Class getShape() { return shape; } + + public Short getObjectType() { + return objectType; + } } diff --git a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java new file mode 100644 index 0000000000..cca8f2d635 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java @@ -0,0 +1,13 @@ +package org.apache.poi.hssf.model; + +import org.apache.poi.hssf.usermodel.HSSFTextbox; + +/** + * @author Evgeniy Berlog + * @date 25.06.12 + */ +public class HSSFTestModelHelper { + public static TextboxShape createTextboxShape(int shapeId, HSSFTextbox textbox){ + return new TextboxShape(textbox, shapeId); + } +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 097d5d01ee..1beeabe94b 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -251,4 +251,41 @@ public class TestDrawingShapes extends TestCase{ ((EscherContainerRecord)spgrContainer.getChild(2)).getChildById(EscherSpRecord.RECORD_ID); assertEquals(1026, sp2.getShapeId()); } + + /** + * Test get new id for shapes from existing file + * File already have for 1 shape on each sheet, because document must contain EscherDgRecord for each sheet + */ + public void testAllocateNewIds(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("empty.xls"); + HSSFSheet sheet = wb.getSheetAt(0); + HSSFPatriarch patriarch = sheet.getDrawingPatriarch(); + + /** + * 2048 - main SpContainer id + * 2049 - existing shape id + */ + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2050); + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2051); + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 2052); + + sheet = wb.getSheetAt(1); + patriarch = sheet.getDrawingPatriarch(); + + /** + * 3072 - main SpContainer id + * 3073 - existing shape id + */ + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3074); + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3075); + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 3076); + + + sheet = wb.getSheetAt(2); + patriarch = sheet.getDrawingPatriarch(); + + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1026); + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1027); + assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1028); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 2d6b14b79a..496139eaab 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -43,4 +43,8 @@ public class HSSFTestHelper { public static EscherAggregate getEscherAggregate(HSSFPatriarch patriarch){ return patriarch._getBoundAggregate(); } + + public static int allocateNewShapeId(HSSFPatriarch patriarch){ + return patriarch.newShapeId(); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java new file mode 100644 index 0000000000..213c5be674 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java @@ -0,0 +1,186 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.model.HSSFTestModelHelper; +import org.apache.poi.hssf.model.TextboxShape; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.TextObjectRecord; + +import java.util.Arrays; + +/** + * @author Evgeniy Berlog + * @date 25.06.12 + */ +public class TestText extends TestCase { + + public void testResultEqualsToAbstractShape() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + TextboxShape textboxShape = HSSFTestModelHelper.createTextboxShape(0, textbox); + + assertEquals(textbox.getEscherContainer().getChildRecords().size(), 5); + assertEquals(textboxShape.getSpContainer().getChildRecords().size(), 5); + + //sp record + byte[] expected = textboxShape.getSpContainer().getChild(0).serialize(); + byte[] actual = textbox.getEscherContainer().getChild(0).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = textboxShape.getSpContainer().getChild(2).serialize(); + actual = textbox.getEscherContainer().getChild(2).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = textboxShape.getSpContainer().getChild(3).serialize(); + actual = textbox.getEscherContainer().getChild(3).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = textboxShape.getSpContainer().getChild(4).serialize(); + actual = textbox.getEscherContainer().getChild(4).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + ObjRecord obj = textbox.getObjRecord(); + ((CommonObjectDataSubRecord) obj.getSubRecords().get(0)).setObjectId(-1024); + ObjRecord objShape = textboxShape.getObjRecord(); + + expected = obj.serialize(); + actual = objShape.serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + TextObjectRecord tor = textbox.getTextObjectRecord(); + TextObjectRecord torShape = textboxShape.getTextObjectRecord(); + + expected = tor.serialize(); + actual = torShape.serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + } + + public void testAddTextToExistingFile() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + textbox.setString(new HSSFRichTextString("just for test")); + HSSFTextbox textbox2 = patriarch.createTextbox(new HSSFClientAnchor()); + textbox2.setString(new HSSFRichTextString("just for test2")); + + assertEquals(patriarch.getChildren().size(), 2); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + HSSFTextbox text3 = patriarch.createTextbox(new HSSFClientAnchor()); + text3.setString(new HSSFRichTextString("text3")); + assertEquals(patriarch.getChildren().size(), 3); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test"); + assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2"); + assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3"); + } + + public void testSetGetProperties() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + textbox.setString(new HSSFRichTextString("test")); + assertEquals(textbox.getString().getString(), "test"); + + textbox.setHorizontalAlignment((short) 5); + assertEquals(textbox.getHorizontalAlignment(), 5); + + textbox.setVerticalAlignment((short) 6); + assertEquals(textbox.getVerticalAlignment(), (short) 6); + + textbox.setMarginBottom(7); + assertEquals(textbox.getMarginBottom(), 7); + + textbox.setMarginLeft(8); + assertEquals(textbox.getMarginLeft(), 8); + + textbox.setMarginRight(9); + assertEquals(textbox.getMarginRight(), 9); + + textbox.setMarginTop(10); + assertEquals(textbox.getMarginTop(), 10); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + textbox = (HSSFTextbox) patriarch.getChildren().get(0); + assertEquals(textbox.getString().getString(), "test"); + assertEquals(textbox.getHorizontalAlignment(), 5); + assertEquals(textbox.getVerticalAlignment(), (short) 6); + assertEquals(textbox.getMarginBottom(), 7); + assertEquals(textbox.getMarginLeft(), 8); + assertEquals(textbox.getMarginRight(), 9); + assertEquals(textbox.getMarginTop(), 10); + + textbox.setString(new HSSFRichTextString("test1")); + textbox.setHorizontalAlignment(HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); + textbox.setVerticalAlignment(HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + textbox.setMarginBottom(71); + textbox.setMarginLeft(81); + textbox.setMarginRight(91); + textbox.setMarginTop(101); + + assertEquals(textbox.getString().getString(), "test1"); + assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); + assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + assertEquals(textbox.getMarginBottom(), 71); + assertEquals(textbox.getMarginLeft(), 81); + assertEquals(textbox.getMarginRight(), 91); + assertEquals(textbox.getMarginTop(), 101); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + textbox = (HSSFTextbox) patriarch.getChildren().get(0); + + assertEquals(textbox.getString().getString(), "test1"); + assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_CENTERED); + assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + assertEquals(textbox.getMarginBottom(), 71); + assertEquals(textbox.getMarginLeft(), 81); + assertEquals(textbox.getMarginRight(), 91); + assertEquals(textbox.getMarginTop(), 101); + } + + public void testExistingFileWithText(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("text"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + HSSFTextbox textbox = (HSSFTextbox) drawing.getChildren().get(0); + assertEquals(textbox.getHorizontalAlignment(), HSSFTextbox.HORIZONTAL_ALIGNMENT_LEFT); + assertEquals(textbox.getVerticalAlignment(), HSSFTextbox.VERTICAL_ALIGNMENT_TOP); + assertEquals(textbox.getMarginTop(), 0); + assertEquals(textbox.getMarginBottom(), 3600000); + assertEquals(textbox.getMarginLeft(), 3600000); + assertEquals(textbox.getMarginRight(), 0); + assertEquals(textbox.getString().getString(), "teeeeesssstttt"); + } +} diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index 27de3b575db9c9d8b04567a1a410b869785263b3..8ea863f59a6eb022c8a5cfa3946adec55f443e46 100644 GIT binary patch delta 4422 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 Wmv(X_iqOTFvWZMR=(LuoV*DRPI@??T delta 3102 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 Date: Thu, 28 Jun 2012 10:56:55 +0000 Subject: [PATCH 14/32] implemented creating comments in existing files, bugfixes git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1354910 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ddf/AbstractEscherOptRecord.java | 23 +- .../poi/hssf/record/EscherAggregate.java | 11 + .../poi/hssf/usermodel/HSSFComment.java | 129 ++++++---- .../poi/hssf/usermodel/HSSFPatriarch.java | 1 + .../poi/hssf/usermodel/HSSFPolygon.java | 11 +- .../apache/poi/hssf/usermodel/HSSFShape.java | 39 ++- .../poi/hssf/usermodel/HSSFShapeFactory.java | 3 + .../poi/hssf/usermodel/HSSFShapeGroup.java | 14 +- .../apache/poi/hssf/usermodel/HSSFSheet.java | 23 ++ .../poi/hssf/usermodel/HSSFSimpleShape.java | 11 +- .../poi/hssf/usermodel/HSSFTextbox.java | 17 +- .../poi/hssf/model/HSSFTestModelHelper.java | 5 + .../poi/hssf/model/TestDrawingShapes.java | 92 +++++-- .../poi/hssf/usermodel/HSSFTestHelper.java | 5 + .../poi/hssf/usermodel/TestComment.java | 241 ++++++++++++++++++ .../poi/hssf/usermodel/TestHSSFComment.java | 2 +- test-data/spreadsheet/drawings.xls | Bin 817664 -> 818688 bytes 17 files changed, 494 insertions(+), 133 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestComment.java diff --git a/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java b/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java index a86fbda669..dbf4a6dad2 100644 --- a/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java +++ b/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java @@ -16,10 +16,7 @@ ==================================================================== */ package org.apache.poi.ddf; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import java.util.*; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndian; @@ -139,6 +136,24 @@ public abstract class AbstractEscherOptRecord extends EscherRecord } ); } + /** + * Set an escher property. If a property with given propId already + exists it is replaced. + * + * @param value the property to set. + */ + public void setEscherProperty(EscherProperty value){ + for ( Iterator iterator = + properties.iterator(); iterator.hasNext(); ) { + EscherProperty prop = iterator.next(); + if (prop.getId() == value.getId()){ + iterator.remove(); + } + } + properties.add( value ); + sortProperties(); + } + /** * Retrieve the string representation of this record. */ diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index ee75870bb8..b5bb2121a0 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -1152,4 +1152,15 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public List getTailRecords(){ return Collections.unmodifiableList(tailRec); } + + public NoteRecord getNoteRecordByObj(ObjRecord obj){ + for (Record rec: tailRec){ + NoteRecord note = (NoteRecord) rec; + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) obj.getSubRecords().get(0); + if (note.getShapeId() == cod.getObjectId()){ + return note; + } + } + return null; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index f949e59fb0..23a792f365 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -16,8 +16,8 @@ ==================================================================== */ package org.apache.poi.hssf.usermodel; -import org.apache.poi.hssf.record.NoteRecord; -import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.record.*; import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.RichTextString; @@ -28,59 +28,89 @@ import org.apache.poi.ss.usermodel.RichTextString; */ public class HSSFComment extends HSSFTextbox implements Comment { - /* - * TODO - make HSSFComment more consistent when created vs read from file. - * Currently HSSFComment has two main forms (corresponding to the two constructors). There - * are certain operations that only work on comment objects in one of the forms (e.g. deleting - * comments). - * POI is also deficient in its management of RowRecord fields firstCol and lastCol. Those - * fields are supposed to take comments into account, but POI does not do this yet (feb 2009). - * It seems like HSSFRow should manage a collection of local HSSFComments - */ - + /* + * TODO - make HSSFComment more consistent when created vs read from file. + * Currently HSSFComment has two main forms (corresponding to the two constructors). There + * are certain operations that only work on comment objects in one of the forms (e.g. deleting + * comments). + * POI is also deficient in its management of RowRecord fields firstCol and lastCol. Those + * fields are supposed to take comments into account, but POI does not do this yet (feb 2009). + * It seems like HSSFRow should manage a collection of local HSSFComments + */ + private boolean _visible; private int _row; private int _col; private String _author; private NoteRecord _note; - private TextObjectRecord _txo; + + public HSSFComment(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord, NoteRecord _note) { + super(spContainer, objRecord, textObjectRecord); + this._note = _note; + } /** * Construct a new comment with the given parent and anchor. * * @param parent - * @param anchor defines position of this anchor in the sheet + * @param anchor defines position of this anchor in the sheet */ public HSSFComment(HSSFShape parent, HSSFAnchor anchor) { super(parent, anchor); - setShapeType(OBJECT_TYPE_COMMENT); - + _note = createNoteRecord(); //default color for comments setFillColor(0x08000050); //by default comments are hidden - _visible = false; - - _author = ""; + setVisible(false); + setAuthor(""); } protected HSSFComment(NoteRecord note, TextObjectRecord txo) { this(null, new HSSFClientAnchor()); - _txo = txo; + _textObjectRecord = txo; _note = note; } + @Override + protected ObjRecord createObjRecord() { + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setObjectType(OBJECT_TYPE_COMMENT); + c.setLocked(true); + c.setPrintable(true); + c.setAutofill(false); + c.setAutoline(true); + + NoteStructureSubRecord u = new NoteStructureSubRecord(); + EndSubRecord e = new EndSubRecord(); + obj.addSubRecord(c); + obj.addSubRecord(u); + obj.addSubRecord(e); + return obj; + } + + private NoteRecord createNoteRecord(){ + NoteRecord note = new NoteRecord(); + note.setFlags(NoteRecord.NOTE_VISIBLE); + note.setAuthor(""); + return note; + } + + @Override + void setShapeId(int shapeId) { + super.setShapeId(shapeId); + _note.setShapeId(shapeId-1024); + } + /** * Returns whether this comment is visible. * * @param visible true if the comment is visible, false otherwise */ - public void setVisible(boolean visible){ - if(_note != null) { - _note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN); - } - _visible = visible; + public void setVisible(boolean visible) { + _note.setFlags(visible ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN); } /** @@ -89,7 +119,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { * @return true if the comment is visible, false otherwise */ public boolean isVisible() { - return _visible; + return _note.getFlags() == NoteRecord.NOTE_VISIBLE; } /** @@ -98,7 +128,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { * @return the 0-based row of the cell that contains the comment */ public int getRow() { - return _row; + return _note.getRow(); } /** @@ -107,10 +137,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { * @param row the 0-based row of the cell that contains the comment */ public void setRow(int row) { - if(_note != null) { - _note.setRow(row); - } - _row = row; + _note.setRow(row); } /** @@ -118,8 +145,8 @@ public class HSSFComment extends HSSFTextbox implements Comment { * * @return the 0-based column of the cell that contains the comment */ - public int getColumn(){ - return _col; + public int getColumn() { + return _note.getColumn(); } /** @@ -128,17 +155,15 @@ public class HSSFComment extends HSSFTextbox implements Comment { * @param col the 0-based column of the cell that contains the comment */ public void setColumn(int col) { - if(_note != null) { - _note.setColumn(col); - } - _col = col; + _note.setColumn(col); } + /** * @deprecated (Nov 2009) use {@link HSSFComment#setColumn(int)} } */ @Deprecated public void setColumn(short col) { - setColumn((int)col); + setColumn((int) col); } /** @@ -147,7 +172,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { * @return the name of the original author of the comment */ public String getAuthor() { - return _author; + return _note.getAuthor(); } /** @@ -155,37 +180,35 @@ public class HSSFComment extends HSSFTextbox implements Comment { * * @param author the name of the original author of the comment */ - public void setAuthor(String author){ - if(_note != null) _note.setAuthor(author); - this._author = author; + public void setAuthor(String author) { + if (_note != null) _note.setAuthor(author); } - + /** * Sets the rich text string used by this comment. * - * @param string Sets the rich text string used by this object. + * @param string Sets the rich text string used by this object. */ public void setString(RichTextString string) { HSSFRichTextString hstring = (HSSFRichTextString) string; //if font is not set we must set the default one - if (hstring.numFormattingRuns() == 0) hstring.applyFont((short)0); + if (hstring.numFormattingRuns() == 0) hstring.applyFont((short) 0); - if (_txo != null) { - _txo.setStr(hstring); - } + _textObjectRecord.setStr(hstring); super.setString(string); } - + /** * Returns the underlying Note record */ protected NoteRecord getNoteRecord() { - return _note; - } + return _note; + } + /** * Returns the underlying Text record */ public TextObjectRecord getTextObjectRecord() { - return _txo; - } + return _textObjectRecord; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 137086d9b8..bc3eebc1b3 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -163,6 +163,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFComment shape = new HSSFComment(null, anchor); shape.anchor = anchor; addShape(shape); + onCreate(shape); return shape; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index c6dc9d7f0a..33f17d7e48 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.hssf.record.ObjRecord; /** @@ -38,12 +39,18 @@ public class HSSFPolygon @Override protected EscherContainerRecord createSpContainer() { - return null; //To change body of implemented methods use File | Settings | File Templates. + EscherContainerRecord spContainer = new EscherContainerRecord(); + spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); + spContainer.setOptions( (short) 0x000F ); + EscherOptRecord optRecord = new EscherOptRecord(); + optRecord.setRecordId(EscherOptRecord.RECORD_ID); + spContainer.addChildRecord(optRecord); + return spContainer; } @Override protected ObjRecord createObjRecord() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public int[] getXPoints() diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 975453ad01..9c2775373f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -53,8 +53,8 @@ public abstract class HSSFShape { HSSFAnchor anchor; HSSFPatriarch _patriarch; - protected EscherContainerRecord _escherContainer; - protected ObjRecord _objRecord; + protected final EscherContainerRecord _escherContainer; + protected final ObjRecord _objRecord; protected final EscherOptRecord _optRecord; public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord) { @@ -70,14 +70,11 @@ public abstract class HSSFShape { public HSSFShape(HSSFShape parent, HSSFAnchor anchor) { this.parent = parent; this.anchor = anchor; - this._escherContainer = new EscherContainerRecord(); - _optRecord = new EscherOptRecord(); - _optRecord.setRecordId( EscherOptRecord.RECORD_ID ); - _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); - _optRecord.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); - _optRecord.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); - _optRecord.addEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - _optRecord.addEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + this._escherContainer = createSpContainer(); + _optRecord = _escherContainer.getChildById(EscherOptRecord.RECORD_ID); + addStandardOptions(_optRecord); + _objRecord = createObjRecord(); + } protected abstract EscherContainerRecord createSpContainer(); @@ -90,6 +87,14 @@ public abstract class HSSFShape { CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); cod.setObjectId((short) (shapeId-1024)); } + + private void addStandardOptions(EscherOptRecord optRecord){ + setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + } int getShapeId(){ return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); @@ -270,19 +275,7 @@ public abstract class HSSFShape { } protected void setPropertyValue(EscherProperty property){ - if (null == _optRecord.lookup(property.getId())){ - _optRecord.addEscherProperty(property); - } else { - int i=0; - for (EscherProperty prop: _optRecord.getEscherProperties()){ - if (prop.getId() == property.getId()){ - _optRecord.getEscherProperties().remove(i); - break; - } - i++; - } - _optRecord.addEscherProperty(property); - } + _optRecord.setEscherProperty(property); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 5c1be44b4d..5358f4868f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -127,6 +127,9 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: shape = new HSSFTextbox(container, objRecord, txtRecord); break; + case CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT: + shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord)); + break; default: shape = new HSSFSimpleShape(container, objRecord); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 96b39daceb..d98471e33a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -17,11 +17,7 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherChildAnchorRecord; -import org.apache.poi.ddf.EscherClientAnchorRecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSpgrRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.model.TextboxShape; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; @@ -76,7 +72,13 @@ public class HSSFShapeGroup @Override protected EscherContainerRecord createSpContainer() { - return null; //To change body of implemented methods use File | Settings | File Templates. + EscherContainerRecord spContainer = new EscherContainerRecord(); + spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); + spContainer.setOptions( (short) 0x000F ); + EscherOptRecord optRecord = new EscherOptRecord(); + optRecord.setRecordId(EscherOptRecord.RECORD_ID); + spContainer.addChildRecord(optRecord); + return spContainer; } @Override diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index da7a404b28..cbfb1807d1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -2007,4 +2007,27 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { return new HSSFAutoFilter(this); } + protected HSSFComment findCellComment(int row, int column) { + return lookForComment(getDrawingPatriarch(), row, column); + } + + private HSSFComment lookForComment(HSSFShapeContainer container, int row, int column){ + for (Object object: container.getChildren()){ + HSSFShape shape = (HSSFShape) object; + if (shape instanceof HSSFShapeGroup){ + HSSFShape res = lookForComment((HSSFShapeContainer) shape, row, column); + if (null != res){ + return (HSSFComment) res; + } + continue; + } + if (shape instanceof HSSFComment){ + HSSFComment comment = (HSSFComment) shape; + if (comment.getColumn() == column && comment.getRow() == row){ + return comment; + } + } + } + return null; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index e7b2c718c6..2b64faaa5a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -60,8 +60,6 @@ public class HSSFSimpleShape public final static short OBJECT_TYPE_COMMENT = 25; // public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; - int shapeType = OBJECT_TYPE_LINE; - private static final Map objTypeToShapeType = new HashMap(); static { @@ -77,8 +75,6 @@ public class HSSFSimpleShape public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) { super( parent, anchor ); - _escherContainer = createSpContainer(); - _objRecord = createObjRecord(); setShapeType(OBJECT_TYPE_LINE); } @@ -96,8 +92,11 @@ public class HSSFSimpleShape clientData.setRecordId( EscherClientDataRecord.RECORD_ID ); clientData.setOptions( (short) 0x0000 ); + EscherOptRecord optRecord = new EscherOptRecord(); + optRecord.setRecordId( EscherOptRecord.RECORD_ID ); + spContainer.addChildRecord(sp); - spContainer.addChildRecord(_optRecord); + spContainer.addChildRecord(optRecord); spContainer.addChildRecord(anchor.getEscherAnchor()); spContainer.addChildRecord(clientData); return spContainer; @@ -159,6 +158,6 @@ public class HSSFSimpleShape System.out.println("Unknown shape type: "+shapeType); return; } - spRecord.setShapeType(objTypeToShapeType.get((short)shapeType)); + spRecord.setShapeType(objTypeToShapeType.get((short) shapeType)); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 00dfe9590c..42385a87ed 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -47,11 +47,7 @@ public class HSSFTextbox extends HSSFSimpleShape { public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4; public final static short VERTICAL_ALIGNMENT_DISTRIBUTED = 7; - - int marginLeft, marginRight, marginTop, marginBottom; - short halign, valign; - - private TextObjectRecord _textObjectRecord; + protected TextObjectRecord _textObjectRecord; public HSSFTextbox(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) { super(spContainer, objRecord); @@ -113,15 +109,16 @@ public class HSSFTextbox extends HSSFSimpleShape { sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); opt.setRecordId(EscherOptRecord.RECORD_ID); opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTID, 0)); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, getMarginLeft())); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, getMarginRight())); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, getMarginBottom())); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, getMarginTop())); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, 0)); opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__ANCHORTEXT, 0)); opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTLEFT, 0)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTRIGHT, 0)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, 0)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, 0)); + + EscherRecord anchor = getAnchor().getEscherAnchor(); clientData.setRecordId(EscherClientDataRecord.RECORD_ID); clientData.setOptions((short) 0x0000); diff --git a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java index cca8f2d635..507561e7e4 100644 --- a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java +++ b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java @@ -1,5 +1,6 @@ package org.apache.poi.hssf.model; +import org.apache.poi.hssf.usermodel.HSSFComment; import org.apache.poi.hssf.usermodel.HSSFTextbox; /** @@ -10,4 +11,8 @@ public class HSSFTestModelHelper { public static TextboxShape createTextboxShape(int shapeId, HSSFTextbox textbox){ return new TextboxShape(textbox, shapeId); } + + public static CommentShape createCommentShape(int shapeId, HSSFComment comment){ + return new CommentShape(comment, shapeId); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 1beeabe94b..4e120a7cb8 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -17,7 +17,7 @@ import static junit.framework.Assert.assertEquals; * @author Evgeniy Berlog * date: 12.06.12 */ -public class TestDrawingShapes extends TestCase{ +public class TestDrawingShapes extends TestCase { /** * HSSFShape tree bust be built correctly @@ -33,7 +33,7 @@ public class TestDrawingShapes extends TestCase{ * ----shape * ----shape */ - public void testDrawingGroups(){ + public void testDrawingGroups() { HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); HSSFSheet sheet = wb.getSheet("groups"); HSSFPatriarch patriarch = sheet.getDrawingPatriarch(); @@ -47,7 +47,7 @@ public class TestDrawingShapes extends TestCase{ } public void testHSSFShapeCompatibility() { - HSSFShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor()); + HSSFShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor()); assertEquals(0x08000040, shape.getLineStyleColor()); assertEquals(0x08000009, shape.getFillColor()); assertEquals(HSSFShape.LINEWIDTH_DEFAULT, shape.getLineWidth()); @@ -61,22 +61,22 @@ public class TestDrawingShapes extends TestCase{ assertEquals(7, opt.getEscherProperties().size()); assertEquals(true, - ((EscherBoolProperty)opt.lookup(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE)).isTrue()); + ((EscherBoolProperty) opt.lookup(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE)).isTrue()); assertEquals(0x00000004, - ((EscherSimpleProperty)opt.lookup(EscherProperties.GEOMETRY__SHAPEPATH)).getPropertyValue()); + ((EscherSimpleProperty) opt.lookup(EscherProperties.GEOMETRY__SHAPEPATH)).getPropertyValue()); assertEquals(0x08000009, - ((EscherSimpleProperty)opt.lookup(EscherProperties.FILL__FILLCOLOR)).getPropertyValue()); + ((EscherSimpleProperty) opt.lookup(EscherProperties.FILL__FILLCOLOR)).getPropertyValue()); assertEquals(true, - ((EscherBoolProperty)opt.lookup(EscherProperties.FILL__NOFILLHITTEST)).isTrue()); + ((EscherBoolProperty) opt.lookup(EscherProperties.FILL__NOFILLHITTEST)).isTrue()); assertEquals(0x08000040, - ((EscherSimpleProperty)opt.lookup(EscherProperties.LINESTYLE__COLOR)).getPropertyValue()); + ((EscherSimpleProperty) opt.lookup(EscherProperties.LINESTYLE__COLOR)).getPropertyValue()); assertEquals(true, - ((EscherBoolProperty)opt.lookup(EscherProperties.LINESTYLE__NOLINEDRAWDASH)).isTrue()); + ((EscherBoolProperty) opt.lookup(EscherProperties.LINESTYLE__NOLINEDRAWDASH)).isTrue()); assertEquals(true, - ((EscherBoolProperty)opt.lookup(EscherProperties.GROUPSHAPE__PRINT)).isTrue()); + ((EscherBoolProperty) opt.lookup(EscherProperties.GROUPSHAPE__PRINT)).isTrue()); } - public void testDefaultPictureSettings(){ + public void testDefaultPictureSettings() { HSSFPicture picture = new HSSFPicture(null, new HSSFClientAnchor()); assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT); @@ -89,7 +89,7 @@ public class TestDrawingShapes extends TestCase{ /** * No NullPointerException should appear */ - public void testDefaultSettingsWithEmptyContainer(){ + public void testDefaultSettingsWithEmptyContainer() { EscherContainerRecord container = new EscherContainerRecord(); EscherOptRecord opt = new EscherOptRecord(); opt.setRecordId(EscherOptRecord.RECORD_ID); @@ -107,6 +107,7 @@ public class TestDrawingShapes extends TestCase{ assertEquals(picture.isNoFill(), HSSFShape.NO_FILL_DEFAULT); assertEquals(picture.getPictureIndex(), -1);//not set yet } + /** * create a rectangle, save the workbook, read back and verify that all shape properties are there */ @@ -116,7 +117,7 @@ public class TestDrawingShapes extends TestCase{ HSSFSheet sheet = wb.createSheet(); HSSFPatriarch drawing = sheet.createDrawingPatriarch(); - HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short)2, 2, (short)15, 15); + HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short) 2, 2, (short) 15, 15); anchor.setAnchorType(2); assertEquals(anchor.getAnchorType(), 2); @@ -139,7 +140,7 @@ public class TestDrawingShapes extends TestCase{ assertEquals(1, drawing.getChildren().size()); HSSFSimpleShape rectangle2 = - (HSSFSimpleShape)drawing.getChildren().get(0); + (HSSFSimpleShape) drawing.getChildren().get(0); assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, rectangle2.getShapeType()); assertEquals(10000, rectangle2.getLineWidth()); @@ -163,7 +164,7 @@ public class TestDrawingShapes extends TestCase{ sheet = wb.getSheetAt(0); drawing = sheet.getDrawingPatriarch(); assertEquals(1, drawing.getChildren().size()); - rectangle2 = (HSSFSimpleShape)drawing.getChildren().get(0); + rectangle2 = (HSSFSimpleShape) drawing.getChildren().get(0); assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, rectangle2.getShapeType()); assertEquals(77, rectangle2.getLineWidth()); assertEquals(9, rectangle2.getLineStyle()); @@ -183,7 +184,7 @@ public class TestDrawingShapes extends TestCase{ assertEquals(drawing.getChildren().size(), 2); } - public void testReadExistingImage(){ + public void testReadExistingImage() { HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); HSSFSheet sheet = wb.getSheet("pictures"); HSSFPatriarch drawing = sheet.getDrawingPatriarch(); @@ -196,6 +197,9 @@ public class TestDrawingShapes extends TestCase{ assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT); assertEquals(picture.isNoFill(), true); + + picture.setPictureIndex(2); + assertEquals(picture.getPictureIndex(), 2); } @@ -206,20 +210,19 @@ public class TestDrawingShapes extends TestCase{ HSSFPatriarch drawing = sheet.getDrawingPatriarch(); assertEquals(1, drawing.getChildren().size()); - for(HSSFShape shape : drawing.getChildren()){ - assertEquals(shape.isNoFill(), true); - assertEquals(shape.getLineStyle(), HSSFShape.LINESTYLE_DASHDOTGEL); - assertEquals(shape.getLineStyleColor(), 0x616161); - assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D); - assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT*2); - } + HSSFSimpleShape shape = (HSSFSimpleShape) drawing.getChildren().get(0); + assertEquals(shape.isNoFill(), true); + assertEquals(shape.getLineStyle(), HSSFShape.LINESTYLE_DASHDOTGEL); + assertEquals(shape.getLineStyleColor(), 0x616161); + assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D); + assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT * 2); } public void testShapeIds() { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet1 = wb.createSheet(); HSSFPatriarch patriarch1 = sheet1.createDrawingPatriarch(); - for(int i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) { patriarch1.createSimpleShape(new HSSFClientAnchor()); } @@ -240,15 +243,15 @@ public class TestDrawingShapes extends TestCase{ assertEquals(3, spgrContainer.getChildRecords().size()); EscherSpRecord sp0 = - ((EscherContainerRecord)spgrContainer.getChild(0)).getChildById(EscherSpRecord.RECORD_ID); + ((EscherContainerRecord) spgrContainer.getChild(0)).getChildById(EscherSpRecord.RECORD_ID); assertEquals(1024, sp0.getShapeId()); EscherSpRecord sp1 = - ((EscherContainerRecord)spgrContainer.getChild(1)).getChildById(EscherSpRecord.RECORD_ID); + ((EscherContainerRecord) spgrContainer.getChild(1)).getChildById(EscherSpRecord.RECORD_ID); assertEquals(1025, sp1.getShapeId()); EscherSpRecord sp2 = - ((EscherContainerRecord)spgrContainer.getChild(2)).getChildById(EscherSpRecord.RECORD_ID); + ((EscherContainerRecord) spgrContainer.getChild(2)).getChildById(EscherSpRecord.RECORD_ID); assertEquals(1026, sp2.getShapeId()); } @@ -256,7 +259,7 @@ public class TestDrawingShapes extends TestCase{ * Test get new id for shapes from existing file * File already have for 1 shape on each sheet, because document must contain EscherDgRecord for each sheet */ - public void testAllocateNewIds(){ + public void testAllocateNewIds() { HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("empty.xls"); HSSFSheet sheet = wb.getSheetAt(0); HSSFPatriarch patriarch = sheet.getDrawingPatriarch(); @@ -288,4 +291,37 @@ public class TestDrawingShapes extends TestCase{ assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1027); assertEquals(HSSFTestHelper.allocateNewShapeId(patriarch), 1028); } + + public void testOpt() throws Exception { + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + EscherOptRecord opt1 = HSSFTestHelper.getOptRecord(textbox); + EscherOptRecord opt2 = textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID); + assertSame(opt1, opt2); + } + + public void testCorrectOrderInOptRecord(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); + EscherOptRecord opt = HSSFTestHelper.getOptRecord(textbox); + + String opt1Str = opt.toXml(); + + textbox.setFillColor(textbox.getFillColor()); + assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + textbox.setLineStyle(textbox.getLineStyle()); + assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + textbox.setLineWidth(textbox.getLineWidth()); + assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + textbox.setLineStyleColor(textbox.getLineStyleColor()); + assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 496139eaab..9b2273c590 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -16,6 +16,7 @@ ==================================================================== */ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.EscherAggregate; @@ -47,4 +48,8 @@ public class HSSFTestHelper { public static int allocateNewShapeId(HSSFPatriarch patriarch){ return patriarch.newShapeId(); } + + public static EscherOptRecord getOptRecord(HSSFShape shape){ + return shape._optRecord; + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java new file mode 100644 index 0000000000..91b1a7cb19 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -0,0 +1,241 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.model.CommentShape; +import org.apache.poi.hssf.model.HSSFTestModelHelper; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.NoteRecord; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.TextObjectRecord; + +import java.io.IOException; +import java.util.Arrays; + +/** + * @author Evgeniy Berlog + * @date 26.06.12 + */ +public class TestComment extends TestCase { + + public void testResultEqualsToAbstractShape() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); + HSSFRow row = sh.createRow(0); + HSSFCell cell = row.createCell(0); + cell.setCellComment(comment); + + CommentShape commentShape = HSSFTestModelHelper.createCommentShape(0, comment); + + assertEquals(comment.getEscherContainer().getChildRecords().size(), 5); + assertEquals(commentShape.getSpContainer().getChildRecords().size(), 5); + + //sp record + byte[] expected = commentShape.getSpContainer().getChild(0).serialize(); + byte[] actual = comment.getEscherContainer().getChild(0).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = commentShape.getSpContainer().getChild(2).serialize(); + actual = comment.getEscherContainer().getChild(2).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = commentShape.getSpContainer().getChild(3).serialize(); + actual = comment.getEscherContainer().getChild(3).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = commentShape.getSpContainer().getChild(4).serialize(); + actual = comment.getEscherContainer().getChild(4).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + ObjRecord obj = comment.getObjRecord(); + ObjRecord objShape = commentShape.getObjRecord(); + + expected = obj.serialize(); + actual = objShape.serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + TextObjectRecord tor = comment.getTextObjectRecord(); + TextObjectRecord torShape = commentShape.getTextObjectRecord(); + + expected = tor.serialize(); + actual = torShape.serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + NoteRecord note = comment.getNoteRecord(); + NoteRecord noteShape = commentShape.getNoteRecord(); + + expected = note.serialize(); + actual = noteShape.serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + } + + public void testAddToExistingFile() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); + comment.setString(new HSSFRichTextString("comment1")); + comment = patriarch.createCellComment(new HSSFClientAnchor()); + comment.setString(new HSSFRichTextString("comment2")); + + assertEquals(patriarch.getChildren().size(), 2); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + comment = patriarch.createCellComment(new HSSFClientAnchor()); + comment.setString(new HSSFRichTextString("comment3")); + + assertEquals(patriarch.getChildren().size(), 3); + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + assertEquals(patriarch.getChildren().size(), 3); + assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1"); + assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2"); + assertEquals(((HSSFComment) patriarch.getChildren().get(2)).getString().getString(), "comment3"); + } + + public void testSetGetProperties() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); + comment.setString(new HSSFRichTextString("comment1")); + assertEquals(comment.getString().getString(), "comment1"); + + comment.setAuthor("poi"); + assertEquals(comment.getAuthor(), "poi"); + + comment.setColumn(3); + assertEquals(comment.getColumn(), 3); + + comment.setRow(4); + assertEquals(comment.getRow(), 4); + + comment.setVisible(false); + assertEquals(comment.isVisible(), false); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + comment = (HSSFComment) patriarch.getChildren().get(0); + + assertEquals(comment.getString().getString(), "comment1"); + assertEquals("poi", comment.getAuthor()); + assertEquals(comment.getColumn(), 3); + assertEquals(comment.getRow(), 4); + assertEquals(comment.isVisible(), false); + + comment.setString(new HSSFRichTextString("comment12")); + comment.setAuthor("poi2"); + comment.setColumn(32); + comment.setRow(42); + comment.setVisible(true); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + comment = (HSSFComment) patriarch.getChildren().get(0); + + assertEquals(comment.getString().getString(), "comment12"); + assertEquals("poi2", comment.getAuthor()); + assertEquals(comment.getColumn(), 32); + assertEquals(comment.getRow(), 42); + assertEquals(comment.isVisible(), true); + } + + public void testExistingFileWithComment(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("comments"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + HSSFComment comment = (HSSFComment) drawing.getChildren().get(0); + assertEquals(comment.getAuthor(), "evgeniy"); + assertEquals(comment.getString().getString(), "evgeniy:\npoi test"); + assertEquals(comment.getColumn(), 1); + assertEquals(comment.getRow(), 2); + } + + public void testFindComments(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); + HSSFRow row = sh.createRow(5); + HSSFCell cell = row.createCell(4); + cell.setCellComment(comment); + + HSSFTestModelHelper.createCommentShape(0, comment); + + assertNotNull(sh.findCellComment(5, 4)); + assertNull(sh.findCellComment(5, 5)); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + + assertNotNull(sh.findCellComment(5, 4)); + assertNull(sh.findCellComment(5, 5)); + } + + public void testInitState(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); + + HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor()); + + //5 properties of HSSFShape + 8 of HSSFTextbox + assertEquals(comment._optRecord.getEscherProperties().size(), 13); + } + + public void testShapeId(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); + + comment.setShapeId(2024); + /** + * SpRecord.id == shapeId + * ObjRecord.id == shapeId - 1024 + * NoteRecord.id == ObjectRecord.id == shapeId - 1024 + */ + + assertEquals(comment.getShapeId(), 2024); + + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0); + assertEquals(cod.getObjectId(), 1000); + EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0); + assertEquals(spRecord.getShapeId(), 2024); + assertEquals(comment.getShapeId(), 2024); + assertEquals(comment.getNoteRecord().getShapeId(), 1000); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java index 7d04110b12..b49f725baa 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java @@ -32,7 +32,7 @@ public final class TestHSSFComment extends BaseTestCellComment { } public void testDefaultShapeType() { - HSSFComment comment = new HSSFComment((HSSFShape)null, (HSSFAnchor)null); + HSSFComment comment = new HSSFComment((HSSFShape)null, new HSSFClientAnchor()); assertEquals(HSSFSimpleShape.OBJECT_TYPE_COMMENT, comment.getShapeType()); } diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index 8ea863f59a6eb022c8a5cfa3946adec55f443e46..24684cb6ccc0880829ab8de111fe6263a07ebcad 100644 GIT binary patch delta 4651 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 IBGJtF59$64c>n+a delta 4080 zcmZ|S3s_8P9{})k&P+4Y%-e;oO1g+rA}L)|M(9dcUDP((sHxC)MO#cloA^-CSs@Ce zvT0LHE0;)VN0QmZrmVFTrF5abviRQjo!#fz=lh;-p68u;=6C-8|M|b~yq(U;{Bu#} z`$dNxNxN#NyCk`^Mu8GiiU$5+>&E==llBFv%-xhvK*1FAGih2dsZg!RAt-`DFbRc% z%dEvDqvj23f+}cWvkD^E>>3O191Hiaxqu)DE|C2Q7j0KNJ?iA4v|&5=PN|~;1WZLC@)sL^ zkZ_D*)m8I)MM6xu#}QpHxbMw5-K>M@Vm;{(3ZDz z-fRjKVTu$Wy0hr|O|u>RZcN!b5s8bb6N!gLdofiMBch%!ls!K_5{{|u24%%7Y^4NZ zDFwT1rE=7PZ9t@Iw`I5q4j6roa#}a$TIMPSIbzZz8IVTD-apXy>y>xuV2DW1q(5FI z$MFn~5-dm5?xyNf_4Z>jrmU|K>CaE?ofDqbk4d}>QEcFTQ)V&y1tw_;BIcxhKW0YwCeJ68%Vs73E95DSQ%27E#5fl)$H3-uZCKFQqtvLIl z!06kULX8pG7kXV7tSf$vY3E8r{6eo+Vxp6YsdOWvjH&LZ)tf^vU~1ljC^<@}I_#aA z7N-8Qi26MeXO~ffO_-FMn4_G+cBVkw#)MtAGg~x)+lRe#MX{-?ae!4H%K84IN~m~i zaT}%}wgM#Qv{}N6o^=l}eQSc~k5)^&lJ_6vT^73`YNwobYpSu9%03TZX75ecQY(Uf?*U1uY6PcA-o`AZ}NHUCI<*YXR%iek(pJ z@0p1M{QFVP;Ci*$?LOz{V%o}OLCW(#UX+`qZH}qP4AIsFuWyE#&-;w&h9{!?O_xoz zj3%5hy@*5P?$)H6sPB-1iM1b5@b~tMi^qH9Kb6@9L??~1Z!S2yqX0*F-(y{36?U)$ zVi^l|*}>w>09!KVRGkZaa0~||4WgX!zKoy3A0OX`sZfaxX{tl`U{`-&KBlV{h@@f< z>GwUQt1vxVgJ?v0C{5$#&9j)Octk(FJn~0OT)#G^xd#!|xj8=&>9sw>jewdCQ+ogLCdin69XDAl*yo z8Pe1>orS5(5>b;x5c(`2cmUI9UqqR%#v7z*bL4X|N<)KCsA(AoK#wRyUj$o2rMHJ{e zZF#^B1Npy}p)THZvhW#CP}t4uR{Z?s%NH~pB!k^NH8SroMSHhC zGSfeyGCNge!F!e1v?HO%lPu8#l{_k$M@xm^2Rd&aP^TsW=mRleB|R_?Xex3!1ffDO zh7;&_FX}#bizikkbY?e{HP`k zRJwtlSPZ`6`oY@_RLy1qJsbnWa;#xF5Bjt<(54y(Xzw*(v1HI1oMQ7lV8zVF0V={b z9aXfT?>GW01y7hy($}59B6_|PaOQc!D0s&~H0+krsZL-8=|xwq1vd1M6L92t{dF*6 zkCe7?2D3?D+9wd6NH&g7M8gx!m9#p8Mi$Q(hMLO8sm#9l^0VDt1*YqwZYeH7G!new zAb1uL984mUFm1-Ix=EJ0f{QG!A4+Z>p!i<2_gb*PLW`|JFo(6^Es_<%9fs>ito}cR z%9;lxaL(f_-fCC_exo9S@O0OcYtTdzd29Zf1F=_1n+L)K#wGuv`RGaf*)bg;69J}SEGFGZ|TKCU_$Y=>4ZeMn_RT%Bq0bQLnJ>7 z0h`p<=BN11lne{CM|IBN`ZXw&>?tROVs?=uaF6sU`;GA zWRS!(Ix!ZQb4+1Yd7}|q;^zt+C~ou-6ZL3Ve1b(AS^!PawZNzGPc6X?{U1fD@1J%3 zbU9wN{M%eQKxe%Pf!Tx0{|Sd#F~qFE`gw zvTc%e*f5@?6bqt$Q4r=VI=((j*G21|DDUt}pO{U;lV42l|14N!btKu`OW#rby9aG* z8VgmK=kJG~=_pq}pzanbD!+1KnVARSDJpnAw`20cJXh(hcpWP7T+f!rQmgkMRQY=L zyTTibt`hDoHdOkCw`6{MRQT>G+h!3aycVDn&#BEb?sFF`miv8odKD&TZwT*j|@??C&KYywfRBlkZwrB3Mx&%Ad zhdqA|mwhUkQ@Y`0Y0}OWm(wc>O5W86R33I)lEFVd{rx5P9piPk?v1K#d&)Fq8?4{% z(fIXt5SOf9q<6mj)ptJ}DCcOE?zXkm&@T@(rnRneN|)U zXFb~<*B@-Y9@pX;8mxPNml9>*-zP5nP}G<-l5vtq6ufq^cJ)#YdlPY@_|(7d{AhWy z?Pc`PW9EulU9R%ciNVAEbg;jotz~6L+0kaR-=}riScrajZTXdrHOLC9SXnu;*RyuC zB!BYppJ9nHFUm9GE=D^gZ|Pk&_+rCkOJv)^g;PH}sV+ZNjfg;X76L z$xGqCUTxVkCQEAAQl}p5lKbIfbm^Eh#6Md0Xj$E01KnvFx#sTgEcbXF@;k7~^4~EkXZGm5ecxfGXK42+VTwol zECq-E`S&`s5?JfvWrPoz<#4FrtJ&XgH)y9-z=+hM+Y-PGqr;>&yf_fVv|)5SoX{aO zi0SZ&6 Date: Sun, 1 Jul 2012 09:38:08 +0000 Subject: [PATCH 15/32] implemented work with existing shape groups and polygons git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1355866 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/ddf/EscherSpRecord.java | 2 +- .../apache/poi/hssf/model/PolygonShape.java | 2 +- .../poi/hssf/usermodel/HSSFComment.java | 5 - .../poi/hssf/usermodel/HSSFPatriarch.java | 2 + .../poi/hssf/usermodel/HSSFPolygon.java | 197 +++++++++++---- .../apache/poi/hssf/usermodel/HSSFShape.java | 9 - .../poi/hssf/usermodel/HSSFShapeFactory.java | 16 +- .../poi/hssf/usermodel/HSSFShapeGroup.java | 206 +++++++++++----- .../poi/hssf/usermodel/HSSFSimpleShape.java | 8 +- .../poi/hssf/usermodel/HSSFTextbox.java | 6 + .../poi/hssf/model/HSSFTestModelHelper.java | 5 + .../poi/hssf/model/TestDrawingAggregate.java | 17 +- .../poi/hssf/usermodel/HSSFTestHelper.java | 53 ++++ .../poi/hssf/usermodel/TestPolygon.java | 231 ++++++++++++++++++ .../poi/hssf/usermodel/TestShapeGroup.java | 225 +++++++++++++++++ test-data/spreadsheet/drawings.xls | Bin 818688 -> 821760 bytes 16 files changed, 830 insertions(+), 154 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java diff --git a/src/java/org/apache/poi/ddf/EscherSpRecord.java b/src/java/org/apache/poi/ddf/EscherSpRecord.java index 11a893f466..7d4dd5cfba 100644 --- a/src/java/org/apache/poi/ddf/EscherSpRecord.java +++ b/src/java/org/apache/poi/ddf/EscherSpRecord.java @@ -119,7 +119,7 @@ public class EscherSpRecord public String toXml(String tab) { StringBuilder builder = new StringBuilder(); builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance()))) - .append(tab).append("\t").append("").append(HexDump.toHex(getShapeType())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getShapeType())).append("\n") .append(tab).append("\t").append("").append(field_1_shapeId).append("\n") .append(tab).append("\t").append("").append(decodeFlags(field_2_flags) + " (0x" + HexDump.toHex(field_2_flags) + ")").append("\n"); builder.append(tab).append("\n"); diff --git a/src/java/org/apache/poi/hssf/model/PolygonShape.java b/src/java/org/apache/poi/hssf/model/PolygonShape.java index 02308bf48c..22212c88d2 100644 --- a/src/java/org/apache/poi/hssf/model/PolygonShape.java +++ b/src/java/org/apache/poi/hssf/model/PolygonShape.java @@ -63,7 +63,7 @@ public class PolygonShape spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); spContainer.setOptions( (short) 0x000F ); sp.setRecordId( EscherSpRecord.RECORD_ID ); - sp.setOptions( (short) ( ( EscherAggregate.ST_DONUT << 4 ) | 0x2 ) ); + sp.setOptions( (short) ( ( EscherAggregate.ST_NOT_PRIMATIVE << 4 ) | 0x2 ) ); sp.setShapeId( shapeId ); if (hssfShape.getParent() == null) sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE ); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 23a792f365..add7e32728 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -38,11 +38,6 @@ public class HSSFComment extends HSSFTextbox implements Comment { * It seems like HSSFRow should manage a collection of local HSSFComments */ - private boolean _visible; - private int _row; - private int _col; - private String _author; - private NoteRecord _note; public HSSFComment(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord, NoteRecord _note) { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index bc3eebc1b3..675c7d7f86 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -73,6 +73,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFShapeGroup group = new HSSFShapeGroup(null, anchor); group.anchor = anchor; addShape(group); + onCreate(group); return group; } @@ -132,6 +133,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFPolygon shape = new HSSFPolygon(null, anchor); shape.anchor = anchor; addShape(shape); + onCreate(shape); return shape; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index 33f17d7e48..8d561a0ff1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -17,87 +17,186 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.EndSubRecord; +import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.util.LittleEndian; /** * @author Glen Stampoultzis (glens at superlinksoftware.com) */ -public class HSSFPolygon - extends HSSFShape -{ - int[] xPoints; - int[] yPoints; - int drawAreaWidth = 100; - int drawAreaHeight = 100; +public class HSSFPolygon extends HSSFShape { - HSSFPolygon( HSSFShape parent, HSSFAnchor anchor ) - { - super( parent, anchor ); + public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 0x1E; + + public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); } - @Override + HSSFPolygon(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); + } + + /** + * Generates the shape records for this shape. + */ protected EscherContainerRecord createSpContainer() { EscherContainerRecord spContainer = new EscherContainerRecord(); - spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); - spContainer.setOptions( (short) 0x000F ); - EscherOptRecord optRecord = new EscherOptRecord(); - optRecord.setRecordId(EscherOptRecord.RECORD_ID); - spContainer.addChildRecord(optRecord); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherClientDataRecord clientData = new EscherClientDataRecord(); + + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) ((EscherAggregate.ST_NOT_PRIMATIVE << 4) | 0x2)); + if (getParent() == null) { + sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + } else { + sp.setFlags(EscherSpRecord.FLAG_CHILD | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + } + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION, false, false, 0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, false, false, 100)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, false, false, 100)); + opt.setEscherProperty(new EscherShapePathProperty(EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX)); + + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__FILLOK, false, false, 0x00010001)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINESTARTARROWHEAD, false, false, 0x0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDARROWHEAD, false, false, 0x0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0)); + + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + + EscherRecord anchor = getAnchor().getEscherAnchor(); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); + + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); + return spContainer; } - @Override + /** + * Creates the low level OBJ record for this shape. + */ protected ObjRecord createObjRecord() { - return null; + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING); + c.setLocked(true); + c.setPrintable(true); + c.setAutofill(true); + c.setAutoline(true); + EndSubRecord e = new EndSubRecord(); + obj.addSubRecord(c); + obj.addSubRecord(e); + return obj; } - public int[] getXPoints() - { - return xPoints; + public int[] getXPoints() { + EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + if (null == verticesProp){ + return new int[]{}; + } + int []array = new int[verticesProp.getNumberOfElementsInArray()-1]; + for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){ + byte[] property = verticesProp.getElement(i); + short x = LittleEndian.getShort(property, 0); + array[i] = x; + } + return array; } - public int[] getYPoints() - { - return yPoints; + public int[] getYPoints() { + EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + if (null == verticesProp){ + return new int[]{}; + } + int []array = new int[verticesProp.getNumberOfElementsInArray()-1]; + for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){ + byte[] property = verticesProp.getElement(i); + short x = LittleEndian.getShort(property, 2); + array[i] = x; + } + return array; } - public void setPoints(int[] xPoints, int[] yPoints) - { - this.xPoints = cloneArray(xPoints); - this.yPoints = cloneArray(yPoints); - } + public void setPoints(int[] xPoints, int[] yPoints) { + if (xPoints.length != yPoints.length){ + System.out.println("xPoint.length must be equal to yPoints.length"); + return; + } + if (xPoints.length == 0){ + System.out.println("HSSFPolygon must have at least one point"); + } + EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] ); + verticesProp.setNumberOfElementsInArray(xPoints.length+1); + verticesProp.setNumberOfElementsInMemory(xPoints.length+1); + verticesProp.setSizeOfElements(0xFFF0); + for (int i = 0; i < xPoints.length; i++) + { + byte[] data = new byte[4]; + LittleEndian.putShort(data, 0, (short)xPoints[i]); + LittleEndian.putShort(data, 2, (short)yPoints[i]); + verticesProp.setElement(i, data); + } + int point = xPoints.length; + byte[] data = new byte[4]; + LittleEndian.putShort(data, 0, (short)xPoints[0]); + LittleEndian.putShort(data, 2, (short)yPoints[0]); + verticesProp.setElement(point, data); + setPropertyValue(verticesProp); - private int[] cloneArray( int[] a ) - { - int[] result = new int[a.length]; - for ( int i = 0; i < a.length; i++ ) - result[i] = a[i]; - - return result; + EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null ); + segmentsProp.setSizeOfElements(0x0002); + segmentsProp.setNumberOfElementsInArray(xPoints.length * 2 + 4); + segmentsProp.setNumberOfElementsInMemory(xPoints.length * 2 + 4); + segmentsProp.setElement(0, new byte[] { (byte)0x00, (byte)0x40 } ); + segmentsProp.setElement(1, new byte[] { (byte)0x00, (byte)0xAC } ); + for (int i = 0; i < xPoints.length; i++) + { + segmentsProp.setElement(2 + i * 2, new byte[] { (byte)0x01, (byte)0x00 } ); + segmentsProp.setElement(3 + i * 2, new byte[] { (byte)0x00, (byte)0xAC } ); + } + segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 2, new byte[] { (byte)0x01, (byte)0x60 } ); + segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 1, new byte[] { (byte)0x00, (byte)0x80 } ); + setPropertyValue(segmentsProp); } /** * Defines the width and height of the points in the polygon + * * @param width * @param height */ - public void setPolygonDrawArea( int width, int height ) - { - this.drawAreaWidth = width; - this.drawAreaHeight = height; + public void setPolygonDrawArea(int width, int height) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, width)); + setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, height)); } - public int getDrawAreaWidth() - { - return drawAreaWidth; + public int getDrawAreaWidth() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__RIGHT); + return property == null ? 100: property.getPropertyValue(); } - public int getDrawAreaHeight() - { - return drawAreaHeight; + public int getDrawAreaHeight() { + EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__BOTTOM); + return property == null ? 100: property.getPropertyValue(); } - + @Override + void afterInsert(HSSFPatriarch patriarch) { + EscherAggregate agg = patriarch._getBoundAggregate(); + agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 9c2775373f..09bf271fc5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -72,7 +72,6 @@ public abstract class HSSFShape { this.anchor = anchor; this._escherContainer = createSpContainer(); _optRecord = _escherContainer.getChildById(EscherOptRecord.RECORD_ID); - addStandardOptions(_optRecord); _objRecord = createObjRecord(); } @@ -87,14 +86,6 @@ public abstract class HSSFShape { CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); cod.setObjectId((short) (shapeId-1024)); } - - private void addStandardOptions(EscherOptRecord optRecord){ - setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); - setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); - setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); - setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); - } int getShapeId(){ return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 5358f4868f..1ee53171b6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -17,12 +17,7 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.ddf.EscherSpgrRecord; -import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.model.TextboxShape; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.EscherAggregate; @@ -124,6 +119,15 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: shape = new HSSFSimpleShape(container, objRecord); break; + case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: + EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); + EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + if (null != property){ + shape = new HSSFPolygon(container, objRecord); + } else { + shape = new HSSFSimpleShape(container, objRecord); + } + break; case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: shape = new HSSFTextbox(container, objRecord, txtRecord); break; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index d98471e33a..eb023e0cae 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -19,8 +19,7 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; import org.apache.poi.hssf.model.TextboxShape; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.*; import java.util.ArrayList; import java.util.List; @@ -32,10 +31,7 @@ import java.util.Iterator; * * @author Glen Stampoultzis (glens at apache.org) */ -public class HSSFShapeGroup - extends HSSFShape - implements HSSFShapeContainer -{ +public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { List shapes = new ArrayList(); private EscherSpgrRecord _spgrRecord; @@ -45,24 +41,22 @@ public class HSSFShapeGroup // read internal and external coordinates from spgrContainer EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0); _spgrRecord = (EscherSpgrRecord) spContainer.getChild(0); - for(EscherRecord ch : spContainer.getChildRecords()){ - switch(ch.getRecordId()) { + for (EscherRecord ch : spContainer.getChildRecords()) { + switch (ch.getRecordId()) { case EscherSpgrRecord.RECORD_ID: break; case EscherClientAnchorRecord.RECORD_ID: - anchor = new HSSFClientAnchor((EscherClientAnchorRecord)ch); + anchor = new HSSFClientAnchor((EscherClientAnchorRecord) ch); break; case EscherChildAnchorRecord.RECORD_ID: - anchor = new HSSFChildAnchor((EscherChildAnchorRecord)ch); + anchor = new HSSFChildAnchor((EscherChildAnchorRecord) ch); break; } } - } - public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor ) - { - super( parent, anchor ); + public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); _spgrRecord = new EscherSpgrRecord(); _spgrRecord.setRectX1(0); _spgrRecord.setRectX2(1023); @@ -72,104 +66,169 @@ public class HSSFShapeGroup @Override protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spgrContainer = new EscherContainerRecord(); EscherContainerRecord spContainer = new EscherContainerRecord(); - spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); - spContainer.setOptions( (short) 0x000F ); - EscherOptRecord optRecord = new EscherOptRecord(); - optRecord.setRecordId(EscherOptRecord.RECORD_ID); - spContainer.addChildRecord(optRecord); - return spContainer; + EscherSpgrRecord spgr = new EscherSpgrRecord(); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherRecord anchor; + EscherClientDataRecord clientData = new EscherClientDataRecord(); + + spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); + spgrContainer.setOptions((short) 0x000F); + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + spgr.setRecordId(EscherSpgrRecord.RECORD_ID); + spgr.setOptions((short) 0x0001); + spgr.setRectX1(0); + spgr.setRectY1(0); + spgr.setRectX2(1023); + spgr.setRectY2(255); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) 0x0002); + if (getAnchor() instanceof HSSFClientAnchor) { + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR); + } else { + sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD); + } + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.setOptions((short) 0x0023); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); + + anchor = getAnchor().getEscherAnchor(); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); + + spgrContainer.addChildRecord(spContainer); + spContainer.addChildRecord(spgr); + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); + return spgrContainer; } @Override protected ObjRecord createObjRecord() { - return null; //To change body of implemented methods use File | Settings | File Templates. + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); + cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP); + cmo.setLocked(true); + cmo.setPrintable(true); + cmo.setAutofill(true); + cmo.setAutoline(true); + GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); + EndSubRecord end = new EndSubRecord(); + obj.addSubRecord(cmo); + obj.addSubRecord(gmo); + obj.addSubRecord(end); + return obj; + } + + private void onCreate(HSSFShape shape){ + if(_patriarch != null && _patriarch._getBoundAggregate().getPatriarch() == null){ + EscherContainerRecord spContainer = shape.getEscherContainer(); + int shapeId = _patriarch.newShapeId(); + shape.setShapeId(shapeId); + _escherContainer.addChildRecord(spContainer); + shape.afterInsert(_patriarch); + } } /** * Create another group under this group. - * @param anchor the position of the new group. - * @return the group + * + * @param anchor the position of the new group. + * @return the group */ - public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) - { + public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) { HSSFShapeGroup group = new HSSFShapeGroup(this, anchor); + group.parent = this; group.anchor = anchor; shapes.add(group); + onCreate(group); return group; } - public void addShape(HSSFShape shape){ + public void addShape(HSSFShape shape) { shape._patriarch = this._patriarch; + shape.parent = this; shapes.add(shape); } - public void addTextBox(TextboxShape textboxShape){ + public void addTextBox(TextboxShape textboxShape) { // HSSFTextbox shape = new HSSFTextbox(this, textboxShape.geanchor); // shapes.add(textboxShape); } /** * Create a new simple shape under this group. - * @param anchor the position of the shape. - * @return the shape + * + * @param anchor the position of the shape. + * @return the shape */ - public HSSFSimpleShape createShape(HSSFChildAnchor anchor) - { + public HSSFSimpleShape createShape(HSSFChildAnchor anchor) { HSSFSimpleShape shape = new HSSFSimpleShape(this, anchor); + shape.parent = this; shape.anchor = anchor; shapes.add(shape); + onCreate(shape); return shape; } /** * Create a new textbox under this group. - * @param anchor the position of the shape. - * @return the textbox + * + * @param anchor the position of the shape. + * @return the textbox */ - public HSSFTextbox createTextbox(HSSFChildAnchor anchor) - { + public HSSFTextbox createTextbox(HSSFChildAnchor anchor) { HSSFTextbox shape = new HSSFTextbox(this, anchor); + shape.parent = this; shape.anchor = anchor; shapes.add(shape); + onCreate(shape); return shape; } /** * Creates a polygon * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. */ - public HSSFPolygon createPolygon(HSSFChildAnchor anchor) - { + public HSSFPolygon createPolygon(HSSFChildAnchor anchor) { HSSFPolygon shape = new HSSFPolygon(this, anchor); + shape.parent = this; shape.anchor = anchor; shapes.add(shape); + onCreate(shape); return shape; } /** * Creates a picture. * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. */ - public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) - { - HSSFPicture shape = new HSSFPicture(this, anchor); - shape.anchor = anchor; - shape.setPictureIndex( pictureIndex ); - shapes.add(shape); - return shape; + public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) { + HSSFPicture shape = new HSSFPicture(this, anchor); + shape.parent = this; + shape.anchor = anchor; + shape.setPictureIndex(pictureIndex); + shapes.add(shape); + onCreate(shape); + return shape; } + /** * Return all children contained by this shape. */ - public List getChildren() - { + public List getChildren() { return shapes; } @@ -177,8 +236,7 @@ public class HSSFShapeGroup * Sets the coordinate space of this group. All children are constrained * to these coordinates. */ - public void setCoordinates( int x1, int y1, int x2, int y2 ) - { + public void setCoordinates(int x1, int y1, int x2, int y2) { _spgrRecord.setRectX1(x1); _spgrRecord.setRectX2(x2); _spgrRecord.setRectY1(y1); @@ -188,46 +246,62 @@ public class HSSFShapeGroup /** * The top left x coordinate of this group. */ - public int getX1() - { + public int getX1() { return _spgrRecord.getRectX1(); } /** * The top left y coordinate of this group. */ - public int getY1() - { + public int getY1() { return _spgrRecord.getRectY1(); } /** * The bottom right x coordinate of this group. */ - public int getX2() - { + public int getX2() { return _spgrRecord.getRectX2(); } /** * The bottom right y coordinate of this group. */ - public int getY2() - { + public int getY2() { return _spgrRecord.getRectY2(); } /** * Count of all children and their childrens children. */ - public int countOfAllChildren() - { + public int countOfAllChildren() { int count = shapes.size(); - for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); ) - { + for (Iterator iterator = shapes.iterator(); iterator.hasNext(); ) { HSSFShape shape = (HSSFShape) iterator.next(); count += shape.countOfAllChildren(); } return count; } + + @Override + void afterInsert(HSSFPatriarch patriarch){ + EscherAggregate agg = patriarch._getBoundAggregate(); + EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + agg.associateShapeToObjRecord(containerRecord.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + } + + @Override + void setShapeId(int shapeId){ + EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID); + spRecord.setShapeId(shapeId); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + cod.setObjectId((short) (shapeId-1024)); + } + + @Override + int getShapeId(){ + EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 2b64faaa5a..62b9d6a8e0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -32,8 +32,7 @@ import java.util.Map; * * @author Glen Stampoultzis (glens at apache.org) */ -public class HSSFSimpleShape - extends HSSFShape +public class HSSFSimpleShape extends HSSFShape { // The commented out ones haven't been tested yet or aren't supported // by HSSFSimpleShape. @@ -93,6 +92,11 @@ public class HSSFSimpleShape clientData.setOptions( (short) 0x0000 ); EscherOptRecord optRecord = new EscherOptRecord(); + optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); optRecord.setRecordId( EscherOptRecord.RECORD_ID ); spContainer.addChildRecord(sp); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 42385a87ed..1ed70f86a6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -118,6 +118,12 @@ public class HSSFTextbox extends HSSFSimpleShape { opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTTOP, 0)); opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, 0)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); + opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); + opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + EscherRecord anchor = getAnchor().getEscherAnchor(); clientData.setRecordId(EscherClientDataRecord.RECORD_ID); diff --git a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java index 507561e7e4..bc22d17a97 100644 --- a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java +++ b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java @@ -1,6 +1,7 @@ package org.apache.poi.hssf.model; import org.apache.poi.hssf.usermodel.HSSFComment; +import org.apache.poi.hssf.usermodel.HSSFPolygon; import org.apache.poi.hssf.usermodel.HSSFTextbox; /** @@ -15,4 +16,8 @@ public class HSSFTestModelHelper { public static CommentShape createCommentShape(int shapeId, HSSFComment comment){ return new CommentShape(comment, shapeId); } + + public static PolygonShape createPolygonShape(int shapeId, HSSFPolygon polygon){ + return new PolygonShape(polygon, shapeId); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index 18572d6ec1..1f058c06da 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -201,7 +201,7 @@ public class TestDrawingAggregate extends TestCase { HSSFPatriarch drawing = sheet.createDrawingPatriarch(); EscherAggregate agg1 = HSSFTestHelper.getEscherAggregate(drawing); - callConvertPatriarch(agg1); + HSSFTestHelper.callConvertPatriarch(agg1); agg1.setPatriarch(null); agg.setPatriarch(null); @@ -213,20 +213,7 @@ public class TestDrawingAggregate extends TestCase { assertTrue(Arrays.equals(aggS, agg1S)); } - private static void callConvertPatriarch(EscherAggregate agg) { - Method method = null; - try { - method = agg.getClass().getDeclaredMethod("convertPatriarch", HSSFPatriarch.class); - method.setAccessible(true); - method.invoke(agg, agg.getPatriarch()); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } catch (InvocationTargetException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } + /** * when reading incomplete data ensure that the serialized bytes diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 9b2273c590..214121d940 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -16,17 +16,40 @@ ==================================================================== */ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherDggRecord; import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.EscherAggregate; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + /** * Helper class for HSSF tests that aren't within the * HSSF UserModel package, but need to do internal * UserModel things. */ public class HSSFTestHelper { + + private static class MockDrawingManager extends DrawingManager2 { +// +// public MockDrawingManager(EscherDggRecord dgg) { +// super(dgg); +// } + + public MockDrawingManager (){ + super(null); + } + + @Override + public int allocateShapeId(short drawingGroupId) { + return 0; //Mock value + } + } /** * Lets non UserModel tests at the low level Workbook */ @@ -52,4 +75,34 @@ public class HSSFTestHelper { public static EscherOptRecord getOptRecord(HSSFShape shape){ return shape._optRecord; } + + public static void convertHSSFGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj){ + Class clazz = EscherAggregate.class; + try { + Method method = clazz.getDeclaredMethod("convertGroup", HSSFShapeGroup.class, EscherContainerRecord.class, Map.class); + method.setAccessible(true); + method.invoke(new EscherAggregate(new MockDrawingManager()), shape, escherParent, shapeToObj); + } catch (NoSuchMethodException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (IllegalAccessException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + + public static void callConvertPatriarch(EscherAggregate agg) { + Method method = null; + try { + method = agg.getClass().getDeclaredMethod("convertPatriarch", HSSFPatriarch.class); + method.setAccessible(true); + method.invoke(agg, agg.getPatriarch()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java new file mode 100644 index 0000000000..7c83a0d25f --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java @@ -0,0 +1,231 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherArrayProperty; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.model.HSSFTestModelHelper; +import org.apache.poi.hssf.model.PolygonShape; +import org.apache.poi.hssf.record.ObjRecord; + +import java.io.IOException; +import java.util.Arrays; + +/** + * @author Evgeniy Berlog + * @date 28.06.12 + */ +public class TestPolygon extends TestCase{ + + public void testResultEqualsToAbstractShape() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 100, 100 ); + polygon.setPoints( new int[]{0, 90, 50}, new int[]{5, 5, 44} ); + PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(1024, polygon); + polygon.setShapeId(1024); + + assertEquals(polygon.getEscherContainer().getChildRecords().size(), 4); + assertEquals(polygonShape.getSpContainer().getChildRecords().size(), 4); + + //sp record + byte[] expected = polygonShape.getSpContainer().getChild(0).serialize(); + byte[] actual = polygon.getEscherContainer().getChild(0).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = polygonShape.getSpContainer().getChild(2).serialize(); + actual = polygon.getEscherContainer().getChild(2).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + expected = polygonShape.getSpContainer().getChild(3).serialize(); + actual = polygon.getEscherContainer().getChild(3).serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + + ObjRecord obj = polygon.getObjRecord(); + ObjRecord objShape = polygonShape.getObjRecord(); + + expected = obj.serialize(); + actual = objShape.serialize(); + + assertEquals(expected.length, actual.length); + assertTrue(Arrays.equals(expected, actual)); + } + + public void testPolygonPoints(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 100, 100 ); + polygon.setPoints( new int[]{0, 90, 50, 90}, new int[]{5, 5, 44, 88} ); + + PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon); + + EscherArrayProperty verticesProp1 = polygon._optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + EscherArrayProperty verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID)) + .lookup(EscherProperties.GEOMETRY__VERTICES); + + assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray()); + assertEquals(verticesProp1.toXml(""), verticesProp2.toXml("")); + + polygon.setPoints(new int[]{1,2,3}, new int[] {4,5,6}); + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6})); + + polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon); + verticesProp1 = polygon._optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID)) + .lookup(EscherProperties.GEOMETRY__VERTICES); + + assertEquals(verticesProp1.getNumberOfElementsInArray(), verticesProp2.getNumberOfElementsInArray()); + assertEquals(verticesProp1.toXml(""), verticesProp2.toXml("")); + } + + public void testSetGetProperties(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1,2,3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6})); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6})); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + polygon.setPolygonDrawArea( 1021, 1011 ); + polygon.setPoints( new int[]{11,21,31}, new int[]{41,51,61} ); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61})); + assertEquals(polygon.getDrawAreaHeight(), 1011); + assertEquals(polygon.getDrawAreaWidth(), 1021); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{11, 21, 31})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{41, 51, 61})); + assertEquals(polygon.getDrawAreaHeight(), 1011); + assertEquals(polygon.getDrawAreaWidth(), 1021); + } + + public void testAddToExistingFile(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon1.setPolygonDrawArea( 103, 104 ); + polygon1.setPoints( new int[]{11,12,13}, new int[]{14,15,16} ); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + + HSSFPolygon polygon2 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon2.setPolygonDrawArea( 203, 204 ); + polygon2.setPoints( new int[]{21,22,23}, new int[]{24,25,26} ); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + + polygon = (HSSFPolygon) patriarch.getChildren().get(0); + polygon1 = (HSSFPolygon) patriarch.getChildren().get(1); + polygon2 = (HSSFPolygon) patriarch.getChildren().get(2); + + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{1, 2, 3})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4,5,6})); + assertEquals(polygon.getDrawAreaHeight(), 101); + assertEquals(polygon.getDrawAreaWidth(), 102); + + assertTrue(Arrays.equals(polygon1.getXPoints(), new int[]{11,12,13})); + assertTrue(Arrays.equals(polygon1.getYPoints(), new int[]{14,15,16})); + assertEquals(polygon1.getDrawAreaHeight(), 104); + assertEquals(polygon1.getDrawAreaWidth(), 103); + + assertTrue(Arrays.equals(polygon2.getXPoints(), new int[]{21,22,23})); + assertTrue(Arrays.equals(polygon2.getYPoints(), new int[]{24,25,26})); + assertEquals(polygon2.getDrawAreaHeight(), 204); + assertEquals(polygon2.getDrawAreaWidth(), 203); + } + + public void testExistingFile() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("polygon"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + HSSFPolygon polygon = (HSSFPolygon) drawing.getChildren().get(0); + assertEquals(polygon.getDrawAreaHeight(), 2466975); + assertEquals(polygon.getDrawAreaWidth(), 3686175); + assertTrue(Arrays.equals(polygon.getXPoints(), new int[]{0, 0, 31479, 16159, 19676, 20502})); + assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{0, 0, 36, 56, 34, 18})); + } + + public void testPolygonType(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + + HSSFPolygon polygon = patriarch.createPolygon(new HSSFClientAnchor()); + polygon.setPolygonDrawArea( 102, 101 ); + polygon.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + HSSFPolygon polygon1 = patriarch.createPolygon(new HSSFClientAnchor()); + polygon1.setPolygonDrawArea( 102, 101 ); + polygon1.setPoints( new int[]{1,2,3}, new int[]{4,5,6} ); + + EscherSpRecord spRecord = polygon1.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + + spRecord.setShapeType((short)77/**RANDOM**/); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + assertTrue(patriarch.getChildren().get(0) instanceof HSSFPolygon); + assertTrue(patriarch.getChildren().get(1) instanceof HSSFPolygon); + } +} diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java new file mode 100644 index 0000000000..bdbf25fc4d --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java @@ -0,0 +1,225 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.ObjRecord; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Evgeniy Berlog + * @date 29.06.12 + */ +public class TestShapeGroup extends TestCase{ + + public void testResultEqualsToAbstractShape() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + + EscherContainerRecord container = new EscherContainerRecord(); + Map shapeToObj = new HashMap(); + HSSFTestHelper.convertHSSFGroup(group, container, shapeToObj); + + byte [] actual = group.getEscherContainer().serialize(); + byte [] expected = container.getChild(0).serialize(); + + assertEquals(actual.length, expected.length); + assertTrue(Arrays.equals(actual, expected)); + + actual = group.getObjRecord().serialize(); + expected = ((ObjRecord)shapeToObj.values().toArray()[0]).serialize(); + + assertEquals(actual.length, expected.length); + assertTrue(Arrays.equals(actual, expected)); + } + + public void testSetGetCoordinates(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + assertEquals(group.getX1(), 0); + assertEquals(group.getY1(), 0); + assertEquals(group.getX2(), 1023); + assertEquals(group.getY2(), 255); + + group.setCoordinates(1,2,3,4); + + assertEquals(group.getX1(), 1); + assertEquals(group.getY1(), 2); + assertEquals(group.getX2(), 3); + assertEquals(group.getY2(), 4); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + assertEquals(group.getX1(), 1); + assertEquals(group.getY1(), 2); + assertEquals(group.getX2(), 3); + assertEquals(group.getY2(), 4); + } + + public void testAddToExistingFile(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + HSSFShapeGroup group1 = patriarch.createGroup(new HSSFClientAnchor()); + HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); + + group1.setCoordinates(1,2,3,4); + group2.setCoordinates(5,6,7,8); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 2); + + HSSFShapeGroup group3 = patriarch.createGroup(new HSSFClientAnchor()); + group3.setCoordinates(9,10,11,12); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.getDrawingPatriarch(); + + assertEquals(patriarch.getChildren().size(), 3); + } + + public void testModify() throws Exception { + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group1 = patriarch.createGroup(new + HSSFClientAnchor(0,0,0,0, + (short)0, 0, (short)15, 25)); + group1.setCoordinates(0, 0, 792, 612); + + HSSFTextbox textbox1 = group1.createTextbox(new + HSSFChildAnchor(100, 100, 300, 300)); + HSSFRichTextString rt1 = new HSSFRichTextString("Hello, World!"); + textbox1.setString(rt1); + + // write, read back and check that our text box is there + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + assertEquals(1, group1.getChildren().size()); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + assertEquals("Hello, World!", textbox1.getString().getString()); + + // modify anchor + assertEquals(new HSSFChildAnchor(100, 100, 300, 300), + textbox1.getAnchor()); + HSSFChildAnchor newAnchor = new HSSFChildAnchor(200,200, 400, 400); + textbox1.setAnchor(newAnchor); + // modify text + textbox1.setString(new HSSFRichTextString("Hello, World! (modified)")); + + // add a new text box + HSSFTextbox textbox2 = group1.createTextbox(new + HSSFChildAnchor(400, 400, 600, 600)); + HSSFRichTextString rt2 = new HSSFRichTextString("Hello, World-2"); + textbox2.setString(rt2); + assertEquals(2, group1.getChildren().size()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + assertEquals(2, group1.getChildren().size()); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + assertEquals("Hello, World! (modified)", + textbox1.getString().getString()); + assertEquals(new HSSFChildAnchor(200,200, 400, 400), + textbox1.getAnchor()); + + textbox2 = (HSSFTextbox)group1.getChildren().get(1); + assertEquals("Hello, World-2", textbox2.getString().getString()); + assertEquals(new HSSFChildAnchor(400, 400, 600, 600), + textbox2.getAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + group1 = (HSSFShapeGroup)patriarch.getChildren().get(0); + textbox1 = (HSSFTextbox)group1.getChildren().get(0); + textbox2 = (HSSFTextbox)group1.getChildren().get(1); + HSSFTextbox textbox3 = group1.createTextbox(new + HSSFChildAnchor(400,200, 600, 400)); + HSSFRichTextString rt3 = new HSSFRichTextString("Hello, World-3"); + textbox3.setString(rt3); + } + + public void testAddShapesToGroup(){ + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + int index = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_JPEG); + group.createPicture(new HSSFChildAnchor(), index); + HSSFPolygon polygon = group.createPolygon(new HSSFChildAnchor()); + polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); + group.createTextbox(new HSSFChildAnchor()); + group.createShape(new HSSFChildAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(1, patriarch.getChildren().size()); + + assertTrue(patriarch.getChildren().get(0) instanceof HSSFShapeGroup); + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + + assertEquals(group.getChildren().size(), 4); + + assertTrue(group.getChildren().get(0) instanceof HSSFPicture); + assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); + assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); + assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); + + HSSFShapeGroup group2 = patriarch.createGroup(new HSSFClientAnchor()); + + index = wb.addPicture(new byte[]{2,2,2}, HSSFWorkbook.PICTURE_TYPE_JPEG); + group2.createPicture(new HSSFChildAnchor(), index); + polygon = group2.createPolygon(new HSSFChildAnchor()); + polygon.setPoints(new int[]{1,100, 1}, new int[]{1, 50, 100}); + group2.createTextbox(new HSSFChildAnchor()); + group2.createShape(new HSSFChildAnchor()); + group2.createShape(new HSSFChildAnchor()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + assertEquals(2, patriarch.getChildren().size()); + + group = (HSSFShapeGroup) patriarch.getChildren().get(1); + + assertEquals(group.getChildren().size(), 5); + + assertTrue(group.getChildren().get(0) instanceof HSSFPicture); + assertTrue(group.getChildren().get(1) instanceof HSSFPolygon); + assertTrue(group.getChildren().get(2) instanceof HSSFTextbox); + assertTrue(group.getChildren().get(3) instanceof HSSFSimpleShape); + assertTrue(group.getChildren().get(4) instanceof HSSFSimpleShape); + + group.getShapeId(); + } +} diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index 24684cb6ccc0880829ab8de111fe6263a07ebcad..9700c91086f0b771299ce855063de7b2e1c19bcd 100644 GIT binary patch delta 6068 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 WB@9Z%wx-?hvanr{(IXX~m;4*T$o=I2 From 06df547a594c30a10d9d25eb82fcd107c2f42ae4 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Fri, 6 Jul 2012 17:00:20 +0000 Subject: [PATCH 16/32] implemented creating shapes in new file using new model git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1358301 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/model/DrawingManager2.java | 5 +- .../apache/poi/hssf/model/InternalSheet.java | 2 +- .../poi/hssf/record/EscherAggregate.java | 40 +++++++++++----- .../poi/hssf/usermodel/HSSFComment.java | 10 +++- .../poi/hssf/usermodel/HSSFPatriarch.java | 46 ++++++++++++------- .../poi/hssf/usermodel/HSSFPolygon.java | 5 +- .../apache/poi/hssf/usermodel/HSSFShape.java | 5 ++ .../poi/hssf/usermodel/HSSFShapeFactory.java | 3 ++ .../poi/hssf/usermodel/HSSFShapeGroup.java | 10 ++-- .../apache/poi/hssf/usermodel/HSSFSheet.java | 5 +- .../poi/hssf/usermodel/HSSFSimpleShape.java | 10 +++- .../poi/hssf/usermodel/HSSFTextbox.java | 5 +- .../hssf/usermodel/drawing/HSSFShapeType.java | 2 + .../poi/hssf/model/TestDrawingAggregate.java | 29 ++++++++++-- .../poi/hssf/model/TestDrawingShapes.java | 10 ++++ .../poi/hssf/usermodel/HSSFTestHelper.java | 28 +++++++---- .../poi/hssf/usermodel/TestComment.java | 19 ++++---- .../poi/hssf/usermodel/TestShapeGroup.java | 27 +++++++++++ .../apache/poi/hssf/usermodel/TestText.java | 3 +- 19 files changed, 195 insertions(+), 69 deletions(-) diff --git a/src/java/org/apache/poi/hssf/model/DrawingManager2.java b/src/java/org/apache/poi/hssf/model/DrawingManager2.java index c9993c2418..0d5e34f24d 100644 --- a/src/java/org/apache/poi/hssf/model/DrawingManager2.java +++ b/src/java/org/apache/poi/hssf/model/DrawingManager2.java @@ -112,7 +112,7 @@ public class DrawingManager2 /** * Finds the next available (1 based) drawing group id */ - short findNewDrawingGroupId() + public short findNewDrawingGroupId() { short dgId = 1; while ( drawingGroupExists( dgId ) ) @@ -147,4 +147,7 @@ public class DrawingManager2 return dgg; } + public void incrementDrawingsSaved(){ + dgg.setDrawingsSaved(dgg.getDrawingsSaved()+1); + } } diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index 1e0af24530..09d8e4b803 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -1497,7 +1497,7 @@ public final class InternalSheet { return -1; } - EscherAggregate aggregate = new EscherAggregate( drawingManager ); + EscherAggregate aggregate = new EscherAggregate(); loc = findFirstRecordLocBySid(EscherAggregate.sid); if (loc == -1) { loc = findFirstRecordLocBySid( WindowTwoRecord.sid ); diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index b5bb2121a0..11e2c8d4b0 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -524,7 +524,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); } } - if ((pos - offset) < buffer.length-1){ + if ((pos - offset) < buffer.length - 1) { byte[] drawingData = new byte[buffer.length - (pos - offset)]; System.arraycopy(buffer, (pos - offset), drawingData, 0, drawingData.length); pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); @@ -613,8 +613,8 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } int drawingRecordSize = rawEscherSize + (shapeToObj.size()) * 4; - if (rawEscherSize != 0 && spEndingOffsets.size()==1/**EMPTY**/){ - continueRecordsHeadersSize +=4; + if (rawEscherSize != 0 && spEndingOffsets.size() == 1/**EMPTY**/) { + continueRecordsHeadersSize += 4; } int objRecordSize = 0; for (Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); ) { @@ -1032,7 +1032,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { throw new IllegalArgumentException("Can not find client data record"); } - private void buildBaseTree(){ + private void buildBaseTree() { EscherContainerRecord dgContainer = new EscherContainerRecord(); EscherContainerRecord spgrContainer = new EscherContainerRecord(); EscherContainerRecord spContainer1 = new EscherContainerRecord(); @@ -1044,7 +1044,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { dg.setRecordId( EscherDgRecord.RECORD_ID ); short dgId = 1; dg.setOptions((short) (dgId << 4)); - dg.setNumShapes(1); + dg.setNumShapes(0); dg.setLastMSOSPID(1024); drawingGroupId = dg.getDrawingGroupId(); spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); @@ -1059,7 +1059,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { spgr.setRectY2(255); sp1.setRecordId(EscherSpRecord.RECORD_ID); sp1.setOptions((short) 0x0002); - sp1.setShapeId(1024); + sp1.setShapeId(-1); sp1.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH); dgContainer.addChildRecord(dg); dgContainer.addChildRecord(spgrContainer); @@ -1069,6 +1069,19 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { addEscherRecord(dgContainer); } + public void setDgId(short dgId) { + EscherContainerRecord dgContainer = getEscherContainer(); + EscherDgRecord dg = dgContainer.getChildById(EscherDgRecord.RECORD_ID); + dg.setOptions((short) (dgId << 4)); + } + + public void setMainSpRecordId(int shapeId){ + EscherContainerRecord dgContainer = getEscherContainer(); + EscherContainerRecord spContainer = (EscherContainerRecord) dgContainer.getChildById(EscherContainerRecord.SPGR_CONTAINER).getChild(0); + EscherSpRecord sp = (EscherSpRecord) spContainer.getChildById(EscherSpRecord.RECORD_ID); + sp.setShapeId(shapeId); + } + private void convertPatriarch(HSSFPatriarch patriarch) { EscherContainerRecord dgContainer = new EscherContainerRecord(); EscherDgRecord dg; @@ -1145,22 +1158,25 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } /** - * * @return tails records. We need to access them when building shapes. - * Every HSSFComment shape has a link to a NoteRecord from the tailRec collection. + * Every HSSFComment shape has a link to a NoteRecord from the tailRec collection. */ - public List getTailRecords(){ + public List getTailRecords() { return Collections.unmodifiableList(tailRec); } - public NoteRecord getNoteRecordByObj(ObjRecord obj){ - for (Record rec: tailRec){ + public NoteRecord getNoteRecordByObj(ObjRecord obj) { + for (Record rec : tailRec) { NoteRecord note = (NoteRecord) rec; CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) obj.getSubRecords().get(0); - if (note.getShapeId() == cod.getObjectId()){ + if (note.getShapeId() == cod.getObjectId()) { return note; } } return null; } + + public void addTailRecord(NoteRecord note){ + tailRec.add(note); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index add7e32728..3e844516e9 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -68,6 +68,12 @@ public class HSSFComment extends HSSFTextbox implements Comment { _note = note; } + @Override + void afterInsert(HSSFPatriarch patriarch) { + super.afterInsert(patriarch); + _patriarch._getBoundAggregate().addTailRecord(getNoteRecord()); + } + @Override protected ObjRecord createObjRecord() { ObjRecord obj = new ObjRecord(); @@ -96,7 +102,9 @@ public class HSSFComment extends HSSFTextbox implements Comment { @Override void setShapeId(int shapeId) { super.setShapeId(shapeId); - _note.setShapeId(shapeId-1024); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + cod.setObjectId((short) (shapeId)); + _note.setShapeId(shapeId); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 675c7d7f86..07fcc4d0d0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -38,10 +38,12 @@ import org.apache.poi.ss.usermodel.ClientAnchor; */ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { private final List _shapes = new ArrayList(); - private int _x1 = 0; - private int _y1 = 0 ; - private int _x2 = 1023; - private int _y2 = 255; +// private int _x1 = 0; +// private int _y1 = 0 ; +// private int _x2 = 1023; +// private int _y2 = 255; + + private final EscherSpgrRecord _spgrRecord; /** * The EscherAggregate we have been bound to. @@ -59,6 +61,18 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate){ _sheet = sheet; _boundAggregate = boundAggregate; + EscherContainerRecord spContainer = (EscherContainerRecord) _boundAggregate.getEscherContainer() + .getChildContainers().get(0).getChild(0); + _spgrRecord = spContainer.getChildById(EscherSpgrRecord.RECORD_ID); + buildShapeTree(); + } + + public void afterCreate(){ + DrawingManager2 drawingManager = _sheet.getWorkbook().getWorkbook().getDrawingManager(); + short dgId = drawingManager.findNewDrawingGroupId(); + _boundAggregate.setDgId(dgId); + _boundAggregate.setMainSpRecordId(newShapeId()); + drawingManager.incrementDrawingsSaved(); } /** @@ -234,17 +248,14 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * to these coordinates. */ public void setCoordinates(int x1, int y1, int x2, int y2){ - _x1 = x1; - _y1 = y1; - _x2 = x2; - _y2 = y2; + _spgrRecord.setRectY1(y1); + _spgrRecord.setRectY2(y2); + _spgrRecord.setRectX1(x1); + _spgrRecord.setRectX2(x2); } int newShapeId() { - if (_boundAggregate.getEscherContainer() == null){ - throw new IllegalStateException("We can use this method for only existing files"); - } - DrawingManager2 dm = _boundAggregate.getDrawingManager(); + DrawingManager2 dm = _sheet.getWorkbook().getWorkbook().getDrawingManager(); EscherDgRecord dg = _boundAggregate.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); short drawingGroupId = dg.getDrawingGroupId(); @@ -289,7 +300,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ public int getX1() { - return _x1; + return _spgrRecord.getRectX1(); } /** @@ -297,7 +308,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ public int getY1() { - return _y1; + return _spgrRecord.getRectY1(); } /** @@ -305,7 +316,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ public int getX2() { - return _x2; + return _spgrRecord.getRectX2(); } /** @@ -313,7 +324,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ public int getY2() { - return _y2; + return _spgrRecord.getRectY2(); } /** @@ -348,6 +359,9 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { void buildShapeTree(){ EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer(); + if (dgContainer == null){ + return; + } EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0); List spgrChildren = spgrConrainer.getChildContainers(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index 8d561a0ff1..44684a6052 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -69,10 +69,13 @@ public class HSSFPolygon extends HSSFShape { opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0)); opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + opt.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1)); + + opt.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000)); EscherRecord anchor = getAnchor().getEscherAnchor(); clientData.setRecordId(EscherClientDataRecord.RECORD_ID); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 09bf271fc5..be69ad6354 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -248,6 +248,11 @@ public abstract class HSSFShape { */ public void setLineStyle(int lineStyle) { setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle)); + if (getLineStyle() == HSSFShape.LINESTYLE_NONE){ + setPropertyValue(new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000)); + } else { + setPropertyValue( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); + } } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 1ee53171b6..e65afcb200 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -119,6 +119,9 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: shape = new HSSFSimpleShape(container, objRecord); break; + case CommonObjectDataSubRecord.OBJECT_TYPE_LINE: + shape = new HSSFSimpleShape(container, objRecord); + break; case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index eb023e0cae..f7fab2bbc8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -57,11 +57,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) { super(parent, anchor); - _spgrRecord = new EscherSpgrRecord(); - _spgrRecord.setRectX1(0); - _spgrRecord.setRectX2(1023); - _spgrRecord.setRectY1(0); - _spgrRecord.setRectY2(255); + _spgrRecord = ((EscherContainerRecord)_escherContainer.getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID); } @Override @@ -133,6 +129,8 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { shape.setShapeId(shapeId); _escherContainer.addChildRecord(spContainer); shape.afterInsert(_patriarch); + EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD); } } @@ -296,7 +294,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID); spRecord.setShapeId(shapeId); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); - cod.setObjectId((short) (shapeId-1024)); + cod.setObjectId((short) (shapeId)); } @Override diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index cbfb1807d1..aa25061c40 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -1683,7 +1683,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { _sheet.aggregateDrawingRecords(_book.getDrawingManager(), true); EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid); _patriarch = new HSSFPatriarch(this, agg); - agg.setPatriarch(_patriarch); + _patriarch.afterCreate(); +// agg.setPatriarch(_patriarch); } } return _patriarch; @@ -1738,7 +1739,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { if(agg == null) return null; _patriarch = new HSSFPatriarch(this, agg); - _patriarch.buildShapeTree(); +// _patriarch.buildShapeTree(); //HSSFShapeFactory.createShapeTree(); //agg.setPatriarch(_patriarch); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 62b9d6a8e0..bc000b715b 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -65,6 +65,7 @@ public class HSSFSimpleShape extends HSSFShape objTypeToShapeType.put(OBJECT_TYPE_RECTANGLE, HSSFShapeType.RECTANGLE.getType()); objTypeToShapeType.put(OBJECT_TYPE_PICTURE, HSSFShapeType.PICTURE.getType()); objTypeToShapeType.put(OBJECT_TYPE_LINE, HSSFShapeType.LINE.getType()); + objTypeToShapeType.put(OBJECT_TYPE_OVAL, HSSFShapeType.OVAL.getType()); } public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { @@ -93,10 +94,15 @@ public class HSSFSimpleShape extends HSSFShape EscherOptRecord optRecord = new EscherOptRecord(); optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); - optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); + optRecord.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); +// optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); + optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0)); + optRecord.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); + + optRecord.setEscherProperty( new EscherShapePathProperty( EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX ) ); + optRecord.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000)); optRecord.setRecordId( EscherOptRecord.RECORD_ID ); spContainer.addChildRecord(sp); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 1ed70f86a6..4e652de5e5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -119,11 +119,12 @@ public class HSSFTextbox extends HSSFSimpleShape { opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TEXT__TEXTBOTTOM, 0)); opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); + opt.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0)); - + opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1)); + opt.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000)); EscherRecord anchor = getAnchor().getEscherAnchor(); clientData.setRecordId(EscherClientDataRecord.RECORD_ID); diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java index 2e2b64eeb4..f386dd1cfe 100644 --- a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -1,5 +1,6 @@ package org.apache.poi.hssf.usermodel.drawing; +import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.usermodel.HSSFPicture; import org.apache.poi.hssf.usermodel.HSSFSimpleShape; import org.apache.poi.hssf.usermodel.HSSFTextbox; @@ -13,6 +14,7 @@ public enum HSSFShapeType { RECTANGLE((short)0x1, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_RECTANGLE), PICTURE((short)0x004B, HSSFPicture.class, HSSFSimpleShape.OBJECT_TYPE_PICTURE), LINE((short)0x14, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_LINE), + OVAL(EscherAggregate.ST_ELLIPSE, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_OVAL), TEXT((short)202, HSSFTextbox.class, HSSFTextbox.OBJECT_TYPE_TEXT), ROUND_RECTANGLE((short)0x2, null, null); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index 1f058c06da..b497212518 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -195,16 +195,35 @@ public class TestDrawingAggregate extends TestCase { } public void testBuildBaseTree(){ - EscherAggregate agg = new EscherAggregate(); HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(); - - HSSFPatriarch drawing = sheet.createDrawingPatriarch(); - EscherAggregate agg1 = HSSFTestHelper.getEscherAggregate(drawing); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); + EscherAggregate agg1 = new EscherAggregate(new HSSFTestHelper.MockDrawingManager()); + EscherSpgrRecord spgr = new EscherSpgrRecord(); + spgr.setRectY1(0); + spgr.setRectY2(255); + spgr.setRectX1(0); + spgr.setRectX2(1023); + EscherContainerRecord spContainer = new EscherContainerRecord(); + spContainer.addChildRecord(spgr); + EscherContainerRecord spgrContainer = new EscherContainerRecord(); + spgrContainer.addChildRecord(spContainer); + EscherContainerRecord dgContainer = new EscherContainerRecord(); + dgContainer.addChildRecord(spgrContainer); + agg1.addEscherRecord(dgContainer); + agg1.setPatriarch(HSSFTestHelper.createTestPatriarch(sheet, agg1)); + agg1.clear(); HSSFTestHelper.callConvertPatriarch(agg1); agg1.setPatriarch(null); - + agg.setPatriarch(null); +// + EscherSpRecord sp = (EscherSpRecord) agg.getEscherContainer().getChildContainers().get(0).getChild(0).getChild(1); + sp.setShapeId(1025); + EscherDgRecord dg = (EscherDgRecord) agg.getEscherContainer().getChild(0); + dg.setNumShapes(1); + dg.setOptions((short) (1 << 4)); byte[] aggS = agg.serialize(); byte []agg1S = agg1.serialize(); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 4e120a7cb8..e50aa47adf 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -324,4 +324,14 @@ public class TestDrawingShapes extends TestCase { textbox.setLineStyleColor(textbox.getLineStyleColor()); assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); } + + public void testDgRecordNumShapes(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + EscherAggregate aggregate = HSSFTestHelper.getEscherAggregate(patriarch); + EscherDgRecord dgRecord = (EscherDgRecord) aggregate.getEscherRecord(0).getChild(0); + assertEquals(dgRecord.getNumShapes(), 1); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 214121d940..3aafa04edd 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -16,9 +16,7 @@ ==================================================================== */ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; @@ -26,6 +24,7 @@ import org.apache.poi.hssf.record.EscherAggregate; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Map; /** @@ -35,11 +34,7 @@ import java.util.Map; */ public class HSSFTestHelper { - private static class MockDrawingManager extends DrawingManager2 { -// -// public MockDrawingManager(EscherDggRecord dgg) { -// super(dgg); -// } + public static class MockDrawingManager extends DrawingManager2 { public MockDrawingManager (){ super(null); @@ -47,7 +42,22 @@ public class HSSFTestHelper { @Override public int allocateShapeId(short drawingGroupId) { - return 0; //Mock value + return 1025; //Mock value + } + + @Override + public int allocateShapeId(short drawingGroupId, EscherDgRecord dg) { + return 1025; + } + + public EscherDgRecord createDgRecord() + { + EscherDgRecord dg = new EscherDgRecord(); + dg.setRecordId( EscherDgRecord.RECORD_ID ); + dg.setOptions( (short) (16) ); + dg.setNumShapes( 1 ); + dg.setLastMSOSPID( 1024 ); + return dg; } } /** diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java index 91b1a7cb19..376edc32b1 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -5,10 +5,7 @@ import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.model.CommentShape; import org.apache.poi.hssf.model.HSSFTestModelHelper; -import org.apache.poi.hssf.record.CommonObjectDataSubRecord; -import org.apache.poi.hssf.record.NoteRecord; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.hssf.record.*; import java.io.IOException; import java.util.Arrays; @@ -29,7 +26,7 @@ public class TestComment extends TestCase { HSSFCell cell = row.createCell(0); cell.setCellComment(comment); - CommentShape commentShape = HSSFTestModelHelper.createCommentShape(0, comment); + CommentShape commentShape = HSSFTestModelHelper.createCommentShape(1025, comment); assertEquals(comment.getEscherContainer().getChildRecords().size(), 5); assertEquals(commentShape.getSpContainer().getChildRecords().size(), 5); @@ -207,12 +204,16 @@ public class TestComment extends TestCase { HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); + assertEquals(agg.getTailRecords().size(), 0); + HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); + assertEquals(agg.getTailRecords().size(), 1); HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor()); - //5 properties of HSSFShape + 8 of HSSFTextbox - assertEquals(comment._optRecord.getEscherProperties().size(), 13); + //6 properties of HSSFShape + 8 of HSSFTextbox + assertEquals(comment._optRecord.getEscherProperties().size(), 14); } public void testShapeId(){ @@ -232,10 +233,10 @@ public class TestComment extends TestCase { assertEquals(comment.getShapeId(), 2024); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0); - assertEquals(cod.getObjectId(), 1000); + assertEquals(cod.getObjectId(), 2024); EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0); assertEquals(spRecord.getShapeId(), 2024); assertEquals(comment.getShapeId(), 2024); - assertEquals(comment.getNoteRecord().getShapeId(), 1000); + assertEquals(comment.getNoteRecord().getShapeId(), 2024); } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java index bdbf25fc4d..5eb93f6e3e 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java @@ -2,9 +2,11 @@ package org.apache.poi.hssf.usermodel; import junit.framework.TestCase; import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.record.ObjRecord; +import java.lang.reflect.Field; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -222,4 +224,29 @@ public class TestShapeGroup extends TestCase{ group.getShapeId(); } + + public void testSpgrRecord(){ + HSSFWorkbook wb = new HSSFWorkbook(); + + // create a sheet with a text box + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + assertSame(((EscherContainerRecord)group.getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID), getSpgrRecord(group)); + } + + private static EscherSpgrRecord getSpgrRecord(HSSFShapeGroup group) { + Field spgrField = null; + try { + spgrField = group.getClass().getDeclaredField("_spgrRecord"); + spgrField.setAccessible(true); + return (EscherSpgrRecord) spgrField.get(group); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java index 213c5be674..18eefd4786 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java @@ -21,7 +21,7 @@ public class TestText extends TestCase { HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); - TextboxShape textboxShape = HSSFTestModelHelper.createTextboxShape(0, textbox); + TextboxShape textboxShape = HSSFTestModelHelper.createTextboxShape(1025, textbox); assertEquals(textbox.getEscherContainer().getChildRecords().size(), 5); assertEquals(textboxShape.getSpContainer().getChildRecords().size(), 5); @@ -52,7 +52,6 @@ public class TestText extends TestCase { assertTrue(Arrays.equals(expected, actual)); ObjRecord obj = textbox.getObjRecord(); - ((CommonObjectDataSubRecord) obj.getSubRecords().get(0)).setObjectId(-1024); ObjRecord objShape = textboxShape.getObjRecord(); expected = obj.serialize(); From 8b027ef5cdef15ace8ba6585458a32209d9e6928 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Wed, 11 Jul 2012 12:08:38 +0000 Subject: [PATCH 17/32] checked all examples, added several features git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1360132 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/record/EscherAggregate.java | 55 +++++++++---- .../poi/hssf/usermodel/EscherGraphics.java | 1 + .../apache/poi/hssf/usermodel/HSSFAnchor.java | 4 +- .../apache/poi/hssf/usermodel/HSSFCell.java | 37 +-------- .../poi/hssf/usermodel/HSSFChildAnchor.java | 20 +++-- .../poi/hssf/usermodel/HSSFClientAnchor.java | 25 +++--- .../poi/hssf/usermodel/HSSFComment.java | 46 +++++------ .../poi/hssf/usermodel/HSSFPatriarch.java | 34 ++++++-- .../poi/hssf/usermodel/HSSFPicture.java | 45 ++++++++++- .../poi/hssf/usermodel/HSSFPolygon.java | 14 ++-- .../apache/poi/hssf/usermodel/HSSFShape.java | 44 +++++++--- .../poi/hssf/usermodel/HSSFShapeFactory.java | 2 +- .../poi/hssf/usermodel/HSSFShapeGroup.java | 30 +++++-- .../apache/poi/hssf/usermodel/HSSFSheet.java | 35 ++++---- .../poi/hssf/usermodel/HSSFSimpleShape.java | 75 +++++++++++++++--- .../poi/hssf/usermodel/HSSFTextbox.java | 70 ++++++---------- .../poi/hssf/usermodel/HSSFUnknownShape.java | 12 ++- .../poi/hssf/usermodel/HSSFWorkbook.java | 2 +- .../poi/hssf/model/TestDrawingShapes.java | 15 +++- .../apache/poi/hssf/model/TestHSSFAnchor.java | 34 ++++++++ .../poi/hssf/usermodel/HSSFTestHelper.java | 2 +- .../poi/hssf/usermodel/TestComment.java | 3 +- .../poi/hssf/usermodel/TestHSSFPicture.java | 61 ++++++++++++++ .../poi/hssf/usermodel/TestPolygon.java | 4 +- test-data/spreadsheet/drawings.xls | Bin 821760 -> 836096 bytes 25 files changed, 455 insertions(+), 215 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 11e2c8d4b0..7079cf7dc1 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -303,6 +303,12 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { protected HSSFPatriarch patriarch; + /** + * if we want to get the same byte array if we open existing file and serialize it we should save + * note records in right order. This list contains ids of NoteRecords in such order as we read from existing file + */ + private List _tailIds = new ArrayList(); + /** * Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */ @@ -313,7 +319,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { /** * list of "tail" records that need to be serialized after all drawing group records */ - private List tailRec = new ArrayList(); + private Map tailRec = new HashMap(); public EscherAggregate() { buildBaseTree(); @@ -440,7 +446,8 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { while (loc < records.size()) { if (sid(records, loc) == NoteRecord.sid) { NoteRecord r = (NoteRecord) records.get(loc); - agg.tailRec.add(r); + agg.tailRec.put(r.getShapeId(), r); + agg._tailIds.add(agg._tailIds.size(), r.getShapeId()); } else { break; } @@ -531,8 +538,18 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } // write records that need to be serialized after all drawing group records - for (i = 0; i < tailRec.size(); i++) { - Record rec = tailRec.get(i); + Map tailCopy = new HashMap(tailRec); + // at first we should save records in correct order which were already in the file during EscherAggregate.createAggregate() + for (Integer id : _tailIds){ + NoteRecord note = tailCopy.get(id); + if (null != note){ + pos += note.serialize(pos, data); + tailCopy.remove(id); + } + } + // Add all other notes which were created after createAggregate() + for (i = 0; i < tailCopy.size(); i++) { + Record rec = (Record) tailCopy.values().toArray()[i]; pos += rec.serialize(pos, data); } int bytesWritten = pos - offset; @@ -622,7 +639,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { objRecordSize += r.getRecordSize(); } int tailRecordSize = 0; - for (Iterator iterator = tailRec.iterator(); iterator.hasNext(); ) { + for (Iterator iterator = tailRec.values().iterator(); iterator.hasNext(); ) { Record r = (Record) iterator.next(); tailRecordSize += r.getRecordSize(); } @@ -636,6 +653,10 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return shapeToObj.put(r, objRecord); } + public void removeShapeToObjRecord(EscherRecord rec){ + shapeToObj.remove(rec); + } + public HSSFPatriarch getPatriarch() { return patriarch; } @@ -938,7 +959,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { if (shapeModel instanceof CommentShape) { CommentShape comment = (CommentShape) shapeModel; - tailRec.add(comment.getNoteRecord()); + tailRec.put(comment.getNoteRecord().getShapeId(), comment.getNoteRecord()); } } @@ -1058,7 +1079,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { spgr.setRectX2(1023); spgr.setRectY2(255); sp1.setRecordId(EscherSpRecord.RECORD_ID); + sp1.setOptions((short) 0x0002); + sp1.setVersion((short) 0x2); sp1.setShapeId(-1); sp1.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH); dgContainer.addChildRecord(dg); @@ -1161,22 +1184,20 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { * @return tails records. We need to access them when building shapes. * Every HSSFComment shape has a link to a NoteRecord from the tailRec collection. */ - public List getTailRecords() { - return Collections.unmodifiableList(tailRec); + public Map getTailRecords() { + return tailRec; } public NoteRecord getNoteRecordByObj(ObjRecord obj) { - for (Record rec : tailRec) { - NoteRecord note = (NoteRecord) rec; - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) obj.getSubRecords().get(0); - if (note.getShapeId() == cod.getObjectId()) { - return note; - } - } - return null; + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) obj.getSubRecords().get(0); + return tailRec.get(cod.getObjectId()); } public void addTailRecord(NoteRecord note){ - tailRec.add(note); + tailRec.put(note.getShapeId(), note); + } + + public void removeTailRecord(NoteRecord note){ + tailRec.remove(note.getShapeId()); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java index 7500ac7b7b..90a93e5260 100644 --- a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java +++ b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java @@ -349,6 +349,7 @@ public class EscherGraphics shape.setLineStyle(HSSFShape.LINESTYLE_NONE); shape.setFillColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue()); shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue()); + shape.setNoFill(false); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java index 2fe36130cf..32422168b5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java @@ -31,6 +31,9 @@ import org.apache.poi.ddf.EscherRecord; */ public abstract class HSSFAnchor { + protected boolean _isHorizontallyFlipped = false; + protected boolean _isVerticallyFlipped = false; + public HSSFAnchor() { createEscherAnchor(); } @@ -51,7 +54,6 @@ public abstract class HSSFAnchor { return new HSSFClientAnchor((EscherClientAnchorRecord) container.getChildById(EscherClientAnchorRecord.RECORD_ID)); } return null; -// throw new IllegalArgumentException("continer must have anchor record"); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 28c15fac72..67fb64f227 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -1021,7 +1021,7 @@ public class HSSFCell implements Cell { */ public HSSFComment getCellComment(){ if (_comment == null) { - _comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn()); + _comment = _sheet.findCellComment(_record.getRow(), _record.getColumn()); } return _comment; } @@ -1033,41 +1033,12 @@ public class HSSFCell implements Cell { * all comments after performing this action! */ public void removeCellComment() { - HSSFComment comment = findCellComment(_sheet.getSheet(), _record.getRow(), _record.getColumn()); + HSSFComment comment = _sheet.findCellComment(_record.getRow(), _record.getColumn()); _comment = null; - - if(comment == null) { - // Nothing to do + if (null == comment){ return; } - - // Zap the underlying NoteRecord - List sheetRecords = _sheet.getSheet().getRecords(); - sheetRecords.remove(comment.getNoteRecord()); - - // If we have a TextObjectRecord, is should - // be proceeed by: - // MSODRAWING with container - // OBJ - // MSODRAWING with EscherTextboxRecord - if(comment.getTextObjectRecord() != null) { - TextObjectRecord txo = comment.getTextObjectRecord(); - int txoAt = sheetRecords.indexOf(txo); - - if(sheetRecords.get(txoAt-3) instanceof DrawingRecord && - sheetRecords.get(txoAt-2) instanceof ObjRecord && - sheetRecords.get(txoAt-1) instanceof DrawingRecord) { - // Zap these, in reverse order - sheetRecords.remove(txoAt-1); - sheetRecords.remove(txoAt-2); - sheetRecords.remove(txoAt-3); - } else { - throw new IllegalStateException("Found the wrong records before the TextObjectRecord, can't remove comment"); - } - - // Now remove the text record - sheetRecords.remove(txo); - } + _sheet.getDrawingPatriarch().removeShape(comment); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java index 38c4f5f0e2..9df47d64c1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java @@ -34,7 +34,13 @@ public final class HSSFChildAnchor extends HSSFAnchor { } public HSSFChildAnchor(int dx1, int dy1, int dx2, int dy2) { - super(dx1, dy1, dx2, dy2); + super(Math.min(dx1, dx2), Math.min(dy1, dy2), Math.max(dx1, dx2), Math.max(dy1, dy2)); + if (dx1 > dx2){ + _isHorizontallyFlipped = true; + } + if (dy1 > dy2){ + _isVerticallyFlipped = true; + } } @Override @@ -78,18 +84,18 @@ public final class HSSFChildAnchor extends HSSFAnchor { } public void setAnchor(int dx1, int dy1, int dx2, int dy2) { - setDx1(dx1); - setDy1(dy1); - setDx2(dx2); - setDy2(dy2); + setDx1(Math.min(dx1, dx2)); + setDy1(Math.min(dy1, dy2)); + setDx2(Math.max(dx1, dx2)); + setDy2(Math.max(dy1, dy2)); } public boolean isHorizontallyFlipped() { - return getDx1() > getDx2(); + return _isHorizontallyFlipped; } public boolean isVerticallyFlipped() { - return getDy1() > getDy2(); + return _isVerticallyFlipped; } @Override diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java index 49e20a42f1..ad77c7a4d5 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java @@ -66,10 +66,17 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { checkRange(row1, 0, 255 * 256, "row1"); checkRange(row2, 0, 255 * 256, "row2"); - setCol1(col1); - setCol2(col2); - setRow1(row1); - setRow2(row2); + setCol1((short) Math.min(col1, col2)); + setCol2((short) Math.max(col1, col2)); + setRow1((short) Math.min(row1, row2)); + setRow2((short) Math.max(row1, row2)); + + if (col1 > col2){ + _isHorizontallyFlipped = true; + } + if (row1 > row2){ + _isVerticallyFlipped = true; + } } /** @@ -187,20 +194,14 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { * @return true if the anchor goes from right to left. */ public boolean isHorizontallyFlipped() { - if (getCol1() == getCol2()) { - return getDx1() > getDx2(); - } - return getCol1() > getCol2(); + return _isHorizontallyFlipped; } /** * @return true if the anchor goes from bottom to top. */ public boolean isVerticallyFlipped() { - if (getRow1() == getRow2()) { - return getDy1() > getDy2(); - } - return getRow1() > getRow2(); + return _isVerticallyFlipped; } @Override diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 3e844516e9..ea8ae3c7e7 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -16,7 +16,7 @@ ==================================================================== */ package org.apache.poi.hssf.usermodel; -import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.*; import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.RichTextString; @@ -64,7 +64,6 @@ public class HSSFComment extends HSSFTextbox implements Comment { protected HSSFComment(NoteRecord note, TextObjectRecord txo) { this(null, new HSSFClientAnchor()); - _textObjectRecord = txo; _note = note; } @@ -74,6 +73,17 @@ public class HSSFComment extends HSSFTextbox implements Comment { _patriarch._getBoundAggregate().addTailRecord(getNoteRecord()); } + @Override + protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spContainer = super.createSpContainer(); + EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID); + removeEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT); + removeEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT); + removeEscherProperty(opt, EscherProperties.TEXT__TEXTTOP); + removeEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); + return spContainer; + } + @Override protected ObjRecord createObjRecord() { ObjRecord obj = new ObjRecord(); @@ -94,7 +104,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { private NoteRecord createNoteRecord(){ NoteRecord note = new NoteRecord(); - note.setFlags(NoteRecord.NOTE_VISIBLE); + note.setFlags(NoteRecord.NOTE_HIDDEN); note.setAuthor(""); return note; } @@ -102,7 +112,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { @Override void setShapeId(int shapeId) { super.setShapeId(shapeId); - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); cod.setObjectId((short) (shapeId)); _note.setShapeId(shapeId); } @@ -187,20 +197,6 @@ public class HSSFComment extends HSSFTextbox implements Comment { if (_note != null) _note.setAuthor(author); } - /** - * Sets the rich text string used by this comment. - * - * @param string Sets the rich text string used by this object. - */ - public void setString(RichTextString string) { - HSSFRichTextString hstring = (HSSFRichTextString) string; - //if font is not set we must set the default one - if (hstring.numFormattingRuns() == 0) hstring.applyFont((short) 0); - - _textObjectRecord.setStr(hstring); - super.setString(string); - } - /** * Returns the underlying Note record */ @@ -208,10 +204,14 @@ public class HSSFComment extends HSSFTextbox implements Comment { return _note; } - /** - * Returns the underlying Text record - */ - public TextObjectRecord getTextObjectRecord() { - return _textObjectRecord; + @Override + public void setShapeType(int shapeType) { + throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); + } + + public void afterRemove(HSSFPatriarch patriarch){ + patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID)); + patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + patriarch._getBoundAggregate().removeTailRecord(getNoteRecord()); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 07fcc4d0d0..aa8603635b 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -44,6 +44,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { // private int _y2 = 255; private final EscherSpgrRecord _spgrRecord; + private final EscherContainerRecord _mainSpgrContainer; /** * The EscherAggregate we have been bound to. @@ -61,12 +62,23 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate){ _sheet = sheet; _boundAggregate = boundAggregate; + _mainSpgrContainer = _boundAggregate.getEscherContainer().getChildContainers().get(0); EscherContainerRecord spContainer = (EscherContainerRecord) _boundAggregate.getEscherContainer() .getChildContainers().get(0).getChild(0); _spgrRecord = spContainer.getChildById(EscherSpgrRecord.RECORD_ID); buildShapeTree(); } + /** + * remove first level shapes + * @param shape to be removed + */ + public void removeShape(HSSFShape shape){ + _mainSpgrContainer.removeChildRecord(shape.getEscherContainer()); + shape.afterRemove(this); + _shapes.remove(shape); + } + public void afterCreate(){ DrawingManager2 drawingManager = _sheet.getWorkbook().getWorkbook().getDrawingManager(); short dgId = drawingManager.findNewDrawingGroupId(); @@ -106,6 +118,13 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { addShape(shape); //open existing file onCreate(shape); + EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + if (shape.anchor.isHorizontallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); + } + if (shape.anchor.isVerticallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); + } return shape; } @@ -125,8 +144,13 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { //open existing file onCreate(shape); - EscherBSERecord bse = _sheet.getWorkbook().getWorkbook().getBSERecord(pictureIndex); - bse.setRef(bse.getRef() + 1); + EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + if (shape.anchor.isHorizontallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); + } + if (shape.anchor.isVerticallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); + } return shape; } @@ -368,11 +392,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { for(int i = 0; i < spgrChildren.size(); i++){ EscherContainerRecord spContainer = spgrChildren.get(i); if (i == 0){ - EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); - setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); + continue; } else { HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 985bb8f177..9eff50dd3e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -19,6 +19,7 @@ package org.apache.poi.hssf.usermodel; import java.awt.Dimension; import java.io.ByteArrayInputStream; +import java.io.UnsupportedEncodingException; import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.ObjRecord; @@ -69,7 +70,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { public int getPictureIndex() { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.BLIP__BLIPTODISPLAY); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.BLIP__BLIPTODISPLAY); if (null == property){ return -1; } @@ -81,6 +82,15 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { setPropertyValue(new EscherSimpleProperty( EscherProperties.BLIP__BLIPTODISPLAY, false, true, pictureIndex)); } + @Override + protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spContainer = super.createSpContainer(); + EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID); + removeEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING); + removeEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH); + return spContainer; + } + /** * Resize the image *

@@ -237,4 +247,37 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord(); return new HSSFPictureData(blipRecord); } + + @Override + void afterInsert(HSSFPatriarch patriarch) { + super.afterInsert(patriarch); + EscherBSERecord bse = + patriarch._sheet.getWorkbook().getWorkbook().getBSERecord(getPictureIndex()); + bse.setRef(bse.getRef() + 1); + } + + /** + * The color applied to the lines of this shape. + */ + public String getAdditionalData() { + EscherComplexProperty propFile = (EscherComplexProperty) getOptRecord().lookup( + EscherProperties.BLIP__BLIPFILENAME); + try { + if (null == propFile){ + return ""; + } + return new String(propFile.getComplexData(), "UTF-16LE").trim(); + } catch (UnsupportedEncodingException e) { + return ""; + } + } + + public void setAdditionalData(String data){ + try { + EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, true, data.getBytes("UTF-16LE")); + setPropertyValue(prop); + } catch (UnsupportedEncodingException e) { + System.out.println("Unsupported encoding: UTF-16LE"); + } + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index 44684a6052..079ae744ae 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -106,8 +106,12 @@ public class HSSFPolygon extends HSSFShape { return obj; } + @Override + protected void afterRemove(HSSFPatriarch patriarch) { + } + public int[] getXPoints() { - EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); if (null == verticesProp){ return new int[]{}; } @@ -121,7 +125,7 @@ public class HSSFPolygon extends HSSFShape { } public int[] getYPoints() { - EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); if (null == verticesProp){ return new int[]{}; } @@ -188,18 +192,18 @@ public class HSSFPolygon extends HSSFShape { } public int getDrawAreaWidth() { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__RIGHT); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__RIGHT); return property == null ? 100: property.getPropertyValue(); } public int getDrawAreaHeight() { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__BOTTOM); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__BOTTOM); return property == null ? 100: property.getPropertyValue(); } @Override void afterInsert(HSSFPatriarch patriarch) { EscherAggregate agg = patriarch._getBoundAggregate(); - agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index be69ad6354..4e01aa63ea 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -21,6 +21,8 @@ import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.ObjRecord; +import java.util.Iterator; + /** * An abstract shape. * @@ -53,9 +55,12 @@ public abstract class HSSFShape { HSSFAnchor anchor; HSSFPatriarch _patriarch; - protected final EscherContainerRecord _escherContainer; - protected final ObjRecord _objRecord; - protected final EscherOptRecord _optRecord; + private final EscherContainerRecord _escherContainer; + private final ObjRecord _objRecord; + private final EscherOptRecord _optRecord; + + public final static int NO_FILLHITTEST_TRUE = 0x00110000; + public final static int NO_FILLHITTEST_FALSE = 0x00010000; public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord) { this._escherContainer = spContainer; @@ -80,6 +85,17 @@ public abstract class HSSFShape { protected abstract ObjRecord createObjRecord(); + protected abstract void afterRemove(HSSFPatriarch patriarch); + + protected void removeEscherProperty(EscherOptRecord opt, int num){ + for ( Iterator iterator = opt.getEscherProperties().iterator(); iterator.hasNext(); ) { + EscherProperty prop = iterator.next(); + if (prop.getPropertyNumber() == num){ + iterator.remove(); + } + } + } + void setShapeId(int shapeId){ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); spRecord.setShapeId(shapeId); @@ -91,8 +107,7 @@ public abstract class HSSFShape { return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); } - void afterInsert(HSSFPatriarch patriarch){ - } + abstract void afterInsert(HSSFPatriarch patriarch); public EscherContainerRecord getEscherContainer() { return _escherContainer; @@ -102,6 +117,10 @@ public abstract class HSSFShape { return _objRecord; } + public EscherOptRecord getOptRecord() { + return _optRecord; + } + /** * Gets the parent shape. */ @@ -248,10 +267,13 @@ public abstract class HSSFShape { */ public void setLineStyle(int lineStyle) { setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, lineStyle)); - if (getLineStyle() == HSSFShape.LINESTYLE_NONE){ - setPropertyValue(new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000)); - } else { - setPropertyValue( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); + if (getLineStyle() != HSSFShape.LINESTYLE_SOLID) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, 0)); + if (getLineStyle() == HSSFShape.LINESTYLE_NONE){ + setPropertyValue(new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000)); + } else { + setPropertyValue( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); + } } } @@ -260,14 +282,14 @@ public abstract class HSSFShape { */ public boolean isNoFill() { EscherBoolProperty property = _optRecord.lookup(EscherProperties.FILL__NOFILLHITTEST); - return property == null ? NO_FILL_DEFAULT : property.isTrue(); + return property == null ? NO_FILL_DEFAULT : property.getPropertyValue() == NO_FILLHITTEST_TRUE; } /** * Sets whether this shape is filled or transparent. */ public void setNoFill(boolean noFill) { - setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? 1 : 0)); + setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? NO_FILLHITTEST_TRUE : NO_FILLHITTEST_FALSE)); } protected void setPropertyValue(EscherProperty property){ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index e65afcb200..eab30fcdaa 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -117,7 +117,7 @@ public class HSSFShapeFactory { shape = new HSSFPicture(container, objRecord); break; case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE: - shape = new HSSFSimpleShape(container, objRecord); + shape = new HSSFSimpleShape(container, objRecord, txtRecord); break; case CommonObjectDataSubRecord.OBJECT_TYPE_LINE: shape = new HSSFSimpleShape(container, objRecord); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index f7fab2bbc8..32471f5176 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -57,7 +57,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) { super(parent, anchor); - _spgrRecord = ((EscherContainerRecord)_escherContainer.getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID); + _spgrRecord = ((EscherContainerRecord)getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID); } @Override @@ -122,12 +122,16 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { return obj; } + @Override + protected void afterRemove(HSSFPatriarch patriarch) { + } + private void onCreate(HSSFShape shape){ if(_patriarch != null && _patriarch._getBoundAggregate().getPatriarch() == null){ EscherContainerRecord spContainer = shape.getEscherContainer(); int shapeId = _patriarch.newShapeId(); shape.setShapeId(shapeId); - _escherContainer.addChildRecord(spContainer); + getEscherContainer().addChildRecord(spContainer); shape.afterInsert(_patriarch); EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD); @@ -172,6 +176,13 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { shape.anchor = anchor; shapes.add(shape); onCreate(shape); + EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + if (shape.anchor.isHorizontallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); + } + if (shape.anchor.isVerticallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); + } return shape; } @@ -220,6 +231,13 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { shape.setPictureIndex(pictureIndex); shapes.add(shape); onCreate(shape); + EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + if (shape.anchor.isHorizontallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); + } + if (shape.anchor.isVerticallyFlipped()){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); + } return shape; } @@ -284,22 +302,22 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { @Override void afterInsert(HSSFPatriarch patriarch){ EscherAggregate agg = patriarch._getBoundAggregate(); - EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER); agg.associateShapeToObjRecord(containerRecord.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); } @Override void setShapeId(int shapeId){ - EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER); EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID); spRecord.setShapeId(shapeId); - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); cod.setObjectId((short) (shapeId)); } @Override int getShapeId(){ - EscherContainerRecord containerRecord = _escherContainer.getChildById(EscherContainerRecord.SP_CONTAINER); + EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER); return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index aa25061c40..f294946008 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -1358,15 +1358,17 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { // exist for cells which are null if(moveComments) { // This code would get simpler if NoteRecords could be organised by HSSFRow. - for(int i=noteRecs.length-1; i>=0; i--) { - NoteRecord nr = noteRecs[i]; - if (nr.getRow() != rowNum) { + HSSFPatriarch patriarch = createDrawingPatriarch(); + for(int i=patriarch.getChildren().size()-1; i>=0; i--){ + HSSFShape shape = patriarch.getChildren().get(i); + if (!(shape instanceof HSSFComment)){ continue; } - HSSFComment comment = getCellComment(rowNum, nr.getColumn()); - if (comment != null) { - comment.setRow(rowNum + n); + HSSFComment comment = (HSSFComment) shape; + if (comment.getRow() != rowNum){ + continue; } + comment.setRow(rowNum + n); } } } @@ -1875,20 +1877,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @return cell comment or null if not found */ public HSSFComment getCellComment(int row, int column) { - // Don't call findCellComment directly, otherwise - // two calls to this method will result in two - // new HSSFComment instances, which is bad - HSSFRow r = getRow(row); - if(r != null) { - HSSFCell c = r.getCell(column); - if(c != null) { - return c.getCellComment(); - } - // No cell, so you will get new - // objects every time, sorry... - return HSSFCell.findCellComment(_sheet, row, column); - } - return null; + return findCellComment(row, column); } public HSSFSheetConditionalFormatting getSheetConditionalFormatting() { @@ -2009,7 +1998,11 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { } protected HSSFComment findCellComment(int row, int column) { - return lookForComment(getDrawingPatriarch(), row, column); + HSSFPatriarch patriarch = getDrawingPatriarch(); + if (null == patriarch){ + patriarch = createDrawingPatriarch(); + } + return lookForComment(patriarch, row, column); } private HSSFComment lookForComment(HSSFShapeContainer container, int row, int column){ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index bc000b715b..ac4697ac14 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -18,11 +18,9 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; -import org.apache.poi.hssf.record.CommonObjectDataSubRecord; -import org.apache.poi.hssf.record.EndSubRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; +import org.apache.poi.ss.usermodel.RichTextString; import java.util.HashMap; import java.util.Map; @@ -61,6 +59,8 @@ public class HSSFSimpleShape extends HSSFShape private static final Map objTypeToShapeType = new HashMap(); + private TextObjectRecord _textObjectRecord; + static { objTypeToShapeType.put(OBJECT_TYPE_RECTANGLE, HSSFShapeType.RECTANGLE.getType()); objTypeToShapeType.put(OBJECT_TYPE_PICTURE, HSSFShapeType.PICTURE.getType()); @@ -68,6 +68,11 @@ public class HSSFSimpleShape extends HSSFShape objTypeToShapeType.put(OBJECT_TYPE_OVAL, HSSFShapeType.OVAL.getType()); } + public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) { + super(spContainer, objRecord); + this._textObjectRecord = _textObjectRecord; + } + public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { super(spContainer, objRecord); } @@ -75,7 +80,18 @@ public class HSSFSimpleShape extends HSSFShape public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) { super( parent, anchor ); - setShapeType(OBJECT_TYPE_LINE); + _textObjectRecord = createTextObjRecord(); + } + + public TextObjectRecord getTextObjectRecord() { + return _textObjectRecord; + } + + protected TextObjectRecord createTextObjRecord(){ + TextObjectRecord obj = new TextObjectRecord(); + obj.setTextLocked(true); + obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE); + return obj; } @Override @@ -87,10 +103,11 @@ public class HSSFSimpleShape extends HSSFShape EscherSpRecord sp = new EscherSpRecord(); sp.setRecordId( EscherSpRecord.RECORD_ID ); sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE ); + sp.setVersion((short) 0x2); EscherClientDataRecord clientData = new EscherClientDataRecord(); clientData.setRecordId( EscherClientDataRecord.RECORD_ID ); - clientData.setOptions( (short) 0x0000 ); + clientData.setOptions( (short) (0x0000) ); EscherOptRecord optRecord = new EscherOptRecord(); optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID)); @@ -98,7 +115,7 @@ public class HSSFSimpleShape extends HSSFShape // optRecord.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); optRecord.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0)); + optRecord.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, NO_FILLHITTEST_FALSE)); optRecord.setEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008)); optRecord.setEscherProperty( new EscherShapePathProperty( EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX ) ); @@ -127,10 +144,46 @@ public class HSSFSimpleShape extends HSSFShape return obj; } + @Override + protected void afterRemove(HSSFPatriarch patriarch) { + } + + /** + * @return the rich text string for this textbox. + */ + public HSSFRichTextString getString() { + return _textObjectRecord.getStr(); + } + + /** + * @param string Sets the rich text string used by this object. + */ + public void setString(RichTextString string) { + HSSFRichTextString rtr = (HSSFRichTextString) string; + // If font is not set we must set the default one + if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); + EscherTextboxRecord textbox = getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID); + if (string.getString()!= null && !string.getString().equals("")){ + if (null == textbox){ + EscherTextboxRecord escherTextbox = new EscherTextboxRecord(); + escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID); + escherTextbox.setOptions((short) 0x0000); + getEscherContainer().addChildRecord(escherTextbox); + _patriarch._getBoundAggregate().associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord()); + } + } else { + if (null != textbox){ + getEscherContainer().removeChildRecord(textbox); + _patriarch._getBoundAggregate().removeShapeToObjRecord(textbox); + } + } + _textObjectRecord.setStr(rtr); + } + @Override void afterInsert(HSSFPatriarch patriarch){ EscherAggregate agg = patriarch._getBoundAggregate(); - agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); } @@ -145,7 +198,7 @@ public class HSSFSimpleShape extends HSSFShape * @see #OBJECT_TYPE_COMMENT */ public int getShapeType() { - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); return cod.getObjectType(); } @@ -161,9 +214,9 @@ public class HSSFSimpleShape extends HSSFShape * @see #OBJECT_TYPE_COMMENT */ public void setShapeType( int shapeType ){ - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); cod.setObjectType((short) shapeType); - EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); + EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); if (null == objTypeToShapeType.get((short)shapeType)){ System.out.println("Unknown shape type: "+shapeType); return; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 4e652de5e5..af39d59784 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -47,11 +47,8 @@ public class HSSFTextbox extends HSSFSimpleShape { public final static short VERTICAL_ALIGNMENT_JUSTIFY = 4; public final static short VERTICAL_ALIGNMENT_DISTRIBUTED = 7; - protected TextObjectRecord _textObjectRecord; - public HSSFTextbox(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) { - super(spContainer, objRecord); - this._textObjectRecord = textObjectRecord; + super(spContainer, objRecord, textObjectRecord); } HSSFRichTextString string = new HSSFRichTextString(""); @@ -64,25 +61,16 @@ public class HSSFTextbox extends HSSFSimpleShape { */ public HSSFTextbox(HSSFShape parent, HSSFAnchor anchor) { super(parent, anchor); - _textObjectRecord = createTextObjRecord(); setHorizontalAlignment(HORIZONTAL_ALIGNMENT_LEFT); setVerticalAlignment(VERTICAL_ALIGNMENT_TOP); setString(new HSSFRichTextString("")); - - } - - protected TextObjectRecord createTextObjRecord(){ - TextObjectRecord obj = new TextObjectRecord(); - obj.setTextLocked(true); - obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE); - return obj; } @Override protected ObjRecord createObjRecord() { ObjRecord obj = new ObjRecord(); CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); - c.setObjectType(OBJECT_TYPE_TEXT); + c.setObjectType(HSSFTextbox.OBJECT_TYPE_TEXT); c.setLocked( true ); c.setPrintable( true ); c.setAutofill( true ); @@ -90,8 +78,7 @@ public class HSSFTextbox extends HSSFSimpleShape { EndSubRecord e = new EndSubRecord(); obj.addSubRecord( c ); obj.addSubRecord( e ); - return obj; - } + return obj; } @Override protected EscherContainerRecord createSpContainer() { @@ -123,7 +110,7 @@ public class HSSFTextbox extends HSSFSimpleShape { opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT)); opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT)); opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT)); - opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1)); + opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, NO_FILLHITTEST_FALSE)); opt.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000)); EscherRecord anchor = getAnchor().getEscherAnchor(); @@ -142,34 +129,25 @@ public class HSSFTextbox extends HSSFSimpleShape { } @Override - void afterInsert(HSSFPatriarch patriarch){ - EscherAggregate agg = patriarch._getBoundAggregate(); - agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); - agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord()); - } - - /** - * @return the rich text string for this textbox. - */ - public HSSFRichTextString getString() { - return _textObjectRecord.getStr(); - } - - /** - * @param string Sets the rich text string used by this object. - */ public void setString(RichTextString string) { HSSFRichTextString rtr = (HSSFRichTextString) string; // If font is not set we must set the default one if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); - _textObjectRecord.setStr(rtr); + getTextObjectRecord().setStr(rtr); + } + + @Override + void afterInsert(HSSFPatriarch patriarch){ + EscherAggregate agg = patriarch._getBoundAggregate(); + agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord()); } /** * @return Returns the left margin within the textbox. */ public int getMarginLeft() { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTLEFT); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTLEFT); return property == null ? 0: property.getPropertyValue(); } @@ -184,7 +162,7 @@ public class HSSFTextbox extends HSSFSimpleShape { * @return returns the right margin within the textbox. */ public int getMarginRight() { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTRIGHT); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTRIGHT); return property == null ? 0: property.getPropertyValue(); } @@ -199,7 +177,7 @@ public class HSSFTextbox extends HSSFSimpleShape { * @return returns the top margin within the textbox. */ public int getMarginTop() { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTTOP); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTTOP); return property == null ? 0: property.getPropertyValue(); } @@ -214,7 +192,7 @@ public class HSSFTextbox extends HSSFSimpleShape { * Gets the bottom margin within the textbox. */ public int getMarginBottom() { - EscherSimpleProperty property = _optRecord.lookup(EscherProperties.TEXT__TEXTBOTTOM); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__TEXTBOTTOM); return property == null ? 0: property.getPropertyValue(); } @@ -229,34 +207,32 @@ public class HSSFTextbox extends HSSFSimpleShape { * Gets the horizontal alignment. */ public short getHorizontalAlignment() { - return (short) _textObjectRecord.getHorizontalTextAlignment(); + return (short) getTextObjectRecord().getHorizontalTextAlignment(); } /** * Sets the horizontal alignment. */ public void setHorizontalAlignment(short align) { - _textObjectRecord.setHorizontalTextAlignment(align); + getTextObjectRecord().setHorizontalTextAlignment(align); } /** * Gets the vertical alignment. */ public short getVerticalAlignment() { - return (short) _textObjectRecord.getVerticalTextAlignment(); + return (short) getTextObjectRecord().getVerticalTextAlignment(); } /** * Sets the vertical alignment. */ public void setVerticalAlignment(short align) { - _textObjectRecord.setVerticalTextAlignment(align); - } - - public TextObjectRecord getTextObjectRecord() { - return _textObjectRecord; + getTextObjectRecord().setVerticalTextAlignment(align); } @Override - public void setShapeType(int shapeType) {/**DO NOTHING**/} + public void setShapeType(int shapeType) { + throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java index 406dfe7219..827a5c34ac 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java @@ -33,11 +33,19 @@ public class HSSFUnknownShape extends HSSFShape { @Override protected EscherContainerRecord createSpContainer() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } @Override protected ObjRecord createObjRecord() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; + } + + @Override + protected void afterRemove(HSSFPatriarch patriarch) { + } + + @Override + void afterInsert(HSSFPatriarch patriarch) { } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index afd0bce10f..e24ccc2d91 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -1614,7 +1614,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss r.setUid( uid ); r.setTag( (short) 0xFF ); r.setSize( pictureData.length + 25 ); - r.setRef( 1 ); + r.setRef( 0 ); r.setOffset( 0 ); r.setBlipRecord( blipRecord ); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index e50aa47adf..06564e94c4 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -47,7 +47,8 @@ public class TestDrawingShapes extends TestCase { } public void testHSSFShapeCompatibility() { - HSSFShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor()); + HSSFSimpleShape shape = new HSSFSimpleShape(null, new HSSFClientAnchor()); + shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); assertEquals(0x08000040, shape.getLineStyleColor()); assertEquals(0x08000009, shape.getFillColor()); assertEquals(HSSFShape.LINEWIDTH_DEFAULT, shape.getLineWidth()); @@ -80,7 +81,7 @@ public class TestDrawingShapes extends TestCase { HSSFPicture picture = new HSSFPicture(null, new HSSFClientAnchor()); assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); assertEquals(picture.getFillColor(), HSSFShape.FILL__FILLCOLOR_DEFAULT); - assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_SOLID); + assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_NONE); assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT); assertEquals(picture.isNoFill(), false); assertEquals(picture.getPictureIndex(), -1);//not set yet @@ -131,8 +132,10 @@ public class TestDrawingShapes extends TestCase { assertEquals(10, rectangle.getLineStyle()); rectangle.setLineStyleColor(1111); rectangle.setNoFill(true); + rectangle.setString(new HSSFRichTextString("teeeest")); assertEquals(rectangle.getLineStyleColor(), 1111); assertEquals(rectangle.isNoFill(), true); + assertEquals(rectangle.getString().getString(), "teeeest"); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sheet = wb.getSheetAt(0); @@ -149,6 +152,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(rectangle2.getLineStyleColor(), 1111); assertEquals(rectangle2.getFillColor(), 777); assertEquals(rectangle2.isNoFill(), true); + assertEquals(rectangle2.getString().getString(), "teeeest"); rectangle2.setFillColor(3333); rectangle2.setLineStyle(9); @@ -159,6 +163,7 @@ public class TestDrawingShapes extends TestCase { rectangle2.getAnchor().setDx2(3); rectangle2.getAnchor().setDy1(4); rectangle2.getAnchor().setDy2(5); + rectangle2.setString(new HSSFRichTextString("test22")); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sheet = wb.getSheetAt(0); @@ -175,6 +180,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(rectangle2.getAnchor().getDy1(), 4); assertEquals(rectangle2.getAnchor().getDy2(), 5); assertEquals(rectangle2.isNoFill(), false); + assertEquals(rectangle2.getString().getString(), "test22"); HSSFSimpleShape rect3 = drawing.createSimpleShape(new HSSFClientAnchor()); rect3.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); @@ -196,7 +202,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(picture.getFillColor(), 0x5DC943); assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); assertEquals(picture.getLineStyle(), HSSFShape.LINESTYLE_DEFAULT); - assertEquals(picture.isNoFill(), true); + assertEquals(picture.isNoFill(), false); picture.setPictureIndex(2); assertEquals(picture.getPictureIndex(), 2); @@ -211,11 +217,12 @@ public class TestDrawingShapes extends TestCase { assertEquals(1, drawing.getChildren().size()); HSSFSimpleShape shape = (HSSFSimpleShape) drawing.getChildren().get(0); - assertEquals(shape.isNoFill(), true); + assertEquals(shape.isNoFill(), false); assertEquals(shape.getLineStyle(), HSSFShape.LINESTYLE_DASHDOTGEL); assertEquals(shape.getLineStyleColor(), 0x616161); assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D); assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT * 2); + assertEquals(shape.getString().getString(), "POItest"); } public void testShapeIds() { diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index 248247266a..9134332834 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -375,4 +375,38 @@ public class TestHSSFAnchor extends TestCase { childAnchor2.setDy2(3); assertEquals(childAnchor1, childAnchor2); } + + public void testFlipped(){ + HSSFChildAnchor child = new HSSFChildAnchor(2,2,1,1); + assertEquals(child.isHorizontallyFlipped(), true); + assertEquals(child.isVerticallyFlipped(), true); + assertEquals(child.getDx1(), 1); + assertEquals(child.getDx2(), 2); + assertEquals(child.getDy1(), 1); + assertEquals(child.getDy2(), 2); + + child = new HSSFChildAnchor(3,3,4,4); + assertEquals(child.isHorizontallyFlipped(), false); + assertEquals(child.isVerticallyFlipped(), false); + assertEquals(child.getDx1(), 3); + assertEquals(child.getDx2(), 4); + assertEquals(child.getDy1(), 3); + assertEquals(child.getDy2(), 4); + + HSSFClientAnchor client = new HSSFClientAnchor(1,1,1,1, (short)4,4,(short)3,3); + assertEquals(client.isVerticallyFlipped(), true); + assertEquals(client.isHorizontallyFlipped(), true); + assertEquals(client.getCol1(), 3); + assertEquals(client.getCol2(), 4); + assertEquals(client.getRow1(), 3); + assertEquals(client.getRow2(), 4); + + client = new HSSFClientAnchor(1,1,1,1, (short)5,5,(short)6,6); + assertEquals(client.isVerticallyFlipped(), false); + assertEquals(client.isHorizontallyFlipped(), false); + assertEquals(client.getCol1(), 5); + assertEquals(client.getCol2(), 6); + assertEquals(client.getRow1(), 5); + assertEquals(client.getRow2(), 6); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 3aafa04edd..d5606362c8 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -83,7 +83,7 @@ public class HSSFTestHelper { } public static EscherOptRecord getOptRecord(HSSFShape shape){ - return shape._optRecord; + return shape.getOptRecord(); } public static void convertHSSFGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj){ diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java index 376edc32b1..b098c19737 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -212,8 +212,7 @@ public class TestComment extends TestCase { HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor()); - //6 properties of HSSFShape + 8 of HSSFTextbox - assertEquals(comment._optRecord.getEscherProperties().size(), 14); + assertEquals(comment.getOptRecord().getEscherProperties().size(), 10); } public void testShapeId(){ diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java index 6c08a167a1..234cddccfd 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java @@ -17,8 +17,10 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.ddf.EscherBSERecord; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFITestDataProvider; +import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.ss.usermodel.BaseTestPicture; import org.apache.poi.ss.usermodel.PictureData; import org.apache.poi.ss.usermodel.Workbook; @@ -149,4 +151,63 @@ public final class TestHSSFPicture extends BaseTestPicture { assertTrue(Arrays.equals(data4, ((HSSFPicture)dr.getChildren().get(3)).getPictureData().getData())); } + public void testBSEPictureRef(){ + HSSFWorkbook wb = new HSSFWorkbook(); + + HSSFSheet sh = wb.createSheet("Pictures"); + HSSFPatriarch dr = sh.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(); + + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + + //register a picture + byte[] data1 = new byte[]{1, 2, 3}; + int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); + assertEquals(1, idx1); + HSSFPicture p1 = dr.createPicture(anchor, idx1); + + EscherBSERecord bse = wb.getWorkbook().getBSERecord(idx1); + + assertEquals(bse.getRef(), 1); + dr.createPicture(new HSSFClientAnchor(), idx1); + assertEquals(bse.getRef(), 2); + + HSSFShapeGroup gr = dr.createGroup(new HSSFClientAnchor()); + gr.createPicture(new HSSFChildAnchor(), idx1); + assertEquals(bse.getRef(), 3); + } + + public void testReadExistingImage(){ + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + HSSFSheet sheet = wb.getSheet("picture"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); + + HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); + assertEquals(picture.getAdditionalData(), "test"); + } + + public void testSetGetProperties(){ + HSSFWorkbook wb = new HSSFWorkbook(); + + HSSFSheet sh = wb.createSheet("Pictures"); + HSSFPatriarch dr = sh.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(); + + //register a picture + byte[] data1 = new byte[]{1, 2, 3}; + int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); + HSSFPicture p1 = dr.createPicture(anchor, idx1); + + assertEquals(p1.getAdditionalData(), ""); + p1.setAdditionalData("aaa"); + assertEquals(p1.getAdditionalData(), "aaa"); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheet("Pictures"); + dr = sh.getDrawingPatriarch(); + + p1 = (HSSFPicture) dr.getChildren().get(0); + assertEquals(p1.getAdditionalData(), "aaa"); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java index 7c83a0d25f..3983c838b2 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java @@ -73,7 +73,7 @@ public class TestPolygon extends TestCase{ PolygonShape polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon); - EscherArrayProperty verticesProp1 = polygon._optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + EscherArrayProperty verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); EscherArrayProperty verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID)) .lookup(EscherProperties.GEOMETRY__VERTICES); @@ -85,7 +85,7 @@ public class TestPolygon extends TestCase{ assertTrue(Arrays.equals(polygon.getYPoints(), new int[]{4, 5, 6})); polygonShape = HSSFTestModelHelper.createPolygonShape(0, polygon); - verticesProp1 = polygon._optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); + verticesProp1 = polygon.getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); verticesProp2 = ((EscherOptRecord)polygonShape.getSpContainer().getChildById(EscherOptRecord.RECORD_ID)) .lookup(EscherProperties.GEOMETRY__VERTICES); diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index 9700c91086f0b771299ce855063de7b2e1c19bcd..eeac150c3f4bf3c2329e3cecf5c56b706220d337 100644 GIT binary patch delta 18459 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 A2><{9 delta 4326 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 ZPNF_7VBNr Date: Wed, 11 Jul 2012 22:22:24 +0000 Subject: [PATCH 18/32] fixed auto filters(added class HSSFCombobox) git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1360445 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/usermodel/HSSFCombobox.java | 77 +++++++++++++++++++ .../poi/hssf/usermodel/HSSFPatriarch.java | 11 +-- .../poi/hssf/usermodel/HSSFPicture.java | 7 +- .../poi/hssf/usermodel/HSSFShapeFactory.java | 16 +--- .../poi/hssf/usermodel/HSSFSimpleShape.java | 7 +- .../poi/hssf/model/TestDrawingShapes.java | 56 ++++++++++++++ .../apache/poi/hssf/model/TestHSSFAnchor.java | 3 +- .../poi/hssf/usermodel/HSSFTestHelper.java | 14 ++-- 8 files changed, 160 insertions(+), 31 deletions(-) create mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java new file mode 100644 index 0000000000..4b13278f0c --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java @@ -0,0 +1,77 @@ +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.*; + +/** + * @author Evgeniy Berlog + * @date 12.07.12 + */ +public class HSSFCombobox extends HSSFSimpleShape { + + public HSSFCombobox(EscherContainerRecord spContainer, ObjRecord objRecord) { + super(spContainer, objRecord); + } + + public HSSFCombobox(HSSFShape parent, HSSFAnchor anchor) { + super(parent, anchor); + super.setShapeType(OBJECT_TYPE_COMBO_BOX); + } + + @Override + protected EscherContainerRecord createSpContainer() { + EscherContainerRecord spContainer = new EscherContainerRecord(); + EscherSpRecord sp = new EscherSpRecord(); + EscherOptRecord opt = new EscherOptRecord(); + EscherClientDataRecord clientData = new EscherClientDataRecord(); + + spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); + spContainer.setOptions((short) 0x000F); + sp.setRecordId(EscherSpRecord.RECORD_ID); + sp.setOptions((short) ((EscherAggregate.ST_HOSTCONTROL << 4) | 0x2)); + + sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE); + opt.setRecordId(EscherOptRecord.RECORD_ID); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 17039620)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x00080008)); + opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000)); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00020000)); + + HSSFClientAnchor userAnchor = (HSSFClientAnchor) getAnchor(); + userAnchor.setAnchorType(1); + EscherRecord anchor = userAnchor.getEscherAnchor(); + clientData.setRecordId(EscherClientDataRecord.RECORD_ID); + clientData.setOptions((short) 0x0000); + + spContainer.addChildRecord(sp); + spContainer.addChildRecord(opt); + spContainer.addChildRecord(anchor); + spContainer.addChildRecord(clientData); + + return spContainer; + } + + @Override + protected ObjRecord createObjRecord() { + ObjRecord obj = new ObjRecord(); + CommonObjectDataSubRecord c = new CommonObjectDataSubRecord(); + c.setObjectType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX); + c.setLocked(true); + c.setPrintable(false); + c.setAutofill(true); + c.setAutoline(false); + FtCblsSubRecord f = new FtCblsSubRecord(); + LbsDataSubRecord l = LbsDataSubRecord.newAutoFilterInstance(); + EndSubRecord e = new EndSubRecord(); + obj.addSubRecord(c); + obj.addSubRecord(f); + obj.addSubRecord(l); + obj.addSubRecord(e); + return obj; + } + + @Override + public void setShapeType(int shapeType) { + throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index aa8603635b..fbe3f56b68 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -97,7 +97,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) { HSSFShapeGroup group = new HSSFShapeGroup(null, anchor); - group.anchor = anchor; addShape(group); onCreate(group); return group; @@ -114,7 +113,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) { HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); - shape.anchor = anchor; addShape(shape); //open existing file onCreate(shape); @@ -139,7 +137,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { { HSSFPicture shape = new HSSFPicture(null, anchor); shape.setPictureIndex( pictureIndex ); - shape.anchor = anchor; addShape(shape); //open existing file onCreate(shape); @@ -169,7 +166,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFPolygon createPolygon(HSSFClientAnchor anchor) { HSSFPolygon shape = new HSSFPolygon(null, anchor); - shape.anchor = anchor; addShape(shape); onCreate(shape); return shape; @@ -185,7 +181,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFTextbox createTextbox(HSSFClientAnchor anchor) { HSSFTextbox shape = new HSSFTextbox(null, anchor); - shape.anchor = anchor; addShape(shape); onCreate(shape); return shape; @@ -201,7 +196,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { public HSSFComment createComment(HSSFAnchor anchor) { HSSFComment shape = new HSSFComment(null, anchor); - shape.anchor = anchor; addShape(shape); onCreate(shape); return shape; @@ -214,10 +208,9 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ HSSFSimpleShape createComboBox(HSSFAnchor anchor) { - HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); - shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX); - shape.anchor = anchor; + HSSFCombobox shape = new HSSFCombobox(null, anchor); addShape(shape); + onCreate(shape); return shape; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 9eff50dd3e..6e5d98cf55 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -65,7 +65,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { public HSSFPicture( HSSFShape parent, HSSFAnchor anchor ) { super( parent, anchor ); - setShapeType(OBJECT_TYPE_PICTURE); + super.setShapeType(OBJECT_TYPE_PICTURE); } public int getPictureIndex() @@ -280,4 +280,9 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { System.out.println("Unsupported encoding: UTF-16LE"); } } + + @Override + public void setShapeType(int shapeType) { + throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index eab30fcdaa..4bf927b2a0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -122,6 +122,9 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_LINE: shape = new HSSFSimpleShape(container, objRecord); break; + case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX: + shape = new HSSFCombobox(container, objRecord); + break; case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); @@ -143,19 +146,6 @@ public class HSSFShapeFactory { if (null != shape){ out.addShape(shape); } -// if (null != objRecord){ -// HSSFShape shape = shapeCreator.createNewShape(spRecord.getShapeType(), container, objRecord); -// out.addShape(shape); -// } -// if (null != txtRecord){ -// //TODO resolve textbox -//// TextboxShape shape = new TextboxShape(container, txtRecord); -//// out.a -// } -//// -//// //TODO decide what shape to create based on ObjRecord / EscherSpRecord -//// HSSFShape shape = new HSSFUnknownShape(container, objRecord); -//// out.addShape(shape); } } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index ac4697ac14..28153d2d45 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -70,11 +70,12 @@ public class HSSFSimpleShape extends HSSFShape public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) { super(spContainer, objRecord); - this._textObjectRecord = _textObjectRecord; + this._textObjectRecord = _textObjectRecord == null ? createTextObjRecord() : _textObjectRecord; } public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { super(spContainer, objRecord); + this._textObjectRecord = createTextObjRecord(); } public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) @@ -159,6 +160,10 @@ public class HSSFSimpleShape extends HSSFShape * @param string Sets the rich text string used by this object. */ public void setString(RichTextString string) { + //TODO add other shape types which can not contain text + if (getShapeType() == 0 || getShapeType() == OBJECT_TYPE_LINE){ + throw new IllegalStateException("Cannot set text for shape type: "+getShapeType()); + } HSSFRichTextString rtr = (HSSFRichTextString) string; // If font is not set we must set the default one if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 06564e94c4..7d5bfaee6d 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -10,6 +10,7 @@ import org.apache.poi.hssf.usermodel.*; import org.apache.poi.util.HexDump; import java.io.IOException; +import java.util.Arrays; import static junit.framework.Assert.assertEquals; @@ -341,4 +342,59 @@ public class TestDrawingShapes extends TestCase { EscherDgRecord dgRecord = (EscherDgRecord) aggregate.getEscherRecord(0).getChild(0); assertEquals(dgRecord.getNumShapes(), 1); } + + public void testTextForSimpleShape(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor()); + shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); + assertNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 1); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + shape = (HSSFSimpleShape) patriarch.getChildren().get(0); + + agg = HSSFTestHelper.getEscherAggregate(patriarch); + assertNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 1); + + shape.setString(new HSSFRichTextString("string1")); + assertEquals(shape.getString().getString(), "string1"); + + assertNotNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 2); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + shape = (HSSFSimpleShape) patriarch.getChildren().get(0); + + assertNotNull(shape.getTextObjectRecord()); + assertEquals(shape.getString().getString(), "string1"); + assertNotNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertEquals(agg.getShapeToObjMapping().size(), 2); + } + + public void testComboboxRecords(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFCombobox combobox = new HSSFCombobox(null, new HSSFClientAnchor()); + HSSFTestHelper.setShapeId(combobox, 1024); + ComboboxShape comboboxShape = new ComboboxShape(combobox, 1024); + + assertTrue(Arrays.equals(comboboxShape.getSpContainer().serialize(), combobox.getEscherContainer().serialize())); + assertTrue(Arrays.equals(comboboxShape.getObjRecord().serialize(), combobox.getObjRecord().serialize())); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index 9134332834..7d42b46375 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -54,11 +54,10 @@ public class TestHSSFAnchor extends TestCase { HSSFPatriarch drawing = sheet.getDrawingPatriarch(); HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0); - rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); assertEquals(rectangle.getEscherContainer().getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); assertEquals(rectangle.getEscherContainer().getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); - assertEquals(" " + HexDump.toHex(rectangle.getEscherContainer().getChild(2).getRecordId()) + " ", rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); assertEquals(rectangle.getEscherContainer().getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); rectangle.setAnchor(new HSSFClientAnchor()); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index d5606362c8..50ff1dc50c 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -93,11 +93,11 @@ public class HSSFTestHelper { method.setAccessible(true); method.invoke(new EscherAggregate(new MockDrawingManager()), shape, escherParent, shapeToObj); } catch (NoSuchMethodException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } catch (InvocationTargetException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } catch (IllegalAccessException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } } @@ -110,9 +110,13 @@ public class HSSFTestHelper { } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } catch (InvocationTargetException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } } + + public static void setShapeId(HSSFShape shape, int id){ + shape.setShapeId(id); + } } From 47dd4545797ec8e0e789445931d3897a98cf384c Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Fri, 13 Jul 2012 15:45:01 +0000 Subject: [PATCH 19/32] moved HSSFObjectData into drawing layer git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1361278 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/usermodel/HSSFObjectData.java | 45 +++++++----- .../poi/hssf/usermodel/HSSFPatriarch.java | 2 +- .../poi/hssf/usermodel/HSSFShapeFactory.java | 68 ++++++++++-------- .../poi/hssf/usermodel/HSSFWorkbook.java | 35 +++++---- .../poi/hssf/model/TestDrawingShapes.java | 2 +- .../hssf/usermodel/TestEmbeddedObjects.java | 24 +++++++ test-data/spreadsheet/drawings.xls | Bin 836096 -> 851968 bytes 7 files changed, 110 insertions(+), 66 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java index 5b2a463f4c..efb19331b0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java @@ -21,6 +21,7 @@ package org.apache.poi.hssf.usermodel; import java.io.IOException; import java.util.Iterator; +import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord; import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.hssf.record.SubRecord; @@ -31,29 +32,19 @@ import org.apache.poi.util.HexDump; /** * Represents binary object (i.e. OLE) data stored in the file. Eg. A GIF, JPEG etc... * + * Right now, 13, july, 2012 can not be created from scratch + * * @author Daniel Noll */ -public final class HSSFObjectData { - /** - * Underlying object record ultimately containing a reference to the object. - */ - private final ObjRecord _record; - +public final class HSSFObjectData extends HSSFShape{ /** * Reference to the filesystem root, required for retrieving the object data. */ private final DirectoryEntry _root; - /** - * Constructs object data by wrapping a lower level object record. - * - * @param record the low-level object record. - * @param root the root of the filesystem, required for retrieving the object data. - */ - public HSSFObjectData(ObjRecord record, DirectoryEntry root) - { - _record = record; - _root = root; + public HSSFObjectData(EscherContainerRecord spContainer, ObjRecord objRecord, DirectoryEntry _root) { + super(spContainer, objRecord); + this._root = _root; } /** @@ -110,7 +101,7 @@ public final class HSSFObjectData { * Exception if there wasn't one */ protected EmbeddedObjectRefSubRecord findObjectRecord() { - Iterator subRecordIter = _record.getSubRecords().iterator(); + Iterator subRecordIter = getObjRecord().getSubRecords().iterator(); while (subRecordIter.hasNext()) { Object subRecord = subRecordIter.next(); @@ -121,4 +112,24 @@ public final class HSSFObjectData { throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory"); } + + @Override + protected EscherContainerRecord createSpContainer() { + throw new IllegalStateException("HSSFObjectData cannot be created from scratch"); + } + + @Override + protected ObjRecord createObjRecord() { + throw new IllegalStateException("HSSFObjectData cannot be created from scratch"); + } + + @Override + protected void afterRemove(HSSFPatriarch patriarch) { + throw new IllegalStateException("HSSFObjectData cannot be created from scratch"); + } + + @Override + void afterInsert(HSSFPatriarch patriarch) { + throw new IllegalStateException("HSSFObjectData cannot be created from scratch"); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index fbe3f56b68..221dfc475a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -387,7 +387,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { if (i == 0){ continue; } else { - HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this); + HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getRootDirectory()); } } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 4bf927b2a0..5d2c9bb619 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -18,18 +18,14 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; -import org.apache.poi.hssf.model.TextboxShape; -import org.apache.poi.hssf.record.CommonObjectDataSubRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.NoteRecord; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.TextObjectRecord; +import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; +import org.apache.poi.poifs.filesystem.DirectoryNode; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -43,7 +39,7 @@ public class HSSFShapeFactory { private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass); static { - for (HSSFShapeType type: HSSFShapeType.values()){ + for (HSSFShapeType type : HSSFShapeType.values()) { shapeTypeToClass.put(type.getType(), type); } } @@ -56,60 +52,65 @@ public class HSSFShapeFactory { this.shapeTypeToClass = shapeTypeToClass; } - public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord){ - if (!shapeTypeToClass.containsKey(type)){ + public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord) { + if (!shapeTypeToClass.containsKey(type)) { return new HSSFUnknownShape(spContainer, objRecord); } Class clazz = shapeTypeToClass.get(type).getShape(); - if (null == clazz){ + if (null == clazz) { //System.out.println("No class attached to shape type: "+type); return new HSSFUnknownShape(spContainer, objRecord); } - try{ + try { Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class}); return (HSSFShape) constructor.newInstance(spContainer, objRecord); } catch (NoSuchMethodException e) { - throw new IllegalStateException(clazz.getName() +" doesn't have required for shapes constructor"); + throw new IllegalStateException(clazz.getName() + " doesn't have required for shapes constructor"); } catch (Exception e) { throw new IllegalStateException("Couldn't create new instance of " + clazz.getName()); } } } - public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){ - if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ + public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { + if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { HSSFShapeGroup group = new HSSFShapeGroup(container, null /* shape containers don't have a associated Obj record*/); List children = container.getChildContainers(); // skip the first child record, it is group descriptor - for(int i = 0; i < children.size(); i++) { + for (int i = 0; i < children.size(); i++) { EscherContainerRecord spContainer = children.get(i); - if(i == 0){ - EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID); + if (i == 0) { + EscherSpgrRecord spgr = (EscherSpgrRecord) spContainer.getChildById(EscherSpgrRecord.RECORD_ID); } else { - createShapeTree(spContainer, agg, group); + createShapeTree(spContainer, agg, group, root); } } out.addShape(group); - } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER){ + } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) { Map shapeToObj = agg.getShapeToObjMapping(); EscherSpRecord spRecord = null; ObjRecord objRecord = null; TextObjectRecord txtRecord = null; - for(EscherRecord record : container.getChildRecords()) { - switch(record.getRecordId()) { + for (EscherRecord record : container.getChildRecords()) { + switch (record.getRecordId()) { case EscherSpRecord.RECORD_ID: - spRecord = (EscherSpRecord)record; + spRecord = (EscherSpRecord) record; break; case EscherClientDataRecord.RECORD_ID: - objRecord = (ObjRecord)shapeToObj.get(record); + objRecord = (ObjRecord) shapeToObj.get(record); break; case EscherTextboxRecord.RECORD_ID: - txtRecord = (TextObjectRecord)shapeToObj.get(record); + txtRecord = (TextObjectRecord) shapeToObj.get(record); break; } } + if (isEmbeddedObject(objRecord)){ + HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root); + out.addShape(objectData); + return; + } CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); HSSFShape shape = null; switch (cmo.getObjectType()) { @@ -128,8 +129,8 @@ public class HSSFShapeFactory { case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING: EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); - if (null != property){ - shape = new HSSFPolygon(container, objRecord); + if (null != property) { + shape = new HSSFPolygon(container, objRecord); } else { shape = new HSSFSimpleShape(container, objRecord); } @@ -143,9 +144,20 @@ public class HSSFShapeFactory { default: shape = new HSSFSimpleShape(container, objRecord); } - if (null != shape){ + if (null != shape) { out.addShape(shape); } } } + + private static boolean isEmbeddedObject(ObjRecord obj) { + Iterator subRecordIter = obj.getSubRecords().iterator(); + while (subRecordIter.hasNext()) { + SubRecord sub = subRecordIter.next(); + if (sub instanceof EmbeddedObjectRefSubRecord) { + return true; + } + } + return false; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index e24ccc2d91..332289e109 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -1706,7 +1706,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss List objects = new ArrayList(); for (int i = 0; i < getNumberOfSheets(); i++) { - getAllEmbeddedObjects(getSheetAt(i).getSheet().getRecords(), objects); + getAllEmbeddedObjects(getSheetAt(i), objects); } return objects; } @@ -1714,27 +1714,20 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss /** * Gets all embedded OLE2 objects from the Workbook. * - * @param records the list of records to search. + * @param sheet embedded object attached to * @param objects the list of embedded objects to populate. */ - private void getAllEmbeddedObjects(List records, List objects) + private void getAllEmbeddedObjects(HSSFSheet sheet, List objects) { - for (RecordBase obj : records) { - if (obj instanceof ObjRecord) - { - // TODO: More convenient way of determining if there is stored binary. - // TODO: Link to the data stored in the other stream. - Iterator subRecordIter = ((ObjRecord) obj).getSubRecords().iterator(); - while (subRecordIter.hasNext()) - { - SubRecord sub = subRecordIter.next(); - if (sub instanceof EmbeddedObjectRefSubRecord) - { - objects.add(new HSSFObjectData((ObjRecord) obj, directory)); - } - } - } - } + HSSFPatriarch patriarch = sheet.getDrawingPatriarch(); + if (null == patriarch){ + return; + } + for (HSSFShape shape: patriarch.getChildren()){ + if (shape instanceof HSSFObjectData){ + objects.add((HSSFObjectData) shape); + } + } } public HSSFCreationHelper getCreationHelper() { @@ -1808,4 +1801,8 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss public boolean changeExternalReference(String oldUrl, String newUrl) { return workbook.changeExternalReference(oldUrl, newUrl); } + + public DirectoryNode getRootDirectory(){ + return directory; + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 7d5bfaee6d..dd8882764f 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -198,7 +198,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(1, drawing.getChildren().size()); HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); - assertEquals(picture.getPictureIndex(), 1); + assertEquals(picture.getPictureIndex(), 2); assertEquals(picture.getLineStyleColor(), HSSFShape.LINESTYLE__COLOR_DEFAULT); assertEquals(picture.getFillColor(), 0x5DC943); assertEquals(picture.getLineWidth(), HSSFShape.LINEWIDTH_DEFAULT); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java new file mode 100644 index 0000000000..840643b951 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java @@ -0,0 +1,24 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.hssf.HSSFTestDataSamples; + +import java.io.IOException; +import java.util.List; + +/** + * @author Evgeniy Berlog + * @date 13.07.12 + */ +public class TestEmbeddedObjects extends TestCase{ + + public void testReadExistingObject() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); + List list = wb.getAllEmbeddedObjects(); + assertEquals(list.size(), 1); + HSSFObjectData obj = list.get(0); + assertNotNull(obj.getObjectData()); + assertNotNull(obj.getDirectory()); + assertNotNull(obj.getOLE2ClassName()); + } +} diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index eeac150c3f4bf3c2329e3cecf5c56b706220d337..45b9a958870d9362f8ade14e7b93e6b5d7159207 100644 GIT binary patch delta 17270 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 From 4e646a718235a622fde308eab8e66698204f923d Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Thu, 19 Jul 2012 19:02:43 +0000 Subject: [PATCH 20/32] implemented cloning of shapes git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1363479 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/model/InternalSheet.java | 4 +- .../poi/hssf/record/EscherAggregate.java | 436 ------------------ .../poi/hssf/usermodel/HSSFCombobox.java | 5 + .../poi/hssf/usermodel/HSSFComment.java | 17 +- .../poi/hssf/usermodel/HSSFObjectData.java | 57 ++- .../poi/hssf/usermodel/HSSFPatriarch.java | 193 ++++---- .../poi/hssf/usermodel/HSSFPicture.java | 14 +- .../poi/hssf/usermodel/HSSFPolygon.java | 22 +- .../apache/poi/hssf/usermodel/HSSFShape.java | 2 + .../poi/hssf/usermodel/HSSFShapeFactory.java | 10 +- .../poi/hssf/usermodel/HSSFShapeGroup.java | 46 +- .../apache/poi/hssf/usermodel/HSSFSheet.java | 10 +- .../poi/hssf/usermodel/HSSFSimpleShape.java | 44 +- .../poi/hssf/usermodel/HSSFTextbox.java | 10 + .../poi/hssf/usermodel/HSSFUnknownShape.java | 5 + .../poi/hssf/usermodel/HSSFWorkbook.java | 2 +- .../poi/hssf/model/TestDrawingAggregate.java | 40 -- .../poi/hssf/model/TestDrawingShapes.java | 6 +- .../poi/hssf/usermodel/HSSFTestHelper.java | 15 - .../poi/hssf/usermodel/TestCloneSheet.java | 76 +++ .../poi/hssf/usermodel/TestComment.java | 11 +- .../poi/hssf/usermodel/TestHSSFSheet.java | 4 +- .../poi/hssf/usermodel/TestShapeGroup.java | 23 - 23 files changed, 376 insertions(+), 676 deletions(-) diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index 09d8e4b803..ce8e5a9bb3 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -354,9 +354,9 @@ public final class InternalSheet { // EscherAggregate is used only as a container for SODRAWING and OBJ record combinations // So, if the container is empty, there is no reason to clone this record // See https://issues.apache.org/bugzilla/show_bug.cgi?id=49529 - if (0 == rb.getRecordSize()){ +// if (0 == rb.getRecordSize()){ continue; - } +// } } Record rec = (Record) ((Record) rb).clone(); clonedRecords.add(rec); diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 7079cf7dc1..30a815acbb 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -22,27 +22,16 @@ import java.io.IOException; import java.util.*; import org.apache.poi.ddf.DefaultEscherRecordFactory; -import org.apache.poi.ddf.EscherBoolProperty; -import org.apache.poi.ddf.EscherChildAnchorRecord; -import org.apache.poi.ddf.EscherClientAnchorRecord; import org.apache.poi.ddf.EscherClientDataRecord; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherDgRecord; -import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherRecordFactory; import org.apache.poi.ddf.EscherSerializationListener; -import org.apache.poi.ddf.EscherSimpleProperty; import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.ddf.EscherTextboxRecord; -import org.apache.poi.hssf.model.AbstractShape; -import org.apache.poi.hssf.model.CommentShape; -import org.apache.poi.hssf.model.ConvertAnchor; import org.apache.poi.hssf.model.DrawingManager2; -import org.apache.poi.hssf.model.TextboxShape; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -313,8 +302,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { * Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */ private final Map shapeToObj = new HashMap(); - private DrawingManager2 drawingManager; - private short drawingGroupId; /** * list of "tail" records that need to be serialized after all drawing group records @@ -326,11 +313,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } public EscherAggregate(DrawingManager2 drawingManager) { - this.drawingManager = drawingManager; - } - - public DrawingManager2 getDrawingManager() { - return drawingManager; } /** @@ -458,8 +440,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { // replace drawing block with the created EscherAggregate records.subList(locFirstDrawingRecord, locLastDrawingRecord).clear(); records.add(locFirstDrawingRecord, agg); - - return agg; } @@ -472,14 +452,11 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { * @return The number of bytes serialized. */ public int serialize(int offset, byte[] data) { - convertUserModelToRecords(); - // Determine buffer size List records = getEscherRecords(); int size = getEscherRecordSize(records); byte[] buffer = new byte[size]; - // Serialize escher records into one big data structure and keep note of ending offsets. final List spEndingOffsets = new ArrayList(); final List shapes = new ArrayList(); @@ -594,8 +571,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } public int getRecordSize() { - // TODO - convert this to RecordAggregate - convertUserModelToRecords(); // To determine size of aggregate record we have to know size of each DrawingRecord because if DrawingRecord // is split into several continue records we have to add header size to total EscherAggregate size int continueRecordsHeadersSize = 0; @@ -657,249 +632,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { shapeToObj.remove(rec); } - public HSSFPatriarch getPatriarch() { - return patriarch; - } - - public void setPatriarch(HSSFPatriarch patriarch) { - this.patriarch = patriarch; - } - - /** - * Converts the Records into UserModel - * objects on the bound HSSFPatriarch - */ - public void convertRecordsToUserModel() { - if (patriarch == null) { - throw new IllegalStateException("Must call setPatriarch() first"); - } - - // The top level container ought to have - // the DgRecord and the container of one container - // per shape group (patriach overall first) - EscherContainerRecord topContainer = getEscherContainer(); - if (topContainer == null) { - return; - } - topContainer = topContainer.getChildContainers().get(0); - - List tcc = topContainer.getChildContainers(); - if (tcc.size() == 0) { - throw new IllegalStateException("No child escher containers at the point that should hold the patriach data, and one container per top level shape!"); - } - - // First up, get the patriach position - // This is in the first EscherSpgrRecord, in - // the first container, with a EscherSRecord too - EscherContainerRecord patriachContainer = - (EscherContainerRecord) tcc.get(0); - EscherSpgrRecord spgr = null; - for (Iterator it = patriachContainer.getChildIterator(); it.hasNext(); ) { - EscherRecord r = it.next(); - if (r instanceof EscherSpgrRecord) { - spgr = (EscherSpgrRecord) r; - break; - } - } - if (spgr != null) { - patriarch.setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); - } - - convertRecordsToUserModelRecursive(tcc, patriarch, null); - - // Now, clear any trace of what records make up - // the patriarch - // Otherwise, everything will go horribly wrong - // when we try to write out again.... -// clearEscherRecords(); - drawingManager.getDgg().setFileIdClusters(new EscherDggRecord.FileIdCluster[0]); - - // TODO: Support converting our records - // back into shapes - // log.log(POILogger.WARN, "Not processing objects into Patriarch!"); - } - - private static void convertRecordsToUserModelRecursive(List tcc, HSSFShapeContainer container, HSSFShape parent) { - // Now process the containers for each group - // and objects - for (int i = 1; i < tcc.size(); i++) { - EscherContainerRecord shapeContainer = (EscherContainerRecord) tcc.get(i); - - // Could be a group, or a base object - if (shapeContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - // Group - final int shapeChildren = shapeContainer.getChildRecords().size(); - if (shapeChildren > 0) { - HSSFShapeGroup group = new HSSFShapeGroup(parent, new HSSFClientAnchor()); - addToParentOrContainer(group, container, parent); - - EscherContainerRecord groupContainer = (EscherContainerRecord) shapeContainer.getChild(0); - convertRecordsToUserModel(groupContainer, group); - - if (shapeChildren > 1) { - convertRecordsToUserModelRecursive(shapeContainer.getChildRecords(), container, group); - } - } else { - log.log(POILogger.WARN, - "Found drawing group without children."); - } - - } else if (shapeContainer.getRecordId() == EscherContainerRecord.SP_CONTAINER) { - EscherSpRecord spRecord = shapeContainer - .getChildById(EscherSpRecord.RECORD_ID); - int type = spRecord.getShapeType(); - - switch (type) { - case ST_TEXTBOX: - HSSFTextbox box = new HSSFTextbox(parent, - new HSSFClientAnchor()); - addToParentOrContainer(box, container, parent); - - convertRecordsToUserModel(shapeContainer, box); - break; - case ST_PICTUREFRAME: - // Duplicated from - // org.apache.poi.hslf.model.Picture.getPictureIndex() - EscherOptRecord opt = (EscherOptRecord) getEscherChild( - shapeContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty) opt.lookup( - EscherProperties.BLIP__BLIPTODISPLAY); - if (prop == null) { - log.log(POILogger.WARN, - "Picture index for picture shape not found."); - } else { - int pictureIndex = prop.getPropertyValue(); - - EscherClientAnchorRecord anchorRecord = (EscherClientAnchorRecord) getEscherChild( - shapeContainer, - EscherClientAnchorRecord.RECORD_ID); - - EscherChildAnchorRecord childRecord = (EscherChildAnchorRecord) getEscherChild( - shapeContainer, - EscherChildAnchorRecord.RECORD_ID); - - if (anchorRecord != null && childRecord != null) { - log.log(POILogger.WARN, "Picture with both CLIENT and CHILD anchor: " + type); - } - - HSSFAnchor anchor; - if (anchorRecord != null) { - anchor = toClientAnchor(anchorRecord); - } else { - anchor = toChildAnchor(childRecord); - } - - HSSFPicture picture = new HSSFPicture(parent, anchor); - picture.setPictureIndex(pictureIndex); - - addToParentOrContainer(picture, container, parent); - } - break; - default: - final HSSFSimpleShape shape = new HSSFSimpleShape(parent, - new HSSFClientAnchor()); - addToParentOrContainer(shape, container, parent); - convertRecordsToUserModel(shapeContainer, shape); - - log.log(POILogger.WARN, "Unhandled shape type: " - + type); - break; - } - } else { - log.log(POILogger.WARN, "Unexpected record id of shape group."); - } - - } - } - - private static void addToParentOrContainer(HSSFShape shape, HSSFShapeContainer container, HSSFShape parent) { - - if (parent instanceof HSSFShapeGroup) - ((HSSFShapeGroup) parent).addShape(shape); - else if (container instanceof HSSFPatriarch) - ((HSSFPatriarch) container).addShape(shape); - else - container.getChildren().add(shape); - } - - public static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) { - HSSFClientAnchor anchor = new HSSFClientAnchor(); - anchor.setAnchorType(anchorRecord.getFlag()); - anchor.setCol1(anchorRecord.getCol1()); - anchor.setCol2(anchorRecord.getCol2()); - anchor.setDx1(anchorRecord.getDx1()); - anchor.setDx2(anchorRecord.getDx2()); - anchor.setDy1(anchorRecord.getDy1()); - anchor.setDy2(anchorRecord.getDy2()); - anchor.setRow1(anchorRecord.getRow1()); - anchor.setRow2(anchorRecord.getRow2()); - return anchor; - } - - public static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) { - HSSFChildAnchor anchor = new HSSFChildAnchor(); -// anchor.setAnchorType(anchorRecord.getFlag()); -// anchor.setCol1( anchorRecord.getCol1() ); -// anchor.setCol2( anchorRecord.getCol2() ); - anchor.setDx1(anchorRecord.getDx1()); - anchor.setDx2(anchorRecord.getDx2()); - anchor.setDy1(anchorRecord.getDy1()); - anchor.setDy2(anchorRecord.getDy2()); -// anchor.setRow1( anchorRecord.getRow1() ); -// anchor.setRow2( anchorRecord.getRow2() ); - return anchor; - } - - private static void convertRecordsToUserModel(EscherContainerRecord shapeContainer, Object model) { - for (Iterator it = shapeContainer.getChildIterator(); it.hasNext(); ) { - EscherRecord r = it.next(); - if (r instanceof EscherSpgrRecord) { - // This may be overriden by a later EscherClientAnchorRecord - EscherSpgrRecord spgr = (EscherSpgrRecord) r; - - if (model instanceof HSSFShapeGroup) { - HSSFShapeGroup g = (HSSFShapeGroup) model; - g.setCoordinates( - spgr.getRectX1(), spgr.getRectY1(), - spgr.getRectX2(), spgr.getRectY2() - ); - } else { - throw new IllegalStateException("Got top level anchor but not processing a group"); - } - } else if (r instanceof EscherClientAnchorRecord) { - EscherClientAnchorRecord car = (EscherClientAnchorRecord) r; - - if (model instanceof HSSFShape) { - HSSFShape g = (HSSFShape) model; - g.getAnchor().setDx1(car.getDx1()); - g.getAnchor().setDx2(car.getDx2()); - g.getAnchor().setDy1(car.getDy1()); - g.getAnchor().setDy2(car.getDy2()); - } else { - throw new IllegalStateException("Got top level anchor but not processing a group or shape"); - } - } else if (r instanceof EscherTextboxRecord) { - EscherTextboxRecord tbr = (EscherTextboxRecord) r; - - // Also need to find the TextObjectRecord too - // TODO - } else if (r instanceof EscherSpRecord) { - // Use flags if needed - final EscherSpRecord spr = (EscherSpRecord) r; - if (model instanceof HSSFShape) { - final HSSFShape s = (HSSFShape) model; - } - } else if (r instanceof EscherOptRecord) { - // Use properties if needed - } else { - //System.err.println(r); - } - } - } - public void clear() { clearEscherRecords(); shapeToObj.clear(); @@ -916,133 +648,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return sid(records, loc) == ObjRecord.sid || sid(records, loc) == TextObjectRecord.sid; } - private void convertUserModelToRecords() { - if (patriarch != null) { - shapeToObj.clear(); - tailRec.clear(); - clearEscherRecords(); - if (patriarch.getChildren().size() != 0) { - convertPatriarch(patriarch); - EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord(0); - EscherContainerRecord spgrContainer = null; - Iterator iter = dgContainer.getChildIterator(); - while (iter.hasNext()) { - EscherRecord child = iter.next(); - if (child.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - spgrContainer = (EscherContainerRecord) child; - } - } - convertShapes(patriarch, spgrContainer, shapeToObj); - - patriarch = null; - } - } - } - - private void convertShapes(HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj) { - if (escherParent == null) throw new IllegalArgumentException("Parent record required"); - - List shapes = parent.getChildren(); - for (Iterator iterator = shapes.iterator(); iterator.hasNext(); ) { - HSSFShape shape = (HSSFShape) iterator.next(); - if (shape instanceof HSSFShapeGroup) { - convertGroup((HSSFShapeGroup) shape, escherParent, shapeToObj); - } else { - AbstractShape shapeModel = AbstractShape.createShape( - shape, - drawingManager.allocateShapeId(drawingGroupId)); - shapeToObj.put(findClientData(shapeModel.getSpContainer()), shapeModel.getObjRecord()); - if (shapeModel instanceof TextboxShape) { - EscherRecord escherTextbox = ((TextboxShape) shapeModel).getEscherTextbox(); - shapeToObj.put(escherTextbox, ((TextboxShape) shapeModel).getTextObjectRecord()); - // escherParent.addChildRecord(escherTextbox); - - if (shapeModel instanceof CommentShape) { - CommentShape comment = (CommentShape) shapeModel; - tailRec.put(comment.getNoteRecord().getShapeId(), comment.getNoteRecord()); - } - - } - escherParent.addChildRecord(shapeModel.getSpContainer()); - } - } -// drawingManager.newCluster( (short)1 ); -// drawingManager.newCluster( (short)2 ); - - } - - private void convertGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj) { - EscherContainerRecord spgrContainer = new EscherContainerRecord(); - EscherContainerRecord spContainer = new EscherContainerRecord(); - EscherSpgrRecord spgr = new EscherSpgrRecord(); - EscherSpRecord sp = new EscherSpRecord(); - EscherOptRecord opt = new EscherOptRecord(); - EscherRecord anchor; - EscherClientDataRecord clientData = new EscherClientDataRecord(); - - spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); - spgrContainer.setOptions((short) 0x000F); - spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER); - spContainer.setOptions((short) 0x000F); - spgr.setRecordId(EscherSpgrRecord.RECORD_ID); - spgr.setOptions((short) 0x0001); - spgr.setRectX1(shape.getX1()); - spgr.setRectY1(shape.getY1()); - spgr.setRectX2(shape.getX2()); - spgr.setRectY2(shape.getY2()); - sp.setRecordId(EscherSpRecord.RECORD_ID); - sp.setOptions((short) 0x0002); - int shapeId = drawingManager.allocateShapeId(drawingGroupId); - sp.setShapeId(shapeId); - if (shape.getAnchor() instanceof HSSFClientAnchor) - sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR); - else - sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD); - opt.setRecordId(EscherOptRecord.RECORD_ID); - opt.setOptions((short) 0x0023); - opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004)); - opt.addEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); - - anchor = ConvertAnchor.createAnchor(shape.getAnchor()); -// clientAnchor.setCol1( ( (HSSFClientAnchor) shape.getAnchor() ).getCol1() ); -// clientAnchor.setRow1( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow1() ); -// clientAnchor.setDx1( (short) shape.getAnchor().getDx1() ); -// clientAnchor.setDy1( (short) shape.getAnchor().getDy1() ); -// clientAnchor.setCol2( ( (HSSFClientAnchor) shape.getAnchor() ).getCol2() ); -// clientAnchor.setRow2( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow2() ); -// clientAnchor.setDx2( (short) shape.getAnchor().getDx2() ); -// clientAnchor.setDy2( (short) shape.getAnchor().getDy2() ); - clientData.setRecordId(EscherClientDataRecord.RECORD_ID); - clientData.setOptions((short) 0x0000); - - spgrContainer.addChildRecord(spContainer); - spContainer.addChildRecord(spgr); - spContainer.addChildRecord(sp); - spContainer.addChildRecord(opt); - spContainer.addChildRecord(anchor); - spContainer.addChildRecord(clientData); - - ObjRecord obj = new ObjRecord(); - CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); - cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP); - cmo.setObjectId(shapeId); - cmo.setLocked(true); - cmo.setPrintable(true); - cmo.setAutofill(true); - cmo.setAutoline(true); - GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); - EndSubRecord end = new EndSubRecord(); - obj.addSubRecord(cmo); - obj.addSubRecord(gmo); - obj.addSubRecord(end); - shapeToObj.put(clientData, obj); - - escherParent.addChildRecord(spgrContainer); - - convertShapes(shape, spgrContainer, shapeToObj); - - } - private EscherRecord findClientData(EscherContainerRecord spContainer) { for (Iterator iterator = spContainer.getChildIterator(); iterator.hasNext(); ) { EscherRecord r = iterator.next(); @@ -1067,7 +672,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { dg.setOptions((short) (dgId << 4)); dg.setNumShapes(0); dg.setLastMSOSPID(1024); - drawingGroupId = dg.getDrawingGroupId(); spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); spgrContainer.setOptions((short) 0x000F); spContainer1.setRecordId(EscherContainerRecord.SP_CONTAINER); @@ -1105,46 +709,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { sp.setShapeId(shapeId); } - private void convertPatriarch(HSSFPatriarch patriarch) { - EscherContainerRecord dgContainer = new EscherContainerRecord(); - EscherDgRecord dg; - EscherContainerRecord spgrContainer = new EscherContainerRecord(); - EscherContainerRecord spContainer1 = new EscherContainerRecord(); - EscherSpgrRecord spgr = new EscherSpgrRecord(); - EscherSpRecord sp1 = new EscherSpRecord(); - - dgContainer.setRecordId(EscherContainerRecord.DG_CONTAINER); - dgContainer.setOptions((short) 0x000F); - dg = drawingManager.createDgRecord(); - drawingGroupId = dg.getDrawingGroupId(); -// dg.setOptions( (short) ( drawingId << 4 ) ); -// dg.setNumShapes( getNumberOfShapes( patriarch ) ); -// dg.setLastMSOSPID( 0 ); // populated after all shape id's are assigned. - spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); - spgrContainer.setOptions((short) 0x000F); - spContainer1.setRecordId(EscherContainerRecord.SP_CONTAINER); - spContainer1.setOptions((short) 0x000F); - spgr.setRecordId(EscherSpgrRecord.RECORD_ID); - spgr.setOptions((short) 0x0001); // version - spgr.setRectX1(patriarch.getX1()); - spgr.setRectY1(patriarch.getY1()); - spgr.setRectX2(patriarch.getX2()); - spgr.setRectY2(patriarch.getY2()); - sp1.setRecordId(EscherSpRecord.RECORD_ID); - sp1.setOptions((short) 0x0002); - sp1.setShapeId(drawingManager.allocateShapeId(dg.getDrawingGroupId())); - sp1.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH); - - dgContainer.addChildRecord(dg); - dgContainer.addChildRecord(spgrContainer); - spgrContainer.addChildRecord(spContainer1); - spContainer1.addChildRecord(spgr); - spContainer1.addChildRecord(sp1); - - addEscherRecord(dgContainer); - } - - private static short sid(List records, int loc) { return ((Record) records.get(loc)).getSid(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java index 4b13278f0c..184a6d3201 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java @@ -18,6 +18,11 @@ public class HSSFCombobox extends HSSFSimpleShape { super.setShapeType(OBJECT_TYPE_COMBO_BOX); } + @Override + protected TextObjectRecord createTextObjRecord() { + return null; + } + @Override protected EscherContainerRecord createSpContainer() { EscherContainerRecord spContainer = new EscherContainerRecord(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index ea8ae3c7e7..8bafa3b507 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -70,7 +70,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { @Override void afterInsert(HSSFPatriarch patriarch) { super.afterInsert(patriarch); - _patriarch._getBoundAggregate().addTailRecord(getNoteRecord()); + patriarch._getBoundAggregate().addTailRecord(getNoteRecord()); } @Override @@ -113,8 +113,8 @@ public class HSSFComment extends HSSFTextbox implements Comment { void setShapeId(int shapeId) { super.setShapeId(shapeId); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); - cod.setObjectId((short) (shapeId)); - _note.setShapeId(shapeId); + cod.setObjectId((short) (shapeId % 1024)); + _note.setShapeId(shapeId % 1024); } /** @@ -214,4 +214,15 @@ public class HSSFComment extends HSSFTextbox implements Comment { patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); patriarch._getBoundAggregate().removeTailRecord(getNoteRecord()); } + + @Override + public HSSFShape cloneShape() { + TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise(); + EscherContainerRecord spContainer = new EscherContainerRecord(); + byte [] inSp = getEscherContainer().serialize(); + spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); + ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); + NoteRecord note = (NoteRecord) getNoteRecord().cloneViaReserialise(); + return new HSSFComment(spContainer, obj, txo, note); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java index efb19331b0..565c89e78c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java @@ -21,22 +21,20 @@ package org.apache.poi.hssf.usermodel; import java.io.IOException; import java.util.Iterator; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord; -import org.apache.poi.hssf.record.ObjRecord; -import org.apache.poi.hssf.record.SubRecord; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.*; import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.Entry; import org.apache.poi.util.HexDump; /** * Represents binary object (i.e. OLE) data stored in the file. Eg. A GIF, JPEG etc... - * + *

* Right now, 13, july, 2012 can not be created from scratch * * @author Daniel Noll */ -public final class HSSFObjectData extends HSSFShape{ +public final class HSSFObjectData extends HSSFShape { /** * Reference to the filesystem root, required for retrieving the object data. */ @@ -56,7 +54,7 @@ public final class HSSFObjectData extends HSSFShape{ /** * Gets the object data. Only call for ones that have - * data though. See {@link #hasDirectoryEntry()} + * data though. See {@link #hasDirectoryEntry()} * * @return the object data as an OLE2 directory. * @throws IOException if there was an error reading the data. @@ -76,8 +74,8 @@ public final class HSSFObjectData extends HSSFShape{ /** * Returns the data portion, for an ObjectData - * that doesn't have an associated POIFS Directory - * Entry + * that doesn't have an associated POIFS Directory + * Entry */ public byte[] getObjectData() { return findObjectRecord().getObjectData(); @@ -85,7 +83,7 @@ public final class HSSFObjectData extends HSSFShape{ /** * Does this ObjectData have an associated POIFS - * Directory Entry? + * Directory Entry? * (Not all do, those that don't have a data portion) */ public boolean hasDirectoryEntry() { @@ -98,7 +96,7 @@ public final class HSSFObjectData extends HSSFShape{ /** * Finds the EmbeddedObjectRefSubRecord, or throws an - * Exception if there wasn't one + * Exception if there wasn't one */ protected EmbeddedObjectRefSubRecord findObjectRecord() { Iterator subRecordIter = getObjRecord().getSubRecords().iterator(); @@ -106,7 +104,7 @@ public final class HSSFObjectData extends HSSFShape{ while (subRecordIter.hasNext()) { Object subRecord = subRecordIter.next(); if (subRecord instanceof EmbeddedObjectRefSubRecord) { - return (EmbeddedObjectRefSubRecord)subRecord; + return (EmbeddedObjectRefSubRecord) subRecord; } } @@ -130,6 +128,39 @@ public final class HSSFObjectData extends HSSFShape{ @Override void afterInsert(HSSFPatriarch patriarch) { - throw new IllegalStateException("HSSFObjectData cannot be created from scratch"); + EscherAggregate agg = patriarch._getBoundAggregate(); + agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + EscherBSERecord bse = + patriarch._sheet.getWorkbook().getWorkbook().getBSERecord(getPictureIndex()); + bse.setRef(bse.getRef() + 1); + } + + @Override + public HSSFShape cloneShape() { + EscherContainerRecord spContainer = new EscherContainerRecord(); + byte[] inSp = getEscherContainer().serialize(); + spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); + ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); + return new HSSFObjectData(spContainer, obj, _root); + } + + public int getPictureIndex() { + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.BLIP__BLIPTODISPLAY); + if (null == property) { + return -1; + } + return property.getPropertyValue(); + } + + public void setPictureIndex(int pictureIndex) { + setPropertyValue(new EscherSimpleProperty(EscherProperties.BLIP__BLIPTODISPLAY, false, true, pictureIndex)); + } + + @Override + void setShapeId(int shapeId) { + EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + spRecord.setShapeId(shapeId); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); + cod.setObjectId((short) (shapeId % 1024)); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 221dfc475a..96d12adaa7 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -38,10 +38,6 @@ import org.apache.poi.ss.usermodel.ClientAnchor; */ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { private final List _shapes = new ArrayList(); -// private int _x1 = 0; -// private int _y1 = 0 ; -// private int _x2 = 1023; -// private int _y2 = 255; private final EscherSpgrRecord _spgrRecord; private final EscherContainerRecord _mainSpgrContainer; @@ -49,19 +45,19 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * The EscherAggregate we have been bound to. * (This will handle writing us out into records, - * and building up our shapes from the records) + * and building up our shapes from the records) */ private EscherAggregate _boundAggregate; - final HSSFSheet _sheet; // TODO make private + final HSSFSheet _sheet; // TODO make private /** * Creates the patriarch. * * @param sheet the sheet this patriarch is stored in. */ - HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate){ + HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate) { _sheet = sheet; - _boundAggregate = boundAggregate; + _boundAggregate = boundAggregate; _mainSpgrContainer = _boundAggregate.getEscherContainer().getChildContainers().get(0); EscherContainerRecord spContainer = (EscherContainerRecord) _boundAggregate.getEscherContainer() .getChildContainers().get(0).getChild(0); @@ -69,17 +65,36 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { buildShapeTree(); } + static HSSFPatriarch createPatriarch(HSSFPatriarch patriarch, HSSFSheet sheet){ + HSSFPatriarch newPatriarch = new HSSFPatriarch(sheet, new EscherAggregate()); + newPatriarch.afterCreate(); + + for (HSSFShape shape: patriarch.getChildren()){ + HSSFShape newShape; + if (shape instanceof HSSFShapeGroup){ + newShape = ((HSSFShapeGroup)shape).cloneShape(newPatriarch); + } else { + newShape = shape.cloneShape(); + } + newPatriarch.onCreate(newShape); + newPatriarch.addShape(newShape); + } + + return newPatriarch; + } + /** * remove first level shapes + * * @param shape to be removed */ - public void removeShape(HSSFShape shape){ + public void removeShape(HSSFShape shape) { _mainSpgrContainer.removeChildRecord(shape.getEscherContainer()); shape.afterRemove(this); _shapes.remove(shape); } - public void afterCreate(){ + void afterCreate() { DrawingManager2 drawingManager = _sheet.getWorkbook().getWorkbook().getDrawingManager(); short dgId = drawingManager.findNewDrawingGroupId(); _boundAggregate.setDgId(dgId); @@ -90,12 +105,11 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * Creates a new group record stored under this patriarch. * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created group. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created group. */ - public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) - { + public HSSFShapeGroup createGroup(HSSFClientAnchor anchor) { HSSFShapeGroup group = new HSSFShapeGroup(null, anchor); addShape(group); onCreate(group); @@ -106,21 +120,20 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * Creates a simple shape. This includes such shapes as lines, rectangles, * and ovals. * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. */ - public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) - { + public HSSFSimpleShape createSimpleShape(HSSFClientAnchor anchor) { HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor); addShape(shape); //open existing file onCreate(shape); EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - if (shape.anchor.isHorizontallyFlipped()){ + if (shape.anchor.isHorizontallyFlipped()) { sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); } - if (shape.anchor.isVerticallyFlipped()){ + if (shape.anchor.isVerticallyFlipped()) { sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); } return shape; @@ -129,42 +142,39 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * Creates a picture. * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. */ - public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex) - { + public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex) { HSSFPicture shape = new HSSFPicture(null, anchor); - shape.setPictureIndex( pictureIndex ); + shape.setPictureIndex(pictureIndex); addShape(shape); //open existing file onCreate(shape); EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - if (shape.anchor.isHorizontallyFlipped()){ + if (shape.anchor.isHorizontallyFlipped()) { sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); } - if (shape.anchor.isVerticallyFlipped()){ + if (shape.anchor.isVerticallyFlipped()) { sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); } return shape; } - public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) - { - return createPicture((HSSFClientAnchor)anchor, pictureIndex); + public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) { + return createPicture((HSSFClientAnchor) anchor, pictureIndex); } /** * Creates a polygon * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. */ - public HSSFPolygon createPolygon(HSSFClientAnchor anchor) - { + public HSSFPolygon createPolygon(HSSFClientAnchor anchor) { HSSFPolygon shape = new HSSFPolygon(null, anchor); addShape(shape); onCreate(shape); @@ -174,12 +184,11 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * Constructs a textbox under the patriarch. * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created textbox. + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created textbox. */ - public HSSFTextbox createTextbox(HSSFClientAnchor anchor) - { + public HSSFTextbox createTextbox(HSSFClientAnchor anchor) { HSSFTextbox shape = new HSSFTextbox(null, anchor); addShape(shape); onCreate(shape); @@ -189,12 +198,11 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * Constructs a cell comment. * - * @param anchor the client anchor describes how this comment is attached - * to the sheet. - * @return the newly created comment. + * @param anchor the client anchor describes how this comment is attached + * to the sheet. + * @return the newly created comment. */ - public HSSFComment createComment(HSSFAnchor anchor) - { + public HSSFComment createComment(HSSFAnchor anchor) { HSSFComment shape = new HSSFComment(null, anchor); addShape(shape); onCreate(shape); @@ -206,23 +214,21 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * * @see org.apache.poi.hssf.usermodel.HSSFSheet#setAutoFilter(org.apache.poi.ss.util.CellRangeAddress) */ - HSSFSimpleShape createComboBox(HSSFAnchor anchor) - { - HSSFCombobox shape = new HSSFCombobox(null, anchor); - addShape(shape); - onCreate(shape); - return shape; - } + HSSFSimpleShape createComboBox(HSSFAnchor anchor) { + HSSFCombobox shape = new HSSFCombobox(null, anchor); + addShape(shape); + onCreate(shape); + return shape; + } public HSSFComment createCellComment(ClientAnchor anchor) { - return createComment((HSSFAnchor)anchor); + return createComment((HSSFAnchor) anchor); } /** * Returns a list of all shapes contained by the patriarch. */ - public List getChildren() - { + public List getChildren() { return _shapes; } @@ -230,23 +236,21 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * add a shape to this drawing */ @Internal - public void addShape(HSSFShape shape){ + public void addShape(HSSFShape shape) { shape._patriarch = this; _shapes.add(shape); } - private void onCreate(HSSFShape shape){ - if(_boundAggregate.getPatriarch() == null){ - EscherContainerRecord spgrContainer = - _boundAggregate.getEscherContainer().getChildContainers().get(0); + private void onCreate(HSSFShape shape) { + EscherContainerRecord spgrContainer = + _boundAggregate.getEscherContainer().getChildContainers().get(0); - EscherContainerRecord spContainer = shape.getEscherContainer(); - int shapeId = newShapeId(); - shape.setShapeId(shapeId); + EscherContainerRecord spContainer = shape.getEscherContainer(); + int shapeId = newShapeId(); + shape.setShapeId(shapeId); - spgrContainer.addChildRecord(spContainer); - shape.afterInsert(this); - } + spgrContainer.addChildRecord(spContainer); + shape.afterInsert(this); } /** @@ -254,17 +258,18 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ public int countOfAllChildren() { int count = _shapes.size(); - for (Iterator iterator = _shapes.iterator(); iterator.hasNext();) { + for (Iterator iterator = _shapes.iterator(); iterator.hasNext(); ) { HSSFShape shape = iterator.next(); count += shape.countOfAllChildren(); } return count; } + /** * Sets the coordinate space of this group. All children are constrained * to these coordinates. */ - public void setCoordinates(int x1, int y1, int x2, int y2){ + public void setCoordinates(int x1, int y1, int x2, int y2) { _spgrRecord.setRectY1(y1); _spgrRecord.setRectY2(y2); _spgrRecord.setRectX1(x1); @@ -282,28 +287,28 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * Does this HSSFPatriarch contain a chart? * (Technically a reference to a chart, since they - * get stored in a different block of records) + * get stored in a different block of records) * FIXME - detect chart in all cases (only seems - * to work on some charts so far) + * to work on some charts so far) */ public boolean containsChart() { // TODO - support charts properly in usermodel // We're looking for a EscherOptRecord EscherOptRecord optRecord = (EscherOptRecord) - _boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID); - if(optRecord == null) { + _boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID); + if (optRecord == null) { // No opt record, can't have chart return false; } - for(Iterator it = optRecord.getEscherProperties().iterator(); it.hasNext();) { + for (Iterator it = optRecord.getEscherProperties().iterator(); it.hasNext(); ) { EscherProperty prop = it.next(); - if(prop.getPropertyNumber() == 896 && prop.isComplex()) { - EscherComplexProperty cp = (EscherComplexProperty)prop; + if (prop.getPropertyNumber() == 896 && prop.isComplex()) { + EscherComplexProperty cp = (EscherComplexProperty) prop; String str = StringUtil.getFromUnicodeLE(cp.getComplexData()); - if(str.equals("Chart 1\0")) { + if (str.equals("Chart 1\0")) { return true; } } @@ -315,32 +320,28 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * The top left x coordinate of this group. */ - public int getX1() - { + public int getX1() { return _spgrRecord.getRectX1(); } /** * The top left y coordinate of this group. */ - public int getY1() - { + public int getY1() { return _spgrRecord.getRectY1(); } /** * The bottom right x coordinate of this group. */ - public int getX2() - { + public int getX2() { return _spgrRecord.getRectX2(); } /** * The bottom right y coordinate of this group. */ - public int getY2() - { + public int getY2() { return _spgrRecord.getRectY2(); } @@ -365,26 +366,26 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * @param row2 the row (0 based) of the second cell. * @return the newly created client anchor */ - public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2){ - return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short)col1, row1, (short)col2, row2); + public HSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) { + return new HSSFClientAnchor(dx1, dy1, dx2, dy2, (short) col1, row1, (short) col2, row2); } - public Chart createChart(ClientAnchor anchor) { - throw new RuntimeException("NotImplemented"); - } + public Chart createChart(ClientAnchor anchor) { + throw new RuntimeException("NotImplemented"); + } - void buildShapeTree(){ + void buildShapeTree() { EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer(); - if (dgContainer == null){ + if (dgContainer == null) { return; } EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0); List spgrChildren = spgrConrainer.getChildContainers(); - for(int i = 0; i < spgrChildren.size(); i++){ + for (int i = 0; i < spgrChildren.size(); i++) { EscherContainerRecord spContainer = spgrChildren.get(i); - if (i == 0){ + if (i == 0) { continue; } else { HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getRootDirectory()); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 6e5d98cf55..6bc713366d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.ss.usermodel.Picture; import org.apache.poi.ss.util.ImageUtils; @@ -88,6 +89,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID); removeEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING); removeEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH); + spContainer.removeChildRecord(spContainer.getChildById(EscherTextboxRecord.RECORD_ID)); return spContainer; } @@ -250,7 +252,8 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { @Override void afterInsert(HSSFPatriarch patriarch) { - super.afterInsert(patriarch); + EscherAggregate agg = patriarch._getBoundAggregate(); + agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); EscherBSERecord bse = patriarch._sheet.getWorkbook().getWorkbook().getBSERecord(getPictureIndex()); bse.setRef(bse.getRef() + 1); @@ -285,4 +288,13 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { public void setShapeType(int shapeType) { throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); } + + @Override + public HSSFShape cloneShape() { + EscherContainerRecord spContainer = new EscherContainerRecord(); + byte [] inSp = getEscherContainer().serialize(); + spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); + ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); + return new HSSFPicture(spContainer, obj); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index 079ae744ae..e145b9fe50 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -18,19 +18,20 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; -import org.apache.poi.hssf.record.CommonObjectDataSubRecord; -import org.apache.poi.hssf.record.EndSubRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.*; import org.apache.poi.util.LittleEndian; /** * @author Glen Stampoultzis (glens at superlinksoftware.com) */ -public class HSSFPolygon extends HSSFShape { +public class HSSFPolygon extends HSSFSimpleShape { public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 0x1E; + public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) { + super(spContainer, objRecord, _textObjectRecord); + } + public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord) { super(spContainer, objRecord); } @@ -39,6 +40,11 @@ public class HSSFPolygon extends HSSFShape { super(parent, anchor); } + @Override + protected TextObjectRecord createTextObjRecord() { + return null; + } + /** * Generates the shape records for this shape. */ @@ -200,10 +206,4 @@ public class HSSFPolygon extends HSSFShape { EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__BOTTOM); return property == null ? 100: property.getPropertyValue(); } - - @Override - void afterInsert(HSSFPatriarch patriarch) { - EscherAggregate agg = patriarch._getBoundAggregate(); - agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); - } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 4e01aa63ea..137ead3c75 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -302,4 +302,6 @@ public abstract class HSSFShape { public int countOfAllChildren() { return 1; } + + public abstract HSSFShape cloneShape(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 5d2c9bb619..178bdf5fe9 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -74,8 +74,12 @@ public class HSSFShapeFactory { public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - HSSFShapeGroup group = new HSSFShapeGroup(container, - null /* shape containers don't have a associated Obj record*/); + ObjRecord obj = null; + EscherClientDataRecord clientData = ((EscherContainerRecord)container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID); + if (null != clientData){ + obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData); + } + HSSFShapeGroup group = new HSSFShapeGroup(container, obj); List children = container.getChildContainers(); // skip the first child record, it is group descriptor for (int i = 0; i < children.size(); i++) { @@ -130,7 +134,7 @@ public class HSSFShapeFactory { EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES); if (null != property) { - shape = new HSSFPolygon(container, objRecord); + shape = new HSSFPolygon(container, objRecord, txtRecord); } else { shape = new HSSFSimpleShape(container, objRecord); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 32471f5176..548b45b75d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -127,13 +127,18 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { } private void onCreate(HSSFShape shape){ - if(_patriarch != null && _patriarch._getBoundAggregate().getPatriarch() == null){ + if(_patriarch != null){ EscherContainerRecord spContainer = shape.getEscherContainer(); int shapeId = _patriarch.newShapeId(); shape.setShapeId(shapeId); getEscherContainer().addChildRecord(spContainer); shape.afterInsert(_patriarch); - EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + EscherSpRecord sp; + if (shape instanceof HSSFShapeGroup){ + sp = shape.getEscherContainer().getChildContainers().get(0).getChildById(EscherSpRecord.RECORD_ID); + } else { + sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + } sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD); } } @@ -312,7 +317,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID); spRecord.setShapeId(shapeId); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); - cod.setObjectId((short) (shapeId)); + cod.setObjectId((short) (shapeId % 1024)); } @Override @@ -320,4 +325,39 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER); return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); } + + @Override + public HSSFShape cloneShape() { + throw new IllegalStateException("Use method cloneShape(HSSFPatriarch patriarch)"); + } + + public HSSFShape cloneShape(HSSFPatriarch patriarch) { + EscherContainerRecord spgrContainer = new EscherContainerRecord(); + spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); + spgrContainer.setOptions((short) 0x000F); + EscherContainerRecord spContainer = new EscherContainerRecord(); + byte [] inSp = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER).serialize(); + spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); + + spgrContainer.addChildRecord(spContainer); + ObjRecord obj = null; + if (null != getObjRecord()){ + obj = (ObjRecord) getObjRecord().cloneViaReserialise(); + } + + HSSFShapeGroup group = new HSSFShapeGroup(spgrContainer, obj); + group._patriarch = patriarch; + + for (HSSFShape shape: getChildren()){ + HSSFShape newShape; + if (shape instanceof HSSFShapeGroup){ + newShape = ((HSSFShapeGroup)shape).cloneShape(patriarch); + } else { + newShape = shape.cloneShape(); + } + group.addShape(newShape); + group.onCreate(newShape); + } + return group; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index f294946008..afe4cf99d8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -115,7 +115,15 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { } HSSFSheet cloneSheet(HSSFWorkbook workbook) { - return new HSSFSheet(workbook, _sheet.cloneSheet()); + this.getDrawingPatriarch();/**Aggregate drawing records**/ + HSSFSheet sheet = new HSSFSheet(workbook, _sheet.cloneSheet()); + if (getDrawingPatriarch() != null){ + int insertPos = sheet._sheet.findFirstRecordLocBySid(WindowTwoRecord.sid); + HSSFPatriarch patr = HSSFPatriarch.createPatriarch(this.getDrawingPatriarch(), sheet); + sheet._sheet.getRecords().add(insertPos, patr._getBoundAggregate()); + sheet._patriarch = patr; + } + return sheet; } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 28153d2d45..eb2e865e76 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -68,14 +68,13 @@ public class HSSFSimpleShape extends HSSFShape objTypeToShapeType.put(OBJECT_TYPE_OVAL, HSSFShapeType.OVAL.getType()); } - public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord _textObjectRecord) { + public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) { super(spContainer, objRecord); - this._textObjectRecord = _textObjectRecord == null ? createTextObjRecord() : _textObjectRecord; + this._textObjectRecord = textObjectRecord; } public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord) { super(spContainer, objRecord); - this._textObjectRecord = createTextObjRecord(); } public HSSFSimpleShape( HSSFShape parent, HSSFAnchor anchor) @@ -92,6 +91,7 @@ public class HSSFSimpleShape extends HSSFShape TextObjectRecord obj = new TextObjectRecord(); obj.setTextLocked(true); obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE); + obj.setStr(new HSSFRichTextString("")); return obj; } @@ -123,10 +123,15 @@ public class HSSFSimpleShape extends HSSFShape optRecord.setEscherProperty(new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000)); optRecord.setRecordId( EscherOptRecord.RECORD_ID ); + EscherTextboxRecord escherTextbox = new EscherTextboxRecord(); + escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID); + escherTextbox.setOptions((short) 0x0000); + spContainer.addChildRecord(sp); spContainer.addChildRecord(optRecord); spContainer.addChildRecord(anchor.getEscherAnchor()); spContainer.addChildRecord(clientData); + spContainer.addChildRecord(escherTextbox); return spContainer; } @@ -167,21 +172,6 @@ public class HSSFSimpleShape extends HSSFShape HSSFRichTextString rtr = (HSSFRichTextString) string; // If font is not set we must set the default one if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); - EscherTextboxRecord textbox = getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID); - if (string.getString()!= null && !string.getString().equals("")){ - if (null == textbox){ - EscherTextboxRecord escherTextbox = new EscherTextboxRecord(); - escherTextbox.setRecordId(EscherTextboxRecord.RECORD_ID); - escherTextbox.setOptions((short) 0x0000); - getEscherContainer().addChildRecord(escherTextbox); - _patriarch._getBoundAggregate().associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord()); - } - } else { - if (null != textbox){ - getEscherContainer().removeChildRecord(textbox); - _patriarch._getBoundAggregate().removeShapeToObjRecord(textbox); - } - } _textObjectRecord.setStr(rtr); } @@ -189,6 +179,24 @@ public class HSSFSimpleShape extends HSSFShape void afterInsert(HSSFPatriarch patriarch){ EscherAggregate agg = patriarch._getBoundAggregate(); agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); + + //used only when clone shapes + if (null != getTextObjectRecord()){ + agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord()); + } + } + + @Override + public HSSFShape cloneShape() { + TextObjectRecord txo = null; + EscherContainerRecord spContainer = new EscherContainerRecord(); + byte [] inSp = getEscherContainer().serialize(); + spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); + ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); + if (getTextObjectRecord() != null && getString() != null && !"".equals(getString().getString())){ + txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise(); + } + return new HSSFSimpleShape(spContainer, obj, txo); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index af39d59784..cfbbd9797c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -235,4 +235,14 @@ public class HSSFTextbox extends HSSFSimpleShape { public void setShapeType(int shapeType) { throw new IllegalStateException("Shape type can not be changed in "+this.getClass().getSimpleName()); } + + @Override + public HSSFShape cloneShape() { + TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise(); + EscherContainerRecord spContainer = new EscherContainerRecord(); + byte [] inSp = getEscherContainer().serialize(); + spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); + ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); + return new HSSFTextbox(spContainer, obj, txo); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java index 827a5c34ac..75d33c6c65 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java @@ -48,4 +48,9 @@ public class HSSFUnknownShape extends HSSFShape { @Override void afterInsert(HSSFPatriarch patriarch) { } + + @Override + public HSSFShape cloneShape() { + return null; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 332289e109..cc6e40c271 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -701,7 +701,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss names.add(newName); } // TODO - maybe same logic required for other/all built-in name records - workbook.cloneDrawings(clonedSheet.getSheet()); +// workbook.cloneDrawings(clonedSheet.getSheet()); return clonedSheet; } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index b497212518..9de806cfc7 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -194,46 +194,6 @@ public class TestDrawingAggregate extends TestCase { } } - public void testBuildBaseTree(){ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); - EscherAggregate agg1 = new EscherAggregate(new HSSFTestHelper.MockDrawingManager()); - EscherSpgrRecord spgr = new EscherSpgrRecord(); - spgr.setRectY1(0); - spgr.setRectY2(255); - spgr.setRectX1(0); - spgr.setRectX2(1023); - EscherContainerRecord spContainer = new EscherContainerRecord(); - spContainer.addChildRecord(spgr); - EscherContainerRecord spgrContainer = new EscherContainerRecord(); - spgrContainer.addChildRecord(spContainer); - EscherContainerRecord dgContainer = new EscherContainerRecord(); - dgContainer.addChildRecord(spgrContainer); - agg1.addEscherRecord(dgContainer); - agg1.setPatriarch(HSSFTestHelper.createTestPatriarch(sheet, agg1)); - agg1.clear(); - HSSFTestHelper.callConvertPatriarch(agg1); - agg1.setPatriarch(null); - - agg.setPatriarch(null); -// - EscherSpRecord sp = (EscherSpRecord) agg.getEscherContainer().getChildContainers().get(0).getChild(0).getChild(1); - sp.setShapeId(1025); - EscherDgRecord dg = (EscherDgRecord) agg.getEscherContainer().getChild(0); - dg.setNumShapes(1); - dg.setOptions((short) (1 << 4)); - - byte[] aggS = agg.serialize(); - byte []agg1S = agg1.serialize(); - - assertEquals(aggS.length, agg1S.length); - assertTrue(Arrays.equals(aggS, agg1S)); - } - - - /** * when reading incomplete data ensure that the serialized bytes match the source diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index dd8882764f..e57a1b4372 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -352,8 +352,7 @@ public class TestDrawingShapes extends TestCase { shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); - assertNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); - assertEquals(agg.getShapeToObjMapping().size(), 1); + assertEquals(agg.getShapeToObjMapping().size(), 2); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sheet = wb.getSheetAt(0); @@ -362,8 +361,7 @@ public class TestDrawingShapes extends TestCase { shape = (HSSFSimpleShape) patriarch.getChildren().get(0); agg = HSSFTestHelper.getEscherAggregate(patriarch); - assertNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); - assertEquals(agg.getShapeToObjMapping().size(), 1); + assertEquals(agg.getShapeToObjMapping().size(), 2); shape.setString(new HSSFRichTextString("string1")); assertEquals(shape.getString().getString(), "string1"); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 50ff1dc50c..465f7746b0 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -101,21 +101,6 @@ public class HSSFTestHelper { } } - public static void callConvertPatriarch(EscherAggregate agg) { - Method method = null; - try { - method = agg.getClass().getDeclaredMethod("convertPatriarch", HSSFPatriarch.class); - method.setAccessible(true); - method.invoke(agg, agg.getPatriarch()); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - public static void setShapeId(HSSFShape shape, int id){ shape.setShapeId(id); } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java index 1f276b7765..10acaa5e9f 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java @@ -19,8 +19,14 @@ package org.apache.poi.hssf.usermodel; import junit.framework.TestCase; +import org.apache.poi.ddf.EscherDgRecord; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.ss.util.CellRangeAddress; +import java.io.IOException; +import java.util.Arrays; + /** * Test the ability to clone a sheet. * If adding new records that belong to a sheet (as opposed to a book) @@ -55,4 +61,74 @@ public final class TestCloneSheet extends TestCase { assertTrue("Row 3 still should be broken", clone.isRowBroken(3)); } + + public void testCloneSheetWithoutDrawings(){ + HSSFWorkbook b = new HSSFWorkbook(); + HSSFSheet s = b.createSheet("Test"); + HSSFSheet s2 = s.cloneSheet(b); + + assertNull(s.getDrawingPatriarch()); + assertNull(s2.getDrawingPatriarch()); + assertEquals(HSSFTestHelper.getSheetForTest(s).getRecords().size(), HSSFTestHelper.getSheetForTest(s2).getRecords().size()); + } + + public void testCloneSheetWithEmptyDrawingAggregate(){ + HSSFWorkbook b = new HSSFWorkbook(); + HSSFSheet s = b.createSheet("Test"); + HSSFPatriarch patriarch = s.createDrawingPatriarch(); + + EscherAggregate agg1 = patriarch._getBoundAggregate(); + + HSSFSheet s2 = s.cloneSheet(b); + + patriarch = s2.getDrawingPatriarch(); + + EscherAggregate agg2 = patriarch._getBoundAggregate(); + + EscherSpRecord sp1 = (EscherSpRecord) agg1.getEscherContainer().getChild(1).getChild(0).getChild(1); + EscherSpRecord sp2 = (EscherSpRecord) agg2.getEscherContainer().getChild(1).getChild(0).getChild(1); + + assertEquals(sp1.getShapeId(), 1024); + assertEquals(sp2.getShapeId(), 2048); + + EscherDgRecord dg = (EscherDgRecord) agg2.getEscherContainer().getChild(0); + + assertEquals(dg.getLastMSOSPID(), 2048); + assertEquals(dg.getInstance(), 0x2); + + //everything except id and DgRecord.lastMSOSPID and DgRecord.Instance must be the same + + sp2.setShapeId(1024); + dg.setLastMSOSPID(1024); + dg.setInstance((short) 0x1); + + assertEquals(agg1.serialize().length, agg2.serialize().length); + assertEquals(agg1.toXml(""), agg2.toXml("")); + assertTrue(Arrays.equals(agg1.serialize(), agg2.serialize())); + } + + public void testCloneComment() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch p = sh.createDrawingPatriarch(); + HSSFComment c = p.createComment(new HSSFClientAnchor(0,0,100,100, (short) 0,0,(short)5,5)); + c.setColumn(1); + c.setRow(2); + c.setString(new HSSFRichTextString("qwertyuio")); + + HSSFSheet sh2 = wb.cloneSheet(0); + HSSFPatriarch p2 = sh2.getDrawingPatriarch(); + HSSFComment c2 = (HSSFComment) p2.getChildren().get(0); + + assertTrue(Arrays.equals(c2.getTextObjectRecord().serialize(), c.getTextObjectRecord().serialize())); + assertTrue(Arrays.equals(c2.getObjRecord().serialize(), c.getObjRecord().serialize())); + assertTrue(Arrays.equals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize())); + + + //everything except spRecord.shapeId must be the same + assertFalse(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize())); + EscherSpRecord sp = (EscherSpRecord) c2.getEscherContainer().getChild(0); + sp.setShapeId(1025); + assertTrue(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize())); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java index b098c19737..cbf49bb5e3 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -58,6 +58,8 @@ public class TestComment extends TestCase { ObjRecord obj = comment.getObjRecord(); ObjRecord objShape = commentShape.getObjRecord(); + /**shapeId = 1025 % 1024**/ + ((CommonObjectDataSubRecord)objShape.getSubRecords().get(0)).setObjectId(1); expected = obj.serialize(); actual = objShape.serialize(); @@ -76,6 +78,7 @@ public class TestComment extends TestCase { NoteRecord note = comment.getNoteRecord(); NoteRecord noteShape = commentShape.getNoteRecord(); + noteShape.setShapeId(1); expected = note.serialize(); actual = noteShape.serialize(); @@ -225,17 +228,17 @@ public class TestComment extends TestCase { comment.setShapeId(2024); /** * SpRecord.id == shapeId - * ObjRecord.id == shapeId - 1024 - * NoteRecord.id == ObjectRecord.id == shapeId - 1024 + * ObjRecord.id == shapeId % 1024 + * NoteRecord.id == ObjectRecord.id == shapeId % 1024 */ assertEquals(comment.getShapeId(), 2024); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0); - assertEquals(cod.getObjectId(), 2024); + assertEquals(cod.getObjectId(), 1000); EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0); assertEquals(spRecord.getShapeId(), 2024); assertEquals(comment.getShapeId(), 2024); - assertEquals(comment.getNoteRecord().getShapeId(), 2024); + assertEquals(comment.getNoteRecord().getShapeId(), 1000); } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java index 1abf1026ed..d05f048771 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java @@ -808,8 +808,8 @@ public final class TestHSSFSheet extends BaseTestSheet { HSSFSheet sheet2 = wb2.getSheetAt(1); //check that id of the drawing group was updated - EscherDgRecord dg1 = (EscherDgRecord)sheet1.getDrawingEscherAggregate().findFirstWithId(EscherDgRecord.RECORD_ID); - EscherDgRecord dg2 = (EscherDgRecord)sheet2.getDrawingEscherAggregate().findFirstWithId(EscherDgRecord.RECORD_ID); + EscherDgRecord dg1 = (EscherDgRecord)sheet1.getDrawingPatriarch()._getBoundAggregate().findFirstWithId(EscherDgRecord.RECORD_ID); + EscherDgRecord dg2 = (EscherDgRecord)sheet2.getDrawingPatriarch()._getBoundAggregate().findFirstWithId(EscherDgRecord.RECORD_ID); int dg_id_1 = dg1.getOptions() >> 4; int dg_id_2 = dg2.getOptions() >> 4; assertEquals(dg_id_1 + 1, dg_id_2); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java index 5eb93f6e3e..f0ce3f2801 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java @@ -17,29 +17,6 @@ import java.util.Map; */ public class TestShapeGroup extends TestCase{ - public void testResultEqualsToAbstractShape() { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); - - EscherContainerRecord container = new EscherContainerRecord(); - Map shapeToObj = new HashMap(); - HSSFTestHelper.convertHSSFGroup(group, container, shapeToObj); - - byte [] actual = group.getEscherContainer().serialize(); - byte [] expected = container.getChild(0).serialize(); - - assertEquals(actual.length, expected.length); - assertTrue(Arrays.equals(actual, expected)); - - actual = group.getObjRecord().serialize(); - expected = ((ObjRecord)shapeToObj.values().toArray()[0]).serialize(); - - assertEquals(actual.length, expected.length); - assertTrue(Arrays.equals(actual, expected)); - } - public void testSetGetCoordinates(){ HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); From 63ff9839aecfd3254e8fdc308d5f01a083c4e818 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Thu, 19 Jul 2012 20:29:42 +0000 Subject: [PATCH 21/32] implemented removing of all shape types git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1363524 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/usermodel/HSSFComment.java | 3 +- .../poi/hssf/usermodel/HSSFPatriarch.java | 11 +- .../poi/hssf/usermodel/HSSFPolygon.java | 1 + .../poi/hssf/usermodel/HSSFShapeGroup.java | 17 +++ .../poi/hssf/usermodel/HSSFSimpleShape.java | 4 + .../poi/hssf/usermodel/HSSFTextbox.java | 39 +++-- .../poi/hssf/model/TestDrawingShapes.java | 141 ++++++++++++++++++ 7 files changed, 194 insertions(+), 22 deletions(-) diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 8bafa3b507..4922529e6d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -210,8 +210,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { } public void afterRemove(HSSFPatriarch patriarch){ - patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID)); - patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + super.afterRemove(patriarch); patriarch._getBoundAggregate().removeTailRecord(getNoteRecord()); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 96d12adaa7..8f40651205 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -88,10 +88,13 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * * @param shape to be removed */ - public void removeShape(HSSFShape shape) { - _mainSpgrContainer.removeChildRecord(shape.getEscherContainer()); - shape.afterRemove(this); - _shapes.remove(shape); + public boolean removeShape(HSSFShape shape) { + boolean isRemoved = _mainSpgrContainer.removeChildRecord(shape.getEscherContainer()); + if (isRemoved){ + shape.afterRemove(this); + _shapes.remove(shape); + } + return isRemoved; } void afterCreate() { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index e145b9fe50..0d15030c96 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -114,6 +114,7 @@ public class HSSFPolygon extends HSSFSimpleShape { @Override protected void afterRemove(HSSFPatriarch patriarch) { + patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID)); } public int[] getXPoints() { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 548b45b75d..7cf6803fd0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -124,6 +124,14 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { @Override protected void afterRemove(HSSFPatriarch patriarch) { + patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildContainers().get(0) + .getChildById(EscherClientDataRecord.RECORD_ID)); + for ( int i=0; i Date: Mon, 23 Jul 2012 09:06:56 +0000 Subject: [PATCH 22/32] added few improvements git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1364547 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/model/AbstractShape.java | 1 + .../apache/poi/hssf/model/ComboboxShape.java | 1 + .../apache/poi/hssf/model/CommentShape.java | 1 + .../org/apache/poi/hssf/model/LineShape.java | 1 + .../apache/poi/hssf/model/PolygonShape.java | 1 + .../poi/hssf/model/SimpleFilledShape.java | 1 + .../apache/poi/hssf/model/TextboxShape.java | 1 + .../apache/poi/hssf/usermodel/HSSFCell.java | 57 --------- .../poi/hssf/usermodel/HSSFObjectData.java | 24 +--- .../poi/hssf/usermodel/HSSFPatriarch.java | 46 ++++--- .../poi/hssf/usermodel/HSSFPicture.java | 22 ++-- .../apache/poi/hssf/usermodel/HSSFShape.java | 52 +++++++- .../hssf/usermodel/HSSFShapeContainer.java | 13 +- .../poi/hssf/usermodel/HSSFShapeGroup.java | 22 ++-- .../poi/hssf/usermodel/HSSFSimpleShape.java | 3 + .../poi/hssf/usermodel/HSSFTextbox.java | 8 -- .../poi/hssf/model/TestDrawingShapes.java | 114 ++++++++++++++++++ .../poi/hssf/usermodel/TestHSSFPicture.java | 10 +- .../poi/hssf/usermodel/TestShapeGroup.java | 33 +++++ test-data/spreadsheet/drawings.xls | Bin 851968 -> 851968 bytes 20 files changed, 280 insertions(+), 131 deletions(-) diff --git a/src/java/org/apache/poi/hssf/model/AbstractShape.java b/src/java/org/apache/poi/hssf/model/AbstractShape.java index 3fd8883d63..3441ba9f44 100644 --- a/src/java/org/apache/poi/hssf/model/AbstractShape.java +++ b/src/java/org/apache/poi/hssf/model/AbstractShape.java @@ -26,6 +26,7 @@ import org.apache.poi.hssf.usermodel.*; * * @author Glen Stampoultzis (glens at apache.org) */ +@Deprecated public abstract class AbstractShape { /** diff --git a/src/java/org/apache/poi/hssf/model/ComboboxShape.java b/src/java/org/apache/poi/hssf/model/ComboboxShape.java index 674fc46f0f..ffca90a79f 100644 --- a/src/java/org/apache/poi/hssf/model/ComboboxShape.java +++ b/src/java/org/apache/poi/hssf/model/ComboboxShape.java @@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.*; * * @author Yegor Kozlov */ +@Deprecated public class ComboboxShape extends AbstractShape { private EscherContainerRecord spContainer; diff --git a/src/java/org/apache/poi/hssf/model/CommentShape.java b/src/java/org/apache/poi/hssf/model/CommentShape.java index f739a44d72..19e83fff66 100644 --- a/src/java/org/apache/poi/hssf/model/CommentShape.java +++ b/src/java/org/apache/poi/hssf/model/CommentShape.java @@ -39,6 +39,7 @@ import org.apache.poi.hssf.usermodel.HSSFShape; * * @author Yegor Kozlov */ +@Deprecated public final class CommentShape extends TextboxShape { private NoteRecord _note; diff --git a/src/java/org/apache/poi/hssf/model/LineShape.java b/src/java/org/apache/poi/hssf/model/LineShape.java index 2480d42606..e4517e4d7a 100644 --- a/src/java/org/apache/poi/hssf/model/LineShape.java +++ b/src/java/org/apache/poi/hssf/model/LineShape.java @@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.*; * * @author Glen Stampoultzis (glens at apache.org) */ +@Deprecated public class LineShape extends AbstractShape { diff --git a/src/java/org/apache/poi/hssf/model/PolygonShape.java b/src/java/org/apache/poi/hssf/model/PolygonShape.java index 22212c88d2..1543e2df80 100644 --- a/src/java/org/apache/poi/hssf/model/PolygonShape.java +++ b/src/java/org/apache/poi/hssf/model/PolygonShape.java @@ -27,6 +27,7 @@ import org.apache.poi.hssf.usermodel.HSSFShape; import org.apache.poi.hssf.usermodel.HSSFPolygon; import org.apache.poi.util.LittleEndian; +@Deprecated public class PolygonShape extends AbstractShape { diff --git a/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java b/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java index 739e1ce329..1763b9d562 100644 --- a/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java +++ b/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java @@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.EndSubRecord; import org.apache.poi.hssf.usermodel.HSSFSimpleShape; import org.apache.poi.hssf.usermodel.HSSFShape; +@Deprecated public class SimpleFilledShape extends AbstractShape { diff --git a/src/java/org/apache/poi/hssf/model/TextboxShape.java b/src/java/org/apache/poi/hssf/model/TextboxShape.java index 1ea79d0942..1b2a154a1d 100644 --- a/src/java/org/apache/poi/hssf/model/TextboxShape.java +++ b/src/java/org/apache/poi/hssf/model/TextboxShape.java @@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.*; * * @author Glen Stampoultzis (glens at apache.org) */ +@Deprecated public class TextboxShape extends AbstractShape { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 67fb64f227..1ad05587e6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -1041,63 +1041,6 @@ public class HSSFCell implements Cell { _sheet.getDrawingPatriarch().removeShape(comment); } - /** - * Cell comment finder. - * Returns cell comment for the specified sheet, row and column. - * - * @return cell comment or null if not found - */ - protected static HSSFComment findCellComment(InternalSheet sheet, int row, int column) { - // TODO - optimise this code by searching backwards, find NoteRecord first, quit if not found. Find one TXO by id - HSSFComment comment = null; - Map noteTxo = - new HashMap(); - int i = 0; - for (Iterator it = sheet.getRecords().iterator(); it.hasNext();) { - RecordBase rec = it.next(); - if (rec instanceof NoteRecord) { - NoteRecord note = (NoteRecord) rec; - if (note.getRow() == row && note.getColumn() == column) { - if(i < noteTxo.size()) { - TextObjectRecord txo = noteTxo.get(note.getShapeId()); - if(txo != null){ - comment = new HSSFComment(note, txo); - comment.setRow(note.getRow()); - comment.setColumn(note.getColumn()); - comment.setAuthor(note.getAuthor()); - comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE); - comment.setString(txo.getStr()); - } else{ - log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column); - } - } else { - log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column); - } - break; - } - i++; - } else if (rec instanceof ObjRecord) { - ObjRecord obj = (ObjRecord) rec; - SubRecord sub = obj.getSubRecords().get(0); - if (sub instanceof CommonObjectDataSubRecord) { - CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) sub; - if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT) { - //map ObjectId and corresponding TextObjectRecord, - //it will be used to match NoteRecord and TextObjectRecord - while (it.hasNext()) { - rec = it.next(); - if (rec instanceof TextObjectRecord) { - noteTxo.put(cmo.getObjectId(), (TextObjectRecord) rec); - break; - } - } - } - } - } - } - return comment; - } - /** * @return hyperlink associated with this cell or null if not found */ diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java index 565c89e78c..dfe2b76a7e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java @@ -34,7 +34,7 @@ import org.apache.poi.util.HexDump; * * @author Daniel Noll */ -public final class HSSFObjectData extends HSSFShape { +public final class HSSFObjectData extends HSSFPicture { /** * Reference to the filesystem root, required for retrieving the object data. */ @@ -131,7 +131,7 @@ public final class HSSFObjectData extends HSSFShape { EscherAggregate agg = patriarch._getBoundAggregate(); agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); EscherBSERecord bse = - patriarch._sheet.getWorkbook().getWorkbook().getBSERecord(getPictureIndex()); + patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex()); bse.setRef(bse.getRef() + 1); } @@ -143,24 +143,4 @@ public final class HSSFObjectData extends HSSFShape { ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); return new HSSFObjectData(spContainer, obj, _root); } - - public int getPictureIndex() { - EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.BLIP__BLIPTODISPLAY); - if (null == property) { - return -1; - } - return property.getPropertyValue(); - } - - public void setPictureIndex(int pictureIndex) { - setPropertyValue(new EscherSimpleProperty(EscherProperties.BLIP__BLIPTODISPLAY, false, true, pictureIndex)); - } - - @Override - void setShapeId(int shapeId) { - EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - spRecord.setShapeId(shapeId); - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); - cod.setObjectId((short) (shapeId % 1024)); - } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 8f40651205..9240998c20 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.usermodel; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -48,7 +49,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * and building up our shapes from the records) */ private EscherAggregate _boundAggregate; - final HSSFSheet _sheet; // TODO make private + private final HSSFSheet _sheet; /** * Creates the patriarch. @@ -132,13 +133,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { addShape(shape); //open existing file onCreate(shape); - EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - if (shape.anchor.isHorizontallyFlipped()) { - sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); - } - if (shape.anchor.isVerticallyFlipped()) { - sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); - } return shape; } @@ -155,14 +149,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { addShape(shape); //open existing file onCreate(shape); - - EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - if (shape.anchor.isHorizontallyFlipped()) { - sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); - } - if (shape.anchor.isVerticallyFlipped()) { - sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); - } return shape; } @@ -232,7 +218,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { * Returns a list of all shapes contained by the patriarch. */ public List getChildren() { - return _shapes; + return Collections.unmodifiableList(_shapes); } /** @@ -254,6 +240,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { spgrContainer.addChildRecord(spContainer); shape.afterInsert(this); + setFlipFlags(shape); } /** @@ -279,6 +266,13 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { _spgrRecord.setRectX2(x2); } + public void clear() { + ArrayList copy = new ArrayList(_shapes); + for (HSSFShape shape: copy){ + removeShape(shape); + } + } + int newShapeId() { DrawingManager2 dm = _sheet.getWorkbook().getWorkbook().getDrawingManager(); EscherDgRecord dg = @@ -395,4 +389,22 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { } } } + + private void setFlipFlags(HSSFShape shape){ + EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + if (shape.anchor.isHorizontallyFlipped()) { + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); + } + if (shape.anchor.isVerticallyFlipped()) { + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); + } + } + + public Iterator iterator() { + return _shapes.iterator(); + } + + protected HSSFSheet getSheet() { + return _sheet; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 6bc713366d..7d8618ba7b 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -34,7 +34,7 @@ import org.apache.poi.hssf.model.InternalWorkbook; * @author Glen Stampoultzis * @author Yegor Kozlov (yegor at apache.org) */ -public final class HSSFPicture extends HSSFSimpleShape implements Picture { +public class HSSFPicture extends HSSFSimpleShape implements Picture { public static final int PICTURE_TYPE_EMF = HSSFWorkbook.PICTURE_TYPE_EMF; // Windows Enhanced Metafile public static final int PICTURE_TYPE_WMF = HSSFWorkbook.PICTURE_TYPE_WMF; // Windows Metafile public static final int PICTURE_TYPE_PICT = HSSFWorkbook.PICTURE_TYPE_PICT; // Macintosh PICT @@ -203,7 +203,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { private float getColumnWidthInPixels(int column){ - int cw = _patriarch._sheet.getColumnWidth(column); + int cw = _patriarch.getSheet().getColumnWidth(column); float px = getPixelWidth(column); return cw/px; @@ -211,18 +211,18 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { private float getRowHeightInPixels(int i){ - HSSFRow row = _patriarch._sheet.getRow(i); + HSSFRow row = _patriarch.getSheet().getRow(i); float height; if(row != null) height = row.getHeight(); - else height = _patriarch._sheet.getDefaultRowHeight(); + else height = _patriarch.getSheet().getDefaultRowHeight(); return height/PX_ROW; } private float getPixelWidth(int column){ - int def = _patriarch._sheet.getDefaultColumnWidth()*256; - int cw = _patriarch._sheet.getColumnWidth(column); + int def = _patriarch.getSheet().getDefaultColumnWidth()*256; + int cw = _patriarch.getSheet().getColumnWidth(column); return cw == def ? PX_DEFAULT : PX_MODIFIED; } @@ -233,7 +233,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { * @return image dimension */ public Dimension getImageDimension(){ - EscherBSERecord bse = _patriarch._sheet._book.getBSERecord(getPictureIndex()); + EscherBSERecord bse = _patriarch.getSheet()._book.getBSERecord(getPictureIndex()); byte[] data = bse.getBlipRecord().getPicturedata(); int type = bse.getBlipTypeWin32(); return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type); @@ -245,7 +245,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { * @return picture data for this shape */ public HSSFPictureData getPictureData(){ - InternalWorkbook iwb = _patriarch._sheet.getWorkbook().getWorkbook(); + InternalWorkbook iwb = _patriarch.getSheet().getWorkbook().getWorkbook(); EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord(); return new HSSFPictureData(blipRecord); } @@ -255,14 +255,14 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { EscherAggregate agg = patriarch._getBoundAggregate(); agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); EscherBSERecord bse = - patriarch._sheet.getWorkbook().getWorkbook().getBSERecord(getPictureIndex()); + patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(getPictureIndex()); bse.setRef(bse.getRef() + 1); } /** * The color applied to the lines of this shape. */ - public String getAdditionalData() { + public String getFileName() { EscherComplexProperty propFile = (EscherComplexProperty) getOptRecord().lookup( EscherProperties.BLIP__BLIPFILENAME); try { @@ -275,7 +275,7 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { } } - public void setAdditionalData(String data){ + public void setFileName(String data){ try { EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, true, data.getBytes("UTF-16LE")); setPropertyValue(prop); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index 137ead3c75..ba7a866706 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -20,7 +20,10 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.util.LittleEndian; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.Iterator; /** @@ -100,7 +103,7 @@ public abstract class HSSFShape { EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); spRecord.setShapeId(shapeId); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); - cod.setObjectId((short) (shapeId-1024)); + cod.setObjectId((short) (shapeId%1024)); } int getShapeId(){ @@ -295,6 +298,53 @@ public abstract class HSSFShape { protected void setPropertyValue(EscherProperty property){ _optRecord.setEscherProperty(property); } + + public void setFlipVertical(boolean value){ + EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + if (value){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); + } else { + sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPVERT)); + } + } + + public void setFlipHorizontal(boolean value){ + EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + if (value){ + sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); + } else { + sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPHORIZ)); + } + } + + public boolean isFlipVertical(){ + EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + return (sp.getFlags() & EscherSpRecord.FLAG_FLIPVERT) != 0; + } + + public boolean isFlipHorizontal(){ + EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + return (sp.getFlags() & EscherSpRecord.FLAG_FLIPHORIZ) != 0; + } + + public int getRotationDegree(){ + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TRANSFORM__ROTATION); + if (null == property){ + return 0; + } + try { + LittleEndian.putInt(property.getPropertyValue(), bos); + return LittleEndian.getShort(bos.toByteArray(), 2); + } catch (IOException e) { + e.printStackTrace(); + return 0; + } + } + + public void setRotationDegree(short value){ + setPropertyValue(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION , (value << 16))); + } /** * Count of all children and their children's children. diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java index 181b3d17a9..1d7748edc3 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java @@ -24,12 +24,12 @@ import java.util.List; * * @author Glen Stampoultzis (glens at apache.org) */ -public interface HSSFShapeContainer +public interface HSSFShapeContainer extends Iterable { /** * @return Any children contained by this shape. */ - List getChildren(); + List getChildren(); /** * add shape to the list of child records @@ -42,4 +42,13 @@ public interface HSSFShapeContainer */ void setCoordinates( int x1, int y1, int x2, int y2 ); + void clear(); + + public int getX1(); + + public int getY1(); + + public int getX2(); + + public int getY2(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 7cf6803fd0..1c8ac95dfa 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -18,10 +18,10 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; -import org.apache.poi.hssf.model.TextboxShape; import org.apache.poi.hssf.record.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Iterator; @@ -32,7 +32,7 @@ import java.util.Iterator; * @author Glen Stampoultzis (glens at apache.org) */ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { - List shapes = new ArrayList(); + private final List shapes = new ArrayList(); private EscherSpgrRecord _spgrRecord; public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) { @@ -172,11 +172,6 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { shapes.add(shape); } - public void addTextBox(TextboxShape textboxShape) { -// HSSFTextbox shape = new HSSFTextbox(this, textboxShape.geanchor); -// shapes.add(textboxShape); - } - /** * Create a new simple shape under this group. * @@ -258,7 +253,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { * Return all children contained by this shape. */ public List getChildren() { - return shapes; + return Collections.unmodifiableList(shapes); } /** @@ -272,6 +267,13 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { _spgrRecord.setRectY2(y2); } + public void clear() { + ArrayList copy = new ArrayList(shapes); + for (HSSFShape shape: copy){ + removeShape(shape); + } + } + /** * The top left x coordinate of this group. */ @@ -377,4 +379,8 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { } return isRemoved; } + + public Iterator iterator() { + return shapes.iterator(); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 258ee011a6..77d23f3f1d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -177,6 +177,9 @@ public class HSSFSimpleShape extends HSSFShape // If font is not set we must set the default one if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); _textObjectRecord.setStr(rtr); + if (string.getString() != null){ + setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__TEXTID, string.getString().hashCode())); + } } @Override diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 872a195228..9f859ee3ac 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -129,14 +129,6 @@ public class HSSFTextbox extends HSSFSimpleShape { return spContainer; } - @Override - public void setString(RichTextString string) { - HSSFRichTextString rtr = (HSSFRichTextString) string; - // If font is not set we must set the default one - if (rtr.numFormattingRuns() == 0) rtr.applyFont((short) 0); - getTextObjectRecord().setStr(rtr); - } - @Override void afterInsert(HSSFPatriarch patriarch) { EscherAggregate agg = patriarch._getBoundAggregate(); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index e31a6ecbf8..23dc0526cd 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -136,6 +136,8 @@ public class TestDrawingShapes extends TestCase { rectangle.setNoFill(true); rectangle.setString(new HSSFRichTextString("teeeest")); assertEquals(rectangle.getLineStyleColor(), 1111); + assertEquals(((EscherSimpleProperty)((EscherOptRecord)rectangle.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID)) + .lookup(EscherProperties.TEXT__TEXTID)).getPropertyValue(), "teeeest".hashCode()); assertEquals(rectangle.isNoFill(), true); assertEquals(rectangle.getString().getString(), "teeeest"); @@ -225,6 +227,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(HexDump.toHex(shape.getFillColor()), shape.getFillColor(), 0x2CE03D); assertEquals(shape.getLineWidth(), HSSFShape.LINEWIDTH_ONE_PT * 2); assertEquals(shape.getString().getString(), "POItest"); + assertEquals(shape.getRotationDegree(), 27); } public void testShapeIds() { @@ -536,4 +539,115 @@ public class TestDrawingShapes extends TestCase { assertEquals(HSSFTestHelper.getEscherAggregate(patriarch).getTailRecords().size(), 0); assertEquals(patriarch.getChildren().size(), 0); } + + public void testShapeFlip(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor()); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + assertEquals(rectangle.isFlipVertical(), false); + assertEquals(rectangle.isFlipHorizontal(), false); + + rectangle.setFlipVertical(true); + assertEquals(rectangle.isFlipVertical(), true); + rectangle.setFlipHorizontal(true); + assertEquals(rectangle.isFlipHorizontal(), true); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0); + + assertEquals(rectangle.isFlipHorizontal(), true); + rectangle.setFlipHorizontal(false); + assertEquals(rectangle.isFlipHorizontal(), false); + + assertEquals(rectangle.isFlipVertical(), true); + rectangle.setFlipVertical(false); + assertEquals(rectangle.isFlipVertical(), false); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0); + + assertEquals(rectangle.isFlipVertical(), false); + assertEquals(rectangle.isFlipHorizontal(), false); + } + + public void testRotation() { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + HSSFSimpleShape rectangle = patriarch.createSimpleShape(new HSSFClientAnchor(0,0,100,100, (short) 0,0,(short)5,5)); + rectangle.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE); + + assertEquals(rectangle.getRotationDegree(), 0); + rectangle.setRotationDegree((short) 45); + assertEquals(rectangle.getRotationDegree(), 45); + rectangle.setFlipHorizontal(true); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + rectangle = (HSSFSimpleShape) patriarch.getChildren().get(0); + assertEquals(rectangle.getRotationDegree(), 45); + rectangle.setRotationDegree((short) 30); + assertEquals(rectangle.getRotationDegree(), 30); + + patriarch.setCoordinates(0, 0, 10, 10); + rectangle.setString(new HSSFRichTextString("1234")); + } + + public void testShapeContainerImplementsIterable(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + patriarch.createSimpleShape(new HSSFClientAnchor()); + patriarch.createSimpleShape(new HSSFClientAnchor()); + + int i=2; + + for (HSSFShape shape: patriarch){ + i--; + } + assertEquals(i, 0); + } + + public void testClearShapesForPatriarch(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + + patriarch.createSimpleShape(new HSSFClientAnchor()); + patriarch.createSimpleShape(new HSSFClientAnchor()); + patriarch.createCellComment(new HSSFClientAnchor()); + + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); + + assertEquals(agg.getShapeToObjMapping().size(), 6); + assertEquals(agg.getTailRecords().size(), 1); + assertEquals(patriarch.getChildren().size(), 3); + + patriarch.clear(); + + assertEquals(agg.getShapeToObjMapping().size(), 0); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(patriarch.getChildren().size(), 0); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + assertEquals(agg.getShapeToObjMapping().size(), 0); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(patriarch.getChildren().size(), 0); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java index 234cddccfd..dcc611c05a 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java @@ -184,7 +184,7 @@ public final class TestHSSFPicture extends BaseTestPicture { assertEquals(1, drawing.getChildren().size()); HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); - assertEquals(picture.getAdditionalData(), "test"); + assertEquals(picture.getFileName(), "test"); } public void testSetGetProperties(){ @@ -199,15 +199,15 @@ public final class TestHSSFPicture extends BaseTestPicture { int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); HSSFPicture p1 = dr.createPicture(anchor, idx1); - assertEquals(p1.getAdditionalData(), ""); - p1.setAdditionalData("aaa"); - assertEquals(p1.getAdditionalData(), "aaa"); + assertEquals(p1.getFileName(), ""); + p1.setFileName("aaa"); + assertEquals(p1.getFileName(), "aaa"); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sh = wb.getSheet("Pictures"); dr = sh.getDrawingPatriarch(); p1 = (HSSFPicture) dr.getChildren().get(0); - assertEquals(p1.getAdditionalData(), "aaa"); + assertEquals(p1.getFileName(), "aaa"); } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java index f0ce3f2801..d5ea732d02 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java @@ -4,6 +4,7 @@ import junit.framework.TestCase; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherSpgrRecord; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; import java.lang.reflect.Field; @@ -226,4 +227,36 @@ public class TestShapeGroup extends TestCase{ } return null; } + + public void testClearShapes(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + HSSFShapeGroup group = patriarch.createGroup(new HSSFClientAnchor()); + + group.createShape(new HSSFChildAnchor()); + group.createShape(new HSSFChildAnchor()); + + EscherAggregate agg = HSSFTestHelper.getEscherAggregate(patriarch); + + assertEquals(agg.getShapeToObjMapping().size(), 5); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(group.getChildren().size(), 2); + + group.clear(); + + assertEquals(agg.getShapeToObjMapping().size(), 1); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(group.getChildren().size(), 0); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sheet = wb.getSheetAt(0); + patriarch = sheet.getDrawingPatriarch(); + + group = (HSSFShapeGroup) patriarch.getChildren().get(0); + + assertEquals(agg.getShapeToObjMapping().size(), 1); + assertEquals(agg.getTailRecords().size(), 0); + assertEquals(group.getChildren().size(), 0); + } } diff --git a/test-data/spreadsheet/drawings.xls b/test-data/spreadsheet/drawings.xls index 45b9a958870d9362f8ade14e7b93e6b5d7159207..69fb3af3d19fc51bb60124e10e377bb3de9676f7 100644 GIT binary patch delta 2601 zcmZ`*3sjRw7M?!|NeqJ^AfSK*?TqbR8ZEa zqlgk-E^ma0Da2io2rUhfhxp{F<$x#(l`2vn?ED0+yXS0jzRdi0?w#+O`_J5rP-rg{ z+FyyJ(HnFQ=vRk};%G+*ebE#xVlF3Q6U{VSNvK*$oLZX$bLHz96IHaHzFHz&%O?mR z8FS3z2>8Ab06+&}anXq}@rQvHSdvCsm>_0PNJ3&958EIhj*&JRNZ=(WkUsNIt9(MD zqoR2H1ni>;+!1MGfSBmW{bA93(j+UGHL0c|BjYctB6(54ywFgdNR#hRA*@Av`3t$a zIGln}fI-EWi$TLs$56u{$LJVyFc=ujA8Yw(wR{4DfIGLqlRY)J0ihxK*PN%bO+uZ~-OqbJ8&}TuWiK-kh-Jo^45;W3k`s zeoya43hZqD4`G%Rqid$;$dMY4BM#O}x2+EQI5hM?+i zS{ihD!!rA@!{_7qR()=EX;IN#=hT01^-11V;`?HIowk31wwNAJ4|e1rp5DpEtt^?XK>9+&bP+KZu`32`a_z8epbx- zkQYA*T2s50-M1+^z2o0C`KQK$UT_Cr#c}Ue2v;jgEPemcnXcWk*Lv$j;zaC3(bU}@ zzLP_LcK6WmQ2c~!s_#A9RO3(1E#Zo!2RG(r%6GSvb|ron@Fu-6BU?sq zf-Z^s84Le|OBQNq28T-%z0w}X8Z;GWSj2pDs=!%r$n`|9SKI?F*BII2@%otOu7>YU zmA!B<+v4TWRkvy+%4{dSx(zIMb?=Wc7JiShX zuM=k#dhwOuT$<^}MZwKE8_u0iIjmN0`Rg^q!;!M)BvznX$o(vdcDN zHM8v+tGxxuxl7Lu2Rv$*4V4cB295q%retq2$%vWK)u!duXnRTRqAG+ZT8=-xx_`lP zldTgqhlU<4sJrp?v}cCZ*n-}cGd;%pcX}3?lx7G^uUbtW*eQB@ufevuY`AnsL1Dz( zwCdWZ-0-E%EWTFjylI0Xd+9=6LofG@c8Sy?Ht2Yi&v#qqwfZ*Rf{Pvnn*U+#ZT~<` zu8$P|D)UZ`bshkR4vzd3wQ8M!S697eQF+8({bnAQm%a0kjz2&2HQoIXp0g{;xPDN! zKf2-BrOiG!6SFyrD+!ezlO};-6Lm__!R2~tPCxgbHbKsp;Zgw%-O3cxL*VY9ClUT@ zuU)xTSP}U?Wo)-r-}f)4o~}!Btnl?b(OKUZPVe0W+@E!&yN($ghzc}WbZ|{u?Lbk- zshgf(o!i8ZZg$kW+^OKC@vliC1?r2))Dl2Gw#ghAa z%Gm~6n$$C$2j8>x1$7%HpPMuV@%2nvCi^B+3QD_mx~DvDn73v0_TQCQu>}+(%N0DRIam7&0#Za^;@Xhb5EOk` z44h@q-e@LIxL_a*OA*T)4+TS(DI>BJ@Ln&tU`lx)cVm@^LjL%btTRTHgg?qz7c1g=!OfTtkP+^dj_evm*X zcmcbSI)W0aspw}3bR}}mDxd>$z6u>-&g`JeK0KIq6`B!wNUXqQ#j&$w2$NY#jccKt z4)e&>;sLSkCq{$oP}_(UO~JKTj%%?WX8Kfx!S|{;Jfs=dVI>{rlVsS&HvbeJC&%Fz z|4(>3UYiuJ_ca|}#F6A9+eQ@`NL<2eh=rGC<%<)s{2vrpey&Qsb>e@?*J*{#beN01 z$$w z&>J`9Jx~cXW|akTFxTW1w4?-a(9L0}O9|#6c`x*%=p0uCZ+r(mkZC{EBUornKlC~^z3^b)uNrA|U0in8!CsR!zQ3-wqGwrV2}0@X&goWdKKft;pb1!T~?;TXP+lQTM zXsT-h>7a#kS%7oti0wD+uqSI=*xP;EaC=r1u{BJ2WgVB=0%+j8ee#G!y^M z!QVx|fV}Rka;H*&-3Nk71B4-M4Q)Nml?Kuo8i*)?`jm#nGYgpCxY(FHzXpJun!u5` RN08^-MC48%x%?4Q{sV`#yL12m delta 2479 zcmYjT3p`ZWAHVm`orjsjOiW9e)~HF;dTsQ!4eeixw!G2 zC9yk6OOK)P-zJU5MxjJo5upeFN>Xj9tlD!M?f%dGeCOW#JKx{yoH@VWmCK#va;H;U zNXGE8BUYqDv5ic{EfsIcC?jFb=R#7_g6r?9ZS-r-tfM@{X~Agu$avo;&yBcM>2rDN~dHb78f2LM{x`e={Xys zw{8uW#vu+Dn+GWw6N`!7k`NIsr9>x7$3=QmlxBoduNl5IG(0RUT)~yDA!s5+q;#_5 z1f)(N>_ea-a1clY76KiCnq!QENy(C`rD@et9DzWfA&>}k1O@^VfrVgzz((MxtEIrh zQK)2bF=AMWtnx6{FlC%F%tH@cj5hou3mzB*v!F*Y;LHd>LSu~mkwg(NHiorhoM9xWBIVP9hayWg zqryq>yx~~deIGv8&RjCPr*6`Gaah`tp}JJdhS(#e_peV2Te{>iv&^jZIq9~m%te+b z)fDu5DwE?=E5ONm=IV2T(1ea=|E0a%+mxE}Z#=$UPjm zUXS!gjjG2w-oJ3W$Cc#MY6m6HB5ur?`)$C_<>&g_W>lS3=3=!@IpL2g#6j2N<9JEh zn>LeD8YKK_rUlwQjbO~ON-8k1PcxKBcx1Oxk7Hd$R$ITbB2e|h!N-%|lokFBjIOTp z?Q#_s=4obLoq2Va551!QmPw^%`a_%f`L*m4gCYwd)2#kM=!_7T?YlEa8%uezY|9Pb zD*f#RIwHVt^RHP!aSLKQwHe1+3T8LF+3TA0lox+yxmYXQ)3{T&oIB^n{{Hzg6RWsN zx^4b6vn02@?*;Rs9WLHfaD>Uto}0R_*6bj^6D=(n=%3utXX!M{i+Ag)HtEB}OMAHc zUO(_1G}2Ti`)5z+ZOt8eV06+nUBM`?|7G2k(5yq1eHM)0&o1yuT_Nfc=1&`X>)|2g zx5>|ywoG@6=7cJo?`(8+ckpnzGO%*E%1Go|>f{qL!0%aY^}5ooFKaBB)@o2-W%ZxK z7aW(F3%Hl|ccwb}G?$f_E~$D~vn%$M!{mt7x6*3g?7SFts*|Z$6?0g5!+Xo&r`L7I zZgvK3Rml{%a3X!0-P%_|xJ(IV$uezxS;mI-)(ie{z5DoPVsdqGC;QHY5h%J^ zFAh|-%K|k15mVeUvM-*~E|oMDu3)d7;nIWGJt}Hn4^RCHa@c>@09M`=;3W9CQm9Hm z1TLy0|BMB6=zRrP;%P9W3^)QFHX#HR7+P;6lYkXhfEny916EY=LxmQD#ofRZ_H+UZ zK-EPY6>5Mn7;wdLu!M*UQ1^`h1`Z3#!Dq2lzO%ivf!FeNd7%w4YntJN_lKmrrU zkQ+)Sj?%mN0$QrTmvlKQ)i~re0Y{jw0$%|+MMEP*dJKo{D&U6ifuIREL$4~Z2<#c3 zm4AcD4qu1i5%^y?x0*W-i7zLQ4Ly>v2^pSlD z@9F?wov#6v43LIYsEOjg!}~#pRQBpstQq4fYNVoLfW3%K$+TPa$*jYZs3>DW(s+Q{ ztthJWCKO=urvOdJRwKQY)oP1oaESqu5t)(|+YtnO-UhzHQ=mgTFr#rlc}r{ulbIle z@`hw`YKIVSCR{%P?BSoCz=yEk2hkR2A-4+z;cU323+(_K)^vduz#fl9OszsrH?Sha zO|Y*M@Cmmjc&!@*5X=m{@|scL4sCnDXKW^4-=a9}GCM&_aX+p$>cu3~|CUU+;D1 zAPSid(*}W;fG$9Ljym6V9CbeQkNwp7ygA6{&>&dI26W0NdKEV4H}&Hx$niRL?+BQJ z<0O3l2IWpd&$plgkmI=*H-5^!xKW>bNh5T9hjLFi_D}A@Ms!4oVJ(V5{(t?N5a}1A z4Ab}P$D@E_8-qw^NPWMi2s{+E0`==TNPYo*N3bx`6(xXiaO&_`{|VOk_fCnV+CMr@ z1iDxV2I%@6Gee&o^57#lfu$a&(MSw8C+Cr_q#KFtV;WKl*i*#8uu0E(=$A4|4azAY Vg1qDC$hf})w$OA8^eEp0;xAD2gZcmf From f1ecf76191727bcefd32557be05600474fa45d68 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Tue, 24 Jul 2012 19:42:28 +0000 Subject: [PATCH 23/32] fixed cloning of sheets with charts git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1365255 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/poi/hssf/model/InternalSheet.java | 7 +------ src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java | 8 ++++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index ce8e5a9bb3..5e5d601996 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -351,12 +351,7 @@ public final class InternalSheet { continue; } if (rb instanceof EscherAggregate){ - // EscherAggregate is used only as a container for SODRAWING and OBJ record combinations - // So, if the container is empty, there is no reason to clone this record - // See https://issues.apache.org/bugzilla/show_bug.cgi?id=49529 -// if (0 == rb.getRecordSize()){ - continue; -// } + rb = new DrawingRecord(); } Record rec = (Record) ((Record) rb).clone(); clonedRecords.add(rec); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index afe4cf99d8..ebbd95cc28 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -117,10 +117,14 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { HSSFSheet cloneSheet(HSSFWorkbook workbook) { this.getDrawingPatriarch();/**Aggregate drawing records**/ HSSFSheet sheet = new HSSFSheet(workbook, _sheet.cloneSheet()); + int pos = sheet._sheet.findFirstRecordLocBySid(DrawingRecord.sid); + DrawingRecord dr = (DrawingRecord) sheet._sheet.findFirstRecordBySid(DrawingRecord.sid); + if (null != dr){ + sheet._sheet.getRecords().remove(dr); + } if (getDrawingPatriarch() != null){ - int insertPos = sheet._sheet.findFirstRecordLocBySid(WindowTwoRecord.sid); HSSFPatriarch patr = HSSFPatriarch.createPatriarch(this.getDrawingPatriarch(), sheet); - sheet._sheet.getRecords().add(insertPos, patr._getBoundAggregate()); + sheet._sheet.getRecords().add(pos, patr._getBoundAggregate()); sheet._patriarch = patr; } return sheet; From 61cb6a93c53224c57cbeb5a0dbd46e5fca62b5c1 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Sat, 28 Jul 2012 10:21:40 +0000 Subject: [PATCH 24/32] added features: -background image for comment -wrapText for HSSFSimpleShape -few other improvements git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1366636 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ddf/AbstractEscherOptRecord.java | 9 +++++ .../apache/poi/ddf/EscherBoolProperty.java | 2 +- .../poi/hssf/usermodel/HSSFComment.java | 37 ++++++++++++++++--- .../poi/hssf/usermodel/HSSFObjectData.java | 2 +- .../poi/hssf/usermodel/HSSFPicture.java | 6 +-- .../apache/poi/hssf/usermodel/HSSFShape.java | 17 ++------- .../poi/hssf/usermodel/HSSFShapeGroup.java | 2 +- .../poi/hssf/usermodel/HSSFSimpleShape.java | 19 +++++++++- .../poi/hssf/usermodel/HSSFTextbox.java | 2 +- .../poi/hssf/usermodel/HSSFUnknownShape.java | 2 +- .../poi/hssf/model/TestDrawingShapes.java | 30 +++++++++------ .../apache/poi/hssf/model/TestHSSFAnchor.java | 20 +++++----- .../poi/hssf/usermodel/HSSFTestHelper.java | 14 +++++++ .../poi/hssf/usermodel/TestComment.java | 14 ++++++- 14 files changed, 123 insertions(+), 53 deletions(-) diff --git a/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java b/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java index dbf4a6dad2..b97eeafda2 100644 --- a/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java +++ b/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java @@ -154,6 +154,15 @@ public abstract class AbstractEscherOptRecord extends EscherRecord sortProperties(); } + public void removeEscherProperty(int num){ + for ( Iterator iterator = getEscherProperties().iterator(); iterator.hasNext(); ) { + EscherProperty prop = iterator.next(); + if (prop.getPropertyNumber() == num){ + iterator.remove(); + } + } + } + /** * Retrieve the string representation of this record. */ diff --git a/src/java/org/apache/poi/ddf/EscherBoolProperty.java b/src/java/org/apache/poi/ddf/EscherBoolProperty.java index da9499af38..3044395485 100644 --- a/src/java/org/apache/poi/ddf/EscherBoolProperty.java +++ b/src/java/org/apache/poi/ddf/EscherBoolProperty.java @@ -70,7 +70,7 @@ public class EscherBoolProperty public String toXml(String tab){ StringBuilder builder = new StringBuilder(); builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId())) - .append("\" name=\"").append(getName()).append("\" blipId=\"") + .append("\" name=\"").append(getName()).append("\" simpleValue=\"").append(getPropertyValue()).append("\" blipId=\"") .append(isBlipId()).append("\" value=\"").append(isTrue()).append("\"").append("/>\n"); return builder.toString(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 4922529e6d..6c1fecbc3b 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -19,7 +19,6 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.*; import org.apache.poi.ss.usermodel.Comment; -import org.apache.poi.ss.usermodel.RichTextString; /** * Represents a cell comment - a sticky note associated with a cell. @@ -28,6 +27,9 @@ import org.apache.poi.ss.usermodel.RichTextString; */ public class HSSFComment extends HSSFTextbox implements Comment { + private final static int FILL_TYPE_SOLID = 0; + private final static int FILL_TYPE_PICTURE = 3; + /* * TODO - make HSSFComment more consistent when created vs read from file. * Currently HSSFComment has two main forms (corresponding to the two constructors). There @@ -77,10 +79,11 @@ public class HSSFComment extends HSSFTextbox implements Comment { protected EscherContainerRecord createSpContainer() { EscherContainerRecord spContainer = super.createSpContainer(); EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID); - removeEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT); - removeEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT); - removeEscherProperty(opt, EscherProperties.TEXT__TEXTTOP); - removeEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); + opt.removeEscherProperty(EscherProperties.TEXT__TEXTLEFT); + opt.removeEscherProperty(EscherProperties.TEXT__TEXTRIGHT); + opt.removeEscherProperty(EscherProperties.TEXT__TEXTTOP); + opt.removeEscherProperty(EscherProperties.TEXT__TEXTBOTTOM); + opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, false, false, 655362)); return spContainer; } @@ -215,7 +218,7 @@ public class HSSFComment extends HSSFTextbox implements Comment { } @Override - public HSSFShape cloneShape() { + protected HSSFShape cloneShape() { TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise(); EscherContainerRecord spContainer = new EscherContainerRecord(); byte [] inSp = getEscherContainer().serialize(); @@ -224,4 +227,26 @@ public class HSSFComment extends HSSFTextbox implements Comment { NoteRecord note = (NoteRecord) getNoteRecord().cloneViaReserialise(); return new HSSFComment(spContainer, obj, txo, note); } + + public void setBackgroundImage(int pictureIndex){ + setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__PATTERNTEXTURE, false, true, pictureIndex)); + setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_PICTURE)); + EscherBSERecord bse = _patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(pictureIndex); + bse.setRef(bse.getRef() + 1); + } + + public void resetBackgroundImage(){ + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE); + if (null != property){ + EscherBSERecord bse = _patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(property.getPropertyValue()); + bse.setRef(bse.getRef() - 1); + getOptRecord().removeEscherProperty(EscherProperties.FILL__PATTERNTEXTURE); + } + setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_SOLID)); + } + + public int getBackgroundImageId(){ + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE); + return property == null ? 0 : property.getPropertyValue(); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java index dfe2b76a7e..57451dd817 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java @@ -136,7 +136,7 @@ public final class HSSFObjectData extends HSSFPicture { } @Override - public HSSFShape cloneShape() { + protected HSSFShape cloneShape() { EscherContainerRecord spContainer = new EscherContainerRecord(); byte[] inSp = getEscherContainer().serialize(); spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 7d8618ba7b..2fa906f467 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -87,8 +87,8 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { protected EscherContainerRecord createSpContainer() { EscherContainerRecord spContainer = super.createSpContainer(); EscherOptRecord opt = spContainer.getChildById(EscherOptRecord.RECORD_ID); - removeEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING); - removeEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH); + opt.removeEscherProperty(EscherProperties.LINESTYLE__LINEDASHING); + opt.removeEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH); spContainer.removeChildRecord(spContainer.getChildById(EscherTextboxRecord.RECORD_ID)); return spContainer; } @@ -290,7 +290,7 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { } @Override - public HSSFShape cloneShape() { + protected HSSFShape cloneShape() { EscherContainerRecord spContainer = new EscherContainerRecord(); byte [] inSp = getEscherContainer().serialize(); spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index ba7a866706..dd8a586f73 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -90,15 +90,6 @@ public abstract class HSSFShape { protected abstract void afterRemove(HSSFPatriarch patriarch); - protected void removeEscherProperty(EscherOptRecord opt, int num){ - for ( Iterator iterator = opt.getEscherProperties().iterator(); iterator.hasNext(); ) { - EscherProperty prop = iterator.next(); - if (prop.getPropertyNumber() == num){ - iterator.remove(); - } - } - } - void setShapeId(int shapeId){ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); spRecord.setShapeId(shapeId); @@ -112,15 +103,15 @@ public abstract class HSSFShape { abstract void afterInsert(HSSFPatriarch patriarch); - public EscherContainerRecord getEscherContainer() { + protected EscherContainerRecord getEscherContainer() { return _escherContainer; } - public ObjRecord getObjRecord() { + protected ObjRecord getObjRecord() { return _objRecord; } - public EscherOptRecord getOptRecord() { + protected EscherOptRecord getOptRecord() { return _optRecord; } @@ -353,5 +344,5 @@ public abstract class HSSFShape { return 1; } - public abstract HSSFShape cloneShape(); + protected abstract HSSFShape cloneShape(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 1c8ac95dfa..f08625a010 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -337,7 +337,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { } @Override - public HSSFShape cloneShape() { + protected HSSFShape cloneShape() { throw new IllegalStateException("Use method cloneShape(HSSFPatriarch patriarch)"); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 77d23f3f1d..661c1d998c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -57,6 +57,10 @@ public class HSSFSimpleShape extends HSSFShape public final static short OBJECT_TYPE_COMMENT = 25; // public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; + public final static int WRAP_SQUARE = 0; + public final static int WRAP_BY_POINTS = 1; + public final static int WRAP_NONE = 2; + private static final Map objTypeToShapeType = new HashMap(); private TextObjectRecord _textObjectRecord; @@ -83,12 +87,14 @@ public class HSSFSimpleShape extends HSSFShape _textObjectRecord = createTextObjRecord(); } - public TextObjectRecord getTextObjectRecord() { + protected TextObjectRecord getTextObjectRecord() { return _textObjectRecord; } protected TextObjectRecord createTextObjRecord(){ TextObjectRecord obj = new TextObjectRecord(); + obj.setHorizontalTextAlignment(2); + obj.setVerticalTextAlignment(2); obj.setTextLocked(true); obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE); obj.setStr(new HSSFRichTextString("")); @@ -194,7 +200,7 @@ public class HSSFSimpleShape extends HSSFShape } @Override - public HSSFShape cloneShape() { + protected HSSFShape cloneShape() { TextObjectRecord txo = null; EscherContainerRecord spContainer = new EscherContainerRecord(); byte [] inSp = getEscherContainer().serialize(); @@ -243,4 +249,13 @@ public class HSSFSimpleShape extends HSSFShape } spRecord.setShapeType(objTypeToShapeType.get((short) shapeType)); } + + public int getWrapText(){ + EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TEXT__WRAPTEXT); + return null == property ? WRAP_SQUARE : property.getPropertyValue(); + } + + public void setWrapText(int value){ + setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, false, false, value)); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java index 9f859ee3ac..4260ead638 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFTextbox.java @@ -230,7 +230,7 @@ public class HSSFTextbox extends HSSFSimpleShape { } @Override - public HSSFShape cloneShape() { + protected HSSFShape cloneShape() { TextObjectRecord txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise(); EscherContainerRecord spContainer = new EscherContainerRecord(); byte[] inSp = getEscherContainer().serialize(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java index 75d33c6c65..e28d3f8cc1 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java @@ -50,7 +50,7 @@ public class HSSFUnknownShape extends HSSFShape { } @Override - public HSSFShape cloneShape() { + protected HSSFShape cloneShape() { return null; } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 23dc0526cd..512ad2371e 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -120,7 +120,7 @@ public class TestDrawingShapes extends TestCase { HSSFSheet sheet = wb.createSheet(); HSSFPatriarch drawing = sheet.createDrawingPatriarch(); - HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 200, 200, (short) 2, 2, (short) 15, 15); + HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 50, 50, (short) 2, 2, (short) 4, 4); anchor.setAnchorType(2); assertEquals(anchor.getAnchorType(), 2); @@ -132,13 +132,16 @@ public class TestDrawingShapes extends TestCase { assertEquals(10000, rectangle.getLineWidth()); rectangle.setLineStyle(10); assertEquals(10, rectangle.getLineStyle()); + assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_SQUARE); rectangle.setLineStyleColor(1111); rectangle.setNoFill(true); + rectangle.setWrapText(HSSFSimpleShape.WRAP_NONE); rectangle.setString(new HSSFRichTextString("teeeest")); assertEquals(rectangle.getLineStyleColor(), 1111); - assertEquals(((EscherSimpleProperty)((EscherOptRecord)rectangle.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID)) + assertEquals(((EscherSimpleProperty)((EscherOptRecord)HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherOptRecord.RECORD_ID)) .lookup(EscherProperties.TEXT__TEXTID)).getPropertyValue(), "teeeest".hashCode()); assertEquals(rectangle.isNoFill(), true); + assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_NONE); assertEquals(rectangle.getString().getString(), "teeeest"); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); @@ -157,6 +160,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(rectangle2.getFillColor(), 777); assertEquals(rectangle2.isNoFill(), true); assertEquals(rectangle2.getString().getString(), "teeeest"); + assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_NONE); rectangle2.setFillColor(3333); rectangle2.setLineStyle(9); @@ -167,6 +171,7 @@ public class TestDrawingShapes extends TestCase { rectangle2.getAnchor().setDx2(3); rectangle2.getAnchor().setDy1(4); rectangle2.getAnchor().setDy2(5); + rectangle.setWrapText(HSSFSimpleShape.WRAP_BY_POINTS); rectangle2.setString(new HSSFRichTextString("test22")); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); @@ -175,6 +180,7 @@ public class TestDrawingShapes extends TestCase { assertEquals(1, drawing.getChildren().size()); rectangle2 = (HSSFSimpleShape) drawing.getChildren().get(0); assertEquals(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE, rectangle2.getShapeType()); + assertEquals(rectangle.getWrapText(), HSSFSimpleShape.WRAP_BY_POINTS); assertEquals(77, rectangle2.getLineWidth()); assertEquals(9, rectangle2.getLineStyle()); assertEquals(rectangle2.getLineStyleColor(), 4444); @@ -313,7 +319,7 @@ public class TestDrawingShapes extends TestCase { HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor()); EscherOptRecord opt1 = HSSFTestHelper.getOptRecord(textbox); - EscherOptRecord opt2 = textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID); + EscherOptRecord opt2 = HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID); assertSame(opt1, opt2); } @@ -328,13 +334,13 @@ public class TestDrawingShapes extends TestCase { String opt1Str = opt.toXml(); textbox.setFillColor(textbox.getFillColor()); - assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); textbox.setLineStyle(textbox.getLineStyle()); - assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); textbox.setLineWidth(textbox.getLineWidth()); - assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); textbox.setLineStyleColor(textbox.getLineStyleColor()); - assertEquals(opt1Str, textbox.getEscherContainer().getChildById(EscherOptRecord.RECORD_ID).toXml()); + assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); } public void testDgRecordNumShapes(){ @@ -370,7 +376,7 @@ public class TestDrawingShapes extends TestCase { shape.setString(new HSSFRichTextString("string1")); assertEquals(shape.getString().getString(), "string1"); - assertNotNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertNotNull(HSSFTestHelper.getEscherContainer(shape).getChildById(EscherTextboxRecord.RECORD_ID)); assertEquals(agg.getShapeToObjMapping().size(), 2); wb = HSSFTestDataSamples.writeOutAndReadBack(wb); @@ -381,9 +387,9 @@ public class TestDrawingShapes extends TestCase { shape = (HSSFSimpleShape) patriarch.getChildren().get(0); - assertNotNull(shape.getTextObjectRecord()); + assertNotNull(HSSFTestHelper.getTextObjRecord(shape)); assertEquals(shape.getString().getString(), "string1"); - assertNotNull(shape.getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID)); + assertNotNull(HSSFTestHelper.getEscherContainer(shape).getChildById(EscherTextboxRecord.RECORD_ID)); assertEquals(agg.getShapeToObjMapping().size(), 2); } @@ -396,8 +402,8 @@ public class TestDrawingShapes extends TestCase { HSSFTestHelper.setShapeId(combobox, 1024); ComboboxShape comboboxShape = new ComboboxShape(combobox, 1024); - assertTrue(Arrays.equals(comboboxShape.getSpContainer().serialize(), combobox.getEscherContainer().serialize())); - assertTrue(Arrays.equals(comboboxShape.getObjRecord().serialize(), combobox.getObjRecord().serialize())); + assertTrue(Arrays.equals(comboboxShape.getSpContainer().serialize(), HSSFTestHelper.getEscherContainer(combobox).serialize())); + assertTrue(Arrays.equals(comboboxShape.getObjRecord().serialize(), HSSFTestHelper.getObjRecord(combobox).serialize())); } public void testRemoveShapes(){ diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index 7d42b46375..08da761936 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -55,17 +55,17 @@ public class TestHSSFAnchor extends TestCase { HSSFSimpleShape rectangle = (HSSFSimpleShape) drawing.getChildren().get(0); - assertEquals(rectangle.getEscherContainer().getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); - assertEquals(rectangle.getEscherContainer().getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); - assertEquals(rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); - assertEquals(rectangle.getEscherContainer().getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); rectangle.setAnchor(new HSSFClientAnchor()); - assertEquals(rectangle.getEscherContainer().getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); - assertEquals(rectangle.getEscherContainer().getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); - assertEquals(" " + HexDump.toHex(rectangle.getEscherContainer().getChild(2).getRecordId()) + " ", rectangle.getEscherContainer().getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); - assertEquals(rectangle.getEscherContainer().getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(0).getRecordId(), EscherSpRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(1).getRecordId(), EscherOptRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(2).getRecordId(), EscherClientAnchorRecord.RECORD_ID); + assertEquals(HSSFTestHelper.getEscherContainer(rectangle).getChild(3).getRecordId(), EscherClientDataRecord.RECORD_ID); } public void testCreateClientAnchorFromContainer(){ @@ -135,8 +135,8 @@ public class TestHSSFAnchor extends TestCase { rectangle.setAnchor(anchor); assertNotNull(anchor.getEscherAnchor()); - assertNotNull(rectangle.getEscherContainer()); - assertTrue(anchor.getEscherAnchor().equals(rectangle.getEscherContainer().getChildById(EscherClientAnchorRecord.RECORD_ID))); + assertNotNull(HSSFTestHelper.getEscherContainer(rectangle)); + assertTrue(anchor.getEscherAnchor().equals(HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherClientAnchorRecord.RECORD_ID))); } public void testClientAnchorFromEscher(){ diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 465f7746b0..3954688912 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -21,6 +21,8 @@ import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.TextObjectRecord; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -104,4 +106,16 @@ public class HSSFTestHelper { public static void setShapeId(HSSFShape shape, int id){ shape.setShapeId(id); } + + public static EscherContainerRecord getEscherContainer(HSSFShape shape){ + return shape.getEscherContainer(); + } + + public static TextObjectRecord getTextObjRecord(HSSFSimpleShape shape){ + return shape.getTextObjectRecord(); + } + + public static ObjRecord getObjRecord(HSSFShape shape){ + return shape.getObjRecord(); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java index cbf49bb5e3..1f8c069351 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -7,7 +7,7 @@ import org.apache.poi.hssf.model.CommentShape; import org.apache.poi.hssf.model.HSSFTestModelHelper; import org.apache.poi.hssf.record.*; -import java.io.IOException; +import java.io.*; import java.util.Arrays; /** @@ -91,11 +91,14 @@ public class TestComment extends TestCase { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + int idx = wb.addPicture(new byte[]{1,2,3}, HSSFWorkbook.PICTURE_TYPE_PNG); HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); comment.setString(new HSSFRichTextString("comment1")); - comment = patriarch.createCellComment(new HSSFClientAnchor()); + comment = patriarch.createCellComment(new HSSFClientAnchor(0,0,100,100,(short)0,0,(short)10,10)); comment.setString(new HSSFRichTextString("comment2")); + comment.setBackgroundImage(idx); + assertEquals(comment.getBackgroundImageId(), idx); assertEquals(patriarch.getChildren().size(), 2); @@ -103,6 +106,11 @@ public class TestComment extends TestCase { sh = wb.getSheetAt(0); patriarch = sh.getDrawingPatriarch(); + comment = (HSSFComment) patriarch.getChildren().get(1); + assertEquals(comment.getBackgroundImageId(), idx); + comment.resetBackgroundImage(); + assertEquals(comment.getBackgroundImageId(), 0); + assertEquals(patriarch.getChildren().size(), 2); comment = patriarch.createCellComment(new HSSFClientAnchor()); comment.setString(new HSSFRichTextString("comment3")); @@ -111,6 +119,8 @@ public class TestComment extends TestCase { wb = HSSFTestDataSamples.writeOutAndReadBack(wb); sh = wb.getSheetAt(0); patriarch = sh.getDrawingPatriarch(); + comment = (HSSFComment) patriarch.getChildren().get(1); + assertEquals(comment.getBackgroundImageId(), 0); assertEquals(patriarch.getChildren().size(), 3); assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1"); assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2"); From c445756d0880312c943e0e4da26bf551993fa973 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Sat, 28 Jul 2012 16:01:24 +0000 Subject: [PATCH 25/32] fixed bug 51675, added test case for bug 52272 git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1366700 13f79535-47bb-0310-9956-ffa450edef68 --- .../record/aggregates/PageSettingsBlock.java | 2 +- .../apache/poi/hssf/usermodel/TestBugs.java | 30 ++++++++++++++++++ test-data/spreadsheet/51675.xls | Bin 0 -> 69120 bytes 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test-data/spreadsheet/51675.xls diff --git a/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java b/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java index 676a8f9831..5236e184b8 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java @@ -284,9 +284,9 @@ public final class PageSettingsBlock extends RecordAggregate { pls.visitContainedRecords(rv); } visitIfPresent(_printSetup, rv); - visitIfPresent(_bitmap, rv); visitIfPresent(_printSize, rv); visitIfPresent(_headerFooter, rv); + visitIfPresent(_bitmap, rv); } private static void visitIfPresent(Record r, RecordVisitor rv) { if (r != null) { diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java index 0864549f6c..69f0e3425b 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java @@ -24,9 +24,12 @@ import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.OldExcelFormatException; import org.apache.poi.hssf.extractor.ExcelExtractor; +import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; +import org.apache.poi.hssf.record.aggregates.PageSettingsBlock; +import org.apache.poi.hssf.record.aggregates.RecordAggregate; import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; @@ -2238,4 +2241,31 @@ if(1==2) { // make sure we are still readable writeOutAndReadBack(workbook); } + + public void test51675(){ + final List list = new ArrayList(); + HSSFWorkbook workbook = openSample("51675.xls"); + HSSFSheet sh = workbook.getSheetAt(0); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + PageSettingsBlock psb = (PageSettingsBlock) ish.getRecords().get(13); + psb.visitContainedRecords(new RecordAggregate.RecordVisitor() { + public void visitRecord(Record r) { + list.add(r.getSid()); + } + }); + assertTrue(list.get(list.size()-1).intValue() == UnknownRecord.BITMAP_00E9); + assertTrue(list.get(list.size()-2).intValue() == UnknownRecord.HEADER_FOOTER_089C); + } + + public void test52272(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + HSSFPatriarch p = sh.createDrawingPatriarch(); + + HSSFSimpleShape s = p.createSimpleShape(new HSSFClientAnchor()); + s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); + + HSSFSheet sh2 = wb.cloneSheet(0); + assertNotNull(sh2.getDrawingPatriarch()); + } } diff --git a/test-data/spreadsheet/51675.xls b/test-data/spreadsheet/51675.xls new file mode 100644 index 0000000000000000000000000000000000000000..78df32cb946142537d871f294050a12594d8cc32 GIT binary patch literal 69120 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 G|Nj6H!zv^I literal 0 HcmV?d00001 From 7305869f20f551d0c71309a465a7a914670b4842 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Mon, 30 Jul 2012 20:37:34 +0000 Subject: [PATCH 26/32] added feature for setting additional shape type git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1367279 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/usermodel/HSSFShapeFactory.java | 15 +- .../poi/hssf/usermodel/HSSFSimpleShape.java | 21 +- .../hssf/usermodel/drawing/HSSFShapeType.java | 1 + .../hssf/usermodel/drawing/ShapeTypes.java | 224 ++++++++++++++++++ 4 files changed, 246 insertions(+), 15 deletions(-) create mode 100644 src/java/org/apache/poi/hssf/usermodel/drawing/ShapeTypes.java diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 178bdf5fe9..42aef17569 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -23,7 +23,6 @@ import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; import org.apache.poi.poifs.filesystem.DirectoryNode; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -75,8 +74,8 @@ public class HSSFShapeFactory { public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { ObjRecord obj = null; - EscherClientDataRecord clientData = ((EscherContainerRecord)container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID); - if (null != clientData){ + EscherClientDataRecord clientData = ((EscherContainerRecord) container.getChild(0)).getChildById(EscherClientDataRecord.RECORD_ID); + if (null != clientData) { obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData); } HSSFShapeGroup group = new HSSFShapeGroup(container, obj); @@ -110,7 +109,7 @@ public class HSSFShapeFactory { break; } } - if (isEmbeddedObject(objRecord)){ + if (isEmbeddedObject(objRecord)) { HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root); out.addShape(objectData); return; @@ -136,7 +135,7 @@ public class HSSFShapeFactory { if (null != property) { shape = new HSSFPolygon(container, objRecord, txtRecord); } else { - shape = new HSSFSimpleShape(container, objRecord); + shape = new HSSFSimpleShape(container, objRecord, txtRecord); } break; case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT: @@ -146,11 +145,9 @@ public class HSSFShapeFactory { shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord)); break; default: - shape = new HSSFSimpleShape(container, objRecord); - } - if (null != shape) { - out.addShape(shape); + shape = new HSSFSimpleShape(container, objRecord, txtRecord); } + out.addShape(shape); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 661c1d998c..48cacfc3d7 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -38,7 +38,7 @@ public class HSSFSimpleShape extends HSSFShape public final static short OBJECT_TYPE_LINE = 1; public final static short OBJECT_TYPE_RECTANGLE = 2; public final static short OBJECT_TYPE_OVAL = 3; -// public final static short OBJECT_TYPE_ARC = 4; + public final static short OBJECT_TYPE_ARC = 4; // public final static short OBJECT_TYPE_CHART = 5; // public final static short OBJECT_TYPE_TEXT = 6; // public final static short OBJECT_TYPE_BUTTON = 7; @@ -55,7 +55,7 @@ public class HSSFSimpleShape extends HSSFShape // public final static short OBJECT_TYPE_GROUP_BOX = 19; public final static short OBJECT_TYPE_COMBO_BOX = 20; public final static short OBJECT_TYPE_COMMENT = 25; -// public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; + public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; public final static int WRAP_SQUARE = 0; public final static int WRAP_BY_POINTS = 1; @@ -70,6 +70,7 @@ public class HSSFSimpleShape extends HSSFShape objTypeToShapeType.put(OBJECT_TYPE_PICTURE, HSSFShapeType.PICTURE.getType()); objTypeToShapeType.put(OBJECT_TYPE_LINE, HSSFShapeType.LINE.getType()); objTypeToShapeType.put(OBJECT_TYPE_OVAL, HSSFShapeType.OVAL.getType()); + objTypeToShapeType.put(OBJECT_TYPE_ARC, HSSFShapeType.ARC.getType()); } public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) { @@ -193,7 +194,6 @@ public class HSSFSimpleShape extends HSSFShape EscherAggregate agg = patriarch._getBoundAggregate(); agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord()); - //used only when clone shapes if (null != getTextObjectRecord()){ agg.associateShapeToObjRecord(getEscherContainer().getChildById(EscherTextboxRecord.RECORD_ID), getTextObjectRecord()); } @@ -206,7 +206,7 @@ public class HSSFSimpleShape extends HSSFShape byte [] inSp = getEscherContainer().serialize(); spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); - if (getTextObjectRecord() != null && getString() != null && !"".equals(getString().getString())){ + if (getTextObjectRecord() != null && getString() != null && null != getString().getString()){ txo = (TextObjectRecord) getTextObjectRecord().cloneViaReserialise(); } return new HSSFSimpleShape(spContainer, obj, txo); @@ -236,8 +236,6 @@ public class HSSFSimpleShape extends HSSFShape * @see #OBJECT_TYPE_LINE * @see #OBJECT_TYPE_OVAL * @see #OBJECT_TYPE_RECTANGLE - * @see #OBJECT_TYPE_PICTURE - * @see #OBJECT_TYPE_COMMENT */ public void setShapeType( int shapeType ){ CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); @@ -258,4 +256,15 @@ public class HSSFSimpleShape extends HSSFShape public void setWrapText(int value){ setPropertyValue(new EscherSimpleProperty(EscherProperties.TEXT__WRAPTEXT, false, false, value)); } + + /** + * @see org.apache.poi.hssf.usermodel.drawing.ShapeTypes + * @param value + */ + public void setAdditionalShapeType(short value){ + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); + cod.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING); + EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); + spRecord.setShapeType(value); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java index f386dd1cfe..6a38ab3b96 100644 --- a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -15,6 +15,7 @@ public enum HSSFShapeType { PICTURE((short)0x004B, HSSFPicture.class, HSSFSimpleShape.OBJECT_TYPE_PICTURE), LINE((short)0x14, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_LINE), OVAL(EscherAggregate.ST_ELLIPSE, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_OVAL), + ARC(EscherAggregate.ST_ARC, HSSFSimpleShape.class, HSSFSimpleShape.OBJECT_TYPE_ARC), TEXT((short)202, HSSFTextbox.class, HSSFTextbox.OBJECT_TYPE_TEXT), ROUND_RECTANGLE((short)0x2, null, null); diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/ShapeTypes.java b/src/java/org/apache/poi/hssf/usermodel/drawing/ShapeTypes.java new file mode 100644 index 0000000000..3391130bd0 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/ShapeTypes.java @@ -0,0 +1,224 @@ +/* ==================================================================== + 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.hssf.usermodel.drawing; + +public interface ShapeTypes { + public static final int NotPrimitive = 0; + public static final int Rectangle = 1; + public static final int RoundRectangle = 2; + public static final int Ellipse = 3; + public static final int Diamond = 4; + public static final int IsocelesTriangle = 5; + public static final int RightTriangle = 6; + public static final int Parallelogram = 7; + public static final int Trapezoid = 8; + public static final int Hexagon = 9; + public static final int Octagon = 10; + public static final int Plus = 11; + public static final int Star = 12; + public static final int Arrow = 13; + public static final int ThickArrow = 14; + public static final int HomePlate = 15; + public static final int Cube = 16; + public static final int Balloon = 17; + public static final int Seal = 18; + public static final int Arc = 19; + public static final int Line = 20; + public static final int Plaque = 21; + public static final int Can = 22; + public static final int Donut = 23; + public static final int TextSimple = 24; + public static final int TextOctagon = 25; + public static final int TextHexagon = 26; + public static final int TextCurve = 27; + public static final int TextWave = 28; + public static final int TextRing = 29; + public static final int TextOnCurve = 30; + public static final int TextOnRing = 31; + public static final int StraightConnector1 = 32; + public static final int BentConnector2 = 33; + public static final int BentConnector3 = 34; + public static final int BentConnector4 = 35; + public static final int BentConnector5 = 36; + public static final int CurvedConnector2 = 37; + public static final int CurvedConnector3 = 38; + public static final int CurvedConnector4 = 39; + public static final int CurvedConnector5 = 40; + public static final int Callout1 = 41; + public static final int Callout2 = 42; + public static final int Callout3 = 43; + public static final int AccentCallout1 = 44; + public static final int AccentCallout2 = 45; + public static final int AccentCallout3 = 46; + public static final int BorderCallout1 = 47; + public static final int BorderCallout2 = 48; + public static final int BorderCallout3 = 49; + public static final int AccentBorderCallout1 = 50; + public static final int AccentBorderCallout2 = 51; + public static final int AccentBorderCallout3 = 52; + public static final int Ribbon = 53; + public static final int Ribbon2 = 54; + public static final int Chevron = 55; + public static final int Pentagon = 56; + public static final int NoSmoking = 57; + public static final int Star8 = 58; + public static final int Star16 = 59; + public static final int Star32 = 60; + public static final int WedgeRectCallout = 61; + public static final int WedgeRRectCallout = 62; + public static final int WedgeEllipseCallout = 63; + public static final int Wave = 64; + public static final int FoldedCorner = 65; + public static final int LeftArrow = 66; + public static final int DownArrow = 67; + public static final int UpArrow = 68; + public static final int LeftRightArrow = 69; + public static final int UpDownArrow = 70; + public static final int IrregularSeal1 = 71; + public static final int IrregularSeal2 = 72; + public static final int LightningBolt = 73; + public static final int Heart = 74; + public static final int PictureFrame = 75; + public static final int QuadArrow = 76; + public static final int LeftArrowCallout = 77; + public static final int RightArrowCallout = 78; + public static final int UpArrowCallout = 79; + public static final int DownArrowCallout = 80; + public static final int LeftRightArrowCallout = 81; + public static final int UpDownArrowCallout = 82; + public static final int QuadArrowCallout = 83; + public static final int Bevel = 84; + public static final int LeftBracket = 85; + public static final int RightBracket = 86; + public static final int LeftBrace = 87; + public static final int RightBrace = 88; + public static final int LeftUpArrow = 89; + public static final int BentUpArrow = 90; + public static final int BentArrow = 91; + public static final int Star24 = 92; + public static final int StripedRightArrow = 93; + public static final int NotchedRightArrow = 94; + public static final int BlockArc = 95; + public static final int SmileyFace = 96; + public static final int VerticalScroll = 97; + public static final int HorizontalScroll = 98; + public static final int CircularArrow = 99; + public static final int NotchedCircularArrow = 100; + public static final int UturnArrow = 101; + public static final int CurvedRightArrow = 102; + public static final int CurvedLeftArrow = 103; + public static final int CurvedUpArrow = 104; + public static final int CurvedDownArrow = 105; + public static final int CloudCallout = 106; + public static final int EllipseRibbon = 107; + public static final int EllipseRibbon2 = 108; + public static final int FlowChartProcess = 109; + public static final int FlowChartDecision = 110; + public static final int FlowChartInputOutput = 111; + public static final int FlowChartPredefinedProcess = 112; + public static final int FlowChartInternalStorage = 113; + public static final int FlowChartDocument = 114; + public static final int FlowChartMultidocument = 115; + public static final int FlowChartTerminator = 116; + public static final int FlowChartPreparation = 117; + public static final int FlowChartManualInput = 118; + public static final int FlowChartManualOperation = 119; + public static final int FlowChartConnector = 120; + public static final int FlowChartPunchedCard = 121; + public static final int FlowChartPunchedTape = 122; + public static final int FlowChartSummingJunction = 123; + public static final int FlowChartOr = 124; + public static final int FlowChartCollate = 125; + public static final int FlowChartSort = 126; + public static final int FlowChartExtract = 127; + public static final int FlowChartMerge = 128; + public static final int FlowChartOfflineStorage = 129; + public static final int FlowChartOnlineStorage = 130; + public static final int FlowChartMagneticTape = 131; + public static final int FlowChartMagneticDisk = 132; + public static final int FlowChartMagneticDrum = 133; + public static final int FlowChartDisplay = 134; + public static final int FlowChartDelay = 135; + public static final int TextPlainText = 136; + public static final int TextStop = 137; + public static final int TextTriangle = 138; + public static final int TextTriangleInverted = 139; + public static final int TextChevron = 140; + public static final int TextChevronInverted = 141; + public static final int TextRingInside = 142; + public static final int TextRingOutside = 143; + public static final int TextArchUpCurve = 144; + public static final int TextArchDownCurve = 145; + public static final int TextCircleCurve = 146; + public static final int TextButtonCurve = 147; + public static final int TextArchUpPour = 148; + public static final int TextArchDownPour = 149; + public static final int TextCirclePour = 150; + public static final int TextButtonPour = 151; + public static final int TextCurveUp = 152; + public static final int TextCurveDown = 153; + public static final int TextCascadeUp = 154; + public static final int TextCascadeDown = 155; + public static final int TextWave1 = 156; + public static final int TextWave2 = 157; + public static final int TextWave3 = 158; + public static final int TextWave4 = 159; + public static final int TextInflate = 160; + public static final int TextDeflate = 161; + public static final int TextInflateBottom = 162; + public static final int TextDeflateBottom = 163; + public static final int TextInflateTop = 164; + public static final int TextDeflateTop = 165; + public static final int TextDeflateInflate = 166; + public static final int TextDeflateInflateDeflate = 167; + public static final int TextFadeRight = 168; + public static final int TextFadeLeft = 169; + public static final int TextFadeUp = 170; + public static final int TextFadeDown = 171; + public static final int TextSlantUp = 172; + public static final int TextSlantDown = 173; + public static final int TextCanUp = 174; + public static final int TextCanDown = 175; + public static final int FlowChartAlternateProcess = 176; + public static final int FlowChartOffpageConnector = 177; + public static final int Callout90 = 178; + public static final int AccentCallout90 = 179; + public static final int BorderCallout90 = 180; + public static final int AccentBorderCallout90 = 181; + public static final int LeftRightUpArrow = 182; + public static final int Sun = 183; + public static final int Moon = 184; + public static final int BracketPair = 185; + public static final int BracePair = 186; + public static final int Star4 = 187; + public static final int DoubleWave = 188; + public static final int ActionButtonBlank = 189; + public static final int ActionButtonHome = 190; + public static final int ActionButtonHelp = 191; + public static final int ActionButtonInformation = 192; + public static final int ActionButtonForwardNext = 193; + public static final int ActionButtonBackPrevious = 194; + public static final int ActionButtonEnd = 195; + public static final int ActionButtonBeginning = 196; + public static final int ActionButtonReturn = 197; + public static final int ActionButtonDocument = 198; + public static final int ActionButtonSound = 199; + public static final int ActionButtonMovie = 200; + public static final int HostControl = 201; + public static final int TextBox = 202; +} From 3c170100d769742e076580e7e52054b28ea7f546 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Wed, 1 Aug 2012 19:34:08 +0000 Subject: [PATCH 27/32] code refactoring git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1368211 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/model/InternalSheet.java | 1 + .../poi/hssf/record/EscherAggregate.java | 26 +- .../hssf/usermodel/HSSFShapeContainer.java | 2 + .../apache/poi/hssf/usermodel/HSSFSheet.java | 826 +++++++++--------- .../poi/hssf/usermodel/TestPatriarch.java | 40 + 5 files changed, 488 insertions(+), 407 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index 5e5d601996..62da2bb1ad 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -1482,6 +1482,7 @@ public final class InternalSheet { * if none currently exist * @param drawingManager The DrawingManager2 for our workbook * @param createIfMissing Should one be created if missing? + * @return location of EscherAggregate record. if no EscherAggregate record is found return -1 */ public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing) { int loc = findFirstRecordLocBySid(DrawingRecord.sid); diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 30a815acbb..12f6b8ae9e 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -293,7 +293,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { protected HSSFPatriarch patriarch; /** - * if we want to get the same byte array if we open existing file and serialize it we should save + * if we want to get the same byte array if we open existing file and serialize it we should save * note records in right order. This list contains ids of NoteRecords in such order as we read from existing file */ private List _tailIds = new ArrayList(); @@ -306,7 +306,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { /** * list of "tail" records that need to be serialized after all drawing group records */ - private Map tailRec = new HashMap(); + private Map tailRec = new HashMap(); public EscherAggregate() { buildBaseTree(); @@ -517,9 +517,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { // write records that need to be serialized after all drawing group records Map tailCopy = new HashMap(tailRec); // at first we should save records in correct order which were already in the file during EscherAggregate.createAggregate() - for (Integer id : _tailIds){ + for (Integer id : _tailIds) { NoteRecord note = tailCopy.get(id); - if (null != note){ + if (null != note) { pos += note.serialize(pos, data); tailCopy.remove(id); } @@ -539,14 +539,18 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { //First record in drawing layer MUST be DrawingRecord if (writtenEscherBytes + drawingData.length > RecordInputStream.MAX_RECORD_DATA_SIZE && i != 1) { for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { - ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + byte[] buf = new byte[Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length - j)]; + System.arraycopy(drawingData, j, buf, 0, Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length - j)); + ContinueRecord drawing = new ContinueRecord(buf); temp += drawing.serialize(pos + temp, data); } } else { for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { if (j == 0) { DrawingRecord drawing = new DrawingRecord(); - drawing.setData(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + byte[] buf = new byte[Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length - j)]; + System.arraycopy(drawingData, j, buf, 0, Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length - j)); + drawing.setData(buf); temp += drawing.serialize(pos + temp, data); } else { ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); @@ -628,7 +632,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return shapeToObj.put(r, objRecord); } - public void removeShapeToObjRecord(EscherRecord rec){ + public void removeShapeToObjRecord(EscherRecord rec) { shapeToObj.remove(rec); } @@ -667,7 +671,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { dgContainer.setRecordId(EscherContainerRecord.DG_CONTAINER); dgContainer.setOptions((short) 0x000F); EscherDgRecord dg = new EscherDgRecord(); - dg.setRecordId( EscherDgRecord.RECORD_ID ); + dg.setRecordId(EscherDgRecord.RECORD_ID); short dgId = 1; dg.setOptions((short) (dgId << 4)); dg.setNumShapes(0); @@ -702,7 +706,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { dg.setOptions((short) (dgId << 4)); } - public void setMainSpRecordId(int shapeId){ + public void setMainSpRecordId(int shapeId) { EscherContainerRecord dgContainer = getEscherContainer(); EscherContainerRecord spContainer = (EscherContainerRecord) dgContainer.getChildById(EscherContainerRecord.SPGR_CONTAINER).getChild(0); EscherSpRecord sp = (EscherSpRecord) spContainer.getChildById(EscherSpRecord.RECORD_ID); @@ -757,11 +761,11 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return tailRec.get(cod.getObjectId()); } - public void addTailRecord(NoteRecord note){ + public void addTailRecord(NoteRecord note) { tailRec.put(note.getShapeId(), note); } - public void removeTailRecord(NoteRecord note){ + public void removeTailRecord(NoteRecord note) { tailRec.remove(note.getShapeId()); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java index 1d7748edc3..d7cb533cd2 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java @@ -51,4 +51,6 @@ public interface HSSFShapeContainer extends Iterable public int getX2(); public int getY2(); + + public boolean removeShape(HSSFShape shape); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index ebbd95cc28..f0ec2d6804 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.TreeMap; import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.hssf.model.DrawingManager2; import org.apache.poi.hssf.model.HSSFFormulaParser; import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalWorkbook; @@ -52,14 +53,15 @@ import org.apache.poi.util.POILogger; /** * High level representation of a worksheet. - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Glen Stampoultzis (glens at apache.org) - * @author Libin Roman (romal at vistaportal.com) - * @author Shawn Laubach (slaubach at apache dot org) (Just a little) - * @author Jean-Pierre Paris (jean-pierre.paris at m4x dot org) (Just a little, too) - * @author Yegor Kozlov (yegor at apache.org) (Autosizing columns) - * @author Josh Micich - * @author Petr Udalau(Petr.Udalau at exigenservices.com) - set/remove array formulas + * + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Glen Stampoultzis (glens at apache.org) + * @author Libin Roman (romal at vistaportal.com) + * @author Shawn Laubach (slaubach at apache dot org) (Just a little) + * @author Jean-Pierre Paris (jean-pierre.paris at m4x dot org) (Just a little, too) + * @author Yegor Kozlov (yegor at apache.org) (Autosizing columns) + * @author Josh Micich + * @author Petr Udalau(Petr.Udalau at exigenservices.com) - set/remove array formulas */ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { private static final POILogger log = POILogFactory.getLogger(HSSFSheet.class); @@ -76,7 +78,9 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * reference to the low level {@link InternalSheet} object */ private final InternalSheet _sheet; - /** stores rows by zero-based row number */ + /** + * stores rows by zero-based row number + */ private final TreeMap _rows; protected final InternalWorkbook _book; protected final HSSFWorkbook _workbook; @@ -103,7 +107,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * called by HSSFWorkbook when reading in an exisiting file. * * @param workbook - The HSSF Workbook object associated with the sheet. - * @param sheet - lowlevel Sheet object this sheet will represent + * @param sheet - lowlevel Sheet object this sheet will represent * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createSheet() */ protected HSSFSheet(HSSFWorkbook workbook, InternalSheet sheet) { @@ -119,10 +123,10 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { HSSFSheet sheet = new HSSFSheet(workbook, _sheet.cloneSheet()); int pos = sheet._sheet.findFirstRecordLocBySid(DrawingRecord.sid); DrawingRecord dr = (DrawingRecord) sheet._sheet.findFirstRecordBySid(DrawingRecord.sid); - if (null != dr){ + if (null != dr) { sheet._sheet.getRecords().remove(dr); } - if (getDrawingPatriarch() != null){ + if (getDrawingPatriarch() != null) { HSSFPatriarch patr = HSSFPatriarch.createPatriarch(this.getDrawingPatriarch(), sheet); sheet._sheet.getRecords().add(pos, patr._getBoundAggregate()); sheet._patriarch = patr; @@ -135,7 +139,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * * @return the parent workbook */ - public HSSFWorkbook getWorkbook(){ + public HSSFWorkbook getWorkbook() { return _workbook; } @@ -145,7 +149,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { private void setPropertiesFromSheet(InternalSheet sheet) { RowRecord row = sheet.getNextRow(); - boolean rowRecordsAlreadyPresent = row!=null; + boolean rowRecordsAlreadyPresent = row != null; while (row != null) { createRowFromRecord(row); @@ -156,9 +160,9 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { Iterator iter = sheet.getCellValueIterator(); long timestart = System.currentTimeMillis(); - if (log.check( POILogger.DEBUG )) + if (log.check(POILogger.DEBUG)) log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ", - Long.valueOf(timestart)); + Long.valueOf(timestart)); HSSFRow lastrow = null; // Add every cell to its row @@ -169,7 +173,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { HSSFRow hrow = lastrow; if (hrow == null || hrow.getRowNum() != cval.getRow()) { - hrow = getRow( cval.getRow() ); + hrow = getRow(cval.getRow()); lastrow = hrow; if (hrow == null) { // Some tools (like Perl module Spreadsheet::WriteExcel - bug 41187) skip the RowRecords @@ -184,29 +188,28 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { hrow = createRowFromRecord(rowRec); } } - if (log.check( POILogger.DEBUG )) - log.log( DEBUG, "record id = " + Integer.toHexString( ( (Record) cval ).getSid() ) ); - hrow.createCellFromRecord( cval ); - if (log.check( POILogger.DEBUG )) - log.log( DEBUG, "record took ", - Long.valueOf( System.currentTimeMillis() - cellstart ) ); + if (log.check(POILogger.DEBUG)) + log.log(DEBUG, "record id = " + Integer.toHexString(((Record) cval).getSid())); + hrow.createCellFromRecord(cval); + if (log.check(POILogger.DEBUG)) + log.log(DEBUG, "record took ", + Long.valueOf(System.currentTimeMillis() - cellstart)); } - if (log.check( POILogger.DEBUG )) + if (log.check(POILogger.DEBUG)) log.log(DEBUG, "total sheet cell creation took ", - Long.valueOf(System.currentTimeMillis() - timestart)); + Long.valueOf(System.currentTimeMillis() - timestart)); } /** * Create a new row within the sheet and return the high level representation * - * @param rownum row number + * @param rownum row number * @return High level HSSFRow object representing a row in the sheet * @see org.apache.poi.hssf.usermodel.HSSFRow * @see #removeRow(org.apache.poi.ss.usermodel.Row) */ - public HSSFRow createRow(int rownum) - { + public HSSFRow createRow(int rownum) { HSSFRow row = new HSSFRow(_workbook, this, rownum); // new rows inherit default height from the sheet row.setHeight(getDefaultRowHeight()); @@ -218,12 +221,12 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Used internally to create a high level Row object from a low level row object. * USed when reading an existing file - * @param row low level record to represent as a high level Row and add to sheet + * + * @param row low level record to represent as a high level Row and add to sheet * @return HSSFRow high level representation */ - private HSSFRow createRowFromRecord(RowRecord row) - { + private HSSFRow createRowFromRecord(RowRecord row) { HSSFRow hrow = new HSSFRow(_workbook, this, row); addRow(hrow, false); @@ -233,17 +236,17 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Remove a row from this sheet. All cells contained in the row are removed as well * - * @param row representing a row to remove. + * @param row representing a row to remove. */ public void removeRow(Row row) { HSSFRow hrow = (HSSFRow) row; if (row.getSheet() != this) { throw new IllegalArgumentException("Specified row does not belong to this sheet"); } - for(Cell cell : row) { - HSSFCell xcell = (HSSFCell)cell; - if(xcell.isPartOfArrayFormulaGroup()){ - String msg = "Row[rownum="+row.getRowNum()+"] contains cell(s) included in a multi-cell array formula. You cannot change part of an array."; + for (Cell cell : row) { + HSSFCell xcell = (HSSFCell) cell; + if (xcell.isPartOfArrayFormulaGroup()) { + String msg = "Row[rownum=" + row.getRowNum() + "] contains cell(s) included in a multi-cell array formula. You cannot change part of an array."; xcell.notifyArrayFormulaChanging(msg); } } @@ -255,12 +258,10 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { //should not happen if the input argument is valid throw new IllegalArgumentException("Specified row does not belong to this sheet"); } - if (hrow.getRowNum() == getLastRowNum()) - { + if (hrow.getRowNum() == getLastRowNum()) { _lastrow = findLastRow(_lastrow); } - if (hrow.getRowNum() == getFirstRowNum()) - { + if (hrow.getRowNum() == getFirstRowNum()) { _firstrow = findFirstRow(_firstrow); } _sheet.removeRow(hrow.getRowRecord()); @@ -290,13 +291,11 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * used internally to refresh the "first row" when the first row is removed. */ - private int findFirstRow(int firstrow) - { + private int findFirstRow(int firstrow) { int rownum = firstrow + 1; HSSFRow r = getRow(rownum); - while (r == null && rownum <= getLastRowNum()) - { + while (r == null && rownum <= getLastRowNum()) { r = getRow(++rownum); } @@ -312,20 +311,16 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @param addLow whether to add the row to the low level model - false if its already there */ - private void addRow(HSSFRow row, boolean addLow) - { + private void addRow(HSSFRow row, boolean addLow) { _rows.put(Integer.valueOf(row.getRowNum()), row); - if (addLow) - { + if (addLow) { _sheet.addRow(row.getRowRecord()); } boolean firstRow = _rows.size() == 1; - if (row.getRowNum() > getLastRowNum() || firstRow) - { + if (row.getRowNum() > getLastRowNum() || firstRow) { _lastrow = row.getRowNum(); } - if (row.getRowNum() < getFirstRowNum() || firstRow) - { + if (row.getRowNum() < getFirstRowNum() || firstRow) { _firstrow = row.getRowNum(); } } @@ -333,7 +328,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Returns the logical row (not physical) 0-based. If you ask for a row that is not * defined you get a null. This is to say row 4 represents the fifth row on a sheet. - * @param rowIndex row to get + * + * @param rowIndex row to get * @return HSSFRow representing the row number or null if its not defined on the sheet */ public HSSFRow getRow(int rowIndex) { @@ -349,6 +345,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Gets the first row on the sheet + * * @return the number of the first logical row on the sheet, zero based */ public int getFirstRowNum() { @@ -358,13 +355,14 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Gets the number last row on the sheet. * Owing to idiosyncrasies in the excel file - * format, if the result of calling this method - * is zero, you can't tell if that means there - * are zero rows on the sheet, or one at - * position zero. For that case, additionally - * call {@link #getPhysicalNumberOfRows()} to - * tell if there is a row at position zero - * or not. + * format, if the result of calling this method + * is zero, you can't tell if that means there + * are zero rows on the sheet, or one at + * position zero. For that case, additionally + * call {@link #getPhysicalNumberOfRows()} to + * tell if there is a row at position zero + * or not. + * * @return the number of the last row contained in this sheet, zero based. */ public int getLastRowNum() { @@ -376,14 +374,14 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @param dataValidation The Data validation object settings */ public void addValidationData(DataValidation dataValidation) { - if (dataValidation == null) { - throw new IllegalArgumentException("objValidation must not be null"); - } - HSSFDataValidation hssfDataValidation = (HSSFDataValidation)dataValidation; - DataValidityTable dvt = _sheet.getOrCreateDataValidityTable(); + if (dataValidation == null) { + throw new IllegalArgumentException("objValidation must not be null"); + } + HSSFDataValidation hssfDataValidation = (HSSFDataValidation) dataValidation; + DataValidityTable dvt = _sheet.getOrCreateDataValidityTable(); - DVRecord dvRecord = hssfDataValidation.createDVRecord(this); - dvt.addDataValidation(dvRecord); + DVRecord dvRecord = hssfDataValidation.createDVRecord(this); + dvt.addDataValidation(dvRecord); } @@ -412,7 +410,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @deprecated (Sep 2008) use {@link #getColumnWidth(int)} */ public short getColumnWidth(short columnIndex) { - return (short)getColumnWidth(columnIndex & 0xFFFF); + return (short) getColumnWidth(columnIndex & 0xFFFF); } /** @@ -424,8 +422,9 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Get the visibility state for a given column. + * * @param columnIndex - the column to get (0-based) - * @param hidden - the visiblity state of the column + * @param hidden - the visiblity state of the column */ public void setColumnHidden(int columnIndex, boolean hidden) { _sheet.setColumnHidden(columnIndex, hidden); @@ -433,6 +432,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Get the hidden state for a given column. + * * @param columnIndex - the column to set (0-based) * @return hidden - false if the column is visible */ @@ -442,13 +442,13 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Set the width (in units of 1/256th of a character width) - * + *

*

* The maximum column width for an individual cell is 255 characters. * This value represents the number of characters that can be displayed * in a cell that is formatted with the standard font (first font in the workbook). *

- * + *

*

* Character width is defined as the maximum digit width * of the numbers 0, 1, 2, ... 9 as rendered @@ -457,7 +457,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * Unless you are using a very special font, the default character is '0' (zero), * this is true for Arial (default font font in HSSF) and Calibri (default font in XSSF) *

- * + *

*

* Please note, that the width set by this method includes 4 pixels of margin padding (two on each side), * plus 1 pixel padding for the gridlines (Section 3.3.1.12 of the OOXML spec). @@ -465,23 +465,23 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { *

*

* To compute the actual number of visible characters, - * Excel uses the following formula (Section 3.3.1.12 of the OOXML spec): + * Excel uses the following formula (Section 3.3.1.12 of the OOXML spec): *

* - * width = Truncate([{Number of Visible Characters} * - * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256 + * width = Truncate([{Number of Visible Characters} * + * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256 * *

Using the Calibri font as an example, the maximum digit width of 11 point font size is 7 pixels (at 96 dpi). - * If you set a column width to be eight characters wide, e.g. setColumnWidth(columnIndex, 8*256), - * then the actual value of visible characters (the value shown in Excel) is derived from the following equation: - * - Truncate([numChars*7+5]/7*256)/256 = 8; - * - * - * which gives 7.29. + * If you set a column width to be eight characters wide, e.g. setColumnWidth(columnIndex, 8*256), + * then the actual value of visible characters (the value shown in Excel) is derived from the following equation: + * + * Truncate([numChars*7+5]/7*256)/256 = 8; + * + *

+ * which gives 7.29. * * @param columnIndex - the column to set (0-based) - * @param width - the width in units of 1/256th of a character width + * @param width - the width in units of 1/256th of a character width * @throws IllegalArgumentException if width > 255*256 (the maximum column width in Excel is 255 characters) */ public void setColumnWidth(int columnIndex, int width) { @@ -490,6 +490,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * get the width (in units of 1/256th of a character width ) + * * @param columnIndex - the column to set (0-based) * @return width - the width in units of 1/256th of a character width */ @@ -500,14 +501,17 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * get the default column width for the sheet (if the columns do not define their own width) in * characters + * * @return default column width */ public int getDefaultColumnWidth() { return _sheet.getDefaultColumnWidth(); } + /** * set the default column width for the sheet (if the columns do not define their own width) in * characters + * * @param width default column width */ public void setDefaultColumnWidth(int width) { @@ -518,7 +522,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * get the default row height for the sheet (if the rows do not define their own height) in * twips (1/20 of a point) - * @return default row height + * @return default row height */ public short getDefaultRowHeight() { return _sheet.getDefaultRowHeight(); @@ -527,45 +531,44 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * get the default row height for the sheet (if the rows do not define their own height) in * points. - * @return default row height in points + * @return default row height in points */ - public float getDefaultRowHeightInPoints() - { - return ((float)_sheet.getDefaultRowHeight() / 20); + public float getDefaultRowHeightInPoints() { + return ((float) _sheet.getDefaultRowHeight() / 20); } /** * set the default row height for the sheet (if the rows do not define their own height) in * twips (1/20 of a point) - * @param height default row height + * + * @param height default row height */ - public void setDefaultRowHeight(short height) - { + public void setDefaultRowHeight(short height) { _sheet.setDefaultRowHeight(height); } /** * set the default row height for the sheet (if the rows do not define their own height) in * points + * * @param height default row height */ - public void setDefaultRowHeightInPoints(float height) - { + public void setDefaultRowHeightInPoints(float height) { _sheet.setDefaultRowHeight((short) (height * 20)); } /** * Returns the HSSFCellStyle that applies to the given - * (0 based) column, or null if no style has been - * set for that column + * (0 based) column, or null if no style has been + * set for that column */ public HSSFCellStyle getColumnStyle(int column) { - short styleIndex = _sheet.getXFIndexForColAt((short)column); + short styleIndex = _sheet.getXFIndexForColAt((short) column); - if(styleIndex == 0xf) { + if (styleIndex == 0xf) { // None set return null; } @@ -576,55 +579,55 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * get whether gridlines are printed. + * * @return true if printed */ - public boolean isGridsPrinted() - { + public boolean isGridsPrinted() { return _sheet.isGridsPrinted(); } /** * set whether gridlines printed. - * @param value false if not printed. + * + * @param value false if not printed. */ - public void setGridsPrinted(boolean value) - { + public void setGridsPrinted(boolean value) { _sheet.setGridsPrinted(value); } /** * @deprecated (Aug-2008) use CellRangeAddress instead of Region */ - public int addMergedRegion(org.apache.poi.ss.util.Region region) - { - return _sheet.addMergedRegion( region.getRowFrom(), + public int addMergedRegion(org.apache.poi.ss.util.Region region) { + return _sheet.addMergedRegion(region.getRowFrom(), region.getColumnFrom(), //(short) region.getRowTo(), region.getRowTo(), region.getColumnTo()); } + /** * adds a merged region of cells (hence those cells form one) + * * @param region (rowfrom/colfrom-rowto/colto) to merge * @return index of this region */ - public int addMergedRegion(CellRangeAddress region) - { + public int addMergedRegion(CellRangeAddress region) { region.validate(SpreadsheetVersion.EXCEL97); // throw IllegalStateException if the argument CellRangeAddress intersects with // a multi-cell array formula defined in this sheet validateArrayFormulas(region); - return _sheet.addMergedRegion( region.getFirstRow(), + return _sheet.addMergedRegion(region.getFirstRow(), region.getFirstColumn(), region.getLastRow(), region.getLastColumn()); } - private void validateArrayFormulas(CellRangeAddress region){ + private void validateArrayFormulas(CellRangeAddress region) { int firstRow = region.getFirstRow(); int firstColumn = region.getFirstColumn(); int lastRow = region.getLastRow(); @@ -635,13 +638,13 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { if (row == null) continue; HSSFCell cell = row.getCell(colIn); - if(cell == null) continue; + if (cell == null) continue; - if(cell.isPartOfArrayFormulaGroup()){ + if (cell.isPartOfArrayFormulaGroup()) { CellRangeAddress arrayRange = cell.getArrayFormulaRange(); if (arrayRange.getNumberOfCells() > 1 && - ( arrayRange.isInRange(region.getFirstRow(), region.getFirstColumn()) || - arrayRange.isInRange(region.getFirstRow(), region.getFirstColumn())) ){ + (arrayRange.isInRange(region.getFirstRow(), region.getFirstColumn()) || + arrayRange.isInRange(region.getFirstRow(), region.getFirstColumn()))) { String msg = "The range " + region.formatAsString() + " intersects with a multi-cell array formula. " + "You cannot merge cells of an array."; throw new IllegalStateException(msg); @@ -655,50 +658,51 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Control if Excel should be asked to recalculate all formulas on this sheet * when the workbook is opened. + *

+ *

+ * Calculating the formula values with {@link org.apache.poi.ss.usermodel.FormulaEvaluator} is the + * recommended solution, but this may be used for certain cases where + * evaluation in POI is not possible. + *

+ *

+ *

+ * It is recommended to force recalcuation of formulas on workbook level using + * {@link org.apache.poi.ss.usermodel.Workbook#setForceFormulaRecalculation(boolean)} + * to ensure that all cross-worksheet formuals and external dependencies are updated. + *

* - *

- * Calculating the formula values with {@link org.apache.poi.ss.usermodel.FormulaEvaluator} is the - * recommended solution, but this may be used for certain cases where - * evaluation in POI is not possible. - *

- * - *

- * It is recommended to force recalcuation of formulas on workbook level using - * {@link org.apache.poi.ss.usermodel.Workbook#setForceFormulaRecalculation(boolean)} - * to ensure that all cross-worksheet formuals and external dependencies are updated. - *

* @param value true if the application will perform a full recalculation of - * this worksheet values when the workbook is opened - * + * this worksheet values when the workbook is opened * @see org.apache.poi.ss.usermodel.Workbook#setForceFormulaRecalculation(boolean) */ - public void setForceFormulaRecalculation(boolean value) - { + public void setForceFormulaRecalculation(boolean value) { _sheet.setUncalced(value); } + /** * Whether a record must be inserted or not at generation to indicate that * formula must be recalculated when workbook is opened. + * * @return true if an uncalced record must be inserted or not at generation */ - public boolean getForceFormulaRecalculation() - { + public boolean getForceFormulaRecalculation() { return _sheet.getUncalced(); } /** * determines whether the output is vertically centered on the page. + * * @param value true to vertically center, false otherwise. */ - public void setVerticallyCenter(boolean value) - { + public void setVerticallyCenter(boolean value) { _sheet.getPageSettings().getVCenter().setVCenter(value); } /** * TODO: Boolean not needed, remove after next release + * * @deprecated (Mar-2008) use getVerticallyCenter() instead */ public boolean getVerticallyCenter(boolean value) { @@ -708,18 +712,17 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Determine whether printed output for this sheet will be vertically centered. */ - public boolean getVerticallyCenter() - { + public boolean getVerticallyCenter() { return _sheet.getPageSettings().getVCenter().getVCenter(); } /** * determines whether the output is horizontally centered on the page. + * * @param value true to horizontally center, false otherwise. */ - public void setHorizontallyCenter(boolean value) - { + public void setHorizontallyCenter(boolean value) { _sheet.getPageSettings().getHCenter().setHCenter(value); } @@ -727,8 +730,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * Determine whether printed output for this sheet will be horizontally centered. */ - public boolean getHorizontallyCenter() - { + public boolean getHorizontallyCenter() { return _sheet.getPageSettings().getHCenter().getHCenter(); } @@ -738,8 +740,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * * @param value true for right to left, false otherwise. */ - public void setRightToLeft(boolean value) - { + public void setRightToLeft(boolean value) { _sheet.getWindowTwo().setArabic(value); } @@ -748,28 +749,27 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * * @return whether the text is displayed in right-to-left mode in the window */ - public boolean isRightToLeft() - { + public boolean isRightToLeft() { return _sheet.getWindowTwo().getArabic(); } /** * removes a merged region of cells (hence letting them free) + * * @param index of the region to unmerge */ - public void removeMergedRegion(int index) - { + public void removeMergedRegion(int index) { _sheet.removeMergedRegion(index); } /** * returns the number of merged regions + * * @return number of merged regions */ - public int getNumMergedRegions() - { + public int getNumMergedRegions() { return _sheet.getNumMergedRegions(); } @@ -779,9 +779,10 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { public org.apache.poi.hssf.util.Region getMergedRegionAt(int index) { CellRangeAddress cra = getMergedRegion(index); - return new org.apache.poi.hssf.util.Region(cra.getFirstRow(), (short)cra.getFirstColumn(), - cra.getLastRow(), (short)cra.getLastColumn()); + return new org.apache.poi.hssf.util.Region(cra.getFirstRow(), (short) cra.getFirstColumn(), + cra.getLastRow(), (short) cra.getLastColumn()); } + /** * @return the merged region at the specified index */ @@ -791,17 +792,18 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not - * be the third row if say for instance the second row is undefined. - * Call getRowNum() on each row if you care which one it is. + * be the third row if say for instance the second row is undefined. + * Call getRowNum() on each row if you care which one it is. */ public Iterator rowIterator() { @SuppressWarnings("unchecked") // can this clumsy generic syntax be improved? - Iterator result = (Iterator)(Iterator)_rows.values().iterator(); + Iterator result = (Iterator) (Iterator) _rows.values().iterator(); return result; } + /** * Alias for {@link #rowIterator()} to allow - * foreach loops + * foreach loops */ public Iterator iterator() { return rowIterator(); @@ -819,7 +821,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * whether alternate expression evaluation is on - * @param b alternative expression evaluation or not + * @param b alternative expression evaluation or not */ public void setAlternativeExpression(boolean b) { WSBoolRecord record = @@ -830,7 +832,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * whether alternative formula entry is on - * @param b alternative formulas or not + * @param b alternative formulas or not */ public void setAlternativeFormula(boolean b) { WSBoolRecord record = @@ -841,7 +843,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * show automatic page breaks or not - * @param b whether to show auto page breaks + * @param b whether to show auto page breaks */ public void setAutobreaks(boolean b) { WSBoolRecord record = @@ -852,7 +854,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * set whether sheet is a dialog sheet or not - * @param b isDialog or not + * @param b isDialog or not */ public void setDialog(boolean b) { WSBoolRecord record = @@ -864,7 +866,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * set whether to display the guts or not * - * @param b guts or no guts (or glory) + * @param b guts or no guts (or glory) */ public void setDisplayGuts(boolean b) { WSBoolRecord record = @@ -875,7 +877,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * fit to page option is on - * @param b fit or not + * @param b fit or not */ public void setFitToPage(boolean b) { WSBoolRecord record = @@ -886,7 +888,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * set if row summaries appear below detail in the outline - * @param b below or not + * @param b below or not */ public void setRowSumsBelow(boolean b) { WSBoolRecord record = @@ -899,7 +901,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * set if col summaries appear right of the detail in the outline - * @param b right or not + * @param b right or not */ public void setRowSumsRight(boolean b) { WSBoolRecord record = @@ -963,7 +965,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { *

* @return whether all zero values on the worksheet are displayed */ - public boolean isDisplayZeros(){ + public boolean isDisplayZeros() { return _sheet.getWindowTwo().getDisplayZeros(); } @@ -975,7 +977,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { *

* @param value whether to display or hide all zero values on the worksheet */ - public void setDisplayZeros(boolean value){ + public void setDisplayZeros(boolean value) { _sheet.getWindowTwo().setDisplayZeros(value); } @@ -1041,26 +1043,32 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Note - this is not the same as whether the sheet is focused (isActive) + * * @return true if this sheet is currently selected */ public boolean isSelected() { return getSheet().getWindowTwo().getSelected(); } + /** * Sets whether sheet is selected. + * * @param sel Whether to select the sheet or deselect the sheet. */ public void setSelected(boolean sel) { getSheet().getWindowTwo().setSelected(sel); } + /** * @return true if this sheet is currently focused */ public boolean isActive() { return getSheet().getWindowTwo().isActive(); } + /** * Sets whether sheet is selected. + * * @param sel Whether to select the sheet or deselect the sheet. */ public void setActive(boolean sel) { @@ -1069,11 +1077,12 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Gets the size of the margin in inches. + * * @param margin which margin to get * @return the size of the margin */ public double getMargin(short margin) { - switch (margin){ + switch (margin) { case FooterMargin: return _sheet.getPageSettings().getPrintSetup().getFooterMargin(); case HeaderMargin: @@ -1085,11 +1094,12 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Sets the size of the margin in inches. + * * @param margin which margin to get - * @param size the size of the margin + * @param size the size of the margin */ public void setMargin(short margin, double size) { - switch (margin){ + switch (margin) { case FooterMargin: _sheet.getPageSettings().getPrintSetup().setFooterMargin(size); break; @@ -1104,8 +1114,10 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { private WorksheetProtectionBlock getProtectionBlock() { return _sheet.getProtectionBlock(); } + /** * Answer whether protection is enabled or disabled + * * @return true => protection enabled; false => protection disabled */ public boolean getProtect() { @@ -1116,11 +1128,12 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @return hashed password */ public short getPassword() { - return (short)getProtectionBlock().getPasswordHash(); + return (short) getProtectionBlock().getPasswordHash(); } /** * Answer whether object protection is enabled or disabled + * * @return true => protection enabled; false => protection disabled */ public boolean getObjectProtect() { @@ -1129,13 +1142,16 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Answer whether scenario protection is enabled or disabled + * * @return true => protection enabled; false => protection disabled */ public boolean getScenarioProtect() { return getProtectionBlock().isScenarioProtected(); } + /** * Sets the protection enabled as well as the password + * * @param password to set for protection. Pass null to remove protection */ public void protectSheet(String password) { @@ -1147,25 +1163,25 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * fraction. For example to express a zoom of 75% use 3 for the numerator * and 4 for the denominator. * - * @param numerator The numerator for the zoom magnification. - * @param denominator The denominator for the zoom magnification. + * @param numerator The numerator for the zoom magnification. + * @param denominator The denominator for the zoom magnification. */ - public void setZoom( int numerator, int denominator) - { + public void setZoom(int numerator, int denominator) { if (numerator < 1 || numerator > 65535) throw new IllegalArgumentException("Numerator must be greater than 1 and less than 65536"); if (denominator < 1 || denominator > 65535) throw new IllegalArgumentException("Denominator must be greater than 1 and less than 65536"); SCLRecord sclRecord = new SCLRecord(); - sclRecord.setNumerator((short)numerator); - sclRecord.setDenominator((short)denominator); + sclRecord.setNumerator((short) numerator); + sclRecord.setDenominator((short) denominator); getSheet().setSCLRecord(sclRecord); } /** * The top row in the visible view when the sheet is * first viewed after opening it in a viewer + * * @return short indicating the rownum (0 based) of the top row */ public short getTopRow() { @@ -1175,6 +1191,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * The left col in the visible view when the sheet is * first viewed after opening it in a viewer + * * @return short indicating the rownum (0 based) of the top row */ public short getLeftCol() { @@ -1184,18 +1201,20 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Sets desktop window pane display area, when the * file is first opened in a viewer. - * @param toprow the top row to show in desktop window pane + * + * @param toprow the top row to show in desktop window pane * @param leftcol the left column to show in desktop window pane */ - public void showInPane(short toprow, short leftcol){ + public void showInPane(short toprow, short leftcol) { _sheet.setTopRow(toprow); _sheet.setLeftCol(leftcol); } /** * Shifts the merged regions left or right depending on mode - *

+ *

* TODO: MODE , this is only row specific + * * @param startRow * @param endRow * @param n @@ -1205,26 +1224,26 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { List shiftedRegions = new ArrayList(); //move merged regions completely if they fall within the new region boundaries when they are shifted for (int i = 0; i < getNumMergedRegions(); i++) { - CellRangeAddress merged = getMergedRegion(i); + CellRangeAddress merged = getMergedRegion(i); - boolean inStart= (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow); - boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow); + boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow); + boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow); - //don't check if it's not within the shifted area - if (!inStart || !inEnd) { + //don't check if it's not within the shifted area + if (!inStart || !inEnd) { continue; - } + } - //only shift if the region outside the shifted rows is not merged too - if (!SheetUtil.containsCell(merged, startRow-1, 0) && - !SheetUtil.containsCell(merged, endRow+1, 0)){ - merged.setFirstRow(merged.getFirstRow()+n); - merged.setLastRow(merged.getLastRow()+n); - //have to remove/add it back - shiftedRegions.add(merged); - removeMergedRegion(i); - i = i -1; // we have to back up now since we removed one - } + //only shift if the region outside the shifted rows is not merged too + if (!SheetUtil.containsCell(merged, startRow - 1, 0) && + !SheetUtil.containsCell(merged, endRow + 1, 0)) { + merged.setFirstRow(merged.getFirstRow() + n); + merged.setLastRow(merged.getLastRow() + n); + //have to remove/add it back + shiftedRegions.add(merged); + removeMergedRegion(i); + i = i - 1; // we have to back up now since we removed one + } } //read so it doesn't get shifted again @@ -1240,17 +1259,18 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * Shifts rows between startRow and endRow n number of rows. * If you use a negative number, it will shift rows up. * Code ensures that rows don't wrap around. - * + *

* Calls shiftRows(startRow, endRow, n, false, false); - * - *

+ *

+ *

* Additionally shifts merged regions that are completely defined in these * rows (ie. merged 2 cells on a row to be shifted). + * * @param startRow the row to start shifting - * @param endRow the row to end shifting - * @param n the number of rows to shift + * @param endRow the row to end shifting + * @param n the number of rows to shift */ - public void shiftRows( int startRow, int endRow, int n ) { + public void shiftRows(int startRow, int endRow, int n) { shiftRows(startRow, endRow, n, false, false); } @@ -1258,19 +1278,20 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * Shifts rows between startRow and endRow n number of rows. * If you use a negative number, it will shift rows up. * Code ensures that rows don't wrap around - * - *

+ *

+ *

* Additionally shifts merged regions that are completely defined in these * rows (ie. merged 2 cells on a row to be shifted). - *

+ *

* TODO Might want to add bounds checking here - * @param startRow the row to start shifting - * @param endRow the row to end shifting - * @param n the number of rows to shift - * @param copyRowHeight whether to copy the row height during the shift + * + * @param startRow the row to start shifting + * @param endRow the row to end shifting + * @param n the number of rows to shift + * @param copyRowHeight whether to copy the row height during the shift * @param resetOriginalRowHeight whether to set the original row's height to the default */ - public void shiftRows( int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { + public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { shiftRows(startRow, endRow, n, copyRowHeight, resetOriginalRowHeight, true); } @@ -1278,21 +1299,22 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * Shifts rows between startRow and endRow n number of rows. * If you use a negative number, it will shift rows up. * Code ensures that rows don't wrap around - * - *

+ *

+ *

* Additionally shifts merged regions that are completely defined in these * rows (ie. merged 2 cells on a row to be shifted). - *

+ *

* TODO Might want to add bounds checking here - * @param startRow the row to start shifting - * @param endRow the row to end shifting - * @param n the number of rows to shift - * @param copyRowHeight whether to copy the row height during the shift + * + * @param startRow the row to start shifting + * @param endRow the row to end shifting + * @param n the number of rows to shift + * @param copyRowHeight whether to copy the row height during the shift * @param resetOriginalRowHeight whether to set the original row's height to the default - * @param moveComments whether to move comments at the same time as the cells they are attached to + * @param moveComments whether to move comments at the same time as the cells they are attached to */ public void shiftRows(int startRow, int endRow, int n, - boolean copyRowHeight, boolean resetOriginalRowHeight, boolean moveComments) { + boolean copyRowHeight, boolean resetOriginalRowHeight, boolean moveComments) { int s, inc; if (n < 0) { s = startRow; @@ -1301,10 +1323,10 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { s = endRow; inc = -1; } else { - // Nothing to do - return; + // Nothing to do + return; } - + NoteRecord[] noteRecs; if (moveComments) { noteRecs = _sheet.getNoteRecords(); @@ -1315,16 +1337,16 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { shiftMerged(startRow, endRow, n, true); _sheet.getPageSettings().shiftRowBreaks(startRow, endRow, n); - for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc ) { - HSSFRow row = getRow( rowNum ); + for (int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc) { + HSSFRow row = getRow(rowNum); // notify all cells in this row that we are going to shift them, // it can throw IllegalStateException if the operation is not allowed, for example, // if the row contains cells included in a multi-cell array formula - if(row != null) notifyRowShifting(row); + if (row != null) notifyRowShifting(row); - HSSFRow row2Replace = getRow( rowNum + n ); - if ( row2Replace == null ) - row2Replace = createRow( rowNum + n ); + HSSFRow row2Replace = getRow(rowNum + n); + if (row2Replace == null) + row2Replace = createRow(rowNum + n); // Remove all the old cells from the row we'll @@ -1343,21 +1365,21 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { row2Replace.setHeight(row.getHeight()); } if (resetOriginalRowHeight) { - row.setHeight((short)0xff); + row.setHeight((short) 0xff); } // Copy each cell from the source row to // the destination row - for(Iterator cells = row.cellIterator(); cells.hasNext(); ) { - HSSFCell cell = (HSSFCell)cells.next(); - row.removeCell( cell ); + for (Iterator cells = row.cellIterator(); cells.hasNext(); ) { + HSSFCell cell = (HSSFCell) cells.next(); + row.removeCell(cell); CellValueRecordInterface cellRecord = cell.getCellValueRecord(); - cellRecord.setRow( rowNum + n ); - row2Replace.createCellFromRecord( cellRecord ); - _sheet.addValueRecord( rowNum + n, cellRecord ); + cellRecord.setRow(rowNum + n); + row2Replace.createCellFromRecord(cellRecord); + _sheet.addValueRecord(rowNum + n, cellRecord); HSSFHyperlink link = cell.getHyperlink(); - if(link != null){ + if (link != null) { link.setFirstRow(link.getFirstRow() + n); link.setLastRow(link.getLastRow() + n); } @@ -1368,54 +1390,54 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { // Move comments from the source row to the // destination row. Note that comments can // exist for cells which are null - if(moveComments) { + if (moveComments) { // This code would get simpler if NoteRecords could be organised by HSSFRow. HSSFPatriarch patriarch = createDrawingPatriarch(); - for(int i=patriarch.getChildren().size()-1; i>=0; i--){ + for (int i = patriarch.getChildren().size() - 1; i >= 0; i--) { HSSFShape shape = patriarch.getChildren().get(i); - if (!(shape instanceof HSSFComment)){ + if (!(shape instanceof HSSFComment)) { continue; } HSSFComment comment = (HSSFComment) shape; - if (comment.getRow() != rowNum){ + if (comment.getRow() != rowNum) { continue; } comment.setRow(rowNum + n); } } } - + // Re-compute the first and last rows of the sheet as needed - if(n > 0) { - // Rows are moving down - if ( startRow == _firstrow ) { - // Need to walk forward to find the first non-blank row - _firstrow = Math.max( startRow + n, 0 ); - for( int i=startRow+1; i < startRow+n; i++ ) { - if (getRow(i) != null) { - _firstrow = i; - break; - } - } - } - if ( endRow + n > _lastrow ) { - _lastrow = Math.min( endRow + n, SpreadsheetVersion.EXCEL97.getLastRowIndex() ); - } + if (n > 0) { + // Rows are moving down + if (startRow == _firstrow) { + // Need to walk forward to find the first non-blank row + _firstrow = Math.max(startRow + n, 0); + for (int i = startRow + 1; i < startRow + n; i++) { + if (getRow(i) != null) { + _firstrow = i; + break; + } + } + } + if (endRow + n > _lastrow) { + _lastrow = Math.min(endRow + n, SpreadsheetVersion.EXCEL97.getLastRowIndex()); + } } else { - // Rows are moving up - if ( startRow + n < _firstrow ) { - _firstrow = Math.max( startRow + n, 0 ); - } - if ( endRow == _lastrow ) { - // Need to walk backward to find the last non-blank row - _lastrow = Math.min( endRow + n, SpreadsheetVersion.EXCEL97.getLastRowIndex() ); - for (int i=endRow-1; i > endRow+n; i++) { - if (getRow(i) != null) { - _lastrow = i; - break; - } - } - } + // Rows are moving up + if (startRow + n < _firstrow) { + _firstrow = Math.max(startRow + n, 0); + } + if (endRow == _lastrow) { + // Need to walk backward to find the last non-blank row + _lastrow = Math.min(endRow + n, SpreadsheetVersion.EXCEL97.getLastRowIndex()); + for (int i = endRow - 1; i > endRow + n; i++) { + if (getRow(i) != null) { + _lastrow = i; + break; + } + } + } } // Update any formulas on this sheet that point to @@ -1426,7 +1448,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { _sheet.updateFormulasAfterCellShift(shifter, externSheetIndex); int nSheets = _workbook.getNumberOfSheets(); - for(int i=0; i *

- * If both colSplit and rowSplit are zero then the existing freeze pane is removed + * If both colSplit and rowSplit are zero then the existing freeze pane is removed *

* - * @param colSplit Horizonatal position of split. - * @param rowSplit Vertical position of split. - * @param leftmostColumn Left column visible in right pane. - * @param topRow Top row visible in bottom pane + * @param colSplit Horizonatal position of split. + * @param rowSplit Vertical position of split. + * @param leftmostColumn Left column visible in right pane. + * @param topRow Top row visible in bottom pane */ public void createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) { validateColumn(colSplit); validateRow(rowSplit); - if (leftmostColumn < colSplit) throw new IllegalArgumentException("leftmostColumn parameter must not be less than colSplit parameter"); - if (topRow < rowSplit) throw new IllegalArgumentException("topRow parameter must not be less than leftmostColumn parameter"); - getSheet().createFreezePane( colSplit, rowSplit, topRow, leftmostColumn ); + if (leftmostColumn < colSplit) + throw new IllegalArgumentException("leftmostColumn parameter must not be less than colSplit parameter"); + if (topRow < rowSplit) + throw new IllegalArgumentException("topRow parameter must not be less than leftmostColumn parameter"); + getSheet().createFreezePane(colSplit, rowSplit, topRow, leftmostColumn); } /** * Creates a split (freezepane). Any existing freezepane or split pane is overwritten. - * + *

*

- * If both colSplit and rowSplit are zero then the existing freeze pane is removed + * If both colSplit and rowSplit are zero then the existing freeze pane is removed *

* - * @param colSplit Horizonatal position of split. - * @param rowSplit Vertical position of split. + * @param colSplit Horizonatal position of split. + * @param rowSplit Vertical position of split. */ public void createFreezePane(int colSplit, int rowSplit) { createFreezePane(colSplit, rowSplit, colSplit, rowSplit); @@ -1489,23 +1513,25 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Creates a split pane. Any existing freezepane or split pane is overwritten. + * * @param xSplitPos Horizonatal position of split (in 1/20th of a point). * @param ySplitPos Vertical position of split (in 1/20th of a point). - * @param topRow Top row visible in bottom pane - * @param leftmostColumn Left column visible in right pane. - * @param activePane Active pane. One of: PANE_LOWER_RIGHT, - * PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT + * @param topRow Top row visible in bottom pane + * @param leftmostColumn Left column visible in right pane. + * @param activePane Active pane. One of: PANE_LOWER_RIGHT, + * PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT * @see #PANE_LOWER_LEFT * @see #PANE_LOWER_RIGHT * @see #PANE_UPPER_LEFT * @see #PANE_UPPER_RIGHT */ public void createSplitPane(int xSplitPos, int ySplitPos, int leftmostColumn, int topRow, int activePane) { - getSheet().createSplitPane( xSplitPos, ySplitPos, topRow, leftmostColumn, activePane ); + getSheet().createSplitPane(xSplitPos, ySplitPos, topRow, leftmostColumn, activePane); } /** * Returns the information regarding the currently configured pane (split or freeze). + * * @return null if no pane configured, or the pane information. */ public PaneInformation getPaneInformation() { @@ -1514,6 +1540,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Sets whether the gridlines are shown in a viewer. + * * @param show whether to show gridlines or not */ public void setDisplayGridlines(boolean show) { @@ -1522,14 +1549,16 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Returns if gridlines are displayed. + * * @return whether gridlines are displayed */ public boolean isDisplayGridlines() { - return _sheet.isDisplayGridlines(); + return _sheet.isDisplayGridlines(); } /** * Sets whether the formulas are shown in a viewer. + * * @param show whether to show formulas or not */ public void setDisplayFormulas(boolean show) { @@ -1538,6 +1567,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Returns if formulas are displayed. + * * @return whether formulas are displayed */ public boolean isDisplayFormulas() { @@ -1546,6 +1576,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Sets whether the RowColHeadings are shown in a viewer. + * * @param show whether to show RowColHeadings or not */ public void setDisplayRowColHeadings(boolean show) { @@ -1554,6 +1585,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Returns if RowColHeadings are displayed. + * * @return whether RowColHeadings are displayed */ public boolean isDisplayRowColHeadings() { @@ -1563,7 +1595,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Sets a page break at the indicated row * Breaks occur above the specified row and left of the specified column inclusive. - * + *

* For example, sheet.setColumnBreak(2); breaks the sheet into two parts * with columns A,B,C in the first and D,E,... in the second. Simuilar, sheet.setRowBreak(2); * breaks the sheet into two parts with first three rows (rownum=1...3) in the first part @@ -1573,7 +1605,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { */ public void setRowBreak(int row) { validateRow(row); - _sheet.getPageSettings().setRowBreak(row, (short)0, (short)255); + _sheet.getPageSettings().setRowBreak(row, (short) 0, (short) 255); } /** @@ -1610,7 +1642,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Sets a page break at the indicated column. * Breaks occur above the specified row and left of the specified column inclusive. - * + *

* For example, sheet.setColumnBreak(2); breaks the sheet into two parts * with columns A,B,C in the first and D,E,... in the second. Simuilar, sheet.setRowBreak(2); * breaks the sheet into two parts with first three rows (rownum=1...3) in the first part @@ -1619,12 +1651,13 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * @param column the column to break, inclusive */ public void setColumnBreak(int column) { - validateColumn((short)column); - _sheet.getPageSettings().setColumnBreak((short)column, (short)0, (short) SpreadsheetVersion.EXCEL97.getLastRowIndex()); + validateColumn((short) column); + _sheet.getPageSettings().setColumnBreak((short) column, (short) 0, (short) SpreadsheetVersion.EXCEL97.getLastRowIndex()); } /** * Determines if there is a page break at the indicated column + * * @param column FIXME: Document this! * @return FIXME: Document this! */ @@ -1634,6 +1667,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Removes a page break at the indicated column + * * @param column */ public void removeColumnBreak(int column) { @@ -1642,6 +1676,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Runs a bounds check for row numbers + * * @param row */ protected void validateRow(int row) { @@ -1652,12 +1687,13 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Runs a bounds check for column numbers + * * @param column */ protected void validateColumn(int column) { int maxcol = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); if (column > maxcol) throw new IllegalArgumentException("Maximum column number is " + maxcol); - if (column < 0) throw new IllegalArgumentException("Minimum column number is 0"); + if (column < 0) throw new IllegalArgumentException("Minimum column number is 0"); } /** @@ -1670,7 +1706,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { EscherAggregate r = (EscherAggregate) getSheet().findFirstRecordBySid(EscherAggregate.sid); List escherRecords = r.getEscherRecords(); PrintWriter w = new PrintWriter(System.out); - for (Iterator iterator = escherRecords.iterator(); iterator.hasNext();) { + for (Iterator iterator = escherRecords.iterator(); iterator.hasNext(); ) { EscherRecord escherRecord = iterator.next(); if (fat) { System.out.println(escherRecord.toString()); @@ -1681,50 +1717,23 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { w.flush(); } - /** - * Creates the top-level drawing patriarch. This will have - * the effect of removing any existing drawings on this - * sheet. - * This may then be used to add graphics or charts - * @return The new patriarch. - */ - public HSSFPatriarch createDrawingPatriarch() { - if(_patriarch == null){ - // Create the drawing group if it doesn't already exist. - _workbook.initDrawings(); - - if(_patriarch == null){ - _sheet.aggregateDrawingRecords(_book.getDrawingManager(), true); - EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid); - _patriarch = new HSSFPatriarch(this, agg); - _patriarch.afterCreate(); -// agg.setPatriarch(_patriarch); - } - } - return _patriarch; - } - /** * Returns the agregate escher records for this sheet, - * it there is one. - * WARNING - calling this will trigger a parsing of the - * associated escher records. Any that aren't supported - * (such as charts and complex drawing types) will almost - * certainly be lost or corrupted when written out. + * it there is one. */ public EscherAggregate getDrawingEscherAggregate() { _book.findDrawingGroup(); // If there's now no drawing manager, then there's // no drawing escher records on the workbook - if(_book.getDrawingManager() == null) { + if (_book.getDrawingManager() == null) { return null; } int found = _sheet.aggregateDrawingRecords( _book.getDrawingManager(), false ); - if(found == -1) { + if (found == -1) { // Workbook has drawing stuff, but this sheet doesn't return null; } @@ -1735,51 +1744,76 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { } /** - * Returns the top-level drawing patriach, if there is - * one. * This will hold any graphics or charts for the sheet. - * WARNING - calling this will trigger a parsing of the - * associated escher records. Any that aren't supported - * (such as charts and complex drawing types) will almost - * certainly be lost or corrupted when written out. Only - * use this with simple drawings, otherwise call - * {@link HSSFSheet#createDrawingPatriarch()} and - * start from scratch! + * + * @return the top-level drawing patriarch, if there is one, else returns null */ public HSSFPatriarch getDrawingPatriarch() { - if(_patriarch != null) return _patriarch; - - EscherAggregate agg = getDrawingEscherAggregate(); - if(agg == null) return null; - - _patriarch = new HSSFPatriarch(this, agg); -// _patriarch.buildShapeTree(); - - //HSSFShapeFactory.createShapeTree(); - //agg.setPatriarch(_patriarch); - //EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg); - - // Have it process the records into high level objects - // as best it can do (this step may eat anything - // that isn't supported, you were warned...) -// agg.convertRecordsToUserModel(); - - // Return what we could cope with + _patriarch = getPatriarch(false); return _patriarch; } /** - * @deprecated (Sep 2008) use {@link #setColumnGroupCollapsed(int, boolean)} + * Creates the top-level drawing patriarch. This will have + * the effect of removing any existing drawings on this + * sheet. + * This may then be used to add graphics or charts + * + * @return The new patriarch. */ + public HSSFPatriarch createDrawingPatriarch() { + _patriarch = getPatriarch(true); + return _patriarch; + } + + private HSSFPatriarch getPatriarch(boolean createIfMissing) { + HSSFPatriarch patriarch = null; + if (_patriarch != null) { + return _patriarch; + } + DrawingManager2 dm = _book.findDrawingGroup(); + if (null == dm) { + if (!createIfMissing) { + return null; + } else { + _book.createDrawingGroup(); + dm = _book.getDrawingManager(); + } + } + EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid); + if (null == agg) { + int pos = _sheet.aggregateDrawingRecords(dm, false); + if (-1 == pos) { + if (createIfMissing) { + pos = _sheet.aggregateDrawingRecords(dm, true); + agg = (EscherAggregate) _sheet.getRecords().get(pos); + patriarch = new HSSFPatriarch(this, agg); + patriarch.afterCreate(); + return patriarch; + } else { + return null; + } + } + agg = (EscherAggregate) _sheet.getRecords().get(pos); + } + return new HSSFPatriarch(this, agg); + } + + /** + * @deprecated (Sep 2008) use {@link #setColumnGroupCollapsed(int, boolean)} + */ + public void setColumnGroupCollapsed(short columnNumber, boolean collapsed) { setColumnGroupCollapsed(columnNumber & 0xFFFF, collapsed); } + /** * @deprecated (Sep 2008) use {@link #groupColumn(int, int)} */ public void groupColumn(short fromColumn, short toColumn) { groupColumn(fromColumn & 0xFFFF, toColumn & 0xFFFF); } + /** * @deprecated (Sep 2008) use {@link #ungroupColumn(int, int)} */ @@ -1790,8 +1824,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Expands or collapses a column group. * - * @param columnNumber One of the columns in the group. - * @param collapsed true = collapse group, false = expand group. + * @param columnNumber One of the columns in the group. + * @param collapsed true = collapse group, false = expand group. */ public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) { _sheet.setColumnGroupCollapsed(columnNumber, collapsed); @@ -1800,8 +1834,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Create an outline for the provided column range. * - * @param fromColumn beginning of the column range. - * @param toColumn end of the column range. + * @param fromColumn beginning of the column range. + * @param toColumn end of the column range. */ public void groupColumn(int fromColumn, int toColumn) { _sheet.groupColumnRange(fromColumn, toColumn, true); @@ -1814,8 +1848,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Tie a range of cell together so that they can be collapsed or expanded * - * @param fromRow start row (0-based) - * @param toRow end row (0-based) + * @param fromRow start row (0-based) + * @param toRow end row (0-based) */ public void groupRow(int fromRow, int toRow) { _sheet.groupRowRange(fromRow, toRow, true); @@ -1837,18 +1871,18 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * Sets the default column style for a given column. POI will only apply this style to new cells added to the sheet. * * @param column the column index - * @param style the style to set + * @param style the style to set */ public void setDefaultColumnStyle(int column, CellStyle style) { - _sheet.setDefaultColumnStyle(column, ((HSSFCellStyle)style).getIndex()); + _sheet.setDefaultColumnStyle(column, ((HSSFCellStyle) style).getIndex()); } /** * Adjusts the column width to fit the contents. - * + *

* This process can be relatively slow on large sheets, so this should - * normally only be called once per column, at the end of your - * processing. + * normally only be called once per column, at the end of your + * processing. * * @param column the column index */ @@ -1858,15 +1892,15 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { /** * Adjusts the column width to fit the contents. - * + *

* This process can be relatively slow on large sheets, so this should - * normally only be called once per column, at the end of your - * processing. - * + * normally only be called once per column, at the end of your + * processing. + *

* You can specify whether the content of merged cells should be considered or ignored. - * Default is to ignore merged cells. + * Default is to ignore merged cells. * - * @param column the column index + * @param column the column index * @param useMergedCells whether to use the contents of merged cells when calculating the width of the column */ public void autoSizeColumn(int column, boolean useMergedCells) { @@ -1874,11 +1908,11 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { if (width != -1) { width *= 256; - int maxColumnWidth = 255*256; // The maximum column width for an individual cell is 255 characters + int maxColumnWidth = 255 * 256; // The maximum column width for an individual cell is 255 characters if (width > maxColumnWidth) { width = maxColumnWidth; } - setColumnWidth(column, (int)(width)); + setColumnWidth(column, (int) (width)); } } @@ -1888,7 +1922,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { * * @return cell comment or null if not found */ - public HSSFComment getCellComment(int row, int column) { + public HSSFComment getCellComment(int row, int column) { return findCellComment(row, column); } @@ -1917,7 +1951,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { int lastColumn = range.getLastColumn(); int height = lastRow - firstRow + 1; int width = lastColumn - firstColumn + 1; - List temp = new ArrayList(height*width); + List temp = new ArrayList(height * width); for (int rowIn = firstRow; rowIn <= lastRow; rowIn++) { for (int colIn = firstColumn; colIn <= lastColumn; colIn++) { HSSFRow row = getRow(rowIn); @@ -1944,7 +1978,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { c.setCellArrayFormula(range); } HSSFCell mainArrayFormulaCell = cells.getTopLeftCell(); - FormulaRecordAggregate agg = (FormulaRecordAggregate)mainArrayFormulaCell.getCellValueRecord(); + FormulaRecordAggregate agg = (FormulaRecordAggregate) mainArrayFormulaCell.getCellValueRecord(); agg.setArrayFormula(range, ptgs); return cells; } @@ -1970,20 +2004,20 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { return result; } - public DataValidationHelper getDataValidationHelper() { - return new HSSFDataValidationHelper(this); - } - + public DataValidationHelper getDataValidationHelper() { + return new HSSFDataValidationHelper(this); + } + public HSSFAutoFilter setAutoFilter(CellRangeAddress range) { InternalWorkbook workbook = _workbook.getWorkbook(); int sheetIndex = _workbook.getSheetIndex(this); - NameRecord name = workbook.getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, sheetIndex+1); + NameRecord name = workbook.getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, sheetIndex + 1); if (name == null) { - name = workbook.createBuiltInName(NameRecord.BUILTIN_FILTER_DB, sheetIndex+1); + name = workbook.createBuiltInName(NameRecord.BUILTIN_FILTER_DB, sheetIndex + 1); } // The built-in name must consist of a single Area3d Ptg. @@ -1995,41 +2029,41 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { AutoFilterInfoRecord r = new AutoFilterInfoRecord(); // the number of columns that have AutoFilter enabled. int numcols = 1 + range.getLastColumn() - range.getFirstColumn(); - r.setNumEntries((short)numcols); + r.setNumEntries((short) numcols); int idx = _sheet.findFirstRecordLocBySid(DimensionsRecord.sid); _sheet.getRecords().add(idx, r); //create a combobox control for each column HSSFPatriarch p = createDrawingPatriarch(); - for(int col = range.getFirstColumn(); col <= range.getLastColumn(); col++){ - p.createComboBox(new HSSFClientAnchor(0,0,0,0, - (short)col, range.getFirstRow(), (short)(col+1), range.getFirstRow()+1)); + for (int col = range.getFirstColumn(); col <= range.getLastColumn(); col++) { + p.createComboBox(new HSSFClientAnchor(0, 0, 0, 0, + (short) col, range.getFirstRow(), (short) (col + 1), range.getFirstRow() + 1)); } - + return new HSSFAutoFilter(this); } protected HSSFComment findCellComment(int row, int column) { HSSFPatriarch patriarch = getDrawingPatriarch(); - if (null == patriarch){ + if (null == patriarch) { patriarch = createDrawingPatriarch(); } return lookForComment(patriarch, row, column); } - private HSSFComment lookForComment(HSSFShapeContainer container, int row, int column){ - for (Object object: container.getChildren()){ + private HSSFComment lookForComment(HSSFShapeContainer container, int row, int column) { + for (Object object : container.getChildren()) { HSSFShape shape = (HSSFShape) object; - if (shape instanceof HSSFShapeGroup){ - HSSFShape res = lookForComment((HSSFShapeContainer) shape, row, column); - if (null != res){ + if (shape instanceof HSSFShapeGroup) { + HSSFShape res = lookForComment((HSSFShapeContainer) shape, row, column); + if (null != res) { return (HSSFComment) res; } continue; } - if (shape instanceof HSSFComment){ + if (shape instanceof HSSFComment) { HSSFComment comment = (HSSFComment) shape; - if (comment.getColumn() == column && comment.getRow() == row){ + if (comment.getColumn() == column && comment.getRow() == row) { return comment; } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java new file mode 100644 index 0000000000..be5dc51594 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java @@ -0,0 +1,40 @@ +package org.apache.poi.hssf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.ddf.EscherDgRecord; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.EscherAggregate; + +/** + * @author Evgeniy Berlog + * @date 01.08.12 + */ +public class TestPatriarch extends TestCase { + + public void testGetPatriarch(){ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sh = wb.createSheet(); + assertNull(sh.getDrawingPatriarch()); + + HSSFPatriarch patriarch = sh.createDrawingPatriarch(); + assertNotNull(patriarch); + patriarch.createSimpleShape(new HSSFClientAnchor()); + patriarch.createSimpleShape(new HSSFClientAnchor()); + + assertSame(patriarch, sh.getDrawingPatriarch()); + + EscherAggregate agg = patriarch._getBoundAggregate(); + + EscherDgRecord dg = agg.getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); + int lastId = dg.getLastMSOSPID(); + + assertSame(patriarch, sh.createDrawingPatriarch()); + + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wb.getSheetAt(0); + patriarch = sh.createDrawingPatriarch(); + dg = patriarch._getBoundAggregate().getEscherContainer().getChildById(EscherDgRecord.RECORD_ID); + + assertEquals(lastId, dg.getLastMSOSPID()); + } +} From 9a2b63d59e2557efd52f2e2493a7921a65e53eda Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Wed, 1 Aug 2012 19:48:24 +0000 Subject: [PATCH 28/32] added Apache License header to each new file git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1368221 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/usermodel/HSSFCombobox.java | 17 +++++++++++++++++ .../hssf/usermodel/drawing/HSSFShapeType.java | 17 +++++++++++++++++ .../poi/hssf/model/HSSFTestModelHelper.java | 17 +++++++++++++++++ .../poi/hssf/model/TestDrawingShapes.java | 17 +++++++++++++++++ .../poi/hssf/model/TestEscherRecordFactory.java | 17 +++++++++++++++++ .../apache/poi/hssf/model/TestHSSFAnchor.java | 17 +++++++++++++++++ .../apache/poi/hssf/usermodel/TestComment.java | 17 +++++++++++++++++ .../poi/hssf/usermodel/TestEmbeddedObjects.java | 17 +++++++++++++++++ .../poi/hssf/usermodel/TestPatriarch.java | 17 +++++++++++++++++ .../apache/poi/hssf/usermodel/TestPolygon.java | 17 +++++++++++++++++ .../poi/hssf/usermodel/TestShapeGroup.java | 17 +++++++++++++++++ .../org/apache/poi/hssf/usermodel/TestText.java | 17 +++++++++++++++++ 12 files changed, 204 insertions(+) diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java index 184a6d3201..7537b6296a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel; import org.apache.poi.ddf.*; diff --git a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java index 6a38ab3b96..14dacc6a22 100644 --- a/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java +++ b/src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel.drawing; import org.apache.poi.hssf.record.EscherAggregate; diff --git a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java index bc22d17a97..10acb70e73 100644 --- a/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java +++ b/src/testcases/org/apache/poi/hssf/model/HSSFTestModelHelper.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.model; import org.apache.poi.hssf.usermodel.HSSFComment; diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 512ad2371e..f9f35ce406 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.model; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java b/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java index 9b37d43c68..4ff7c441ee 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java +++ b/src/testcases/org/apache/poi/hssf/model/TestEscherRecordFactory.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.model; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index 08da761936..868848a0ed 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.model; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java index 1f8c069351..caa038c217 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java index 840643b951..c7d478e4f8 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestEmbeddedObjects.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java index be5dc51594..d9eba84bd7 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPatriarch.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java index 3983c838b2..e677f97ec9 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestPolygon.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java index d5ea732d02..7b78e21edd 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestShapeGroup.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel; import junit.framework.TestCase; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java index 18eefd4786..1b6f750ea1 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java @@ -1,3 +1,20 @@ +/* ==================================================================== + 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.hssf.usermodel; import junit.framework.TestCase; From 3786b5d599afa60e320b8ef3e20f03650dbc9a07 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Thu, 2 Aug 2012 19:52:47 +0000 Subject: [PATCH 29/32] fixed compilation for jdk 1.5 git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1368670 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/hssf/record/EscherAggregate.java | 7 +++++-- .../org/apache/poi/hssf/usermodel/HSSFShapeGroup.java | 3 ++- .../org/apache/poi/hssf/model/TestDrawingShapes.java | 10 ++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index 12f6b8ae9e..a93b655ca0 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -553,7 +553,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { drawing.setData(buf); temp += drawing.serialize(pos + temp, data); } else { - ContinueRecord drawing = new ContinueRecord(Arrays.copyOfRange(drawingData, j, Math.min(j + RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length))); + byte[] buf = new byte[Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length - j)]; + System.arraycopy(drawingData, j, buf, 0, Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.length - j)); + ContinueRecord drawing = new ContinueRecord(buf); temp += drawing.serialize(pos + temp, data); } } @@ -708,7 +710,8 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public void setMainSpRecordId(int shapeId) { EscherContainerRecord dgContainer = getEscherContainer(); - EscherContainerRecord spContainer = (EscherContainerRecord) dgContainer.getChildById(EscherContainerRecord.SPGR_CONTAINER).getChild(0); + EscherContainerRecord spgrConatiner = (EscherContainerRecord) dgContainer.getChildById(EscherContainerRecord.SPGR_CONTAINER); + EscherContainerRecord spContainer = (EscherContainerRecord) spgrConatiner.getChild(0); EscherSpRecord sp = (EscherSpRecord) spContainer.getChildById(EscherSpRecord.RECORD_ID); sp.setShapeId(shapeId); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index f08625a010..4ee6995620 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -346,7 +346,8 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); spgrContainer.setOptions((short) 0x000F); EscherContainerRecord spContainer = new EscherContainerRecord(); - byte [] inSp = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER).serialize(); + EscherContainerRecord cont = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER); + byte [] inSp = cont.serialize(); spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory()); spgrContainer.addChildRecord(spContainer); diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index f9f35ce406..6a1638335d 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -351,13 +351,15 @@ public class TestDrawingShapes extends TestCase { String opt1Str = opt.toXml(); textbox.setFillColor(textbox.getFillColor()); - assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); + EscherContainerRecord container = HSSFTestHelper.getEscherContainer(textbox); + EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID); + assertEquals(opt1Str, optRecord.toXml()); textbox.setLineStyle(textbox.getLineStyle()); - assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); + assertEquals(opt1Str, optRecord.toXml()); textbox.setLineWidth(textbox.getLineWidth()); - assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); + assertEquals(opt1Str, optRecord.toXml()); textbox.setLineStyleColor(textbox.getLineStyleColor()); - assertEquals(opt1Str, HSSFTestHelper.getEscherContainer(textbox).getChildById(EscherOptRecord.RECORD_ID).toXml()); + assertEquals(opt1Str, optRecord.toXml()); } public void testDgRecordNumShapes(){ From 234a9a1ebb827452251c5a1c71e904d977a85286 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Mon, 6 Aug 2012 21:06:12 +0000 Subject: [PATCH 30/32] added javadoc and few other improvements git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1370018 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/model/InternalSheet.java | 3 + .../apache/poi/hssf/record/DrawingRecord.java | 12 ++-- .../poi/hssf/record/EscherAggregate.java | 55 +++++++++++------ .../apache/poi/hssf/usermodel/HSSFAnchor.java | 32 +++++++++- .../poi/hssf/usermodel/HSSFChildAnchor.java | 21 ++++++- .../poi/hssf/usermodel/HSSFClientAnchor.java | 41 ++++++++++--- .../poi/hssf/usermodel/HSSFCombobox.java | 2 + .../poi/hssf/usermodel/HSSFComment.java | 2 + .../poi/hssf/usermodel/HSSFPatriarch.java | 43 +++++++------ .../poi/hssf/usermodel/HSSFPicture.java | 3 + .../poi/hssf/usermodel/HSSFPolygon.java | 17 +++++- .../apache/poi/hssf/usermodel/HSSFShape.java | 44 +++++++++++-- .../hssf/usermodel/HSSFShapeContainer.java | 19 +++++- .../poi/hssf/usermodel/HSSFShapeFactory.java | 61 +++++-------------- .../poi/hssf/usermodel/HSSFShapeGroup.java | 2 +- .../poi/hssf/usermodel/HSSFSimpleShape.java | 60 +++++------------- .../poi/hssf/usermodel/HSSFUnknownShape.java | 56 ----------------- .../poi/hssf/model/TestDrawingShapes.java | 13 ---- .../apache/poi/hssf/model/TestHSSFAnchor.java | 8 +-- .../poi/hssf/usermodel/HSSFTestHelper.java | 4 ++ .../poi/hssf/usermodel/TestComment.java | 3 - .../apache/poi/hssf/usermodel/TestText.java | 3 - 22 files changed, 270 insertions(+), 234 deletions(-) delete mode 100644 src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java diff --git a/src/java/org/apache/poi/hssf/model/InternalSheet.java b/src/java/org/apache/poi/hssf/model/InternalSheet.java index bb4ce3fb3d..856df327e8 100644 --- a/src/java/org/apache/poi/hssf/model/InternalSheet.java +++ b/src/java/org/apache/poi/hssf/model/InternalSheet.java @@ -351,6 +351,9 @@ public final class InternalSheet { continue; } if (rb instanceof EscherAggregate){ + /** + * this record will be removed after reading actual data from EscherAggregate + */ rb = new DrawingRecord(); } Record rec = (Record) ((Record) rb).clone(); diff --git a/src/java/org/apache/poi/hssf/record/DrawingRecord.java b/src/java/org/apache/poi/hssf/record/DrawingRecord.java index 89a8072784..fac9e715bb 100644 --- a/src/java/org/apache/poi/hssf/record/DrawingRecord.java +++ b/src/java/org/apache/poi/hssf/record/DrawingRecord.java @@ -37,6 +37,7 @@ public final class DrawingRecord extends StandardRecord { recordData = in.readRemainder(); } + @Deprecated public void processContinueRecord(byte[] record) { //don't merge continue record with the drawing record, it must be serialized separately contd = record; @@ -54,13 +55,8 @@ public final class DrawingRecord extends StandardRecord { return sid; } + @Deprecated public byte[] getData() { -// if (continueData.size() != 0) { -// byte[] newBuffer = new byte[recordData.length + continueData.size()]; -// System.arraycopy(recordData, 0, newBuffer, 0, recordData.length); -// System.arraycopy(continueData.toByteArray(), 0, newBuffer, recordData.length, continueData.size()); -// return newBuffer; -// } return recordData; } @@ -75,6 +71,10 @@ public final class DrawingRecord extends StandardRecord { recordData = thedata; } + /** + * Cloning of drawing records must be executed through HSSFPatriarch, because all id's must be changed + * @return cloned drawing records + */ public Object clone() { DrawingRecord rec = new DrawingRecord(); rec.recordData = recordData.clone(); diff --git a/src/java/org/apache/poi/hssf/record/EscherAggregate.java b/src/java/org/apache/poi/hssf/record/EscherAggregate.java index a93b655ca0..68937de15e 100644 --- a/src/java/org/apache/poi/hssf/record/EscherAggregate.java +++ b/src/java/org/apache/poi/hssf/record/EscherAggregate.java @@ -290,8 +290,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { public static final short ST_TEXTBOX = (short) 202; public static final short ST_NIL = (short) 0x0FFF; - protected HSSFPatriarch patriarch; - /** * if we want to get the same byte array if we open existing file and serialize it we should save * note records in right order. This list contains ids of NoteRecords in such order as we read from existing file @@ -340,6 +338,10 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return result.toString(); } + /** + * Calculates the xml representation of this record. This is + * simply a dump of all the records. + */ public String toXml(String tab) { StringBuilder builder = new StringBuilder(); builder.append(tab).append("<").append(getRecordName()).append(">\n"); @@ -360,7 +362,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { /** * Collapses the drawing records into an aggregate. - * read Drawing and Continue records into single byte array, create Escher tree from byte array, create map + * read Drawing, Obj, TxtObj, Note and Continue records into single byte array, + * create Escher tree from byte array, create map + * */ public static EscherAggregate createAggregate(List records, int locFirstDrawingRecord, DrawingManager2 drawingManager) { // Keep track of any shape records created so we can match them back to the object id's. @@ -494,7 +498,7 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { byte[] drawingData = new byte[endOffset - startOffset + 1]; System.arraycopy(buffer, startOffset, drawingData, 0, drawingData.length); - pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); + pos += writeDataIntoDrawingRecord(drawingData, writtenEscherBytes, pos, data, i); writtenEscherBytes += drawingData.length; @@ -505,13 +509,13 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { if (i == shapes.size() - 1 && endOffset < buffer.length - 1) { drawingData = new byte[buffer.length - endOffset - 1]; System.arraycopy(buffer, endOffset + 1, drawingData, 0, drawingData.length); - pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); + pos += writeDataIntoDrawingRecord(drawingData, writtenEscherBytes, pos, data, i); } } if ((pos - offset) < buffer.length - 1) { byte[] drawingData = new byte[buffer.length - (pos - offset)]; System.arraycopy(buffer, (pos - offset), drawingData, 0, drawingData.length); - pos += writeDataIntoDrawingRecord(0, drawingData, writtenEscherBytes, pos, data, i); + pos += writeDataIntoDrawingRecord(drawingData, writtenEscherBytes, pos, data, i); } // write records that need to be serialized after all drawing group records @@ -535,7 +539,17 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return bytesWritten; } - private int writeDataIntoDrawingRecord(int temp, byte[] drawingData, int writtenEscherBytes, int pos, byte[] data, int i) { + /** + * @param drawingData - escher records saved into single byte array + * @param writtenEscherBytes - count of bytes already saved into drawing records (we should know it to decide create + * drawing or continue record) + * @param pos current position of data array + * @param data - array of bytes where drawing records must be serialized + * @param i - number of shape, saved into data array + * @return offset of data array after serialization + */ + private int writeDataIntoDrawingRecord(byte[] drawingData, int writtenEscherBytes, int pos, byte[] data, int i) { + int temp = 0; //First record in drawing layer MUST be DrawingRecord if (writtenEscherBytes + drawingData.length > RecordInputStream.MAX_RECORD_DATA_SIZE && i != 1) { for (int j = 0; j < drawingData.length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { @@ -576,6 +590,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { return size; } + /** + * @return record size, including header size of obj, text, note, drawing, continue records + */ public int getRecordSize() { // To determine size of aggregate record we have to know size of each DrawingRecord because if DrawingRecord // is split into several continue records we have to add header size to total EscherAggregate size @@ -638,12 +655,6 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { shapeToObj.remove(rec); } - public void clear() { - clearEscherRecords(); - shapeToObj.clear(); -// lastShapeId = 1024; - } - protected String getRecordName() { return "ESCHERAGGREGATE"; } @@ -740,34 +751,44 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { } /** - * Returns the mapping of {@link EscherClientDataRecord} and {@link EscherTextboxRecord} + * @return unmodifiable copy of the mapping of {@link EscherClientDataRecord} and {@link EscherTextboxRecord} * to their {@link TextObjectRecord} or {@link ObjRecord} . *

* We need to access it outside of EscherAggregate when building shapes - * - * @return */ public Map getShapeToObjMapping() { return Collections.unmodifiableMap(shapeToObj); } /** - * @return tails records. We need to access them when building shapes. + * @return unmodifiable copy of tail records. We need to access them when building shapes. * Every HSSFComment shape has a link to a NoteRecord from the tailRec collection. */ public Map getTailRecords() { return tailRec; } + /** + * @param obj - ObjRecord with id == NoteRecord.id + * @return null if note record is not found else returns note record with id == obj.id + */ public NoteRecord getNoteRecordByObj(ObjRecord obj) { CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) obj.getSubRecords().get(0); return tailRec.get(cod.getObjectId()); } + /** + * Add tail record to existing map + * @param note to be added + */ public void addTailRecord(NoteRecord note) { tailRec.put(note.getShapeId(), note); } + /** + * Remove tail record from the existing map + * @param note to be removed + */ public void removeTailRecord(NoteRecord note) { tailRec.remove(note.getShapeId()); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java index 32422168b5..91bbd5b952 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFAnchor.java @@ -57,27 +57,57 @@ public abstract class HSSFAnchor { } } + /** + * @return x coordinate of the left up corner + */ public abstract int getDx1(); + /** + * @param dx1 x coordinate of the left up corner + */ public abstract void setDx1(int dx1); + /** + * @return y coordinate of the left up corner + */ public abstract int getDy1(); + /** + * @param dy1 y coordinate of the left up corner + */ public abstract void setDy1(int dy1); + /** + * @return y coordinate of the right down corner + */ public abstract int getDy2(); + /** + * @param dy2 y coordinate of the right down corner + */ public abstract void setDy2(int dy2); + /** + * @return x coordinate of the right down corner + */ public abstract int getDx2(); + /** + * @param dx2 x coordinate of the right down corner + */ public abstract void setDx2(int dx2); + /** + * @return whether this shape is horizontally flipped + */ public abstract boolean isHorizontallyFlipped(); + /** + * @return whether this shape is vertically flipped + */ public abstract boolean isVerticallyFlipped(); - public abstract EscherRecord getEscherAnchor(); + protected abstract EscherRecord getEscherAnchor(); protected abstract void createEscherAnchor(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java index 9df47d64c1..be69c2a98d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java @@ -25,6 +25,10 @@ public final class HSSFChildAnchor extends HSSFAnchor { private EscherChildAnchorRecord _escherChildAnchor; + /** + * create anchor from existing file + * @param escherChildAnchorRecord + */ public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) { this._escherChildAnchor = escherChildAnchorRecord; } @@ -33,6 +37,13 @@ public final class HSSFChildAnchor extends HSSFAnchor { _escherChildAnchor = new EscherChildAnchorRecord(); } + /** + * create anchor from scratch + * @param dx1 x coordinate of the left up corner + * @param dy1 y coordinate of the left up corner + * @param dx2 x coordinate of the right down corner + * @param dy2 y coordinate of the right down corner + */ public HSSFChildAnchor(int dx1, int dy1, int dx2, int dy2) { super(Math.min(dx1, dx2), Math.min(dy1, dy2), Math.max(dx1, dx2), Math.max(dy1, dy2)); if (dx1 > dx2){ @@ -83,6 +94,12 @@ public final class HSSFChildAnchor extends HSSFAnchor { _escherChildAnchor.setDx2(dx2); } + /** + * @param dx1 x coordinate of the left up corner + * @param dy1 y coordinate of the left up corner + * @param dx2 x coordinate of the right down corner + * @param dy2 y coordinate of the right down corner + */ public void setAnchor(int dx1, int dy1, int dx2, int dy2) { setDx1(Math.min(dx1, dx2)); setDy1(Math.min(dy1, dy2)); @@ -90,16 +107,18 @@ public final class HSSFChildAnchor extends HSSFAnchor { setDy2(Math.max(dy1, dy2)); } + public boolean isHorizontallyFlipped() { return _isHorizontallyFlipped; } + public boolean isVerticallyFlipped() { return _isVerticallyFlipped; } @Override - public EscherRecord getEscherAnchor() { + protected EscherRecord getEscherAnchor() { return _escherChildAnchor; } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java index ad77c7a4d5..ac199e005d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java @@ -113,45 +113,75 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { return row.getHeightInPoints(); } + /** + * @return the column(0 based) of the first cell. + */ public short getCol1() { return _escherClientAnchor.getCol1(); } + /** + * @param col1 the column(0 based) of the first cell. + */ public void setCol1(short col1) { checkRange(col1, 0, 255, "col1"); _escherClientAnchor.setCol1(col1); } + /** + * @param col1 0-based column of the first cell. + */ public void setCol1(int col1) { setCol1((short) col1); } + /** + * @return the column(0 based) of the first cell. + */ public short getCol2() { return _escherClientAnchor.getCol2(); } + /** + * @param col2 the column(0 based) of the second cell. + */ public void setCol2(short col2) { checkRange(col2, 0, 255, "col2"); _escherClientAnchor.setCol2(col2); } + /** + * @param col2 the column(0 based) of the second cell. + */ public void setCol2(int col2) { setCol2((short) col2); } + /** + * @return the row(0 based) of the first cell. + */ public int getRow1() { return _escherClientAnchor.getRow1(); } + /** + * @param row1 0-based row of the first cell. + */ public void setRow1(int row1) { checkRange(row1, 0, 256 * 256, "row1"); _escherClientAnchor.setRow1(Integer.valueOf(row1).shortValue()); } + /** + * @return the row(0 based) of the second cell. + */ public int getRow2() { return _escherClientAnchor.getRow2(); } + /** + * @return the row(0 based) of the second cell. + */ public void setRow2(int row2) { checkRange(row2, 0, 256 * 256, "row2"); _escherClientAnchor.setRow2(Integer.valueOf(row2).shortValue()); @@ -190,22 +220,16 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { setDy2(y2); } - /** - * @return true if the anchor goes from right to left. - */ public boolean isHorizontallyFlipped() { return _isHorizontallyFlipped; } - /** - * @return true if the anchor goes from bottom to top. - */ public boolean isVerticallyFlipped() { return _isVerticallyFlipped; } @Override - public EscherRecord getEscherAnchor() { + protected EscherRecord getEscherAnchor() { return _escherClientAnchor; } @@ -229,9 +253,6 @@ public final class HSSFClientAnchor extends HSSFAnchor implements ClientAnchor { * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. */ public void setAnchorType(int anchorType) { -// if (0 != anchorType && 2 != anchorType && 3 != anchorType){ -// throw new IllegalArgumentException("Anchor type of shape can take only such values: 0, 2, 3"); -// } _escherClientAnchor.setFlag(Integer.valueOf(anchorType).shortValue()); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java index 7537b6296a..c6cba8f72d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCombobox.java @@ -33,6 +33,8 @@ public class HSSFCombobox extends HSSFSimpleShape { public HSSFCombobox(HSSFShape parent, HSSFAnchor anchor) { super(parent, anchor); super.setShapeType(OBJECT_TYPE_COMBO_BOX); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); + cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX); } @Override diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 6c1fecbc3b..8ae7edbe73 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -62,6 +62,8 @@ public class HSSFComment extends HSSFTextbox implements Comment { //by default comments are hidden setVisible(false); setAuthor(""); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); + cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT); } protected HSSFComment(NoteRecord note, TextObjectRecord txo) { diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 9240998c20..152762ba4f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -66,10 +66,17 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { buildShapeTree(); } + /** + * used to clone patriarch + * + * create patriarch from existing one + * @param patriarch - copy all the shapes from this patriarch to new one + * @param sheet where must be located new patriarch + * @return new patriarch with copies of all shapes from the existing patriarch + */ static HSSFPatriarch createPatriarch(HSSFPatriarch patriarch, HSSFSheet sheet){ HSSFPatriarch newPatriarch = new HSSFPatriarch(sheet, new EscherAggregate()); newPatriarch.afterCreate(); - for (HSSFShape shape: patriarch.getChildren()){ HSSFShape newShape; if (shape instanceof HSSFShapeGroup){ @@ -80,15 +87,9 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { newPatriarch.onCreate(newShape); newPatriarch.addShape(newShape); } - return newPatriarch; } - /** - * remove first level shapes - * - * @param shape to be removed - */ public boolean removeShape(HSSFShape shape) { boolean isRemoved = _mainSpgrContainer.removeChildRecord(shape.getEscherContainer()); if (isRemoved){ @@ -152,6 +153,15 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { return shape; } + /** + * + * @param anchor the client anchor describes how this picture is + * attached to the sheet. + * @param pictureIndex the index of the picture in the workbook collection + * of pictures. + * + * @return newly created shape + */ public HSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) { return createPicture((HSSFClientAnchor) anchor, pictureIndex); } @@ -245,6 +255,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { /** * Total count of all children and their children's children. + * @return count of shapes including shapes inside shape groups */ public int countOfAllChildren() { int count = _shapes.size(); @@ -266,6 +277,9 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { _spgrRecord.setRectX2(x2); } + /** + * remove all shapes inside patriarch + */ public void clear() { ArrayList copy = new ArrayList(_shapes); for (HSSFShape shape: copy){ @@ -273,6 +287,9 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { } } + /** + * @return new unique shapeId + */ int newShapeId() { DrawingManager2 dm = _sheet.getWorkbook().getWorkbook().getDrawingManager(); EscherDgRecord dg = @@ -314,30 +331,18 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { return false; } - /** - * The top left x coordinate of this group. - */ public int getX1() { return _spgrRecord.getRectX1(); } - /** - * The top left y coordinate of this group. - */ public int getY1() { return _spgrRecord.getRectY1(); } - /** - * The bottom right x coordinate of this group. - */ public int getX2() { return _spgrRecord.getRectX2(); } - /** - * The bottom right y coordinate of this group. - */ public int getY2() { return _spgrRecord.getRectY2(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 2fa906f467..faffa20f01 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.ss.usermodel.Picture; @@ -67,6 +68,8 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { { super( parent, anchor ); super.setShapeType(OBJECT_TYPE_PICTURE); + CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); + cod.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE); } public int getPictureIndex() diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java index 0d15030c96..98936f90cb 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java @@ -117,6 +117,9 @@ public class HSSFPolygon extends HSSFSimpleShape { patriarch._getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildById(EscherClientDataRecord.RECORD_ID)); } + /** + * @return array of x coordinates + */ public int[] getXPoints() { EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); if (null == verticesProp){ @@ -131,6 +134,9 @@ public class HSSFPolygon extends HSSFSimpleShape { return array; } + /** + * @return array of y coordinates + */ public int[] getYPoints() { EscherArrayProperty verticesProp = getOptRecord().lookup(EscherProperties.GEOMETRY__VERTICES); if (null == verticesProp){ @@ -145,6 +151,10 @@ public class HSSFPolygon extends HSSFSimpleShape { return array; } + /** + * @param xPoints - array of x coordinates + * @param yPoints - array of y coordinates + */ public void setPoints(int[] xPoints, int[] yPoints) { if (xPoints.length != yPoints.length){ System.out.println("xPoint.length must be equal to yPoints.length"); @@ -189,7 +199,6 @@ public class HSSFPolygon extends HSSFSimpleShape { /** * Defines the width and height of the points in the polygon - * * @param width * @param height */ @@ -198,11 +207,17 @@ public class HSSFPolygon extends HSSFSimpleShape { setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, height)); } + /** + * @return shape width + */ public int getDrawAreaWidth() { EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__RIGHT); return property == null ? 100: property.getPropertyValue(); } + /** + * @return shape height + */ public int getDrawAreaHeight() { EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.GEOMETRY__BOTTOM); return property == null ? 100: property.getPropertyValue(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index dd8a586f73..daceee09a2 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -65,6 +65,11 @@ public abstract class HSSFShape { public final static int NO_FILLHITTEST_TRUE = 0x00110000; public final static int NO_FILLHITTEST_FALSE = 0x00010000; + /** + * creates shapes from existing file + * @param spContainer + * @param objRecord + */ public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord) { this._escherContainer = spContainer; this._objRecord = objRecord; @@ -90,13 +95,19 @@ public abstract class HSSFShape { protected abstract void afterRemove(HSSFPatriarch patriarch); + /** + * @param shapeId - global shapeId which must be set to EscherSpRecord + */ void setShapeId(int shapeId){ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); spRecord.setShapeId(shapeId); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0); cod.setObjectId((short) (shapeId%1024)); } - + + /** + * @return global shapeId(from EscherSpRecord) + */ int getShapeId(){ return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId(); } @@ -280,7 +291,7 @@ public abstract class HSSFShape { } /** - * Sets whether this shape is filled or transparent. + * @param noFill sets whether this shape is filled or transparent. */ public void setNoFill(boolean noFill) { setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, noFill ? NO_FILLHITTEST_TRUE : NO_FILLHITTEST_FALSE)); @@ -289,7 +300,10 @@ public abstract class HSSFShape { protected void setPropertyValue(EscherProperty property){ _optRecord.setEscherProperty(property); } - + + /** + * @param value specifies whether this shape is vertically flipped. + */ public void setFlipVertical(boolean value){ EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); if (value){ @@ -299,6 +313,9 @@ public abstract class HSSFShape { } } + /** + * @param value specifies whether this shape is horizontally flipped. + */ public void setFlipHorizontal(boolean value){ EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); if (value){ @@ -307,17 +324,26 @@ public abstract class HSSFShape { sp.setFlags(sp.getFlags() & (Integer.MAX_VALUE - EscherSpRecord.FLAG_FLIPHORIZ)); } } - + + /** + * @return whether this shape is vertically flipped. + */ public boolean isFlipVertical(){ EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); return (sp.getFlags() & EscherSpRecord.FLAG_FLIPVERT) != 0; } + /** + * @return whether this shape is horizontally flipped. + */ public boolean isFlipHorizontal(){ EscherSpRecord sp = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); return (sp.getFlags() & EscherSpRecord.FLAG_FLIPHORIZ) != 0; } - + + /** + * @return the rotation, in degrees, that is applied to a shape. + */ public int getRotationDegree(){ ByteArrayOutputStream bos = new ByteArrayOutputStream(); EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.TRANSFORM__ROTATION); @@ -333,6 +359,14 @@ public abstract class HSSFShape { } } + /** + * specifies the rotation, in degrees, that is applied to a shape. + * Positive values specify rotation in the clockwise direction. + * Negative values specify rotation in the counterclockwise direction. + * Rotation occurs around the center of the shape. + * The default value for this property is 0x00000000 + * @param value + */ public void setRotationDegree(short value){ setPropertyValue(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION , (value << 16))); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java index d7cb533cd2..c240519eff 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java @@ -43,14 +43,31 @@ public interface HSSFShapeContainer extends Iterable void setCoordinates( int x1, int y1, int x2, int y2 ); void clear(); - + + /** + *@return The top left x coordinate of this group. + */ public int getX1(); + /** + *@return The top left y coordinate of this group. + */ public int getY1(); + /** + *@return The bottom right x coordinate of this group. + */ public int getX2(); + /** + * @return The bottom right y coordinate of this group. + */ public int getY2(); + /** + * remove first level shapes + * @param shape to be removed + * @return true if shape is removed else return false + */ public boolean removeShape(HSSFShape shape); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java index 42aef17569..7955da3bcc 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java @@ -19,11 +19,8 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.*; -import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; import org.apache.poi.poifs.filesystem.DirectoryNode; -import java.lang.reflect.Constructor; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -34,43 +31,19 @@ import java.util.Map; */ public class HSSFShapeFactory { - private static final Map shapeTypeToClass = new HashMap(HSSFShapeType.values().length); - private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass); - - static { - for (HSSFShapeType type : HSSFShapeType.values()) { - shapeTypeToClass.put(type.getType(), type); - } - } - - private static class ReflectionConstructorShapeCreator { - - private final Map shapeTypeToClass; - - private ReflectionConstructorShapeCreator(Map shapeTypeToClass) { - this.shapeTypeToClass = shapeTypeToClass; - } - - public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord) { - if (!shapeTypeToClass.containsKey(type)) { - return new HSSFUnknownShape(spContainer, objRecord); - } - Class clazz = shapeTypeToClass.get(type).getShape(); - if (null == clazz) { - //System.out.println("No class attached to shape type: "+type); - return new HSSFUnknownShape(spContainer, objRecord); - } - try { - Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class}); - return (HSSFShape) constructor.newInstance(spContainer, objRecord); - } catch (NoSuchMethodException e) { - throw new IllegalStateException(clazz.getName() + " doesn't have required for shapes constructor"); - } catch (Exception e) { - throw new IllegalStateException("Couldn't create new instance of " + clazz.getName()); - } - } - } + private final static short OBJECT_TYPE_LINE = 1; + private final static short OBJECT_TYPE_RECTANGLE = 2; + private final static short OBJECT_TYPE_OVAL = 3; + private final static short OBJECT_TYPE_ARC = 4; + private final static short OBJECT_TYPE_PICTURE = 8; + /** + * build shape tree from escher container + * @param container root escher container from which escher records must be taken + * @param agg - EscherAggregate + * @param out - shape container to which shapes must be added + * @param root - node to create HSSFObjectData shapes + */ public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) { if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { ObjRecord obj = null; @@ -83,24 +56,18 @@ public class HSSFShapeFactory { // skip the first child record, it is group descriptor for (int i = 0; i < children.size(); i++) { EscherContainerRecord spContainer = children.get(i); - if (i == 0) { - EscherSpgrRecord spgr = (EscherSpgrRecord) spContainer.getChildById(EscherSpgrRecord.RECORD_ID); - } else { + if (i != 0) { createShapeTree(spContainer, agg, group, root); } } out.addShape(group); } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) { Map shapeToObj = agg.getShapeToObjMapping(); - EscherSpRecord spRecord = null; ObjRecord objRecord = null; TextObjectRecord txtRecord = null; for (EscherRecord record : container.getChildRecords()) { switch (record.getRecordId()) { - case EscherSpRecord.RECORD_ID: - spRecord = (EscherSpRecord) record; - break; case EscherClientDataRecord.RECORD_ID: objRecord = (ObjRecord) shapeToObj.get(record); break; @@ -115,7 +82,7 @@ public class HSSFShapeFactory { return; } CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0); - HSSFShape shape = null; + HSSFShape shape; switch (cmo.getObjectType()) { case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE: shape = new HSSFPicture(container, objRecord); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 4ee6995620..a80e5bb98c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -341,7 +341,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { throw new IllegalStateException("Use method cloneShape(HSSFPatriarch patriarch)"); } - public HSSFShape cloneShape(HSSFPatriarch patriarch) { + protected HSSFShape cloneShape(HSSFPatriarch patriarch) { EscherContainerRecord spgrContainer = new EscherContainerRecord(); spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER); spgrContainer.setOptions((short) 0x000F); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java index 48cacfc3d7..3f14ecdf4e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSimpleShape.java @@ -19,12 +19,9 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.*; -import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType; +import org.apache.poi.hssf.usermodel.drawing.ShapeTypes; import org.apache.poi.ss.usermodel.RichTextString; -import java.util.HashMap; -import java.util.Map; - /** * Represents a simple shape such as a line, rectangle or oval. * @@ -35,14 +32,15 @@ public class HSSFSimpleShape extends HSSFShape // The commented out ones haven't been tested yet or aren't supported // by HSSFSimpleShape. - public final static short OBJECT_TYPE_LINE = 1; - public final static short OBJECT_TYPE_RECTANGLE = 2; - public final static short OBJECT_TYPE_OVAL = 3; - public final static short OBJECT_TYPE_ARC = 4; -// public final static short OBJECT_TYPE_CHART = 5; + public final static short OBJECT_TYPE_LINE = ShapeTypes.Line; + public final static short OBJECT_TYPE_RECTANGLE = ShapeTypes.Rectangle; + public final static short OBJECT_TYPE_OVAL = ShapeTypes.Ellipse; + public final static short OBJECT_TYPE_ARC = ShapeTypes.Arc; + // public final static short OBJECT_TYPE_CHART = 5; // public final static short OBJECT_TYPE_TEXT = 6; // public final static short OBJECT_TYPE_BUTTON = 7; - public final static short OBJECT_TYPE_PICTURE = 8; + public final static short OBJECT_TYPE_PICTURE = ShapeTypes.PictureFrame; + // public final static short OBJECT_TYPE_POLYGON = 9; // public final static short OBJECT_TYPE_CHECKBOX = 11; // public final static short OBJECT_TYPE_OPTION_BUTTON = 12; @@ -53,26 +51,16 @@ public class HSSFSimpleShape extends HSSFShape // public final static short OBJECT_TYPE_SCROLL_BAR = 17; // public final static short OBJECT_TYPE_LIST_BOX = 18; // public final static short OBJECT_TYPE_GROUP_BOX = 19; - public final static short OBJECT_TYPE_COMBO_BOX = 20; - public final static short OBJECT_TYPE_COMMENT = 25; + public final static short OBJECT_TYPE_COMBO_BOX = ShapeTypes.HostControl; + public final static short OBJECT_TYPE_COMMENT = ShapeTypes.TextBox; public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; public final static int WRAP_SQUARE = 0; public final static int WRAP_BY_POINTS = 1; public final static int WRAP_NONE = 2; - private static final Map objTypeToShapeType = new HashMap(); - private TextObjectRecord _textObjectRecord; - static { - objTypeToShapeType.put(OBJECT_TYPE_RECTANGLE, HSSFShapeType.RECTANGLE.getType()); - objTypeToShapeType.put(OBJECT_TYPE_PICTURE, HSSFShapeType.PICTURE.getType()); - objTypeToShapeType.put(OBJECT_TYPE_LINE, HSSFShapeType.LINE.getType()); - objTypeToShapeType.put(OBJECT_TYPE_OVAL, HSSFShapeType.OVAL.getType()); - objTypeToShapeType.put(OBJECT_TYPE_ARC, HSSFShapeType.ARC.getType()); - } - public HSSFSimpleShape(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord) { super(spContainer, objRecord); this._textObjectRecord = textObjectRecord; @@ -224,28 +212,8 @@ public class HSSFSimpleShape extends HSSFShape * @see #OBJECT_TYPE_COMMENT */ public int getShapeType() { - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); - return cod.getObjectType(); - } - - /** - * Sets the shape types. - * - * @param shapeType One of the OBJECT_TYPE_* constants. - * - * @see #OBJECT_TYPE_LINE - * @see #OBJECT_TYPE_OVAL - * @see #OBJECT_TYPE_RECTANGLE - */ - public void setShapeType( int shapeType ){ - CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); - cod.setObjectType((short) shapeType); EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - if (null == objTypeToShapeType.get((short)shapeType)){ - System.out.println("Unknown shape type: "+shapeType); - return; - } - spRecord.setShapeType(objTypeToShapeType.get((short) shapeType)); + return spRecord.getShapeType(); } public int getWrapText(){ @@ -259,12 +227,12 @@ public class HSSFSimpleShape extends HSSFShape /** * @see org.apache.poi.hssf.usermodel.drawing.ShapeTypes - * @param value + * @param value - shapeType */ - public void setAdditionalShapeType(short value){ + public void setShapeType(int value){ CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); cod.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING); EscherSpRecord spRecord = getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - spRecord.setShapeType(value); + spRecord.setShapeType((short) value); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java deleted file mode 100644 index e28d3f8cc1..0000000000 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.hssf.usermodel; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.hssf.record.ObjRecord; - -/** - * @author Evgeniy Berlog - * date: 05.06.12 - */ -public class HSSFUnknownShape extends HSSFShape { - - public HSSFUnknownShape(EscherRecord spContainer, ObjRecord objRecord) { - super((EscherContainerRecord) spContainer, objRecord); - } - - @Override - protected EscherContainerRecord createSpContainer() { - return null; - } - - @Override - protected ObjRecord createObjRecord() { - return null; - } - - @Override - protected void afterRemove(HSSFPatriarch patriarch) { - } - - @Override - void afterInsert(HSSFPatriarch patriarch) { - } - - @Override - protected HSSFShape cloneShape() { - return null; - } -} diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java index 6a1638335d..dc3711f507 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -412,19 +412,6 @@ public class TestDrawingShapes extends TestCase { assertEquals(agg.getShapeToObjMapping().size(), 2); } - public void testComboboxRecords(){ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - - HSSFCombobox combobox = new HSSFCombobox(null, new HSSFClientAnchor()); - HSSFTestHelper.setShapeId(combobox, 1024); - ComboboxShape comboboxShape = new ComboboxShape(combobox, 1024); - - assertTrue(Arrays.equals(comboboxShape.getSpContainer().serialize(), HSSFTestHelper.getEscherContainer(combobox).serialize())); - assertTrue(Arrays.equals(comboboxShape.getObjRecord().serialize(), HSSFTestHelper.getObjRecord(combobox).serialize())); - } - public void testRemoveShapes(){ HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(); diff --git a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java index 868848a0ed..bda65884cd 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java +++ b/src/testcases/org/apache/poi/hssf/model/TestHSSFAnchor.java @@ -151,9 +151,9 @@ public class TestHSSFAnchor extends TestCase { rectangle.setAnchor(anchor); - assertNotNull(anchor.getEscherAnchor()); + assertNotNull(HSSFTestHelper.getEscherAnchor(anchor)); assertNotNull(HSSFTestHelper.getEscherContainer(rectangle)); - assertTrue(anchor.getEscherAnchor().equals(HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherClientAnchorRecord.RECORD_ID))); + assertTrue(HSSFTestHelper.getEscherAnchor(anchor).equals(HSSFTestHelper.getEscherContainer(rectangle).getChildById(EscherClientAnchorRecord.RECORD_ID))); } public void testClientAnchorFromEscher(){ @@ -188,7 +188,7 @@ public class TestHSSFAnchor extends TestCase { public void testClientAnchorFromScratch(){ HSSFClientAnchor anchor = new HSSFClientAnchor(); - EscherClientAnchorRecord escher = (EscherClientAnchorRecord) anchor.getEscherAnchor(); + EscherClientAnchorRecord escher = (EscherClientAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor); anchor.setAnchor((short)11, 12, 13, 14, (short)15, 16, 17, 18); assertEquals(anchor.getCol1(), 11); @@ -254,7 +254,7 @@ public class TestHSSFAnchor extends TestCase { public void testChildAnchorFromScratch(){ HSSFChildAnchor anchor = new HSSFChildAnchor(); - EscherChildAnchorRecord escher = (EscherChildAnchorRecord) anchor.getEscherAnchor(); + EscherChildAnchorRecord escher = (EscherChildAnchorRecord) HSSFTestHelper.getEscherAnchor(anchor); anchor.setAnchor(11, 12, 13, 14); assertEquals(anchor.getDx1(), 11); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java index 3954688912..a2df1c841d 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java @@ -118,4 +118,8 @@ public class HSSFTestHelper { public static ObjRecord getObjRecord(HSSFShape shape){ return shape.getObjRecord(); } + + public static EscherRecord getEscherAnchor(HSSFAnchor anchor){ + return anchor.getEscherAnchor(); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java index caa038c217..6c0919894f 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -81,9 +81,6 @@ public class TestComment extends TestCase { expected = obj.serialize(); actual = objShape.serialize(); - assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); - TextObjectRecord tor = comment.getTextObjectRecord(); TextObjectRecord torShape = commentShape.getTextObjectRecord(); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java index 1b6f750ea1..1bbf69f9d4 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestText.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestText.java @@ -74,9 +74,6 @@ public class TestText extends TestCase { expected = obj.serialize(); actual = objShape.serialize(); - assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); - TextObjectRecord tor = textbox.getTextObjectRecord(); TextObjectRecord torShape = textboxShape.getTextObjectRecord(); From effa9bbef0853d8e20a95ea75a5adfd210375d75 Mon Sep 17 00:00:00 2001 From: Evgeniy Berlog Date: Wed, 8 Aug 2012 19:41:14 +0000 Subject: [PATCH 31/32] added javadoc and code refactoring git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1370912 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/usermodel/HSSFComment.java | 4 +- .../poi/hssf/usermodel/HSSFPatriarch.java | 27 +++++++-- .../poi/hssf/usermodel/HSSFPicture.java | 14 ++--- .../apache/poi/hssf/usermodel/HSSFShape.java | 22 ++++++- .../poi/hssf/usermodel/HSSFShapeGroup.java | 44 +++++++------- .../ShapeTypes.java => HSSFShapeTypes.java} | 4 +- .../poi/hssf/usermodel/HSSFSimpleShape.java | 19 +++--- .../hssf/usermodel/drawing/HSSFShapeType.java | 60 ------------------- 8 files changed, 85 insertions(+), 109 deletions(-) rename src/java/org/apache/poi/hssf/usermodel/{drawing/ShapeTypes.java => HSSFShapeTypes.java} (99%) delete mode 100644 src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 8ae7edbe73..8f4795b9bc 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -233,14 +233,14 @@ public class HSSFComment extends HSSFTextbox implements Comment { public void setBackgroundImage(int pictureIndex){ setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__PATTERNTEXTURE, false, true, pictureIndex)); setPropertyValue(new EscherSimpleProperty( EscherProperties.FILL__FILLTYPE, false, false, FILL_TYPE_PICTURE)); - EscherBSERecord bse = _patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(pictureIndex); + EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(pictureIndex); bse.setRef(bse.getRef() + 1); } public void resetBackgroundImage(){ EscherSimpleProperty property = getOptRecord().lookup(EscherProperties.FILL__PATTERNTEXTURE); if (null != property){ - EscherBSERecord bse = _patriarch.getSheet().getWorkbook().getWorkbook().getBSERecord(property.getPropertyValue()); + EscherBSERecord bse = getPatriarch().getSheet().getWorkbook().getWorkbook().getBSERecord(property.getPropertyValue()); bse.setRef(bse.getRef() - 1); getOptRecord().removeEscherProperty(EscherProperties.FILL__PATTERNTEXTURE); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 152762ba4f..233a798dc7 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -90,6 +90,10 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { return newPatriarch; } + /** + * @param shape to be removed + * @return true of shape is removed + */ public boolean removeShape(HSSFShape shape) { boolean isRemoved = _mainSpgrContainer.removeChildRecord(shape.getEscherContainer()); if (isRemoved){ @@ -225,7 +229,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { } /** - * Returns a list of all shapes contained by the patriarch. + * Returns a unmodifiable list of all shapes contained by the patriarch. */ public List getChildren() { return Collections.unmodifiableList(_shapes); @@ -236,7 +240,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { */ @Internal public void addShape(HSSFShape shape) { - shape._patriarch = this; + shape.setPatriarch(this); _shapes.add(shape); } @@ -331,18 +335,30 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { return false; } + /** + * @return x coordinate of the left up corner + */ public int getX1() { return _spgrRecord.getRectX1(); } + /** + * @return y coordinate of the left up corner + */ public int getY1() { return _spgrRecord.getRectY1(); } + /** + * @return x coordinate of the right down corner + */ public int getX2() { return _spgrRecord.getRectX2(); } + /** + * @return y coordinate of the right down corner + */ public int getY2() { return _spgrRecord.getRectY2(); } @@ -377,6 +393,9 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { } + /** + * create shape tree from existing escher records tree + */ void buildShapeTree() { EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer(); if (dgContainer == null) { @@ -397,10 +416,10 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing { private void setFlipFlags(HSSFShape shape){ EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); - if (shape.anchor.isHorizontallyFlipped()) { + if (shape.getAnchor().isHorizontallyFlipped()) { sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ); } - if (shape.anchor.isVerticallyFlipped()) { + if (shape.getAnchor().isVerticallyFlipped()) { sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT); } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index faffa20f01..1f20d9f0fa 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -206,7 +206,7 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { private float getColumnWidthInPixels(int column){ - int cw = _patriarch.getSheet().getColumnWidth(column); + int cw = getPatriarch().getSheet().getColumnWidth(column); float px = getPixelWidth(column); return cw/px; @@ -214,18 +214,18 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { private float getRowHeightInPixels(int i){ - HSSFRow row = _patriarch.getSheet().getRow(i); + HSSFRow row = getPatriarch().getSheet().getRow(i); float height; if(row != null) height = row.getHeight(); - else height = _patriarch.getSheet().getDefaultRowHeight(); + else height = getPatriarch().getSheet().getDefaultRowHeight(); return height/PX_ROW; } private float getPixelWidth(int column){ - int def = _patriarch.getSheet().getDefaultColumnWidth()*256; - int cw = _patriarch.getSheet().getColumnWidth(column); + int def = getPatriarch().getSheet().getDefaultColumnWidth()*256; + int cw = getPatriarch().getSheet().getColumnWidth(column); return cw == def ? PX_DEFAULT : PX_MODIFIED; } @@ -236,7 +236,7 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { * @return image dimension */ public Dimension getImageDimension(){ - EscherBSERecord bse = _patriarch.getSheet()._book.getBSERecord(getPictureIndex()); + EscherBSERecord bse = getPatriarch().getSheet()._book.getBSERecord(getPictureIndex()); byte[] data = bse.getBlipRecord().getPicturedata(); int type = bse.getBlipTypeWin32(); return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type); @@ -248,7 +248,7 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { * @return picture data for this shape */ public HSSFPictureData getPictureData(){ - InternalWorkbook iwb = _patriarch.getSheet().getWorkbook().getWorkbook(); + InternalWorkbook iwb = getPatriarch().getSheet().getWorkbook().getWorkbook(); EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord(); return new HSSFPictureData(blipRecord); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java index daceee09a2..f20239567f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShape.java @@ -54,9 +54,9 @@ public abstract class HSSFShape { public static final int LINESTYLE_DEFAULT = LINESTYLE_NONE; // TODO - make all these fields private - HSSFShape parent; + private HSSFShape parent; HSSFAnchor anchor; - HSSFPatriarch _patriarch; + private HSSFPatriarch _patriarch; private final EscherContainerRecord _escherContainer; private final ObjRecord _objRecord; @@ -93,6 +93,12 @@ public abstract class HSSFShape { protected abstract ObjRecord createObjRecord(); + /** + * remove escher container from the patriarch.escherAggregate + * remove obj, textObj and note records if it's necessary + * in case of ShapeGroup remove all contained shapes + * @param patriarch + */ protected abstract void afterRemove(HSSFPatriarch patriarch); /** @@ -379,4 +385,16 @@ public abstract class HSSFShape { } protected abstract HSSFShape cloneShape(); + + protected void setPatriarch(HSSFPatriarch _patriarch) { + this._patriarch = _patriarch; + } + + public HSSFPatriarch getPatriarch() { + return _patriarch; + } + + protected void setParent(HSSFShape parent) { + this.parent = parent; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index a80e5bb98c..9f60d6eae4 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -129,18 +129,18 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer { for ( int i=0; i Date: Thu, 9 Aug 2012 14:43:41 +0000 Subject: [PATCH 32/32] increased jvm heap size for testing(Xmx256) git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1371230 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/build.xml b/build.xml index 4c519e1133..b90e1615c5 100644 --- a/build.xml +++ b/build.xml @@ -632,6 +632,7 @@ under the License. +