You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@poi.apache.org by ni...@apache.org on 2006/03/26 18:20:10 UTC

svn commit: r388920 - in /jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf: ./ data/ model/ record/ usermodel/

Author: nick
Date: Sun Mar 26 08:20:08 2006
New Revision: 388920

URL: http://svn.apache.org/viewcvs?rev=388920&view=rev
Log:
Patches from Yegor (Bug #39097), along with some sorting out of indenting, method positioning etc

Added:
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/data/
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt   (with props)
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java
Removed:
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/Picture.java
Modified:
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/Document.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
    jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java Sun Mar 26 08:20:08 2006
@@ -23,7 +23,6 @@
 import java.io.*;
 
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.poifs.filesystem.POIFSDocument;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.DocumentInputStream;
 
@@ -33,10 +32,8 @@
 import org.apache.poi.hpsf.SummaryInformation;
 import org.apache.poi.hpsf.DocumentSummaryInformation;
 
-import org.apache.poi.util.LittleEndian;
-
 import org.apache.poi.hslf.record.*;
-import org.apache.poi.hslf.usermodel.Picture;
+import org.apache.poi.hslf.usermodel.PictureData;
 
 /**
  * This class contains the main functionality for the Powerpoint file 
@@ -47,78 +44,91 @@
 
 public class HSLFSlideShow
 {
-  private InputStream istream;
-  private POIFSFileSystem filesystem;
+	private InputStream istream;
+	private POIFSFileSystem filesystem;
 
-  // Holds metadata on our document
-  private SummaryInformation sInf;
-  private DocumentSummaryInformation dsInf;
-  private CurrentUserAtom currentUser;
+	// Holds metadata on our document
+	private SummaryInformation sInf;
+	private DocumentSummaryInformation dsInf;
+	private CurrentUserAtom currentUser;
 
-  // Low level contents of the file
-  private byte[] _docstream;
+	// Low level contents of the file
+	private byte[] _docstream;
 
-  // Low level contents
-  private Record[] _records;
+	// Low level contents
+	private Record[] _records;
 
-  /**
-   * Constructs a Powerpoint document from fileName. Parses the document 
-   * and places all the important stuff into data structures.
-   *
-   * @param fileName The name of the file to read.
-   * @throws IOException if there is a problem while parsing the document.
-   */
-  public HSLFSlideShow(String fileName) throws IOException
-  {
-  	this(new FileInputStream(fileName));
-  }
+	// Raw Pictures contained in the pictures stream
+	private PictureData[] _pictures;
+
+	/**
+	 * Constructs a Powerpoint document from fileName. Parses the document 
+	 * and places all the important stuff into data structures.
+	 *
+	 * @param fileName The name of the file to read.
+	 * @throws IOException if there is a problem while parsing the document.
+	 */
+	public HSLFSlideShow(String fileName) throws IOException
+	{
+		this(new FileInputStream(fileName));
+	}
   
-  /**
-   * Constructs a Powerpoint document from an input stream. Parses the 
-   * document and places all the important stuff into data structures.
-   *
-   * @param inputStream the source of the data
-   * @throws IOException if there is a problem while parsing the document.
-   */
-  public HSLFSlideShow(InputStream inputStream) throws IOException
-  {
-        //do Ole stuff
+	/**
+	 * Constructs a Powerpoint document from an input stream. Parses the 
+	 * document and places all the important stuff into data structures.
+	 *
+	 * @param inputStream the source of the data
+	 * @throws IOException if there is a problem while parsing the document.
+	 */
+	public HSLFSlideShow(InputStream inputStream) throws IOException
+	{
+		//do Ole stuff
 		this(new POIFSFileSystem(inputStream));
-        istream = inputStream;
-  }
+		istream = inputStream;
+	}
 
-  /**
-   * Constructs a Powerpoint document from a POIFS Filesystem. Parses the 
-   * document and places all the important stuff into data structures.
-   *
-   * @param filesystem the POIFS FileSystem to read from
-   * @throws IOException if there is a problem while parsing the document.
-   */
-  public HSLFSlideShow(POIFSFileSystem filesystem) throws IOException
-  {
+	/**
+	 * Constructs a Powerpoint document from a POIFS Filesystem. Parses the 
+	 * document and places all the important stuff into data structures.
+	 *
+	 * @param filesystem the POIFS FileSystem to read from
+	 * @throws IOException if there is a problem while parsing the document.
+	 */
+	public HSLFSlideShow(POIFSFileSystem filesystem) throws IOException
+	{
 		this.filesystem = filesystem;
 
-        // Go find a PowerPoint document in the stream
-        // Save anything useful we come across
-        readFIB();
+		// Go find a PowerPoint document in the stream
+		// Save anything useful we come across
+		readFIB();
 
 		// Look for Property Streams:
 		readProperties();
-  }
 
+		// Look for Picture Streams:
+		readPictures();
+	}
 
-  /**
-   * Shuts things down. Closes underlying streams etc
-   *
-   * @throws IOException
-   */
-  public void close() throws IOException
-  {
-	if(istream != null) {
-		istream.close();
+	/**
+	 * Constructs a new, empty, Powerpoint document.
+	 */
+	public HSLFSlideShow() throws IOException 
+	{
+		this(HSLFSlideShow.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt"));
+	}
+
+	/**
+	 * Shuts things down. Closes underlying streams etc
+	 *
+	 * @throws IOException
+	 */
+	public void close() throws IOException
+	{
+		if(istream != null) {
+			istream.close();
+		}
+		filesystem = null;
 	}
-	filesystem = null;
-  }
 
 
   /**
@@ -175,24 +185,52 @@
   }
 
 
-  /**
-   * Find the properties from the filesystem, and load them
-   */
-  public void readProperties() {
-	// DocumentSummaryInformation
-	dsInf = (DocumentSummaryInformation)getPropertySet("\005DocumentSummaryInformation");
+	/**
+	 * Find the properties from the filesystem, and load them
+	 */
+	public void readProperties() {
+		// DocumentSummaryInformation
+		dsInf = (DocumentSummaryInformation)getPropertySet("\005DocumentSummaryInformation");
 
-	// SummaryInformation
-	sInf = (SummaryInformation)getPropertySet("\005SummaryInformation");
+		// SummaryInformation
+		sInf = (SummaryInformation)getPropertySet("\005SummaryInformation");
 
-	// Current User
-	try {
-		currentUser = new CurrentUserAtom(filesystem);
-	} catch(IOException ie) {
-		System.err.println("Error finding Current User Atom:\n" + ie);
-		currentUser = new CurrentUserAtom();
+		// Current User
+		try {
+			currentUser = new CurrentUserAtom(filesystem);
+		} catch(IOException ie) {
+			System.err.println("Error finding Current User Atom:\n" + ie);
+			currentUser = new CurrentUserAtom();
+		}
+	}
+
+	/**
+	 * Find and read in pictures contained in this presentation
+	 */
+	private void readPictures() 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 - will use a null set instead
+			return;
+		}
+
+		ArrayList p = new ArrayList();
+		int pos = 0; 
+		while (pos < pictstream.length) {
+			PictureData pict = new PictureData(pictstream, pos);
+			p.add(pict);
+			pos += PictureData.HEADER_SIZE + pict.getSize();
+		}
+
+		_pictures = (PictureData[])p.toArray(new PictureData[p.size()]);
 	}
-  }
 
 
   /** 
@@ -287,6 +325,17 @@
 	currentUser.setCurrentEditOffset(newLastUserEditAtomPos.intValue());
 	currentUser.writeToFS(outFS);
 
+	
+	// Write any pictures, into another stream
+	if (_pictures != null) {
+		ByteArrayOutputStream pict = new ByteArrayOutputStream();
+		for (int i = 0; i < _pictures.length; i++ ) {
+			_pictures[i].write(pict);
+		}
+		outFS.createDocument(
+				new ByteArrayInputStream(pict.toByteArray()), "Pictures"
+		);
+	}
 
 	// Send the POIFSFileSystem object out to the underlying stream
 	outFS.writeFilesystem(out);
@@ -311,87 +360,86 @@
   }
 
 
-  /* ******************* fetching methods follow ********************* */
+	/* ******************* adding methods follow ********************* */
 
+	/**
+	 * Adds a new root level record, at the end, but before the last
+	 *  PersistPtrIncrementalBlock.
+	 */
+	public synchronized int appendRootLevelRecord(Record newRecord) {
+		int addedAt = -1;
+		Record[] r = new Record[_records.length+1];
+		boolean added = false;
+		for(int i=(_records.length-1); i>=0; i--) {
+			if(added) {
+				// Just copy over
+				r[i] = _records[i];
+			} else {
+				r[(i+1)] = _records[i];
+				if(_records[i] instanceof PersistPtrHolder) {
+					r[i] = newRecord;
+					added = true;
+					addedAt = i;
+				}
+			}
+		}
+		_records = r;
+		return addedAt;
+	}
+	
+	/**
+	 *  Add a new picture to this presentation.
+	 */
+	public void addPicture(PictureData img) {
+		// Copy over the existing pictures, into an array one bigger
+		PictureData[] lst;
+		if(_pictures == null) {
+			lst = new PictureData[1];
+		} else {
+			lst = new PictureData[(_pictures.length+1)];
+			System.arraycopy(_pictures,0,lst,0,_pictures.length);
+		}
+		// Add in the new image
+		lst[lst.length - 1] = img;
+		_pictures = lst;
+	}
 
-  /**
-   * Returns an array of all the records found in the slideshow
-   */
-  public Record[] getRecords() { return _records; }
-  
-  /**
-   * Adds a new root level record, at the end, but before the last
-   *  PersistPtrIncrementalBlock.
-   */
-  public synchronized int appendRootLevelRecord(Record newRecord) {
-	  int addedAt = -1;
-	  Record[] r = new Record[_records.length+1];
-	  boolean added = false;
-	  for(int i=(_records.length-1); i>=0; i--) {
-		  if(added) {
-			  // Just copy over
-			  r[i] = _records[i];
-		  } else {
-			  r[(i+1)] = _records[i];
-			  if(_records[i] instanceof PersistPtrHolder) {
-				  r[i] = newRecord;
-				  added = true;
-				  addedAt = i;
-			  }
-		  }
-	  }
-	  _records = r;
-	  return addedAt;
-  }
+	/* ******************* fetching methods follow ********************* */
 
-  /**
-   * Returns an array of the bytes of the file. Only correct after a
-   *  call to open or write - at all other times might be wrong!
-   */
-  public byte[] getUnderlyingBytes() { return _docstream; }
 
-  /** 
-   * Fetch the Document Summary Information of the document
-   */
-  public DocumentSummaryInformation getDocumentSummaryInformation() { return dsInf; }
+	/**
+	 * Returns an array of all the records found in the slideshow
+	 */
+	public Record[] getRecords() { return _records; }
 
-  /** 
-   * Fetch the Summary Information of the document
-   */
-  public SummaryInformation getSummaryInformation() { return sInf; }
+	/**
+	 * Returns an array of the bytes of the file. Only correct after a
+	 *  call to open or write - at all other times might be wrong!
+	 */
+	public byte[] getUnderlyingBytes() { return _docstream; }
 
- /**
-  * Fetch the Current User Atom of the document
-  */
- public CurrentUserAtom getCurrentUserAtom() { return currentUser; }
+	/** 
+	 * Fetch the Document Summary Information of the document
+	 */
+	public DocumentSummaryInformation getDocumentSummaryInformation() { return dsInf; }
+
+	/** 
+	 * Fetch the Summary Information of the document
+	 */
+	public SummaryInformation getSummaryInformation() { return sInf; }
 
 	/**
-	 *  Read pictures contained in this presentation
+	 * Fetch the Current User Atom of the document
+	 */
+	public CurrentUserAtom getCurrentUserAtom() { return currentUser; }
+
+	/**
+	 *  Return array of pictures contained in this presentation
 	 *
-	 *  @return array with the read pictures ot <code>null</code> if the
+	 *  @return array with the read pictures or <code>null</code> 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;
 	}
 }

Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt?rev=388920&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java Sun Mar 26 08:20:08 2006
@@ -33,16 +33,15 @@
 
     public Ellipse(Shape parent){
         super(null, parent);
-        _escherContainer = create(parent instanceof ShapeGroup);
+        _escherContainer = createSpContainer(parent instanceof ShapeGroup);
     }
 
     public Ellipse(){
         this(null);
     }
 
-    protected EscherContainerRecord create(boolean isChild){
-        EscherContainerRecord spcont = super.create(isChild);
-        spcont.setOptions((short)15);
+    protected EscherContainerRecord createSpContainer(boolean isChild){
+        EscherContainerRecord spcont = super.createSpContainer(isChild);
 
         EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
         short type = (ShapeTypes.Ellipse << 4) + 2;

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Line.java Sun Mar 26 08:20:08 2006
@@ -96,16 +96,15 @@
 
     public Line(Shape parent){
         super(null, parent);
-        _escherContainer = create(parent instanceof ShapeGroup);
+        _escherContainer = createSpContainer(parent instanceof ShapeGroup);
     }
 
     public Line(){
         this(null);
     }
 
-    protected EscherContainerRecord create(boolean isChild){
-        EscherContainerRecord spcont = super.create(isChild);
-        spcont.setOptions((short)15);
+    protected EscherContainerRecord createSpContainer(boolean isChild){
+        EscherContainerRecord spcont = super.createSpContainer(isChild);
 
         EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
         short type = (ShapeTypes.Line << 4) + 2;

Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java?rev=388920&view=auto
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java (added)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java Sun Mar 26 08:20:08 2006
@@ -0,0 +1,137 @@
+package org.apache.poi.hslf.model;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.usermodel.PictureData;
+import org.apache.poi.hslf.usermodel.SlideShow;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+
+/**
+ * Represents a picture in a PowerPoint document.
+ * <p>
+ * The information about an image in PowerPoint document is stored in
+ * two places:
+ *  <li> EscherBSE container in the Document keeps information about image
+ *    type, image index to refer by slides etc.
+ *  <li> "Pictures" OLE stream holds the actual data of the image.
+ * </p>
+ * <p>
+ *  Data in the "Pictures" OLE stream is organized as follows:<br>
+ *  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.<br>
+ *   Header format:
+ *    <li> 2 byte: image type. For JPEGs it is 0x46A0, for PNG it is 0x6E00.
+ *    <li> 2 byte: unknown.
+ *    <li> 4 byte : image size + 17. Looks like shift from the end of
+ *          header but why to add it to the image  size?
+ *    <li> next 16 bytes. Unique identifier of this image which is used by
+ *          EscherBSE record.
+ *  </p>
+ *
+ * @author Yegor Kozlov
+ */
+public class Picture extends SimpleShape {
+
+    /**
+    *  Windows Metafile
+    *  ( NOT YET SUPPORTED )
+    */
+    public static final int WMF = 3;
+
+    /**
+    * Macintosh PICT
+     *  ( NOT YET SUPPORTED )
+    */
+    public static final int PICT = 4;
+
+    /**
+    *  JPEG
+    */
+    public static final int JPEG = 5;
+
+    /**
+    *  PNG
+    */
+    public static final int PNG = 6;
+
+    /**
+    * Windows DIB (BMP)
+    */
+    public static final int DIB = 7;
+
+    /**
+     * Create a new <code>Picture</code>
+     *
+    * @param idx the index of the picture
+     */
+    public Picture(int idx){
+        super(null, null);
+        _escherContainer = createSpContainer(idx);
+    }
+
+    /**
+      * Create a <code>Picture</code> object
+      *
+      * @param escherRecord the <code>EscherSpContainer</code> record which holds information about
+      *        this picture in the <code>Slide</code>
+      * @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 <code>EscherSp</code> record which holds information about this picture.
+
+     * @param idx the index of the picture which referes to <code>EscherBSE</code> 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));
+    }
+}

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java Sun Mar 26 08:20:08 2006
@@ -33,15 +33,15 @@
 
     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);

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java Sun Mar 26 08:20:08 2006
@@ -26,25 +26,37 @@
   *
   * @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.
+     * <code>null</code> 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       <code>EscherSpContainer</code> 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 @@
         setAnchor(anchor);
     }
 
-    protected static EscherRecord getEscherChild(EscherContainerRecord owner, int recordId){
+    /**
+     * Helper method to return escher child by record ID
+     *
+     * @return escher record or <code>null</code> 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 <code>null</code> 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 @@
         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 @@
     }
 
     /**
-     *
-     * @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;
     }
 }

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java Sun Mar 26 08:20:08 2006
@@ -37,10 +37,10 @@
         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 @@
                 shape = new ShapeGroup(spContainer, parent);
                 break;
             default:
-                shape = new Shape(spContainer, parent);
+                shape = new SimpleShape(spContainer, parent);
                 break;
         }
         return shape;

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java Sun Mar 26 08:20:08 2006
@@ -27,13 +27,9 @@
  */
 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 @@
     /**
      * Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> 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 @@
      * @param shape - the Shape to add
      */
     public void addShape(Shape shape){
-        _escherContainer.addChildRecord(shape.getShapeRecord());
+        _escherContainer.addChildRecord(shape.getSpContainer());
     }
 
     /**

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java Sun Mar 26 08:20:08 2006
@@ -158,7 +158,7 @@
 
 	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);

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java Sun Mar 26 08:20:08 2006
@@ -39,10 +39,10 @@
      * @param isChild   <code>true</code> if the Line is inside a group, <code>false</code> 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;

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/Document.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/Document.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/Document.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/Document.java Sun Mar 26 08:20:08 2006
@@ -36,6 +36,7 @@
 	// Links to our more interesting children
 	private DocumentAtom documentAtom;
 	private Environment environment;
+	private PPDrawingGroup ppDrawing;
 	private SlideListWithText[] slwts;
 
 	/**
@@ -48,6 +49,11 @@
 	 */
 	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
 	 *  properties, which are referred to by the slides.
@@ -81,6 +87,9 @@
 			}
 			if(_children[i] instanceof Environment) {
 				environment = (Environment)_children[i];
+			}
+			if(_children[i] instanceof PPDrawingGroup) {
+				ppDrawing = (PPDrawingGroup)_children[i];
 			}
 		}
 		// Now grab them all

Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java?rev=388920&view=auto
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java (added)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/PPDrawingGroup.java Sun Mar 26 08:20:08 2006
@@ -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;
+    }
+}

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java Sun Mar 26 08:20:08 2006
@@ -60,7 +60,7 @@
     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);

