From a6b1ef6d07c6eb85d5763c3f3e3e27af2d77d5ba Mon Sep 17 00:00:00 2001
From: Nick Burch
+ * The information about an image in PowerPoint document is stored in
+ * two places:
+ * null
if the
+ * @return array with the read pictures or null
if the
* presentation doesn't contain pictures.
*/
- public Picture[] getPictures() throws IOException {
- byte[] pictstream;
-
- try {
- DocumentEntry entry = (DocumentEntry)filesystem.getRoot().getEntry("Pictures");
- pictstream = new byte[entry.getSize()];
- DocumentInputStream is = filesystem.createDocumentInputStream("Pictures");
- is.read(pictstream);
- } catch (FileNotFoundException e){
- //silently catch exceptions if the presentation doesn't contain pictures
- return null;
- }
-
- ArrayList p = new ArrayList();
- int pos = 0;
- while (pos < pictstream.length) {
- Picture pict = new Picture(pictstream, pos);
- p.add(pict);
- pos += Picture.HEADER_SIZE + pict.getSize();
- }
-
- return (Picture[])p.toArray(new Picture[p.size()]);
+ public PictureData[] getPictures() {
+ return _pictures;
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt b/src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt
new file mode 100644
index 0000000000000000000000000000000000000000..23e1e94ca8a5d1888d35fd89f307c4b01e57e059
GIT binary patch
literal 10240
zcmeHNYiu0V6+Sbw_O9)9cGq@HNJugX0RkkcYllKh3r=GKDcEs|DWxyGc*oAd?vAq$
zJ3*j238hpO5(w&&7M1X-fJzmQN=>0{ETyzijGzyy6qGhqKuV)ZI6w;olI{21yJI%?
zE;x?=AaSj4?w$KM_nhyZ`
+ * Data in the "Pictures" OLE stream is organized as follows:
+ * For each image there is an entry: 25 byte header + image data.
+ * Image data is the exact content of the JPEG file, i.e. PowerPoint
+ * puts the whole jpeg file there without any modifications.
+ * Header format:
+ *
Picture
+ *
+ * @param idx the index of the picture
+ */
+ public Picture(int idx){
+ super(null, null);
+ _escherContainer = createSpContainer(idx);
+ }
+
+ /**
+ * Create a Picture
object
+ *
+ * @param escherRecord the EscherSpContainer
record which holds information about
+ * this picture in the Slide
+ * @param parent the parent shape of this picture
+ */
+ protected Picture(EscherContainerRecord escherRecord, Shape parent){
+ super(escherRecord, parent);
+ }
+
+ /**
+ * Returns index associated with this picture.
+ * Index starts with 1 and points to a EscherBSE record which
+ * holds information about this picture.
+ *
+ * @return the index to this picture (1 based).
+ */
+ public int getPictureIndex(){
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.BLIP__BLIPTODISPLAY + 0x4000);
+ return prop.getPropertyValue();
+ }
+
+ /**
+ * Create a new Picture and populate the inital structure of the EscherSp
record which holds information about this picture.
+
+ * @param idx the index of the picture which referes to EscherBSE
container.
+ * @return the create Picture object
+ */
+ protected EscherContainerRecord createSpContainer(int idx) {
+ EscherContainerRecord spContainer = super.createSpContainer(false);
+ spContainer.setOptions((short)15);
+
+ EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID);
+ spRecord.setOptions((short)((ShapeTypes.PictureFrame << 4) | 0x2));
+
+ //set default properties for a picture
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+ setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 8388736);
+
+ //another weird feature of powerpoint: for picture id we must add 0x4000.
+ setEscherProperty(opt, (short)(EscherProperties.BLIP__BLIPTODISPLAY + 0x4000), idx);
+
+ return spContainer;
+ }
+
+ /**
+ * Set default size of the picture
+ *
+ * @param ppt presentation which holds the picture
+ */
+ public void setDefaultSize(SlideShow ppt) throws IOException {
+ int idx = getPictureIndex();
+
+ PictureData pict = ppt.getPictures()[idx-1];
+ BufferedImage img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
+
+ setAnchor(new java.awt.Rectangle(0, 0, img.getWidth()*6, img.getHeight()*6));
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java b/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java
index a4be8e2711..2c5d69d22f 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java
@@ -33,15 +33,15 @@ public class Rectangle extends SimpleShape {
public Rectangle(Shape parent){
super(null, parent);
- _escherContainer = create(parent instanceof ShapeGroup);
+ _escherContainer = createSpContainer(parent instanceof ShapeGroup);
}
public Rectangle(){
this(null);
}
- protected EscherContainerRecord create(boolean isChild){
- EscherContainerRecord spcont = super.create(isChild);
+ protected EscherContainerRecord createSpContainer(boolean isChild){
+ EscherContainerRecord spcont = super.createSpContainer(isChild);
spcont.setOptions((short)15);
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
index a01b116917..aa1b200e64 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
@@ -26,25 +26,37 @@ import java.util.Iterator;
*
* @author Yegor Kozlov
*/
-public class Shape {
+public abstract class Shape {
public static final int EMU_PER_POINT = 12700;
- /**
- * The parent of the shape
- */
- protected Shape _parent;
-
/**
* Either EscherSpContainer or EscheSpgrContainer record
* which holds information about this shape.
*/
protected EscherContainerRecord _escherContainer;
- protected Shape(EscherContainerRecord escherRecord, Shape parent){
+ /**
+ * Parent of this shape.
+ * null
for the topmost shapes.
+ */
+ protected Shape _parent;
+
+ /**
+ * Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document.
+ *
+ * @param escherRecord EscherSpContainer
container which holds information about this shape
+ * @param parent the parent of this Shape
+ */
+ protected Shape(EscherContainerRecord escherRecord, Shape parent){
_escherContainer = escherRecord;
_parent = parent;
- }
+ }
+
+ /**
+ * Creates the lowerlevel escher records for this shape.
+ */
+ protected abstract EscherContainerRecord createSpContainer(boolean isChild);
/**
* @return the parent of this shape
@@ -128,17 +140,27 @@ public class Shape {
setAnchor(anchor);
}
- protected static EscherRecord getEscherChild(EscherContainerRecord owner, int recordId){
+ /**
+ * Helper method to return escher child by record ID
+ *
+ * @return escher record or null
if not found.
+ */
+ public static EscherRecord getEscherChild(EscherContainerRecord owner, int recordId){
for ( Iterator iterator = owner.getChildRecords().iterator(); iterator.hasNext(); )
{
EscherRecord escherRecord = (EscherRecord) iterator.next();
if (escherRecord.getRecordId() == recordId)
- return (EscherRecord) escherRecord;
+ return escherRecord;
}
return null;
}
- protected static EscherProperty getEscherProperty(EscherOptRecord opt, int propId){
+ /**
+ * Returns escher property by id.
+ *
+ * @return escher property or null
if not found.
+ */
+ public static EscherProperty getEscherProperty(EscherOptRecord opt, int propId){
for ( Iterator iterator = opt.getEscherProperties().iterator(); iterator.hasNext(); )
{
EscherProperty prop = (EscherProperty) iterator.next();
@@ -148,7 +170,14 @@ public class Shape {
return null;
}
- protected static void setEscherProperty(EscherOptRecord opt, short propId, int value){
+ /**
+ * Set an escher property in the opt record.
+ *
+ * @param opt The opt record to set the properties to.
+ * @param propId The id of the property. One of the constants defined in EscherOptRecord.
+ * @param value value of the property
+ */
+ public static void setEscherProperty(EscherOptRecord opt, short propId, int value){
java.util.List props = opt.getEscherProperties();
for ( Iterator iterator = props.iterator(); iterator.hasNext(); ) {
EscherProperty prop = (EscherProperty) iterator.next();
@@ -163,10 +192,10 @@ public class Shape {
}
/**
- *
- * @return escher container which holds information about this shape
+ * @return The shape container and it's children that can represent this
+ * shape.
*/
- public EscherContainerRecord getShapeRecord(){
+ public EscherContainerRecord getSpContainer(){
return _escherContainer;
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
index 67f2d708bd..c886638c3c 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
@@ -37,10 +37,10 @@ public class ShapeFactory {
switch (type){
case ShapeTypes.TextBox:
case ShapeTypes.Rectangle:
- shape = new Shape(spContainer, parent);
+ shape = new Rectangle(spContainer, parent);
break;
case ShapeTypes.PictureFrame:
- shape = new Shape(spContainer, parent);
+ shape = new Picture(spContainer, parent);
break;
case ShapeTypes.Line:
shape = new Line(spContainer, parent);
@@ -52,7 +52,7 @@ public class ShapeFactory {
shape = new ShapeGroup(spContainer, parent);
break;
default:
- shape = new Shape(spContainer, parent);
+ shape = new SimpleShape(spContainer, parent);
break;
}
return shape;
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
index c11e294716..0d2d61e95a 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
@@ -27,13 +27,9 @@ import java.util.List;
*/
public class ShapeGroup extends Shape{
- public ShapeGroup(Shape parent){
- super(null, parent);
- _escherContainer = create();
- }
-
public ShapeGroup(){
- this(null);
+ this(null, null);
+ _escherContainer = createSpContainer(false);
}
protected ShapeGroup(EscherContainerRecord escherRecord, Shape parent){
@@ -91,7 +87,7 @@ public class ShapeGroup extends Shape{
/**
* Create a new ShapeGroup and create an instance of EscherSpgrContainer
which represents a group of shapes
*/
- protected EscherContainerRecord create() {
+ protected EscherContainerRecord createSpContainer(boolean isChild) {
EscherContainerRecord spgr = new EscherContainerRecord();
spgr.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
spgr.setOptions((short)15);
@@ -124,7 +120,7 @@ public class ShapeGroup extends Shape{
* @param shape - the Shape to add
*/
public void addShape(Shape shape){
- _escherContainer.addChildRecord(shape.getShapeRecord());
+ _escherContainer.addChildRecord(shape.getSpContainer());
}
/**
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
index f0834578e7..e4a688628e 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
@@ -158,7 +158,7 @@ public abstract class Sheet
EscherContainerRecord dgContainer = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
EscherContainerRecord spgr = (EscherContainerRecord)Shape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER);
- spgr.addChildRecord(shape.getShapeRecord());
+ spgr.addChildRecord(shape.getSpContainer());
EscherDgRecord dg = (EscherDgRecord)Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
dg.setNumShapes(dg.getNumShapes()+1);
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
index 7f08b83a64..787780dcf5 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
@@ -39,10 +39,10 @@ public class SimpleShape extends Shape {
* @param isChild true
if the Line is inside a group, false
otherwise
* @return the record container which holds this shape
*/
- protected EscherContainerRecord create(boolean isChild) {
+ protected EscherContainerRecord createSpContainer(boolean isChild) {
EscherContainerRecord spContainer = new EscherContainerRecord();
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
- //spContainer.setOptions((short)15);
+ spContainer.setOptions((short)15);
EscherSpRecord sp = new EscherSpRecord();
int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE;
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/Document.java b/src/scratchpad/src/org/apache/poi/hslf/record/Document.java
index c3c0012dd9..2593eecd30 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/record/Document.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/Document.java
@@ -36,6 +36,7 @@ public class Document extends PositionDependentRecordContainer
// Links to our more interesting children
private DocumentAtom documentAtom;
private Environment environment;
+ private PPDrawingGroup ppDrawing;
private SlideListWithText[] slwts;
/**
@@ -47,6 +48,11 @@ public class Document extends PositionDependentRecordContainer
* settings for the document in it
*/
public Environment getEnvironment() { return environment; }
+ /**
+ * Returns the PPDrawingGroup, which holds an Escher Structure
+ * that contains information on pictures in the slides.
+ */
+ public PPDrawingGroup getPPDrawingGroup() { return ppDrawing; }
/**
* Returns all the SlideListWithTexts that are defined for
* this Document. They hold the text, and some of the text
@@ -82,6 +88,9 @@ public class Document extends PositionDependentRecordContainer
if(_children[i] instanceof Environment) {
environment = (Environment)_children[i];
}
+ if(_children[i] instanceof PPDrawingGroup) {
+ ppDrawing = (PPDrawingGroup)_children[i];
+ }
}
// Now grab them all
slwts = new SlideListWithText[slwtcount];
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java
new file mode 100644
index 0000000000..f877d2a4a1
--- /dev/null
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java
@@ -0,0 +1,103 @@
+package org.apache.poi.hslf.record;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.util.LittleEndian;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * Container records which always exists inside Document.
+ * It always acts as a holder for escher DGG container
+ * which may contain which Escher BStore container information
+ * about pictures containes in the presentation (if any).
+ *
+ * @author Yegor Kozlov
+ */
+public class PPDrawingGroup extends RecordAtom {
+
+ private byte[] _header;
+ private EscherContainerRecord dggContainer;
+
+ protected PPDrawingGroup(byte[] source, int start, int len) {
+ // Get the header
+ _header = new byte[8];
+ System.arraycopy(source,start,_header,0,8);
+
+ // Get the contents for now
+ byte[] contents = new byte[len];
+ System.arraycopy(source,start,contents,0,len);
+
+ DefaultEscherRecordFactory erf = new DefaultEscherRecordFactory();
+ EscherRecord child = erf.createRecord(contents, 0);
+ child.fillFields( contents, 0, erf );
+ dggContainer = (EscherContainerRecord)child.getChild(0);
+ }
+
+ /**
+ * We are type 1035
+ */
+ public long getRecordType() {
+ return RecordTypes.PPDrawingGroup.typeID;
+ }
+
+ /**
+ * We're pretending to be an atom, so return null
+ */
+ public Record[] getChildRecords() {
+ return null;
+ }
+
+ public void writeOut(OutputStream out) throws IOException {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ List child = dggContainer.getChildRecords();
+ for (int i = 0; i < child.size(); i++) {
+ EscherRecord r = (EscherRecord)child.get(i);
+ if (r.getRecordId() == EscherContainerRecord.BSTORE_CONTAINER){
+ EscherContainerRecord bstore = (EscherContainerRecord)r;
+
+ ByteArrayOutputStream b2 = new ByteArrayOutputStream();
+ List blip = bstore.getChildRecords();
+ for (Iterator it=blip.iterator(); it.hasNext();) {
+ EscherBSERecord bse = (EscherBSERecord)it.next();
+ byte[] b = new byte[36+8];
+ bse.serialize(0, b);
+ b2.write(b);
+ }
+ byte[] bstorehead = new byte[8];
+ LittleEndian.putShort(bstorehead, 0, bstore.getOptions());
+ LittleEndian.putShort(bstorehead, 2, bstore.getRecordId());
+ LittleEndian.putInt(bstorehead, 4, b2.size());
+ bout.write(bstorehead);
+ bout.write(b2.toByteArray());
+
+ } else {
+ bout.write(r.serialize());
+ }
+ }
+ int size = bout.size();
+
+ // Update the size (header bytes 5-8)
+ LittleEndian.putInt(_header,4,size+8);
+
+ // Write out our header
+ out.write(_header);
+
+ byte[] dgghead = new byte[8];
+ LittleEndian.putShort(dgghead, 0, dggContainer.getOptions());
+ LittleEndian.putShort(dgghead, 2, dggContainer.getRecordId());
+ LittleEndian.putInt(dgghead, 4, size);
+ out.write(dgghead);
+
+ // Finally, write out the children
+ out.write(bout.toByteArray());
+
+ }
+
+ public EscherContainerRecord getDggContainer(){
+ return dggContainer;
+ }
+}
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 eaca249e96..41935120c1 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
@@ -60,7 +60,7 @@ public class RecordTypes {
public static final Type SorterViewInfo = new Type(1032,null);
public static final Type ExObjList = new Type(1033,null);
public static final Type ExObjListAtom = new Type(1034,null);
- public static final Type PPDrawingGroup = new Type(1035,null);
+ 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);
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/Picture.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/Picture.java
deleted file mode 100644
index 64caff7fa7..0000000000
--- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/Picture.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
-
- Licensed 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.usermodel;
-
-import org.apache.poi.util.LittleEndian;
-
-/**
- * Represents a picture in a PowerPoint document.
- * - * The information about an image in PowerPoint document is stored in - * two places: - *
- * Data in the "Pictures" OLE stream is organized as follows:
- * For each image there is an entry: 25 byte header + image data.
- * Image data is the exact content of the JPEG file, i.e. PowerPoint
- * puts the whole jpeg file there without any modifications.
- * Header format:
- *
Picture class.
+ */
+ public void setType(int format){
+ switch (format){
+ case Picture.JPEG: LittleEndian.putInt(header, 0, -266516832); break;
+ case Picture.PNG: LittleEndian.putInt(header, 0, -266441216); break;
+ }
+ }
+
+ /**
+ * Returns the header of the Picture
+ *
+ * @return the header of the Picture
+ */
+ public byte[] getHeader(){
+ return header;
+ }
+
+ /**
+ * Compute 16-byte checksum of this picture
+ */
+ public static byte[] getChecksum(byte[] data) {
+ MessageDigest sha;
+ try {
+ sha = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e){
+ throw new RuntimeException(e.getMessage());
+ }
+ sha.update(data);
+ return sha.digest();
+ }
+
+ /**
+ * Write this picture into OutputStream
+ */
+ public void write(OutputStream out) throws IOException {
+ out.write(header);
+ out.write(pictdata);
+ }
+
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
index a114ee91f9..ba5e75562f 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
@@ -23,6 +23,10 @@ import java.util.*;
import java.awt.Dimension;
import java.io.*;
+import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hslf.*;
import org.apache.poi.hslf.model.*;
import org.apache.poi.hslf.record.Document;
@@ -50,6 +54,7 @@ import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
* - handle Slide creation cleaner
*
* @author Nick Burch
+ * @author Yegor kozlov
*/
public class SlideShow
@@ -74,6 +79,12 @@ public class SlideShow
// MetaSheets (eg masters) not yet supported
// private MetaSheets[] _msheets;
+
+ /* ===============================================================
+ * Setup Code
+ * ===============================================================
+ */
+
/**
* Constructs a Powerpoint document from the underlying
@@ -86,7 +97,6 @@ public class SlideShow
// Get useful things from our base slideshow
_hslfSlideShow = hslfSlideShow;
_records = _hslfSlideShow.getRecords();
- byte[] _docstream = _hslfSlideShow.getUnderlyingBytes();
// Handle Parent-aware Reocrds
for(int i=0; i<_records.length; i++) {
@@ -100,6 +110,12 @@ public class SlideShow
buildSlidesAndNotes();
}
+ /**
+ * Constructs a new, empty, Powerpoint document.
+ */
+ public SlideShow() throws IOException {
+ this(new HSLFSlideShow());
+ }
/**
* Find the records that are parent-aware, and tell them
@@ -373,6 +389,77 @@ public class SlideShow
}
}
+ /**
+ * Writes out the slideshow file the is represented by an instance of
+ * this class
+ * @param out The OutputStream to write to.
+ * @throws IOException If there is an unexpected IOException from the passed
+ * in OutputStream
+ */
+ public void write(OutputStream out) throws IOException {
+ _hslfSlideShow.write(out);
+ }
+
+
+ /* ===============================================================
+ * Accessor Code
+ * ===============================================================
+ */
+
+
+ /**
+ * Returns an array of the most recent version of all the interesting
+ * records
+ */
+ public Record[] getMostRecentCoreRecords() { return _mostRecentCoreRecords; }
+
+ /**
+ * Returns an array of all the normal Slides found in the slideshow
+ */
+ public Slide[] getSlides() { return _slides; }
+
+ /**
+ * Returns an array of all the normal Notes found in the slideshow
+ */
+ public Notes[] getNotes() { return _notes; }
+
+ /**
+ * Returns an array of all the meta Sheets (master sheets etc)
+ * found in the slideshow
+ */
+ //public MetaSheet[] getMetaSheets() { return _msheets; }
+
+ /**
+ * Returns all the pictures attached to the SlideShow
+ */
+ public PictureData[] getPictures() throws IOException {
+ return _hslfSlideShow.getPictures();
+ }
+
+ /**
+ * Return the current page size
+ */
+ public Dimension getPageSize(){
+ DocumentAtom docatom = _documentRecord.getDocumentAtom();
+ return new Dimension((int)docatom.getSlideSizeX(), (int)docatom.getSlideSizeY());
+ }
+
+ /**
+ * Helper method for usermodel: Get the font collection
+ */
+ protected FontCollection getFontCollection() { return _fonts; }
+ /**
+ * Helper method for usermodel: Get the document record
+ */
+ protected Document getDocumentRecord() { return _documentRecord; }
+
+
+ /* ===============================================================
+ * Addition Code
+ * ===============================================================
+ */
+
+
/**
* Create a blank Slide
.
*
@@ -476,63 +563,87 @@ public class SlideShow
}
- /**
- * Writes out the slideshow file the is represented by an instance of
- * this class
- * @param out The OutputStream to write to.
- * @throws IOException If there is an unexpected IOException from the passed
- * in OutputStream
- */
- public void write(OutputStream out) throws IOException {
- _hslfSlideShow.write(out);
- }
+ /**
+ * Adds a picture to this presentation and returns the associated index.
+ *
+ * @param data picture data
+ * @param format the format of the picture. One of constans defined in the Picture
class.
+ * @return the index to this picture (1 based).
+ */
+ public int addPicture(byte[] data, int format) {
+ byte[] uid = PictureData.getChecksum(data);
+ EscherContainerRecord bstore;
+ int offset = 0;
- // Accesser methods follow
+ EscherContainerRecord dggContainer = _documentRecord.getPPDrawingGroup().getDggContainer();
+ bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
+ if (bstore == null){
+ bstore = new EscherContainerRecord();
+ bstore.setRecordId( EscherContainerRecord.BSTORE_CONTAINER);
- /**
- * Returns an array of the most recent version of all the interesting
- * records
- */
- public Record[] getMostRecentCoreRecords() { return _mostRecentCoreRecords; }
+ List child = dggContainer.getChildRecords();
+ for ( int i = 0; i < child.size(); i++ ) {
+ EscherRecord rec = (EscherRecord)child.get(i);
+ if (rec.getRecordId() == EscherOptRecord.RECORD_ID){
+ child.add(i, bstore);
+ i++;
+ }
+ }
+ dggContainer.setChildRecords(child);
+ } else {
+ List lst = bstore.getChildRecords();
+ for ( int i = 0; i < lst.size(); i++ ) {
+ EscherBSERecord bse = (EscherBSERecord) lst.get(i);
+ if (Arrays.equals(bse.getUid(), uid)){
+ return i + 1;
+ }
+ offset += bse.getSize();
+ }
+ }
- /**
- * Returns an array of all the normal Slides found in the slideshow
- */
- public Slide[] getSlides() { return _slides; }
+ EscherBSERecord bse = new EscherBSERecord();
+ bse.setRecordId(EscherBSERecord.RECORD_ID);
+ bse.setOptions( (short) ( 0x0002 | ( format << 4 ) ) );
+ bse.setSize(data.length + PictureData.HEADER_SIZE);
+ bse.setUid(uid);
+ bse.setBlipTypeMacOS((byte)format);
+ bse.setBlipTypeWin32((byte)format);
- /**
- * Returns an array of all the normal Notes found in the slideshow
- */
- public Notes[] getNotes() { return _notes; }
+ bse.setRef(1);
+ bse.setOffset(offset);
- /**
- * Returns an array of all the meta Sheets (master sheets etc)
- * found in the slideshow
- */
- //public MetaSheet[] getMetaSheets() { return _msheets; }
+ bstore.addChildRecord(bse);
+ int count = bstore.getChildRecords().size();
+ bstore.setOptions((short)( (count << 4) | 0xF ));
- /**
- * Returns all the pictures attached to the SlideShow
- */
- public Picture[] getPictures() throws IOException {
- return _hslfSlideShow.getPictures();
- }
-
- /**
- * Return the current page size
- */
- public Dimension getPageSize(){
- DocumentAtom docatom = _documentRecord.getDocumentAtom();
- return new Dimension((int)docatom.getSlideSizeX(), (int)docatom.getSlideSizeY());
- }
-
- /**
- * Helper method for usermodel: Get the font collection
- */
- protected FontCollection getFontCollection() { return _fonts; }
- /**
- * Helper method for usermodel: Get the document record
- */
- protected Document getDocumentRecord() { return _documentRecord; }
+ PictureData pict = new PictureData();
+ pict.setUID(uid);
+ pict.setData(data);
+ pict.setType(format);
+
+ _hslfSlideShow.addPicture(pict);
+
+ return count;
+ }
+
+ /**
+ * Adds a picture to this presentation and returns the associated index.
+ *
+ * @param pict the file containing the image to add
+ * @param format the format of the picture. One of constans defined in the Picture
class.
+ * @return the index to this picture (1 based).
+ */
+ public int addPicture(File pict, int format) {
+ int length = (int)pict.length();
+ byte[] data = new byte[length];
+ try {
+ FileInputStream is = new FileInputStream(pict);
+ is.read(data);
+ is.close();
+ } catch (IOException e){
+ throw new RuntimeException(e);
+ }
+ return addPicture(data, format);
+ }
}