added support for TitleMaster object

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@541622 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2007-05-25 12:04:45 +00:00
parent 581fb11400
commit 3bcdf011d1
18 changed files with 607 additions and 364 deletions

View File

@ -16,6 +16,9 @@
*/ */
package org.apache.poi.hslf.model; package org.apache.poi.hslf.model;
import org.apache.poi.hslf.record.SheetContainer;
import org.apache.poi.hslf.model.textproperties.TextProp;
/** /**
* The superclass of all master sheets - Slide masters, Notes masters, etc. * The superclass of all master sheets - Slide masters, Notes masters, etc.
* *
@ -24,5 +27,14 @@ package org.apache.poi.hslf.model;
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public abstract class MasterSheet extends Sheet { public abstract class MasterSheet extends Sheet {
public MasterSheet(SheetContainer container, int sheetNo){
super(container, sheetNo);
}
/**
* Pickup a style attribute from the master.
* This is the "workhorse" which returns the default style attrubutes.
*/
public abstract TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) ;
} }

View File

@ -20,8 +20,6 @@
package org.apache.poi.hslf.model; package org.apache.poi.hslf.model;
import org.apache.poi.hslf.record.PPDrawing;
/** /**
* This class represents a slide's notes in a PowerPoint Document. It * This class represents a slide's notes in a PowerPoint Document. It
* allows access to the text within, and the layout. For now, it only * allows access to the text within, and the layout. For now, it only
@ -32,9 +30,6 @@ import org.apache.poi.hslf.record.PPDrawing;
public class Notes extends Sheet public class Notes extends Sheet
{ {
private int _refSheetNo;
private int _slideNo;
private org.apache.poi.hslf.record.Notes _notes;
private TextRun[] _runs; private TextRun[] _runs;
/** /**
@ -44,18 +39,12 @@ public class Notes extends Sheet
* @param notes the Notes record to read from * @param notes the Notes record to read from
*/ */
public Notes (org.apache.poi.hslf.record.Notes notes) { public Notes (org.apache.poi.hslf.record.Notes notes) {
_notes = notes; super(notes, notes.getNotesAtom().getSlideID());
// Grab our internal sheet ID
_refSheetNo = notes.getSheetId();
// Grab the number of the slide we're for, via the NotesAtom
_slideNo = _notes.getNotesAtom().getSlideID();
// Now, build up TextRuns from pairs of TextHeaderAtom and // Now, build up TextRuns from pairs of TextHeaderAtom and
// one of TextBytesAtom or TextCharsAtom, found inside // one of TextBytesAtom or TextCharsAtom, found inside
// EscherTextboxWrapper's in the PPDrawing // EscherTextboxWrapper's in the PPDrawing
_runs = findTextRuns(_notes.getPPDrawing()); _runs = findTextRuns(getPPDrawing());
// Set the sheet on each TextRun // Set the sheet on each TextRun
for (int i = 0; i < _runs.length; i++) for (int i = 0; i < _runs.length; i++)
@ -71,14 +60,10 @@ public class Notes extends Sheet
public TextRun[] getTextRuns() { return _runs; } public TextRun[] getTextRuns() { return _runs; }
/** /**
* Returns the (internal, RefID based) sheet number, as used * Return <code>null</code> - Notes Masters are not yet supported
* to in PersistPtr stuff.
*/ */
public int _getSheetRefId() { return _refSheetNo; } public MasterSheet getMasterSheet() {
/** return null;
* Returns the (internal, SlideIdentifer based) number of the }
* slide we're attached to
*/
public int _getSheetNumber() { return _slideNo; }
protected PPDrawing getPPDrawing() { return _notes.getPPDrawing(); }} }

View File

@ -39,8 +39,6 @@ public class ShapeFactory {
int type = spRecord.getOptions() >> 4; int type = spRecord.getOptions() >> 4;
switch (type){ switch (type){
case ShapeTypes.TextBox: case ShapeTypes.TextBox:
shape = new TextBox(spContainer, parent);
break;
case ShapeTypes.Rectangle: case ShapeTypes.Rectangle:
EscherTextboxRecord txtbox = (EscherTextboxRecord)Shape.getEscherChild(spContainer, EscherTextboxRecord.RECORD_ID); EscherTextboxRecord txtbox = (EscherTextboxRecord)Shape.getEscherChild(spContainer, EscherTextboxRecord.RECORD_ID);
if (txtbox == null) if (txtbox == null)

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -17,7 +16,6 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hslf.model; package org.apache.poi.hslf.model;
import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherContainerRecord;
@ -36,15 +34,35 @@ import java.util.Vector;
* document. Such sheets could be Slides, Notes, Master etc * document. Such sheets could be Slides, Notes, Master etc
* *
* @author Nick Burch * @author Nick Burch
* @author Yegor Kozlov
*/ */
public abstract class Sheet public abstract class Sheet {
{
/** /**
* The <code>SlideShow</code> we belong to * The <code>SlideShow</code> we belong to
*/ */
private SlideShow _slideShow; private SlideShow _slideShow;
/**
* Sheet background
*/
private Background _background;
/**
* Record container that holds sheet data.
* For slides it is org.apache.poi.hslf.record.Slide,
* for notes it is org.apache.poi.hslf.record.Notes,
* for slide masters it is org.apache.poi.hslf.record.SlideMaster, etc.
*/
private SheetContainer _container;
private int _sheetNo;
public Sheet(SheetContainer container, int sheetNo) {
_container = container;
_sheetNo = sheetNo;
}
/** /**
* Returns an array of all the TextRuns in the sheet. * Returns an array of all the TextRuns in the sheet.
*/ */
@ -54,24 +72,38 @@ public abstract class Sheet
* Returns the (internal, RefID based) sheet number, as used * Returns the (internal, RefID based) sheet number, as used
* to in PersistPtr stuff. * to in PersistPtr stuff.
*/ */
public abstract int _getSheetRefId(); public int _getSheetRefId() {
return _container.getSheetId();
}
/** /**
* Returns the (internal, SlideIdentifier based) sheet number, as used * Returns the (internal, SlideIdentifier based) sheet number, as used
* to reference this sheet from other records. * to reference this sheet from other records.
*/ */
public abstract int _getSheetNumber(); public int _getSheetNumber() {
return _sheetNo;
}
/** /**
* Fetch the PPDrawing from the underlying record * Fetch the PPDrawing from the underlying record
*/ */
protected abstract PPDrawing getPPDrawing(); protected PPDrawing getPPDrawing() {
return _container.getPPDrawing();
}
/** /**
* Fetch the SlideShow we're attached to * Fetch the SlideShow we're attached to
*/ */
public SlideShow getSlideShow() { return _slideShow; } public SlideShow getSlideShow() {
return _slideShow;
}
/**
* Return record container for this sheet
*/
public SheetContainer getSheetContainer() {
return _container;
}
/** /**
* Set the SlideShow we're attached to. * Set the SlideShow we're attached to.
@ -80,8 +112,8 @@ public abstract class Sheet
public void setSlideShow(SlideShow ss) { public void setSlideShow(SlideShow ss) {
_slideShow = ss; _slideShow = ss;
TextRun[] trs = getTextRuns(); TextRun[] trs = getTextRuns();
if(trs != null) { if (trs != null) {
for(int i=0; i<trs.length; i++) { for (int i = 0; i < trs.length; i++) {
trs[i].supplySlideShow(_slideShow); trs[i].supplySlideShow(_slideShow);
} }
} }
@ -94,12 +126,12 @@ public abstract class Sheet
public static TextRun[] findTextRuns(PPDrawing ppdrawing) { public static TextRun[] findTextRuns(PPDrawing ppdrawing) {
Vector runsV = new Vector(); Vector runsV = new Vector();
EscherTextboxWrapper[] wrappers = ppdrawing.getTextboxWrappers(); EscherTextboxWrapper[] wrappers = ppdrawing.getTextboxWrappers();
for(int i=0; i<wrappers.length; i++) { for (int i = 0; i < wrappers.length; i++) {
findTextRuns(wrappers[i].getChildRecords(),runsV); findTextRuns(wrappers[i].getChildRecords(), runsV);
} }
TextRun[] runs = new TextRun[runsV.size()]; TextRun[] runs = new TextRun[runsV.size()];
for(int i=0; i<runs.length; i++) { for (int i = 0; i < runs.length; i++) {
runs[i] = (TextRun)runsV.get(i); runs[i] = (TextRun) runsV.get(i);
} }
return runs; return runs;
} }
@ -114,36 +146,36 @@ public abstract class Sheet
*/ */
protected static void findTextRuns(Record[] records, Vector found) { protected static void findTextRuns(Record[] records, Vector found) {
// Look for a TextHeaderAtom // Look for a TextHeaderAtom
for(int i=0; i<(records.length-1); i++) { for (int i = 0; i < (records.length - 1); i++) {
if(records[i] instanceof TextHeaderAtom) { if (records[i] instanceof TextHeaderAtom) {
TextRun trun = null; TextRun trun = null;
TextHeaderAtom tha = (TextHeaderAtom)records[i]; TextHeaderAtom tha = (TextHeaderAtom) records[i];
StyleTextPropAtom stpa = null; StyleTextPropAtom stpa = null;
// Look for a subsequent StyleTextPropAtom // Look for a subsequent StyleTextPropAtom
if(i < (records.length-2)) { if (i < (records.length - 2)) {
if(records[i+2] instanceof StyleTextPropAtom) { if (records[i + 2] instanceof StyleTextPropAtom) {
stpa = (StyleTextPropAtom)records[i+2]; stpa = (StyleTextPropAtom) records[i + 2];
} }
} }
// See what follows the TextHeaderAtom // See what follows the TextHeaderAtom
if(records[i+1] instanceof TextCharsAtom) { if (records[i + 1] instanceof TextCharsAtom) {
TextCharsAtom tca = (TextCharsAtom)records[i+1]; TextCharsAtom tca = (TextCharsAtom) records[i + 1];
trun = new TextRun(tha,tca,stpa); trun = new TextRun(tha, tca, stpa);
} else if(records[i+1] instanceof TextBytesAtom) { } else if (records[i + 1] instanceof TextBytesAtom) {
TextBytesAtom tba = (TextBytesAtom)records[i+1]; TextBytesAtom tba = (TextBytesAtom) records[i + 1];
trun = new TextRun(tha,tba,stpa); trun = new TextRun(tha, tba, stpa);
} else if(records[i+1].getRecordType() == 4001l) { } else if (records[i + 1].getRecordType() == 4001l) {
// StyleTextPropAtom - Safe to ignore // StyleTextPropAtom - Safe to ignore
} else if(records[i+1].getRecordType() == 4010l) { } else if (records[i + 1].getRecordType() == 4010l) {
// TextSpecInfoAtom - Safe to ignore // TextSpecInfoAtom - Safe to ignore
} else { } else {
System.err.println("Found a TextHeaderAtom not followed by a TextBytesAtom or TextCharsAtom: Followed by " + records[i+1].getRecordType()); System.err.println("Found a TextHeaderAtom not followed by a TextBytesAtom or TextCharsAtom: Followed by " + records[i + 1].getRecordType());
continue; continue;
} }
if(trun != null) { if (trun != null) {
found.add(trun); found.add(trun);
i++; i++;
} else { } else {
@ -161,28 +193,28 @@ public abstract class Sheet
public Shape[] getShapes() { public Shape[] getShapes() {
PPDrawing ppdrawing = getPPDrawing(); PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0]; EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
EscherContainerRecord spgr = null; EscherContainerRecord spgr = null;
List ch = dg.getChildRecords(); List ch = dg.getChildRecords();
for (Iterator it = ch.iterator(); it.hasNext();) { for (Iterator it = ch.iterator(); it.hasNext();) {
EscherRecord rec = (EscherRecord)it.next(); EscherRecord rec = (EscherRecord) it.next();
if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){ if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
spgr = (EscherContainerRecord)rec; spgr = (EscherContainerRecord) rec;
break; break;
} }
} }
ch = spgr.getChildRecords(); ch = spgr.getChildRecords();
ArrayList shapes = new ArrayList(); ArrayList shapes = new ArrayList();
for (int i=1;i<ch.size();i++) { for (int i = 1; i < ch.size(); i++) {
EscherContainerRecord sp = (EscherContainerRecord)ch.get(i); EscherContainerRecord sp = (EscherContainerRecord) ch.get(i);
Shape sh = ShapeFactory.createShape(sp, null); Shape sh = ShapeFactory.createShape(sp, null);
sh.setSheet(this); sh.setSheet(this);
shapes.add(sh); shapes.add(sh);
} }
return (Shape[])shapes.toArray(new Shape[shapes.size()]); return (Shape[]) shapes.toArray(new Shape[shapes.size()]);
} }
/** /**
@ -190,23 +222,23 @@ public abstract class Sheet
* *
* @param shape - the Shape to add * @param shape - the Shape to add
*/ */
public void addShape(Shape shape){ public void addShape(Shape shape) {
PPDrawing ppdrawing = getPPDrawing(); PPDrawing ppdrawing = getPPDrawing();
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.getSpContainer()); 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);
shape.setSheet(this); shape.setSheet(this);
shape.afterInsert(this); shape.afterInsert(this);
// If it's a TextBox, we need to tell the PPDrawing, as it has to // If it's a TextBox, we need to tell the PPDrawing, as it has to
// track TextboxWrappers specially // track TextboxWrappers specially
if(shape instanceof TextBox) { if (shape instanceof TextBox) {
TextBox tbox = (TextBox)shape; TextBox tbox = (TextBox) shape;
ppdrawing.addTextboxWrapper(tbox._txtbox); ppdrawing.addTextboxWrapper(tbox._txtbox);
} }
} }
@ -214,14 +246,39 @@ public abstract class Sheet
/** /**
* Return the master sheet . * Return the master sheet .
*/ */
public MasterSheet getMasterSheet(){ public abstract MasterSheet getMasterSheet();
return null;
}
/** /**
* Color scheme for this sheet. * Color scheme for this sheet.
*/ */
public ColorSchemeAtom getColorScheme(){ public ColorSchemeAtom getColorScheme() {
return null; return _container.getColorScheme();
} }
/**
* Returns the background shape for this sheet.
*
* @return the background shape for this sheet.
*/
public Background getBackground() {
if (_background == null) {
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
EscherContainerRecord spContainer = null;
List ch = dg.getChildRecords();
for (Iterator it = ch.iterator(); it.hasNext();) {
EscherRecord rec = (EscherRecord) it.next();
if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
spContainer = (EscherContainerRecord) rec;
break;
}
}
_background = new Background(spContainer, null);
_background.setSheet(this);
}
return _background;
}
} }

View File

@ -44,15 +44,10 @@ import org.apache.poi.ddf.EscherRecord;
public class Slide extends Sheet public class Slide extends Sheet
{ {
private int _refSheetNo;
private int _sheetNo;
private int _slideNo; private int _slideNo;
private org.apache.poi.hslf.record.Slide _slide;
private SlideAtomsSet _atomSet; private SlideAtomsSet _atomSet;
private TextRun[] _runs; private TextRun[] _runs;
private TextRun[] _otherRuns; // Any from the PPDrawing, shouldn't really be any though
private Notes _notes; // usermodel needs to set this private Notes _notes; // usermodel needs to set this
private Background _background;
/** /**
* Constructs a Slide from the Slide record, and the SlideAtomsSet * Constructs a Slide from the Slide record, and the SlideAtomsSet
@ -64,15 +59,14 @@ public class Slide extends Sheet
* @param atomSet the SlideAtomsSet to get the text from * @param atomSet the SlideAtomsSet to get the text from
*/ */
public Slide(org.apache.poi.hslf.record.Slide slide, Notes notes, SlideAtomsSet atomSet, int slideIdentifier, int slideNumber) { public Slide(org.apache.poi.hslf.record.Slide slide, Notes notes, SlideAtomsSet atomSet, int slideIdentifier, int slideNumber) {
_slide = slide; super(slide, slideIdentifier);
_notes = notes; _notes = notes;
_atomSet = atomSet; _atomSet = atomSet;
_refSheetNo = slide.getSheetId();
_sheetNo = slideIdentifier;
_slideNo = slideNumber; _slideNo = slideNumber;
// Grab the TextRuns from the PPDrawing // Grab the TextRuns from the PPDrawing
_otherRuns = findTextRuns(_slide.getPPDrawing()); TextRun[] _otherRuns = findTextRuns(getPPDrawing());
// For the text coming in from the SlideAtomsSet: // For the text coming in from the SlideAtomsSet:
// Build up TextRuns from pairs of TextHeaderAtom and // Build up TextRuns from pairs of TextHeaderAtom and
@ -105,10 +99,9 @@ public class Slide extends Sheet
* @param slideNumber The user facing number of the sheet * @param slideNumber The user facing number of the sheet
*/ */
public Slide(int sheetNumber, int sheetRefId, int slideNumber){ public Slide(int sheetNumber, int sheetRefId, int slideNumber){
_slide = new org.apache.poi.hslf.record.Slide(); super(new org.apache.poi.hslf.record.Slide(), sheetNumber);
_refSheetNo = sheetRefId;
_sheetNo = sheetNumber;
_slideNo = slideNumber; _slideNo = slideNumber;
getSheetContainer().setSheetId(sheetRefId);
} }
/** /**
@ -119,7 +112,7 @@ public class Slide extends Sheet
_notes = notes; _notes = notes;
// Update the Slide Atom's ID of where to point to // Update the Slide Atom's ID of where to point to
SlideAtom sa = _slide.getSlideAtom(); SlideAtom sa = getSlideRecord().getSlideAtom();
if(notes == null) { if(notes == null) {
// Set to 0 // Set to 0
@ -132,7 +125,7 @@ public class Slide extends Sheet
/** /**
* Changes the Slide's (external facing) page number. * Changes the Slide's (external facing) page number.
* @see SlideShow.reorderSlide() * @see org.apache.poi.hslf.usermodel.SlideShow#reorderSlide(int, int)
*/ */
public void setSlideNumber(int newSlideNumber) { public void setSlideNumber(int newSlideNumber) {
_slideNo = newSlideNumber; _slideNo = newSlideNumber;
@ -187,17 +180,6 @@ public class Slide extends Sheet
*/ */
public TextRun[] getTextRuns() { return _runs; } public TextRun[] getTextRuns() { return _runs; }
/**
* Returns the (internal, RefID based) sheet number, as used
* to in PersistPtr stuff.
*/
public int _getSheetRefId() { return _refSheetNo; }
/**
* Returns the (internal, SlideIdentifier based) sheet number
* @see #getSlideNumber()
*/
public int _getSheetNumber() { return _sheetNo; }
/** /**
* Returns the (public facing) page number of this slide * Returns the (public facing) page number of this slide
*/ */
@ -206,18 +188,15 @@ public class Slide extends Sheet
/** /**
* Returns the underlying slide record * Returns the underlying slide record
*/ */
public org.apache.poi.hslf.record.Slide getSlideRecord() { return _slide; } public org.apache.poi.hslf.record.Slide getSlideRecord() {
return (org.apache.poi.hslf.record.Slide)getSheetContainer();
}
/** /**
* Returns the Notes Sheet for this slide, or null if there isn't one * Returns the Notes Sheet for this slide, or null if there isn't one
*/ */
public Notes getNotesSheet() { return _notes; } public Notes getNotesSheet() { return _notes; }
/**
* Returns the PPDrawing associated with this slide, or null if there isn't one
*/
protected PPDrawing getPPDrawing() { return _slide.getPPDrawing(); }
/** /**
* @return set of records inside <code>SlideListWithtext</code> container * @return set of records inside <code>SlideListWithtext</code> container
* which hold text data for this slide (typically for placeholders). * which hold text data for this slide (typically for placeholders).
@ -225,60 +204,43 @@ public class Slide extends Sheet
protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; } protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; }
/** /**
* Returns the slide master associated with this slide. * Returns master sheet associated with this slide.
* It can be either SlideMaster or TitleMaster objects.
* *
* @return the slide master associated with this slide. * @return the master sheet associated with this slide.
*/ */
public MasterSheet getMasterSheet(){ public MasterSheet getMasterSheet(){
SlideMaster[] master = getSlideShow().getSlidesMasters(); SlideMaster[] master = getSlideShow().getSlidesMasters();
SlideAtom sa = _slide.getSlideAtom(); SlideAtom sa = getSlideRecord().getSlideAtom();
int masterId = sa.getMasterID(); int masterId = sa.getMasterID();
MasterSheet sheet = null;
for (int i = 0; i < master.length; i++) { for (int i = 0; i < master.length; i++) {
if (masterId == master[i]._getSheetNumber()) return master[i]; if (masterId == master[i]._getSheetNumber()) {
sheet = master[i];
break;
} }
return null; }
if (sheet == null){
TitleMaster[] titleMaster = getSlideShow().getTitleMasters();
if(titleMaster != null) for (int i = 0; i < titleMaster.length; i++) {
if (masterId == titleMaster[i]._getSheetNumber()) {
sheet = titleMaster[i];
break;
}
}
}
return sheet;
} }
/** /**
* Change Master of this slide. * Change Master of this slide.
*/ */
public void setMasterSheet(MasterSheet master){ public void setMasterSheet(MasterSheet master){
SlideAtom sa = _slide.getSlideAtom(); SlideAtom sa = getSlideRecord().getSlideAtom();
int sheetNo = master._getSheetNumber(); int sheetNo = master._getSheetNumber();
sa.setMasterID(sheetNo); sa.setMasterID(sheetNo);
} }
public ColorSchemeAtom getColorScheme(){
return _slide.getColorScheme();
}
/**
* Returns the background shape for this sheet.
*
* @return the background shape for this sheet.
*/
public Background getBackground(){
if (_background == null){
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
EscherContainerRecord spContainer = null;
List ch = dg.getChildRecords();
for (Iterator it = ch.iterator(); it.hasNext();) {
EscherRecord rec = (EscherRecord)it.next();
if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER){
spContainer = (EscherContainerRecord)rec;
break;
}
}
_background = new Background(spContainer, null);
_background.setSheet(this);
}
return _background;
}
/** /**
* Sets whether this slide follows master background * Sets whether this slide follows master background
* *
@ -286,7 +248,7 @@ public class Slide extends Sheet
* <code>false</code> otherwise * <code>false</code> otherwise
*/ */
public void setFollowMasterBackground(boolean flag){ public void setFollowMasterBackground(boolean flag){
SlideAtom sa = _slide.getSlideAtom(); SlideAtom sa = getSlideRecord().getSlideAtom();
sa.setFollowMasterBackground(flag); sa.setFollowMasterBackground(flag);
} }
@ -297,7 +259,7 @@ public class Slide extends Sheet
* <code>false</code> otherwise * <code>false</code> otherwise
*/ */
public boolean getFollowMasterBackground(){ public boolean getFollowMasterBackground(){
SlideAtom sa = _slide.getSlideAtom(); SlideAtom sa = getSlideRecord().getSlideAtom();
return sa.getFollowMasterBackground(); return sa.getFollowMasterBackground();
} }
} }

View File

@ -36,11 +36,7 @@ import java.util.Iterator;
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class SlideMaster extends MasterSheet { public class SlideMaster extends MasterSheet {
private int _refSheetNo;
private int _sheetNo;
private MainMaster _master;
private TextRun[] _runs; private TextRun[] _runs;
private Background _background;
/** /**
* all TxMasterStyleAtoms available in this master * all TxMasterStyleAtoms available in this master
@ -51,16 +47,11 @@ public class SlideMaster extends MasterSheet {
* Constructs a SlideMaster from the MainMaster record, * Constructs a SlideMaster from the MainMaster record,
* *
*/ */
public SlideMaster(org.apache.poi.hslf.record.MainMaster rec, int slideId) { public SlideMaster(MainMaster record, int sheetNo) {
_master = rec; super(record, sheetNo);
// Grab our internal sheet ID _runs = findTextRuns(getPPDrawing());
_refSheetNo = rec.getSheetId(); for (int i = 0; i < _runs.length; i++) _runs[i].setSheet(this);
// Grab the number of the slide we're for, via the NotesAtom
_sheetNo = slideId;
_runs = findTextRuns(_master.getPPDrawing());
} }
/** /**
@ -71,26 +62,10 @@ public class SlideMaster extends MasterSheet {
} }
/** /**
* Returns the (internal, RefID based) sheet number, as used * Returns <code>null</code> since SlideMasters doen't have master sheet.
* to in PersistPtr stuff.
*/ */
public int _getSheetRefId() { public MasterSheet getMasterSheet() {
return _refSheetNo; return null;
}
/**
* Returns the (internal, SlideIdentifer based) number of the
* slide we're attached to
*/
public int _getSheetNumber() {
return _sheetNo;
}
/**
* Returns the PPDrawing associated with this slide master
*/
protected PPDrawing getPPDrawing() {
return _master.getPPDrawing();
} }
/** /**
@ -138,44 +113,10 @@ public class SlideMaster extends MasterSheet {
TxMasterStyleAtom txdoc = getSlideShow().getDocumentRecord().getEnvironment().getTxMasterStyleAtom(); TxMasterStyleAtom txdoc = getSlideShow().getDocumentRecord().getEnvironment().getTxMasterStyleAtom();
_txmaster[txdoc.getTextType()] = txdoc; _txmaster[txdoc.getTextType()] = txdoc;
TxMasterStyleAtom[] txrec = _master.getTxMasterStyleAtoms(); TxMasterStyleAtom[] txrec = ((MainMaster)getSheetContainer()).getTxMasterStyleAtoms();
for (int i = 0; i < txrec.length; i++) { for (int i = 0; i < txrec.length; i++) {
_txmaster[txrec[i].getTextType()] = txrec[i]; _txmaster[txrec[i].getTextType()] = txrec[i];
} }
} }
} }
/**
* Returns the ColorSchemeAtom associated with this slide master
*/
public ColorSchemeAtom getColorScheme(){
return _master.getColorScheme();
}
/**
* Returns the background shape for this sheet.
*
* @return the background shape for this sheet.
*/
public Background getBackground(){
if (_background == null){
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
EscherContainerRecord spContainer = null;
List ch = dg.getChildRecords();
for (Iterator it = ch.iterator(); it.hasNext();) {
EscherRecord rec = (EscherRecord)it.next();
if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER){
spContainer = (EscherContainerRecord)rec;
break;
}
}
_background = new Background(spContainer, null);
_background.setSheet(this);
}
return _background;
}
} }

View File

@ -0,0 +1,69 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hslf.model;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.record.*;
/**
* Title masters define the design template for slides with a Title Slide layout.
*
* @author Yegor Kozlov
*/
public class TitleMaster extends MasterSheet {
private TextRun[] _runs;
/**
* Constructs a TitleMaster
*
*/
public TitleMaster(org.apache.poi.hslf.record.Slide record, int sheetNo) {
super(record, sheetNo);
_runs = findTextRuns(getPPDrawing());
for (int i = 0; i < _runs.length; i++) _runs[i].setSheet(this);
}
/**
* Returns an array of all the TextRuns found
*/
public TextRun[] getTextRuns() {
return _runs;
}
/**
* Delegate the call to the underlying slide master.
*/
public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
MasterSheet master = getMasterSheet();
return master == null ? null : master.getStyleAttribute(txtype, level, name, isCharacter);
}
/**
* Returns the slide master for this title master.
*/
public MasterSheet getMasterSheet(){
SlideMaster[] master = getSlideShow().getSlidesMasters();
SlideAtom sa = ((org.apache.poi.hslf.record.Slide)getSheetContainer()).getSlideAtom();
int masterId = sa.getMasterID();
for (int i = 0; i < master.length; i++) {
if (masterId == master[i]._getSheetNumber()) return master[i];
}
return null;
}
}

View File

@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndian;
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class MainMaster extends PositionDependentRecordContainer public class MainMaster extends SheetContainer
{ {
private byte[] _header; private byte[] _header;
private static long _type = 1016; private static long _type = 1016;

View File

@ -29,7 +29,7 @@ import java.io.OutputStream;
* @author Nick Burch * @author Nick Burch
*/ */
public class Notes extends PositionDependentRecordContainer public class Notes extends SheetContainer
{ {
private byte[] _header; private byte[] _header;
private static long _type = 1008l; private static long _type = 1008l;
@ -37,6 +37,7 @@ public class Notes extends PositionDependentRecordContainer
// Links to our more interesting children // Links to our more interesting children
private NotesAtom notesAtom; private NotesAtom notesAtom;
private PPDrawing ppDrawing; private PPDrawing ppDrawing;
private ColorSchemeAtom _colorScheme;
/** /**
* Returns the NotesAtom of this Notes * Returns the NotesAtom of this Notes
@ -69,6 +70,9 @@ public class Notes extends PositionDependentRecordContainer
if(_children[i] instanceof PPDrawing) { if(_children[i] instanceof PPDrawing) {
ppDrawing = (PPDrawing)_children[i]; ppDrawing = (PPDrawing)_children[i];
} }
if(ppDrawing != null && _children[i] instanceof ColorSchemeAtom) {
_colorScheme = (ColorSchemeAtom)_children[i];
}
} }
} }
@ -85,4 +89,8 @@ public class Notes extends PositionDependentRecordContainer
public void writeOut(OutputStream out) throws IOException { public void writeOut(OutputStream out) throws IOException {
writeOut(_header[0],_header[1],_type,_children,out); writeOut(_header[0],_header[1],_type,_children,out);
} }
public ColorSchemeAtom getColorScheme(){
return _colorScheme;
}
} }

View File

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.poi.hslf.record;
/**
* The superclass of all sheet container records - Slide, Notes, MainMaster, etc.
*/
public abstract class SheetContainer extends PositionDependentRecordContainer {
/**
* Returns the PPDrawing of this sheet, which has all the
* interesting data in it
*/
public abstract PPDrawing getPPDrawing();
public abstract ColorSchemeAtom getColorScheme();
}

View File

@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndian;
* @author Nick Burch * @author Nick Burch
*/ */
public class Slide extends PositionDependentRecordContainer public class Slide extends SheetContainer
{ {
private byte[] _header; private byte[] _header;
private static long _type = 1006l; private static long _type = 1006l;

View File

@ -23,9 +23,11 @@ package org.apache.poi.hslf.usermodel;
import org.apache.poi.hslf.model.TextRun; import org.apache.poi.hslf.model.TextRun;
import org.apache.poi.hslf.model.Sheet; import org.apache.poi.hslf.model.Sheet;
import org.apache.poi.hslf.model.SlideMaster; import org.apache.poi.hslf.model.SlideMaster;
import org.apache.poi.hslf.model.MasterSheet;
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp; import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
import org.apache.poi.hslf.model.textproperties.TextProp; import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection; import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
import org.apache.poi.hslf.record.ColorSchemeAtom; import org.apache.poi.hslf.record.ColorSchemeAtom;
import java.awt.*; import java.awt.*;
@ -169,7 +171,7 @@ public class RichTextRun
if (cftp == null){ if (cftp == null){
Sheet sheet = parentRun.getSheet(); Sheet sheet = parentRun.getSheet();
int txtype = parentRun.getRunType(); int txtype = parentRun.getRunType();
SlideMaster master = (SlideMaster)sheet.getMasterSheet(); MasterSheet master = sheet.getMasterSheet();
if (master != null) if (master != null)
cftp = (CharFlagsTextProp)master.getStyleAttribute(txtype, getIndentLevel(), "char_flags", true); cftp = (CharFlagsTextProp)master.getStyleAttribute(txtype, getIndentLevel(), "char_flags", true);
} }
@ -223,7 +225,7 @@ public class RichTextRun
if (prop == null){ if (prop == null){
Sheet sheet = parentRun.getSheet(); Sheet sheet = parentRun.getSheet();
int txtype = parentRun.getRunType(); int txtype = parentRun.getRunType();
SlideMaster master = (SlideMaster)sheet.getMasterSheet(); MasterSheet master = sheet.getMasterSheet();
if (master != null) if (master != null)
prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, true); prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, true);
} }
@ -243,7 +245,7 @@ public class RichTextRun
if (prop == null){ if (prop == null){
Sheet sheet = parentRun.getSheet(); Sheet sheet = parentRun.getSheet();
int txtype = parentRun.getRunType(); int txtype = parentRun.getRunType();
SlideMaster master = (SlideMaster)sheet.getMasterSheet(); MasterSheet master = sheet.getMasterSheet();
if (master != null) if (master != null)
prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false); prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false);
} }

View File

@ -74,6 +74,7 @@ public class SlideShow
// Friendly objects for people to deal with // Friendly objects for people to deal with
private SlideMaster[] _masters; private SlideMaster[] _masters;
private TitleMaster[] _titleMasters;
private Slide[] _slides; private Slide[] _slides;
private Notes[] _notes; private Notes[] _notes;
private FontCollection _fonts; private FontCollection _fonts;
@ -311,25 +312,33 @@ public class SlideShow
// About the only thing you can say is that the master details are in // About the only thing you can say is that the master details are in
// the first SLWT. // the first SLWT.
SlideAtomsSet[] masterSets = new SlideAtomsSet[0]; SlideAtomsSet[] masterSets = new SlideAtomsSet[0];
org.apache.poi.hslf.record.MainMaster[] mainMasterRecords = null;
if (masterSLWT != null){ if (masterSLWT != null){
masterSets = masterSLWT.getSlideAtomsSets(); masterSets = masterSLWT.getSlideAtomsSets();
// For now, we only care about the records which are MainMasters
// (In future, we might want to know about the other too)
ArrayList mmr = new ArrayList(); ArrayList mmr = new ArrayList();
ArrayList tmr = new ArrayList();
for(int i=0; i<masterSets.length; i++) { for(int i=0; i<masterSets.length; i++) {
Record r = getCoreRecordForSAS(masterSets[i]); Record r = getCoreRecordForSAS(masterSets[i]);
SlideAtomsSet sas = masterSets[i];
int sheetNo = sas.getSlidePersistAtom().getSlideIdentifier();
if(r instanceof org.apache.poi.hslf.record.Slide) { if(r instanceof org.apache.poi.hslf.record.Slide) {
// Slide master, skip TitleMaster master = new TitleMaster((org.apache.poi.hslf.record.Slide)r, sheetNo);
master.setSlideShow(this);
tmr.add(master);
} else if(r instanceof org.apache.poi.hslf.record.MainMaster) { } else if(r instanceof org.apache.poi.hslf.record.MainMaster) {
mmr.add(r); SlideMaster master = new SlideMaster((org.apache.poi.hslf.record.MainMaster)r, sheetNo);
master.setSlideShow(this);
mmr.add(master);
} }
} }
mainMasterRecords = new org.apache.poi.hslf.record.MainMaster[mmr.size()]; _masters = new SlideMaster[mmr.size()];
mmr.toArray(mainMasterRecords); mmr.toArray(_masters);
_titleMasters = new TitleMaster[tmr.size()];
tmr.toArray(_titleMasters);
} }
@ -394,14 +403,6 @@ public class SlideShow
} }
// Finally, generate model objects for everything // Finally, generate model objects for everything
_masters = new SlideMaster[mainMasterRecords.length];
for(int i=0; i<_masters.length; i++) {
SlideAtomsSet sas = masterSets[i];
int sheetNo = sas.getSlidePersistAtom().getSlideIdentifier();
_masters[i] = new SlideMaster(mainMasterRecords[i], sheetNo);
_masters[i].setSlideShow(this);
}
// Notes first // Notes first
_notes = new Notes[notesRecords.length]; _notes = new Notes[notesRecords.length];
for(int i=0; i<_notes.length; i++) { for(int i=0; i<_notes.length; i++) {
@ -465,10 +466,14 @@ public class SlideShow
public Notes[] getNotes() { return _notes; } public Notes[] getNotes() { return _notes; }
/** /**
* Returns an array of all the normal Slides found in the slideshow * Returns an array of all the normal Slide Masters found in the slideshow
*/ */
public SlideMaster[] getSlidesMasters() { return _masters; } public SlideMaster[] getSlidesMasters() { return _masters; }
/**
* Returns an array of all the normal Title Masters found in the slideshow
*/
public TitleMaster[] getTitleMasters() { return _titleMasters; }
/** /**
* Returns the data of all the pictures attached to the SlideShow * Returns the data of all the pictures attached to the SlideShow
*/ */

View File

@ -0,0 +1,100 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hslf.model;
import junit.framework.TestCase;
import java.io.FileInputStream;
import java.io.File;
import org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.usermodel.SlideShow;
/**
* Test common functionality of the <code>Sheet</code> object.
* For each ppt in the test directory check that all sheets are properly initialized
*
* @author Yegor Kozlov
*/
public class TestSheet extends TestCase{
/**
* For each ppt in the test directory check that all sheets are properly initialized
*/
public void testSheet() throws Exception {
File home = new File(System.getProperty("HSLF.testdata.path"));
File[] files = home.listFiles();
for (int i = 0; i < files.length; i++) {
if(!files[i].getName().endsWith(".ppt")) continue;
try {
FileInputStream is = new FileInputStream(files[i]);
HSLFSlideShow hslf = new HSLFSlideShow(is);
is.close();
SlideShow ppt = new SlideShow(hslf);
doSlideShow(ppt);
} catch (EncryptedPowerPointFileException e){
; //skip encrypted ppt
}
}
}
private void doSlideShow(SlideShow ppt) throws Exception {
Slide[] slide = ppt.getSlides();
for (int i = 0; i < slide.length; i++) {
verify(slide[i]);
Notes notes = slide[i].getNotesSheet();
if(notes != null) verify(notes);
MasterSheet master = slide[i].getMasterSheet();
assertNotNull(master);
verify(master);
}
}
private void verify(Sheet sheet){
ColorSchemeAtom colorscheme = sheet.getColorScheme();
assertNotNull(colorscheme);
PPDrawing ppdrawing = sheet.getPPDrawing();
assertNotNull(ppdrawing);
Background background = sheet.getBackground();
assertNotNull(background);
assertTrue(sheet._getSheetNumber() != 0);
assertTrue(sheet._getSheetRefId() != 0);
TextRun[] txt = sheet.getTextRuns();
assertTrue(txt != null);
for (int i = 0; i < txt.length; i++) {
assertNotNull(txt[i].getSheet());
}
Shape[] shape = sheet.getShapes();
assertTrue(shape != null);
for (int i = 0; i < shape.length; i++) {
assertNotNull(shape[i].getSheet());
}
assertNotNull(sheet.getSlideShow());
}
}

View File

@ -27,6 +27,7 @@ import org.apache.poi.hslf.record.StyleTextPropAtom.*;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.awt.*;
/** /**
* Tests for SlideMaster * Tests for SlideMaster
@ -81,13 +82,63 @@ public class TestSlideMaster extends TestCase{
assertEquals("Georgia", env.getFontCollection().getFontWithId(b2)); assertEquals("Georgia", env.getFontCollection().getFontWithId(b2));
} }
/**
* Test we can read default text attributes for a title master sheet
*/
public void testTitleMasterTextAttributes() throws Exception {
SlideShow ppt = new SlideShow(new HSLFSlideShow(home + "/slide_master.ppt"));
TitleMaster[] master = ppt.getTitleMasters();
assertEquals(1, master.length);
assertEquals(32, master[0].getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "font.size", true).getValue());
CharFlagsTextProp prop1 = (CharFlagsTextProp)master[0].getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "char_flags", true);
assertEquals(true, prop1.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(true, prop1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
assertEquals(20, master[0].getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "font.size", true).getValue());
CharFlagsTextProp prop2 = (CharFlagsTextProp)master[0].getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "char_flags", true);
assertEquals(true, prop2.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
}
/**
* Slide 3 has title layout and follows the TitleMaster. Verify that.
*/
public void testTitleMaster() throws Exception {
SlideShow ppt = new SlideShow(new HSLFSlideShow(home + "/slide_master.ppt"));
Slide slide = ppt.getSlides()[2];
MasterSheet masterSheet = slide.getMasterSheet();
assertTrue(masterSheet instanceof TitleMaster);
TextRun[] txt = slide.getTextRuns();
for (int i = 0; i < txt.length; i++) {
RichTextRun rt = txt[i].getRichTextRuns()[0];
switch(txt[i].getRunType()){
case TextHeaderAtom.CENTER_TITLE_TYPE:
assertEquals("Arial", rt.getFontName());
assertEquals(32, rt.getFontSize());
assertEquals(true, rt.isBold());
assertEquals(true, rt.isUnderlined());
break;
case TextHeaderAtom.CENTRE_BODY_TYPE:
assertEquals("Courier New", rt.getFontName());
assertEquals(20, rt.getFontSize());
assertEquals(true, rt.isBold());
assertEquals(false, rt.isUnderlined());
break;
}
}
}
/** /**
* If a style attribute is not set ensure it is read from the master * If a style attribute is not set ensure it is read from the master
*/ */
public void testMasterAttributes() throws Exception { public void testMasterAttributes() throws Exception {
SlideShow ppt = new SlideShow(new HSLFSlideShow(home + "/slide_master.ppt")); SlideShow ppt = new SlideShow(new HSLFSlideShow(home + "/slide_master.ppt"));
Slide[] slide = ppt.getSlides(); Slide[] slide = ppt.getSlides();
assertEquals(2, slide.length); assertEquals(3, slide.length);
TextRun[] trun; TextRun[] trun;
trun = slide[0].getTextRuns(); trun = slide[0].getTextRuns();

View File

@ -163,4 +163,25 @@ public class TestBugs extends TestCase {
assertTrue("No Exceptions while reading file", true); assertTrue("No Exceptions while reading file", true);
} }
/**
* Bug 41381: Exception from Slide.getMasterSheet() on a seemingly valid PPT file
*/
public void test41381() throws Exception {
FileInputStream is = new FileInputStream(new File(cwd, "alterman_security.ppt"));
HSLFSlideShow hslf = new HSLFSlideShow(is);
is.close();
SlideShow ppt = new SlideShow(hslf);
assertTrue("No Exceptions while reading file", true);
assertEquals(1, ppt.getSlidesMasters().length);
assertEquals(1, ppt.getTitleMasters().length);
Slide[] slide = ppt.getSlides();
for (int i = 0; i < slide.length; i++) {
MasterSheet master = slide[i].getMasterSheet();
if (i == 0) assertTrue(master instanceof TitleMaster); //the first slide follows TitleMaster
else assertTrue(master instanceof SlideMaster);
}
}
} }