Added: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java?rev=388920&view=auto
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java (added)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java Sun Mar 26 08:20:08 2006
@@ -0,0 +1,157 @@
+/* ====================================================================
+   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;
+import org.apache.poi.hslf.model.Picture;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * A class that represents the image data contained in the Presentation.
+ *
+ *  @author Yegor Kozlov
+ */
+public class PictureData {
+
+	/**
+	* The size of the header
+	*/
+	public static final int HEADER_SIZE = 25;
+
+	/**
+	* Binary data of the picture
+	*/
+	protected byte[] pictdata;
+
+	/**
+	* Header which holds information about this picture
+	*/
+	protected byte[] header;
+
+    public PictureData(){
+        header = new byte[PictureData.HEADER_SIZE];
+    }
+
+	/**
+	* Read a picture from "Pictures" OLE stream
+	*
+	* @param pictstream    the bytes to read
+	* @param offset        the index of the first byte to read
+	*/
+	public PictureData(byte[] pictstream, int offset){
+		header = new byte[PictureData.HEADER_SIZE];
+		System.arraycopy(pictstream, offset, header, 0, header.length);
+
+		int size = LittleEndian.getInt(header, 4) - 17;
+		pictdata = new byte[size];
+		System.arraycopy(pictstream, offset + PictureData.HEADER_SIZE, pictdata, 0, pictdata.length);
+	}
+
+	/**
+	* @return  the binary data of this picture
+	*/
+	public byte[] getData(){
+		return pictdata;
+	}
+
+    /**
+     *  Set picture data
+     */
+    public void setData(byte[] data) {
+        pictdata = data;
+        LittleEndian.putInt(header, 4, data.length + 17);
+    }
+
+	/**
+	* Return image size in bytes
+	*
+	* @return the size of the picture in bytes
+	*/
+	public int getSize(){
+		return pictdata.length;
+	}
+
+	/**
+	* Returns the unique identifier (UID) of this picture.
+	* The UID is a checksum of the picture data. Its length is 16 bytes
+	* and it must be unique across the presentation.
+	*
+	* @return the unique identifier of this picture
+	*/
+	public byte[] getUID(){
+		byte[] uid = new byte[16];
+		System.arraycopy(header, 8, uid, 0, uid.length);
+		return uid;
+	}
+
+    /**
+     * Set the unique identifier (UID) of this picture.
+     *
+     * @param uid checksum of the picture data
+     */
+    public void setUID(byte[] uid){
+        System.arraycopy(uid, 0, header, 8, uid.length);
+    }
+
+	/**
+	* Set the type of this picture.
+	*
+	* @return type of this picture.
+    * Must be one of the static constans defined in the <code>Picture<code> 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 <code>OutputStream</code>
+     */
+    public void write(OutputStream out) throws IOException {
+        out.write(header);
+        out.write(pictdata);
+    }
+
+}

