diff options
author | Nick Burch <nick@apache.org> | 2008-08-12 08:51:08 +0000 |
---|---|---|
committer | Nick Burch <nick@apache.org> | 2008-08-12 08:51:08 +0000 |
commit | da62696507edb1a3eaee858d6f991f5dcc311276 (patch) | |
tree | 1f27a70bb06a2f4c85038a0f2c668deda0430d05 /src/scratchpad | |
parent | 1073cfb53d419fb9f91faec7e99d9b99448f6507 (diff) | |
download | poi-da62696507edb1a3eaee858d6f991f5dcc311276.tar.gz poi-da62696507edb1a3eaee858d6f991f5dcc311276.zip |
Merged revisions 638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-639917,639919-640056,640058-640710,640712-641156,641158-641184,641186-641795,641797-641798,641800-641933,641935-641963,641965-641966,641968-641995,641997-642230,642232-642562,642564-642565,642568-642570,642572-642573,642576-642736,642739-642877,642879,642881-642890,642892-642903,642905-642945,642947-643624,643626-643653,643655-643669,643671,643673-643830,643832-643833,643835-644342,644344-644472,644474-644508,644510-645347,645349-645351,645353-645559,645561-645565,645568-645951,645953-646193,646195-646311,646313-646404,646406-646665,646667-646853,646855-646869,646871-647151,647153-647185,647187-647277,647279-647566,647568-647573,647575,647578-647711,647714-647737,647739-647823,647825-648155,648157-648202,648204-648273,648275,648277-648302,648304-648333,648335-648588,648590-648622,648625-648673,648675-649141,649144,649146-649556,649558-649795,649799,649801-649910,649912-649913,649915-650128,650131-650132,650134-650137,650140-650914,650916-651991,651993-652284,652286-652287,652289,652291,652293-652297,652299-652328,652330-652425,652427-652445,652447-652560,652562-652933,652935,652937-652993,652995-653116,653118-653124,653126-653483,653487-653519,653522-653550,653552-653607,653609-653667,653669-653674,653676-653814,653817-653830,653832-653891,653893-653944,653946-654055,654057-654355,654357-654365,654367-654648,654651-655215,655217-655277,655279-655281,655283-655911,655913-656212,656214,656216-656251,656253-656698,656700-656756,656758-656892,656894-657135,657137-657165,657168-657179,657181-657354,657356-657357,657359-657701,657703-657874,657876-658032,658034-658284,658286,658288-658301,658303-658307,658309-658321,658323-658335,658337-658348,658351,658353-658832,658834-658983,658985,658987-659066,659068-659402,659404-659428,659430-659451,659453-659454,659456-659461,659463-659477,659479-659524,659526-659571,659574,659576-660255,660257-660262,660264-660279,660281-660343,660345-660473,660475-660827,660829-660833,660835-660888,660890-663321,663323-663435,663437-663764,663766-663854,663856-664219,664221-664489,664494-664514,664516-668013,668015-668142,668144-668152,668154,668156-668256,668258,668260-669139,669141-669455,669457-669657,669659-669808,669810-670189,670191-671321,671323-672229,672231-672549,672551-672552,672554-672561,672563-672566,672568,672571-673049,673051-673852,673854-673862,673864-673986,673988-673996,673998-674347,674349-674890,674892-674910,674912-674936,674938-674952,674954-675078,675080-675085,675087-675217,675219-675660,675662-675670,675672-675716,675718-675726,675728-675733,675735-675775,675777-675782,675784,675786-675791,675794-675852,675854-676200,676202,676204,676206-676220,676222-676309,676311-676456,676458-676994,676996-677027,677030-677040,677042-677056,677058-677375,677377-677968,677970-677971,677973,677975-677994,677996-678286,678288-678538,678540-680393,680395-680469,680471-680529,680531-680852,680854-681529,681531-681571,681573-682224,682226,682228,682231-682281,682283-682335,682337-682507,682509,682512-682517,682519-682532,682534-682619,682622-682777,682779-682998,683000-683019,683021-683022,683024-683080,683082-683092,683094-683095,683097-683127,683129-683131,683133-683166,683168-683698,683700-683705,683707-683757,683759-683787,683789-683870,683872-683879,683881-683900,683902-684066,684068-684074,684076-684222,684224-684254,684257-684281,684283-684286,684288-684292,684294-684298,684300-684301,684303-684308,684310-684317,684320,684323-684335,684337-684348,684350-684354,684356-684361,684363-684369,684371-684453,684455-684883,684885-684937,684940-684958,684960-684970,684972-684985,684987-685082 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk
........
r685054 | yegor | 2008-08-12 07:55:10 +0100 (Tue, 12 Aug 2008) | 1 line
Fix bug #45590: Header/footer extraction for .ppt files saved in Office 2007
........
r685064 | yegor | 2008-08-12 08:15:26 +0100 (Tue, 12 Aug 2008) | 1 line
Properly update the array of Slide's text runs in HSLF when new text shapes are added
........
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@685090 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/scratchpad')
13 files changed, 616 insertions, 94 deletions
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java b/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java index 90aee3421d..38b0dff9e2 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java @@ -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;
+ }
+
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java index 17c1d1c23f..501cf65bdf 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java @@ -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; - } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java index 6eb84ca2e7..c4d542aa05 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java @@ -362,4 +362,92 @@ public abstract class Sheet { public void draw(Graphics2D graphics){ } + + /** + * Subclasses should call this method and update the array of text runs + * when a text shape is added + * + * @param shape + */ + protected void onAddTextShape(TextShape shape) { + + } + + /** + * 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; + + } + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java index 48f2fdefcc..8acbca5ac9 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java @@ -440,14 +440,36 @@ 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); + } + } + + protected void onAddTextShape(TextShape shape) { + TextRun run = shape.getTextRun(); + + if(_runs == null) _runs = new TextRun[]{run}; + else { + TextRun[] tmp = new TextRun[_runs.length + 1]; + System.arraycopy(_runs, 0, tmp, 0, _runs.length); + tmp[tmp.length-1] = run; + _runs = tmp; + } } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java b/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java index b48edfc1a1..b30a46e38a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/SlideMaster.java @@ -129,33 +129,15 @@ public class SlideMaster extends MasterSheet { } } - /** - * Checks if the shape is a placeholder. - * (placeholders aren't normal shapes, they are visible only in the Edit Master mode) - * - * - * @return true if the shape is a placeholder - */ - public static boolean isPlaceholder(Shape shape){ - if(!(shape instanceof TextShape)) return false; - - TextShape tx = (TextShape)shape; - TextRun run = tx.getTextRun(); - if(run == null) return false; - - Record[] records = run._records; - for (int i = 0; i < records.length; i++) { - int type = (int)records[i].getRecordType(); - if (type == RecordTypes.OEPlaceholderAtom.typeID || - type == RecordTypes.SlideNumberMCAtom.typeID || - type == RecordTypes.DateTimeMCAtom.typeID || - type == RecordTypes.GenericDateMCAtom.typeID || - type == RecordTypes.FooterMCAtom.typeID ){ - return true; - - } - + protected void onAddTextShape(TextShape shape) { + TextRun run = shape.getTextRun(); + + if(_runs == null) _runs = new TextRun[]{run}; + else { + TextRun[] tmp = new TextRun[_runs.length + 1]; + System.arraycopy(_runs, 0, tmp, 0, _runs.length); + tmp[tmp.length-1] = run; + _runs = tmp; } - return false; } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java index 44cb2b2412..de78b62656 100755 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java @@ -199,6 +199,10 @@ public abstract class TextShape extends SimpleShape { } if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText(); } + if(_txtrun != null) { + _txtrun.setShapeId(getShapeId()); + sh.onAddTextShape(this); + } } protected EscherTextboxWrapper getEscherTextboxWrapper(){ @@ -269,7 +273,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. diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java index 62a624af9d..9bfae4fccb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java @@ -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; - - public static final byte Object = 20; + /** + * 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 Graph = 21; + /** + * 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 Table = 22; + /** + * 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 ClipArt = 23; + /** + * 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 OrganizationChart = 24; + /** + * 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 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){ diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java index d7a664725e..9c867d5ab0 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java @@ -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; diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java new file mode 100644 index 0000000000..0f49b5bd03 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java @@ -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);
+ }
+}
\ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java index 1b2b9f5eeb..a546d0444c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java @@ -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); + } } + } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt Binary files differnew file mode 100644 index 0000000000..51b2c53b62 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hslf/data/headers_footers_2007.ppt diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java index 8b1cdbe09e..39255d3e8b 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java @@ -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();
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java index 7b75c3676c..6463da4c31 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java @@ -445,4 +445,55 @@ public class TestTextRun extends TestCase { assertEquals("Sdfsdfs\n" + "Sdfsdf\n", rt[1].getText()); } + + /** + * Test creation of TextRun objects. + */ + public void testAddTextRun() throws Exception{ + SlideShow ppt = new SlideShow(); + Slide slide = ppt.createSlide(); + + assertNull(slide.getTextRuns()); + + TextBox shape1 = new TextBox(); + TextRun run1 = shape1.getTextRun(); + assertSame(run1, shape1.createTextRun()); + run1.setText("Text 1"); + slide.addShape(shape1); + + //The array of Slide's text runs must be updated when new text shapes are added. + TextRun[] runs = slide.getTextRuns(); + assertNotNull(runs); + assertSame(run1, runs[0]); + + TextBox shape2 = new TextBox(); + TextRun run2 = shape2.getTextRun(); + assertSame(run2, shape2.createTextRun()); + run2.setText("Text 2"); + slide.addShape(shape2); + + runs = slide.getTextRuns(); + assertEquals(2, runs.length); + + assertSame(run1, runs[0]); + assertSame(run2, runs[1]); + + //as getShapes() + Shape[] sh = slide.getShapes(); + assertEquals(2, sh.length); + assertTrue(sh[0] instanceof TextBox); + TextBox box1 = (TextBox)sh[0]; + assertSame(run1, box1.getTextRun()); + TextBox box2 = (TextBox)sh[1]; + assertSame(run2, box2.getTextRun()); + + //test Table - a complex group of shapes containing text objects + Slide slide2 = ppt.createSlide(); + assertNull(slide2.getTextRuns()); + Table table = new Table(2, 2); + slide2.addShape(table); + runs = slide2.getTextRuns(); + assertNotNull(runs); + assertEquals(4, runs.length); + } } |