From: Andreas Beeker Date: Thu, 31 Dec 2015 22:10:17 +0000 (+0000) Subject: #56570 - RecordType has repeat by code type 3009 X-Git-Tag: REL_3_14_FINAL~124 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b9851d98b9e0ff3144b13ecb06a192a469960942;p=poi.git #56570 - RecordType has repeat by code type 3009 #58159 - getHeaderText() and getFooterText() duplicate text in sheet.getTextRuns() git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722476 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java b/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java index 75180c2d19..ec0cec8dc1 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java +++ b/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java @@ -16,13 +16,10 @@ ==================================================================== */ package org.apache.poi.hslf.examples; import java.io.FileInputStream; +import java.io.IOException; -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.hslf.record.InteractiveInfo; import org.apache.poi.hslf.record.InteractiveInfoAtom; -import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.hslf.usermodel.HSLFShape; import org.apache.poi.hslf.usermodel.HSLFSlide; import org.apache.poi.hslf.usermodel.HSLFSlideShow; @@ -30,12 +27,11 @@ import org.apache.poi.hslf.usermodel.HSLFSoundData; /** * For each slide iterate over shapes and found associated sound data. - * - * @author Yegor Kozlov */ public class SoundFinder { - public static void main(String[] args) throws Exception { - HSLFSlideShow ppt = new HSLFSlideShow(new FileInputStream(args[0])); + public static void main(String[] args) throws IOException { + FileInputStream fis = new FileInputStream(args[0]); + HSLFSlideShow ppt = new HSLFSlideShow(fis); HSLFSoundData[] sounds = ppt.getSoundData(); for (HSLFSlide slide : ppt.getSlides()) { @@ -49,6 +45,8 @@ public class SoundFinder { System.out.println(" " + sounds[soundRef].getSoundType()); } } + ppt.close(); + fis.close(); } /** @@ -59,19 +57,9 @@ public class SoundFinder { protected static int getSoundReference(HSLFShape shape){ int soundRef = -1; //dive into the shape container and search for InteractiveInfoAtom - EscherContainerRecord spContainer = shape.getSpContainer(); - for (EscherRecord obj : spContainer.getChildRecords()) { - if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) { - byte[] data = obj.serialize(); - for (Record record : Record.findChildRecords(data, 8, data.length - 8)) { - if (record instanceof InteractiveInfo) { - InteractiveInfoAtom info = ((InteractiveInfo)record).getInteractiveInfoAtom(); - if (info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) { - soundRef = info.getSoundRef(); - } - } - } - } + InteractiveInfoAtom info = shape.getClientDataRecord(RecordTypes.InteractiveInfo.typeID); + if (info != null && info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) { + soundRef = info.getSoundRef(); } return soundRef; } diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java index 28c1fa3f12..4433605f34 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java @@ -23,7 +23,7 @@ import java.awt.Rectangle; import java.io.FileOutputStream; import java.io.IOException; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; /** * How to set slide title diff --git a/src/java/org/apache/poi/ddf/EscherClientDataRecord.java b/src/java/org/apache/poi/ddf/EscherClientDataRecord.java index bea83a83cf..0b307ad532 100644 --- a/src/java/org/apache/poi/ddf/EscherClientDataRecord.java +++ b/src/java/org/apache/poi/ddf/EscherClientDataRecord.java @@ -76,7 +76,7 @@ public class EscherClientDataRecord public String toString() { String nl = System.getProperty("line.separator"); - String extraData = HexDump.dump(this.remainingData, 0, 0); + String extraData = HexDump.dump(getRemainingData(), 0, 0); return getClass().getName() + ":" + nl + " RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl + " Version: 0x" + HexDump.toHex(getVersion()) + nl + @@ -88,7 +88,7 @@ public class EscherClientDataRecord @Override public String toXml(String tab) { - String extraData = HexDump.dump(this.remainingData, 0, 0).trim(); + String extraData = HexDump.dump(getRemainingData(), 0, 0).trim(); StringBuilder builder = new StringBuilder(); builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance()))) diff --git a/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java b/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java index 76ae92de70..3bcedbe850 100644 --- a/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java +++ b/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java @@ -33,7 +33,12 @@ public class DrawMasterSheet extends DrawSheet { * for instance, slide masters and layouts don't display placeholders */ @Override - protected boolean canDraw(Shape shape){ - return !(shape instanceof SimpleShape) || !((SimpleShape)shape).isPlaceholder(); + protected boolean canDraw(Shape shape) { + if (shape instanceof SimpleShape) { + Placeholder ph = ((SimpleShape)shape).getPlaceholder(); + return ph == null; + } else { + return true; + } } } diff --git a/src/java/org/apache/poi/sl/usermodel/Placeholder.java b/src/java/org/apache/poi/sl/usermodel/Placeholder.java new file mode 100644 index 0000000000..a3bc9c7c88 --- /dev/null +++ b/src/java/org/apache/poi/sl/usermodel/Placeholder.java @@ -0,0 +1,138 @@ +/* ==================================================================== + 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.sl.usermodel; + +public enum Placeholder { + /** + * No placeholder shape. + */ + NONE(0,0,0,0,0), + /** + * Title text placeholder shape. + */ + TITLE(13,1,1,1,1), + /** + * Body text placeholder shape. + */ + BODY(14,2,12,6,2), + /** + * Center title text placeholder shape. + */ + CENTERED_TITLE(15,3,3,3,3), + /** + * Sub-title text placeholder shape. + */ + SUBTITLE(16,4,4,4,4), + /** + * Date placeholder shape. + */ + DATETIME(7,7,7,7,5), + /** + * Slide number placeholder shape. + */ + SLIDE_NUMBER(8,8,8,8,6), + /** + * Footer placeholder shape. + */ + FOOTER(9,9,9,9,7), + /** + * Header placeholder shape. + */ + HEADER(10,10,10,10,8), + /** + * Object placeholder shape. + */ + CONTENT(19,19,19,19,9), + /** + * Graph object placeholder shape. + */ + CHART(20,20,20,20,10), + /** + * Table object placeholder shape. + */ + TABLE(21,21,21,21,11), + /** + * Clipart object placeholder shape. + */ + CLIP_ART(22,22,22,22,12), + /** + * Organization chart object placeholder shape. + */ + DGM(23,23,23,23,13), + /** + * Media object placeholder shape. + */ + MEDIA(24,24,24,24,14), + /** + * Slide image placeholder shape. + */ + SLIDE_IMAGE(11,11,11,5,15), + /** + * Picture object placeholder shape. + */ + PICTURE(26,26,26,26,16), + /** + * Vertical object placeholder shape. + */ + VERTICAL_OBJECT(25,25,25,25,-2), + /** + * Vertical title text placeholder shape. + */ + VERTICAL_TEXT_TITLE(17,17,17,17,-2), + /** + * Vertical body text placeholder shape. + */ + VERTICAL_TEXT_BODY(18,18,18,18,-2) + ; + + public final int nativeSlideId; + public final int nativeSlideMasterId; + public final int nativeNotesId; + public final int nativeNotesMasterId; + public final int ooxmlId; + + Placeholder(int nativeSlideId, int nativeSlideMasterId, int nativeNotesId, int nativeNotesMasterId, int ooxmlId) { + this.nativeSlideId = nativeSlideId; + this.nativeSlideMasterId = nativeSlideMasterId; + this.nativeNotesId = nativeNotesId; + this.nativeNotesMasterId = nativeNotesMasterId; + this.ooxmlId = ooxmlId; + } + + public static Placeholder lookupNative(int nativeId) { + for (Placeholder ph : values()) { + if (ph.nativeSlideId == nativeId || + ph.nativeSlideMasterId == nativeId || + ph.nativeNotesId == nativeId || + ph.nativeNotesMasterId == nativeId + ) { + return ph; + } + } + return null; + } + + public static Placeholder lookupOoxml(int ooxmlId) { + for (Placeholder ph : values()) { + if (ph.ooxmlId == ooxmlId) { + return ph; + } + } + return null; + } +} \ No newline at end of file diff --git a/src/java/org/apache/poi/sl/usermodel/SimpleShape.java b/src/java/org/apache/poi/sl/usermodel/SimpleShape.java index 8ed151b496..53ee6de529 100644 --- a/src/java/org/apache/poi/sl/usermodel/SimpleShape.java +++ b/src/java/org/apache/poi/sl/usermodel/SimpleShape.java @@ -28,25 +28,6 @@ public interface SimpleShape< P extends TextParagraph > extends Shape, IAdjustableShape, PlaceableShape { - enum Placeholder { - TITLE, - BODY, - CENTERED_TITLE, - SUBTITLE, - DATETIME, - SLIDE_NUMBER, - FOOTER, - HEADER, - CONTENT, - CHART, - TABLE, - CLIP_ART, - DGM, - MEDIA, - SLIDE_IMAGE, - PICTURE - } - FillStyle getFillStyle(); LineDecoration getLineDecoration(); @@ -69,7 +50,20 @@ public interface SimpleShape< ShapeType getShapeType(); void setShapeType(ShapeType type); - boolean isPlaceholder(); + /** + * @return the placeholder or null if none is assigned + * @see #setPlaceholder(Placeholder) + */ + Placeholder getPlaceholder(); + + /** + * Specifies that the corresponding shape should be represented by the generating application + * as a placeholder. When a shape is considered a placeholder by the generating application + * it can have special properties to alert the user that they may enter content into the shape. + * + * @param placeholder the placeholder or null to remove the reference to the placeholder + */ + void setPlaceholder(Placeholder placeholder); Shadow getShadow(); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java index 6dbdf2d4f1..290b5f4945 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java @@ -21,11 +21,13 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.geom.Rectangle2D; +import org.apache.poi.POIXMLException; import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.usermodel.Background; import org.apache.poi.sl.usermodel.ColorStyle; import org.apache.poi.sl.usermodel.FillStyle; import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground; @@ -70,4 +72,10 @@ public class XSLFBackground extends XSLFSimpleShape protected CTTransform2D getXfrm() { return CTTransform2D.Factory.newInstance(); } + + @Override + public void setPlaceholder(Placeholder placeholder) { + // extending XSLFSimpleShape is a bit unlucky ... + throw new POIXMLException("Can't set a placeholder for a background"); + } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java index ef8a2adf0f..0ca895efa8 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java @@ -19,7 +19,9 @@ package org.apache.poi.xslf.usermodel; +import org.apache.poi.POIXMLException; import org.apache.poi.sl.usermodel.ConnectorShape; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.util.Beta; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; @@ -69,4 +71,8 @@ public class XSLFConnectorShape extends XSLFSimpleShape return null; } + @Override + public void setPlaceholder(Placeholder placeholder) { + throw new POIXMLException("A connector shape can't be a placeholder."); + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index 48c8babddf..b9d7e37f6b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.sl.usermodel.PictureShape; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.util.Beta; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; @@ -118,6 +119,12 @@ public class XSLFPictureShape extends XSLFSimpleShape } return _data; } + + @Override + public void setPlaceholder(Placeholder placeholder) { + super.setPlaceholder(placeholder); + } + /** * For an external linked picture, return the last-seen @@ -168,7 +175,6 @@ public class XSLFPictureShape extends XSLFSimpleShape return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR()); } - @SuppressWarnings("deprecation") @Override void copy(XSLFShape sh){ super.copy(sh); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index dc1ef5af2c..f25c9278ed 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -33,7 +33,7 @@ import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; import org.apache.poi.sl.usermodel.PlaceableShape; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.Shape; import org.apache.poi.util.Beta; import org.apache.poi.util.Internal; @@ -255,6 +255,14 @@ public abstract class XSLFShape implements Shape { return _ph; } + public Placeholder getPlaceholder() { + CTPlaceholder ph = getCTPlaceholder(); + if (ph == null || !ph.isSetType()) { + return null; + } + return Placeholder.lookupOoxml(ph.getType().intValue()); + } + /** * Specifies that the corresponding shape should be represented by the generating application * as a placeholder. When a shape is considered a placeholder by the generating application @@ -272,7 +280,7 @@ public abstract class XSLFShape implements Shape { if (nv.isSetPh()) nv.unsetPh(); _ph = null; } else { - nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1)); + nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ooxmlId)); } } @@ -442,7 +450,6 @@ public abstract class XSLFShape implements Shape { protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) { - @SuppressWarnings("deprecation") final CTGradientStop[] gs = gradFill.getGsLst().getGsArray(); Arrays.sort(gs, new Comparator() { diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index 5dac2181e9..e8fa1da034 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -42,8 +42,8 @@ import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.DrawPictureShape; import org.apache.poi.sl.draw.Drawable; import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.Sheet; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; import org.apache.poi.util.Beta; import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index c6bbb1ff04..8b92ec2316 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -34,6 +34,7 @@ import org.apache.poi.sl.usermodel.LineDecoration; import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.ShapeType; import org.apache.poi.sl.usermodel.SimpleShape; @@ -815,7 +816,6 @@ public abstract class XSLFSimpleShape extends XSLFShape return ph != null; } - @SuppressWarnings("deprecation") public Guide getAdjustValue(String name) { CTPresetGeometry2D prst = getSpPr().getPrstGeom(); if (prst.isSetAvLst()) { @@ -918,4 +918,9 @@ public abstract class XSLFSimpleShape extends XSLFShape } } } + + @Override + public void setPlaceholder(Placeholder placeholder) { + super.setPlaceholder(placeholder); + } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java index 4be19ea435..491062163c 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java @@ -27,7 +27,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.Drawable; import org.apache.poi.sl.usermodel.Notes; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.Slide; import org.apache.poi.util.Beta; import org.apache.xmlbeans.XmlException; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java index 95835e4952..1d49b068e8 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java @@ -24,7 +24,7 @@ import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.sl.usermodel.MasterSheet; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.util.Beta; import org.apache.poi.util.Internal; import org.apache.xmlbeans.XmlException; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java index cf45bf7446..34d282cd07 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java @@ -27,7 +27,7 @@ import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.sl.usermodel.MasterSheet; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.util.Beta; import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java index 4a1856d7fd..d78749c750 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java @@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException; import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.DrawTextShape; import org.apache.poi.sl.usermodel.Insets2D; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.TextShape; import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.util.Beta; @@ -54,7 +55,6 @@ public abstract class XSLFTextShape extends XSLFSimpleShape implements TextShape { private final List _paragraphs; - @SuppressWarnings("deprecation") /*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) { super(shape, sheet); @@ -497,13 +497,13 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public void setPlaceholder(Placeholder placeholder) { super.setPlaceholder(placeholder); } - + public Placeholder getTextType(){ CTPlaceholder ph = getCTPlaceholder(); if (ph == null) return null; int val = ph.getType().intValue(); - return Placeholder.values()[val - 1]; + return Placeholder.lookupOoxml(val); } @Override diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java index 02fac93bc8..ae18fc70c2 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java @@ -22,7 +22,7 @@ import static org.junit.Assert.assertNull; import java.io.IOException; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.xslf.XSLFTestDataSamples; import org.junit.Test; diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java index 452f22ebcb..9b6f448954 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java @@ -28,7 +28,7 @@ import java.io.IOException; import java.util.List; import org.apache.poi.sl.draw.geom.TestPresetGeometries; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; import org.apache.poi.util.Units; diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java index cee11e541a..15352b448b 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java @@ -21,7 +21,7 @@ import static org.junit.Assert.assertNull; import java.io.IOException; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.junit.Test; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java index c8a1aeebd5..a87a9cb555 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java @@ -31,7 +31,7 @@ import java.util.List; import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.usermodel.HSLFTextShape; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.sl.usermodel.SlideShowFactory; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java b/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java index 5a5f82d165..cf6f6bc412 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java @@ -122,7 +122,7 @@ public final class PPTXMLDump { pos += LittleEndian.INT_SIZE; //get name of the record by type - String recname = RecordTypes.recordName(type); + String recname = RecordTypes.forTypeID(type).name(); write(out, "<"+recname + " info=\""+info+"\" type=\""+type+"\" size=\""+size+"\" offset=\""+(pos-8)+"\"", padding); if (hexHeader){ out.write(" header=\""); diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java index 91d6086b1b..90f404b1eb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java @@ -79,7 +79,7 @@ public final class SLWTListing { for(int k=0; k it = spContainer.getChildIterator(); it.hasNext();) { - EscherRecord obj = it.next(); - if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) { - EscherClientDataRecord clientRecord = (EscherClientDataRecord)obj; - byte[] recdata = clientRecord.getRemainingData(); - LittleEndian.putInt(recdata, 8, idx); - } + public void setActiveXIndex(int idx) { + ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID); + if (oe == null) { + throw new HSLFException("OEShapeAtom for ActiveX doesn't exist"); } + oe.setExObjIdRef(idx); } public int getControlIndex(){ int idx = -1; - OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID); - if(oe != null) idx = oe.getOptions(); + ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID); + if(oe != null) idx = oe.getExObjIdRef(); return idx; } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java index d4da2a3101..5650b2b2d8 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java @@ -17,14 +17,24 @@ package org.apache.poi.hslf.model; -import java.io.ByteArrayOutputStream; - -import org.apache.poi.ddf.EscherClientDataRecord; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.record.*; -import org.apache.poi.hslf.usermodel.*; +import org.apache.poi.hslf.record.AnimationInfo; +import org.apache.poi.hslf.record.AnimationInfoAtom; +import org.apache.poi.hslf.record.ExMCIMovie; +import org.apache.poi.hslf.record.ExObjList; +import org.apache.poi.hslf.record.ExObjRefAtom; +import org.apache.poi.hslf.record.ExVideoContainer; +import org.apache.poi.hslf.record.HSLFEscherClientDataRecord; +import org.apache.poi.hslf.record.InteractiveInfo; +import org.apache.poi.hslf.record.InteractiveInfoAtom; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordTypes; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFPictureShape; +import org.apache.poi.hslf.usermodel.HSLFShape; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextParagraph; import org.apache.poi.sl.usermodel.ShapeContainer; /** @@ -82,11 +92,7 @@ public final class MovieShape extends HSLFPictureShape { setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x1000100); setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x10001); - EscherClientDataRecord cldata = new EscherClientDataRecord(); - cldata.setOptions((short)0xF); - _escherContainer.addChildRecord(cldata); - - OEShapeAtom oe = new OEShapeAtom(); + ExObjRefAtom oe = new ExObjRefAtom(); InteractiveInfo info = new InteractiveInfo(); InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom(); infoAtom.setAction(InteractiveInfoAtom.ACTION_MEDIA); @@ -96,16 +102,10 @@ public final class MovieShape extends HSLFPictureShape { AnimationInfoAtom anAtom = an.getAnimationInfoAtom(); anAtom.setFlag(AnimationInfoAtom.Automatic, true); - //convert hslf into ddf - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - oe.writeOut(out); - an.writeOut(out); - info.writeOut(out); - } catch(Exception e){ - throw new HSLFException(e); - } - cldata.setRemainingData(out.toByteArray()); + HSLFEscherClientDataRecord cldata = getClientData(true); + cldata.addChild(oe); + cldata.addChild(an); + cldata.addChild(info); return _escherContainer; } @@ -117,8 +117,8 @@ public final class MovieShape extends HSLFPictureShape { * @param idx the index of the movie */ public void setMovieIndex(int idx){ - OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID); - oe.setOptions(idx); + ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID); + oe.setExObjIdRef(idx); AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID); if(an != null) { @@ -135,7 +135,6 @@ public final class MovieShape extends HSLFPictureShape { AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID); if(an != null){ an.getAnimationInfoAtom().setFlag(AnimationInfoAtom.Automatic, flag); - updateClientData(); } } @@ -150,13 +149,16 @@ public final class MovieShape extends HSLFPictureShape { /** * @return UNC or local path to a video file */ + @SuppressWarnings("resource") public String getPath(){ - OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID); - int idx = oe.getOptions(); + ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID); + int idx = oe.getExObjIdRef(); HSLFSlideShow ppt = getSheet().getSlideShow(); ExObjList lst = (ExObjList)ppt.getDocumentRecord().findFirstOfType(RecordTypes.ExObjList.typeID); - if(lst == null) return null; + if(lst == null) { + return null; + } Record[] r = lst.getChildRecords(); for (int i = 0; i < r.length; i++) { diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java index c61c5ce5ac..c0e5948d77 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java @@ -17,14 +17,22 @@ package org.apache.poi.hslf.model; -import org.apache.poi.ddf.*; -import org.apache.poi.hslf.usermodel.*; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hslf.record.ExEmbed; import org.apache.poi.hslf.record.ExObjList; +import org.apache.poi.hslf.record.ExObjRefAtom; +import org.apache.poi.hslf.record.HSLFEscherClientDataRecord; import org.apache.poi.hslf.record.Record; -import org.apache.poi.hslf.record.ExEmbed; import org.apache.poi.hslf.record.RecordTypes; +import org.apache.poi.hslf.usermodel.HSLFObjectData; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFPictureShape; +import org.apache.poi.hslf.usermodel.HSLFShape; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextParagraph; import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogger; @@ -88,26 +96,19 @@ public final class OLEShape extends HSLFPictureShape { EscherSpRecord spRecord = ecr.getChildById(EscherSpRecord.RECORD_ID); spRecord.setFlags(spRecord.getFlags()|EscherSpRecord.FLAG_OLESHAPE); - EscherContainerRecord uerCont = ecr.getChildById((short)RecordTypes.EscherClientData); - if (uerCont == null) { - uerCont = new EscherContainerRecord(); - ecr.addChildRecord(uerCont); + HSLFEscherClientDataRecord cldata = getClientData(true); + ExObjRefAtom uer = null; + for (Record r : cldata.getHSLFChildRecords()) { + if (r.getRecordType() == RecordTypes.ExObjRefAtom.typeID) { + uer = (ExObjRefAtom)r; + break; + } } - uerCont.setRecordId((short)RecordTypes.EscherClientData); - uerCont.setVersion((short)0x000F); // yes, we are still a container ... - - UnknownEscherRecord uer = uerCont.getChildById((short)RecordTypes.ExObjRefAtom.typeID); if (uer == null) { - uer = new UnknownEscherRecord(); - uerCont.addChildRecord(uer); + uer = new ExObjRefAtom(); + cldata.addChild(uer); } - - byte uerData[] = new byte[12]; - LittleEndian.putShort( uerData, 0, (short)0 ); // options = 0 - LittleEndian.putShort( uerData, 2, (short)RecordTypes.ExObjRefAtom.typeID); // recordId - LittleEndian.putInt( uerData, 4, 4 ); // remaining bytes - LittleEndian.putInt( uerData, 8, objectId ); // the data - uer.fillFields(uerData, 0, null); + uer.setExObjIdRef(objectId); } @@ -116,6 +117,7 @@ public final class OLEShape extends HSLFPictureShape { * * @return the unique identifier for the OLE object */ + @SuppressWarnings("resource") public HSLFObjectData getObjectData(){ HSLFSlideShow ppt = getSheet().getSlideShow(); HSLFObjectData[] ole = ppt.getEmbeddedObjects(); @@ -153,6 +155,7 @@ public final class OLEShape extends HSLFPictureShape { * 6. MetaFile( 4033), optional *