Modified: jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java
URL: http://svn.apache.org/viewcvs/jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java?rev=388920&r1=388919&r2=388920&view=diff
==============================================================================
--- jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java (original)
+++ jakarta/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java Sun Mar 26 08:20:08 2006
@@ -23,6 +23,10 @@
 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 @@
  *  - handle Slide creation cleaner
  * 
  * @author Nick Burch
+ * @author Yegor kozlov
  */
 
 public class SlideShow
@@ -74,6 +79,12 @@
   // MetaSheets (eg masters) not yet supported
   // private MetaSheets[] _msheets;
 
+  
+  /* ===============================================================
+   *                       Setup Code
+   * ===============================================================
+   */
+  
 
   /**
    * Constructs a Powerpoint document from the underlying 
@@ -86,7 +97,6 @@
 	// 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 @@
 	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 @@
 	}
   }
 
+  /**
+   * 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 <code>Slide</code>.
 	 *
@@ -476,63 +563,87 @@
 	}
 
 
-  /**
-   * 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);
-   }
-
-
-	// Accesser methods follow
-
-	/**
-	 * 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 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; }
+    /**
+     * 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 <code>Picture</code> 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;
+
+        EscherContainerRecord dggContainer = _documentRecord.getPPDrawingGroup().getDggContainer();
+        bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
+        if (bstore == null){
+            bstore = new EscherContainerRecord();
+            bstore.setRecordId( EscherContainerRecord.BSTORE_CONTAINER);
+
+            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();
+             }
+        }
+
+        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);
+
+        bse.setRef(1);
+        bse.setOffset(offset);
+
+        bstore.addChildRecord(bse);
+        int count = bstore.getChildRecords().size();
+        bstore.setOptions((short)( (count << 4) | 0xF ));
+
+        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 <code>Picture</code> 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);
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: poi-dev-unsubscribe@jakarta.apache.org
Mailing List:    http://jakarta.apache.org/site/mail2.html#poi
The Apache Jakarta POI Project: http://jakarta.apache.org/poi/