Patches from Yegor (Bug #39097), along with some sorting out of indenting, method positioning etc
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@388920 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f213a74d5a
commit
7067a15892
@ -23,7 +23,6 @@ import java.util.*;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
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.DocumentEntry;
|
||||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||||
|
|
||||||
@ -33,10 +32,8 @@ import org.apache.poi.hpsf.MutablePropertySet;
|
|||||||
import org.apache.poi.hpsf.SummaryInformation;
|
import org.apache.poi.hpsf.SummaryInformation;
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
|
|
||||||
import org.apache.poi.util.LittleEndian;
|
|
||||||
|
|
||||||
import org.apache.poi.hslf.record.*;
|
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
|
* This class contains the main functionality for the Powerpoint file
|
||||||
@ -47,78 +44,91 @@ import org.apache.poi.hslf.usermodel.Picture;
|
|||||||
|
|
||||||
public class HSLFSlideShow
|
public class HSLFSlideShow
|
||||||
{
|
{
|
||||||
private InputStream istream;
|
private InputStream istream;
|
||||||
private POIFSFileSystem filesystem;
|
private POIFSFileSystem filesystem;
|
||||||
|
|
||||||
// Holds metadata on our document
|
// Holds metadata on our document
|
||||||
private SummaryInformation sInf;
|
private SummaryInformation sInf;
|
||||||
private DocumentSummaryInformation dsInf;
|
private DocumentSummaryInformation dsInf;
|
||||||
private CurrentUserAtom currentUser;
|
private CurrentUserAtom currentUser;
|
||||||
|
|
||||||
// Low level contents of the file
|
// Low level contents of the file
|
||||||
private byte[] _docstream;
|
private byte[] _docstream;
|
||||||
|
|
||||||
// Low level contents
|
// Low level contents
|
||||||
private Record[] _records;
|
private Record[] _records;
|
||||||
|
|
||||||
/**
|
// Raw Pictures contained in the pictures stream
|
||||||
* Constructs a Powerpoint document from fileName. Parses the document
|
private PictureData[] _pictures;
|
||||||
* and places all the important stuff into data structures.
|
|
||||||
*
|
/**
|
||||||
* @param fileName The name of the file to read.
|
* Constructs a Powerpoint document from fileName. Parses the document
|
||||||
* @throws IOException if there is a problem while parsing the document.
|
* and places all the important stuff into data structures.
|
||||||
*/
|
*
|
||||||
public HSLFSlideShow(String fileName) throws IOException
|
* @param fileName The name of the file to read.
|
||||||
{
|
* @throws IOException if there is a problem while parsing the document.
|
||||||
this(new FileInputStream(fileName));
|
*/
|
||||||
}
|
public HSLFSlideShow(String fileName) throws IOException
|
||||||
|
{
|
||||||
|
this(new FileInputStream(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a Powerpoint document from an input stream. Parses the
|
* Constructs a Powerpoint document from an input stream. Parses the
|
||||||
* document and places all the important stuff into data structures.
|
* document and places all the important stuff into data structures.
|
||||||
*
|
*
|
||||||
* @param inputStream the source of the data
|
* @param inputStream the source of the data
|
||||||
* @throws IOException if there is a problem while parsing the document.
|
* @throws IOException if there is a problem while parsing the document.
|
||||||
*/
|
*/
|
||||||
public HSLFSlideShow(InputStream inputStream) throws IOException
|
public HSLFSlideShow(InputStream inputStream) throws IOException
|
||||||
{
|
{
|
||||||
//do Ole stuff
|
//do Ole stuff
|
||||||
this(new POIFSFileSystem(inputStream));
|
this(new POIFSFileSystem(inputStream));
|
||||||
istream = inputStream;
|
istream = inputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a Powerpoint document from a POIFS Filesystem. Parses the
|
* Constructs a Powerpoint document from a POIFS Filesystem. Parses the
|
||||||
* document and places all the important stuff into data structures.
|
* document and places all the important stuff into data structures.
|
||||||
*
|
*
|
||||||
* @param filesystem the POIFS FileSystem to read from
|
* @param filesystem the POIFS FileSystem to read from
|
||||||
* @throws IOException if there is a problem while parsing the document.
|
* @throws IOException if there is a problem while parsing the document.
|
||||||
*/
|
*/
|
||||||
public HSLFSlideShow(POIFSFileSystem filesystem) throws IOException
|
public HSLFSlideShow(POIFSFileSystem filesystem) throws IOException
|
||||||
{
|
{
|
||||||
this.filesystem = filesystem;
|
this.filesystem = filesystem;
|
||||||
|
|
||||||
// Go find a PowerPoint document in the stream
|
// Go find a PowerPoint document in the stream
|
||||||
// Save anything useful we come across
|
// Save anything useful we come across
|
||||||
readFIB();
|
readFIB();
|
||||||
|
|
||||||
// Look for Property Streams:
|
// Look for Property Streams:
|
||||||
readProperties();
|
readProperties();
|
||||||
}
|
|
||||||
|
|
||||||
|
// Look for Picture Streams:
|
||||||
/**
|
readPictures();
|
||||||
* Shuts things down. Closes underlying streams etc
|
}
|
||||||
*
|
|
||||||
* @throws IOException
|
/**
|
||||||
*/
|
* Constructs a new, empty, Powerpoint document.
|
||||||
public void close() throws IOException
|
*/
|
||||||
{
|
public HSLFSlideShow() throws IOException
|
||||||
if(istream != null) {
|
{
|
||||||
istream.close();
|
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 @@ public class HSLFSlideShow
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the properties from the filesystem, and load them
|
* Find the properties from the filesystem, and load them
|
||||||
*/
|
*/
|
||||||
public void readProperties() {
|
public void readProperties() {
|
||||||
// DocumentSummaryInformation
|
// DocumentSummaryInformation
|
||||||
dsInf = (DocumentSummaryInformation)getPropertySet("\005DocumentSummaryInformation");
|
dsInf = (DocumentSummaryInformation)getPropertySet("\005DocumentSummaryInformation");
|
||||||
|
|
||||||
// SummaryInformation
|
// SummaryInformation
|
||||||
sInf = (SummaryInformation)getPropertySet("\005SummaryInformation");
|
sInf = (SummaryInformation)getPropertySet("\005SummaryInformation");
|
||||||
|
|
||||||
// Current User
|
// Current User
|
||||||
try {
|
try {
|
||||||
currentUser = new CurrentUserAtom(filesystem);
|
currentUser = new CurrentUserAtom(filesystem);
|
||||||
} catch(IOException ie) {
|
} catch(IOException ie) {
|
||||||
System.err.println("Error finding Current User Atom:\n" + ie);
|
System.err.println("Error finding Current User Atom:\n" + ie);
|
||||||
currentUser = new CurrentUserAtom();
|
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 @@ public class HSLFSlideShow
|
|||||||
currentUser.setCurrentEditOffset(newLastUserEditAtomPos.intValue());
|
currentUser.setCurrentEditOffset(newLastUserEditAtomPos.intValue());
|
||||||
currentUser.writeToFS(outFS);
|
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
|
// Send the POIFSFileSystem object out to the underlying stream
|
||||||
outFS.writeFilesystem(out);
|
outFS.writeFilesystem(out);
|
||||||
@ -311,87 +360,86 @@ public class HSLFSlideShow
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ******************* fetching methods follow ********************* */
|
/* ******************* adding methods follow ********************* */
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the Summary Information of the document
|
|
||||||
*/
|
|
||||||
public SummaryInformation getSummaryInformation() { return sInf; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the Current User Atom of the document
|
|
||||||
*/
|
|
||||||
public CurrentUserAtom getCurrentUserAtom() { return currentUser; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read pictures contained in this presentation
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ******************* fetching methods follow ********************* */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of all the records found in the slideshow
|
||||||
|
*/
|
||||||
|
public Record[] getRecords() { return _records; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the Summary Information of the document
|
||||||
|
*/
|
||||||
|
public SummaryInformation getSummaryInformation() { return sInf; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* presentation doesn't contain pictures.
|
||||||
*/
|
*/
|
||||||
public Picture[] getPictures() throws IOException {
|
public PictureData[] getPictures() {
|
||||||
byte[] pictstream;
|
return _pictures;
|
||||||
|
|
||||||
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()]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt
Normal file
BIN
src/scratchpad/src/org/apache/poi/hslf/data/empty.ppt
Normal file
Binary file not shown.
@ -33,16 +33,15 @@ public class Ellipse extends SimpleShape {
|
|||||||
|
|
||||||
public Ellipse(Shape parent){
|
public Ellipse(Shape parent){
|
||||||
super(null, parent);
|
super(null, parent);
|
||||||
_escherContainer = create(parent instanceof ShapeGroup);
|
_escherContainer = createSpContainer(parent instanceof ShapeGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ellipse(){
|
public Ellipse(){
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EscherContainerRecord create(boolean isChild){
|
protected EscherContainerRecord createSpContainer(boolean isChild){
|
||||||
EscherContainerRecord spcont = super.create(isChild);
|
EscherContainerRecord spcont = super.createSpContainer(isChild);
|
||||||
spcont.setOptions((short)15);
|
|
||||||
|
|
||||||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
||||||
short type = (ShapeTypes.Ellipse << 4) + 2;
|
short type = (ShapeTypes.Ellipse << 4) + 2;
|
||||||
|
@ -96,16 +96,15 @@ public class Line extends SimpleShape {
|
|||||||
|
|
||||||
public Line(Shape parent){
|
public Line(Shape parent){
|
||||||
super(null, parent);
|
super(null, parent);
|
||||||
_escherContainer = create(parent instanceof ShapeGroup);
|
_escherContainer = createSpContainer(parent instanceof ShapeGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Line(){
|
public Line(){
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EscherContainerRecord create(boolean isChild){
|
protected EscherContainerRecord createSpContainer(boolean isChild){
|
||||||
EscherContainerRecord spcont = super.create(isChild);
|
EscherContainerRecord spcont = super.createSpContainer(isChild);
|
||||||
spcont.setOptions((short)15);
|
|
||||||
|
|
||||||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
||||||
short type = (ShapeTypes.Line << 4) + 2;
|
short type = (ShapeTypes.Line << 4) + 2;
|
||||||
|
137
src/scratchpad/src/org/apache/poi/hslf/model/Picture.java
Normal file
137
src/scratchpad/src/org/apache/poi/hslf/model/Picture.java
Normal file
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -33,15 +33,15 @@ public class Rectangle extends SimpleShape {
|
|||||||
|
|
||||||
public Rectangle(Shape parent){
|
public Rectangle(Shape parent){
|
||||||
super(null, parent);
|
super(null, parent);
|
||||||
_escherContainer = create(parent instanceof ShapeGroup);
|
_escherContainer = createSpContainer(parent instanceof ShapeGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle(){
|
public Rectangle(){
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EscherContainerRecord create(boolean isChild){
|
protected EscherContainerRecord createSpContainer(boolean isChild){
|
||||||
EscherContainerRecord spcont = super.create(isChild);
|
EscherContainerRecord spcont = super.createSpContainer(isChild);
|
||||||
spcont.setOptions((short)15);
|
spcont.setOptions((short)15);
|
||||||
|
|
||||||
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);
|
||||||
|
@ -26,25 +26,37 @@ import java.util.Iterator;
|
|||||||
*
|
*
|
||||||
* @author Yegor Kozlov
|
* @author Yegor Kozlov
|
||||||
*/
|
*/
|
||||||
public class Shape {
|
public abstract class Shape {
|
||||||
|
|
||||||
public static final int EMU_PER_POINT = 12700;
|
public static final int EMU_PER_POINT = 12700;
|
||||||
|
|
||||||
/**
|
|
||||||
* The parent of the shape
|
|
||||||
*/
|
|
||||||
protected Shape _parent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Either EscherSpContainer or EscheSpgrContainer record
|
* Either EscherSpContainer or EscheSpgrContainer record
|
||||||
* which holds information about this shape.
|
* which holds information about this shape.
|
||||||
*/
|
*/
|
||||||
protected EscherContainerRecord _escherContainer;
|
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;
|
_escherContainer = escherRecord;
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the lowerlevel escher records for this shape.
|
||||||
|
*/
|
||||||
|
protected abstract EscherContainerRecord createSpContainer(boolean isChild);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the parent of this shape
|
* @return the parent of this shape
|
||||||
@ -128,17 +140,27 @@ public class Shape {
|
|||||||
setAnchor(anchor);
|
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(); )
|
for ( Iterator iterator = owner.getChildRecords().iterator(); iterator.hasNext(); )
|
||||||
{
|
{
|
||||||
EscherRecord escherRecord = (EscherRecord) iterator.next();
|
EscherRecord escherRecord = (EscherRecord) iterator.next();
|
||||||
if (escherRecord.getRecordId() == recordId)
|
if (escherRecord.getRecordId() == recordId)
|
||||||
return (EscherRecord) escherRecord;
|
return escherRecord;
|
||||||
}
|
}
|
||||||
return null;
|
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(); )
|
for ( Iterator iterator = opt.getEscherProperties().iterator(); iterator.hasNext(); )
|
||||||
{
|
{
|
||||||
EscherProperty prop = (EscherProperty) iterator.next();
|
EscherProperty prop = (EscherProperty) iterator.next();
|
||||||
@ -148,7 +170,14 @@ public class Shape {
|
|||||||
return null;
|
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();
|
java.util.List props = opt.getEscherProperties();
|
||||||
for ( Iterator iterator = props.iterator(); iterator.hasNext(); ) {
|
for ( Iterator iterator = props.iterator(); iterator.hasNext(); ) {
|
||||||
EscherProperty prop = (EscherProperty) iterator.next();
|
EscherProperty prop = (EscherProperty) iterator.next();
|
||||||
@ -163,10 +192,10 @@ public class Shape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @return The shape container and it's children that can represent this
|
||||||
* @return escher container which holds information about this shape
|
* shape.
|
||||||
*/
|
*/
|
||||||
public EscherContainerRecord getShapeRecord(){
|
public EscherContainerRecord getSpContainer(){
|
||||||
return _escherContainer;
|
return _escherContainer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,10 @@ public class ShapeFactory {
|
|||||||
switch (type){
|
switch (type){
|
||||||
case ShapeTypes.TextBox:
|
case ShapeTypes.TextBox:
|
||||||
case ShapeTypes.Rectangle:
|
case ShapeTypes.Rectangle:
|
||||||
shape = new Shape(spContainer, parent);
|
shape = new Rectangle(spContainer, parent);
|
||||||
break;
|
break;
|
||||||
case ShapeTypes.PictureFrame:
|
case ShapeTypes.PictureFrame:
|
||||||
shape = new Shape(spContainer, parent);
|
shape = new Picture(spContainer, parent);
|
||||||
break;
|
break;
|
||||||
case ShapeTypes.Line:
|
case ShapeTypes.Line:
|
||||||
shape = new Line(spContainer, parent);
|
shape = new Line(spContainer, parent);
|
||||||
@ -52,7 +52,7 @@ public class ShapeFactory {
|
|||||||
shape = new ShapeGroup(spContainer, parent);
|
shape = new ShapeGroup(spContainer, parent);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
shape = new Shape(spContainer, parent);
|
shape = new SimpleShape(spContainer, parent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return shape;
|
return shape;
|
||||||
|
@ -27,13 +27,9 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class ShapeGroup extends Shape{
|
public class ShapeGroup extends Shape{
|
||||||
|
|
||||||
public ShapeGroup(Shape parent){
|
|
||||||
super(null, parent);
|
|
||||||
_escherContainer = create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShapeGroup(){
|
public ShapeGroup(){
|
||||||
this(null);
|
this(null, null);
|
||||||
|
_escherContainer = createSpContainer(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ShapeGroup(EscherContainerRecord escherRecord, Shape parent){
|
protected ShapeGroup(EscherContainerRecord escherRecord, Shape parent){
|
||||||
@ -91,7 +87,7 @@ public class ShapeGroup extends Shape{
|
|||||||
/**
|
/**
|
||||||
* Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> which represents a group of shapes
|
* 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();
|
EscherContainerRecord spgr = new EscherContainerRecord();
|
||||||
spgr.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
|
spgr.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
|
||||||
spgr.setOptions((short)15);
|
spgr.setOptions((short)15);
|
||||||
@ -124,7 +120,7 @@ public class ShapeGroup extends Shape{
|
|||||||
* @param shape - the Shape to add
|
* @param shape - the Shape to add
|
||||||
*/
|
*/
|
||||||
public void addShape(Shape shape){
|
public void addShape(Shape shape){
|
||||||
_escherContainer.addChildRecord(shape.getShapeRecord());
|
_escherContainer.addChildRecord(shape.getSpContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,7 +158,7 @@ public abstract class Sheet
|
|||||||
|
|
||||||
EscherContainerRecord dgContainer = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
|
EscherContainerRecord dgContainer = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
|
||||||
EscherContainerRecord spgr = (EscherContainerRecord)Shape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER);
|
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);
|
EscherDgRecord dg = (EscherDgRecord)Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
|
||||||
dg.setNumShapes(dg.getNumShapes()+1);
|
dg.setNumShapes(dg.getNumShapes()+1);
|
||||||
|
@ -39,10 +39,10 @@ public class SimpleShape extends Shape {
|
|||||||
* @param isChild <code>true</code> if the Line is inside a group, <code>false</code> otherwise
|
* @param isChild <code>true</code> if the Line is inside a group, <code>false</code> otherwise
|
||||||
* @return the record container which holds this shape
|
* @return the record container which holds this shape
|
||||||
*/
|
*/
|
||||||
protected EscherContainerRecord create(boolean isChild) {
|
protected EscherContainerRecord createSpContainer(boolean isChild) {
|
||||||
EscherContainerRecord spContainer = new EscherContainerRecord();
|
EscherContainerRecord spContainer = new EscherContainerRecord();
|
||||||
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
||||||
//spContainer.setOptions((short)15);
|
spContainer.setOptions((short)15);
|
||||||
|
|
||||||
EscherSpRecord sp = new EscherSpRecord();
|
EscherSpRecord sp = new EscherSpRecord();
|
||||||
int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE;
|
int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE;
|
||||||
|
@ -36,6 +36,7 @@ public class Document extends PositionDependentRecordContainer
|
|||||||
// Links to our more interesting children
|
// Links to our more interesting children
|
||||||
private DocumentAtom documentAtom;
|
private DocumentAtom documentAtom;
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
private PPDrawingGroup ppDrawing;
|
||||||
private SlideListWithText[] slwts;
|
private SlideListWithText[] slwts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,6 +48,11 @@ public class Document extends PositionDependentRecordContainer
|
|||||||
* settings for the document in it
|
* settings for the document in it
|
||||||
*/
|
*/
|
||||||
public Environment getEnvironment() { return environment; }
|
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
|
* Returns all the SlideListWithTexts that are defined for
|
||||||
* this Document. They hold the text, and some of the text
|
* 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) {
|
if(_children[i] instanceof Environment) {
|
||||||
environment = (Environment)_children[i];
|
environment = (Environment)_children[i];
|
||||||
}
|
}
|
||||||
|
if(_children[i] instanceof PPDrawingGroup) {
|
||||||
|
ppDrawing = (PPDrawingGroup)_children[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Now grab them all
|
// Now grab them all
|
||||||
slwts = new SlideListWithText[slwtcount];
|
slwts = new SlideListWithText[slwtcount];
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -60,7 +60,7 @@ public class RecordTypes {
|
|||||||
public static final Type SorterViewInfo = new Type(1032,null);
|
public static final Type SorterViewInfo = new Type(1032,null);
|
||||||
public static final Type ExObjList = new Type(1033,null);
|
public static final Type ExObjList = new Type(1033,null);
|
||||||
public static final Type ExObjListAtom = new Type(1034,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 PPDrawing = new Type(1036,PPDrawing.class);
|
||||||
public static final Type NamedShows = new Type(1040,null);
|
public static final Type NamedShows = new Type(1040,null);
|
||||||
public static final Type NamedShow = new Type(1041,null);
|
public static final Type NamedShow = new Type(1041,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.
|
|
||||||
* <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 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Windows Metafile
|
|
||||||
*/
|
|
||||||
public static final int WMF = 0x2160;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Macintosh PICT
|
|
||||||
*/
|
|
||||||
public static final int PICT = 0x5420;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JPEG
|
|
||||||
*/
|
|
||||||
public static final int JPEG = 0x46A0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PNG
|
|
||||||
*/
|
|
||||||
public static final int PNG = 0x6E00;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Windows DIB (BMP)
|
|
||||||
*/
|
|
||||||
public static final int DIB = 0x7A80;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a picture from "Pictures" OLE stream
|
|
||||||
*
|
|
||||||
* @param pictstream the bytes to read
|
|
||||||
* @param offset the index of the first byte to read
|
|
||||||
*/
|
|
||||||
public Picture(byte[] pictstream, int offset){
|
|
||||||
header = new byte[Picture.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 + Picture.HEADER_SIZE, pictdata, 0, pictdata.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the binary data of this picture
|
|
||||||
*/
|
|
||||||
public byte[] getData(){
|
|
||||||
return pictdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of this picture. Must be one of the static constans defined in this class.
|
|
||||||
*
|
|
||||||
* @return type of this picture.
|
|
||||||
*/
|
|
||||||
public int getType(){
|
|
||||||
int type = LittleEndian.getShort(header, 0);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,10 @@ import java.util.*;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.io.*;
|
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.*;
|
||||||
import org.apache.poi.hslf.model.*;
|
import org.apache.poi.hslf.model.*;
|
||||||
import org.apache.poi.hslf.record.Document;
|
import org.apache.poi.hslf.record.Document;
|
||||||
@ -50,6 +54,7 @@ import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
|
|||||||
* - handle Slide creation cleaner
|
* - handle Slide creation cleaner
|
||||||
*
|
*
|
||||||
* @author Nick Burch
|
* @author Nick Burch
|
||||||
|
* @author Yegor kozlov
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SlideShow
|
public class SlideShow
|
||||||
@ -74,6 +79,12 @@ public class SlideShow
|
|||||||
// MetaSheets (eg masters) not yet supported
|
// MetaSheets (eg masters) not yet supported
|
||||||
// private MetaSheets[] _msheets;
|
// private MetaSheets[] _msheets;
|
||||||
|
|
||||||
|
|
||||||
|
/* ===============================================================
|
||||||
|
* Setup Code
|
||||||
|
* ===============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a Powerpoint document from the underlying
|
* Constructs a Powerpoint document from the underlying
|
||||||
@ -86,7 +97,6 @@ public class SlideShow
|
|||||||
// Get useful things from our base slideshow
|
// Get useful things from our base slideshow
|
||||||
_hslfSlideShow = hslfSlideShow;
|
_hslfSlideShow = hslfSlideShow;
|
||||||
_records = _hslfSlideShow.getRecords();
|
_records = _hslfSlideShow.getRecords();
|
||||||
byte[] _docstream = _hslfSlideShow.getUnderlyingBytes();
|
|
||||||
|
|
||||||
// Handle Parent-aware Reocrds
|
// Handle Parent-aware Reocrds
|
||||||
for(int i=0; i<_records.length; i++) {
|
for(int i=0; i<_records.length; i++) {
|
||||||
@ -100,6 +110,12 @@ public class SlideShow
|
|||||||
buildSlidesAndNotes();
|
buildSlidesAndNotes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new, empty, Powerpoint document.
|
||||||
|
*/
|
||||||
|
public SlideShow() throws IOException {
|
||||||
|
this(new HSLFSlideShow());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the records that are parent-aware, and tell them
|
* 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 <code>Slide</code>.
|
* Create a blank <code>Slide</code>.
|
||||||
*
|
*
|
||||||
@ -476,63 +563,87 @@ public class SlideShow
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes out the slideshow file the is represented by an instance of
|
* Adds a picture to this presentation and returns the associated index.
|
||||||
* this class
|
*
|
||||||
* @param out The OutputStream to write to.
|
* @param data picture data
|
||||||
* @throws IOException If there is an unexpected IOException from the passed
|
* @param format the format of the picture. One of constans defined in the <code>Picture</code> class.
|
||||||
* in OutputStream
|
* @return the index to this picture (1 based).
|
||||||
*/
|
*/
|
||||||
public void write(OutputStream out) throws IOException {
|
public int addPicture(byte[] data, int format) {
|
||||||
_hslfSlideShow.write(out);
|
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);
|
||||||
|
|
||||||
/**
|
List child = dggContainer.getChildRecords();
|
||||||
* Returns an array of the most recent version of all the interesting
|
for ( int i = 0; i < child.size(); i++ ) {
|
||||||
* records
|
EscherRecord rec = (EscherRecord)child.get(i);
|
||||||
*/
|
if (rec.getRecordId() == EscherOptRecord.RECORD_ID){
|
||||||
public Record[] getMostRecentCoreRecords() { return _mostRecentCoreRecords; }
|
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();
|
||||||
* Returns an array of all the normal Slides found in the slideshow
|
bse.setRecordId(EscherBSERecord.RECORD_ID);
|
||||||
*/
|
bse.setOptions( (short) ( 0x0002 | ( format << 4 ) ) );
|
||||||
public Slide[] getSlides() { return _slides; }
|
bse.setSize(data.length + PictureData.HEADER_SIZE);
|
||||||
|
bse.setUid(uid);
|
||||||
|
bse.setBlipTypeMacOS((byte)format);
|
||||||
|
bse.setBlipTypeWin32((byte)format);
|
||||||
|
|
||||||
/**
|
bse.setRef(1);
|
||||||
* Returns an array of all the normal Notes found in the slideshow
|
bse.setOffset(offset);
|
||||||
*/
|
|
||||||
public Notes[] getNotes() { return _notes; }
|
|
||||||
|
|
||||||
/**
|
bstore.addChildRecord(bse);
|
||||||
* Returns an array of all the meta Sheets (master sheets etc)
|
int count = bstore.getChildRecords().size();
|
||||||
* found in the slideshow
|
bstore.setOptions((short)( (count << 4) | 0xF ));
|
||||||
*/
|
|
||||||
//public MetaSheet[] getMetaSheets() { return _msheets; }
|
|
||||||
|
|
||||||
/**
|
PictureData pict = new PictureData();
|
||||||
* Returns all the pictures attached to the SlideShow
|
pict.setUID(uid);
|
||||||
*/
|
pict.setData(data);
|
||||||
public Picture[] getPictures() throws IOException {
|
pict.setType(format);
|
||||||
return _hslfSlideShow.getPictures();
|
|
||||||
}
|
_hslfSlideShow.addPicture(pict);
|
||||||
|
|
||||||
/**
|
return count;
|
||||||
* Return the current page size
|
}
|
||||||
*/
|
|
||||||
public Dimension getPageSize(){
|
/**
|
||||||
DocumentAtom docatom = _documentRecord.getDocumentAtom();
|
* Adds a picture to this presentation and returns the associated index.
|
||||||
return new Dimension((int)docatom.getSlideSizeX(), (int)docatom.getSlideSizeY());
|
*
|
||||||
}
|
* @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).
|
||||||
* Helper method for usermodel: Get the font collection
|
*/
|
||||||
*/
|
public int addPicture(File pict, int format) {
|
||||||
protected FontCollection getFontCollection() { return _fonts; }
|
int length = (int)pict.length();
|
||||||
/**
|
byte[] data = new byte[length];
|
||||||
* Helper method for usermodel: Get the document record
|
try {
|
||||||
*/
|
FileInputStream is = new FileInputStream(pict);
|
||||||
protected Document getDocumentRecord() { return _documentRecord; }
|
is.read(data);
|
||||||
|
is.close();
|
||||||
|
} catch (IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return addPicture(data, format);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user