#56570 - RecordType has repeat by code type 3009

#58159 - getHeaderText() and getFooterText() duplicate text in sheet.getTextRuns()

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722476 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2015-12-31 22:10:17 +00:00
parent ee6966dae9
commit f317f5e288
53 changed files with 1269 additions and 859 deletions

View File

@ -16,13 +16,10 @@
==================================================================== */
package org.apache.poi.hslf.examples;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.InteractiveInfoAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
@ -30,12 +27,11 @@ import org.apache.poi.hslf.usermodel.HSLFSoundData;
/**
* For each slide iterate over shapes and found associated sound data.
*
* @author Yegor Kozlov
*/
public class SoundFinder {
public static void main(String[] args) throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(new FileInputStream(args[0]));
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream(args[0]);
HSLFSlideShow ppt = new HSLFSlideShow(fis);
HSLFSoundData[] sounds = ppt.getSoundData();
for (HSLFSlide slide : ppt.getSlides()) {
@ -49,6 +45,8 @@ public class SoundFinder {
System.out.println(" " + sounds[soundRef].getSoundType());
}
}
ppt.close();
fis.close();
}
/**
@ -59,19 +57,9 @@ public class SoundFinder {
protected static int getSoundReference(HSLFShape shape){
int soundRef = -1;
//dive into the shape container and search for InteractiveInfoAtom
EscherContainerRecord spContainer = shape.getSpContainer();
for (EscherRecord obj : spContainer.getChildRecords()) {
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
byte[] data = obj.serialize();
for (Record record : Record.findChildRecords(data, 8, data.length - 8)) {
if (record instanceof InteractiveInfo) {
InteractiveInfoAtom info = ((InteractiveInfo)record).getInteractiveInfoAtom();
if (info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
soundRef = info.getSoundRef();
}
}
}
}
InteractiveInfoAtom info = shape.getClientDataRecord(RecordTypes.InteractiveInfo.typeID);
if (info != null && info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
soundRef = info.getSoundRef();
}
return soundRef;
}

View File

@ -23,7 +23,7 @@ import java.awt.Rectangle;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
/**
* How to set slide title

View File

@ -76,7 +76,7 @@ public class EscherClientDataRecord
public String toString()
{
String nl = System.getProperty("line.separator");
String extraData = HexDump.dump(this.remainingData, 0, 0);
String extraData = HexDump.dump(getRemainingData(), 0, 0);
return getClass().getName() + ":" + nl +
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
" Version: 0x" + HexDump.toHex(getVersion()) + nl +
@ -88,7 +88,7 @@ public class EscherClientDataRecord
@Override
public String toXml(String tab) {
String extraData = HexDump.dump(this.remainingData, 0, 0).trim();
String extraData = HexDump.dump(getRemainingData(), 0, 0).trim();
StringBuilder builder = new StringBuilder();
builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()),
HexDump.toHex(getVersion()), HexDump.toHex(getInstance())))

View File

@ -33,7 +33,12 @@ public class DrawMasterSheet extends DrawSheet {
* for instance, slide masters and layouts don't display placeholders
*/
@Override
protected boolean canDraw(Shape<?,?> shape){
return !(shape instanceof SimpleShape) || !((SimpleShape<?,?>)shape).isPlaceholder();
protected boolean canDraw(Shape<?,?> shape) {
if (shape instanceof SimpleShape) {
Placeholder ph = ((SimpleShape<?,?>)shape).getPlaceholder();
return ph == null;
} else {
return true;
}
}
}

View File

@ -0,0 +1,138 @@
/* ====================================================================
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.sl.usermodel;
public enum Placeholder {
/**
* No placeholder shape.
*/
NONE(0,0,0,0,0),
/**
* Title text placeholder shape.
*/
TITLE(13,1,1,1,1),
/**
* Body text placeholder shape.
*/
BODY(14,2,12,6,2),
/**
* Center title text placeholder shape.
*/
CENTERED_TITLE(15,3,3,3,3),
/**
* Sub-title text placeholder shape.
*/
SUBTITLE(16,4,4,4,4),
/**
* Date placeholder shape.
*/
DATETIME(7,7,7,7,5),
/**
* Slide number placeholder shape.
*/
SLIDE_NUMBER(8,8,8,8,6),
/**
* Footer placeholder shape.
*/
FOOTER(9,9,9,9,7),
/**
* Header placeholder shape.
*/
HEADER(10,10,10,10,8),
/**
* Object placeholder shape.
*/
CONTENT(19,19,19,19,9),
/**
* Graph object placeholder shape.
*/
CHART(20,20,20,20,10),
/**
* Table object placeholder shape.
*/
TABLE(21,21,21,21,11),
/**
* Clipart object placeholder shape.
*/
CLIP_ART(22,22,22,22,12),
/**
* Organization chart object placeholder shape.
*/
DGM(23,23,23,23,13),
/**
* Media object placeholder shape.
*/
MEDIA(24,24,24,24,14),
/**
* Slide image placeholder shape.
*/
SLIDE_IMAGE(11,11,11,5,15),
/**
* Picture object placeholder shape.
*/
PICTURE(26,26,26,26,16),
/**
* Vertical object placeholder shape.
*/
VERTICAL_OBJECT(25,25,25,25,-2),
/**
* Vertical title text placeholder shape.
*/
VERTICAL_TEXT_TITLE(17,17,17,17,-2),
/**
* Vertical body text placeholder shape.
*/
VERTICAL_TEXT_BODY(18,18,18,18,-2)
;
public final int nativeSlideId;
public final int nativeSlideMasterId;
public final int nativeNotesId;
public final int nativeNotesMasterId;
public final int ooxmlId;
Placeholder(int nativeSlideId, int nativeSlideMasterId, int nativeNotesId, int nativeNotesMasterId, int ooxmlId) {
this.nativeSlideId = nativeSlideId;
this.nativeSlideMasterId = nativeSlideMasterId;
this.nativeNotesId = nativeNotesId;
this.nativeNotesMasterId = nativeNotesMasterId;
this.ooxmlId = ooxmlId;
}
public static Placeholder lookupNative(int nativeId) {
for (Placeholder ph : values()) {
if (ph.nativeSlideId == nativeId ||
ph.nativeSlideMasterId == nativeId ||
ph.nativeNotesId == nativeId ||
ph.nativeNotesMasterId == nativeId
) {
return ph;
}
}
return null;
}
public static Placeholder lookupOoxml(int ooxmlId) {
for (Placeholder ph : values()) {
if (ph.ooxmlId == ooxmlId) {
return ph;
}
}
return null;
}
}

View File

@ -28,25 +28,6 @@ public interface SimpleShape<
P extends TextParagraph<S,P,?>
> extends Shape<S,P>, IAdjustableShape, PlaceableShape<S,P> {
enum Placeholder {
TITLE,
BODY,
CENTERED_TITLE,
SUBTITLE,
DATETIME,
SLIDE_NUMBER,
FOOTER,
HEADER,
CONTENT,
CHART,
TABLE,
CLIP_ART,
DGM,
MEDIA,
SLIDE_IMAGE,
PICTURE
}
FillStyle getFillStyle();
LineDecoration getLineDecoration();
@ -69,7 +50,20 @@ public interface SimpleShape<
ShapeType getShapeType();
void setShapeType(ShapeType type);
boolean isPlaceholder();
/**
* @return the placeholder or null if none is assigned
* @see #setPlaceholder(Placeholder)
*/
Placeholder getPlaceholder();
/**
* Specifies that the corresponding shape should be represented by the generating application
* as a placeholder. When a shape is considered a placeholder by the generating application
* it can have special properties to alert the user that they may enter content into the shape.
*
* @param placeholder the placeholder or null to remove the reference to the placeholder
*/
void setPlaceholder(Placeholder placeholder);
Shadow<S,P> getShadow();

View File

@ -21,11 +21,13 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.Rectangle2D;
import org.apache.poi.POIXMLException;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.Background;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.FillStyle;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
@ -70,4 +72,10 @@ public class XSLFBackground extends XSLFSimpleShape
protected CTTransform2D getXfrm() {
return CTTransform2D.Factory.newInstance();
}
@Override
public void setPlaceholder(Placeholder placeholder) {
// extending XSLFSimpleShape is a bit unlucky ...
throw new POIXMLException("Can't set a placeholder for a background");
}
}

View File

@ -19,7 +19,9 @@
package org.apache.poi.xslf.usermodel;
import org.apache.poi.POIXMLException;
import org.apache.poi.sl.usermodel.ConnectorShape;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.util.Beta;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
@ -69,4 +71,8 @@ public class XSLFConnectorShape extends XSLFSimpleShape
return null;
}
@Override
public void setPlaceholder(Placeholder placeholder) {
throw new POIXMLException("A connector shape can't be a placeholder.");
}
}

View File

@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.PictureShape;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
@ -118,6 +119,12 @@ public class XSLFPictureShape extends XSLFSimpleShape
}
return _data;
}
@Override
public void setPlaceholder(Placeholder placeholder) {
super.setPlaceholder(placeholder);
}
/**
* For an external linked picture, return the last-seen
@ -168,7 +175,6 @@ public class XSLFPictureShape extends XSLFSimpleShape
return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR());
}
@SuppressWarnings("deprecation")
@Override
void copy(XSLFShape sh){
super.copy(sh);

View File

@ -33,7 +33,7 @@ import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
import org.apache.poi.sl.usermodel.PlaceableShape;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
@ -255,6 +255,14 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
return _ph;
}
public Placeholder getPlaceholder() {
CTPlaceholder ph = getCTPlaceholder();
if (ph == null || !ph.isSetType()) {
return null;
}
return Placeholder.lookupOoxml(ph.getType().intValue());
}
/**
* Specifies that the corresponding shape should be represented by the generating application
* as a placeholder. When a shape is considered a placeholder by the generating application
@ -272,7 +280,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
if (nv.isSetPh()) nv.unsetPh();
_ph = null;
} else {
nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));
nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ooxmlId));
}
}
@ -442,7 +450,6 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) {
@SuppressWarnings("deprecation")
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
Arrays.sort(gs, new Comparator<CTGradientStop>() {

View File

@ -42,8 +42,8 @@ import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawPictureShape;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.Sheet;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.util.Beta;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;

View File

@ -34,6 +34,7 @@ import org.apache.poi.sl.usermodel.LineDecoration;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.SimpleShape;
@ -815,7 +816,6 @@ public abstract class XSLFSimpleShape extends XSLFShape
return ph != null;
}
@SuppressWarnings("deprecation")
public Guide getAdjustValue(String name) {
CTPresetGeometry2D prst = getSpPr().getPrstGeom();
if (prst.isSetAvLst()) {
@ -918,4 +918,9 @@ public abstract class XSLFSimpleShape extends XSLFShape
}
}
}
@Override
public void setPlaceholder(Placeholder placeholder) {
super.setPlaceholder(placeholder);
}
}

View File

@ -27,7 +27,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.Notes;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException;

View File

@ -24,7 +24,7 @@ import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException;

View File

@ -27,7 +27,7 @@ import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;

View File

@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTextShape;
import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Beta;
@ -54,7 +55,6 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
implements TextShape<XSLFShape,XSLFTextParagraph> {
private final List<XSLFTextParagraph> _paragraphs;
@SuppressWarnings("deprecation")
/*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
super(shape, sheet);
@ -497,13 +497,13 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
public void setPlaceholder(Placeholder placeholder) {
super.setPlaceholder(placeholder);
}
public Placeholder getTextType(){
CTPlaceholder ph = getCTPlaceholder();
if (ph == null) return null;
int val = ph.getType().intValue();
return Placeholder.values()[val - 1];
return Placeholder.lookupOoxml(val);
}
@Override

View File

@ -22,7 +22,7 @@ import static org.junit.Assert.assertNull;
import java.io.IOException;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.junit.Test;

View File

@ -28,7 +28,7 @@ import java.io.IOException;
import java.util.List;
import org.apache.poi.sl.draw.geom.TestPresetGeometries;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.util.Units;

View File

@ -21,7 +21,7 @@ import static org.junit.Assert.assertNull;
import java.io.IOException;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;

View File

@ -31,7 +31,7 @@ import java.util.List;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.usermodel.HSLFTextShape;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;

View File

@ -122,7 +122,7 @@ public final class PPTXMLDump {
pos += LittleEndian.INT_SIZE;
//get name of the record by type
String recname = RecordTypes.recordName(type);
String recname = RecordTypes.forTypeID(type).name();
write(out, "<"+recname + " info=\""+info+"\" type=\""+type+"\" size=\""+size+"\" offset=\""+(pos-8)+"\"", padding);
if (hexHeader){
out.write(" header=\"");

View File

@ -79,7 +79,7 @@ public final class SLWTListing {
for(int k=0; k<upTo; k++) {
Record r = children[k];
int typeID = (int)r.getRecordType();
String typeName = RecordTypes.recordName(typeID);
String typeName = RecordTypes.forTypeID(typeID).name();
System.out.println(" - " + typeID + " (" + typeName + ")");
}
}

View File

@ -167,7 +167,7 @@ public void walkTree(int depth, int startPos, int maxLen) throws IOException {
out.println(String.format(Locale.ROOT, fmt, "", pos, type, len));
// See if we know about the type of it
String recordName = RecordTypes.recordName((int)type);
String recordName = RecordTypes.forTypeID((short)type).name();
// Jump over header, and think about going on more
pos += 8;
@ -293,7 +293,7 @@ public void walkTree(int depth, int startPos, int maxLen) throws IOException {
String fmt = ind+"At position %2$d ($2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)";
out.println(String.format(Locale.ROOT, fmt, "", pos, type, atomlen));
String typeName = RecordTypes.recordName((int)type);
String typeName = RecordTypes.forTypeID((short)type).name();
out.println(String.format(Locale.ROOT, ind+"%2$s", "That's an Escher Record: ", typeName));
// Record specific dumps

View File

@ -17,21 +17,17 @@
package org.apache.poi.hslf.model;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherComplexProperty;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.Document;
import org.apache.poi.hslf.record.ExControl;
import org.apache.poi.hslf.record.ExObjList;
import org.apache.poi.hslf.record.OEShapeAtom;
import org.apache.poi.hslf.record.ExObjRefAtom;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.usermodel.HSLFPictureData;
@ -41,7 +37,6 @@ import org.apache.poi.hslf.usermodel.HSLFSheet;
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
/**
@ -92,20 +87,8 @@ public final class ActiveXShape extends HSLFPictureShape {
setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, -1);
EscherClientDataRecord cldata = new EscherClientDataRecord();
cldata.setOptions((short)0xF);
_escherContainer.addChildRecord(cldata); // TODO unit test to prove getChildRecords().add is wrong
OEShapeAtom oe = new OEShapeAtom();
//convert hslf into ddf
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
oe.writeOut(out);
} catch(Exception e){
throw new HSLFException(e);
}
cldata.setRemainingData(out.toByteArray());
HSLFEscherClientDataRecord cldata = getClientData(true);
cldata.addChild(new ExObjRefAtom());
return _escherContainer;
}
@ -116,22 +99,18 @@ public final class ActiveXShape extends HSLFPictureShape {
* @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addMovie(String, int)
* @param idx the index of the movie
*/
public void setActiveXIndex(int idx){
EscherContainerRecord spContainer = getSpContainer();
for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
EscherRecord obj = it.next();
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
EscherClientDataRecord clientRecord = (EscherClientDataRecord)obj;
byte[] recdata = clientRecord.getRemainingData();
LittleEndian.putInt(recdata, 8, idx);
}
public void setActiveXIndex(int idx) {
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
if (oe == null) {
throw new HSLFException("OEShapeAtom for ActiveX doesn't exist");
}
oe.setExObjIdRef(idx);
}
public int getControlIndex(){
int idx = -1;
OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
if(oe != null) idx = oe.getOptions();
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
if(oe != null) idx = oe.getExObjIdRef();
return idx;
}