*/ + @SuppressWarnings("resource") public ExEmbed getExEmbed(){ if(_exEmbed == null){ HSLFSlideShow ppt = getSheet().getSlideShow(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java new file mode 100644 index 0000000000..fa362c8dd0 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java @@ -0,0 +1,94 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import org.apache.poi.util.LittleEndian; +import java.io.IOException; +import java.io.OutputStream; + +/** + * ExObjRefAtom (3009). + *

+ * An atom record that specifies a reference to an external object. + *

+ */ + +public final class ExObjRefAtom extends RecordAtom { + private byte[] _header; + + /** + * A 4-byte unsigned integer that specifies a reference to an external object. + * It MUST be equal to the value of the exObjId field of an ExMediaAtom record + * or the value of the exObjId field of an ExOleObjAtom record. + */ + private int exObjIdRef; + + /** + * Create a new instance of ExObjRefAtom + */ + public ExObjRefAtom() { + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)getRecordType()); + LittleEndian.putInt(_header, 4, 4); + exObjIdRef = 0; + } + + /** + * Build an instance of ExObjRefAtom from on-disk data + * + * @param source the source data as a byte array. + * @param start the start offset into the byte array. + * @param len the length of the slice in the byte array. + */ + protected ExObjRefAtom(byte[] source, int start, int len) { + _header = new byte[8]; + int offset = start; + System.arraycopy(source,start,_header,0,8); + offset += _header.length; + exObjIdRef = (int)LittleEndian.getUInt(source, offset); + } + + /** + * @return type of this record {@link RecordTypes#ExObjRefAtom}. + */ + public long getRecordType() { + return RecordTypes.ExObjRefAtom.typeID; + } + + public int getExObjIdRef(){ + return exObjIdRef; + } + + public void setExObjIdRef(int id){ + exObjIdRef = id; + } + + /** + * Write the contents of the record back, so it can be written + * to disk + */ + public void writeOut(OutputStream out) throws IOException { + out.write(_header); + + byte[] recdata = new byte[4]; + LittleEndian.putUInt(recdata, 0, exObjIdRef); + + out.write(recdata); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java new file mode 100644 index 0000000000..e6a2cdcacf --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java @@ -0,0 +1,120 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.record; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherRecordFactory; +import org.apache.poi.ddf.EscherSerializationListener; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.util.LittleEndian; + +/** + * An atom record that specifies whether a shape is a placeholder shape. + * The number, position, and type of placeholder shapes are determined by + * the slide layout as specified in the SlideAtom record. + * + * @since POI 3.14-Beta2 + */ +public class HSLFEscherClientDataRecord extends EscherClientDataRecord { + + private final List _childRecords = new ArrayList(); + + public List getHSLFChildRecords() { + return _childRecords; + } + + public void removeChild(Class childClass) { + Iterator iter = _childRecords.iterator(); + while (iter.hasNext()) { + if (childClass.isInstance(iter.next())) { + iter.remove(); + } + } + } + + public void addChild(Record childRecord) { + _childRecords.add(childRecord); + } + + @Override + public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { + int bytesRemaining = readHeader( data, offset ); + byte remainingData[] = new byte[bytesRemaining]; + System.arraycopy(data, offset+8, remainingData, 0, bytesRemaining); + setRemainingData(remainingData); + return bytesRemaining + 8; + } + + @Override + public int serialize(int offset, byte[] data, EscherSerializationListener listener) { + listener.beforeRecordSerialize( offset, getRecordId(), this ); + + LittleEndian.putShort(data, offset, getOptions()); + LittleEndian.putShort(data, offset+2, getRecordId()); + + byte childBytes[] = getRemainingData(); + + LittleEndian.putInt(data, offset+4, childBytes.length); + System.arraycopy(childBytes, 0, data, offset+8, childBytes.length); + int recordSize = 8+childBytes.length; + listener.afterRecordSerialize( offset+recordSize, getRecordId(), recordSize, this ); + return recordSize; + } + + @Override + public int getRecordSize() { + return 8 + getRemainingData().length; + } + + @Override + public byte[] getRemainingData() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + for (Record r : _childRecords) { + r.writeOut(bos); + } + } catch (IOException e) { + throw new HSLFException(e); + } + return bos.toByteArray(); + } + + @Override + public void setRemainingData( byte[] remainingData ) { + _childRecords.clear(); + int offset = 0; + while (offset < remainingData.length) { + Record r = Record.buildRecordAtOffset(remainingData, offset); + _childRecords.add(r); + long rlen = LittleEndian.getUInt(remainingData,offset+4); + offset += 8 + rlen; + } + } + + public String getRecordName() { + return "HSLFClientData"; + } + + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java index c985864f00..a37ea943c7 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java @@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndian; * @see EscherRecordFactory */ public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory { - private static Class[] escherRecordClasses = { EscherPlaceholder.class }; + private static Class[] escherRecordClasses = { EscherPlaceholder.class, HSLFEscherClientDataRecord.class }; private static Map> recordsMap = recordsToMap( escherRecordClasses ); @@ -65,6 +65,10 @@ public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory { } escherRecord.setRecordId(recordId); escherRecord.setOptions(options); + if (escherRecord instanceof EscherContainerRecord) { + ((EscherContainerRecord)escherRecord).fillFields(data, offset, this); + } + return escherRecord; } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java index 1d8d7df62f..54d5d86221 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java @@ -201,6 +201,7 @@ public final class OEPlaceholderAtom extends RecordAtom{ private int placementId; private int placeholderId; private int placeholderSize; + private short unusedShort = 0; /** @@ -227,8 +228,9 @@ public final class OEPlaceholderAtom extends RecordAtom{ offset += _header.length; placementId = LittleEndian.getInt(source, offset); offset += 4; - placeholderId = LittleEndian.getUnsignedByte(source, offset); offset++; - placeholderSize = LittleEndian.getUnsignedByte(source, offset); offset++; + placeholderId = LittleEndian.getUByte(source, offset); offset++; + placeholderSize = LittleEndian.getUByte(source, offset); offset++; + unusedShort = LittleEndian.getShort(source, offset); } /** @@ -322,6 +324,7 @@ public final class OEPlaceholderAtom extends RecordAtom{ LittleEndian.putInt(recdata, 0, placementId); recdata[4] = (byte)placeholderId; recdata[5] = (byte)placeholderSize; + LittleEndian.putShort(recdata, 6, unusedShort); out.write(recdata); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEShapeAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEShapeAtom.java deleted file mode 100644 index 00b873f6de..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/record/OEShapeAtom.java +++ /dev/null @@ -1,107 +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.hslf.record; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.poi.util.LittleEndian; - -/** - * Atom that contains information that describes shape client data. - * - * @author Yegor Kozlov - */ -public final class OEShapeAtom extends RecordAtom -{ - - /** - * Record header. - */ - private byte[] _header; - - /** - * record data - */ - private byte[] _recdata; - - /** - * Constructs a brand new link related atom record. - */ - public OEShapeAtom() { - _recdata = new byte[4]; - - _header = new byte[8]; - LittleEndian.putShort(_header, 2, (short)getRecordType()); - LittleEndian.putInt(_header, 4, _recdata.length); - } - - /** - * Constructs the link related atom record from its - * source data. - * - * @param source the source data as a byte array. - * @param start the start offset into the byte array. - * @param len the length of the slice in the byte array. - */ - protected OEShapeAtom(byte[] source, int start, int len) { - // Get the header - _header = new byte[8]; - System.arraycopy(source,start,_header,0,8); - - // Grab the record data - _recdata = new byte[len-8]; - System.arraycopy(source,start+8,_recdata,0,len-8); - } - - /** - * Gets the record type. - * @return the record type. - */ - public long getRecordType() { return RecordTypes.OEShapeAtom.typeID; } - - /** - * Write the contents of the record back, so it can be written - * to disk - * - * @param out the output stream to write to. - * @throws java.io.IOException if an error occurs. - */ - public void writeOut(OutputStream out) throws IOException { - out.write(_header); - out.write(_recdata); - } - - /** - * shape flags. - * - * @return shape flags. - */ - public int getOptions(){ - return LittleEndian.getInt(_recdata, 0); - } - - /** - * shape flags. - * - * @param id shape flags. - */ - public void setOptions(int id){ - LittleEndian.putInt(_recdata, 0, id); - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java index 637f9a8ab8..90b24ed9f2 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java @@ -20,7 +20,6 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -36,7 +35,6 @@ 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.ddf.UnknownEscherRecord; import org.apache.poi.sl.usermodel.ShapeType; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogger; @@ -57,7 +55,7 @@ public final class PPDrawing extends RecordAtom { private byte[] _header; private long _type; - private EscherRecord[] childRecords; + private final List childRecords = new ArrayList(); private EscherTextboxWrapper[] textboxWrappers; //cached EscherDgRecord @@ -66,7 +64,7 @@ public final class PPDrawing extends RecordAtom { /** * Get access to the underlying Escher Records */ - public EscherRecord[] getEscherRecords() { return childRecords; } + public List getEscherRecords() { return childRecords; } /** * Get access to the atoms inside Textboxes @@ -76,6 +74,20 @@ public final class PPDrawing extends RecordAtom { /* ******************** record stuff follows ********************** */ + /** + * Creates a new, empty, PPDrawing (typically for use with a new Slide + * or Notes) + */ + public PPDrawing() { + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 15); + LittleEndian.putUShort(_header, 2, RecordTypes.PPDrawing.typeID); + LittleEndian.putInt(_header, 4, 0); + + textboxWrappers = new EscherTextboxWrapper[]{}; + create(); + } + /** * Sets everything up, groks the escher etc */ @@ -93,12 +105,11 @@ public final class PPDrawing extends RecordAtom { // Build up a tree of Escher records contained within final DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory(); - final List escherChildren = new ArrayList(); - findEscherChildren(erf, contents, 8, len-8, escherChildren); - this.childRecords = escherChildren.toArray(new EscherRecord[escherChildren.size()]); + findEscherChildren(erf, contents, 8, len-8, childRecords); + EscherContainerRecord dgContainer = getDgContainer(); - if (1 == this.childRecords.length && (short)RecordTypes.EscherDgContainer == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) { - this.textboxWrappers = findInDgContainer((EscherContainerRecord) this.childRecords[0]); + if (dgContainer != null) { + textboxWrappers = findInDgContainer(dgContainer); } else { // Find and EscherTextboxRecord's, and wrap them up final List textboxes = new ArrayList(); @@ -108,15 +119,15 @@ public final class PPDrawing extends RecordAtom { } private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord dgContainer) { final List found = new LinkedList(); - final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer); - final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer); + final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer); + final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer); for (EscherContainerRecord spContainer : spContainers) { - StyleTextProp9Atom nineAtom = findInSpContainer(spContainer); - EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherSp, spContainer); - EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherClientTextbox, spContainer); + EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType(RecordTypes.EscherSp, spContainer); + EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType(RecordTypes.EscherClientTextbox, spContainer); if (null == clientTextbox) { continue; } EscherTextboxWrapper w = new EscherTextboxWrapper(clientTextbox); + StyleTextProp9Atom nineAtom = findInSpContainer(spContainer); w.setStyleTextProp9Atom(nineAtom); if (null != sp) { w.setShapeId(sp.getShapeId()); @@ -127,16 +138,26 @@ public final class PPDrawing extends RecordAtom { } private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) { - EscherContainerRecord clientData = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherClientData, spContainer); - if (null == clientData) { return null; } - final EscherContainerRecord progTagsContainer = findFirstEscherContainerRecordOfType((short)0x1388, clientData); - if (null == progTagsContainer) { return null; } - final EscherContainerRecord progBinaryTag = findFirstEscherContainerRecordOfType((short)0x138A, progTagsContainer); - if (null == progBinaryTag) { return null; } - int size = progBinaryTag.getChildRecords().size(); + HSLFEscherClientDataRecord cldata = spContainer.getChildById(RecordTypes.EscherClientData.typeID); + if (cldata == null) { + return null; + } + DummyPositionSensitiveRecordWithChildren progTags = + getChildRecord(cldata.getHSLFChildRecords(), RecordTypes.ProgTags); + if (progTags == null) { + return null; + } + DummyPositionSensitiveRecordWithChildren progBinaryTag = + (DummyPositionSensitiveRecordWithChildren)progTags.findFirstOfType(RecordTypes.ProgBinaryTag.typeID); + if (progBinaryTag == null) { + return null; + } + int size = progBinaryTag.getChildRecords().length; if (2 != size) { return null; } - final Record r0 = buildFromUnknownEscherRecord((UnknownEscherRecord) progBinaryTag.getChild(0)); - final Record r1 = buildFromUnknownEscherRecord((UnknownEscherRecord) progBinaryTag.getChild(1)); + + final Record r0 = progBinaryTag.getChildRecords()[0]; + final Record r1 = progBinaryTag.getChildRecords()[1]; + if (!(r0 instanceof CString)) { return null; } if (!("___PPT9".equals(((CString) r0).getText()))) { return null; }; if (!(r1 instanceof BinaryTagDataBlob )) { return null; } @@ -144,19 +165,6 @@ public final class PPDrawing extends RecordAtom { if (1 != blob.getChildRecords().length) { return null; } return (StyleTextProp9Atom) blob.findFirstOfType(RecordTypes.StyleTextProp9Atom.typeID); } - /** - * Creates a new, empty, PPDrawing (typically for use with a new Slide - * or Notes) - */ - public PPDrawing(){ - _header = new byte[8]; - LittleEndian.putUShort(_header, 0, 15); - LittleEndian.putUShort(_header, 2, RecordTypes.PPDrawing.typeID); - LittleEndian.putInt(_header, 4, 0); - - textboxWrappers = new EscherTextboxWrapper[]{}; - create(); - } /** * Tree walking way of finding Escher Child Records @@ -198,27 +206,22 @@ public final class PPDrawing extends RecordAtom { /** * Look for EscherTextboxRecords */ - private void findEscherTextboxRecord(EscherRecord[] toSearch, List found) { - for(int i=0; i toSearch, List found) { + EscherSpRecord sp = null; + for (EscherRecord r : toSearch) { + if (r instanceof EscherSpRecord) { + sp = (EscherSpRecord)r; + } else if (r instanceof EscherTextboxRecord) { + EscherTextboxRecord tbr = (EscherTextboxRecord)r; EscherTextboxWrapper w = new EscherTextboxWrapper(tbr); - found.add(w); - for (int j = i; j >= 0; j--) { - if(toSearch[j] instanceof EscherSpRecord){ - EscherSpRecord sp = (EscherSpRecord)toSearch[j]; - w.setShapeId(sp.getShapeId()); - break; - } + if (sp != null) { + w.setShapeId(sp.getShapeId()); } - } else { + found.add(w); + } else if (r.isContainerRecord()) { // If it has children, walk them - if(toSearch[i].isContainerRecord()) { - List childrenL = toSearch[i].getChildRecords(); - EscherRecord[] children = new EscherRecord[childrenL.size()]; - childrenL.toArray(children); - findEscherTextboxRecord(children,found); - } + List children = r.getChildRecords(); + findEscherTextboxRecord(children,found); } } } @@ -259,9 +262,8 @@ public final class PPDrawing extends RecordAtom { // Now grab the children's data byte[] b = new byte[newSize]; int done = 0; - for(int i=0; i it = dgContainer.getChildIterator(); it.hasNext();){ - EscherRecord r = it.next(); + for(EscherRecord r : getDgContainer().getChildRecords()){ if(r instanceof EscherDgRecord){ dg = (EscherDgRecord)r; break; @@ -357,59 +371,59 @@ public final class PPDrawing extends RecordAtom { return dg; } - protected EscherContainerRecord findFirstEscherContainerRecordOfType(short type, EscherContainerRecord parent) { + protected EscherContainerRecord findFirstEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) { if (null == parent) { return null; } final List children = parent.getChildContainers(); for (EscherContainerRecord child : children) { - if (type == child.getRecordId()) { + if (type.typeID == child.getRecordId()) { return child; } } return null; } - protected EscherRecord findFirstEscherRecordOfType(short type, EscherContainerRecord parent) { + protected EscherRecord findFirstEscherRecordOfType(RecordTypes type, EscherContainerRecord parent) { if (null == parent) { return null; } final List children = parent.getChildRecords(); for (EscherRecord child : children) { - if (type == child.getRecordId()) { + if (type.typeID == child.getRecordId()) { return child; } } return null; } - protected EscherContainerRecord[] findAllEscherContainerRecordOfType(short type, EscherContainerRecord parent) { + protected EscherContainerRecord[] findAllEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) { if (null == parent) { return new EscherContainerRecord[0]; } final List children = parent.getChildContainers(); final List result = new LinkedList(); for (EscherContainerRecord child : children) { - if (type == child.getRecordId()) { + if (type.typeID == child.getRecordId()) { result.add(child); } } return result.toArray(new EscherContainerRecord[result.size()]); } - protected Record buildFromUnknownEscherRecord(UnknownEscherRecord unknown) { - byte[] bingo = unknown.getData(); - byte[] restoredRecord = new byte[8 + bingo.length]; - System.arraycopy(bingo, 0, restoredRecord, 8, bingo.length); - short recordVersion = unknown.getVersion(); - short recordId = unknown.getRecordId(); - int recordLength = unknown.getRecordSize(); - LittleEndian.putShort(restoredRecord, 0, recordVersion); - LittleEndian.putShort(restoredRecord, 2, recordId); - LittleEndian.putInt(restoredRecord, 4, recordLength); - return Record.createRecordForType(recordId, restoredRecord, 0, restoredRecord.length); - } public StyleTextProp9Atom[] getNumberedListInfo() { final List result = new LinkedList(); - EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0]; - final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer); - final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer); + EscherContainerRecord dgContainer = getDgContainer(); + final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer); + final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer); for (EscherContainerRecord spContainer : spContainers) { StyleTextProp9Atom prop9 = findInSpContainer(spContainer); - if (prop9 != null) result.add(prop9); + if (prop9 != null) { + result.add(prop9); + } } return result.toArray(new StyleTextProp9Atom[result.size()]); } + + @SuppressWarnings("unchecked") + private static T getChildRecord(List children, RecordTypes type) { + for (Record r : children) { + if (r.getRecordType() == type.typeID) { + return (T)r; + } + } + return null; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/Record.java b/src/scratchpad/src/org/apache/poi/hslf/record/Record.java index 78db7ee273..61034f1f94 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/Record.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/Record.java @@ -166,19 +166,19 @@ public abstract class Record // Any special record handling occurs once we have the class Class c = null; try { - c = RecordTypes.recordHandlingClass((int)type); + c = RecordTypes.forTypeID((short)type).handlingClass; if(c == null) { // How odd. RecordTypes normally subsitutes in // a default handler class if it has heard of the record // type but there's no support for it. Explicitly request // that now - c = RecordTypes.recordHandlingClass( RecordTypes.Unknown.typeID ); + c = RecordTypes.UnknownRecordPlaceholder.handlingClass; } // Grab the right constructor java.lang.reflect.Constructor con = c.getDeclaredConstructor(new Class[] { byte[].class, Integer.TYPE, Integer.TYPE }); // Instantiate - toReturn = con.newInstance(new Object[] { b, Integer.valueOf(start), Integer.valueOf(len) }); + toReturn = con.newInstance(new Object[] { b, start, len }); } catch(InstantiationException ie) { throw new RuntimeException("Couldn't instantiate the class for type with id " + type + " on class " + c + " : " + ie, ie); } catch(java.lang.reflect.InvocationTargetException ite) { diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java index 73a95f6d9a..c20ca12b2e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java @@ -17,8 +17,8 @@ package org.apache.poi.hslf.record; -import java.lang.reflect.Field; import java.util.HashMap; +import java.util.Map; /** * List of all known record types in a PowerPoint document, and the @@ -26,191 +26,209 @@ import java.util.HashMap; * There are two categories of records: *
  • PowerPoint records: 0 <= info <= 10002 (will carry class info) *
  • Escher records: info >= 0xF000 (handled by DDF, so no class info) - * - * @author Yegor Kozlov - * @author Nick Burch */ -public final class RecordTypes { - public static final HashMap typeToName; - public static final HashMap> typeToClass; - - public static final Type Unknown = new Type(0,null); - public static final Type Document = new Type(1000,Document.class); - public static final Type DocumentAtom = new Type(1001,DocumentAtom.class); - public static final Type EndDocument = new Type(1002,null); - public static final Type Slide = new Type(1006,Slide.class); - public static final Type SlideAtom = new Type(1007,SlideAtom.class); - public static final Type Notes = new Type(1008,Notes.class); - public static final Type NotesAtom = new Type(1009,NotesAtom.class); - public static final Type Environment = new Type(1010,Environment.class); - public static final Type SlidePersistAtom = new Type(1011,SlidePersistAtom.class); - public static final Type SSlideLayoutAtom = new Type(1015,null); - public static final Type MainMaster = new Type(1016,MainMaster.class); - public static final Type SSSlideInfoAtom = new Type(1017,SSSlideInfoAtom.class); - public static final Type SlideViewInfo = new Type(1018,null); - public static final Type GuideAtom = new Type(1019,null); - public static final Type ViewInfo = new Type(1020,null); - public static final Type ViewInfoAtom = new Type(1021,null); - public static final Type SlideViewInfoAtom = new Type(1022,null); - public static final Type VBAInfo = new Type(1023,null); - public static final Type VBAInfoAtom = new Type(1024,null); - public static final Type SSDocInfoAtom = new Type(1025,null); - public static final Type Summary = new Type(1026,null); - public static final Type DocRoutingSlip = new Type(1030,null); - public static final Type OutlineViewInfo = new Type(1031,null); - public static final Type SorterViewInfo = new Type(1032,null); - public static final Type ExObjList = new Type(1033,ExObjList.class); - public static final Type ExObjListAtom = new Type(1034,ExObjListAtom.class); - public static final Type PPDrawingGroup = new Type(1035,PPDrawingGroup.class); - public static final Type PPDrawing = new Type(1036,PPDrawing.class); - public static final Type NamedShows = new Type(1040,null); - public static final Type NamedShow = new Type(1041,null); - public static final Type NamedShowSlides = new Type(1042,null); - public static final Type SheetProperties = new Type(1044,null); - public static final Type RoundTripCustomTableStyles12Atom = new Type(1064,null); - public static final Type List = new Type(2000,null); - public static final Type FontCollection = new Type(2005,FontCollection.class); - public static final Type BookmarkCollection = new Type(2019,null); - public static final Type SoundCollection = new Type(2020,SoundCollection.class); - public static final Type SoundCollAtom = new Type(2021,null); - public static final Type Sound = new Type(2022,Sound.class); - public static final Type SoundData = new Type(2023,SoundData.class); - public static final Type BookmarkSeedAtom = new Type(2025,null); - public static final Type ColorSchemeAtom = new Type(2032,ColorSchemeAtom.class); - public static final Type ExObjRefAtom = new Type(3009,null); - public static final Type OEShapeAtom = new Type(3009,OEShapeAtom.class); - public static final Type OEPlaceholderAtom = new Type(3011,OEPlaceholderAtom.class); - public static final Type GPopublicintAtom = new Type(3024,null); - public static final Type GRatioAtom = new Type(3031,null); - public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class); - public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class); - public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class); - public static final Type StyleTextPropAtom = new Type(4001, StyleTextPropAtom.class);//0x0fa1 RT_StyleTextPropAtom - public static final Type MasterTextPropAtom = new Type(4002, MasterTextPropAtom.class); - public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class); - public static final Type TxCFStyleAtom = new Type(4004,null); - public static final Type TxPFStyleAtom = new Type(4005,null); - public static final Type TextRulerAtom = new Type(4006,TextRulerAtom.class); - public static final Type TextBookmarkAtom = new Type(4007,null); - public static final Type TextBytesAtom = new Type(4008,TextBytesAtom.class); - public static final Type TxSIStyleAtom = new Type(4009,null); - public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class); - public static final Type DefaultRulerAtom = new Type(4011,null); - public static final Type StyleTextProp9Atom = new Type(4012, StyleTextProp9Atom.class); //0x0FAC RT_StyleTextProp9Atom - public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class); - public static final Type FontEmbeddedData = new Type(4024,null); - public static final Type CString = new Type(4026,CString.class); - public static final Type MetaFile = new Type(4033,null); - public static final Type ExOleObjAtom = new Type(4035,ExOleObjAtom.class); - public static final Type SrKinsoku = new Type(4040,null); - public static final Type HandOut = new Type(4041,DummyPositionSensitiveRecordWithChildren.class); - public static final Type ExEmbed = new Type(4044,ExEmbed.class); - public static final Type ExEmbedAtom = new Type(4045,ExEmbedAtom.class); - public static final Type ExLink = new Type(4046,null); - public static final Type BookmarkEntityAtom = new Type(4048,null); - public static final Type ExLinkAtom = new Type(4049,null); - public static final Type SrKinsokuAtom = new Type(4050,null); - public static final Type ExHyperlinkAtom = new Type(4051,ExHyperlinkAtom.class); - public static final Type ExHyperlink = new Type(4055,ExHyperlink.class); - public static final Type SlideNumberMCAtom = new Type(4056,null); - public static final Type HeadersFooters = new Type(4057,HeadersFootersContainer.class); - public static final Type HeadersFootersAtom = new Type(4058,HeadersFootersAtom.class); - public static final Type TxInteractiveInfoAtom = new Type(4063,TxInteractiveInfoAtom.class); - public static final Type CharFormatAtom = new Type(4066,null); - public static final Type ParaFormatAtom = new Type(4067,null); - public static final Type RecolorInfoAtom = new Type(4071,null); - public static final Type ExQuickTimeMovie = new Type(4074,null); - public static final Type ExQuickTimeMovieData = new Type(4075,null); - public static final Type ExControl = new Type(4078,ExControl.class); - public static final Type SlideListWithText = new Type(4080,SlideListWithText.class); - public static final Type InteractiveInfo = new Type(4082,InteractiveInfo.class); - public static final Type InteractiveInfoAtom = new Type(4083,InteractiveInfoAtom.class); - public static final Type UserEditAtom = new Type(4085,UserEditAtom.class); - public static final Type CurrentUserAtom = new Type(4086,null); - public static final Type DateTimeMCAtom = new Type(4087,null); - public static final Type GenericDateMCAtom = new Type(4088,null); - public static final Type FooterMCAtom = new Type(4090,null); - public static final Type ExControlAtom = new Type(4091,ExControlAtom.class); - public static final Type ExMediaAtom = new Type(4100,ExMediaAtom.class); - public static final Type ExVideoContainer = new Type(4101,ExVideoContainer.class); - public static final Type ExAviMovie = new Type(4102,ExAviMovie.class); - public static final Type ExMCIMovie = new Type(4103,ExMCIMovie.class); - public static final Type ExMIDIAudio = new Type(4109,null); - public static final Type ExCDAudio = new Type(4110,null); - public static final Type ExWAVAudioEmbedded = new Type(4111,null); - public static final Type ExWAVAudioLink = new Type(4112,null); - public static final Type ExOleObjStg = new Type(4113,ExOleObjStg.class); - public static final Type ExCDAudioAtom = new Type(4114,null); - public static final Type ExWAVAudioEmbeddedAtom = new Type(4115,null); - public static final Type AnimationInfo = new Type(4116,AnimationInfo.class); - public static final Type AnimationInfoAtom = new Type(4081,AnimationInfoAtom.class); - public static final Type RTFDateTimeMCAtom = new Type(4117,null); - public static final Type ProgTags = new Type(5000,DummyPositionSensitiveRecordWithChildren.class); - public static final Type ProgStringTag = new Type(5001,null); - public static final Type ProgBinaryTag = new Type(5002,DummyPositionSensitiveRecordWithChildren.class); - public static final Type BinaryTagData = new Type(5003, BinaryTagDataBlob.class);//0x138b RT_BinaryTagDataBlob - public static final Type PrpublicintOptions = new Type(6000,null); - public static final Type PersistPtrFullBlock = new Type(6001,PersistPtrHolder.class); - public static final Type PersistPtrIncrementalBlock = new Type(6002,PersistPtrHolder.class); - public static final Type GScalingAtom = new Type(10001,null); - public static final Type GRColorAtom = new Type(10002,null); +public enum RecordTypes { + Unknown(0,null), + UnknownRecordPlaceholder(-1, UnknownRecordPlaceholder.class), + Document(1000,Document.class), + DocumentAtom(1001,DocumentAtom.class), + EndDocument(1002,null), + Slide(1006,Slide.class), + SlideAtom(1007,SlideAtom.class), + Notes(1008,Notes.class), + NotesAtom(1009,NotesAtom.class), + Environment(1010,Environment.class), + SlidePersistAtom(1011,SlidePersistAtom.class), + SSlideLayoutAtom(1015,null), + MainMaster(1016,MainMaster.class), + SSSlideInfoAtom(1017,SSSlideInfoAtom.class), + SlideViewInfo(1018,null), + GuideAtom(1019,null), + ViewInfo(1020,null), + ViewInfoAtom(1021,null), + SlideViewInfoAtom(1022,null), + VBAInfo(1023,null), + VBAInfoAtom(1024,null), + SSDocInfoAtom(1025,null), + Summary(1026,null), + DocRoutingSlip(1030,null), + OutlineViewInfo(1031,null), + SorterViewInfo(1032,null), + ExObjList(1033,ExObjList.class), + ExObjListAtom(1034,ExObjListAtom.class), + PPDrawingGroup(1035,PPDrawingGroup.class), + PPDrawing(1036,PPDrawing.class), + NamedShows(1040,null), + NamedShow(1041,null), + NamedShowSlides(1042,null), + SheetProperties(1044,null), + RoundTripCustomTableStyles12Atom(1064,null), + List(2000,null), + FontCollection(2005,FontCollection.class), + BookmarkCollection(2019,null), + SoundCollection(2020,SoundCollection.class), + SoundCollAtom(2021,null), + Sound(2022,Sound.class), + SoundData(2023,SoundData.class), + BookmarkSeedAtom(2025,null), + ColorSchemeAtom(2032,ColorSchemeAtom.class), + ExObjRefAtom(3009,ExObjRefAtom.class), + OEPlaceholderAtom(3011,OEPlaceholderAtom.class), + GPopublicintAtom(3024,null), + GRatioAtom(3031,null), + OutlineTextRefAtom(3998,OutlineTextRefAtom.class), + TextHeaderAtom(3999,TextHeaderAtom.class), + TextCharsAtom(4000,TextCharsAtom.class), + StyleTextPropAtom(4001, StyleTextPropAtom.class),//0x0fa1 RT_StyleTextPropAtom + MasterTextPropAtom(4002, MasterTextPropAtom.class), + TxMasterStyleAtom(4003,TxMasterStyleAtom.class), + TxCFStyleAtom(4004,null), + TxPFStyleAtom(4005,null), + TextRulerAtom(4006,TextRulerAtom.class), + TextBookmarkAtom(4007,null), + TextBytesAtom(4008,TextBytesAtom.class), + TxSIStyleAtom(4009,null), + TextSpecInfoAtom(4010, TextSpecInfoAtom.class), + DefaultRulerAtom(4011,null), + StyleTextProp9Atom(4012, StyleTextProp9Atom.class), //0x0FAC RT_StyleTextProp9Atom + FontEntityAtom(4023,FontEntityAtom.class), + FontEmbeddedData(4024,null), + CString(4026,CString.class), + MetaFile(4033,null), + ExOleObjAtom(4035,ExOleObjAtom.class), + SrKinsoku(4040,null), + HandOut(4041,DummyPositionSensitiveRecordWithChildren.class), + ExEmbed(4044,ExEmbed.class), + ExEmbedAtom(4045,ExEmbedAtom.class), + ExLink(4046,null), + BookmarkEntityAtom(4048,null), + ExLinkAtom(4049,null), + SrKinsokuAtom(4050,null), + ExHyperlinkAtom(4051,ExHyperlinkAtom.class), + ExHyperlink(4055,ExHyperlink.class), + SlideNumberMCAtom(4056,null), + HeadersFooters(4057,HeadersFootersContainer.class), + HeadersFootersAtom(4058,HeadersFootersAtom.class), + TxInteractiveInfoAtom(4063,TxInteractiveInfoAtom.class), + CharFormatAtom(4066,null), + ParaFormatAtom(4067,null), + RecolorInfoAtom(4071,null), + ExQuickTimeMovie(4074,null), + ExQuickTimeMovieData(4075,null), + ExControl(4078,ExControl.class), + SlideListWithText(4080,SlideListWithText.class), + InteractiveInfo(4082,InteractiveInfo.class), + InteractiveInfoAtom(4083,InteractiveInfoAtom.class), + UserEditAtom(4085,UserEditAtom.class), + CurrentUserAtom(4086,null), + DateTimeMCAtom(4087,null), + GenericDateMCAtom(4088,null), + FooterMCAtom(4090,null), + ExControlAtom(4091,ExControlAtom.class), + ExMediaAtom(4100,ExMediaAtom.class), + ExVideoContainer(4101,ExVideoContainer.class), + ExAviMovie(4102,ExAviMovie.class), + ExMCIMovie(4103,ExMCIMovie.class), + ExMIDIAudio(4109,null), + ExCDAudio(4110,null), + ExWAVAudioEmbedded(4111,null), + ExWAVAudioLink(4112,null), + ExOleObjStg(4113,ExOleObjStg.class), + ExCDAudioAtom(4114,null), + ExWAVAudioEmbeddedAtom(4115,null), + AnimationInfo(4116,AnimationInfo.class), + AnimationInfoAtom(4081,AnimationInfoAtom.class), + RTFDateTimeMCAtom(4117,null), + ProgTags(5000,DummyPositionSensitiveRecordWithChildren.class), + ProgStringTag(5001,null), + ProgBinaryTag(5002,DummyPositionSensitiveRecordWithChildren.class), + BinaryTagData(5003, BinaryTagDataBlob.class),//0x138b RT_BinaryTagDataBlob + PrpublicintOptions(6000,null), + PersistPtrFullBlock(6001,PersistPtrHolder.class), + PersistPtrIncrementalBlock(6002,PersistPtrHolder.class), + GScalingAtom(10001,null), + GRColorAtom(10002,null), // Records ~12000 seem to be related to the Comments used in PPT 2000/XP // (Comments in PPT97 are normal Escher text boxes) - public static final Type Comment2000 = new Type(12000,Comment2000.class); - public static final Type Comment2000Atom = new Type(12001,Comment2000Atom.class); - public static final Type Comment2000Summary = new Type(12004,null); - public static final Type Comment2000SummaryAtom = new Type(12005,null); + Comment2000(12000,Comment2000.class), + Comment2000Atom(12001,Comment2000Atom.class), + Comment2000Summary(12004,null), + Comment2000SummaryAtom(12005,null), // Records ~12050 seem to be related to Document Encryption - public static final Type DocumentEncryptionAtom = new Type(12052,DocumentEncryptionAtom.class); + DocumentEncryptionAtom(12052,DocumentEncryptionAtom.class), + + OriginalMainMasterId(1052,null), + CompositeMasterId(1052,null), + RoundTripContentMasterInfo12(1054,null), + RoundTripShapeId12(1055,null), + RoundTripHFPlaceholder12(1056,RoundTripHFPlaceholder12.class), + RoundTripContentMasterId(1058,null), + RoundTripOArtTextStyles12(1059,null), + RoundTripShapeCheckSumForCustomLayouts12(1062,null), + RoundTripNotesMasterTextStyles12(1063,null), + RoundTripCustomTableStyles12(1064,null), + + // records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher + EscherDggContainer(0xF000,null), + EscherDgg(0xf006,null), + EscherCLSID(0xf016,null), + EscherOPT(0xf00b,null), + EscherBStoreContainer(0xf001,null), + EscherBSE(0xf007,null), + EscherBlip_START(0xf018,null), + EscherBlip_END(0xf117,null), + EscherDgContainer(0xf002,null), + EscherDg(0xf008,null), + EscherRegroupItems(0xf118,null), + EscherColorScheme(0xf120,null), + EscherSpgrContainer(0xf003,null), + EscherSpContainer(0xf004,null), + EscherSpgr(0xf009,null), + EscherSp(0xf00a,null), + EscherTextbox(0xf00c,null), + EscherClientTextbox(0xf00d,null), + EscherAnchor(0xf00e,null), + EscherChildAnchor(0xf00f,null), + EscherClientAnchor(0xf010,null), + EscherClientData(0xf011,null), + EscherSolverContainer(0xf005,null), + EscherConnectorRule(0xf012,null), + EscherAlignRule(0xf013,null), + EscherArcRule(0xf014,null), + EscherClientRule(0xf015,null), + EscherCalloutRule(0xf017,null), + EscherSelection(0xf119,null), + EscherColorMRU(0xf11a,null), + EscherDeletedPspl(0xf11d,null), + EscherSplitMenuColors(0xf11e,null), + EscherOleObject(0xf11f,null), + EscherUserDefined(0xf122,null); + + private static final Map LOOKUP; + + static { + LOOKUP = new HashMap(); + for(RecordTypes s : values()) { + LOOKUP.put(s.typeID, s); + } + } + + public final short typeID; + public final Class handlingClass; + + private RecordTypes(int typeID, Class handlingClass) { + this.typeID = (short)typeID; + this.handlingClass = handlingClass; + } + + public static RecordTypes forTypeID(int typeID) { + RecordTypes rt = LOOKUP.get((short)typeID); + return (rt != null) ? rt : UnknownRecordPlaceholder; + } - public static final Type OriginalMainMasterId = new Type(1052,null); - public static final Type CompositeMasterId = new Type(1052,null); - public static final Type RoundTripContentMasterInfo12 = new Type(1054,null); - public static final Type RoundTripShapeId12 = new Type(1055,null); - public static final Type RoundTripHFPlaceholder12 = new Type(1056,RoundTripHFPlaceholder12.class); - public static final Type RoundTripContentMasterId = new Type(1058,null); - public static final Type RoundTripOArtTextStyles12 = new Type(1059,null); - public static final Type RoundTripShapeCheckSumForCustomLayouts12 = new Type(1062,null); - public static final Type RoundTripNotesMasterTextStyles12 = new Type(1063,null); - public static final Type RoundTripCustomTableStyles12 = new Type(1064,null); - //records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher - public static final int EscherDggContainer = 0xf000; - public static final int EscherDgg = 0xf006; - public static final int EscherCLSID = 0xf016; - public static final int EscherOPT = 0xf00b; - public static final int EscherBStoreContainer = 0xf001; - public static final int EscherBSE = 0xf007; - public static final int EscherBlip_START = 0xf018; - public static final int EscherBlip_END = 0xf117; - public static final int EscherDgContainer = 0xf002; - public static final int EscherDg = 0xf008; - public static final int EscherRegroupItems = 0xf118; - public static final int EscherColorScheme = 0xf120; - public static final int EscherSpgrContainer = 0xf003; - public static final int EscherSpContainer = 0xf004; - public static final int EscherSpgr = 0xf009; - public static final int EscherSp = 0xf00a; - public static final int EscherTextbox = 0xf00c; - public static final int EscherClientTextbox = 0xf00d; - public static final int EscherAnchor = 0xf00e; - public static final int EscherChildAnchor = 0xf00f; - public static final int EscherClientAnchor = 0xf010; - public static final int EscherClientData = 0xf011; - public static final int EscherSolverContainer = 0xf005; - public static final int EscherConnectorRule = 0xf012; - public static final int EscherAlignRule = 0xf013; - public static final int EscherArcRule = 0xf014; - public static final int EscherClientRule = 0xf015; - public static final int EscherCalloutRule = 0xf017; - public static final int EscherSelection = 0xf119; - public static final int EscherColorMRU = 0xf11a; - public static final int EscherDeletedPspl = 0xf11d; - public static final int EscherSplitMenuColors = 0xf11e; - public static final int EscherOleObject = 0xf11f; - public static final int EscherUserDefined = 0xf122; /** * Returns name of the record by its type @@ -218,10 +236,10 @@ public final class RecordTypes { * @param type section of the record header * @return name of the record */ - public static String recordName(int type) { - String name = typeToName.get(Integer.valueOf(type)); - return (name == null) ? ("Unknown" + type) : name; - } +// public static String recordName(int type) { +// String name = typeToName.get(Integer.valueOf(type)); +// return (name == null) ? ("Unknown" + type) : name; +// } /** * Returns the class handling a record by its type. @@ -232,38 +250,38 @@ public final class RecordTypes { * @param type section of the record header * @return class to handle the record, or null if an unknown (eg Escher) record */ - public static Class recordHandlingClass(int type) { - Class c = typeToClass.get(Integer.valueOf(type)); - return c; - } - - static { - typeToName = new HashMap(); - typeToClass = new HashMap>(); - try { - Field[] f = RecordTypes.class.getFields(); - for (int i = 0; i < f.length; i++){ - Object val = f[i].get(null); - - // Escher record, only store ID -> Name - if (val instanceof Integer) { - typeToName.put((Integer)val, f[i].getName()); - } - // PowerPoint record, store ID -> Name and ID -> Class - if (val instanceof Type) { - Type t = (Type)val; - Class c = t.handlingClass; - Integer id = Integer.valueOf(t.typeID); - if(c == null) { c = UnknownRecordPlaceholder.class; } - - typeToName.put(id, f[i].getName()); - typeToClass.put(id, c); - } - } - } catch (IllegalAccessException e){ - throw new RuntimeException("Failed to initialize records types"); - } - } +// public static Class recordHandlingClass(int type) { +// Class c = typeToClass.get(Integer.valueOf(type)); +// return c; +// } +// +// static { +// typeToName = new HashMap(); +// typeToClass = new HashMap>(); +// try { +// Field[] f = RecordTypes.class.getFields(); +// for (int i = 0; i < f.length; i++){ +// Object val = f[i].get(null); +// +// // Escher record, only store ID -> Name +// if (val instanceof Integer) { +// typeToName.put((Integer)val, f[i].getName()); +// } +// // PowerPoint record, store ID -> Name and ID -> Class +// if (val instanceof Type) { +// Type t = (Type)val; +// Class c = t.handlingClass; +// Integer id = Integer.valueOf(t.typeID); +// if(c == null) { c = UnknownRecordPlaceholder.class; } +// +// typeToName.put(id, f[i].getName()); +// typeToClass.put(id, c); +// } +// } +// } catch (IllegalAccessException e){ +// throw new RuntimeException("Failed to initialize records types"); +// } +// } /** @@ -271,12 +289,12 @@ public final class RecordTypes { * Contains both the type, and the handling class (if any), and * offers methods to get either back out. */ - public static class Type { - public final int typeID; - public final Class handlingClass; - public Type(int typeID, Class handlingClass) { - this.typeID = typeID; - this.handlingClass = handlingClass; - } - } +// public static class Type { +// public final int typeID; +// public final Class handlingClass; +// public Type(int typeID, Class handlingClass) { +// this.typeID = typeID; +// this.handlingClass = handlingClass; +// } +// } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java index 412beb1fc2..e843f1dd73 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java @@ -20,6 +20,8 @@ package org.apache.poi.hslf.record; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.util.LittleEndian; + /** * An atom record that specifies that a shape is a header or footer placeholder shape * @@ -40,6 +42,17 @@ public final class RoundTripHFPlaceholder12 extends RecordAtom { */ private byte _placeholderId; + /** + * Create a new instance of RoundTripHFPlaceholder12 + */ + public RoundTripHFPlaceholder12(){ + _header = new byte[8]; + LittleEndian.putUShort(_header, 0, 0); + LittleEndian.putUShort(_header, 2, (int)getRecordType()); + LittleEndian.putInt(_header, 4, 8); + _placeholderId = 0; + } + /** * Constructs the comment atom record from its source data. * diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java index 6d1c4873d7..9ee64d6281 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java @@ -171,7 +171,7 @@ public final class TxMasterStyleAtom extends RecordAtom { /** * Updates the rawdata from the modified paragraph/character styles * - * @since 3.14-beta1 + * @since POI 3.14-beta1 */ public void updateStyles() { int type = getTextType(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFHyperlink.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFHyperlink.java index 02608b74a3..d20f0efa9b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFHyperlink.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFHyperlink.java @@ -17,10 +17,18 @@ package org.apache.poi.hslf.usermodel; -import java.util.*; - -import org.apache.poi.ddf.*; -import org.apache.poi.hslf.record.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.ListIterator; + +import org.apache.poi.hslf.record.ExHyperlink; +import org.apache.poi.hslf.record.ExObjList; +import org.apache.poi.hslf.record.HSLFEscherClientDataRecord; +import org.apache.poi.hslf.record.InteractiveInfo; +import org.apache.poi.hslf.record.InteractiveInfoAtom; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.TxInteractiveInfoAtom; /** * Represents a hyperlink in a PowerPoint document @@ -156,6 +164,7 @@ public final class HSLFHyperlink { * @param paragraphs List of TextParagraph to lookup hyperlinks * @return found hyperlinks */ + @SuppressWarnings("resource") public static List find(List paragraphs){ List lst = new ArrayList(); if (paragraphs == null || paragraphs.isEmpty()) return lst; @@ -165,10 +174,10 @@ public final class HSLFHyperlink { HSLFSlideShow ppt = firstPara.getSheet().getSlideShow(); //document-level container which stores info about all links in a presentation ExObjList exobj = ppt.getDocumentRecord().getExObjList(); - if (exobj == null) return lst; - - Record[] records = firstPara.getRecords(); - find(records, exobj, lst); + if (exobj != null) { + Record[] records = firstPara.getRecords(); + find(Arrays.asList(records), exobj, lst); + } return lst; } @@ -179,39 +188,38 @@ public final class HSLFHyperlink { * @param shape Shape to lookup hyperlink in * @return found hyperlink or null */ + @SuppressWarnings("resource") public static HSLFHyperlink find(HSLFShape shape){ - List lst = new ArrayList(); HSLFSlideShow ppt = shape.getSheet().getSlideShow(); //document-level container which stores info about all links in a presentation ExObjList exobj = ppt.getDocumentRecord().getExObjList(); - if (exobj == null) { - return null; - } + HSLFEscherClientDataRecord cldata = shape.getClientData(false); - EscherContainerRecord spContainer = shape.getSpContainer(); - for (Iterator it = spContainer.getChildIterator(); it.hasNext(); ) { - EscherRecord obj = it.next(); - if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID){ - byte[] data = obj.serialize(); - Record[] records = Record.findChildRecords(data, 8, data.length-8); - find(records, exobj, lst); - } + if (exobj != null && cldata != null) { + List lst = new ArrayList(); + find(cldata.getHSLFChildRecords(), exobj, lst); + return lst.isEmpty() ? null : (HSLFHyperlink)lst.get(0); } - return lst.size() == 1 ? (HSLFHyperlink)lst.get(0) : null; + return null; } - private static void find(Record[] records, ExObjList exobj, List out){ - if (records == null) return; - for (int i = 0; i < records.length; i++) { - //see if we have InteractiveInfo in the textrun's records - if(!(records[i] instanceof InteractiveInfo)) continue; - - InteractiveInfo hldr = (InteractiveInfo)records[i]; + private static void find(List records, ExObjList exobj, List out){ + ListIterator iter = records.listIterator(); + while (iter.hasNext()) { + Record r = iter.next(); + // see if we have InteractiveInfo in the textrun's records + if (!(r instanceof InteractiveInfo)) { + continue; + } + + InteractiveInfo hldr = (InteractiveInfo)r; InteractiveInfoAtom info = hldr.getInteractiveInfoAtom(); int id = info.getHyperlinkID(); ExHyperlink linkRecord = exobj.get(id); - if (linkRecord == null) continue; + if (linkRecord == null) { + continue; + } HSLFHyperlink link = new HSLFHyperlink(); link.title = linkRecord.getLinkTitle(); @@ -219,8 +227,13 @@ public final class HSLFHyperlink { link.type = info.getAction(); out.add(link); - if (i+1 < records.length && records[i+1] instanceof TxInteractiveInfoAtom){ - TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)records[++i]; + if (iter.hasNext()) { + r = iter.next(); + if (!(r instanceof TxInteractiveInfoAtom)) { + iter.previous(); + continue; + } + TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)r; link.startIndex = txinfo.getStartIndex(); link.endIndex = txinfo.getEndIndex(); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java index c0a7aef69e..22b1d90abb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java @@ -18,7 +18,7 @@ package org.apache.poi.hslf.usermodel; import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.ShapeContainer; /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java index 38483d03a4..e4ef3b1b77 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java @@ -21,6 +21,7 @@ import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.util.Iterator; +import java.util.List; import org.apache.poi.ddf.AbstractEscherOptRecord; import org.apache.poi.ddf.EscherChildAnchorRecord; @@ -33,7 +34,10 @@ import org.apache.poi.ddf.EscherProperty; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherSimpleProperty; import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.hslf.record.ColorSchemeAtom; +import org.apache.poi.hslf.record.HSLFEscherClientDataRecord; +import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.sl.usermodel.FillStyle; import org.apache.poi.sl.usermodel.Shape; @@ -217,19 +221,32 @@ public abstract class HSLFShape implements Shape { public static T getEscherChild(EscherContainerRecord owner, int recordId){ return owner.getChildById((short)recordId); } + + /** + * @since POI 3.14-Beta2 + */ + public static T getEscherChild(EscherContainerRecord owner, RecordTypes recordId){ + return getEscherChild(owner, recordId.typeID); + } public T getEscherChild(int recordId){ return _escherContainer.getChildById((short)recordId); } + /** + * @since POI 3.14-Beta2 + */ + public T getEscherChild(RecordTypes recordId){ + return getEscherChild(recordId.typeID); + } + /** * Returns escher property by id. * * @return escher property or null if not found. */ public static T getEscherProperty(AbstractEscherOptRecord opt, int propId){ - if (opt == null) return null; - return opt.lookup(propId); + return (opt == null) ? null : opt.lookup(propId); } /** @@ -443,7 +460,7 @@ public abstract class HSLFShape implements Shape { } public AbstractEscherOptRecord getEscherOptRecord() { - AbstractEscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID); + AbstractEscherOptRecord opt = getEscherChild(RecordTypes.EscherOPT); if (opt == null) { opt = getEscherChild(RecordTypes.EscherUserDefined); } @@ -485,4 +502,48 @@ public abstract class HSLFShape implements Shape { public boolean isPlaceholder() { return false; } + + /** + * Find a record in the underlying EscherClientDataRecord + * + * @param recordType type of the record to search + */ + @SuppressWarnings("unchecked") + public T getClientDataRecord(int recordType) { + + List records = getClientRecords(); + if (records != null) for (Record r : records) { + if (r.getRecordType() == recordType){ + return (T)r; + } + } + return null; + } + + /** + * Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records + * + * @return an array of HSLF records contained in the shape's EscherClientDataRecord or null + */ + protected List getClientRecords() { + HSLFEscherClientDataRecord clientData = getClientData(false); + return (clientData == null) ? null : clientData.getHSLFChildRecords(); + } + + /** + * Create a new HSLF-specific EscherClientDataRecord + * + * @param create if true, create the missing record + * @return the client record or null if it was missing and create wasn't activated + */ + protected HSLFEscherClientDataRecord getClientData(boolean create) { + HSLFEscherClientDataRecord clientData = getEscherChild(HSLFEscherClientDataRecord.RECORD_ID); + if (clientData == null && create) { + clientData = new HSLFEscherClientDataRecord(); + clientData.setOptions((short)15); + clientData.setRecordId(HSLFEscherClientDataRecord.RECORD_ID); + getSpContainer().addChildBefore(clientData, EscherTextboxRecord.RECORD_ID); + } + return clientData; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java index 737d2927a2..1971713536 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java @@ -17,12 +17,27 @@ package org.apache.poi.hslf.usermodel; -import java.util.Iterator; import java.util.List; -import org.apache.poi.ddf.*; -import org.apache.poi.hslf.model.*; -import org.apache.poi.hslf.record.*; +import org.apache.poi.ddf.AbstractEscherOptRecord; +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherProperty; +import org.apache.poi.ddf.EscherPropertyFactory; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherSimpleProperty; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hslf.model.MovieShape; +import org.apache.poi.hslf.model.OLEShape; +import org.apache.poi.hslf.record.ExObjRefAtom; +import org.apache.poi.hslf.record.HSLFEscherClientDataRecord; +import org.apache.poi.hslf.record.InteractiveInfo; +import org.apache.poi.hslf.record.InteractiveInfoAtom; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.ShapeType; import org.apache.poi.util.POILogFactory; @@ -50,7 +65,7 @@ public final class HSLFShapeFactory { public static HSLFGroupShape createShapeGroup(EscherContainerRecord spContainer, ShapeContainer parent){ boolean isTable = false; EscherContainerRecord ecr = (EscherContainerRecord)spContainer.getChild(0); - EscherRecord opt = HSLFShape.getEscherChild(ecr, (short)RecordTypes.EscherUserDefined); + EscherRecord opt = HSLFShape.getEscherChild(ecr, RecordTypes.EscherUserDefined); if (opt != null) { EscherPropertyFactory f = new EscherPropertyFactory(); @@ -120,12 +135,10 @@ public final class HSLFShapeFactory { } } - OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID); - if (oes != null){ - return new OLEShape(spContainer, parent); - } - - return new HSLFPictureShape(spContainer, parent); + ExObjRefAtom oes = getClientDataRecord(spContainer, RecordTypes.ExObjRefAtom.typeID); + return (oes != null) + ? new OLEShape(spContainer, parent) + : new HSLFPictureShape(spContainer, parent); } private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer parent) { @@ -141,15 +154,10 @@ public final class HSLFShapeFactory { @SuppressWarnings("unchecked") protected static T getClientDataRecord(EscherContainerRecord spContainer, int recordType) { - for (Iterator it = spContainer.getChildIterator(); it.hasNext();) { - EscherRecord obj = it.next(); - if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) { - byte[] data = obj.serialize(); - for (Record r : Record.findChildRecords(data, 8, data.length - 8)) { - if (r.getRecordType() == recordType) { - return (T)r; - } - } + HSLFEscherClientDataRecord cldata = spContainer.getChildById(EscherClientDataRecord.RECORD_ID); + if (cldata != null) for (Record r : cldata.getHSLFChildRecords()) { + if (r.getRecordType() == recordType) { + return (T)r; } } return null; diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java index e80070e6c2..3fe79aeb16 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java @@ -149,7 +149,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet getShapes() { PPDrawing ppdrawing = getPPDrawing(); - EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; + EscherContainerRecord dg = ppdrawing.getDgContainer(); EscherContainerRecord spgr = null; for (Iterator it = dg.getChildIterator(); it.hasNext();) { @@ -187,7 +187,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet it = dg.getChildIterator(); it.hasNext();) { - EscherRecord rec = it.next(); - if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - spgr = (EscherContainerRecord) rec; - break; - } - } + EscherContainerRecord dg = ppdrawing.getDgContainer(); + EscherContainerRecord spgr = dg.getChildById(EscherContainerRecord.SPGR_CONTAINER); if(spgr == null) { return false; } @@ -292,7 +284,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet T getClientDataRecord(int recordType) { - - Record[] records = getClientRecords(); - if(records != null) for (int i = 0; i < records.length; i++) { - if(records[i].getRecordType() == recordType){ - return (T)records[i]; - } - } - return null; - } - - /** - * Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records - * - * @return an array of HSLF records contained in the shape's EscherClientDataRecord or null - */ - protected Record[] getClientRecords() { - if(_clientData == null){ - EscherRecord r = getEscherChild(EscherClientDataRecord.RECORD_ID); - //ddf can return EscherContainerRecord with recordId=EscherClientDataRecord.RECORD_ID - //convert in to EscherClientDataRecord on the fly - if(r != null && !(r instanceof EscherClientDataRecord)){ - byte[] data = r.serialize(); - r = new EscherClientDataRecord(); - r.fillFields(data, 0, new HSLFEscherRecordFactory()); - } - _clientData = (EscherClientDataRecord)r; - } - if(_clientData != null && _clientRecords == null){ - byte[] data = _clientData.getRemainingData(); - _clientRecords = Record.findChildRecords(data, 0, data.length); - } - return _clientRecords; - } - - protected void updateClientData() { - if(_clientData != null && _clientRecords != null){ - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - for (int i = 0; i < _clientRecords.length; i++) { - _clientRecords[i].writeOut(out); - } - } catch(Exception e){ - throw new HSLFException(e); - } - _clientData.setRemainingData(out.toByteArray()); - } - } - public void setHyperlink(HSLFHyperlink link){ if(link.getId() == -1){ throw new HSLFException("You must call SlideShow.addHyperlink(Hyperlink link) first"); } - EscherClientDataRecord cldata = new EscherClientDataRecord(); - cldata.setOptions((short)0xF); - getSpContainer().addChildRecord(cldata); // TODO - junit to prove getChildRecords().add is wrong - InteractiveInfo info = new InteractiveInfo(); InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom(); @@ -356,14 +316,8 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape clRecords = getClientRecords(); + if (clRecords == null) { + return null; + } + for (Record r : clRecords) { + if (r instanceof OEPlaceholderAtom) { + OEPlaceholderAtom oep = (OEPlaceholderAtom)r; + return Placeholder.lookupNative(oep.getPlaceholderId()); + } else if (r instanceof RoundTripHFPlaceholder12) { + RoundTripHFPlaceholder12 rtp = (RoundTripHFPlaceholder12)r; + return Placeholder.lookupNative(rtp.getPlaceholderId()); + } + } + + return null; + } + + @Override + public void setPlaceholder(Placeholder placeholder) { + EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID); int flags = spRecord.getFlags(); - flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER; - spRecord.setFlags(flags); - - EscherClientDataRecord cldata = _escherContainer.getChildById(EscherClientDataRecord.RECORD_ID); - if (cldata == null) { - cldata = new EscherClientDataRecord(); - // append placeholder container before EscherTextboxRecord - _escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID); + if (placeholder == null) { + flags ^= EscherSpRecord.FLAG_HAVEMASTER; + } else { + flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER; } - cldata.setOptions((short)15); - - AbstractEscherOptRecord opt = getEscherOptRecord(); + spRecord.setFlags(flags); // Placeholders can't be grouped - setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144); + setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, (placeholder == null ? -1 : 262144)); + + HSLFEscherClientDataRecord clientData = getClientData(false); + if (placeholder == null) { + if (clientData != null) { + clientData.removeChild(OEPlaceholderAtom.class); + clientData.removeChild(RoundTripHFPlaceholder12.class); + // remove client data if the placeholder was the only child to be carried + if (clientData.getChildRecords().isEmpty()) { + getSpContainer().removeChildRecord(clientData); + } + } + return; + } + + if (clientData == null) { + clientData = getClientData(true); + } // OEPlaceholderAtom tells powerpoint that this shape is a placeholder - OEPlaceholderAtom oep = new OEPlaceholderAtom(); + OEPlaceholderAtom oep = null; + RoundTripHFPlaceholder12 rtp = null; + for (Record r : clientData.getHSLFChildRecords()) { + if (r instanceof OEPlaceholderAtom) { + oep = (OEPlaceholderAtom)r; + break; + } + if (r instanceof RoundTripHFPlaceholder12) { + rtp = (RoundTripHFPlaceholder12)r; + break; + } + } /** - * Extarct from MSDN: + * Extract from MSDN: * * There is a special case when the placeholder does not have a position in the layout. * This occurs when the user has moved the placeholder from its original position. * In this case the placeholder ID is -1. */ - oep.setPlacementId(-1); - - boolean isMaster = (getSheet() instanceof HSLFSlideMaster); - boolean isNotes = (getSheet() instanceof HSLFNotes); byte phId; + HSLFSheet sheet = getSheet(); + // TODO: implement/switch NotesMaster + if (sheet instanceof HSLFSlideMaster) { + phId = (byte)placeholder.nativeSlideMasterId; + } else if (sheet instanceof HSLFNotes) { + phId = (byte)placeholder.nativeNotesId; + } else { + phId = (byte)placeholder.nativeSlideId; + } + + if (phId == -2) { + throw new HSLFException("Placeholder "+placeholder.name()+" not supported for this sheet type ("+sheet.getClass()+")"); + } + switch (placeholder) { - case TITLE: - phId = (isMaster) ? OEPlaceholderAtom.MasterTitle : OEPlaceholderAtom.Title; - break; - case BODY: - phId = (isMaster) ? OEPlaceholderAtom.MasterBody : - ((isNotes) ? OEPlaceholderAtom.NotesBody : OEPlaceholderAtom.Body); - break; - case CENTERED_TITLE: - phId = (isMaster) ? OEPlaceholderAtom.MasterCenteredTitle : OEPlaceholderAtom.CenteredTitle; - break; - case SUBTITLE: - phId = (isMaster) ? OEPlaceholderAtom.MasterSubTitle : OEPlaceholderAtom.Subtitle; - break; - case DATETIME: - phId = OEPlaceholderAtom.MasterDate; - break; - case SLIDE_NUMBER: - phId = OEPlaceholderAtom.MasterSlideNumber; - break; - case FOOTER: - phId = OEPlaceholderAtom.MasterFooter; - break; case HEADER: - phId = OEPlaceholderAtom.MasterHeader; - break; - case DGM: - case CHART: - phId = OEPlaceholderAtom.Graph; - break; - case TABLE: - phId = OEPlaceholderAtom.Table; - break; - case PICTURE: - case CLIP_ART: - phId = OEPlaceholderAtom.ClipArt; - break; - case MEDIA: - phId = OEPlaceholderAtom.MediaClip; - break; - case SLIDE_IMAGE: - phId = (isMaster) ? OEPlaceholderAtom.MasterNotesSlideImage : OEPlaceholderAtom.NotesSlideImage; + case FOOTER: + if (rtp == null) { + rtp = new RoundTripHFPlaceholder12(); + rtp.setPlaceholderId(phId); + clientData.addChild(rtp); + } + if (oep != null) { + clientData.removeChild(OEPlaceholderAtom.class); + } break; default: - case CONTENT: - phId = OEPlaceholderAtom.Object; + if (rtp != null) { + clientData.removeChild(RoundTripHFPlaceholder12.class); + } + if (oep == null) { + oep = new OEPlaceholderAtom(); + oep.setPlaceholderSize((byte)OEPlaceholderAtom.PLACEHOLDER_FULLSIZE); + // TODO: placement id only "SHOULD" be unique ... check other placeholders on sheet for unique id + oep.setPlacementId(-1); + oep.setPlaceholderId(phId); + clientData.addChild(oep); + } break; } - oep.setPlaceholderId(phId); - - //convert hslf into ddf record - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - oep.writeOut(out); - } catch(Exception e){ - throw new HSLFException(e); - } - cldata.setRemainingData(out.toByteArray()); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java index 1ebd32368e..73223646c7 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java @@ -42,8 +42,8 @@ import org.apache.poi.hslf.record.TextHeaderAtom; import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.Drawable; import org.apache.poi.sl.usermodel.Notes; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.sl.usermodel.SimpleShape.Placeholder; import org.apache.poi.sl.usermodel.Slide; /** @@ -163,7 +163,7 @@ public final class HSLFSlide extends HSLFSheet implements Slide interestingRecords = - new HashMap(); + Map interestingRecords = + new HashMap(); try { _hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java index d27b6f050b..750c74ebf3 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java @@ -474,7 +474,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { * May be null, if not needed. * @throws IOException */ - public void updateAndWriteDependantRecords(OutputStream os, Map interestingRecords) + public void updateAndWriteDependantRecords(OutputStream os, Map interestingRecords) throws IOException { // For position dependent records, hold where they were and now are // As we go along, update, and hand over, to any Position Dependent @@ -502,7 +502,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { // Grab interesting records as they come past // this will only save the very last record of each type - RecordTypes.Type saveme = null; + RecordTypes saveme = null; int recordType = (int)record.getRecordType(); if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) { saveme = RecordTypes.PersistPtrIncrementalBlock; diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java index b82bed34a6..664e935d4a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java @@ -95,14 +95,14 @@ implements HSLFShapeContainer, TableShape { EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0); AbstractEscherOptRecord opt = new EscherOptRecord(); - opt.setRecordId((short)RecordTypes.EscherUserDefined); + opt.setRecordId(RecordTypes.EscherUserDefined.typeID); opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__TABLEPROPERTIES, 1)); EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES), false, null); p.setSizeOfElements(0x0004); p.setNumberOfElementsInArray(numRows); p.setNumberOfElementsInMemory(numRows); opt.addEscherProperty(p); - spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor); + spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor.typeID); } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java index da6e164549..8460a5b979 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java @@ -157,7 +157,7 @@ public final class HSLFTextParagraph implements TextParagraph { } /** - * Return OEPlaceholderAtom, the atom that describes a placeholder. + * Return {@link OEPlaceholderAtom}, the atom that describes a placeholder. * - * @return OEPlaceholderAtom or null if not found + * @return {@link OEPlaceholderAtom} or {@code null} if not found */ public OEPlaceholderAtom getPlaceholderAtom(){ return getClientDataRecord(OEPlaceholderAtom.typeID); } + /** + * Return {@link RoundTripHFPlaceholder12}, the atom that describes a header/footer placeholder. + * Compare the {@link RoundTripHFPlaceholder12#getPlaceholderId()} with + * {@link OEPlaceholderAtom#MasterHeader} or {@link OEPlaceholderAtom#MasterFooter}, to find out + * what kind of placeholder this is. + * + * @return {@link RoundTripHFPlaceholder12} or {@code null} if not found + * + * @since POI 3.14-Beta2 + */ + public RoundTripHFPlaceholder12 getHFPlaceholderAtom() { + // special case for files saved in Office 2007 + return getClientDataRecord(RoundTripHFPlaceholder12.typeID); + } + /** * * Assigns a hyperlink to this text shape @@ -644,7 +660,7 @@ implements TextShape { if (oep != null) return true; //special case for files saved in Office 2007 - RoundTripHFPlaceholder12 hldr = getClientDataRecord(RoundTripHFPlaceholder12.typeID); + RoundTripHFPlaceholder12 hldr = getHFPlaceholderAtom(); if (hldr != null) return true; return false; diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java index a742528e21..d5a2b60a09 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java @@ -17,18 +17,22 @@ package org.apache.poi.hslf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; - -import junit.framework.TestCase; +import java.io.IOException; import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.junit.Before; +import org.junit.Test; /** * Tests that HSLFSlideShow writes the powerpoint bit of data back out @@ -36,7 +40,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; * * @author Nick Burch (nick at torchbox dot com) */ -public final class TestReWrite extends TestCase { +public final class TestReWrite { // HSLFSlideShow primed on the test data private HSLFSlideShowImpl hssA; private HSLFSlideShowImpl hssB; @@ -46,7 +50,8 @@ public final class TestReWrite extends TestCase { private POIFSFileSystem pfsB; private POIFSFileSystem pfsC; - public void setUp() throws Exception { + @Before + public void setUp() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); @@ -60,10 +65,12 @@ public final class TestReWrite extends TestCase { hssC = new HSLFSlideShowImpl(pfsC); } + @Test public void testWritesOutTheSame() throws Exception { assertWritesOutTheSame(hssA, pfsA); assertWritesOutTheSame(hssB, pfsB); } + public void assertWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception { // Write out to a byte array ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -85,13 +92,15 @@ public final class TestReWrite extends TestCase { byte[] _nData = new byte[nProps.getSize()]; pfs.createDocumentInputStream("PowerPoint Document").read(_oData); npfs.createDocumentInputStream("PowerPoint Document").read(_nData); - for(int i=0; i<_oData.length; i++) { + for(int i=0; i<_oData.length; i++) { //System.out.println(i + "\t" + Integer.toHexString(i)); assertEquals(_oData[i], _nData[i]); } + npfs.close(); } - public void testWithMacroStreams() throws Exception { + @Test + public void testWithMacroStreams() throws IOException { // Check that they're apparently the same assertSlideShowWritesOutTheSame(hssC, pfsC); @@ -101,28 +110,25 @@ public final class TestReWrite extends TestCase { // Write out normally, will loose the macro stream ByteArrayOutputStream baos = new ByteArrayOutputStream(); hssC.write(baos); - POIFSFileSystem pfsNew = new POIFSFileSystem( - new ByteArrayInputStream(baos.toByteArray()) ); - - try { - pfsNew.getRoot().getEntry("Macros"); - fail(); - } catch(FileNotFoundException e) { - // Good, as expected - } + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + POIFSFileSystem pfsNew = new POIFSFileSystem(bais); + assertFalse(pfsNew.getRoot().hasEntry("Macros")); + pfsNew.close(); // But if we write out with nodes preserved, will be there - baos = new ByteArrayOutputStream(); + baos.reset(); hssC.write(baos, true); - pfsNew = new POIFSFileSystem( - new ByteArrayInputStream(baos.toByteArray()) ); - assertNotNull( pfsNew.getRoot().getEntry("Macros") ); + bais = new ByteArrayInputStream(baos.toByteArray()); + pfsNew = new POIFSFileSystem(bais); + assertTrue( pfsNew.getRoot().hasEntry("Macros") ); + pfsNew.close(); } /** * Ensure that simply opening a slideshow (usermodel) view of it * doesn't change things */ + @Test public void testSlideShowWritesOutTheSame() throws Exception { assertSlideShowWritesOutTheSame(hssA, pfsA); @@ -130,9 +136,11 @@ public final class TestReWrite extends TestCase { // We need to identify and fix that first //assertSlideShowWritesOutTheSame(hssB, pfsB); } - public void assertSlideShowWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception { + + public void assertSlideShowWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws IOException { // Create a slideshow covering it - HSLFSlideShow ss = new HSLFSlideShow(hss); + @SuppressWarnings("resource") + HSLFSlideShow ss = new HSLFSlideShow(hss); ss.getSlides(); ss.getNotes(); @@ -161,17 +169,23 @@ public final class TestReWrite extends TestCase { System.out.println(i + "\t" + Integer.toHexString(i)); assertEquals(_oData[i], _nData[i]); } + npfs.close(); } - public void test48593() throws Exception { - HSLFSlideShow slideShow = new HSLFSlideShow(); - slideShow.createSlide(); - slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow); - slideShow.createSlide(); - slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow); - slideShow.createSlide(); - slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow); - slideShow.createSlide(); - slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow); + @Test + public void test48593() throws IOException { + HSLFSlideShow ppt1 = new HSLFSlideShow(); + ppt1.createSlide(); + HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt2.createSlide(); + HSLFSlideShow ppt3 = HSLFTestDataSamples.writeOutAndReadBack(ppt2); + ppt3.createSlide(); + HSLFSlideShow ppt4 = HSLFTestDataSamples.writeOutAndReadBack(ppt3); + ppt4.createSlide(); + HSLFTestDataSamples.writeOutAndReadBack(ppt4).close(); + ppt4.close(); + ppt3.close(); + ppt2.close(); + ppt1.close(); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordTypes.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordTypes.java index 45522dfd81..814259ca15 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordTypes.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordTypes.java @@ -18,40 +18,44 @@ package org.apache.poi.hslf.record; -import junit.framework.TestCase; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; /** * Tests that RecordTypes returns the right records and classes when asked - * - * @author Nick Burch (nick at torchbox dot com) */ -public final class TestRecordTypes extends TestCase { +public final class TestRecordTypes { + @Test public void testPPTNameLookups() { - assertEquals("MainMaster", RecordTypes.recordName(1016)); - assertEquals("TextBytesAtom", RecordTypes.recordName(4008)); - assertEquals("VBAInfo", RecordTypes.recordName(1023)); + assertEquals("MainMaster", RecordTypes.MainMaster.name()); + assertEquals("TextBytesAtom", RecordTypes.TextBytesAtom.name()); + assertEquals("VBAInfo", RecordTypes.VBAInfo.name()); } + @Test public void testEscherNameLookups() { - assertEquals("EscherDggContainer", RecordTypes.recordName(0xf000)); - assertEquals("EscherClientTextbox", RecordTypes.recordName(0xf00d)); - assertEquals("EscherSelection", RecordTypes.recordName(0xf119)); + assertEquals("EscherDggContainer", RecordTypes.EscherDggContainer.name()); + assertEquals("EscherClientTextbox", RecordTypes.EscherClientTextbox.name()); + assertEquals("EscherSelection", RecordTypes.EscherSelection.name()); } + @Test public void testPPTClassLookups() { - assertEquals(Slide.class, RecordTypes.recordHandlingClass(1006)); - assertEquals(TextCharsAtom.class, RecordTypes.recordHandlingClass(4000)); - assertEquals(TextBytesAtom.class, RecordTypes.recordHandlingClass(4008)); - assertEquals(SlideListWithText.class, RecordTypes.recordHandlingClass(4080)); + assertEquals(Slide.class, RecordTypes.Slide.handlingClass); + assertEquals(TextCharsAtom.class, RecordTypes.TextCharsAtom.handlingClass); + assertEquals(TextBytesAtom.class, RecordTypes.TextBytesAtom.handlingClass); + assertEquals(SlideListWithText.class, RecordTypes.SlideListWithText.handlingClass); // If this record is ever implemented, change to one that isn't! // This is checking the "unhandled default" stuff works - assertEquals(UnknownRecordPlaceholder.class, RecordTypes.recordHandlingClass(2019)); + assertEquals(UnknownRecordPlaceholder.class, RecordTypes.forTypeID(-10).handlingClass); } - public void testEscherClassLookups() { + @Test + public void testEscherClassLookups() { // Should all come back with null, as DDF handles them - assertEquals(null, RecordTypes.recordHandlingClass(0xf000)); - assertEquals(null, RecordTypes.recordHandlingClass(0xf001)); + assertEquals(null, RecordTypes.EscherDggContainer.handlingClass); + assertEquals(null, RecordTypes.EscherBStoreContainer.handlingClass); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java index 68684bf8d6..b57d9e4f2f 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java @@ -20,6 +20,7 @@ package org.apache.poi.hslf.usermodel; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.awt.Color; @@ -42,7 +43,9 @@ import org.apache.poi.hslf.exceptions.OldPowerPointFormatException; import org.apache.poi.hslf.extractor.PowerPointExtractor; import org.apache.poi.hslf.model.HeadersFooters; import org.apache.poi.hslf.record.Document; +import org.apache.poi.hslf.record.OEPlaceholderAtom; import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RoundTripHFPlaceholder12; import org.apache.poi.hslf.record.SlideListWithText; import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; import org.apache.poi.hslf.record.TextHeaderAtom; @@ -50,6 +53,7 @@ import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.PictureData.PictureType; +import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.sl.usermodel.Slide; import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.sl.usermodel.SlideShowFactory; @@ -777,6 +781,31 @@ public final class TestBugs { ex.close(); } + @Test + public void bug58159() throws IOException { + File sample = HSLFTestDataSamples.getSampleFile("bug58159_headers-and-footers.ppt"); + HSLFSlideShow ppt = (HSLFSlideShow)SlideShowFactory.create(sample); + HeadersFooters hf = ppt.getSlideHeadersFooters(); + assertNull(hf.getHeaderText()); + assertEquals("Slide footer", hf.getFooterText()); + hf = ppt.getNotesHeadersFooters(); + assertEquals("Notes header", hf.getHeaderText()); + assertEquals("Notes footer", hf.getFooterText()); + HSLFSlide sl = ppt.getSlides().get(0); + hf = sl.getHeadersFooters(); + assertNull(hf.getHeaderText()); + assertEquals("Slide footer", hf.getFooterText()); + for (HSLFShape shape : sl.getShapes()) { + if (shape instanceof HSLFTextShape) { + HSLFTextShape ts = (HSLFTextShape)shape; + Placeholder ph = ts.getPlaceholder(); + if (Placeholder.FOOTER == ph) { + assertEquals("Slide footer", ts.getText()); + } + } + } + ppt.close(); + } private static HSLFSlideShow open(String fileName) throws IOException { File sample = HSLFTestDataSamples.getSampleFile(fileName); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java index e54da298ff..b21f216577 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java @@ -42,12 +42,11 @@ public final class TestNumberedList { @Test public void testNumberedList() throws Exception { HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers.ppt")); - assertTrue("No Exceptions while reading file", true); - final List slides = ppt.getSlides(); assertEquals(2, slides.size()); checkSlide0(slides.get(0)); checkSlide1(slides.get(1)); + ppt.close(); } private void checkSlide0(final HSLFSlide s) {