2005-05-28 01:36:00 -04:00
/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
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 java.util.* ;
2006-03-19 10:59:23 -05:00
import java.awt.Dimension ;
2005-05-28 01:36:00 -04:00
import java.io.* ;
2006-03-26 11:20:08 -05:00
import org.apache.poi.ddf.EscherBSERecord ;
import org.apache.poi.ddf.EscherContainerRecord ;
import org.apache.poi.ddf.EscherOptRecord ;
import org.apache.poi.ddf.EscherRecord ;
2005-05-28 01:36:00 -04:00
import org.apache.poi.hslf.* ;
import org.apache.poi.hslf.model.* ;
2006-03-19 10:59:23 -05:00
import org.apache.poi.hslf.record.Document ;
import org.apache.poi.hslf.record.DocumentAtom ;
2005-09-17 12:44:00 -04:00
import org.apache.poi.hslf.record.FontCollection ;
2005-11-07 17:24:15 -05:00
import org.apache.poi.hslf.record.ParentAwareRecord ;
2006-03-26 14:07:52 -05:00
import org.apache.poi.hslf.record.PositionDependentRecordContainer ;
2005-05-28 01:36:00 -04:00
import org.apache.poi.hslf.record.Record ;
2005-11-07 17:24:15 -05:00
import org.apache.poi.hslf.record.RecordContainer ;
2005-09-17 12:44:00 -04:00
import org.apache.poi.hslf.record.RecordTypes ;
2005-05-28 01:36:00 -04:00
import org.apache.poi.hslf.record.SlideAtom ;
import org.apache.poi.hslf.record.SlideListWithText ;
2006-03-19 12:53:49 -05:00
import org.apache.poi.hslf.record.SlidePersistAtom ;
import org.apache.poi.hslf.record.UserEditAtom ;
2005-05-28 01:36:00 -04:00
import org.apache.poi.hslf.record.SlideListWithText.* ;
2005-06-26 14:09:15 -04:00
import org.apache.poi.hslf.record.PersistPtrHolder ;
import org.apache.poi.hslf.record.PositionDependentRecord ;
2006-01-03 06:54:38 -05:00
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException ;
2005-05-28 01:36:00 -04:00
/ * *
* This class is a friendly wrapper on top of the more scary HSLFSlideShow .
*
* TODO :
* - figure out how to match notes to their correct sheet
* ( will involve understanding DocSlideList and DocNotesList )
* - handle Slide creation cleaner
*
* @author Nick Burch
2006-03-26 11:20:08 -05:00
* @author Yegor kozlov
2005-05-28 01:36:00 -04:00
* /
public class SlideShow
{
// What we're based on
private HSLFSlideShow _hslfSlideShow ;
// Low level contents, as taken from HSLFSlideShow
private Record [ ] _records ;
2005-06-26 14:09:15 -04:00
// Pointers to the most recent versions of the core records
// (Document, Notes, Slide etc)
private Record [ ] _mostRecentCoreRecords ;
2006-03-27 16:35:37 -05:00
// Lookup between the PersitPtr "sheet" IDs, and the position
// in the mostRecentCoreRecords array
private Hashtable _sheetIdToCoreRecordsLookup ;
// Used when adding new core records
private int _highestSheetId ;
2006-03-18 13:56:26 -05:00
// Records that are interesting
2006-03-19 10:59:23 -05:00
private Document _documentRecord ;
2005-06-26 14:09:15 -04:00
2005-05-28 01:36:00 -04:00
// Friendly objects for people to deal with
private Slide [ ] _slides ;
private Notes [ ] _notes ;
2005-09-17 12:44:00 -04:00
private FontCollection _fonts ;
2005-06-26 15:05:07 -04:00
// MetaSheets (eg masters) not yet supported
2005-05-28 01:36:00 -04:00
// private MetaSheets[] _msheets;
2006-03-26 11:20:08 -05:00
/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Setup Code
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* /
2005-05-28 01:36:00 -04:00
/ * *
* Constructs a Powerpoint document from the underlying
* HSLFSlideShow object . Finds the model stuff from this
*
* @param hslfSlideShow the HSLFSlideShow to base on
* /
public SlideShow ( HSLFSlideShow hslfSlideShow ) throws IOException
{
// Get useful things from our base slideshow
_hslfSlideShow = hslfSlideShow ;
_records = _hslfSlideShow . getRecords ( ) ;
2005-11-07 17:24:15 -05:00
// Handle Parent-aware Reocrds
for ( int i = 0 ; i < _records . length ; i + + ) {
handleParentAwareRecords ( _records [ i ] ) ;
}
2005-05-28 01:36:00 -04:00
2005-06-26 14:09:15 -04:00
// Find the versions of the core records we'll want to use
findMostRecentCoreRecords ( ) ;
2006-03-18 13:56:26 -05:00
2005-06-26 14:09:15 -04:00
// Build up the model level Slides and Notes
buildSlidesAndNotes ( ) ;
}
2005-11-07 17:24:15 -05:00
2006-03-26 11:20:08 -05:00
/ * *
* Constructs a new , empty , Powerpoint document .
* /
public SlideShow ( ) throws IOException {
this ( new HSLFSlideShow ( ) ) ;
}
2005-11-07 17:24:15 -05:00
/ * *
* Find the records that are parent - aware , and tell them
* who their parent is
* /
private void handleParentAwareRecords ( Record baseRecord ) {
// Only need to do something if this is a container record
if ( baseRecord instanceof RecordContainer ) {
RecordContainer br = ( RecordContainer ) baseRecord ;
Record [ ] childRecords = br . getChildRecords ( ) ;
// Loop over child records, looking for interesting ones
for ( int i = 0 ; i < childRecords . length ; i + + ) {
Record record = childRecords [ i ] ;
// Tell parent aware records of their parent
if ( record instanceof ParentAwareRecord ) {
( ( ParentAwareRecord ) record ) . setParentRecord ( br ) ;
}
// Walk on down for the case of container records
if ( record instanceof RecordContainer ) {
handleParentAwareRecords ( record ) ;
}
}
}
}
2005-06-26 14:09:15 -04:00
2005-06-26 15:05:07 -04:00
2005-06-26 14:09:15 -04:00
/ * *
* Use the PersistPtrHolder entries to figure out what is
* the " most recent " version of all the core records
* ( Document , Notes , Slide etc ) , and save a record of them .
* Do this by walking from the oldest PersistPtr to the newest ,
* overwriting any references found along the way with newer ones
* /
private void findMostRecentCoreRecords ( ) {
// To start with, find the most recent in the byte offset domain
Hashtable mostRecentByBytes = new Hashtable ( ) ;
for ( int i = 0 ; i < _records . length ; i + + ) {
if ( _records [ i ] instanceof PersistPtrHolder ) {
PersistPtrHolder pph = ( PersistPtrHolder ) _records [ i ] ;
// If we've already seen any of the "slide" IDs for this
// PersistPtr, remove their old positions
int [ ] ids = pph . getKnownSlideIDs ( ) ;
for ( int j = 0 ; j < ids . length ; j + + ) {
Integer id = new Integer ( ids [ j ] ) ;
if ( mostRecentByBytes . containsKey ( id ) ) {
mostRecentByBytes . remove ( id ) ;
}
}
// Now, update the byte level locations with their latest values
Hashtable thisSetOfLocations = pph . getSlideLocationsLookup ( ) ;
for ( int j = 0 ; j < ids . length ; j + + ) {
Integer id = new Integer ( ids [ j ] ) ;
mostRecentByBytes . put ( id , thisSetOfLocations . get ( id ) ) ;
}
}
}
2005-05-28 01:36:00 -04:00
2005-06-26 14:09:15 -04:00
// We now know how many unique special records we have, so init
// the array
_mostRecentCoreRecords = new Record [ mostRecentByBytes . size ( ) ] ;
2006-03-27 16:35:37 -05:00
// We'll also want to be able to turn the slide IDs into a position
// in this array
_sheetIdToCoreRecordsLookup = new Hashtable ( ) ;
2005-06-26 14:09:15 -04:00
int [ ] allIDs = new int [ _mostRecentCoreRecords . length ] ;
Enumeration ids = mostRecentByBytes . keys ( ) ;
for ( int i = 0 ; i < allIDs . length ; i + + ) {
Integer id = ( Integer ) ids . nextElement ( ) ;
allIDs [ i ] = id . intValue ( ) ;
}
Arrays . sort ( allIDs ) ;
for ( int i = 0 ; i < allIDs . length ; i + + ) {
2006-03-27 16:35:37 -05:00
_sheetIdToCoreRecordsLookup . put ( new Integer ( allIDs [ i ] ) , new Integer ( i ) ) ;
2005-06-26 14:09:15 -04:00
}
2006-03-27 16:35:37 -05:00
// Capture the ID of the highest sheet
_highestSheetId = allIDs [ ( allIDs . length - 1 ) ] ;
2005-06-26 14:09:15 -04:00
// Now convert the byte offsets back into record offsets
for ( int i = 0 ; i < _records . length ; i + + ) {
if ( _records [ i ] instanceof PositionDependentRecord ) {
PositionDependentRecord pdr = ( PositionDependentRecord ) _records [ i ] ;
Integer recordAt = new Integer ( pdr . getLastOnDiskOffset ( ) ) ;
// Is it one we care about?
for ( int j = 0 ; j < allIDs . length ; j + + ) {
Integer thisID = new Integer ( allIDs [ j ] ) ;
Integer thatRecordAt = ( Integer ) mostRecentByBytes . get ( thisID ) ;
if ( thatRecordAt . equals ( recordAt ) ) {
// Bingo. Now, where do we store it?
Integer storeAtI =
2006-03-27 16:35:37 -05:00
( Integer ) _sheetIdToCoreRecordsLookup . get ( thisID ) ;
2005-06-26 14:09:15 -04:00
int storeAt = storeAtI . intValue ( ) ;
2006-03-26 14:07:52 -05:00
// Tell it its Sheet ID, if it cares
if ( pdr instanceof PositionDependentRecordContainer ) {
PositionDependentRecordContainer pdrc =
( PositionDependentRecordContainer ) _records [ i ] ;
pdrc . setSheetId ( thisID . intValue ( ) ) ;
}
2005-06-26 14:09:15 -04:00
// Finally, save the record
_mostRecentCoreRecords [ storeAt ] = _records [ i ] ;
}
}
}
}
2006-03-18 13:56:26 -05:00
// Now look for the interesting records in there
for ( int i = 0 ; i < _mostRecentCoreRecords . length ; i + + ) {
2006-03-27 16:35:37 -05:00
// Check there really is a record at this number
if ( _mostRecentCoreRecords [ i ] ! = null ) {
// Find the Document, and interesting things in it
if ( _mostRecentCoreRecords [ i ] . getRecordType ( ) = = RecordTypes . Document . typeID ) {
_documentRecord = ( Document ) _mostRecentCoreRecords [ i ] ;
_fonts = _documentRecord . getEnvironment ( ) . getFontCollection ( ) ;
}
} else {
System . err . println ( " No core record found with ID " + ( i + 1 ) + " based on PersistPtr lookup " ) ;
2006-03-18 13:56:26 -05:00
}
}
2005-06-26 14:09:15 -04:00
}
/ * *
* Build up model level Slide and Notes objects , from the underlying
* records .
* /
private void buildSlidesAndNotes ( ) {
2006-03-27 16:35:37 -05:00
// For holding the Slide Records
Vector slidesV = new Vector ( 10 ) ;
// For holding the Notes Records
Vector notesV = new Vector ( 10 ) ;
// For holding the Meta Sheet Records
Vector metaSheetsV = new Vector ( 10 ) ;
2006-03-18 13:56:26 -05:00
// Ensure we really found a Document record earlier
2005-11-24 05:46:45 -05:00
// If we didn't, then the file is probably corrupt
2006-03-18 13:56:26 -05:00
if ( _documentRecord = = null ) {
2006-01-03 06:54:38 -05:00
throw new CorruptPowerPointFileException ( " The PowerPoint file didn't contain a Document Record in its PersistPtr blocks. It is probably corrupt. " ) ;
2005-11-24 05:46:45 -05:00
}
2005-05-28 01:36:00 -04:00
2006-03-19 11:09:51 -05:00
// Fetch the SlideListWithTexts in the most up-to-date Document Record
2005-05-28 01:36:00 -04:00
//
2006-03-27 16:35:37 -05:00
// Then, use this to find the Slide records, and also the Notes record
// for each Slide (if it has one)
2005-05-28 01:36:00 -04:00
//
2006-03-27 16:35:37 -05:00
// The following matching algorithm is based on looking at the output
// of org.apache.poi.hslf.dev.SlideIdListing on a number of files:
2005-06-26 15:05:07 -04:00
//
2006-03-27 16:35:37 -05:00
// 1) Get the SlideAtomSets from the SlideListWithTexts of the most
// up-to-date Document
// 2) Get the SlidePersistAtoms from all of these
// 3) Get the RefId, which corresponds to a "sheet ID" from the
// PersistPtr Stuff
// 4) Grab the record at that ID, and see if it's a slide or a notes
// 5) Build a mapping between the SlideIdentifier ID and the RefId
// for both slides and notes
// 6) Loop over all the slides
// 7) Look each slide's SlideAtom to see if it has associated Notes -
// if it does, the ID will be SlideIdentifier for those notes
// (Note: might not be the same as the SlideIdentifier of the Slide)
// 8) Generate the model representations, giving them the matching
// slide atom sets, IDs etc
2005-06-26 15:05:07 -04:00
2006-03-19 11:09:51 -05:00
SlideListWithText [ ] slwts = _documentRecord . getSlideListWithTexts ( ) ;
2006-03-27 16:35:37 -05:00
// To hold the lookup from SlideIdentifier IDs to RefIDs
Hashtable slideSlideIdToRefid = new Hashtable ( ) ;
Hashtable notesSlideIdToRefid = new Hashtable ( ) ;
// To hold the lookup from SlideIdentifier IDs to SlideAtomsSets
Hashtable slideSlideIdToSlideAtomsSet = new Hashtable ( ) ;
Hashtable notesSlideIdToSlideAtomsSet = new Hashtable ( ) ;
// Loop over all the SlideListWithTexts, getting their
// SlideAtomSets
for ( int i = 0 ; i < slwts . length ; i + + ) {
SlideAtomsSet [ ] sas = slwts [ i ] . getSlideAtomsSets ( ) ;
for ( int j = 0 ; j < sas . length ; j + + ) {
// What does this SlidePersistAtom point to?
SlidePersistAtom spa = sas [ j ] . getSlidePersistAtom ( ) ;
Integer slideIdentifier = new Integer ( spa . getSlideIdentifier ( ) ) ;
Integer slideRefId = new Integer ( spa . getRefID ( ) ) ;
// Grab the record it points to
Integer coreRecordId = ( Integer )
_sheetIdToCoreRecordsLookup . get ( slideRefId ) ;
Record r = _mostRecentCoreRecords [ coreRecordId . intValue ( ) ] ;
// Add the IDs to the appropriate lookups
if ( r instanceof org . apache . poi . hslf . record . Slide ) {
slideSlideIdToRefid . put ( slideIdentifier , slideRefId ) ;
// Save the SlideAtomsSet
slideSlideIdToSlideAtomsSet . put ( slideIdentifier , sas [ j ] ) ;
} else if ( r instanceof org . apache . poi . hslf . record . Notes ) {
notesSlideIdToRefid . put ( slideIdentifier , slideRefId ) ;
// Save the SlideAtomsSet
notesSlideIdToSlideAtomsSet . put ( slideIdentifier , sas [ j ] ) ;
} else if ( r . getRecordType ( ) = = RecordTypes . MainMaster . typeID ) {
// Skip for now, we don't do Master slides yet
2005-06-26 15:05:07 -04:00
} else {
2006-03-27 16:35:37 -05:00
throw new IllegalStateException ( " SlidePersistAtom had a RefId that pointed to something other than a Slide or a Notes, was a " + r + " with type " + r . getRecordType ( ) ) ;
2005-06-26 15:05:07 -04:00
}
2005-05-28 01:36:00 -04:00
}
}
2006-03-27 16:35:37 -05:00
// Now, create a model representation of a slide for each
// slide + slideatomset we found
// Do it in order of the SlideIdentifiers
int [ ] slideIDs = new int [ slideSlideIdToRefid . size ( ) ] ;
2005-05-28 01:36:00 -04:00
int pos = 0 ;
2006-03-27 16:35:37 -05:00
Enumeration e = slideSlideIdToRefid . keys ( ) ;
while ( e . hasMoreElements ( ) ) {
Integer id = ( Integer ) e . nextElement ( ) ;
2005-05-28 01:36:00 -04:00
slideIDs [ pos ] = id . intValue ( ) ;
2006-03-27 16:35:37 -05:00
pos + + ;
2005-05-28 01:36:00 -04:00
}
// Sort
Arrays . sort ( slideIDs ) ;
2006-03-27 16:35:37 -05:00
// Create
for ( int i = 0 ; i < slideIDs . length ; i + + ) {
// Build up the list of all the IDs we might want to use
int slideIdentifier = slideIDs [ i ] ;
Integer slideIdentifierI = new Integer ( slideIdentifier ) ;
int slideNumber = ( i + 1 ) ;
Integer slideRefI = ( Integer ) slideSlideIdToRefid . get ( slideIdentifierI ) ;
Integer slideCoreRecNumI = ( Integer ) _sheetIdToCoreRecordsLookup . get ( slideRefI ) ;
int slideCoreRecNum = slideCoreRecNumI . intValue ( ) ;
// Fetch the Slide record
org . apache . poi . hslf . record . Slide s = ( org . apache . poi . hslf . record . Slide )
_mostRecentCoreRecords [ slideCoreRecNum ] ;
// Do we have a notes for this slide?
org . apache . poi . hslf . record . Notes n = null ;
if ( s . getSlideAtom ( ) . getNotesID ( ) > 0 ) {
// Get the SlideIdentifier of the Notes
// (Note - might not be the same as the SlideIdentifier of the Slide)
int notesSlideIdentifier = s . getSlideAtom ( ) . getNotesID ( ) ;
Integer notesSlideIdentifierI = new Integer ( notesSlideIdentifier ) ;
// Grab the notes record
Integer notesRefI = ( Integer ) notesSlideIdToRefid . get ( notesSlideIdentifierI ) ;
Integer notesCoreRecNum = ( Integer ) _sheetIdToCoreRecordsLookup . get ( notesRefI ) ;
n = ( org . apache . poi . hslf . record . Notes )
_mostRecentCoreRecords [ notesCoreRecNum . intValue ( ) ] ;
}
// Grab the matching SlideAtomSet
SlideAtomsSet sas = ( SlideAtomsSet )
slideSlideIdToSlideAtomsSet . get ( slideIdentifierI ) ;
// Build the notes model, if there's notes
Notes notes = null ;
if ( n ! = null ) {
// TODO: Use this
SlideAtomsSet nsas = ( SlideAtomsSet )
notesSlideIdToSlideAtomsSet . get ( slideIdentifierI ) ;
// Create the model view of the notes
notes = new Notes ( n ) ;
notesV . add ( notes ) ;
2005-05-28 01:36:00 -04:00
}
2006-03-27 16:35:37 -05:00
// Build the slide model
Slide slide = new Slide ( s , notes , sas , slideIdentifier , slideNumber ) ;
slidesV . add ( slide ) ;
2005-05-28 01:36:00 -04:00
}
2006-03-27 16:35:37 -05:00
// ******************* Finish up ****************
2005-05-28 01:36:00 -04:00
2006-03-27 16:35:37 -05:00
// Finish setting up the notes
2005-05-28 01:36:00 -04:00
_notes = new Notes [ notesV . size ( ) ] ;
for ( int i = 0 ; i < _notes . length ; i + + ) {
2006-03-27 16:35:37 -05:00
_notes [ i ] = ( Notes ) notesV . get ( i ) ;
2006-04-12 14:48:53 -04:00
_notes [ i ] . setSlideShow ( this ) ;
2006-03-18 13:56:26 -05:00
// Now supply ourselves to all the rich text runs
// of this note's TextRuns
TextRun [ ] trs = _notes [ i ] . getTextRuns ( ) ;
for ( int j = 0 ; j < trs . length ; j + + ) {
RichTextRun [ ] rtrs = trs [ j ] . getRichTextRuns ( ) ;
for ( int k = 0 ; k < rtrs . length ; k + + ) {
rtrs [ k ] . supplySlideShow ( this ) ;
}
}
2005-05-28 01:36:00 -04:00
}
// Create our Slides
_slides = new Slide [ slidesV . size ( ) ] ;
for ( int i = 0 ; i < _slides . length ; i + + ) {
2006-03-27 16:35:37 -05:00
_slides [ i ] = ( Slide ) slidesV . get ( i ) ;
2006-04-12 14:48:53 -04:00
_slides [ i ] . setSlideShow ( this ) ;
2005-05-28 01:36:00 -04:00
2006-03-18 13:56:26 -05:00
// Now supply ourselves to all the rich text runs
// of this slide's TextRuns
TextRun [ ] trs = _slides [ i ] . getTextRuns ( ) ;
for ( int j = 0 ; j < trs . length ; j + + ) {
RichTextRun [ ] rtrs = trs [ j ] . getRichTextRuns ( ) ;
for ( int k = 0 ; k < rtrs . length ; k + + ) {
rtrs [ k ] . supplySlideShow ( this ) ;
}
}
2005-05-28 01:36:00 -04:00
}
}
2006-03-26 11:20:08 -05:00
/ * *
* 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; }
/ * *
2006-04-12 14:48:53 -04:00
* Returns the data of all the pictures attached to the SlideShow
2006-03-26 11:20:08 -05:00
* /
2006-04-12 14:48:53 -04:00
public PictureData [ ] getPictureData ( ) {
2006-03-26 11:20:08 -05:00
return _hslfSlideShow . getPictures ( ) ;
}
/ * *
* Return the current page size
* /
public Dimension getPageSize ( ) {
DocumentAtom docatom = _documentRecord . getDocumentAtom ( ) ;
2006-04-12 14:48:53 -04:00
int pgx = ( int ) docatom . getSlideSizeX ( ) * Shape . POINT_DPI / Shape . MASTER_DPI ;
int pgy = ( int ) docatom . getSlideSizeY ( ) * Shape . POINT_DPI / Shape . MASTER_DPI ;
return new Dimension ( pgx , pgy ) ;
}
/ * *
* Change the current page size
*
* @param pgsize page size ( in points )
* /
public void setPageSize ( Dimension pgsize ) {
DocumentAtom docatom = _documentRecord . getDocumentAtom ( ) ;
docatom . setSlideSizeX ( pgsize . width * Shape . MASTER_DPI / Shape . POINT_DPI ) ;
docatom . setSlideSizeY ( pgsize . height * Shape . MASTER_DPI / Shape . POINT_DPI ) ;
2006-03-26 11:20:08 -05:00
}
/ * *
* Helper method for usermodel : Get the font collection
* /
protected FontCollection getFontCollection ( ) { return _fonts ; }
/ * *
2006-04-12 14:48:53 -04:00
* Helper method for usermodel and model : Get the document record
2006-03-26 11:20:08 -05:00
* /
2006-04-12 14:48:53 -04:00
public Document getDocumentRecord ( ) { return _documentRecord ; }
2006-03-26 11:20:08 -05:00
/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Addition Code
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* /
2006-03-19 10:59:23 -05:00
/ * *
* Create a blank < code > Slide < / code > .
*
* @return the created < code > Slide < / code >
* @throws IOException
* /
public Slide createSlide ( ) throws IOException {
2006-03-19 12:53:49 -05:00
SlideListWithText slist = null ;
2006-06-27 07:42:29 -04:00
// We need to add the records to the SLWT that deals
// with Slides.
// Add it, if it doesn't exist
slist = _documentRecord . getSlideSlideListWithText ( ) ;
if ( slist = = null ) {
2006-03-19 12:53:49 -05:00
// Need to add a new one
slist = new SlideListWithText ( ) ;
2006-03-26 12:37:04 -05:00
_documentRecord . addSlideListWithText ( slist ) ;
2006-03-19 12:53:49 -05:00
}
2006-03-26 12:37:04 -05:00
// Grab the SlidePersistAtom with the highest Slide Number.
// (Will stay as null if no SlidePersistAtom exists yet in
2006-03-27 16:35:37 -05:00
// the slide, or only master slide's ones do)
2006-03-19 13:09:20 -05:00
SlidePersistAtom prev = null ;
2006-06-27 07:42:29 -04:00
SlideAtomsSet [ ] sas = slist . getSlideAtomsSets ( ) ;
for ( int j = 0 ; j < sas . length ; j + + ) {
SlidePersistAtom spa = sas [ j ] . getSlidePersistAtom ( ) ;
if ( spa . getSlideIdentifier ( ) < 0 ) {
// This is for a master slide
// Odd, since we only deal with the Slide SLWT
} else {
// Must be for a real slide
if ( prev = = null ) { prev = spa ; }
if ( prev . getSlideIdentifier ( ) < spa . getSlideIdentifier ( ) ) {
prev = spa ;
2006-03-26 12:37:04 -05:00
}
}
2006-03-19 13:09:20 -05:00
}
2006-03-26 12:37:04 -05:00
// Set up a new SlidePersistAtom for this slide
2006-03-19 12:53:49 -05:00
SlidePersistAtom sp = new SlidePersistAtom ( ) ;
2006-03-27 16:35:37 -05:00
// Reference is the 1-based index of the slide container in
// the PersistPtr root.
2006-03-19 12:53:49 -05:00
// It always starts with 3 (1 is Document, 2 is MainMaster, 3 is
2006-03-27 16:35:37 -05:00
// the first slide), but quicksaves etc can leave gaps
_highestSheetId + + ;
sp . setRefID ( _highestSheetId ) ;
2006-03-19 12:53:49 -05:00
// First slideId is always 256
sp . setSlideIdentifier ( prev = = null ? 256 : ( prev . getSlideIdentifier ( ) + 1 ) ) ;
2006-03-19 13:09:20 -05:00
// Add this new SlidePersistAtom to the SlideListWithText
2006-03-26 12:37:04 -05:00
slist . addSlidePersistAtom ( sp ) ;
2006-03-19 12:53:49 -05:00
// Create a new Slide
2006-03-27 16:35:37 -05:00
Slide slide = new Slide ( sp . getSlideIdentifier ( ) , sp . getRefID ( ) , _slides . length + 1 ) ;
2006-03-26 14:07:52 -05:00
// Add in to the list of Slides
2006-03-19 12:53:49 -05:00
Slide [ ] s = new Slide [ _slides . length + 1 ] ;
System . arraycopy ( _slides , 0 , s , 0 , _slides . length ) ;
s [ _slides . length ] = slide ;
_slides = s ;
System . out . println ( " Added slide " + _slides . length + " with ref " + sp . getRefID ( ) + " and identifier " + sp . getSlideIdentifier ( ) ) ;
2006-03-26 12:37:04 -05:00
// Add the core records for this new Slide to the record tree
2006-03-26 14:07:52 -05:00
org . apache . poi . hslf . record . Slide slideRecord = slide . getSlideRecord ( ) ;
slideRecord . setSheetId ( sp . getRefID ( ) ) ;
2006-03-19 12:53:49 -05:00
int slideRecordPos = _hslfSlideShow . appendRootLevelRecord ( slideRecord ) ;
2006-03-26 12:37:04 -05:00
_records = _hslfSlideShow . getRecords ( ) ;
2006-03-19 12:53:49 -05:00
// Add the new Slide into the PersistPtr stuff
int offset = 0 ;
int slideOffset = 0 ;
PersistPtrHolder ptr = null ;
UserEditAtom usr = null ;
for ( int i = 0 ; i < _records . length ; i + + ) {
Record record = _records [ i ] ;
ByteArrayOutputStream out = new ByteArrayOutputStream ( ) ;
record . writeOut ( out ) ;
// Grab interesting records as they come past
if ( _records [ i ] . getRecordType ( ) = = RecordTypes . PersistPtrIncrementalBlock . typeID ) {
ptr = ( PersistPtrHolder ) _records [ i ] ;
}
if ( _records [ i ] . getRecordType ( ) = = RecordTypes . UserEditAtom . typeID ) {
usr = ( UserEditAtom ) _records [ i ] ;
}
if ( i = = slideRecordPos ) {
slideOffset = offset ;
}
offset + = out . size ( ) ;
}
// Add the new slide into the last PersistPtr
2006-03-26 12:37:04 -05:00
// (Also need to tell it where it is)
2006-03-19 12:53:49 -05:00
slideRecord . setLastOnDiskOffset ( slideOffset ) ;
2006-03-26 12:37:04 -05:00
ptr . addSlideLookup ( sp . getRefID ( ) , slideOffset ) ;
2006-03-19 12:53:49 -05:00
System . out . println ( " New slide ended up at " + slideOffset ) ;
// Last view is now of the slide
usr . setLastViewType ( ( short ) UserEditAtom . LAST_VIEW_SLIDE_VIEW ) ;
// All done and added
2006-04-12 14:48:53 -04:00
slide . setSlideShow ( this ) ;
2006-03-19 12:53:49 -05:00
return slide ;
2006-03-19 10:59:23 -05:00
}
2005-05-28 01:36:00 -04:00
2006-03-26 11:20:08 -05:00
/ * *
* 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 ) ;
}
2005-05-28 01:36:00 -04:00
}