View File

@ -17,14 +17,24 @@
package org.apache.poi.hslf.model;
import java.io.ByteArrayOutputStream;
import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hslf.record.AnimationInfo;
import org.apache.poi.hslf.record.AnimationInfoAtom;
import org.apache.poi.hslf.record.ExMCIMovie;
import org.apache.poi.hslf.record.ExObjList;
import org.apache.poi.hslf.record.ExObjRefAtom;
import org.apache.poi.hslf.record.ExVideoContainer;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.InteractiveInfoAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.usermodel.HSLFPictureData;
import org.apache.poi.hslf.usermodel.HSLFPictureShape;
import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
import org.apache.poi.sl.usermodel.ShapeContainer;
/**
@ -82,11 +92,7 @@ public final class MovieShape extends HSLFPictureShape {
setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x1000100);
setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x10001);
EscherClientDataRecord cldata = new EscherClientDataRecord();
cldata.setOptions((short)0xF);
_escherContainer.addChildRecord(cldata);
OEShapeAtom oe = new OEShapeAtom();
ExObjRefAtom oe = new ExObjRefAtom();
InteractiveInfo info = new InteractiveInfo();
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
infoAtom.setAction(InteractiveInfoAtom.ACTION_MEDIA);
@ -96,16 +102,10 @@ public final class MovieShape extends HSLFPictureShape {
AnimationInfoAtom anAtom = an.getAnimationInfoAtom();
anAtom.setFlag(AnimationInfoAtom.Automatic, true);
//convert hslf into ddf
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
oe.writeOut(out);
an.writeOut(out);
info.writeOut(out);
} catch(Exception e){
throw new HSLFException(e);
}
cldata.setRemainingData(out.toByteArray());
HSLFEscherClientDataRecord cldata = getClientData(true);
cldata.addChild(oe);
cldata.addChild(an);
cldata.addChild(info);
return _escherContainer;
}
@ -117,8 +117,8 @@ public final class MovieShape extends HSLFPictureShape {
* @param idx the index of the movie
*/
public void setMovieIndex(int idx){
OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
oe.setOptions(idx);
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
oe.setExObjIdRef(idx);
AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
if(an != null) {
@ -135,7 +135,6 @@ public final class MovieShape extends HSLFPictureShape {
AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
if(an != null){
an.getAnimationInfoAtom().setFlag(AnimationInfoAtom.Automatic, flag);
updateClientData();
}
}
@ -150,13 +149,16 @@ public final class MovieShape extends HSLFPictureShape {
/**
* @return UNC or local path to a video file
*/
@SuppressWarnings("resource")
public String getPath(){
OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
int idx = oe.getOptions();
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
int idx = oe.getExObjIdRef();
HSLFSlideShow ppt = getSheet().getSlideShow();
ExObjList lst = (ExObjList)ppt.getDocumentRecord().findFirstOfType(RecordTypes.ExObjList.typeID);
if(lst == null) return null;
if(lst == null) {
return null;
}
Record[] r = lst.getChildRecords();
for (int i = 0; i < r.length; i++) {

View File

@ -17,14 +17,22 @@
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hslf.record.ExObjList;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hslf.record.ExEmbed;
import org.apache.poi.hslf.record.ExObjList;
import org.apache.poi.hslf.record.ExObjRefAtom;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.usermodel.HSLFObjectData;
import org.apache.poi.hslf.usermodel.HSLFPictureData;
import org.apache.poi.hslf.usermodel.HSLFPictureShape;
import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger;
@ -88,26 +96,19 @@ public final class OLEShape extends HSLFPictureShape {
EscherSpRecord spRecord = ecr.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setFlags(spRecord.getFlags()|EscherSpRecord.FLAG_OLESHAPE);
EscherContainerRecord uerCont = ecr.getChildById((short)RecordTypes.EscherClientData);
if (uerCont == null) {
uerCont = new EscherContainerRecord();
ecr.addChildRecord(uerCont);
HSLFEscherClientDataRecord cldata = getClientData(true);
ExObjRefAtom uer = null;
for (Record r : cldata.getHSLFChildRecords()) {
if (r.getRecordType() == RecordTypes.ExObjRefAtom.typeID) {
uer = (ExObjRefAtom)r;
break;
}
}
uerCont.setRecordId((short)RecordTypes.EscherClientData);
uerCont.setVersion((short)0x000F); // yes, we are still a container ...
UnknownEscherRecord uer = uerCont.getChildById((short)RecordTypes.ExObjRefAtom.typeID);
if (uer == null) {
uer = new UnknownEscherRecord();
uerCont.addChildRecord(uer);
uer = new ExObjRefAtom();
cldata.addChild(uer);
}
byte uerData[] = new byte[12];
LittleEndian.putShort( uerData, 0, (short)0 ); // options = 0
LittleEndian.putShort( uerData, 2, (short)RecordTypes.ExObjRefAtom.typeID); // recordId
LittleEndian.putInt( uerData, 4, 4 ); // remaining bytes
LittleEndian.putInt( uerData, 8, objectId ); // the data
uer.fillFields(uerData, 0, null);
uer.setExObjIdRef(objectId);
}
@ -116,6 +117,7 @@ public final class OLEShape extends HSLFPictureShape {
*
* @return the unique identifier for the OLE object
*/
@SuppressWarnings("resource")
public HSLFObjectData getObjectData(){
HSLFSlideShow ppt = getSheet().getSlideShow();
HSLFObjectData[] ole = ppt.getEmbeddedObjects();
@ -153,6 +155,7 @@ public final class OLEShape extends HSLFPictureShape {
* 6. MetaFile( 4033), optional
* </p>
*/
@SuppressWarnings("resource")
public ExEmbed getExEmbed(){
if(_exEmbed == null){
HSLFSlideShow ppt = getSheet().getSlideShow();

View File

@ -0,0 +1,94 @@
/* ====================================================================
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 org.apache.poi.util.LittleEndian;
import java.io.IOException;
import java.io.OutputStream;
/**
* ExObjRefAtom (3009).
* <p>
* An atom record that specifies a reference to an external object.
* </p>
*/
public final class ExObjRefAtom extends RecordAtom {
private byte[] _header;
/**
* A 4-byte unsigned integer that specifies a reference to an external object.
* It MUST be equal to the value of the exObjId field of an ExMediaAtom record
* or the value of the exObjId field of an ExOleObjAtom record.
*/
private int exObjIdRef;
/**
* Create a new instance of <code>ExObjRefAtom</code>
*/
public ExObjRefAtom() {
_header = new byte[8];
LittleEndian.putUShort(_header, 0, 0);
LittleEndian.putUShort(_header, 2, (int)getRecordType());
LittleEndian.putInt(_header, 4, 4);
exObjIdRef = 0;
}
/**
* Build an instance of <code>ExObjRefAtom</code> from on-disk 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 ExObjRefAtom(byte[] source, int start, int len) {
_header = new byte[8];
int offset = start;
System.arraycopy(source,start,_header,0,8);
offset += _header.length;
exObjIdRef = (int)LittleEndian.getUInt(source, offset);
}
/**
* @return type of this record {@link RecordTypes#ExObjRefAtom}.
*/
public long getRecordType() {
return RecordTypes.ExObjRefAtom.typeID;
}
public int getExObjIdRef(){
return exObjIdRef;
}
public void setExObjIdRef(int id){
exObjIdRef = id;
}
/**
* Write the contents of the record back, so it can be written
* to disk
*/
public void writeOut(OutputStream out) throws IOException {
out.write(_header);
byte[] recdata = new byte[4];
LittleEndian.putUInt(recdata, 0, exObjIdRef);
out.write(recdata);
}
}

View File

@ -0,0 +1,120 @@
/* ====================================================================
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.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherRecordFactory;
import org.apache.poi.ddf.EscherSerializationListener;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.util.LittleEndian;
/**
* An atom record that specifies whether a shape is a placeholder shape.
* The number, position, and type of placeholder shapes are determined by
* the slide layout as specified in the SlideAtom record.
*
* @since POI 3.14-Beta2
*/
public class HSLFEscherClientDataRecord extends EscherClientDataRecord {
private final List<Record> _childRecords = new ArrayList<Record>();
public List<? extends Record> getHSLFChildRecords() {
return _childRecords;
}
public void removeChild(Class<? extends Record> childClass) {
Iterator<Record> iter = _childRecords.iterator();
while (iter.hasNext()) {
if (childClass.isInstance(iter.next())) {
iter.remove();
}
}
}
public void addChild(Record childRecord) {
_childRecords.add(childRecord);
}
@Override
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
int bytesRemaining = readHeader( data, offset );
byte remainingData[] = new byte[bytesRemaining];
System.arraycopy(data, offset+8, remainingData, 0, bytesRemaining);
setRemainingData(remainingData);
return bytesRemaining + 8;
}
@Override
public int serialize(int offset, byte[] data, EscherSerializationListener listener) {
listener.beforeRecordSerialize( offset, getRecordId(), this );
LittleEndian.putShort(data, offset, getOptions());
LittleEndian.putShort(data, offset+2, getRecordId());
byte childBytes[] = getRemainingData();
LittleEndian.putInt(data, offset+4, childBytes.length);
System.arraycopy(childBytes, 0, data, offset+8, childBytes.length);
int recordSize = 8+childBytes.length;
listener.afterRecordSerialize( offset+recordSize, getRecordId(), recordSize, this );
return recordSize;
}
@Override
public int getRecordSize() {
return 8 + getRemainingData().length;
}
@Override
public byte[] getRemainingData() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
for (Record r : _childRecords) {
r.writeOut(bos);
}
} catch (IOException e) {
throw new HSLFException(e);
}
return bos.toByteArray();
}
@Override
public void setRemainingData( byte[] remainingData ) {
_childRecords.clear();
int offset = 0;
while (offset < remainingData.length) {
Record r = Record.buildRecordAtOffset(remainingData, offset);
_childRecords.add(r);
long rlen = LittleEndian.getUInt(remainingData,offset+4);
offset += 8 + rlen;
}
}
public String getRecordName() {
return "HSLFClientData";
}
}

View File

@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndian;
* @see EscherRecordFactory
*/
public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory {
private static Class<?>[] escherRecordClasses = { EscherPlaceholder.class };
private static Class<?>[] escherRecordClasses = { EscherPlaceholder.class, HSLFEscherClientDataRecord.class };
private static Map<Short, Constructor<? extends EscherRecord>> recordsMap = recordsToMap( escherRecordClasses );
@ -65,6 +65,10 @@ public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory {
}
escherRecord.setRecordId(recordId);
escherRecord.setOptions(options);
if (escherRecord instanceof EscherContainerRecord) {
((EscherContainerRecord)escherRecord).fillFields(data, offset, this);
}
return escherRecord;
}
}

View File

@ -201,6 +201,7 @@ public final class OEPlaceholderAtom extends RecordAtom{
private int placementId;
private int placeholderId;
private int placeholderSize;
private short unusedShort = 0;
/**
@ -227,8 +228,9 @@ public final class OEPlaceholderAtom extends RecordAtom{
offset += _header.length;
placementId = LittleEndian.getInt(source, offset); offset += 4;
placeholderId = LittleEndian.getUnsignedByte(source, offset); offset++;
placeholderSize = LittleEndian.getUnsignedByte(source, offset); offset++;
placeholderId = LittleEndian.getUByte(source, offset); offset++;
placeholderSize = LittleEndian.getUByte(source, offset); offset++;
unusedShort = LittleEndian.getShort(source, offset);
}
/**
@ -322,6 +324,7 @@ public final class OEPlaceholderAtom extends RecordAtom{
LittleEndian.putInt(recdata, 0, placementId);
recdata[4] = (byte)placeholderId;
recdata[5] = (byte)placeholderSize;
LittleEndian.putShort(recdata, 6, unusedShort);
out.write(recdata);
}

View File

@ -1,107 +0,0 @@
/* ====================================================================
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 org.apache.poi.util.LittleEndian;
/**
* Atom that contains information that describes shape client data.
*
* @author Yegor Kozlov
*/
public final class OEShapeAtom extends RecordAtom
{
/**
* Record header.
*/
private byte[] _header;
/**
* record data
*/
private byte[] _recdata;
/**
* Constructs a brand new link related atom record.
*/
public OEShapeAtom() {
_recdata = new byte[4];
_header = new byte[8];
LittleEndian.putShort(_header, 2, (short)getRecordType());
LittleEndian.putInt(_header, 4, _recdata.length);
}
/**
* Constructs the link related 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 OEShapeAtom(byte[] source, int start, int len) {
// Get the header
_header = new byte[8];
System.arraycopy(source,start,_header,0,8);
// Grab the record data
_recdata = new byte[len-8];
System.arraycopy(source,start+8,_recdata,0,len-8);
}
/**
* Gets the record type.
* @return the record type.
*/
public long getRecordType() { return RecordTypes.OEShapeAtom.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(_recdata);
}
/**
* shape flags.
*
* @return shape flags.
*/
public int getOptions(){
return LittleEndian.getInt(_recdata, 0);
}
/**
* shape flags.
*
* @param id shape flags.
*/
public void setOptions(int id){
LittleEndian.putInt(_recdata, 0, id);
}
}

View File

@ -20,7 +20,6 @@ package org.apache.poi.hslf.record;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -36,7 +35,6 @@ import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherSpgrRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.ddf.UnknownEscherRecord;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger;
@ -57,7 +55,7 @@ public final class PPDrawing extends RecordAtom {
private byte[] _header;
private long _type;
private EscherRecord[] childRecords;
private final List<EscherRecord> childRecords = new ArrayList<EscherRecord>();
private EscherTextboxWrapper[] textboxWrappers;
//cached EscherDgRecord
@ -66,7 +64,7 @@ public final class PPDrawing extends RecordAtom {
/**
* Get access to the underlying Escher Records
*/
public EscherRecord[] getEscherRecords() { return childRecords; }
public List<EscherRecord> getEscherRecords() { return childRecords; }
/**
* Get access to the atoms inside Textboxes
@ -76,6 +74,20 @@ public final class PPDrawing extends RecordAtom {
/* ******************** record stuff follows ********************** */
/**
* Creates a new, empty, PPDrawing (typically for use with a new Slide
* or Notes)
*/
public PPDrawing() {
_header = new byte[8];
LittleEndian.putUShort(_header, 0, 15);
LittleEndian.putUShort(_header, 2, RecordTypes.PPDrawing.typeID);
LittleEndian.putInt(_header, 4, 0);
textboxWrappers = new EscherTextboxWrapper[]{};
create();
}
/**
* Sets everything up, groks the escher etc
*/
@ -93,12 +105,11 @@ public final class PPDrawing extends RecordAtom {
// Build up a tree of Escher records contained within
final DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();
final List<EscherRecord> escherChildren = new ArrayList<EscherRecord>();
findEscherChildren(erf, contents, 8, len-8, escherChildren);
this.childRecords = escherChildren.toArray(new EscherRecord[escherChildren.size()]);
findEscherChildren(erf, contents, 8, len-8, childRecords);
EscherContainerRecord dgContainer = getDgContainer();
if (1 == this.childRecords.length && (short)RecordTypes.EscherDgContainer == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) {
this.textboxWrappers = findInDgContainer((EscherContainerRecord) this.childRecords[0]);
if (dgContainer != null) {
textboxWrappers = findInDgContainer(dgContainer);
} else {
// Find and EscherTextboxRecord's, and wrap them up
final List<EscherTextboxWrapper> textboxes = new ArrayList<EscherTextboxWrapper>();
@ -108,15 +119,15 @@ public final class PPDrawing extends RecordAtom {
}
private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord dgContainer) {
final List<EscherTextboxWrapper> found = new LinkedList<EscherTextboxWrapper>();
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer);
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer);
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer);
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer);
for (EscherContainerRecord spContainer : spContainers) {
StyleTextProp9Atom nineAtom = findInSpContainer(spContainer);
EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherSp, spContainer);
EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherClientTextbox, spContainer);
EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType(RecordTypes.EscherSp, spContainer);
EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType(RecordTypes.EscherClientTextbox, spContainer);
if (null == clientTextbox) { continue; }
EscherTextboxWrapper w = new EscherTextboxWrapper(clientTextbox);
StyleTextProp9Atom nineAtom = findInSpContainer(spContainer);
w.setStyleTextProp9Atom(nineAtom);
if (null != sp) {
w.setShapeId(sp.getShapeId());
@ -127,16 +138,26 @@ public final class PPDrawing extends RecordAtom {
}
private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) {
EscherContainerRecord clientData = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherClientData, spContainer);
if (null == clientData) { return null; }
final EscherContainerRecord progTagsContainer = findFirstEscherContainerRecordOfType((short)0x1388, clientData);
if (null == progTagsContainer) { return null; }
final EscherContainerRecord progBinaryTag = findFirstEscherContainerRecordOfType((short)0x138A, progTagsContainer);
if (null == progBinaryTag) { return null; }
int size = progBinaryTag.getChildRecords().size();
HSLFEscherClientDataRecord cldata = spContainer.getChildById(RecordTypes.EscherClientData.typeID);
if (cldata == null) {
return null;
}
DummyPositionSensitiveRecordWithChildren progTags =
getChildRecord(cldata.getHSLFChildRecords(), RecordTypes.ProgTags);
if (progTags == null) {
return null;
}
DummyPositionSensitiveRecordWithChildren progBinaryTag =
(DummyPositionSensitiveRecordWithChildren)progTags.findFirstOfType(RecordTypes.ProgBinaryTag.typeID);
if (progBinaryTag == null) {
return null;
}
int size = progBinaryTag.getChildRecords().length;
if (2 != size) { return null; }
final Record r0 = buildFromUnknownEscherRecord((UnknownEscherRecord) progBinaryTag.getChild(0));
final Record r1 = buildFromUnknownEscherRecord((UnknownEscherRecord) progBinaryTag.getChild(1));
final Record r0 = progBinaryTag.getChildRecords()[0];
final Record r1 = progBinaryTag.getChildRecords()[1];
if (!(r0 instanceof CString)) { return null; }
if (!("___PPT9".equals(((CString) r0).getText()))) { return null; };
if (!(r1 instanceof BinaryTagDataBlob )) { return null; }
@ -144,19 +165,6 @@ public final class PPDrawing extends RecordAtom {
if (1 != blob.getChildRecords().length) { return null; }
return (StyleTextProp9Atom) blob.findFirstOfType(RecordTypes.StyleTextProp9Atom.typeID);
}
/**
* Creates a new, empty, PPDrawing (typically for use with a new Slide
* or Notes)
*/
public PPDrawing(){
_header = new byte[8];
LittleEndian.putUShort(_header, 0, 15);
LittleEndian.putUShort(_header, 2, RecordTypes.PPDrawing.typeID);
LittleEndian.putInt(_header, 4, 0);
textboxWrappers = new EscherTextboxWrapper[]{};
create();
}
/**
* Tree walking way of finding Escher Child Records
@ -198,27 +206,22 @@ public final class PPDrawing extends RecordAtom {
/**
* Look for EscherTextboxRecords
*/
private void findEscherTextboxRecord(EscherRecord[] toSearch, List<EscherTextboxWrapper> found) {
for(int i=0; i<toSearch.length; i++) {
if(toSearch[i] instanceof EscherTextboxRecord) {
EscherTextboxRecord tbr = (EscherTextboxRecord)toSearch[i];
private void findEscherTextboxRecord(List<EscherRecord> toSearch, List<EscherTextboxWrapper> found) {
EscherSpRecord sp = null;
for (EscherRecord r : toSearch) {
if (r instanceof EscherSpRecord) {
sp = (EscherSpRecord)r;
} else if (r instanceof EscherTextboxRecord) {
EscherTextboxRecord tbr = (EscherTextboxRecord)r;
EscherTextboxWrapper w = new EscherTextboxWrapper(tbr);
if (sp != null) {
w.setShapeId(sp.getShapeId());
}
found.add(w);
for (int j = i; j >= 0; j--) {
if(toSearch[j] instanceof EscherSpRecord){
EscherSpRecord sp = (EscherSpRecord)toSearch[j];
w.setShapeId(sp.getShapeId());
break;
}
}
} else {
} else if (r.isContainerRecord()) {
// If it has children, walk them
if(toSearch[i].isContainerRecord()) {
List<EscherRecord> childrenL = toSearch[i].getChildRecords();
EscherRecord[] children = new EscherRecord[childrenL.size()];
childrenL.toArray(children);
findEscherTextboxRecord(children,found);
}
List<EscherRecord> children = r.getChildRecords();
findEscherTextboxRecord(children,found);
}
}
}
@ -259,9 +262,8 @@ public final class PPDrawing extends RecordAtom {
// Now grab the children's data
byte[] b = new byte[newSize];
int done = 0;
for(int i=0; i<childRecords.length; i++) {
int written = childRecords[i].serialize( done, b );
done += written;
for(EscherRecord r : childRecords) {
done += r.serialize( done, b );
}
// Finally, write out the children
@ -276,7 +278,7 @@ public final class PPDrawing extends RecordAtom {
dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
dgContainer.setOptions((short)15);
EscherDgRecord dg = new EscherDgRecord();
dg = new EscherDgRecord();
dg.setOptions((short)16);
dg.setNumShapes(1);
dgContainer.addChildRecord(dg);
@ -321,10 +323,8 @@ public final class PPDrawing extends RecordAtom {
spContainer.addChildRecord(opt);
dgContainer.addChildRecord(spContainer);
childRecords = new EscherRecord[]{
dgContainer
};
childRecords.add(dgContainer);
}
/**
@ -338,6 +338,22 @@ public final class PPDrawing extends RecordAtom {
textboxWrappers = tw;
}
/**
* @return the container record for drawings
* @since POI 3.14-Beta2
*/
public EscherContainerRecord getDgContainer() {
if (childRecords.isEmpty()) {
return null;
}
EscherRecord r = childRecords.get(0);
if (r instanceof EscherContainerRecord && r.getRecordId() == RecordTypes.EscherDgContainer.typeID) {
return (EscherContainerRecord)r;
} else {
return null;
}
}
/**
* Return EscherDgRecord which keeps track of the number of shapes and shapeId in this drawing group
*
@ -345,9 +361,7 @@ public final class PPDrawing extends RecordAtom {
*/
public EscherDgRecord getEscherDgRecord(){
if(dg == null){
EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
for(Iterator<EscherRecord> it = dgContainer.getChildIterator(); it.hasNext();){
EscherRecord r = it.next();
for(EscherRecord r : getDgContainer().getChildRecords()){
if(r instanceof EscherDgRecord){
dg = (EscherDgRecord)r;
break;
@ -357,59 +371,59 @@ public final class PPDrawing extends RecordAtom {
return dg;
}
protected EscherContainerRecord findFirstEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
protected EscherContainerRecord findFirstEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) {
if (null == parent) { return null; }
final List<EscherContainerRecord> children = parent.getChildContainers();
for (EscherContainerRecord child : children) {
if (type == child.getRecordId()) {
if (type.typeID == child.getRecordId()) {
return child;
}
}
return null;
}
protected EscherRecord findFirstEscherRecordOfType(short type, EscherContainerRecord parent) {
protected EscherRecord findFirstEscherRecordOfType(RecordTypes type, EscherContainerRecord parent) {
if (null == parent) { return null; }
final List<EscherRecord> children = parent.getChildRecords();
for (EscherRecord child : children) {
if (type == child.getRecordId()) {
if (type.typeID == child.getRecordId()) {
return child;
}
}
return null;
}
protected EscherContainerRecord[] findAllEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
protected EscherContainerRecord[] findAllEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) {
if (null == parent) { return new EscherContainerRecord[0]; }
final List<EscherContainerRecord> children = parent.getChildContainers();
final List<EscherContainerRecord> result = new LinkedList<EscherContainerRecord>();
for (EscherContainerRecord child : children) {
if (type == child.getRecordId()) {
if (type.typeID == child.getRecordId()) {
result.add(child);
}
}
return result.toArray(new EscherContainerRecord[result.size()]);
}
protected Record buildFromUnknownEscherRecord(UnknownEscherRecord unknown) {
byte[] bingo = unknown.getData();
byte[] restoredRecord = new byte[8 + bingo.length];
System.arraycopy(bingo, 0, restoredRecord, 8, bingo.length);
short recordVersion = unknown.getVersion();
short recordId = unknown.getRecordId();
int recordLength = unknown.getRecordSize();
LittleEndian.putShort(restoredRecord, 0, recordVersion);
LittleEndian.putShort(restoredRecord, 2, recordId);
LittleEndian.putInt(restoredRecord, 4, recordLength);
return Record.createRecordForType(recordId, restoredRecord, 0, restoredRecord.length);
}
public StyleTextProp9Atom[] getNumberedListInfo() {
final List<StyleTextProp9Atom> result = new LinkedList<StyleTextProp9Atom>();
EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer);
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer);
EscherContainerRecord dgContainer = getDgContainer();
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer);
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer);
for (EscherContainerRecord spContainer : spContainers) {
StyleTextProp9Atom prop9 = findInSpContainer(spContainer);
if (prop9 != null) result.add(prop9);
if (prop9 != null) {
result.add(prop9);
}
}
return result.toArray(new StyleTextProp9Atom[result.size()]);
}
@SuppressWarnings("unchecked")
private static <T extends Record> T getChildRecord(List<? extends Record> children, RecordTypes type) {
for (Record r : children) {
if (r.getRecordType() == type.typeID) {
return (T)r;
}
}
return null;
}
}

View File

@ -166,19 +166,19 @@ public abstract class Record
// Any special record handling occurs once we have the class
Class<? extends Record> c = null;
try {
c = RecordTypes.recordHandlingClass((int)type);
c = RecordTypes.forTypeID((short)type).handlingClass;
if(c == null) {
// How odd. RecordTypes normally subsitutes in
// a default handler class if it has heard of the record
// type but there's no support for it. Explicitly request
// that now
c = RecordTypes.recordHandlingClass( RecordTypes.Unknown.typeID );
c = RecordTypes.UnknownRecordPlaceholder.handlingClass;
}
// Grab the right constructor
java.lang.reflect.Constructor<? extends Record> con = c.getDeclaredConstructor(new Class[] { byte[].class, Integer.TYPE, Integer.TYPE });
// Instantiate
toReturn = con.newInstance(new Object[] { b, Integer.valueOf(start), Integer.valueOf(len) });
toReturn = con.newInstance(new Object[] { b, start, len });
} catch(InstantiationException ie) {
throw new RuntimeException("Couldn't instantiate the class for type with id " + type + " on class " + c + " : " + ie, ie);
} catch(java.lang.reflect.InvocationTargetException ite) {

View File

@ -17,8 +17,8 @@
package org.apache.poi.hslf.record;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* List of all known record types in a PowerPoint document, and the
@ -26,191 +26,209 @@ import java.util.HashMap;
* There are two categories of records:
* <li> PowerPoint records: 0 <= info <= 10002 (will carry class info)
* <li> Escher records: info >= 0xF000 (handled by DDF, so no class info)
*
* @author Yegor Kozlov
* @author Nick Burch
*/
public final class RecordTypes {
public static final HashMap<Integer,String> typeToName;
public static final HashMap<Integer,Class<? extends Record>> typeToClass;
public static final Type Unknown = new Type(0,null);
public static final Type Document = new Type(1000,Document.class);
public static final Type DocumentAtom = new Type(1001,DocumentAtom.class);
public static final Type EndDocument = new Type(1002,null);
public static final Type Slide = new Type(1006,Slide.class);
public static final Type SlideAtom = new Type(1007,SlideAtom.class);
public static final Type Notes = new Type(1008,Notes.class);
public static final Type NotesAtom = new Type(1009,NotesAtom.class);
public static final Type Environment = new Type(1010,Environment.class);
public static final Type SlidePersistAtom = new Type(1011,SlidePersistAtom.class);
public static final Type SSlideLayoutAtom = new Type(1015,null);
public static final Type MainMaster = new Type(1016,MainMaster.class);
public static final Type SSSlideInfoAtom = new Type(1017,SSSlideInfoAtom.class);
public static final Type SlideViewInfo = new Type(1018,null);
public static final Type GuideAtom = new Type(1019,null);
public static final Type ViewInfo = new Type(1020,null);
public static final Type ViewInfoAtom = new Type(1021,null);
public static final Type SlideViewInfoAtom = new Type(1022,null);
public static final Type VBAInfo = new Type(1023,null);
public static final Type VBAInfoAtom = new Type(1024,null);
public static final Type SSDocInfoAtom = new Type(1025,null);
public static final Type Summary = new Type(1026,null);
public static final Type DocRoutingSlip = new Type(1030,null);
public static final Type OutlineViewInfo = new Type(1031,null);
public static final Type SorterViewInfo = new Type(1032,null);
public static final Type ExObjList = new Type(1033,ExObjList.class);
public static final Type ExObjListAtom = new Type(1034,ExObjListAtom.class);
public static final Type PPDrawingGroup = new Type(1035,PPDrawingGroup.class);
public static final Type PPDrawing = new Type(1036,PPDrawing.class);
public static final Type NamedShows = new Type(1040,null);
public static final Type NamedShow = new Type(1041,null);
public static final Type NamedShowSlides = new Type(1042,null);
public static final Type SheetProperties = new Type(1044,null);
public static final Type RoundTripCustomTableStyles12Atom = new Type(1064,null);
public static final Type List = new Type(2000,null);
public static final Type FontCollection = new Type(2005,FontCollection.class);
public static final Type BookmarkCollection = new Type(2019,null);
public static final Type SoundCollection = new Type(2020,SoundCollection.class);
public static final Type SoundCollAtom = new Type(2021,null);
public static final Type Sound = new Type(2022,Sound.class);
public static final Type SoundData = new Type(2023,SoundData.class);
public static final Type BookmarkSeedAtom = new Type(2025,null);
public static final Type ColorSchemeAtom = new Type(2032,ColorSchemeAtom.class);
public static final Type ExObjRefAtom = new Type(3009,null);
public static final Type OEShapeAtom = new Type(3009,OEShapeAtom.class);
public static final Type OEPlaceholderAtom = new Type(3011,OEPlaceholderAtom.class);
public static final Type GPopublicintAtom = new Type(3024,null);
public static final Type GRatioAtom = new Type(3031,null);
public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class);
public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class);
public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
public static final Type StyleTextPropAtom = new Type(4001, StyleTextPropAtom.class);//0x0fa1 RT_StyleTextPropAtom
public static final Type MasterTextPropAtom = new Type(4002, MasterTextPropAtom.class);
public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
public static final Type TxCFStyleAtom = new Type(4004,null);
public static final Type TxPFStyleAtom = new Type(4005,null);
public static final Type TextRulerAtom = new Type(4006,TextRulerAtom.class);
public static final Type TextBookmarkAtom = new Type(4007,null);
public static final Type TextBytesAtom = new Type(4008,TextBytesAtom.class);
public static final Type TxSIStyleAtom = new Type(4009,null);
public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class);
public static final Type DefaultRulerAtom = new Type(4011,null);
public static final Type StyleTextProp9Atom = new Type(4012, StyleTextProp9Atom.class); //0x0FAC RT_StyleTextProp9Atom
public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class);
public static final Type FontEmbeddedData = new Type(4024,null);
public static final Type CString = new Type(4026,CString.class);
public static final Type MetaFile = new Type(4033,null);
public static final Type ExOleObjAtom = new Type(4035,ExOleObjAtom.class);
public static final Type SrKinsoku = new Type(4040,null);
public static final Type HandOut = new Type(4041,DummyPositionSensitiveRecordWithChildren.class);
public static final Type ExEmbed = new Type(4044,ExEmbed.class);
public static final Type ExEmbedAtom = new Type(4045,ExEmbedAtom.class);
public static final Type ExLink = new Type(4046,null);
public static final Type BookmarkEntityAtom = new Type(4048,null);
public static final Type ExLinkAtom = new Type(4049,null);
public static final Type SrKinsokuAtom = new Type(4050,null);
public static final Type ExHyperlinkAtom = new Type(4051,ExHyperlinkAtom.class);
public static final Type ExHyperlink = new Type(4055,ExHyperlink.class);
public static final Type SlideNumberMCAtom = new Type(4056,null);
public static final Type HeadersFooters = new Type(4057,HeadersFootersContainer.class);
public static final Type HeadersFootersAtom = new Type(4058,HeadersFootersAtom.class);
public static final Type TxInteractiveInfoAtom = new Type(4063,TxInteractiveInfoAtom.class);
public static final Type CharFormatAtom = new Type(4066,null);
public static final Type ParaFormatAtom = new Type(4067,null);
public static final Type RecolorInfoAtom = new Type(4071,null);
public static final Type ExQuickTimeMovie = new Type(4074,null);
public static final Type ExQuickTimeMovieData = new Type(4075,null);
public static final Type ExControl = new Type(4078,ExControl.class);
public static final Type SlideListWithText = new Type(4080,SlideListWithText.class);
public static final Type InteractiveInfo = new Type(4082,InteractiveInfo.class);
public static final Type InteractiveInfoAtom = new Type(4083,InteractiveInfoAtom.class);
public static final Type UserEditAtom = new Type(4085,UserEditAtom.class);
public static final Type CurrentUserAtom = new Type(4086,null);
public static final Type DateTimeMCAtom = new Type(4087,null);
public static final Type GenericDateMCAtom = new Type(4088,null);
public static final Type FooterMCAtom = new Type(4090,null);
public static final Type ExControlAtom = new Type(4091,ExControlAtom.class);
public static final Type ExMediaAtom = new Type(4100,ExMediaAtom.class);
public static final Type ExVideoContainer = new Type(4101,ExVideoContainer.class);
public static final Type ExAviMovie = new Type(4102,ExAviMovie.class);
public static final Type ExMCIMovie = new Type(4103,ExMCIMovie.class);
public static final Type ExMIDIAudio = new Type(4109,null);
public static final Type ExCDAudio = new Type(4110,null);
public static final Type ExWAVAudioEmbedded = new Type(4111,null);
public static final Type ExWAVAudioLink = new Type(4112,null);
public static final Type ExOleObjStg = new Type(4113,ExOleObjStg.class);
public static final Type ExCDAudioAtom = new Type(4114,null);
public static final Type ExWAVAudioEmbeddedAtom = new Type(4115,null);
public static final Type AnimationInfo = new Type(4116,AnimationInfo.class);
public static final Type AnimationInfoAtom = new Type(4081,AnimationInfoAtom.class);
public static final Type RTFDateTimeMCAtom = new Type(4117,null);
public static final Type ProgTags = new Type(5000,DummyPositionSensitiveRecordWithChildren.class);
public static final Type ProgStringTag = new Type(5001,null);
public static final Type ProgBinaryTag = new Type(5002,DummyPositionSensitiveRecordWithChildren.class);
public static final Type BinaryTagData = new Type(5003, BinaryTagDataBlob.class);//0x138b RT_BinaryTagDataBlob
public static final Type PrpublicintOptions = new Type(6000,null);
public static final Type PersistPtrFullBlock = new Type(6001,PersistPtrHolder.class);
public static final Type PersistPtrIncrementalBlock = new Type(6002,PersistPtrHolder.class);
public static final Type GScalingAtom = new Type(10001,null);
public static final Type GRColorAtom = new Type(10002,null);
public enum RecordTypes {
Unknown(0,null),
UnknownRecordPlaceholder(-1, UnknownRecordPlaceholder.class),
Document(1000,Document.class),
DocumentAtom(1001,DocumentAtom.class),
EndDocument(1002,null),
Slide(1006,Slide.class),
SlideAtom(1007,SlideAtom.class),
Notes(1008,Notes.class),
NotesAtom(1009,NotesAtom.class),
Environment(1010,Environment.class),
SlidePersistAtom(1011,SlidePersistAtom.class),
SSlideLayoutAtom(1015,null),
MainMaster(1016,MainMaster.class),
SSSlideInfoAtom(1017,SSSlideInfoAtom.class),
SlideViewInfo(1018,null),
GuideAtom(1019,null),
ViewInfo(1020,null),
ViewInfoAtom(1021,null),
SlideViewInfoAtom(1022,null),
VBAInfo(1023,null),
VBAInfoAtom(1024,null),
SSDocInfoAtom(1025,null),
Summary(1026,null),
DocRoutingSlip(1030,null),
OutlineViewInfo(1031,null),
SorterViewInfo(1032,null),
ExObjList(1033,ExObjList.class),
ExObjListAtom(1034,ExObjListAtom.class),
PPDrawingGroup(1035,PPDrawingGroup.class),
PPDrawing(1036,PPDrawing.class),
NamedShows(1040,null),
NamedShow(1041,null),
NamedShowSlides(1042,null),
SheetProperties(1044,null),
RoundTripCustomTableStyles12Atom(1064,null),
List(2000,null),
FontCollection(2005,FontCollection.class),
BookmarkCollection(2019,null),
SoundCollection(2020,SoundCollection.class),
SoundCollAtom(2021,null),
Sound(2022,Sound.class),
SoundData(2023,SoundData.class),
BookmarkSeedAtom(2025,null),
ColorSchemeAtom(2032,ColorSchemeAtom.class),
ExObjRefAtom(3009,ExObjRefAtom.class),
OEPlaceholderAtom(3011,OEPlaceholderAtom.class),
GPopublicintAtom(3024,null),
GRatioAtom(3031,null),
OutlineTextRefAtom(3998,OutlineTextRefAtom.class),
TextHeaderAtom(3999,TextHeaderAtom.class),
TextCharsAtom(4000,TextCharsAtom.class),
StyleTextPropAtom(4001, StyleTextPropAtom.class),//0x0fa1 RT_StyleTextPropAtom
MasterTextPropAtom(4002, MasterTextPropAtom.class),
TxMasterStyleAtom(4003,TxMasterStyleAtom.class),
TxCFStyleAtom(4004,null),
TxPFStyleAtom(4005,null),
TextRulerAtom(4006,TextRulerAtom.class),
TextBookmarkAtom(4007,null),
TextBytesAtom(4008,TextBytesAtom.class),
TxSIStyleAtom(4009,null),
TextSpecInfoAtom(4010, TextSpecInfoAtom.class),
DefaultRulerAtom(4011,null),
StyleTextProp9Atom(4012, StyleTextProp9Atom.class), //0x0FAC RT_StyleTextProp9Atom
FontEntityAtom(4023,FontEntityAtom.class),
FontEmbeddedData(4024,null),
CString(4026,CString.class),
MetaFile(4033,null),
ExOleObjAtom(4035,ExOleObjAtom.class),
SrKinsoku(4040,null),
HandOut(4041,DummyPositionSensitiveRecordWithChildren.class),
ExEmbed(4044,ExEmbed.class),
ExEmbedAtom(4045,ExEmbedAtom.class),
ExLink(4046,null),
BookmarkEntityAtom(4048,null),
ExLinkAtom(4049,null),
SrKinsokuAtom(4050,null),
ExHyperlinkAtom(4051,ExHyperlinkAtom.class),
ExHyperlink(4055,ExHyperlink.class),
SlideNumberMCAtom(4056,null),
HeadersFooters(4057,HeadersFootersContainer.class),
HeadersFootersAtom(4058,HeadersFootersAtom.class),
TxInteractiveInfoAtom(4063,TxInteractiveInfoAtom.class),
CharFormatAtom(4066,null),
ParaFormatAtom(4067,null),
RecolorInfoAtom(4071,null),
ExQuickTimeMovie(4074,null),
ExQuickTimeMovieData(4075,null),
ExControl(4078,ExControl.class),
SlideListWithText(4080,SlideListWithText.class),
InteractiveInfo(4082,InteractiveInfo.class),
InteractiveInfoAtom(4083,InteractiveInfoAtom.class),
UserEditAtom(4085,UserEditAtom.class),
CurrentUserAtom(4086,null),
DateTimeMCAtom(4087,null),
GenericDateMCAtom(4088,null),
FooterMCAtom(4090,null),
ExControlAtom(4091,ExControlAtom.class),
ExMediaAtom(4100,ExMediaAtom.class),
ExVideoContainer(4101,ExVideoContainer.class),
ExAviMovie(4102,ExAviMovie.class),
ExMCIMovie(4103,ExMCIMovie.class),
ExMIDIAudio(4109,null),
ExCDAudio(4110,null),
ExWAVAudioEmbedded(4111,null),
ExWAVAudioLink(4112,null),
ExOleObjStg(4113,ExOleObjStg.class),
ExCDAudioAtom(4114,null),
ExWAVAudioEmbeddedAtom(4115,null),
AnimationInfo(4116,AnimationInfo.class),
AnimationInfoAtom(4081,AnimationInfoAtom.class),
RTFDateTimeMCAtom(4117,null),
ProgTags(5000,DummyPositionSensitiveRecordWithChildren.class),
ProgStringTag(5001,null),
ProgBinaryTag(5002,DummyPositionSensitiveRecordWithChildren.class),
BinaryTagData(5003, BinaryTagDataBlob.class),//0x138b RT_BinaryTagDataBlob
PrpublicintOptions(6000,null),
PersistPtrFullBlock(6001,PersistPtrHolder.class),
PersistPtrIncrementalBlock(6002,PersistPtrHolder.class),
GScalingAtom(10001,null),
GRColorAtom(10002,null),
// Records ~12000 seem to be related to the Comments used in PPT 2000/XP
// (Comments in PPT97 are normal Escher text boxes)
public static final Type Comment2000 = new Type(12000,Comment2000.class);
public static final Type Comment2000Atom = new Type(12001,Comment2000Atom.class);
public static final Type Comment2000Summary = new Type(12004,null);
public static final Type Comment2000SummaryAtom = new Type(12005,null);
Comment2000(12000,Comment2000.class),
Comment2000Atom(12001,Comment2000Atom.class),
Comment2000Summary(12004,null),
Comment2000SummaryAtom(12005,null),
// Records ~12050 seem to be related to Document Encryption
public static final Type DocumentEncryptionAtom = new Type(12052,DocumentEncryptionAtom.class);
DocumentEncryptionAtom(12052,DocumentEncryptionAtom.class),
OriginalMainMasterId(1052,null),
CompositeMasterId(1052,null),
RoundTripContentMasterInfo12(1054,null),
RoundTripShapeId12(1055,null),
RoundTripHFPlaceholder12(1056,RoundTripHFPlaceholder12.class),
RoundTripContentMasterId(1058,null),
RoundTripOArtTextStyles12(1059,null),
RoundTripShapeCheckSumForCustomLayouts12(1062,null),
RoundTripNotesMasterTextStyles12(1063,null),
RoundTripCustomTableStyles12(1064,null),
// records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher
EscherDggContainer(0xF000,null),
EscherDgg(0xf006,null),
EscherCLSID(0xf016,null),
EscherOPT(0xf00b,null),
EscherBStoreContainer(0xf001,null),
EscherBSE(0xf007,null),
EscherBlip_START(0xf018,null),
EscherBlip_END(0xf117,null),
EscherDgContainer(0xf002,null),
EscherDg(0xf008,null),
EscherRegroupItems(0xf118,null),
EscherColorScheme(0xf120,null),
EscherSpgrContainer(0xf003,null),
EscherSpContainer(0xf004,null),
EscherSpgr(0xf009,null),
EscherSp(0xf00a,null),
EscherTextbox(0xf00c,null),
EscherClientTextbox(0xf00d,null),
EscherAnchor(0xf00e,null),
EscherChildAnchor(0xf00f,null),
EscherClientAnchor(0xf010,null),
EscherClientData(0xf011,null),
EscherSolverContainer(0xf005,null),
EscherConnectorRule(0xf012,null),
EscherAlignRule(0xf013,null),
EscherArcRule(0xf014,null),
EscherClientRule(0xf015,null),
EscherCalloutRule(0xf017,null),
EscherSelection(0xf119,null),
EscherColorMRU(0xf11a,null),
EscherDeletedPspl(0xf11d,null),
EscherSplitMenuColors(0xf11e,null),
EscherOleObject(0xf11f,null),
EscherUserDefined(0xf122,null);
private static final Map<Short,RecordTypes> LOOKUP;
static {
LOOKUP = new HashMap<Short,RecordTypes>();
for(RecordTypes s : values()) {
LOOKUP.put(s.typeID, s);
}
}
public final short typeID;
public final Class<? extends Record> handlingClass;
private RecordTypes(int typeID, Class<? extends Record> handlingClass) {
this.typeID = (short)typeID;
this.handlingClass = handlingClass;
}
public static RecordTypes forTypeID(int typeID) {
RecordTypes rt = LOOKUP.get((short)typeID);
return (rt != null) ? rt : UnknownRecordPlaceholder;
}
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;
public static final int EscherCLSID = 0xf016;
public static final int EscherOPT = 0xf00b;
public static final int EscherBStoreContainer = 0xf001;
public static final int EscherBSE = 0xf007;
public static final int EscherBlip_START = 0xf018;
public static final int EscherBlip_END = 0xf117;
public static final int EscherDgContainer = 0xf002;
public static final int EscherDg = 0xf008;
public static final int EscherRegroupItems = 0xf118;
public static final int EscherColorScheme = 0xf120;
public static final int EscherSpgrContainer = 0xf003;
public static final int EscherSpContainer = 0xf004;
public static final int EscherSpgr = 0xf009;
public static final int EscherSp = 0xf00a;
public static final int EscherTextbox = 0xf00c;
public static final int EscherClientTextbox = 0xf00d;
public static final int EscherAnchor = 0xf00e;
public static final int EscherChildAnchor = 0xf00f;
public static final int EscherClientAnchor = 0xf010;
public static final int EscherClientData = 0xf011;
public static final int EscherSolverContainer = 0xf005;
public static final int EscherConnectorRule = 0xf012;
public static final int EscherAlignRule = 0xf013;
public static final int EscherArcRule = 0xf014;
public static final int EscherClientRule = 0xf015;
public static final int EscherCalloutRule = 0xf017;
public static final int EscherSelection = 0xf119;
public static final int EscherColorMRU = 0xf11a;
public static final int EscherDeletedPspl = 0xf11d;
public static final int EscherSplitMenuColors = 0xf11e;
public static final int EscherOleObject = 0xf11f;
public static final int EscherUserDefined = 0xf122;
/**
* Returns name of the record by its type
@ -218,10 +236,10 @@ public final class RecordTypes {
* @param type section of the record header
* @return name of the record
*/
public static String recordName(int type) {
String name = typeToName.get(Integer.valueOf(type));
return (name == null) ? ("Unknown" + type) : name;
}
// public static String recordName(int type) {
// String name = typeToName.get(Integer.valueOf(type));
// return (name == null) ? ("Unknown" + type) : name;
// }
/**
* Returns the class handling a record by its type.
@ -232,38 +250,38 @@ public final class RecordTypes {
* @param type section of the record header
* @return class to handle the record, or null if an unknown (eg Escher) record
*/
public static Class<? extends Record> recordHandlingClass(int type) {
Class<? extends Record> c = typeToClass.get(Integer.valueOf(type));
return c;
}
static {
typeToName = new HashMap<Integer,String>();
typeToClass = new HashMap<Integer,Class<? extends Record>>();
try {
Field[] f = RecordTypes.class.getFields();
for (int i = 0; i < f.length; i++){
Object val = f[i].get(null);
// Escher record, only store ID -> Name
if (val instanceof Integer) {
typeToName.put((Integer)val, f[i].getName());
}
// PowerPoint record, store ID -> Name and ID -> Class
if (val instanceof Type) {
Type t = (Type)val;
Class<? extends Record> c = t.handlingClass;
Integer id = Integer.valueOf(t.typeID);
if(c == null) { c = UnknownRecordPlaceholder.class; }
typeToName.put(id, f[i].getName());
typeToClass.put(id, c);
}
}
} catch (IllegalAccessException e){
throw new RuntimeException("Failed to initialize records types");
}
}
// public static Class<? extends Record> recordHandlingClass(int type) {
// Class<? extends Record> c = typeToClass.get(Integer.valueOf(type));
// return c;
// }
//
// static {
// typeToName = new HashMap<Integer,String>();
// typeToClass = new HashMap<Integer,Class<? extends Record>>();
// try {
// Field[] f = RecordTypes.class.getFields();
// for (int i = 0; i < f.length; i++){
// Object val = f[i].get(null);
//
// // Escher record, only store ID -> Name
// if (val instanceof Integer) {
// typeToName.put((Integer)val, f[i].getName());
// }
// // PowerPoint record, store ID -> Name and ID -> Class
// if (val instanceof Type) {
// Type t = (Type)val;
// Class<? extends Record> c = t.handlingClass;
// Integer id = Integer.valueOf(t.typeID);
// if(c == null) { c = UnknownRecordPlaceholder.class; }
//
// typeToName.put(id, f[i].getName());
// typeToClass.put(id, c);
// }
// }
// } catch (IllegalAccessException e){
// throw new RuntimeException("Failed to initialize records types");
// }
// }
/**
@ -271,12 +289,12 @@ public final class RecordTypes {
* Contains both the type, and the handling class (if any), and
* offers methods to get either back out.
*/
public static class Type {
public final int typeID;
public final Class<? extends Record> handlingClass;
public Type(int typeID, Class<? extends Record> handlingClass) {
this.typeID = typeID;
this.handlingClass = handlingClass;
}
}
// public static class Type {
// public final int typeID;
// public final Class<? extends Record> handlingClass;
// public Type(int typeID, Class<? extends Record> handlingClass) {
// this.typeID = typeID;
// this.handlingClass = handlingClass;
// }
// }
}

View File

@ -20,6 +20,8 @@ package org.apache.poi.hslf.record;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.util.LittleEndian;
/**
* An atom record that specifies that a shape is a header or footer placeholder shape
*
@ -40,6 +42,17 @@ public final class RoundTripHFPlaceholder12 extends RecordAtom {
*/
private byte _placeholderId;
/**
* Create a new instance of <code>RoundTripHFPlaceholder12</code>
*/
public RoundTripHFPlaceholder12(){
_header = new byte[8];
LittleEndian.putUShort(_header, 0, 0);
LittleEndian.putUShort(_header, 2, (int)getRecordType());
LittleEndian.putInt(_header, 4, 8);
_placeholderId = 0;
}
/**
* Constructs the comment atom record from its source data.
*

View File

@ -171,7 +171,7 @@ public final class TxMasterStyleAtom extends RecordAtom {
/**
* Updates the rawdata from the modified paragraph/character styles
*
* @since 3.14-beta1
* @since POI 3.14-beta1
*/
public void updateStyles() {
int type = getTextType();

View File

@ -17,10 +17,18 @@
package org.apache.poi.hslf.usermodel;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.record.ExHyperlink;
import org.apache.poi.hslf.record.ExObjList;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.InteractiveInfoAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
/**
* Represents a hyperlink in a PowerPoint document
@ -156,6 +164,7 @@ public final class HSLFHyperlink {
* @param paragraphs List of <code>TextParagraph</code> to lookup hyperlinks
* @return found hyperlinks
*/
@SuppressWarnings("resource")
public static List<HSLFHyperlink> find(List<HSLFTextParagraph> paragraphs){
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
if (paragraphs == null || paragraphs.isEmpty()) return lst;
@ -165,10 +174,10 @@ public final class HSLFHyperlink {
HSLFSlideShow ppt = firstPara.getSheet().getSlideShow();
//document-level container which stores info about all links in a presentation
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
if (exobj == null) return lst;
Record[] records = firstPara.getRecords();
find(records, exobj, lst);
if (exobj != null) {
Record[] records = firstPara.getRecords();
find(Arrays.asList(records), exobj, lst);
}
return lst;
}
@ -179,39 +188,38 @@ public final class HSLFHyperlink {
* @param shape <code>Shape</code> to lookup hyperlink in
* @return found hyperlink or <code>null</code>
*/
@SuppressWarnings("resource")
public static HSLFHyperlink find(HSLFShape shape){
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
HSLFSlideShow ppt = shape.getSheet().getSlideShow();
//document-level container which stores info about all links in a presentation
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
if (exobj == null) {
return null;
HSLFEscherClientDataRecord cldata = shape.getClientData(false);
if (exobj != null && cldata != null) {
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
find(cldata.getHSLFChildRecords(), exobj, lst);
return lst.isEmpty() ? null : (HSLFHyperlink)lst.get(0);
}
EscherContainerRecord spContainer = shape.getSpContainer();
for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext(); ) {
EscherRecord obj = it.next();
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID){
byte[] data = obj.serialize();
Record[] records = Record.findChildRecords(data, 8, data.length-8);
find(records, exobj, lst);
}
}
return lst.size() == 1 ? (HSLFHyperlink)lst.get(0) : null;
return null;
}
private static void find(Record[] records, ExObjList exobj, List<HSLFHyperlink> out){
if (records == null) return;
for (int i = 0; i < records.length; i++) {
//see if we have InteractiveInfo in the textrun's records
if(!(records[i] instanceof InteractiveInfo)) continue;
InteractiveInfo hldr = (InteractiveInfo)records[i];
private static void find(List<? extends Record> records, ExObjList exobj, List<HSLFHyperlink> out){
ListIterator<? extends Record> iter = records.listIterator();
while (iter.hasNext()) {
Record r = iter.next();
// see if we have InteractiveInfo in the textrun's records
if (!(r instanceof InteractiveInfo)) {
continue;
}
InteractiveInfo hldr = (InteractiveInfo)r;
InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
int id = info.getHyperlinkID();
ExHyperlink linkRecord = exobj.get(id);
if (linkRecord == null) continue;
if (linkRecord == null) {
continue;
}
HSLFHyperlink link = new HSLFHyperlink();
link.title = linkRecord.getLinkTitle();
@ -219,8 +227,13 @@ public final class HSLFHyperlink {
link.type = info.getAction();
out.add(link);
if (i+1 < records.length && records[i+1] instanceof TxInteractiveInfoAtom){
TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)records[++i];
if (iter.hasNext()) {
r = iter.next();
if (!(r instanceof TxInteractiveInfoAtom)) {
iter.previous();
continue;
}
TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)r;
link.startIndex = txinfo.getStartIndex();
link.endIndex = txinfo.getEndIndex();
}

View File

@ -18,7 +18,7 @@
package org.apache.poi.hslf.usermodel;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.ShapeContainer;
/**

View File

@ -21,6 +21,7 @@ import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherChildAnchorRecord;
@ -33,7 +34,10 @@ import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.sl.usermodel.FillStyle;
import org.apache.poi.sl.usermodel.Shape;
@ -217,19 +221,32 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, int recordId){
return owner.getChildById((short)recordId);
}
/**
* @since POI 3.14-Beta2
*/
public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, RecordTypes recordId){
return getEscherChild(owner, recordId.typeID);
}
public <T extends EscherRecord> T getEscherChild(int recordId){
return _escherContainer.getChildById((short)recordId);
}
/**
* @since POI 3.14-Beta2
*/
public <T extends EscherRecord> T getEscherChild(RecordTypes recordId){
return getEscherChild(recordId.typeID);
}
/**
* Returns escher property by id.
*
* @return escher property or <code>null</code> if not found.
*/
public static <T extends EscherProperty> T getEscherProperty(AbstractEscherOptRecord opt, int propId){
if (opt == null) return null;
return opt.lookup(propId);
return (opt == null) ? null : opt.<T>lookup(propId);
}
/**
@ -443,7 +460,7 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
}
public AbstractEscherOptRecord getEscherOptRecord() {
AbstractEscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID);
AbstractEscherOptRecord opt = getEscherChild(RecordTypes.EscherOPT);
if (opt == null) {
opt = getEscherChild(RecordTypes.EscherUserDefined);
}
@ -485,4 +502,48 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
public boolean isPlaceholder() {
return false;
}
/**
* Find a record in the underlying EscherClientDataRecord
*
* @param recordType type of the record to search
*/
@SuppressWarnings("unchecked")
public <T extends Record> T getClientDataRecord(int recordType) {
List<? extends Record> records = getClientRecords();
if (records != null) for (Record r : records) {
if (r.getRecordType() == recordType){
return (T)r;
}
}
return null;
}
/**
* Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records
*
* @return an array of HSLF records contained in the shape's EscherClientDataRecord or <code>null</code>
*/
protected List<? extends Record> getClientRecords() {
HSLFEscherClientDataRecord clientData = getClientData(false);
return (clientData == null) ? null : clientData.getHSLFChildRecords();
}
/**
* Create a new HSLF-specific EscherClientDataRecord
*
* @param create if true, create the missing record
* @return the client record or null if it was missing and create wasn't activated
*/
protected HSLFEscherClientDataRecord getClientData(boolean create) {
HSLFEscherClientDataRecord clientData = getEscherChild(HSLFEscherClientDataRecord.RECORD_ID);
if (clientData == null && create) {
clientData = new HSLFEscherClientDataRecord();
clientData.setOptions((short)15);
clientData.setRecordId(HSLFEscherClientDataRecord.RECORD_ID);
getSpContainer().addChildBefore(clientData, EscherTextboxRecord.RECORD_ID);
}
return clientData;
}
}

View File

@ -17,12 +17,27 @@
package org.apache.poi.hslf.usermodel;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.model.*;
import org.apache.poi.hslf.record.*;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherPropertyFactory;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.model.MovieShape;
import org.apache.poi.hslf.model.OLEShape;
import org.apache.poi.hslf.record.ExObjRefAtom;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.InteractiveInfoAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.POILogFactory;
@ -50,7 +65,7 @@ public final class HSLFShapeFactory {
public static HSLFGroupShape createShapeGroup(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
boolean isTable = false;
EscherContainerRecord ecr = (EscherContainerRecord)spContainer.getChild(0);
EscherRecord opt = HSLFShape.getEscherChild(ecr, (short)RecordTypes.EscherUserDefined);
EscherRecord opt = HSLFShape.getEscherChild(ecr, RecordTypes.EscherUserDefined);
if (opt != null) {
EscherPropertyFactory f = new EscherPropertyFactory();
@ -120,12 +135,10 @@ public final class HSLFShapeFactory {
}
}
OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
if (oes != null){
return new OLEShape(spContainer, parent);
}
return new HSLFPictureShape(spContainer, parent);
ExObjRefAtom oes = getClientDataRecord(spContainer, RecordTypes.ExObjRefAtom.typeID);
return (oes != null)
? new OLEShape(spContainer, parent)
: new HSLFPictureShape(spContainer, parent);
}
private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
@ -141,15 +154,10 @@ public final class HSLFShapeFactory {
@SuppressWarnings("unchecked")
protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
EscherRecord obj = it.next();
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
byte[] data = obj.serialize();
for (Record r : Record.findChildRecords(data, 8, data.length - 8)) {
if (r.getRecordType() == recordType) {
return (T)r;
}
}
HSLFEscherClientDataRecord cldata = spContainer.getChildById(EscherClientDataRecord.RECORD_ID);
if (cldata != null) for (Record r : cldata.getHSLFChildRecords()) {
if (r.getRecordType() == recordType) {
return (T)r;
}
}
return null;

View File

@ -149,7 +149,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
public List<HSLFShape> getShapes() {
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
EscherContainerRecord dg = ppdrawing.getDgContainer();
EscherContainerRecord spgr = null;
for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
@ -187,7 +187,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
public void addShape(HSLFShape shape) {
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dgContainer = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
EscherContainerRecord dgContainer = ppdrawing.getDgContainer();
EscherContainerRecord spgr = (EscherContainerRecord) HSLFShape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER);
spgr.addChildRecord(shape.getSpContainer());
@ -244,16 +244,8 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
public boolean removeShape(HSLFShape shape) {
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
EscherContainerRecord spgr = null;
for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
EscherRecord rec = it.next();
if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
spgr = (EscherContainerRecord) rec;
break;
}
}
EscherContainerRecord dg = ppdrawing.getDgContainer();
EscherContainerRecord spgr = dg.getChildById(EscherContainerRecord.SPGR_CONTAINER);
if(spgr == null) {
return false;
}
@ -292,7 +284,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
if (_background == null) {
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
EscherContainerRecord dg = ppdrawing.getDgContainer();
EscherContainerRecord spContainer = dg.getChildById(EscherContainerRecord.SP_CONTAINER);
_background = new HSLFBackground(spContainer, null);
_background.setSheet(this);

View File

@ -18,16 +18,40 @@
package org.apache.poi.hslf.usermodel;
import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.util.List;
import org.apache.poi.ddf.*;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.InteractiveInfoAtom;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.draw.geom.*;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.sl.usermodel.LineDecoration.*;
import org.apache.poi.sl.draw.geom.CustomGeometry;
import org.apache.poi.sl.draw.geom.Guide;
import org.apache.poi.sl.draw.geom.PresetGeometries;
import org.apache.poi.sl.usermodel.LineDecoration;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.Shadow;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.SimpleShape;
import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
@ -45,12 +69,6 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
public final static double DEFAULT_LINE_WIDTH = 0.75;
/**
* Records stored in EscherClientDataRecord
*/
protected Record[] _clientRecords;
protected EscherClientDataRecord _clientData;
/**
* Create a SimpleShape object and initialize it from the supplied Record container.
*
@ -82,9 +100,10 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
opt.setRecordId(EscherOptRecord.RECORD_ID);
_escherContainer.addChildRecord(opt);
EscherRecord anchor;
if(isChild) anchor = new EscherChildAnchorRecord();
else {
EscherRecord anchor;
if(isChild) {
anchor = new EscherChildAnchorRecord();
} else {
anchor = new EscherClientAnchorRecord();
//hack. internal variable EscherClientAnchorRecord.shortRecord can be
@ -251,70 +270,11 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
getFill().setForegroundColor(color);
}
/**
* Find a record in the underlying EscherClientDataRecord
*
* @param recordType type of the record to search
*/
@SuppressWarnings("unchecked")
protected <T extends Record> T getClientDataRecord(int recordType) {
Record[] records = getClientRecords();
if(records != null) for (int i = 0; i < records.length; i++) {
if(records[i].getRecordType() == recordType){
return (T)records[i];
}
}
return null;
}
/**
* Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records
*
* @return an array of HSLF records contained in the shape's EscherClientDataRecord or <code>null</code>
*/
protected Record[] getClientRecords() {
if(_clientData == null){
EscherRecord r = getEscherChild(EscherClientDataRecord.RECORD_ID);
//ddf can return EscherContainerRecord with recordId=EscherClientDataRecord.RECORD_ID
//convert in to EscherClientDataRecord on the fly
if(r != null && !(r instanceof EscherClientDataRecord)){
byte[] data = r.serialize();
r = new EscherClientDataRecord();
r.fillFields(data, 0, new HSLFEscherRecordFactory());
}
_clientData = (EscherClientDataRecord)r;
}
if(_clientData != null && _clientRecords == null){
byte[] data = _clientData.getRemainingData();
_clientRecords = Record.findChildRecords(data, 0, data.length);
}
return _clientRecords;
}
protected void updateClientData() {
if(_clientData != null && _clientRecords != null){
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
for (int i = 0; i < _clientRecords.length; i++) {
_clientRecords[i].writeOut(out);
}
} catch(Exception e){
throw new HSLFException(e);
}
_clientData.setRemainingData(out.toByteArray());
}
}
public void setHyperlink(HSLFHyperlink link){
if(link.getId() == -1){
throw new HSLFException("You must call SlideShow.addHyperlink(Hyperlink link) first");
}
EscherClientDataRecord cldata = new EscherClientDataRecord();
cldata.setOptions((short)0xF);
getSpContainer().addChildRecord(cldata); // TODO - junit to prove getChildRecords().add is wrong
InteractiveInfo info = new InteractiveInfo();
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
@ -356,14 +316,8 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
infoAtom.setHyperlinkID(link.getId());
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
info.writeOut(out);
} catch(Exception e){
throw new HSLFException(e);
}
cldata.setRemainingData(out.toByteArray());
HSLFEscherClientDataRecord cldata = getClientData(true);
cldata.addChild(infoAtom);
}
public Guide getAdjustValue(String name) {
@ -560,99 +514,119 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
}
};
}
protected void setPlaceholder(Placeholder placeholder) {
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
@Override
public Placeholder getPlaceholder() {
List<? extends Record> clRecords = getClientRecords();
if (clRecords == null) {
return null;
}
for (Record r : clRecords) {
if (r instanceof OEPlaceholderAtom) {
OEPlaceholderAtom oep = (OEPlaceholderAtom)r;
return Placeholder.lookupNative(oep.getPlaceholderId());
} else if (r instanceof RoundTripHFPlaceholder12) {
RoundTripHFPlaceholder12 rtp = (RoundTripHFPlaceholder12)r;
return Placeholder.lookupNative(rtp.getPlaceholderId());
}
}
return null;
}
@Override
public void setPlaceholder(Placeholder placeholder) {
EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
int flags = spRecord.getFlags();
flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER;
if (placeholder == null) {
flags ^= EscherSpRecord.FLAG_HAVEMASTER;
} else {
flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER;
}
spRecord.setFlags(flags);
EscherClientDataRecord cldata = _escherContainer.getChildById(EscherClientDataRecord.RECORD_ID);
if (cldata == null) {
cldata = new EscherClientDataRecord();
// append placeholder container before EscherTextboxRecord
_escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID);
}
cldata.setOptions((short)15);
AbstractEscherOptRecord opt = getEscherOptRecord();
// Placeholders can't be grouped
setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, (placeholder == null ? -1 : 262144));
HSLFEscherClientDataRecord clientData = getClientData(false);
if (placeholder == null) {
if (clientData != null) {
clientData.removeChild(OEPlaceholderAtom.class);
clientData.removeChild(RoundTripHFPlaceholder12.class);
// remove client data if the placeholder was the only child to be carried
if (clientData.getChildRecords().isEmpty()) {
getSpContainer().removeChildRecord(clientData);
}
}
return;
}
if (clientData == null) {
clientData = getClientData(true);
}
// OEPlaceholderAtom tells powerpoint that this shape is a placeholder
OEPlaceholderAtom oep = new OEPlaceholderAtom();
OEPlaceholderAtom oep = null;
RoundTripHFPlaceholder12 rtp = null;
for (Record r : clientData.getHSLFChildRecords()) {
if (r instanceof OEPlaceholderAtom) {
oep = (OEPlaceholderAtom)r;
break;
}
if (r instanceof RoundTripHFPlaceholder12) {
rtp = (RoundTripHFPlaceholder12)r;
break;
}
}
/**
* Extarct from MSDN:
* Extract from MSDN:
*
* There is a special case when the placeholder does not have a position in the layout.
* This occurs when the user has moved the placeholder from its original position.
* In this case the placeholder ID is -1.
*/
oep.setPlacementId(-1);
boolean isMaster = (getSheet() instanceof HSLFSlideMaster);
boolean isNotes = (getSheet() instanceof HSLFNotes);
byte phId;
HSLFSheet sheet = getSheet();
// TODO: implement/switch NotesMaster
if (sheet instanceof HSLFSlideMaster) {
phId = (byte)placeholder.nativeSlideMasterId;
} else if (sheet instanceof HSLFNotes) {
phId = (byte)placeholder.nativeNotesId;
} else {
phId = (byte)placeholder.nativeSlideId;
}
if (phId == -2) {
throw new HSLFException("Placeholder "+placeholder.name()+" not supported for this sheet type ("+sheet.getClass()+")");
}
switch (placeholder) {
case TITLE:
phId = (isMaster) ? OEPlaceholderAtom.MasterTitle : OEPlaceholderAtom.Title;
break;
case BODY:
phId = (isMaster) ? OEPlaceholderAtom.MasterBody :
((isNotes) ? OEPlaceholderAtom.NotesBody : OEPlaceholderAtom.Body);
break;
case CENTERED_TITLE:
phId = (isMaster) ? OEPlaceholderAtom.MasterCenteredTitle : OEPlaceholderAtom.CenteredTitle;
break;
case SUBTITLE:
phId = (isMaster) ? OEPlaceholderAtom.MasterSubTitle : OEPlaceholderAtom.Subtitle;
break;
case DATETIME:
phId = OEPlaceholderAtom.MasterDate;
break;
case SLIDE_NUMBER:
phId = OEPlaceholderAtom.MasterSlideNumber;
break;
case FOOTER:
phId = OEPlaceholderAtom.MasterFooter;
break;
case HEADER:
phId = OEPlaceholderAtom.MasterHeader;
break;
case DGM:
case CHART:
phId = OEPlaceholderAtom.Graph;
break;
case TABLE:
phId = OEPlaceholderAtom.Table;
break;
case PICTURE:
case CLIP_ART:
phId = OEPlaceholderAtom.ClipArt;
break;
case MEDIA:
phId = OEPlaceholderAtom.MediaClip;
break;
case SLIDE_IMAGE:
phId = (isMaster) ? OEPlaceholderAtom.MasterNotesSlideImage : OEPlaceholderAtom.NotesSlideImage;
case FOOTER:
if (rtp == null) {
rtp = new RoundTripHFPlaceholder12();
rtp.setPlaceholderId(phId);
clientData.addChild(rtp);
}
if (oep != null) {
clientData.removeChild(OEPlaceholderAtom.class);
}
break;
default:
case CONTENT:
phId = OEPlaceholderAtom.Object;
if (rtp != null) {
clientData.removeChild(RoundTripHFPlaceholder12.class);
}
if (oep == null) {
oep = new OEPlaceholderAtom();
oep.setPlaceholderSize((byte)OEPlaceholderAtom.PLACEHOLDER_FULLSIZE);
// TODO: placement id only "SHOULD" be unique ... check other placeholders on sheet for unique id
oep.setPlacementId(-1);
oep.setPlaceholderId(phId);
clientData.addChild(oep);
}
break;
}
oep.setPlaceholderId(phId);
//convert hslf into ddf record
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
oep.writeOut(out);
} catch(Exception e){
throw new HSLFException(e);
}
cldata.setRemainingData(out.toByteArray());
}

View File

@ -42,8 +42,8 @@ import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.Notes;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
import org.apache.poi.sl.usermodel.Slide;
/**
@ -163,7 +163,7 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe
public void onCreate(){
//initialize drawing group id
EscherDggRecord dgg = getSlideShow().getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
EscherContainerRecord dgContainer = (EscherContainerRecord)getSheetContainer().getPPDrawing().getEscherRecords()[0];
EscherContainerRecord dgContainer = getSheetContainer().getPPDrawing().getDgContainer();
EscherDgRecord dg = (EscherDgRecord) HSLFShape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
int dgId = dgg.getMaxDrawingGroupId() + 1;
dg.setOptions((short)(dgId << 4));

View File

@ -1162,8 +1162,8 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
// For position dependent records, hold where they were and now are
// As we go along, update, and hand over, to any Position Dependent
// records we happen across
Map<RecordTypes.Type,PositionDependentRecord> interestingRecords =
new HashMap<RecordTypes.Type,PositionDependentRecord>();
Map<RecordTypes,PositionDependentRecord> interestingRecords =
new HashMap<RecordTypes,PositionDependentRecord>();
try {
_hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords);

View File

@ -474,7 +474,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
* May be null, if not needed.
* @throws IOException
*/
public void updateAndWriteDependantRecords(OutputStream os, Map<RecordTypes.Type,PositionDependentRecord> interestingRecords)
public void updateAndWriteDependantRecords(OutputStream os, Map<RecordTypes,PositionDependentRecord> interestingRecords)
throws IOException {
// For position dependent records, hold where they were and now are
// As we go along, update, and hand over, to any Position Dependent
@ -502,7 +502,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
// Grab interesting records as they come past
// this will only save the very last record of each type
RecordTypes.Type saveme = null;
RecordTypes saveme = null;
int recordType = (int)record.getRecordType();
if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) {
saveme = RecordTypes.PersistPtrIncrementalBlock;

View File

@ -95,14 +95,14 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
AbstractEscherOptRecord opt = new EscherOptRecord();
opt.setRecordId((short)RecordTypes.EscherUserDefined);
opt.setRecordId(RecordTypes.EscherUserDefined.typeID);
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__TABLEPROPERTIES, 1));
EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES), false, null);
p.setSizeOfElements(0x0004);
p.setNumberOfElementsInArray(numRows);
p.setNumberOfElementsInMemory(numRows);
opt.addEscherProperty(p);
spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor);
spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor.typeID);
}
/**

View File

@ -157,7 +157,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
*
* @param paragraphStyle the master style reference
*
* @since 3.14-Beta1
* @since POI 3.14-Beta1
*/
@Internal
/* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {

View File

@ -76,7 +76,7 @@ public final class HSLFTextRun implements TextRun {
*
* @param characterStyle the master style reference
*
* @since 3.14-Beta1
* @since POI 3.14-Beta1
*/
@Internal
/* package */ void setMasterStyleReference(TextPropCollection characterStyle) {

View File

@ -45,6 +45,7 @@ import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTextShape;
import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.VerticalAlignment;
@ -603,14 +604,29 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
}
/**
* Return <code>OEPlaceholderAtom</code>, the atom that describes a placeholder.
* Return {@link OEPlaceholderAtom}, the atom that describes a placeholder.
*
* @return <code>OEPlaceholderAtom</code> or <code>null</code> if not found
* @return {@link OEPlaceholderAtom} or {@code null} if not found
*/
public OEPlaceholderAtom getPlaceholderAtom(){
return getClientDataRecord(OEPlaceholderAtom.typeID);
}
/**
* Return {@link RoundTripHFPlaceholder12}, the atom that describes a header/footer placeholder.
* Compare the {@link RoundTripHFPlaceholder12#getPlaceholderId()} with
* {@link OEPlaceholderAtom#MasterHeader} or {@link OEPlaceholderAtom#MasterFooter}, to find out
* what kind of placeholder this is.
*
* @return {@link RoundTripHFPlaceholder12} or {@code null} if not found
*
* @since POI 3.14-Beta2
*/
public RoundTripHFPlaceholder12 getHFPlaceholderAtom() {
// special case for files saved in Office 2007
return getClientDataRecord(RoundTripHFPlaceholder12.typeID);
}
/**
*
* Assigns a hyperlink to this text shape
@ -644,7 +660,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
if (oep != null) return true;
//special case for files saved in Office 2007
RoundTripHFPlaceholder12 hldr = getClientDataRecord(RoundTripHFPlaceholder12.typeID);
RoundTripHFPlaceholder12 hldr = getHFPlaceholderAtom();
if (hldr != null) return true;
return false;

View File

@ -17,18 +17,22 @@
package org.apache.poi.hslf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import junit.framework.TestCase;
import java.io.IOException;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.junit.Before;
import org.junit.Test;
/**
* Tests that HSLFSlideShow writes the powerpoint bit of data back out
@ -36,7 +40,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
*
* @author Nick Burch (nick at torchbox dot com)
*/
public final class TestReWrite extends TestCase {
public final class TestReWrite {
// HSLFSlideShow primed on the test data
private HSLFSlideShowImpl hssA;
private HSLFSlideShowImpl hssB;
@ -46,7 +50,8 @@ public final class TestReWrite extends TestCase {
private POIFSFileSystem pfsB;
private POIFSFileSystem pfsC;
public void setUp() throws Exception {
@Before
public void setUp() throws Exception {
POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
@ -60,10 +65,12 @@ public final class TestReWrite extends TestCase {
hssC = new HSLFSlideShowImpl(pfsC);
}
@Test
public void testWritesOutTheSame() throws Exception {
assertWritesOutTheSame(hssA, pfsA);
assertWritesOutTheSame(hssB, pfsB);
}
public void assertWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception {
// Write out to a byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@ -85,13 +92,15 @@ public final class TestReWrite extends TestCase {
byte[] _nData = new byte[nProps.getSize()];
pfs.createDocumentInputStream("PowerPoint Document").read(_oData);
npfs.createDocumentInputStream("PowerPoint Document").read(_nData);
for(int i=0; i<_oData.length; i++) {
for(int i=0; i<_oData.length; i++) {
//System.out.println(i + "\t" + Integer.toHexString(i));
assertEquals(_oData[i], _nData[i]);
}
npfs.close();
}
public void testWithMacroStreams() throws Exception {
@Test
public void testWithMacroStreams() throws IOException {
// Check that they're apparently the same
assertSlideShowWritesOutTheSame(hssC, pfsC);
@ -101,28 +110,25 @@ public final class TestReWrite extends TestCase {
// Write out normally, will loose the macro stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
hssC.write(baos);
POIFSFileSystem pfsNew = new POIFSFileSystem(
new ByteArrayInputStream(baos.toByteArray()) );
try {
pfsNew.getRoot().getEntry("Macros");
fail();
} catch(FileNotFoundException e) {
// Good, as expected
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
POIFSFileSystem pfsNew = new POIFSFileSystem(bais);
assertFalse(pfsNew.getRoot().hasEntry("Macros"));
pfsNew.close();
// But if we write out with nodes preserved, will be there
baos = new ByteArrayOutputStream();
baos.reset();
hssC.write(baos, true);
pfsNew = new POIFSFileSystem(
new ByteArrayInputStream(baos.toByteArray()) );
assertNotNull( pfsNew.getRoot().getEntry("Macros") );
bais = new ByteArrayInputStream(baos.toByteArray());
pfsNew = new POIFSFileSystem(bais);
assertTrue( pfsNew.getRoot().hasEntry("Macros") );
pfsNew.close();
}
/**
* Ensure that simply opening a slideshow (usermodel) view of it
* doesn't change things
*/
@Test
public void testSlideShowWritesOutTheSame() throws Exception {
assertSlideShowWritesOutTheSame(hssA, pfsA);
@ -130,9 +136,11 @@ public final class TestReWrite extends TestCase {
// We need to identify and fix that first
//assertSlideShowWritesOutTheSame(hssB, pfsB);
}
public void assertSlideShowWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception {
public void assertSlideShowWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws IOException {
// Create a slideshow covering it
HSLFSlideShow ss = new HSLFSlideShow(hss);
@SuppressWarnings("resource")
HSLFSlideShow ss = new HSLFSlideShow(hss);
ss.getSlides();
ss.getNotes();
@ -161,17 +169,23 @@ public final class TestReWrite extends TestCase {
System.out.println(i + "\t" + Integer.toHexString(i));
assertEquals(_oData[i], _nData[i]);
}
npfs.close();
}
public void test48593() throws Exception {
HSLFSlideShow slideShow = new HSLFSlideShow();
slideShow.createSlide();
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
slideShow.createSlide();
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
slideShow.createSlide();
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
slideShow.createSlide();
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
@Test
public void test48593() throws IOException {
HSLFSlideShow ppt1 = new HSLFSlideShow();
ppt1.createSlide();
HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
ppt2.createSlide();
HSLFSlideShow ppt3 = HSLFTestDataSamples.writeOutAndReadBack(ppt2);
ppt3.createSlide();
HSLFSlideShow ppt4 = HSLFTestDataSamples.writeOutAndReadBack(ppt3);
ppt4.createSlide();
HSLFTestDataSamples.writeOutAndReadBack(ppt4).close();
ppt4.close();
ppt3.close();
ppt2.close();
ppt1.close();
}
}

View File

@ -18,40 +18,44 @@
package org.apache.poi.hslf.record;
import junit.framework.TestCase;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* Tests that RecordTypes returns the right records and classes when asked
*
* @author Nick Burch (nick at torchbox dot com)
*/
public final class TestRecordTypes extends TestCase {
public final class TestRecordTypes {
@Test
public void testPPTNameLookups() {
assertEquals("MainMaster", RecordTypes.recordName(1016));
assertEquals("TextBytesAtom", RecordTypes.recordName(4008));
assertEquals("VBAInfo", RecordTypes.recordName(1023));
assertEquals("MainMaster", RecordTypes.MainMaster.name());
assertEquals("TextBytesAtom", RecordTypes.TextBytesAtom.name());
assertEquals("VBAInfo", RecordTypes.VBAInfo.name());
}
@Test
public void testEscherNameLookups() {
assertEquals("EscherDggContainer", RecordTypes.recordName(0xf000));
assertEquals("EscherClientTextbox", RecordTypes.recordName(0xf00d));
assertEquals("EscherSelection", RecordTypes.recordName(0xf119));
assertEquals("EscherDggContainer", RecordTypes.EscherDggContainer.name());
assertEquals("EscherClientTextbox", RecordTypes.EscherClientTextbox.name());
assertEquals("EscherSelection", RecordTypes.EscherSelection.name());
}
@Test
public void testPPTClassLookups() {
assertEquals(Slide.class, RecordTypes.recordHandlingClass(1006));
assertEquals(TextCharsAtom.class, RecordTypes.recordHandlingClass(4000));
assertEquals(TextBytesAtom.class, RecordTypes.recordHandlingClass(4008));
assertEquals(SlideListWithText.class, RecordTypes.recordHandlingClass(4080));
assertEquals(Slide.class, RecordTypes.Slide.handlingClass);
assertEquals(TextCharsAtom.class, RecordTypes.TextCharsAtom.handlingClass);
assertEquals(TextBytesAtom.class, RecordTypes.TextBytesAtom.handlingClass);
assertEquals(SlideListWithText.class, RecordTypes.SlideListWithText.handlingClass);
// If this record is ever implemented, change to one that isn't!
// This is checking the "unhandled default" stuff works
assertEquals(UnknownRecordPlaceholder.class, RecordTypes.recordHandlingClass(2019));
assertEquals(UnknownRecordPlaceholder.class, RecordTypes.forTypeID(-10).handlingClass);
}
public void testEscherClassLookups() {
@Test
public void testEscherClassLookups() {
// Should all come back with null, as DDF handles them
assertEquals(null, RecordTypes.recordHandlingClass(0xf000));
assertEquals(null, RecordTypes.recordHandlingClass(0xf001));
assertEquals(null, RecordTypes.EscherDggContainer.handlingClass);
assertEquals(null, RecordTypes.EscherBStoreContainer.handlingClass);
}
}

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.awt.Color;
@ -42,7 +43,9 @@ import org.apache.poi.hslf.exceptions.OldPowerPointFormatException;
import org.apache.poi.hslf.extractor.PowerPointExtractor;
import org.apache.poi.hslf.model.HeadersFooters;
import org.apache.poi.hslf.record.Document;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.hslf.record.SlideListWithText;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
import org.apache.poi.hslf.record.TextHeaderAtom;
@ -50,6 +53,7 @@ import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.SlideShowFactory;
@ -777,6 +781,31 @@ public final class TestBugs {
ex.close();
}
@Test
public void bug58159() throws IOException {
File sample = HSLFTestDataSamples.getSampleFile("bug58159_headers-and-footers.ppt");
HSLFSlideShow ppt = (HSLFSlideShow)SlideShowFactory.create(sample);
HeadersFooters hf = ppt.getSlideHeadersFooters();
assertNull(hf.getHeaderText());
assertEquals("Slide footer", hf.getFooterText());
hf = ppt.getNotesHeadersFooters();
assertEquals("Notes header", hf.getHeaderText());
assertEquals("Notes footer", hf.getFooterText());
HSLFSlide sl = ppt.getSlides().get(0);
hf = sl.getHeadersFooters();
assertNull(hf.getHeaderText());
assertEquals("Slide footer", hf.getFooterText());
for (HSLFShape shape : sl.getShapes()) {
if (shape instanceof HSLFTextShape) {
HSLFTextShape ts = (HSLFTextShape)shape;
Placeholder ph = ts.getPlaceholder();
if (Placeholder.FOOTER == ph) {
assertEquals("Slide footer", ts.getText());
}
}
}
ppt.close();
}
private static HSLFSlideShow open(String fileName) throws IOException {
File sample = HSLFTestDataSamples.getSampleFile(fileName);

View File

@ -42,12 +42,11 @@ public final class TestNumberedList {
@Test
public void testNumberedList() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers.ppt"));
assertTrue("No Exceptions while reading file", true);
final List<HSLFSlide> slides = ppt.getSlides();
assertEquals(2, slides.size());
checkSlide0(slides.get(0));
checkSlide1(slides.get(1));
ppt.close();
}
private void checkSlide0(final HSLFSlide s) {