mirror of https://github.com/apache/poi.git
Fix bug #45590: Header/footer extraction for .ppt files saved in Office 2007
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@685054 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
481dcf900f
commit
9213d605e2
|
@ -37,6 +37,7 @@
|
|||
|
||||
<!-- Don't forget to update status.xml too! -->
|
||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">45590 - Fix for Header/footer extraction for .ppt files saved in Office 2007</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Big improvement in how HWPF handles unicode text, and more sanity checking of text ranges within HWPF</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Include headers and footers int he extracted text from HWPF's WordExtractor</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Added support to HWPF for headers and footers</action>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<!-- Don't forget to update changes.xml too! -->
|
||||
<changes>
|
||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">45590 - Fix for Header/footer extraction for .ppt files saved in Office 2007</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Big improvement in how HWPF handles unicode text, and more sanity checking of text ranges within HWPF</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Include headers and footers int he extracted text from HWPF's WordExtractor</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Added support to HWPF for headers and footers</action>
|
||||
|
|
|
@ -32,11 +32,22 @@ public class HeadersFooters {
|
|||
private HeadersFootersContainer _container;
|
||||
private boolean _newRecord;
|
||||
private SlideShow _ppt;
|
||||
private Sheet _sheet;
|
||||
private boolean _ppt2007;
|
||||
|
||||
public HeadersFooters(HeadersFootersContainer rec, SlideShow ppt, boolean newRecord){
|
||||
|
||||
public HeadersFooters(HeadersFootersContainer rec, SlideShow ppt, boolean newRecord, boolean isPpt2007){
|
||||
_container = rec;
|
||||
_newRecord = newRecord;
|
||||
_ppt = ppt;
|
||||
_ppt2007 = isPpt2007;
|
||||
}
|
||||
|
||||
public HeadersFooters(HeadersFootersContainer rec, Sheet sheet, boolean newRecord, boolean isPpt2007){
|
||||
_container = rec;
|
||||
_newRecord = newRecord;
|
||||
_sheet = sheet;
|
||||
_ppt2007 = isPpt2007;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,8 +56,8 @@ public class HeadersFooters {
|
|||
* @return Headers's text
|
||||
*/
|
||||
public String getHeaderText(){
|
||||
CString cs = _container.getHeaderAtom();
|
||||
return cs == null ? null : cs.getText();
|
||||
CString cs = _container == null ? null : _container.getHeaderAtom();
|
||||
return getPlaceholderText(OEPlaceholderAtom.MasterHeader, cs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,8 +81,8 @@ public class HeadersFooters {
|
|||
* @return Footer's text
|
||||
*/
|
||||
public String getFooterText(){
|
||||
CString cs = _container.getFooterAtom();
|
||||
return cs == null ? null : cs.getText();
|
||||
CString cs = _container == null ? null : _container.getFooterAtom();
|
||||
return getPlaceholderText(OEPlaceholderAtom.MasterFooter, cs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,8 +106,8 @@ public class HeadersFooters {
|
|||
* @return custom user date
|
||||
*/
|
||||
public String getDateTimeText(){
|
||||
CString cs = _container.getUserDateAtom();
|
||||
return cs == null ? null : cs.getText();
|
||||
CString cs = _container == null ? null : _container.getUserDateAtom();
|
||||
return getPlaceholderText(OEPlaceholderAtom.MasterDate, cs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,7 +130,7 @@ public class HeadersFooters {
|
|||
* whether the footer text is displayed.
|
||||
*/
|
||||
public boolean isFooterVisible(){
|
||||
return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasFooter);
|
||||
return isVisible(HeadersFootersAtom.fHasFooter, OEPlaceholderAtom.MasterFooter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,7 +145,7 @@ public class HeadersFooters {
|
|||
* whether the header text is displayed.
|
||||
*/
|
||||
public boolean isHeaderVisible(){
|
||||
return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasHeader);
|
||||
return isVisible(HeadersFootersAtom.fHasHeader, OEPlaceholderAtom.MasterHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,7 +160,7 @@ public class HeadersFooters {
|
|||
* whether the date is displayed in the footer.
|
||||
*/
|
||||
public boolean isDateTimeVisible(){
|
||||
return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasDate);
|
||||
return isVisible(HeadersFootersAtom.fHasDate, OEPlaceholderAtom.MasterDate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,7 +175,7 @@ public class HeadersFooters {
|
|||
* whether the custom user date is used instead of today's date.
|
||||
*/
|
||||
public boolean isUserDateVisible(){
|
||||
return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasUserDate);
|
||||
return isVisible(HeadersFootersAtom.fHasUserDate, OEPlaceholderAtom.MasterDate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,7 +190,7 @@ public class HeadersFooters {
|
|||
* whether the slide number is displayed in the footer.
|
||||
*/
|
||||
public boolean isSlideNumberVisible(){
|
||||
return _container.getHeadersFootersAtom().getFlag(HeadersFootersAtom.fHasSlideNumber);
|
||||
return isVisible(HeadersFootersAtom.fHasSlideNumber, OEPlaceholderAtom.MasterSlideNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,4 +236,32 @@ public class HeadersFooters {
|
|||
doc.addChildAfter(_container, lst);
|
||||
_newRecord = false;
|
||||
}
|
||||
|
||||
private boolean isVisible(int flag, int placeholderId){
|
||||
boolean visible;
|
||||
if(_ppt2007){
|
||||
Sheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0];
|
||||
TextShape placeholder = master.getPlaceholder(placeholderId);
|
||||
visible = placeholder != null && placeholder.getText() != null;
|
||||
} else {
|
||||
visible = _container.getHeadersFootersAtom().getFlag(flag);
|
||||
}
|
||||
return visible;
|
||||
}
|
||||
|
||||
private String getPlaceholderText(int placeholderId, CString cs){
|
||||
String text = null;
|
||||
if(_ppt2007){
|
||||
Sheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0];
|
||||
TextShape placeholder = master.getPlaceholder(placeholderId);
|
||||
if(placeholder != null) text = placeholder.getText();
|
||||
|
||||
//default text in master placeholders is not visible
|
||||
if("*".equals(text)) text = null;
|
||||
} else {
|
||||
text = cs == null ? null : cs.getText();
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.poi.hslf.model;
|
|||
import org.apache.poi.hslf.record.SheetContainer;
|
||||
import org.apache.poi.hslf.record.Record;
|
||||
import org.apache.poi.hslf.record.RecordTypes;
|
||||
import org.apache.poi.hslf.record.OEPlaceholderAtom;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
|
||||
/**
|
||||
|
@ -54,20 +55,4 @@ public abstract class MasterSheet extends Sheet {
|
|||
return tx.getPlaceholderAtom() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return placeholder by text type
|
||||
*/
|
||||
public TextShape getPlaceholder(int type){
|
||||
Shape[] shape = getShapes();
|
||||
for (int i = 0; i < shape.length; i++) {
|
||||
if(shape[i] instanceof TextShape){
|
||||
TextShape tx = (TextShape)shape[i];
|
||||
TextRun run = tx.getTextRun();
|
||||
if(run != null && run.getRunType() == type){
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,4 +362,83 @@ public abstract class Sheet {
|
|||
public void draw(Graphics2D graphics){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return placeholder by text type
|
||||
*
|
||||
* @param type type of text, See {@link org.apache.poi.hslf.record.TextHeaderAtom}
|
||||
* @return <code>TextShape</code> or <code>null</code>
|
||||
*/
|
||||
public TextShape getPlaceholderByTextType(int type){
|
||||
Shape[] shape = getShapes();
|
||||
for (int i = 0; i < shape.length; i++) {
|
||||
if(shape[i] instanceof TextShape){
|
||||
TextShape tx = (TextShape)shape[i];
|
||||
TextRun run = tx.getTextRun();
|
||||
if(run != null && run.getRunType() == type){
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search text placeholer by its type
|
||||
*
|
||||
* @param type type of placeholder to search. See {@link org.apache.poi.hslf.record.OEPlaceholderAtom}
|
||||
* @return <code>TextShape</code> or <code>null</code>
|
||||
*/
|
||||
public TextShape getPlaceholder(int type){
|
||||
Shape[] shape = getShapes();
|
||||
for (int i = 0; i < shape.length; i++) {
|
||||
if(shape[i] instanceof TextShape){
|
||||
TextShape tx = (TextShape)shape[i];
|
||||
int placeholderId = 0;
|
||||
OEPlaceholderAtom oep = tx.getPlaceholderAtom();
|
||||
if(oep != null) {
|
||||
placeholderId = oep.getPlaceholderId();
|
||||
} else {
|
||||
//special case for files saved in Office 2007
|
||||
RoundTripHFPlaceholder12 hldr = (RoundTripHFPlaceholder12)tx.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID);
|
||||
if(hldr != null) placeholderId = hldr.getPlaceholderId();
|
||||
}
|
||||
if(placeholderId == type){
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return programmable tag associated with this sheet, e.g. <code>___PPT12</code>.
|
||||
*
|
||||
* @return programmable tag associated with this sheet.
|
||||
*/
|
||||
public String getProgrammableTag(){
|
||||
String tag = null;
|
||||
RecordContainer progTags = (RecordContainer)
|
||||
getSheetContainer().findFirstOfType(
|
||||
RecordTypes.ProgTags.typeID
|
||||
);
|
||||
if(progTags != null) {
|
||||
RecordContainer progBinaryTag = (RecordContainer)
|
||||
progTags.findFirstOfType(
|
||||
RecordTypes.ProgBinaryTag.typeID
|
||||
);
|
||||
if(progBinaryTag != null) {
|
||||
CString binaryTag = (CString)
|
||||
progBinaryTag.findFirstOfType(
|
||||
RecordTypes.CString.typeID
|
||||
);
|
||||
if(binaryTag != null) tag = binaryTag.getText();
|
||||
}
|
||||
}
|
||||
|
||||
return tag;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -440,14 +440,24 @@ public class Slide extends Sheet
|
|||
public HeadersFooters getHeadersFooters(){
|
||||
HeadersFootersContainer hdd = null;
|
||||
Record[] ch = getSheetContainer().getChildRecords();
|
||||
boolean ppt2007 = false;
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
if(ch[i] instanceof HeadersFootersContainer){
|
||||
hdd = (HeadersFootersContainer)ch[i];
|
||||
break;
|
||||
} else if (ch[i].getRecordType() == RecordTypes.RoundTripContentMasterId.typeID){
|
||||
ppt2007 = true;
|
||||
}
|
||||
}
|
||||
boolean newRecord = false;
|
||||
if(hdd == null) return getSlideShow().getSlideHeadersFooters();
|
||||
else return new HeadersFooters(hdd, getSlideShow(), newRecord);
|
||||
if(hdd == null && !ppt2007) {
|
||||
return getSlideShow().getSlideHeadersFooters();
|
||||
}
|
||||
else {
|
||||
if(hdd == null) {
|
||||
hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer);
|
||||
newRecord = true;
|
||||
}
|
||||
return new HeadersFooters(hdd, this, newRecord, ppt2007);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ public abstract class TextShape extends SimpleShape {
|
|||
int type = getTextRun().getRunType();
|
||||
MasterSheet master = getSheet().getMasterSheet();
|
||||
if(master != null){
|
||||
TextShape masterShape = master.getPlaceholder(type);
|
||||
TextShape masterShape = master.getPlaceholderByTextType(type);
|
||||
if(masterShape != null) valign = masterShape.getVerticalAlignment();
|
||||
} else {
|
||||
//not found in the master sheet. Use the hardcoded defaults.
|
||||
|
|
|
@ -26,7 +26,7 @@ import java.io.OutputStream;
|
|||
/**
|
||||
* OEPlaceholderAtom (3011).
|
||||
* <p>
|
||||
* Atom that describes the placeholder.
|
||||
* An atom record that specifies whether a shape is a placeholder shape.
|
||||
* </p>
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
|
@ -34,61 +34,169 @@ import java.io.OutputStream;
|
|||
|
||||
public class OEPlaceholderAtom extends RecordAtom{
|
||||
|
||||
/**
|
||||
* The full size of the master body text placeholder shape.
|
||||
*/
|
||||
public static final int PLACEHOLDER_FULLSIZE = 0;
|
||||
|
||||
/**
|
||||
* Half of the size of the master body text placeholder shape.
|
||||
*/
|
||||
public static final int PLACEHOLDER_HALFSIZE = 1;
|
||||
|
||||
/**
|
||||
* A quarter of the size of the master body text placeholder shape.
|
||||
*/
|
||||
public static final int PLACEHOLDER_QUARTSIZE = 2;
|
||||
|
||||
/**
|
||||
* MUST NOT be used for this field.
|
||||
*/
|
||||
public static final byte None = 0;
|
||||
|
||||
/**
|
||||
* The corresponding shape contains the master title text.
|
||||
* The corresponding slide MUST be a main master slide.
|
||||
*/
|
||||
public static final byte MasterTitle = 1;
|
||||
|
||||
/**
|
||||
* The corresponding shape contains the master body text.
|
||||
* The corresponding slide MUST be a main master slide.
|
||||
*/
|
||||
public static final byte MasterBody = 2;
|
||||
|
||||
/**
|
||||
* The corresponding shape contains the master center title text.
|
||||
* The corresponding slide MUST be a title master slide.
|
||||
*/
|
||||
public static final byte MasterCenteredTitle = 3;
|
||||
|
||||
public static final byte MasterNotesSlideImage = 4;
|
||||
/**
|
||||
* The corresponding shape contains the master sub-title text.
|
||||
* The corresponding slide MUST be a title master slide.
|
||||
*/
|
||||
public static final byte MasterSubTitle = 4;
|
||||
|
||||
public static final byte MasterNotesBodyImage = 5;
|
||||
/**
|
||||
* The corresponding shape contains the shared properties for slide image shapes.
|
||||
* The corresponding slide MUST be a notes master slide.
|
||||
*/
|
||||
public static final byte MasterNotesSlideImage = 5;
|
||||
|
||||
public static final byte MasterDate = 6;
|
||||
/**
|
||||
* The corresponding shape contains the master body text.
|
||||
* The corresponding slide MUST be a notes master slide.
|
||||
*/
|
||||
public static final byte MasterNotesBody = 6;
|
||||
|
||||
public static final byte MasterSlideNumber = 7;
|
||||
/**
|
||||
* The corresponding shape contains the date text field.
|
||||
* The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide.
|
||||
*/
|
||||
public static final byte MasterDate = 7;
|
||||
|
||||
public static final byte MasterFooter = 8;
|
||||
/**
|
||||
* The corresponding shape contains a slide number text field.
|
||||
* The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide.
|
||||
*/
|
||||
public static final byte MasterSlideNumber = 8;
|
||||
|
||||
public static final byte MasterHeader = 9;
|
||||
/**
|
||||
* The corresponding shape contains a footer text field.
|
||||
* The corresponding slide MUST be a main master slide, title master slide, notes master slide, or handout master slide.
|
||||
*/
|
||||
public static final byte MasterFooter = 9;
|
||||
|
||||
public static final byte MasterSubtitle = 10;
|
||||
/**
|
||||
* The corresponding shape contains a header text field.
|
||||
* The corresponding slide must be a notes master slide or handout master slide.
|
||||
*/
|
||||
public static final byte MasterHeader = 10;
|
||||
|
||||
public static final byte GenericTextObject = 11;
|
||||
/**
|
||||
* The corresponding shape contains a presentation slide image.
|
||||
* The corresponding slide MUST be a notes slide.
|
||||
*/
|
||||
public static final byte NotesSlideImage = 11;
|
||||
|
||||
public static final byte Title = 12;
|
||||
/**
|
||||
* The corresponding shape contains the notes text.
|
||||
* The corresponding slide MUST be a notes slide.
|
||||
*/
|
||||
public static final byte NotesBody = 12;
|
||||
|
||||
public static final byte Body = 13;
|
||||
/**
|
||||
* The corresponding shape contains the title text.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte Title = 13;
|
||||
|
||||
public static final byte NotesBody = 14;
|
||||
/**
|
||||
* The corresponding shape contains the body text.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte Body = 14;
|
||||
|
||||
/**
|
||||
* The corresponding shape contains the title text.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte CenteredTitle = 15;
|
||||
|
||||
/**
|
||||
* The corresponding shape contains the sub-title text.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte Subtitle = 16;
|
||||
|
||||
/**
|
||||
* The corresponding shape contains the title text with vertical text flow.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte VerticalTextTitle = 17;
|
||||
|
||||
/**
|
||||
* The corresponding shape contains the body text with vertical text flow.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte VerticalTextBody = 18;
|
||||
|
||||
public static final byte NotesSlideImage = 19;
|
||||
/**
|
||||
* The corresponding shape contains a generic object.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte Object = 19;
|
||||
|
||||
public static final byte Object = 20;
|
||||
/**
|
||||
* The corresponding shape contains a chart object.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte Graph = 20;
|
||||
|
||||
public static final byte Graph = 21;
|
||||
/**
|
||||
* The corresponding shape contains a table object.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte Table = 21;
|
||||
|
||||
public static final byte Table = 22;
|
||||
/**
|
||||
* The corresponding shape contains a clipart object.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte ClipArt = 22;
|
||||
|
||||
public static final byte ClipArt = 23;
|
||||
/**
|
||||
* The corresponding shape contains an organization chart object.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte OrganizationChart = 23;
|
||||
|
||||
public static final byte OrganizationChart = 24;
|
||||
|
||||
public static final byte MediaClip = 25;
|
||||
/**
|
||||
* The corresponding shape contains a media object.
|
||||
* The corresponding slide MUST be a presentation slide.
|
||||
*/
|
||||
public static final byte MediaClip = 24;
|
||||
|
||||
private byte[] _header;
|
||||
|
||||
|
@ -116,11 +224,13 @@ public class OEPlaceholderAtom extends RecordAtom{
|
|||
*/
|
||||
protected OEPlaceholderAtom(byte[] source, int start, int len) {
|
||||
_header = new byte[8];
|
||||
System.arraycopy(source,start,_header,0,8);
|
||||
int offset = start;
|
||||
System.arraycopy(source,start,_header,0,8);
|
||||
offset += _header.length;
|
||||
|
||||
placementId = LittleEndian.getInt(source, start);
|
||||
placeholderId = LittleEndian.getUnsignedByte(source, start+4);
|
||||
placeholderSize = LittleEndian.getUnsignedByte(source, start+5);
|
||||
placementId = LittleEndian.getInt(source, offset); offset += 4;
|
||||
placeholderId = LittleEndian.getUnsignedByte(source, offset); offset++;
|
||||
placeholderSize = LittleEndian.getUnsignedByte(source, offset); offset++;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,6 +240,11 @@ public class OEPlaceholderAtom extends RecordAtom{
|
|||
|
||||
/**
|
||||
* Returns the placement Id.
|
||||
* <p>
|
||||
* The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders.
|
||||
* It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide.
|
||||
* The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape.
|
||||
* </p>
|
||||
*
|
||||
* @return the placement Id.
|
||||
*/
|
||||
|
@ -139,6 +254,11 @@ public class OEPlaceholderAtom extends RecordAtom{
|
|||
|
||||
/**
|
||||
* Sets the placement Id.
|
||||
* <p>
|
||||
* The placement Id is a number assigned to the placeholder. It goes from -1 to the number of placeholders.
|
||||
* It SHOULD be unique among all PlacholderAtom records contained in the corresponding slide.
|
||||
* The value 0xFFFFFFFF specifies that the corresponding shape is not a placeholder shape.
|
||||
* </p>
|
||||
*
|
||||
* @param id the placement Id.
|
||||
*/
|
||||
|
@ -149,6 +269,11 @@ public class OEPlaceholderAtom extends RecordAtom{
|
|||
/**
|
||||
* Returns the placeholder Id.
|
||||
*
|
||||
* <p>
|
||||
* placeholder Id specifies the type of the placeholder shape.
|
||||
* The value MUST be one of the static constants defined in this class
|
||||
* </p>
|
||||
*
|
||||
* @return the placeholder Id.
|
||||
*/
|
||||
public int getPlaceholderId(){
|
||||
|
@ -158,6 +283,10 @@ public class OEPlaceholderAtom extends RecordAtom{
|
|||
/**
|
||||
* Sets the placeholder Id.
|
||||
*
|
||||
* <p>
|
||||
* placeholder Id specifies the type of the placeholder shape.
|
||||
* The value MUST be one of the static constants defined in this class
|
||||
* </p>
|
||||
* @param id the placeholder Id.
|
||||
*/
|
||||
public void setPlaceholderId(byte id){
|
||||
|
|
|
@ -162,6 +162,17 @@ public class RecordTypes {
|
|||
// Records ~12050 seem to be related to Document Encryption
|
||||
public static final Type DocumentEncryptionAtom = new Type(12052,DocumentEncryptionAtom.class);
|
||||
|
||||
public static final Type OriginalMainMasterId = new Type(1052,null);
|
||||
public static final Type CompositeMasterId = new Type(1052,null);
|
||||
public static final Type RoundTripContentMasterInfo12 = new Type(1054,null);
|
||||
public static final Type RoundTripShapeId12 = new Type(1055,null);
|
||||
public static final Type RoundTripHFPlaceholder12 = new Type(1056,RoundTripHFPlaceholder12.class);
|
||||
public static final Type RoundTripContentMasterId = new Type(1058,null);
|
||||
public static final Type RoundTripOArtTextStyles12 = new Type(1059,null);
|
||||
public static final Type RoundTripShapeCheckSumForCustomLayouts12 = new Type(1062,null);
|
||||
public static final Type RoundTripNotesMasterTextStyles12 = new Type(1063,null);
|
||||
public static final Type RoundTripCustomTableStyles12 = new Type(1064,null);
|
||||
|
||||
//records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher
|
||||
public static final int EscherDggContainer = 0xf000;
|
||||
public static final int EscherDgg = 0xf006;
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/* ====================================================================
|
||||
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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.poi.hslf.util.SystemTimeUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* An atom record that specifies that a shape is a header or footer placeholder shape
|
||||
*
|
||||
* @since PowerPoint 2007
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
|
||||
public class RoundTripHFPlaceholder12 extends RecordAtom
|
||||
{
|
||||
/**
|
||||
* Record header.
|
||||
*/
|
||||
private byte[] _header;
|
||||
|
||||
/**
|
||||
* Specifies the placeholder shape ID.
|
||||
*
|
||||
* MUST be {@link OEPlaceholderAtom#MasterDate}, {@link OEPlaceholderAtom#MasterSlideNumber},
|
||||
* {@link OEPlaceholderAtom#MasterFooter}, or {@link OEPlaceholderAtom#MasterHeader}
|
||||
*/
|
||||
private byte _placeholderId;
|
||||
|
||||
/**
|
||||
* Constructs the comment atom record from its source data.
|
||||
*
|
||||
* @param source the source data as a byte array.
|
||||
* @param start the start offset into the byte array.
|
||||
* @param len the length of the slice in the byte array.
|
||||
*/
|
||||
protected RoundTripHFPlaceholder12(byte[] source, int start, int len) {
|
||||
// Get the header.
|
||||
_header = new byte[8];
|
||||
System.arraycopy(source,start,_header,0,8);
|
||||
|
||||
// Get the record data.
|
||||
_placeholderId = source[start+8];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the comment number (note - each user normally has their own count).
|
||||
* @return the comment number.
|
||||
*/
|
||||
public int getPlaceholderId() {
|
||||
return _placeholderId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the comment number (note - each user normally has their own count).
|
||||
* @param number the comment number.
|
||||
*/
|
||||
public void setPlaceholderId(int number) {
|
||||
_placeholderId = (byte)number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the record type.
|
||||
* @return the record type.
|
||||
*/
|
||||
public long getRecordType() { return RecordTypes.RoundTripHFPlaceholder12.typeID; }
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*
|
||||
* @param out the output stream to write to.
|
||||
* @throws java.io.IOException if an error occurs.
|
||||
*/
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
out.write(_header);
|
||||
out.write(_placeholderId);
|
||||
}
|
||||
}
|
|
@ -37,14 +37,7 @@ import org.apache.poi.ddf.EscherRecord;
|
|||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
|
||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||
import org.apache.poi.hslf.model.HeadersFooters;
|
||||
import org.apache.poi.hslf.model.Notes;
|
||||
import org.apache.poi.hslf.model.PPFont;
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.hslf.model.Shape;
|
||||
import org.apache.poi.hslf.model.Slide;
|
||||
import org.apache.poi.hslf.model.SlideMaster;
|
||||
import org.apache.poi.hslf.model.TitleMaster;
|
||||
import org.apache.poi.hslf.model.*;
|
||||
import org.apache.poi.hslf.record.Document;
|
||||
import org.apache.poi.hslf.record.DocumentAtom;
|
||||
import org.apache.poi.hslf.record.FontCollection;
|
||||
|
@ -843,6 +836,10 @@ public final class SlideShow {
|
|||
* @return Header / Footer settings for slides
|
||||
*/
|
||||
public HeadersFooters getSlideHeadersFooters(){
|
||||
//detect if this ppt was saved in Office2007
|
||||
String tag = getSlidesMasters()[0].getProgrammableTag();
|
||||
boolean ppt2007 = "___PPT12".equals(tag);
|
||||
|
||||
HeadersFootersContainer hdd = null;
|
||||
Record[] ch = _documentRecord.getChildRecords();
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
|
@ -857,7 +854,7 @@ public final class SlideShow {
|
|||
hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer);
|
||||
newRecord = true;
|
||||
}
|
||||
return new HeadersFooters(hdd, this, newRecord);
|
||||
return new HeadersFooters(hdd, this, newRecord, ppt2007);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -866,6 +863,10 @@ public final class SlideShow {
|
|||
* @return Header / Footer settings for notes
|
||||
*/
|
||||
public HeadersFooters getNotesHeadersFooters(){
|
||||
//detect if this ppt was saved in Office2007
|
||||
String tag = getSlidesMasters()[0].getProgrammableTag();
|
||||
boolean ppt2007 = "___PPT12".equals(tag);
|
||||
|
||||
HeadersFootersContainer hdd = null;
|
||||
Record[] ch = _documentRecord.getChildRecords();
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
|
@ -873,13 +874,18 @@ public final class SlideShow {
|
|||
((HeadersFootersContainer)ch[i]).getOptions() == HeadersFootersContainer.NotesHeadersFootersContainer){
|
||||
hdd = (HeadersFootersContainer)ch[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean newRecord = false;
|
||||
if(hdd == null) {
|
||||
hdd = new HeadersFootersContainer(HeadersFootersContainer.NotesHeadersFootersContainer);
|
||||
newRecord = true;
|
||||
}
|
||||
return new HeadersFooters(hdd, this, newRecord);
|
||||
if(ppt2007 && _notes.length > 0){
|
||||
return new HeadersFooters(hdd, _notes[0], newRecord, ppt2007);
|
||||
} else {
|
||||
return new HeadersFooters(hdd, this, newRecord, ppt2007);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -77,6 +77,112 @@ public class TestHeadersFooters extends TestCase
|
|||
assertEquals("custom date format", hd2.getDateTimeText());
|
||||
}
|
||||
|
||||
/**
|
||||
* If Headers / Footers are not set, all the getters should return <code>false</code> or <code>null</code>
|
||||
*/
|
||||
public void testReadNoHeadersFooters() throws Exception
|
||||
{
|
||||
File file = new File(cwd, "basic_test_ppt_file.ppt");
|
||||
FileInputStream is = new FileInputStream(file);
|
||||
SlideShow ppt = new SlideShow(is);
|
||||
is.close();
|
||||
|
||||
HeadersFooters slideHdd = ppt.getSlideHeadersFooters();
|
||||
assertFalse(slideHdd.isFooterVisible());
|
||||
assertNull(slideHdd.getFooterText());
|
||||
assertFalse(slideHdd.isSlideNumberVisible());
|
||||
assertFalse(slideHdd.isHeaderVisible());
|
||||
assertNull(slideHdd.getHeaderText());
|
||||
assertFalse(slideHdd.isUserDateVisible());
|
||||
assertNull(slideHdd.getDateTimeText());
|
||||
|
||||
|
||||
HeadersFooters notesHdd = ppt.getNotesHeadersFooters();
|
||||
assertFalse(notesHdd.isFooterVisible());
|
||||
assertNull(notesHdd.getFooterText());
|
||||
assertFalse(notesHdd.isHeaderVisible());
|
||||
assertNull(notesHdd.getHeaderText());
|
||||
assertFalse(notesHdd.isUserDateVisible());
|
||||
assertNull(notesHdd.getDateTimeText());
|
||||
|
||||
Slide[] slide = ppt.getSlides();
|
||||
for(int i=0 ; i < slide.length; i++){
|
||||
HeadersFooters hd1 = slide[i].getHeadersFooters();
|
||||
assertFalse(hd1.isFooterVisible());
|
||||
assertNull(hd1.getFooterText());
|
||||
assertFalse(hd1.isHeaderVisible());
|
||||
assertNull(hd1.getHeaderText());
|
||||
assertFalse(hd1.isUserDateVisible());
|
||||
assertNull(hd1.getDateTimeText());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test extraction of headers / footers from PPTs saved in Office 2007
|
||||
*/
|
||||
public void testRead2007() throws Exception
|
||||
{
|
||||
File file = new File(cwd, "headers_footers_2007.ppt");
|
||||
FileInputStream is = new FileInputStream(file);
|
||||
SlideShow ppt = new SlideShow(is);
|
||||
is.close();
|
||||
|
||||
HeadersFooters slideHdd = ppt.getSlideHeadersFooters();
|
||||
assertTrue(slideHdd.isFooterVisible());
|
||||
assertEquals("THE FOOTER TEXT", slideHdd.getFooterText());
|
||||
assertTrue(slideHdd.isSlideNumberVisible());
|
||||
assertFalse(slideHdd.isHeaderVisible());
|
||||
assertNull(slideHdd.getHeaderText());
|
||||
assertTrue(slideHdd.isUserDateVisible());
|
||||
assertEquals("Wednesday, August 06, 2008", slideHdd.getDateTimeText());
|
||||
|
||||
|
||||
HeadersFooters notesHdd = ppt.getNotesHeadersFooters();
|
||||
assertTrue(notesHdd.isFooterVisible());
|
||||
assertEquals("THE NOTES FOOTER TEXT", notesHdd.getFooterText());
|
||||
assertTrue(notesHdd.isHeaderVisible());
|
||||
assertEquals("THE NOTES HEADER TEXT", notesHdd.getHeaderText());
|
||||
assertTrue(notesHdd.isUserDateVisible());
|
||||
assertTrue(notesHdd.isDateTimeVisible());
|
||||
//TODO: depending on the formatId getDateTimeText() should return formatted date
|
||||
//assertEquals("08/12/08", notesHdd.getDateTimeText());
|
||||
|
||||
//per-slide headers / footers
|
||||
Slide[] slide = ppt.getSlides();
|
||||
//the first slide uses presentation-scope headers / footers
|
||||
HeadersFooters hd1 = slide[0].getHeadersFooters();
|
||||
assertTrue(hd1.isFooterVisible());
|
||||
assertEquals("THE FOOTER TEXT", hd1.getFooterText());
|
||||
assertTrue(hd1.isSlideNumberVisible());
|
||||
assertFalse(hd1.isHeaderVisible());
|
||||
assertNull(hd1.getHeaderText());
|
||||
assertTrue(hd1.isUserDateVisible());
|
||||
assertTrue(hd1.isDateTimeVisible());
|
||||
assertEquals("Wednesday, August 06, 2008", hd1.getDateTimeText());
|
||||
|
||||
//the second slide uses custom per-slide headers / footers
|
||||
HeadersFooters hd2 = slide[1].getHeadersFooters();
|
||||
assertTrue(hd2.isFooterVisible());
|
||||
assertEquals("THE FOOTER TEXT FOR SLIDE 2", hd2.getFooterText());
|
||||
assertTrue(hd2.isSlideNumberVisible());
|
||||
assertFalse(hd2.isHeaderVisible());
|
||||
assertNull(hd2.getHeaderText());
|
||||
assertTrue(hd2.isUserDateVisible());
|
||||
assertTrue(hd2.isDateTimeVisible());
|
||||
assertEquals("August 06, 2008", hd2.getDateTimeText());
|
||||
|
||||
//the third slide uses per-slide headers / footers
|
||||
HeadersFooters hd3 = slide[2].getHeadersFooters();
|
||||
assertTrue(hd3.isFooterVisible());
|
||||
assertEquals("THE FOOTER TEXT", hd3.getFooterText());
|
||||
assertTrue(hd3.isSlideNumberVisible());
|
||||
assertFalse(hd3.isHeaderVisible());
|
||||
assertNull(hd3.getHeaderText());
|
||||
assertTrue(hd3.isUserDateVisible());
|
||||
assertTrue(hd3.isDateTimeVisible());
|
||||
assertEquals("Wednesday, August 06, 2008", hd3.getDateTimeText());
|
||||
}
|
||||
|
||||
public void testCreateSlideFooters() throws Exception
|
||||
{
|
||||
SlideShow ppt = new SlideShow();
|
||||
|
|
Loading…
Reference in New Issue