#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:
parent
ee6966dae9
commit
f317f5e288
@ -16,13 +16,10 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.hslf.examples;
|
package org.apache.poi.hslf.examples;
|
||||||
import java.io.FileInputStream;
|
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.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.HSLFShape;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFSlide;
|
import org.apache.poi.hslf.usermodel.HSLFSlide;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
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.
|
* For each slide iterate over shapes and found associated sound data.
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
*/
|
||||||
public class SoundFinder {
|
public class SoundFinder {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws IOException {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow(new FileInputStream(args[0]));
|
FileInputStream fis = new FileInputStream(args[0]);
|
||||||
|
HSLFSlideShow ppt = new HSLFSlideShow(fis);
|
||||||
HSLFSoundData[] sounds = ppt.getSoundData();
|
HSLFSoundData[] sounds = ppt.getSoundData();
|
||||||
|
|
||||||
for (HSLFSlide slide : ppt.getSlides()) {
|
for (HSLFSlide slide : ppt.getSlides()) {
|
||||||
@ -49,6 +45,8 @@ public class SoundFinder {
|
|||||||
System.out.println(" " + sounds[soundRef].getSoundType());
|
System.out.println(" " + sounds[soundRef].getSoundType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ppt.close();
|
||||||
|
fis.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,19 +57,9 @@ public class SoundFinder {
|
|||||||
protected static int getSoundReference(HSLFShape shape){
|
protected static int getSoundReference(HSLFShape shape){
|
||||||
int soundRef = -1;
|
int soundRef = -1;
|
||||||
//dive into the shape container and search for InteractiveInfoAtom
|
//dive into the shape container and search for InteractiveInfoAtom
|
||||||
EscherContainerRecord spContainer = shape.getSpContainer();
|
InteractiveInfoAtom info = shape.getClientDataRecord(RecordTypes.InteractiveInfo.typeID);
|
||||||
for (EscherRecord obj : spContainer.getChildRecords()) {
|
if (info != null && info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
|
||||||
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
|
soundRef = info.getSoundRef();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return soundRef;
|
return soundRef;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import java.awt.Rectangle;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
|
import org.apache.poi.sl.usermodel.Placeholder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How to set slide title
|
* How to set slide title
|
||||||
|
@ -76,7 +76,7 @@ public class EscherClientDataRecord
|
|||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
String nl = System.getProperty("line.separator");
|
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 +
|
return getClass().getName() + ":" + nl +
|
||||||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
||||||
" Version: 0x" + HexDump.toHex(getVersion()) + nl +
|
" Version: 0x" + HexDump.toHex(getVersion()) + nl +
|
||||||
@ -88,7 +88,7 @@ public class EscherClientDataRecord
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toXml(String tab) {
|
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();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()),
|
builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()),
|
||||||
HexDump.toHex(getVersion()), HexDump.toHex(getInstance())))
|
HexDump.toHex(getVersion()), HexDump.toHex(getInstance())))
|
||||||
|
@ -33,7 +33,12 @@ public class DrawMasterSheet extends DrawSheet {
|
|||||||
* for instance, slide masters and layouts don't display placeholders
|
* for instance, slide masters and layouts don't display placeholders
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected boolean canDraw(Shape<?,?> shape){
|
protected boolean canDraw(Shape<?,?> shape) {
|
||||||
return !(shape instanceof SimpleShape) || !((SimpleShape<?,?>)shape).isPlaceholder();
|
if (shape instanceof SimpleShape) {
|
||||||
|
Placeholder ph = ((SimpleShape<?,?>)shape).getPlaceholder();
|
||||||
|
return ph == null;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
138
src/java/org/apache/poi/sl/usermodel/Placeholder.java
Normal file
138
src/java/org/apache/poi/sl/usermodel/Placeholder.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -28,25 +28,6 @@ public interface SimpleShape<
|
|||||||
P extends TextParagraph<S,P,?>
|
P extends TextParagraph<S,P,?>
|
||||||
> extends Shape<S,P>, IAdjustableShape, PlaceableShape<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();
|
FillStyle getFillStyle();
|
||||||
|
|
||||||
LineDecoration getLineDecoration();
|
LineDecoration getLineDecoration();
|
||||||
@ -69,7 +50,20 @@ public interface SimpleShape<
|
|||||||
ShapeType getShapeType();
|
ShapeType getShapeType();
|
||||||
void setShapeType(ShapeType type);
|
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();
|
Shadow<S,P> getShadow();
|
||||||
|
|
||||||
|
@ -21,11 +21,13 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
|
import org.apache.poi.POIXMLException;
|
||||||
import org.apache.poi.sl.draw.DrawPaint;
|
import org.apache.poi.sl.draw.DrawPaint;
|
||||||
import org.apache.poi.sl.usermodel.Background;
|
import org.apache.poi.sl.usermodel.Background;
|
||||||
import org.apache.poi.sl.usermodel.ColorStyle;
|
import org.apache.poi.sl.usermodel.ColorStyle;
|
||||||
import org.apache.poi.sl.usermodel.FillStyle;
|
import org.apache.poi.sl.usermodel.FillStyle;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle;
|
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.PaintStyle.SolidPaint;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
|
||||||
@ -70,4 +72,10 @@ public class XSLFBackground extends XSLFSimpleShape
|
|||||||
protected CTTransform2D getXfrm() {
|
protected CTTransform2D getXfrm() {
|
||||||
return CTTransform2D.Factory.newInstance();
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.POIXMLException;
|
||||||
import org.apache.poi.sl.usermodel.ConnectorShape;
|
import org.apache.poi.sl.usermodel.ConnectorShape;
|
||||||
|
import org.apache.poi.sl.usermodel.Placeholder;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
|
||||||
@ -69,4 +71,8 @@ public class XSLFConnectorShape extends XSLFSimpleShape
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlaceholder(Placeholder placeholder) {
|
||||||
|
throw new POIXMLException("A connector shape can't be a placeholder.");
|
||||||
|
}
|
||||||
}
|
}
|
@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException;
|
|||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
import org.apache.poi.sl.usermodel.PictureShape;
|
import org.apache.poi.sl.usermodel.PictureShape;
|
||||||
|
import org.apache.poi.sl.usermodel.Placeholder;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.apache.xmlbeans.XmlCursor;
|
import org.apache.xmlbeans.XmlCursor;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
@ -118,6 +119,12 @@ public class XSLFPictureShape extends XSLFSimpleShape
|
|||||||
}
|
}
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlaceholder(Placeholder placeholder) {
|
||||||
|
super.setPlaceholder(placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For an external linked picture, return the last-seen
|
* 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());
|
return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
@Override
|
||||||
void copy(XSLFShape sh){
|
void copy(XSLFShape sh){
|
||||||
super.copy(sh);
|
super.copy(sh);
|
||||||
|
@ -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.GradientPaint;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
|
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
|
||||||
import org.apache.poi.sl.usermodel.PlaceableShape;
|
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.sl.usermodel.Shape;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
@ -255,6 +255,14 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
|
|||||||
return _ph;
|
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
|
* 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
|
* 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();
|
if (nv.isSetPh()) nv.unsetPh();
|
||||||
_ph = null;
|
_ph = null;
|
||||||
} else {
|
} 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) {
|
protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) {
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
|
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();
|
||||||
|
|
||||||
Arrays.sort(gs, new Comparator<CTGradientStop>() {
|
Arrays.sort(gs, new Comparator<CTGradientStop>() {
|
||||||
|
@ -42,8 +42,8 @@ import org.apache.poi.sl.draw.DrawFactory;
|
|||||||
import org.apache.poi.sl.draw.DrawPictureShape;
|
import org.apache.poi.sl.draw.DrawPictureShape;
|
||||||
import org.apache.poi.sl.draw.Drawable;
|
import org.apache.poi.sl.draw.Drawable;
|
||||||
import org.apache.poi.sl.usermodel.PictureData;
|
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.Sheet;
|
||||||
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
|
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
|
@ -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.DecorationShape;
|
||||||
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
|
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle;
|
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.PaintStyle.SolidPaint;
|
||||||
import org.apache.poi.sl.usermodel.ShapeType;
|
import org.apache.poi.sl.usermodel.ShapeType;
|
||||||
import org.apache.poi.sl.usermodel.SimpleShape;
|
import org.apache.poi.sl.usermodel.SimpleShape;
|
||||||
@ -815,7 +816,6 @@ public abstract class XSLFSimpleShape extends XSLFShape
|
|||||||
return ph != null;
|
return ph != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public Guide getAdjustValue(String name) {
|
public Guide getAdjustValue(String name) {
|
||||||
CTPresetGeometry2D prst = getSpPr().getPrstGeom();
|
CTPresetGeometry2D prst = getSpPr().getPrstGeom();
|
||||||
if (prst.isSetAvLst()) {
|
if (prst.isSetAvLst()) {
|
||||||
@ -918,4 +918,9 @@ public abstract class XSLFSimpleShape extends XSLFShape
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlaceholder(Placeholder placeholder) {
|
||||||
|
super.setPlaceholder(placeholder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
|
|||||||
import org.apache.poi.sl.draw.DrawFactory;
|
import org.apache.poi.sl.draw.DrawFactory;
|
||||||
import org.apache.poi.sl.draw.Drawable;
|
import org.apache.poi.sl.draw.Drawable;
|
||||||
import org.apache.poi.sl.usermodel.Notes;
|
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.sl.usermodel.Slide;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
@ -24,7 +24,7 @@ import org.apache.poi.POIXMLDocumentPart;
|
|||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
import org.apache.poi.sl.usermodel.MasterSheet;
|
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.Beta;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
@ -27,7 +27,7 @@ import org.apache.poi.POIXMLDocumentPart;
|
|||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
import org.apache.poi.sl.usermodel.MasterSheet;
|
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.Beta;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
|
||||||
|
@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException;
|
|||||||
import org.apache.poi.sl.draw.DrawFactory;
|
import org.apache.poi.sl.draw.DrawFactory;
|
||||||
import org.apache.poi.sl.draw.DrawTextShape;
|
import org.apache.poi.sl.draw.DrawTextShape;
|
||||||
import org.apache.poi.sl.usermodel.Insets2D;
|
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.TextShape;
|
||||||
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
@ -54,7 +55,6 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
|
|||||||
implements TextShape<XSLFShape,XSLFTextParagraph> {
|
implements TextShape<XSLFShape,XSLFTextParagraph> {
|
||||||
private final List<XSLFTextParagraph> _paragraphs;
|
private final List<XSLFTextParagraph> _paragraphs;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
/*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
|
/*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
|
||||||
super(shape, sheet);
|
super(shape, sheet);
|
||||||
|
|
||||||
@ -497,13 +497,13 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
|
|||||||
public void setPlaceholder(Placeholder placeholder) {
|
public void setPlaceholder(Placeholder placeholder) {
|
||||||
super.setPlaceholder(placeholder);
|
super.setPlaceholder(placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Placeholder getTextType(){
|
public Placeholder getTextType(){
|
||||||
CTPlaceholder ph = getCTPlaceholder();
|
CTPlaceholder ph = getCTPlaceholder();
|
||||||
if (ph == null) return null;
|
if (ph == null) return null;
|
||||||
|
|
||||||
int val = ph.getType().intValue();
|
int val = ph.getType().intValue();
|
||||||
return Placeholder.values()[val - 1];
|
return Placeholder.lookupOoxml(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,7 +22,7 @@ import static org.junit.Assert.assertNull;
|
|||||||
|
|
||||||
import java.io.IOException;
|
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.apache.poi.xslf.XSLFTestDataSamples;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import java.io.IOException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.sl.draw.geom.TestPresetGeometries;
|
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.LineCap;
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.poi.util.Units;
|
||||||
|
@ -21,7 +21,7 @@ import static org.junit.Assert.assertNull;
|
|||||||
|
|
||||||
import java.io.IOException;
|
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.junit.Test;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFTextShape;
|
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.SlideShow;
|
||||||
import org.apache.poi.sl.usermodel.SlideShowFactory;
|
import org.apache.poi.sl.usermodel.SlideShowFactory;
|
||||||
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
|
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
|
||||||
|
@ -122,7 +122,7 @@ public final class PPTXMLDump {
|
|||||||
pos += LittleEndian.INT_SIZE;
|
pos += LittleEndian.INT_SIZE;
|
||||||
|
|
||||||
//get name of the record by type
|
//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);
|
write(out, "<"+recname + " info=\""+info+"\" type=\""+type+"\" size=\""+size+"\" offset=\""+(pos-8)+"\"", padding);
|
||||||
if (hexHeader){
|
if (hexHeader){
|
||||||
out.write(" header=\"");
|
out.write(" header=\"");
|
||||||
|
@ -79,7 +79,7 @@ public final class SLWTListing {
|
|||||||
for(int k=0; k<upTo; k++) {
|
for(int k=0; k<upTo; k++) {
|
||||||
Record r = children[k];
|
Record r = children[k];
|
||||||
int typeID = (int)r.getRecordType();
|
int typeID = (int)r.getRecordType();
|
||||||
String typeName = RecordTypes.recordName(typeID);
|
String typeName = RecordTypes.forTypeID(typeID).name();
|
||||||
System.out.println(" - " + typeID + " (" + typeName + ")");
|
System.out.println(" - " + typeID + " (" + typeName + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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));
|
out.println(String.format(Locale.ROOT, fmt, "", pos, type, len));
|
||||||
|
|
||||||
// See if we know about the type of it
|
// 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
|
// Jump over header, and think about going on more
|
||||||
pos += 8;
|
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)";
|
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));
|
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));
|
out.println(String.format(Locale.ROOT, ind+"%2$s", "That's an Escher Record: ", typeName));
|
||||||
|
|
||||||
// Record specific dumps
|
// Record specific dumps
|
||||||
|
@ -17,21 +17,17 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.model;
|
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.AbstractEscherOptRecord;
|
||||||
import org.apache.poi.ddf.EscherClientDataRecord;
|
|
||||||
import org.apache.poi.ddf.EscherComplexProperty;
|
import org.apache.poi.ddf.EscherComplexProperty;
|
||||||
import org.apache.poi.ddf.EscherContainerRecord;
|
import org.apache.poi.ddf.EscherContainerRecord;
|
||||||
import org.apache.poi.ddf.EscherProperties;
|
import org.apache.poi.ddf.EscherProperties;
|
||||||
import org.apache.poi.ddf.EscherRecord;
|
|
||||||
import org.apache.poi.ddf.EscherSpRecord;
|
import org.apache.poi.ddf.EscherSpRecord;
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
import org.apache.poi.hslf.record.Document;
|
import org.apache.poi.hslf.record.Document;
|
||||||
import org.apache.poi.hslf.record.ExControl;
|
import org.apache.poi.hslf.record.ExControl;
|
||||||
import org.apache.poi.hslf.record.ExObjList;
|
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.Record;
|
||||||
import org.apache.poi.hslf.record.RecordTypes;
|
import org.apache.poi.hslf.record.RecordTypes;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFPictureData;
|
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.hslf.usermodel.HSLFTextParagraph;
|
||||||
import org.apache.poi.sl.usermodel.ShapeContainer;
|
import org.apache.poi.sl.usermodel.ShapeContainer;
|
||||||
import org.apache.poi.sl.usermodel.ShapeType;
|
import org.apache.poi.sl.usermodel.ShapeType;
|
||||||
import org.apache.poi.util.LittleEndian;
|
|
||||||
import org.apache.poi.util.StringUtil;
|
import org.apache.poi.util.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,20 +87,8 @@ public final class ActiveXShape extends HSLFPictureShape {
|
|||||||
setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
|
setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
|
||||||
setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, -1);
|
setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, -1);
|
||||||
|
|
||||||
EscherClientDataRecord cldata = new EscherClientDataRecord();
|
HSLFEscherClientDataRecord cldata = getClientData(true);
|
||||||
cldata.setOptions((short)0xF);
|
cldata.addChild(new ExObjRefAtom());
|
||||||
_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());
|
|
||||||
|
|
||||||
return _escherContainer;
|
return _escherContainer;
|
||||||
}
|
}
|
||||||
@ -116,22 +99,18 @@ public final class ActiveXShape extends HSLFPictureShape {
|
|||||||
* @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addMovie(String, int)
|
* @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addMovie(String, int)
|
||||||
* @param idx the index of the movie
|
* @param idx the index of the movie
|
||||||
*/
|
*/
|
||||||
public void setActiveXIndex(int idx){
|
public void setActiveXIndex(int idx) {
|
||||||
EscherContainerRecord spContainer = getSpContainer();
|
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
|
||||||
for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
|
if (oe == null) {
|
||||||
EscherRecord obj = it.next();
|
throw new HSLFException("OEShapeAtom for ActiveX doesn't exist");
|
||||||
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
|
|
||||||
EscherClientDataRecord clientRecord = (EscherClientDataRecord)obj;
|
|
||||||
byte[] recdata = clientRecord.getRemainingData();
|
|
||||||
LittleEndian.putInt(recdata, 8, idx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
oe.setExObjIdRef(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getControlIndex(){
|
public int getControlIndex(){
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
|
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
|
||||||
if(oe != null) idx = oe.getOptions();
|
if(oe != null) idx = oe.getExObjIdRef();
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,14 +17,24 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.model;
|
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.EscherContainerRecord;
|
||||||
import org.apache.poi.ddf.EscherProperties;
|
import org.apache.poi.ddf.EscherProperties;
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.record.AnimationInfo;
|
||||||
import org.apache.poi.hslf.record.*;
|
import org.apache.poi.hslf.record.AnimationInfoAtom;
|
||||||
import org.apache.poi.hslf.usermodel.*;
|
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;
|
import org.apache.poi.sl.usermodel.ShapeContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,11 +92,7 @@ public final class MovieShape extends HSLFPictureShape {
|
|||||||
setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x1000100);
|
setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x1000100);
|
||||||
setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x10001);
|
setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x10001);
|
||||||
|
|
||||||
EscherClientDataRecord cldata = new EscherClientDataRecord();
|
ExObjRefAtom oe = new ExObjRefAtom();
|
||||||
cldata.setOptions((short)0xF);
|
|
||||||
_escherContainer.addChildRecord(cldata);
|
|
||||||
|
|
||||||
OEShapeAtom oe = new OEShapeAtom();
|
|
||||||
InteractiveInfo info = new InteractiveInfo();
|
InteractiveInfo info = new InteractiveInfo();
|
||||||
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
|
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
|
||||||
infoAtom.setAction(InteractiveInfoAtom.ACTION_MEDIA);
|
infoAtom.setAction(InteractiveInfoAtom.ACTION_MEDIA);
|
||||||
@ -96,16 +102,10 @@ public final class MovieShape extends HSLFPictureShape {
|
|||||||
AnimationInfoAtom anAtom = an.getAnimationInfoAtom();
|
AnimationInfoAtom anAtom = an.getAnimationInfoAtom();
|
||||||
anAtom.setFlag(AnimationInfoAtom.Automatic, true);
|
anAtom.setFlag(AnimationInfoAtom.Automatic, true);
|
||||||
|
|
||||||
//convert hslf into ddf
|
HSLFEscherClientDataRecord cldata = getClientData(true);
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
cldata.addChild(oe);
|
||||||
try {
|
cldata.addChild(an);
|
||||||
oe.writeOut(out);
|
cldata.addChild(info);
|
||||||
an.writeOut(out);
|
|
||||||
info.writeOut(out);
|
|
||||||
} catch(Exception e){
|
|
||||||
throw new HSLFException(e);
|
|
||||||
}
|
|
||||||
cldata.setRemainingData(out.toByteArray());
|
|
||||||
|
|
||||||
return _escherContainer;
|
return _escherContainer;
|
||||||
}
|
}
|
||||||
@ -117,8 +117,8 @@ public final class MovieShape extends HSLFPictureShape {
|
|||||||
* @param idx the index of the movie
|
* @param idx the index of the movie
|
||||||
*/
|
*/
|
||||||
public void setMovieIndex(int idx){
|
public void setMovieIndex(int idx){
|
||||||
OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
|
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
|
||||||
oe.setOptions(idx);
|
oe.setExObjIdRef(idx);
|
||||||
|
|
||||||
AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
|
AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
|
||||||
if(an != null) {
|
if(an != null) {
|
||||||
@ -135,7 +135,6 @@ public final class MovieShape extends HSLFPictureShape {
|
|||||||
AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
|
AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
|
||||||
if(an != null){
|
if(an != null){
|
||||||
an.getAnimationInfoAtom().setFlag(AnimationInfoAtom.Automatic, flag);
|
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
|
* @return UNC or local path to a video file
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("resource")
|
||||||
public String getPath(){
|
public String getPath(){
|
||||||
OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
|
ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
|
||||||
int idx = oe.getOptions();
|
int idx = oe.getExObjIdRef();
|
||||||
|
|
||||||
HSLFSlideShow ppt = getSheet().getSlideShow();
|
HSLFSlideShow ppt = getSheet().getSlideShow();
|
||||||
ExObjList lst = (ExObjList)ppt.getDocumentRecord().findFirstOfType(RecordTypes.ExObjList.typeID);
|
ExObjList lst = (ExObjList)ppt.getDocumentRecord().findFirstOfType(RecordTypes.ExObjList.typeID);
|
||||||
if(lst == null) return null;
|
if(lst == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Record[] r = lst.getChildRecords();
|
Record[] r = lst.getChildRecords();
|
||||||
for (int i = 0; i < r.length; i++) {
|
for (int i = 0; i < r.length; i++) {
|
||||||
|
@ -17,14 +17,22 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.model;
|
package org.apache.poi.hslf.model;
|
||||||
|
|
||||||
import org.apache.poi.ddf.*;
|
import org.apache.poi.ddf.EscherContainerRecord;
|
||||||
import org.apache.poi.hslf.usermodel.*;
|
import org.apache.poi.ddf.EscherProperties;
|
||||||
import org.apache.poi.hslf.record.ExObjList;
|
import org.apache.poi.ddf.EscherSpRecord;
|
||||||
import org.apache.poi.hslf.record.Record;
|
|
||||||
import org.apache.poi.hslf.record.ExEmbed;
|
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.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.sl.usermodel.ShapeContainer;
|
||||||
import org.apache.poi.util.LittleEndian;
|
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
|
|
||||||
@ -88,26 +96,19 @@ public final class OLEShape extends HSLFPictureShape {
|
|||||||
EscherSpRecord spRecord = ecr.getChildById(EscherSpRecord.RECORD_ID);
|
EscherSpRecord spRecord = ecr.getChildById(EscherSpRecord.RECORD_ID);
|
||||||
spRecord.setFlags(spRecord.getFlags()|EscherSpRecord.FLAG_OLESHAPE);
|
spRecord.setFlags(spRecord.getFlags()|EscherSpRecord.FLAG_OLESHAPE);
|
||||||
|
|
||||||
EscherContainerRecord uerCont = ecr.getChildById((short)RecordTypes.EscherClientData);
|
HSLFEscherClientDataRecord cldata = getClientData(true);
|
||||||
if (uerCont == null) {
|
ExObjRefAtom uer = null;
|
||||||
uerCont = new EscherContainerRecord();
|
for (Record r : cldata.getHSLFChildRecords()) {
|
||||||
ecr.addChildRecord(uerCont);
|
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) {
|
if (uer == null) {
|
||||||
uer = new UnknownEscherRecord();
|
uer = new ExObjRefAtom();
|
||||||
uerCont.addChildRecord(uer);
|
cldata.addChild(uer);
|
||||||
}
|
}
|
||||||
|
uer.setExObjIdRef(objectId);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -116,6 +117,7 @@ public final class OLEShape extends HSLFPictureShape {
|
|||||||
*
|
*
|
||||||
* @return the unique identifier for the OLE object
|
* @return the unique identifier for the OLE object
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("resource")
|
||||||
public HSLFObjectData getObjectData(){
|
public HSLFObjectData getObjectData(){
|
||||||
HSLFSlideShow ppt = getSheet().getSlideShow();
|
HSLFSlideShow ppt = getSheet().getSlideShow();
|
||||||
HSLFObjectData[] ole = ppt.getEmbeddedObjects();
|
HSLFObjectData[] ole = ppt.getEmbeddedObjects();
|
||||||
@ -153,6 +155,7 @@ public final class OLEShape extends HSLFPictureShape {
|
|||||||
* 6. MetaFile( 4033), optional
|
* 6. MetaFile( 4033), optional
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("resource")
|
||||||
public ExEmbed getExEmbed(){
|
public ExEmbed getExEmbed(){
|
||||||
if(_exEmbed == null){
|
if(_exEmbed == null){
|
||||||
HSLFSlideShow ppt = getSheet().getSlideShow();
|
HSLFSlideShow ppt = getSheet().getSlideShow();
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndian;
|
|||||||
* @see EscherRecordFactory
|
* @see EscherRecordFactory
|
||||||
*/
|
*/
|
||||||
public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory {
|
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 );
|
private static Map<Short, Constructor<? extends EscherRecord>> recordsMap = recordsToMap( escherRecordClasses );
|
||||||
|
|
||||||
|
|
||||||
@ -65,6 +65,10 @@ public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory {
|
|||||||
}
|
}
|
||||||
escherRecord.setRecordId(recordId);
|
escherRecord.setRecordId(recordId);
|
||||||
escherRecord.setOptions(options);
|
escherRecord.setOptions(options);
|
||||||
|
if (escherRecord instanceof EscherContainerRecord) {
|
||||||
|
((EscherContainerRecord)escherRecord).fillFields(data, offset, this);
|
||||||
|
}
|
||||||
|
|
||||||
return escherRecord;
|
return escherRecord;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,7 @@ public final class OEPlaceholderAtom extends RecordAtom{
|
|||||||
private int placementId;
|
private int placementId;
|
||||||
private int placeholderId;
|
private int placeholderId;
|
||||||
private int placeholderSize;
|
private int placeholderSize;
|
||||||
|
private short unusedShort = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,8 +228,9 @@ public final class OEPlaceholderAtom extends RecordAtom{
|
|||||||
offset += _header.length;
|
offset += _header.length;
|
||||||
|
|
||||||
placementId = LittleEndian.getInt(source, offset); offset += 4;
|
placementId = LittleEndian.getInt(source, offset); offset += 4;
|
||||||
placeholderId = LittleEndian.getUnsignedByte(source, offset); offset++;
|
placeholderId = LittleEndian.getUByte(source, offset); offset++;
|
||||||
placeholderSize = LittleEndian.getUnsignedByte(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);
|
LittleEndian.putInt(recdata, 0, placementId);
|
||||||
recdata[4] = (byte)placeholderId;
|
recdata[4] = (byte)placeholderId;
|
||||||
recdata[5] = (byte)placeholderSize;
|
recdata[5] = (byte)placeholderSize;
|
||||||
|
LittleEndian.putShort(recdata, 6, unusedShort);
|
||||||
|
|
||||||
out.write(recdata);
|
out.write(recdata);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,7 +20,6 @@ package org.apache.poi.hslf.record;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
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.EscherSpRecord;
|
||||||
import org.apache.poi.ddf.EscherSpgrRecord;
|
import org.apache.poi.ddf.EscherSpgrRecord;
|
||||||
import org.apache.poi.ddf.EscherTextboxRecord;
|
import org.apache.poi.ddf.EscherTextboxRecord;
|
||||||
import org.apache.poi.ddf.UnknownEscherRecord;
|
|
||||||
import org.apache.poi.sl.usermodel.ShapeType;
|
import org.apache.poi.sl.usermodel.ShapeType;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
@ -57,7 +55,7 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
private byte[] _header;
|
private byte[] _header;
|
||||||
private long _type;
|
private long _type;
|
||||||
|
|
||||||
private EscherRecord[] childRecords;
|
private final List<EscherRecord> childRecords = new ArrayList<EscherRecord>();
|
||||||
private EscherTextboxWrapper[] textboxWrappers;
|
private EscherTextboxWrapper[] textboxWrappers;
|
||||||
|
|
||||||
//cached EscherDgRecord
|
//cached EscherDgRecord
|
||||||
@ -66,7 +64,7 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
/**
|
/**
|
||||||
* Get access to the underlying Escher Records
|
* 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
|
* Get access to the atoms inside Textboxes
|
||||||
@ -76,6 +74,20 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
|
|
||||||
/* ******************** record stuff follows ********************** */
|
/* ******************** 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
|
* 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
|
// Build up a tree of Escher records contained within
|
||||||
final DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();
|
final DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();
|
||||||
final List<EscherRecord> escherChildren = new ArrayList<EscherRecord>();
|
findEscherChildren(erf, contents, 8, len-8, childRecords);
|
||||||
findEscherChildren(erf, contents, 8, len-8, escherChildren);
|
EscherContainerRecord dgContainer = getDgContainer();
|
||||||
this.childRecords = escherChildren.toArray(new EscherRecord[escherChildren.size()]);
|
|
||||||
|
|
||||||
if (1 == this.childRecords.length && (short)RecordTypes.EscherDgContainer == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) {
|
if (dgContainer != null) {
|
||||||
this.textboxWrappers = findInDgContainer((EscherContainerRecord) this.childRecords[0]);
|
textboxWrappers = findInDgContainer(dgContainer);
|
||||||
} else {
|
} else {
|
||||||
// Find and EscherTextboxRecord's, and wrap them up
|
// Find and EscherTextboxRecord's, and wrap them up
|
||||||
final List<EscherTextboxWrapper> textboxes = new ArrayList<EscherTextboxWrapper>();
|
final List<EscherTextboxWrapper> textboxes = new ArrayList<EscherTextboxWrapper>();
|
||||||
@ -108,15 +119,15 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
}
|
}
|
||||||
private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord dgContainer) {
|
private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord dgContainer) {
|
||||||
final List<EscherTextboxWrapper> found = new LinkedList<EscherTextboxWrapper>();
|
final List<EscherTextboxWrapper> found = new LinkedList<EscherTextboxWrapper>();
|
||||||
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer);
|
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer);
|
||||||
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer);
|
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer);
|
||||||
for (EscherContainerRecord spContainer : spContainers) {
|
for (EscherContainerRecord spContainer : spContainers) {
|
||||||
StyleTextProp9Atom nineAtom = findInSpContainer(spContainer);
|
EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType(RecordTypes.EscherSp, spContainer);
|
||||||
EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherSp, spContainer);
|
EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType(RecordTypes.EscherClientTextbox, spContainer);
|
||||||
EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherClientTextbox, spContainer);
|
|
||||||
if (null == clientTextbox) { continue; }
|
if (null == clientTextbox) { continue; }
|
||||||
|
|
||||||
EscherTextboxWrapper w = new EscherTextboxWrapper(clientTextbox);
|
EscherTextboxWrapper w = new EscherTextboxWrapper(clientTextbox);
|
||||||
|
StyleTextProp9Atom nineAtom = findInSpContainer(spContainer);
|
||||||
w.setStyleTextProp9Atom(nineAtom);
|
w.setStyleTextProp9Atom(nineAtom);
|
||||||
if (null != sp) {
|
if (null != sp) {
|
||||||
w.setShapeId(sp.getShapeId());
|
w.setShapeId(sp.getShapeId());
|
||||||
@ -127,16 +138,26 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) {
|
private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) {
|
||||||
EscherContainerRecord clientData = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherClientData, spContainer);
|
HSLFEscherClientDataRecord cldata = spContainer.getChildById(RecordTypes.EscherClientData.typeID);
|
||||||
if (null == clientData) { return null; }
|
if (cldata == null) {
|
||||||
final EscherContainerRecord progTagsContainer = findFirstEscherContainerRecordOfType((short)0x1388, clientData);
|
return null;
|
||||||
if (null == progTagsContainer) { return null; }
|
}
|
||||||
final EscherContainerRecord progBinaryTag = findFirstEscherContainerRecordOfType((short)0x138A, progTagsContainer);
|
DummyPositionSensitiveRecordWithChildren progTags =
|
||||||
if (null == progBinaryTag) { return null; }
|
getChildRecord(cldata.getHSLFChildRecords(), RecordTypes.ProgTags);
|
||||||
int size = progBinaryTag.getChildRecords().size();
|
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; }
|
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 (!(r0 instanceof CString)) { return null; }
|
||||||
if (!("___PPT9".equals(((CString) r0).getText()))) { return null; };
|
if (!("___PPT9".equals(((CString) r0).getText()))) { return null; };
|
||||||
if (!(r1 instanceof BinaryTagDataBlob )) { 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; }
|
if (1 != blob.getChildRecords().length) { return null; }
|
||||||
return (StyleTextProp9Atom) blob.findFirstOfType(RecordTypes.StyleTextProp9Atom.typeID);
|
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
|
* Tree walking way of finding Escher Child Records
|
||||||
@ -198,27 +206,22 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
/**
|
/**
|
||||||
* Look for EscherTextboxRecords
|
* Look for EscherTextboxRecords
|
||||||
*/
|
*/
|
||||||
private void findEscherTextboxRecord(EscherRecord[] toSearch, List<EscherTextboxWrapper> found) {
|
private void findEscherTextboxRecord(List<EscherRecord> toSearch, List<EscherTextboxWrapper> found) {
|
||||||
for(int i=0; i<toSearch.length; i++) {
|
EscherSpRecord sp = null;
|
||||||
if(toSearch[i] instanceof EscherTextboxRecord) {
|
for (EscherRecord r : toSearch) {
|
||||||
EscherTextboxRecord tbr = (EscherTextboxRecord)toSearch[i];
|
if (r instanceof EscherSpRecord) {
|
||||||
|
sp = (EscherSpRecord)r;
|
||||||
|
} else if (r instanceof EscherTextboxRecord) {
|
||||||
|
EscherTextboxRecord tbr = (EscherTextboxRecord)r;
|
||||||
EscherTextboxWrapper w = new EscherTextboxWrapper(tbr);
|
EscherTextboxWrapper w = new EscherTextboxWrapper(tbr);
|
||||||
|
if (sp != null) {
|
||||||
|
w.setShapeId(sp.getShapeId());
|
||||||
|
}
|
||||||
found.add(w);
|
found.add(w);
|
||||||
for (int j = i; j >= 0; j--) {
|
} else if (r.isContainerRecord()) {
|
||||||
if(toSearch[j] instanceof EscherSpRecord){
|
|
||||||
EscherSpRecord sp = (EscherSpRecord)toSearch[j];
|
|
||||||
w.setShapeId(sp.getShapeId());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If it has children, walk them
|
// If it has children, walk them
|
||||||
if(toSearch[i].isContainerRecord()) {
|
List<EscherRecord> children = r.getChildRecords();
|
||||||
List<EscherRecord> childrenL = toSearch[i].getChildRecords();
|
findEscherTextboxRecord(children,found);
|
||||||
EscherRecord[] children = new EscherRecord[childrenL.size()];
|
|
||||||
childrenL.toArray(children);
|
|
||||||
findEscherTextboxRecord(children,found);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,9 +262,8 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
// Now grab the children's data
|
// Now grab the children's data
|
||||||
byte[] b = new byte[newSize];
|
byte[] b = new byte[newSize];
|
||||||
int done = 0;
|
int done = 0;
|
||||||
for(int i=0; i<childRecords.length; i++) {
|
for(EscherRecord r : childRecords) {
|
||||||
int written = childRecords[i].serialize( done, b );
|
done += r.serialize( done, b );
|
||||||
done += written;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, write out the children
|
// Finally, write out the children
|
||||||
@ -276,7 +278,7 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
|
dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
|
||||||
dgContainer.setOptions((short)15);
|
dgContainer.setOptions((short)15);
|
||||||
|
|
||||||
EscherDgRecord dg = new EscherDgRecord();
|
dg = new EscherDgRecord();
|
||||||
dg.setOptions((short)16);
|
dg.setOptions((short)16);
|
||||||
dg.setNumShapes(1);
|
dg.setNumShapes(1);
|
||||||
dgContainer.addChildRecord(dg);
|
dgContainer.addChildRecord(dg);
|
||||||
@ -321,10 +323,8 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
spContainer.addChildRecord(opt);
|
spContainer.addChildRecord(opt);
|
||||||
|
|
||||||
dgContainer.addChildRecord(spContainer);
|
dgContainer.addChildRecord(spContainer);
|
||||||
|
|
||||||
childRecords = new EscherRecord[]{
|
childRecords.add(dgContainer);
|
||||||
dgContainer
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -338,6 +338,22 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
textboxWrappers = tw;
|
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
|
* 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(){
|
public EscherDgRecord getEscherDgRecord(){
|
||||||
if(dg == null){
|
if(dg == null){
|
||||||
EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
|
for(EscherRecord r : getDgContainer().getChildRecords()){
|
||||||
for(Iterator<EscherRecord> it = dgContainer.getChildIterator(); it.hasNext();){
|
|
||||||
EscherRecord r = it.next();
|
|
||||||
if(r instanceof EscherDgRecord){
|
if(r instanceof EscherDgRecord){
|
||||||
dg = (EscherDgRecord)r;
|
dg = (EscherDgRecord)r;
|
||||||
break;
|
break;
|
||||||
@ -357,59 +371,59 @@ public final class PPDrawing extends RecordAtom {
|
|||||||
return dg;
|
return dg;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EscherContainerRecord findFirstEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
|
protected EscherContainerRecord findFirstEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) {
|
||||||
if (null == parent) { return null; }
|
if (null == parent) { return null; }
|
||||||
final List<EscherContainerRecord> children = parent.getChildContainers();
|
final List<EscherContainerRecord> children = parent.getChildContainers();
|
||||||
for (EscherContainerRecord child : children) {
|
for (EscherContainerRecord child : children) {
|
||||||
if (type == child.getRecordId()) {
|
if (type.typeID == child.getRecordId()) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
protected EscherRecord findFirstEscherRecordOfType(short type, EscherContainerRecord parent) {
|
protected EscherRecord findFirstEscherRecordOfType(RecordTypes type, EscherContainerRecord parent) {
|
||||||
if (null == parent) { return null; }
|
if (null == parent) { return null; }
|
||||||
final List<EscherRecord> children = parent.getChildRecords();
|
final List<EscherRecord> children = parent.getChildRecords();
|
||||||
for (EscherRecord child : children) {
|
for (EscherRecord child : children) {
|
||||||
if (type == child.getRecordId()) {
|
if (type.typeID == child.getRecordId()) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
protected EscherContainerRecord[] findAllEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
|
protected EscherContainerRecord[] findAllEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) {
|
||||||
if (null == parent) { return new EscherContainerRecord[0]; }
|
if (null == parent) { return new EscherContainerRecord[0]; }
|
||||||
final List<EscherContainerRecord> children = parent.getChildContainers();
|
final List<EscherContainerRecord> children = parent.getChildContainers();
|
||||||
final List<EscherContainerRecord> result = new LinkedList<EscherContainerRecord>();
|
final List<EscherContainerRecord> result = new LinkedList<EscherContainerRecord>();
|
||||||
for (EscherContainerRecord child : children) {
|
for (EscherContainerRecord child : children) {
|
||||||
if (type == child.getRecordId()) {
|
if (type.typeID == child.getRecordId()) {
|
||||||
result.add(child);
|
result.add(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result.toArray(new EscherContainerRecord[result.size()]);
|
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() {
|
public StyleTextProp9Atom[] getNumberedListInfo() {
|
||||||
final List<StyleTextProp9Atom> result = new LinkedList<StyleTextProp9Atom>();
|
final List<StyleTextProp9Atom> result = new LinkedList<StyleTextProp9Atom>();
|
||||||
EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
|
EscherContainerRecord dgContainer = getDgContainer();
|
||||||
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer);
|
final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer);
|
||||||
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer);
|
final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer);
|
||||||
for (EscherContainerRecord spContainer : spContainers) {
|
for (EscherContainerRecord spContainer : spContainers) {
|
||||||
StyleTextProp9Atom prop9 = findInSpContainer(spContainer);
|
StyleTextProp9Atom prop9 = findInSpContainer(spContainer);
|
||||||
if (prop9 != null) result.add(prop9);
|
if (prop9 != null) {
|
||||||
|
result.add(prop9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result.toArray(new StyleTextProp9Atom[result.size()]);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,19 +166,19 @@ public abstract class Record
|
|||||||
// Any special record handling occurs once we have the class
|
// Any special record handling occurs once we have the class
|
||||||
Class<? extends Record> c = null;
|
Class<? extends Record> c = null;
|
||||||
try {
|
try {
|
||||||
c = RecordTypes.recordHandlingClass((int)type);
|
c = RecordTypes.forTypeID((short)type).handlingClass;
|
||||||
if(c == null) {
|
if(c == null) {
|
||||||
// How odd. RecordTypes normally subsitutes in
|
// How odd. RecordTypes normally subsitutes in
|
||||||
// a default handler class if it has heard of the record
|
// a default handler class if it has heard of the record
|
||||||
// type but there's no support for it. Explicitly request
|
// type but there's no support for it. Explicitly request
|
||||||
// that now
|
// that now
|
||||||
c = RecordTypes.recordHandlingClass( RecordTypes.Unknown.typeID );
|
c = RecordTypes.UnknownRecordPlaceholder.handlingClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab the right constructor
|
// Grab the right constructor
|
||||||
java.lang.reflect.Constructor<? extends Record> con = c.getDeclaredConstructor(new Class[] { byte[].class, Integer.TYPE, Integer.TYPE });
|
java.lang.reflect.Constructor<? extends Record> con = c.getDeclaredConstructor(new Class[] { byte[].class, Integer.TYPE, Integer.TYPE });
|
||||||
// Instantiate
|
// Instantiate
|
||||||
toReturn = con.newInstance(new Object[] { b, Integer.valueOf(start), Integer.valueOf(len) });
|
toReturn = con.newInstance(new Object[] { b, start, len });
|
||||||
} catch(InstantiationException ie) {
|
} catch(InstantiationException ie) {
|
||||||
throw new RuntimeException("Couldn't instantiate the class for type with id " + type + " on class " + c + " : " + ie, 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) {
|
} catch(java.lang.reflect.InvocationTargetException ite) {
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.record;
|
package org.apache.poi.hslf.record;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of all known record types in a PowerPoint document, and the
|
* 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:
|
* There are two categories of records:
|
||||||
* <li> PowerPoint records: 0 <= info <= 10002 (will carry class info)
|
* <li> PowerPoint records: 0 <= info <= 10002 (will carry class info)
|
||||||
* <li> Escher records: info >= 0xF000 (handled by DDF, so no 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 enum RecordTypes {
|
||||||
public static final HashMap<Integer,String> typeToName;
|
Unknown(0,null),
|
||||||
public static final HashMap<Integer,Class<? extends Record>> typeToClass;
|
UnknownRecordPlaceholder(-1, UnknownRecordPlaceholder.class),
|
||||||
|
Document(1000,Document.class),
|
||||||
public static final Type Unknown = new Type(0,null);
|
DocumentAtom(1001,DocumentAtom.class),
|
||||||
public static final Type Document = new Type(1000,Document.class);
|
EndDocument(1002,null),
|
||||||
public static final Type DocumentAtom = new Type(1001,DocumentAtom.class);
|
Slide(1006,Slide.class),
|
||||||
public static final Type EndDocument = new Type(1002,null);
|
SlideAtom(1007,SlideAtom.class),
|
||||||
public static final Type Slide = new Type(1006,Slide.class);
|
Notes(1008,Notes.class),
|
||||||
public static final Type SlideAtom = new Type(1007,SlideAtom.class);
|
NotesAtom(1009,NotesAtom.class),
|
||||||
public static final Type Notes = new Type(1008,Notes.class);
|
Environment(1010,Environment.class),
|
||||||
public static final Type NotesAtom = new Type(1009,NotesAtom.class);
|
SlidePersistAtom(1011,SlidePersistAtom.class),
|
||||||
public static final Type Environment = new Type(1010,Environment.class);
|
SSlideLayoutAtom(1015,null),
|
||||||
public static final Type SlidePersistAtom = new Type(1011,SlidePersistAtom.class);
|
MainMaster(1016,MainMaster.class),
|
||||||
public static final Type SSlideLayoutAtom = new Type(1015,null);
|
SSSlideInfoAtom(1017,SSSlideInfoAtom.class),
|
||||||
public static final Type MainMaster = new Type(1016,MainMaster.class);
|
SlideViewInfo(1018,null),
|
||||||
public static final Type SSSlideInfoAtom = new Type(1017,SSSlideInfoAtom.class);
|
GuideAtom(1019,null),
|
||||||
public static final Type SlideViewInfo = new Type(1018,null);
|
ViewInfo(1020,null),
|
||||||
public static final Type GuideAtom = new Type(1019,null);
|
ViewInfoAtom(1021,null),
|
||||||
public static final Type ViewInfo = new Type(1020,null);
|
SlideViewInfoAtom(1022,null),
|
||||||
public static final Type ViewInfoAtom = new Type(1021,null);
|
VBAInfo(1023,null),
|
||||||
public static final Type SlideViewInfoAtom = new Type(1022,null);
|
VBAInfoAtom(1024,null),
|
||||||
public static final Type VBAInfo = new Type(1023,null);
|
SSDocInfoAtom(1025,null),
|
||||||
public static final Type VBAInfoAtom = new Type(1024,null);
|
Summary(1026,null),
|
||||||
public static final Type SSDocInfoAtom = new Type(1025,null);
|
DocRoutingSlip(1030,null),
|
||||||
public static final Type Summary = new Type(1026,null);
|
OutlineViewInfo(1031,null),
|
||||||
public static final Type DocRoutingSlip = new Type(1030,null);
|
SorterViewInfo(1032,null),
|
||||||
public static final Type OutlineViewInfo = new Type(1031,null);
|
ExObjList(1033,ExObjList.class),
|
||||||
public static final Type SorterViewInfo = new Type(1032,null);
|
ExObjListAtom(1034,ExObjListAtom.class),
|
||||||
public static final Type ExObjList = new Type(1033,ExObjList.class);
|
PPDrawingGroup(1035,PPDrawingGroup.class),
|
||||||
public static final Type ExObjListAtom = new Type(1034,ExObjListAtom.class);
|
PPDrawing(1036,PPDrawing.class),
|
||||||
public static final Type PPDrawingGroup = new Type(1035,PPDrawingGroup.class);
|
NamedShows(1040,null),
|
||||||
public static final Type PPDrawing = new Type(1036,PPDrawing.class);
|
NamedShow(1041,null),
|
||||||
public static final Type NamedShows = new Type(1040,null);
|
NamedShowSlides(1042,null),
|
||||||
public static final Type NamedShow = new Type(1041,null);
|
SheetProperties(1044,null),
|
||||||
public static final Type NamedShowSlides = new Type(1042,null);
|
RoundTripCustomTableStyles12Atom(1064,null),
|
||||||
public static final Type SheetProperties = new Type(1044,null);
|
List(2000,null),
|
||||||
public static final Type RoundTripCustomTableStyles12Atom = new Type(1064,null);
|
FontCollection(2005,FontCollection.class),
|
||||||
public static final Type List = new Type(2000,null);
|
BookmarkCollection(2019,null),
|
||||||
public static final Type FontCollection = new Type(2005,FontCollection.class);
|
SoundCollection(2020,SoundCollection.class),
|
||||||
public static final Type BookmarkCollection = new Type(2019,null);
|
SoundCollAtom(2021,null),
|
||||||
public static final Type SoundCollection = new Type(2020,SoundCollection.class);
|
Sound(2022,Sound.class),
|
||||||
public static final Type SoundCollAtom = new Type(2021,null);
|
SoundData(2023,SoundData.class),
|
||||||
public static final Type Sound = new Type(2022,Sound.class);
|
BookmarkSeedAtom(2025,null),
|
||||||
public static final Type SoundData = new Type(2023,SoundData.class);
|
ColorSchemeAtom(2032,ColorSchemeAtom.class),
|
||||||
public static final Type BookmarkSeedAtom = new Type(2025,null);
|
ExObjRefAtom(3009,ExObjRefAtom.class),
|
||||||
public static final Type ColorSchemeAtom = new Type(2032,ColorSchemeAtom.class);
|
OEPlaceholderAtom(3011,OEPlaceholderAtom.class),
|
||||||
public static final Type ExObjRefAtom = new Type(3009,null);
|
GPopublicintAtom(3024,null),
|
||||||
public static final Type OEShapeAtom = new Type(3009,OEShapeAtom.class);
|
GRatioAtom(3031,null),
|
||||||
public static final Type OEPlaceholderAtom = new Type(3011,OEPlaceholderAtom.class);
|
OutlineTextRefAtom(3998,OutlineTextRefAtom.class),
|
||||||
public static final Type GPopublicintAtom = new Type(3024,null);
|
TextHeaderAtom(3999,TextHeaderAtom.class),
|
||||||
public static final Type GRatioAtom = new Type(3031,null);
|
TextCharsAtom(4000,TextCharsAtom.class),
|
||||||
public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class);
|
StyleTextPropAtom(4001, StyleTextPropAtom.class),//0x0fa1 RT_StyleTextPropAtom
|
||||||
public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class);
|
MasterTextPropAtom(4002, MasterTextPropAtom.class),
|
||||||
public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
|
TxMasterStyleAtom(4003,TxMasterStyleAtom.class),
|
||||||
public static final Type StyleTextPropAtom = new Type(4001, StyleTextPropAtom.class);//0x0fa1 RT_StyleTextPropAtom
|
TxCFStyleAtom(4004,null),
|
||||||
public static final Type MasterTextPropAtom = new Type(4002, MasterTextPropAtom.class);
|
TxPFStyleAtom(4005,null),
|
||||||
public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
|
TextRulerAtom(4006,TextRulerAtom.class),
|
||||||
public static final Type TxCFStyleAtom = new Type(4004,null);
|
TextBookmarkAtom(4007,null),
|
||||||
public static final Type TxPFStyleAtom = new Type(4005,null);
|
TextBytesAtom(4008,TextBytesAtom.class),
|
||||||
public static final Type TextRulerAtom = new Type(4006,TextRulerAtom.class);
|
TxSIStyleAtom(4009,null),
|
||||||
public static final Type TextBookmarkAtom = new Type(4007,null);
|
TextSpecInfoAtom(4010, TextSpecInfoAtom.class),
|
||||||
public static final Type TextBytesAtom = new Type(4008,TextBytesAtom.class);
|
DefaultRulerAtom(4011,null),
|
||||||
public static final Type TxSIStyleAtom = new Type(4009,null);
|
StyleTextProp9Atom(4012, StyleTextProp9Atom.class), //0x0FAC RT_StyleTextProp9Atom
|
||||||
public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class);
|
FontEntityAtom(4023,FontEntityAtom.class),
|
||||||
public static final Type DefaultRulerAtom = new Type(4011,null);
|
FontEmbeddedData(4024,null),
|
||||||
public static final Type StyleTextProp9Atom = new Type(4012, StyleTextProp9Atom.class); //0x0FAC RT_StyleTextProp9Atom
|
CString(4026,CString.class),
|
||||||
public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class);
|
MetaFile(4033,null),
|
||||||
public static final Type FontEmbeddedData = new Type(4024,null);
|
ExOleObjAtom(4035,ExOleObjAtom.class),
|
||||||
public static final Type CString = new Type(4026,CString.class);
|
SrKinsoku(4040,null),
|
||||||
public static final Type MetaFile = new Type(4033,null);
|
HandOut(4041,DummyPositionSensitiveRecordWithChildren.class),
|
||||||
public static final Type ExOleObjAtom = new Type(4035,ExOleObjAtom.class);
|
ExEmbed(4044,ExEmbed.class),
|
||||||
public static final Type SrKinsoku = new Type(4040,null);
|
ExEmbedAtom(4045,ExEmbedAtom.class),
|
||||||
public static final Type HandOut = new Type(4041,DummyPositionSensitiveRecordWithChildren.class);
|
ExLink(4046,null),
|
||||||
public static final Type ExEmbed = new Type(4044,ExEmbed.class);
|
BookmarkEntityAtom(4048,null),
|
||||||
public static final Type ExEmbedAtom = new Type(4045,ExEmbedAtom.class);
|
ExLinkAtom(4049,null),
|
||||||
public static final Type ExLink = new Type(4046,null);
|
SrKinsokuAtom(4050,null),
|
||||||
public static final Type BookmarkEntityAtom = new Type(4048,null);
|
ExHyperlinkAtom(4051,ExHyperlinkAtom.class),
|
||||||
public static final Type ExLinkAtom = new Type(4049,null);
|
ExHyperlink(4055,ExHyperlink.class),
|
||||||
public static final Type SrKinsokuAtom = new Type(4050,null);
|
SlideNumberMCAtom(4056,null),
|
||||||
public static final Type ExHyperlinkAtom = new Type(4051,ExHyperlinkAtom.class);
|
HeadersFooters(4057,HeadersFootersContainer.class),
|
||||||
public static final Type ExHyperlink = new Type(4055,ExHyperlink.class);
|
HeadersFootersAtom(4058,HeadersFootersAtom.class),
|
||||||
public static final Type SlideNumberMCAtom = new Type(4056,null);
|
TxInteractiveInfoAtom(4063,TxInteractiveInfoAtom.class),
|
||||||
public static final Type HeadersFooters = new Type(4057,HeadersFootersContainer.class);
|
CharFormatAtom(4066,null),
|
||||||
public static final Type HeadersFootersAtom = new Type(4058,HeadersFootersAtom.class);
|
ParaFormatAtom(4067,null),
|
||||||
public static final Type TxInteractiveInfoAtom = new Type(4063,TxInteractiveInfoAtom.class);
|
RecolorInfoAtom(4071,null),
|
||||||
public static final Type CharFormatAtom = new Type(4066,null);
|
ExQuickTimeMovie(4074,null),
|
||||||
public static final Type ParaFormatAtom = new Type(4067,null);
|
ExQuickTimeMovieData(4075,null),
|
||||||
public static final Type RecolorInfoAtom = new Type(4071,null);
|
ExControl(4078,ExControl.class),
|
||||||
public static final Type ExQuickTimeMovie = new Type(4074,null);
|
SlideListWithText(4080,SlideListWithText.class),
|
||||||
public static final Type ExQuickTimeMovieData = new Type(4075,null);
|
InteractiveInfo(4082,InteractiveInfo.class),
|
||||||
public static final Type ExControl = new Type(4078,ExControl.class);
|
InteractiveInfoAtom(4083,InteractiveInfoAtom.class),
|
||||||
public static final Type SlideListWithText = new Type(4080,SlideListWithText.class);
|
UserEditAtom(4085,UserEditAtom.class),
|
||||||
public static final Type InteractiveInfo = new Type(4082,InteractiveInfo.class);
|
CurrentUserAtom(4086,null),
|
||||||
public static final Type InteractiveInfoAtom = new Type(4083,InteractiveInfoAtom.class);
|
DateTimeMCAtom(4087,null),
|
||||||
public static final Type UserEditAtom = new Type(4085,UserEditAtom.class);
|
GenericDateMCAtom(4088,null),
|
||||||
public static final Type CurrentUserAtom = new Type(4086,null);
|
FooterMCAtom(4090,null),
|
||||||
public static final Type DateTimeMCAtom = new Type(4087,null);
|
ExControlAtom(4091,ExControlAtom.class),
|
||||||
public static final Type GenericDateMCAtom = new Type(4088,null);
|
ExMediaAtom(4100,ExMediaAtom.class),
|
||||||
public static final Type FooterMCAtom = new Type(4090,null);
|
ExVideoContainer(4101,ExVideoContainer.class),
|
||||||
public static final Type ExControlAtom = new Type(4091,ExControlAtom.class);
|
ExAviMovie(4102,ExAviMovie.class),
|
||||||
public static final Type ExMediaAtom = new Type(4100,ExMediaAtom.class);
|
ExMCIMovie(4103,ExMCIMovie.class),
|
||||||
public static final Type ExVideoContainer = new Type(4101,ExVideoContainer.class);
|
ExMIDIAudio(4109,null),
|
||||||
public static final Type ExAviMovie = new Type(4102,ExAviMovie.class);
|
ExCDAudio(4110,null),
|
||||||
public static final Type ExMCIMovie = new Type(4103,ExMCIMovie.class);
|
ExWAVAudioEmbedded(4111,null),
|
||||||
public static final Type ExMIDIAudio = new Type(4109,null);
|
ExWAVAudioLink(4112,null),
|
||||||
public static final Type ExCDAudio = new Type(4110,null);
|
ExOleObjStg(4113,ExOleObjStg.class),
|
||||||
public static final Type ExWAVAudioEmbedded = new Type(4111,null);
|
ExCDAudioAtom(4114,null),
|
||||||
public static final Type ExWAVAudioLink = new Type(4112,null);
|
ExWAVAudioEmbeddedAtom(4115,null),
|
||||||
public static final Type ExOleObjStg = new Type(4113,ExOleObjStg.class);
|
AnimationInfo(4116,AnimationInfo.class),
|
||||||
public static final Type ExCDAudioAtom = new Type(4114,null);
|
AnimationInfoAtom(4081,AnimationInfoAtom.class),
|
||||||
public static final Type ExWAVAudioEmbeddedAtom = new Type(4115,null);
|
RTFDateTimeMCAtom(4117,null),
|
||||||
public static final Type AnimationInfo = new Type(4116,AnimationInfo.class);
|
ProgTags(5000,DummyPositionSensitiveRecordWithChildren.class),
|
||||||
public static final Type AnimationInfoAtom = new Type(4081,AnimationInfoAtom.class);
|
ProgStringTag(5001,null),
|
||||||
public static final Type RTFDateTimeMCAtom = new Type(4117,null);
|
ProgBinaryTag(5002,DummyPositionSensitiveRecordWithChildren.class),
|
||||||
public static final Type ProgTags = new Type(5000,DummyPositionSensitiveRecordWithChildren.class);
|
BinaryTagData(5003, BinaryTagDataBlob.class),//0x138b RT_BinaryTagDataBlob
|
||||||
public static final Type ProgStringTag = new Type(5001,null);
|
PrpublicintOptions(6000,null),
|
||||||
public static final Type ProgBinaryTag = new Type(5002,DummyPositionSensitiveRecordWithChildren.class);
|
PersistPtrFullBlock(6001,PersistPtrHolder.class),
|
||||||
public static final Type BinaryTagData = new Type(5003, BinaryTagDataBlob.class);//0x138b RT_BinaryTagDataBlob
|
PersistPtrIncrementalBlock(6002,PersistPtrHolder.class),
|
||||||
public static final Type PrpublicintOptions = new Type(6000,null);
|
GScalingAtom(10001,null),
|
||||||
public static final Type PersistPtrFullBlock = new Type(6001,PersistPtrHolder.class);
|
GRColorAtom(10002,null),
|
||||||
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);
|
|
||||||
|
|
||||||
// Records ~12000 seem to be related to the Comments used in PPT 2000/XP
|
// Records ~12000 seem to be related to the Comments used in PPT 2000/XP
|
||||||
// (Comments in PPT97 are normal Escher text boxes)
|
// (Comments in PPT97 are normal Escher text boxes)
|
||||||
public static final Type Comment2000 = new Type(12000,Comment2000.class);
|
Comment2000(12000,Comment2000.class),
|
||||||
public static final Type Comment2000Atom = new Type(12001,Comment2000Atom.class);
|
Comment2000Atom(12001,Comment2000Atom.class),
|
||||||
public static final Type Comment2000Summary = new Type(12004,null);
|
Comment2000Summary(12004,null),
|
||||||
public static final Type Comment2000SummaryAtom = new Type(12005,null);
|
Comment2000SummaryAtom(12005,null),
|
||||||
|
|
||||||
// Records ~12050 seem to be related to Document Encryption
|
// 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
|
* Returns name of the record by its type
|
||||||
@ -218,10 +236,10 @@ public final class RecordTypes {
|
|||||||
* @param type section of the record header
|
* @param type section of the record header
|
||||||
* @return name of the record
|
* @return name of the record
|
||||||
*/
|
*/
|
||||||
public static String recordName(int type) {
|
// public static String recordName(int type) {
|
||||||
String name = typeToName.get(Integer.valueOf(type));
|
// String name = typeToName.get(Integer.valueOf(type));
|
||||||
return (name == null) ? ("Unknown" + type) : name;
|
// return (name == null) ? ("Unknown" + type) : name;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the class handling a record by its type.
|
* Returns the class handling a record by its type.
|
||||||
@ -232,38 +250,38 @@ public final class RecordTypes {
|
|||||||
* @param type section of the record header
|
* @param type section of the record header
|
||||||
* @return class to handle the record, or null if an unknown (eg Escher) record
|
* @return class to handle the record, or null if an unknown (eg Escher) record
|
||||||
*/
|
*/
|
||||||
public static Class<? extends Record> recordHandlingClass(int type) {
|
// public static Class<? extends Record> recordHandlingClass(int type) {
|
||||||
Class<? extends Record> c = typeToClass.get(Integer.valueOf(type));
|
// Class<? extends Record> c = typeToClass.get(Integer.valueOf(type));
|
||||||
return c;
|
// return c;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
static {
|
// static {
|
||||||
typeToName = new HashMap<Integer,String>();
|
// typeToName = new HashMap<Integer,String>();
|
||||||
typeToClass = new HashMap<Integer,Class<? extends Record>>();
|
// typeToClass = new HashMap<Integer,Class<? extends Record>>();
|
||||||
try {
|
// try {
|
||||||
Field[] f = RecordTypes.class.getFields();
|
// Field[] f = RecordTypes.class.getFields();
|
||||||
for (int i = 0; i < f.length; i++){
|
// for (int i = 0; i < f.length; i++){
|
||||||
Object val = f[i].get(null);
|
// Object val = f[i].get(null);
|
||||||
|
//
|
||||||
// Escher record, only store ID -> Name
|
// // Escher record, only store ID -> Name
|
||||||
if (val instanceof Integer) {
|
// if (val instanceof Integer) {
|
||||||
typeToName.put((Integer)val, f[i].getName());
|
// typeToName.put((Integer)val, f[i].getName());
|
||||||
}
|
// }
|
||||||
// PowerPoint record, store ID -> Name and ID -> Class
|
// // PowerPoint record, store ID -> Name and ID -> Class
|
||||||
if (val instanceof Type) {
|
// if (val instanceof Type) {
|
||||||
Type t = (Type)val;
|
// Type t = (Type)val;
|
||||||
Class<? extends Record> c = t.handlingClass;
|
// Class<? extends Record> c = t.handlingClass;
|
||||||
Integer id = Integer.valueOf(t.typeID);
|
// Integer id = Integer.valueOf(t.typeID);
|
||||||
if(c == null) { c = UnknownRecordPlaceholder.class; }
|
// if(c == null) { c = UnknownRecordPlaceholder.class; }
|
||||||
|
//
|
||||||
typeToName.put(id, f[i].getName());
|
// typeToName.put(id, f[i].getName());
|
||||||
typeToClass.put(id, c);
|
// typeToClass.put(id, c);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} catch (IllegalAccessException e){
|
// } catch (IllegalAccessException e){
|
||||||
throw new RuntimeException("Failed to initialize records types");
|
// 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
|
* Contains both the type, and the handling class (if any), and
|
||||||
* offers methods to get either back out.
|
* offers methods to get either back out.
|
||||||
*/
|
*/
|
||||||
public static class Type {
|
// public static class Type {
|
||||||
public final int typeID;
|
// public final int typeID;
|
||||||
public final Class<? extends Record> handlingClass;
|
// public final Class<? extends Record> handlingClass;
|
||||||
public Type(int typeID, Class<? extends Record> handlingClass) {
|
// public Type(int typeID, Class<? extends Record> handlingClass) {
|
||||||
this.typeID = typeID;
|
// this.typeID = typeID;
|
||||||
this.handlingClass = handlingClass;
|
// this.handlingClass = handlingClass;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ package org.apache.poi.hslf.record;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
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
|
* 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;
|
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.
|
* Constructs the comment atom record from its source data.
|
||||||
*
|
*
|
||||||
|
@ -171,7 +171,7 @@ public final class TxMasterStyleAtom extends RecordAtom {
|
|||||||
/**
|
/**
|
||||||
* Updates the rawdata from the modified paragraph/character styles
|
* Updates the rawdata from the modified paragraph/character styles
|
||||||
*
|
*
|
||||||
* @since 3.14-beta1
|
* @since POI 3.14-beta1
|
||||||
*/
|
*/
|
||||||
public void updateStyles() {
|
public void updateStyles() {
|
||||||
int type = getTextType();
|
int type = getTextType();
|
||||||
|
@ -17,10 +17,18 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.usermodel;
|
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.ExHyperlink;
|
||||||
import org.apache.poi.hslf.record.*;
|
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
|
* 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
|
* @param paragraphs List of <code>TextParagraph</code> to lookup hyperlinks
|
||||||
* @return found hyperlinks
|
* @return found hyperlinks
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("resource")
|
||||||
public static List<HSLFHyperlink> find(List<HSLFTextParagraph> paragraphs){
|
public static List<HSLFHyperlink> find(List<HSLFTextParagraph> paragraphs){
|
||||||
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
|
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
|
||||||
if (paragraphs == null || paragraphs.isEmpty()) return lst;
|
if (paragraphs == null || paragraphs.isEmpty()) return lst;
|
||||||
@ -165,10 +174,10 @@ public final class HSLFHyperlink {
|
|||||||
HSLFSlideShow ppt = firstPara.getSheet().getSlideShow();
|
HSLFSlideShow ppt = firstPara.getSheet().getSlideShow();
|
||||||
//document-level container which stores info about all links in a presentation
|
//document-level container which stores info about all links in a presentation
|
||||||
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
||||||
if (exobj == null) return lst;
|
if (exobj != null) {
|
||||||
|
Record[] records = firstPara.getRecords();
|
||||||
Record[] records = firstPara.getRecords();
|
find(Arrays.asList(records), exobj, lst);
|
||||||
find(records, exobj, lst);
|
}
|
||||||
|
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
@ -179,39 +188,38 @@ public final class HSLFHyperlink {
|
|||||||
* @param shape <code>Shape</code> to lookup hyperlink in
|
* @param shape <code>Shape</code> to lookup hyperlink in
|
||||||
* @return found hyperlink or <code>null</code>
|
* @return found hyperlink or <code>null</code>
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("resource")
|
||||||
public static HSLFHyperlink find(HSLFShape shape){
|
public static HSLFHyperlink find(HSLFShape shape){
|
||||||
List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
|
|
||||||
HSLFSlideShow ppt = shape.getSheet().getSlideShow();
|
HSLFSlideShow ppt = shape.getSheet().getSlideShow();
|
||||||
//document-level container which stores info about all links in a presentation
|
//document-level container which stores info about all links in a presentation
|
||||||
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
ExObjList exobj = ppt.getDocumentRecord().getExObjList();
|
||||||
if (exobj == null) {
|
HSLFEscherClientDataRecord cldata = shape.getClientData(false);
|
||||||
return null;
|
|
||||||
|
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();
|
return null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void find(Record[] records, ExObjList exobj, List<HSLFHyperlink> out){
|
private static void find(List<? extends Record> records, ExObjList exobj, List<HSLFHyperlink> out){
|
||||||
if (records == null) return;
|
ListIterator<? extends Record> iter = records.listIterator();
|
||||||
for (int i = 0; i < records.length; i++) {
|
while (iter.hasNext()) {
|
||||||
//see if we have InteractiveInfo in the textrun's records
|
Record r = iter.next();
|
||||||
if(!(records[i] instanceof InteractiveInfo)) continue;
|
// see if we have InteractiveInfo in the textrun's records
|
||||||
|
if (!(r instanceof InteractiveInfo)) {
|
||||||
InteractiveInfo hldr = (InteractiveInfo)records[i];
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
InteractiveInfo hldr = (InteractiveInfo)r;
|
||||||
InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
|
InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
|
||||||
int id = info.getHyperlinkID();
|
int id = info.getHyperlinkID();
|
||||||
ExHyperlink linkRecord = exobj.get(id);
|
ExHyperlink linkRecord = exobj.get(id);
|
||||||
if (linkRecord == null) continue;
|
if (linkRecord == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
HSLFHyperlink link = new HSLFHyperlink();
|
HSLFHyperlink link = new HSLFHyperlink();
|
||||||
link.title = linkRecord.getLinkTitle();
|
link.title = linkRecord.getLinkTitle();
|
||||||
@ -219,8 +227,13 @@ public final class HSLFHyperlink {
|
|||||||
link.type = info.getAction();
|
link.type = info.getAction();
|
||||||
out.add(link);
|
out.add(link);
|
||||||
|
|
||||||
if (i+1 < records.length && records[i+1] instanceof TxInteractiveInfoAtom){
|
if (iter.hasNext()) {
|
||||||
TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)records[++i];
|
r = iter.next();
|
||||||
|
if (!(r instanceof TxInteractiveInfoAtom)) {
|
||||||
|
iter.previous();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)r;
|
||||||
link.startIndex = txinfo.getStartIndex();
|
link.startIndex = txinfo.getStartIndex();
|
||||||
link.endIndex = txinfo.getEndIndex();
|
link.endIndex = txinfo.getEndIndex();
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
package org.apache.poi.hslf.usermodel;
|
package org.apache.poi.hslf.usermodel;
|
||||||
|
|
||||||
import org.apache.poi.ddf.EscherContainerRecord;
|
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;
|
import org.apache.poi.sl.usermodel.ShapeContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,6 +21,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.ddf.AbstractEscherOptRecord;
|
import org.apache.poi.ddf.AbstractEscherOptRecord;
|
||||||
import org.apache.poi.ddf.EscherChildAnchorRecord;
|
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.EscherRecord;
|
||||||
import org.apache.poi.ddf.EscherSimpleProperty;
|
import org.apache.poi.ddf.EscherSimpleProperty;
|
||||||
import org.apache.poi.ddf.EscherSpRecord;
|
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.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.hslf.record.RecordTypes;
|
||||||
import org.apache.poi.sl.usermodel.FillStyle;
|
import org.apache.poi.sl.usermodel.FillStyle;
|
||||||
import org.apache.poi.sl.usermodel.Shape;
|
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){
|
public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, int recordId){
|
||||||
return owner.getChildById((short)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){
|
public <T extends EscherRecord> T getEscherChild(int recordId){
|
||||||
return _escherContainer.getChildById((short)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.
|
* Returns escher property by id.
|
||||||
*
|
*
|
||||||
* @return escher property or <code>null</code> if not found.
|
* @return escher property or <code>null</code> if not found.
|
||||||
*/
|
*/
|
||||||
public static <T extends EscherProperty> T getEscherProperty(AbstractEscherOptRecord opt, int propId){
|
public static <T extends EscherProperty> T getEscherProperty(AbstractEscherOptRecord opt, int propId){
|
||||||
if (opt == null) return null;
|
return (opt == null) ? null : opt.<T>lookup(propId);
|
||||||
return opt.lookup(propId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -443,7 +460,7 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AbstractEscherOptRecord getEscherOptRecord() {
|
public AbstractEscherOptRecord getEscherOptRecord() {
|
||||||
AbstractEscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID);
|
AbstractEscherOptRecord opt = getEscherChild(RecordTypes.EscherOPT);
|
||||||
if (opt == null) {
|
if (opt == null) {
|
||||||
opt = getEscherChild(RecordTypes.EscherUserDefined);
|
opt = getEscherChild(RecordTypes.EscherUserDefined);
|
||||||
}
|
}
|
||||||
@ -485,4 +502,48 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
|
|||||||
public boolean isPlaceholder() {
|
public boolean isPlaceholder() {
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,27 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.usermodel;
|
package org.apache.poi.hslf.usermodel;
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.ddf.*;
|
import org.apache.poi.ddf.AbstractEscherOptRecord;
|
||||||
import org.apache.poi.hslf.model.*;
|
import org.apache.poi.ddf.EscherClientDataRecord;
|
||||||
import org.apache.poi.hslf.record.*;
|
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.ShapeContainer;
|
||||||
import org.apache.poi.sl.usermodel.ShapeType;
|
import org.apache.poi.sl.usermodel.ShapeType;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
@ -50,7 +65,7 @@ public final class HSLFShapeFactory {
|
|||||||
public static HSLFGroupShape createShapeGroup(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
|
public static HSLFGroupShape createShapeGroup(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
|
||||||
boolean isTable = false;
|
boolean isTable = false;
|
||||||
EscherContainerRecord ecr = (EscherContainerRecord)spContainer.getChild(0);
|
EscherContainerRecord ecr = (EscherContainerRecord)spContainer.getChild(0);
|
||||||
EscherRecord opt = HSLFShape.getEscherChild(ecr, (short)RecordTypes.EscherUserDefined);
|
EscherRecord opt = HSLFShape.getEscherChild(ecr, RecordTypes.EscherUserDefined);
|
||||||
|
|
||||||
if (opt != null) {
|
if (opt != null) {
|
||||||
EscherPropertyFactory f = new EscherPropertyFactory();
|
EscherPropertyFactory f = new EscherPropertyFactory();
|
||||||
@ -120,12 +135,10 @@ public final class HSLFShapeFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
|
ExObjRefAtom oes = getClientDataRecord(spContainer, RecordTypes.ExObjRefAtom.typeID);
|
||||||
if (oes != null){
|
return (oes != null)
|
||||||
return new OLEShape(spContainer, parent);
|
? new OLEShape(spContainer, parent)
|
||||||
}
|
: new HSLFPictureShape(spContainer, parent);
|
||||||
|
|
||||||
return new HSLFPictureShape(spContainer, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
|
private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
|
||||||
@ -141,15 +154,10 @@ public final class HSLFShapeFactory {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
|
protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
|
||||||
for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
|
HSLFEscherClientDataRecord cldata = spContainer.getChildById(EscherClientDataRecord.RECORD_ID);
|
||||||
EscherRecord obj = it.next();
|
if (cldata != null) for (Record r : cldata.getHSLFChildRecords()) {
|
||||||
if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
|
if (r.getRecordType() == recordType) {
|
||||||
byte[] data = obj.serialize();
|
return (T)r;
|
||||||
for (Record r : Record.findChildRecords(data, 8, data.length - 8)) {
|
|
||||||
if (r.getRecordType() == recordType) {
|
|
||||||
return (T)r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -149,7 +149,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
|
|||||||
public List<HSLFShape> getShapes() {
|
public List<HSLFShape> getShapes() {
|
||||||
PPDrawing ppdrawing = getPPDrawing();
|
PPDrawing ppdrawing = getPPDrawing();
|
||||||
|
|
||||||
EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
|
EscherContainerRecord dg = ppdrawing.getDgContainer();
|
||||||
EscherContainerRecord spgr = null;
|
EscherContainerRecord spgr = null;
|
||||||
|
|
||||||
for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
|
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) {
|
public void addShape(HSLFShape shape) {
|
||||||
PPDrawing ppdrawing = getPPDrawing();
|
PPDrawing ppdrawing = getPPDrawing();
|
||||||
|
|
||||||
EscherContainerRecord dgContainer = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
|
EscherContainerRecord dgContainer = ppdrawing.getDgContainer();
|
||||||
EscherContainerRecord spgr = (EscherContainerRecord) HSLFShape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER);
|
EscherContainerRecord spgr = (EscherContainerRecord) HSLFShape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER);
|
||||||
spgr.addChildRecord(shape.getSpContainer());
|
spgr.addChildRecord(shape.getSpContainer());
|
||||||
|
|
||||||
@ -244,16 +244,8 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
|
|||||||
public boolean removeShape(HSLFShape shape) {
|
public boolean removeShape(HSLFShape shape) {
|
||||||
PPDrawing ppdrawing = getPPDrawing();
|
PPDrawing ppdrawing = getPPDrawing();
|
||||||
|
|
||||||
EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
|
EscherContainerRecord dg = ppdrawing.getDgContainer();
|
||||||
EscherContainerRecord spgr = null;
|
EscherContainerRecord spgr = dg.getChildById(EscherContainerRecord.SPGR_CONTAINER);
|
||||||
|
|
||||||
for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
|
|
||||||
EscherRecord rec = it.next();
|
|
||||||
if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
|
|
||||||
spgr = (EscherContainerRecord) rec;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(spgr == null) {
|
if(spgr == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -292,7 +284,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
|
|||||||
if (_background == null) {
|
if (_background == null) {
|
||||||
PPDrawing ppdrawing = getPPDrawing();
|
PPDrawing ppdrawing = getPPDrawing();
|
||||||
|
|
||||||
EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
|
EscherContainerRecord dg = ppdrawing.getDgContainer();
|
||||||
EscherContainerRecord spContainer = dg.getChildById(EscherContainerRecord.SP_CONTAINER);
|
EscherContainerRecord spContainer = dg.getChildById(EscherContainerRecord.SP_CONTAINER);
|
||||||
_background = new HSLFBackground(spContainer, null);
|
_background = new HSLFBackground(spContainer, null);
|
||||||
_background.setSheet(this);
|
_background.setSheet(this);
|
||||||
|
@ -18,16 +18,40 @@
|
|||||||
package org.apache.poi.hslf.usermodel;
|
package org.apache.poi.hslf.usermodel;
|
||||||
|
|
||||||
import java.awt.Color;
|
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.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.DrawPaint;
|
||||||
import org.apache.poi.sl.draw.geom.*;
|
import org.apache.poi.sl.draw.geom.CustomGeometry;
|
||||||
import org.apache.poi.sl.usermodel.*;
|
import org.apache.poi.sl.draw.geom.Guide;
|
||||||
import org.apache.poi.sl.usermodel.LineDecoration.*;
|
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.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.LineCap;
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
|
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
|
||||||
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
|
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;
|
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.
|
* 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);
|
opt.setRecordId(EscherOptRecord.RECORD_ID);
|
||||||
_escherContainer.addChildRecord(opt);
|
_escherContainer.addChildRecord(opt);
|
||||||
|
|
||||||
EscherRecord anchor;
|
EscherRecord anchor;
|
||||||
if(isChild) anchor = new EscherChildAnchorRecord();
|
if(isChild) {
|
||||||
else {
|
anchor = new EscherChildAnchorRecord();
|
||||||
|
} else {
|
||||||
anchor = new EscherClientAnchorRecord();
|
anchor = new EscherClientAnchorRecord();
|
||||||
|
|
||||||
//hack. internal variable EscherClientAnchorRecord.shortRecord can be
|
//hack. internal variable EscherClientAnchorRecord.shortRecord can be
|
||||||
@ -251,70 +270,11 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
|
|||||||
getFill().setForegroundColor(color);
|
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){
|
public void setHyperlink(HSLFHyperlink link){
|
||||||
if(link.getId() == -1){
|
if(link.getId() == -1){
|
||||||
throw new HSLFException("You must call SlideShow.addHyperlink(Hyperlink link) first");
|
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();
|
InteractiveInfo info = new InteractiveInfo();
|
||||||
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
|
InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
|
||||||
|
|
||||||
@ -356,14 +316,8 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
|
|||||||
|
|
||||||
infoAtom.setHyperlinkID(link.getId());
|
infoAtom.setHyperlinkID(link.getId());
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
HSLFEscherClientDataRecord cldata = getClientData(true);
|
||||||
try {
|
cldata.addChild(infoAtom);
|
||||||
info.writeOut(out);
|
|
||||||
} catch(Exception e){
|
|
||||||
throw new HSLFException(e);
|
|
||||||
}
|
|
||||||
cldata.setRemainingData(out.toByteArray());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guide getAdjustValue(String name) {
|
public Guide getAdjustValue(String name) {
|
||||||
@ -560,99 +514,119 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setPlaceholder(Placeholder placeholder) {
|
@Override
|
||||||
EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
|
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();
|
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);
|
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
|
// 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 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.
|
* 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.
|
* This occurs when the user has moved the placeholder from its original position.
|
||||||
* In this case the placeholder ID is -1.
|
* In this case the placeholder ID is -1.
|
||||||
*/
|
*/
|
||||||
oep.setPlacementId(-1);
|
|
||||||
|
|
||||||
boolean isMaster = (getSheet() instanceof HSLFSlideMaster);
|
|
||||||
boolean isNotes = (getSheet() instanceof HSLFNotes);
|
|
||||||
byte phId;
|
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) {
|
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:
|
case HEADER:
|
||||||
phId = OEPlaceholderAtom.MasterHeader;
|
case FOOTER:
|
||||||
break;
|
if (rtp == null) {
|
||||||
case DGM:
|
rtp = new RoundTripHFPlaceholder12();
|
||||||
case CHART:
|
rtp.setPlaceholderId(phId);
|
||||||
phId = OEPlaceholderAtom.Graph;
|
clientData.addChild(rtp);
|
||||||
break;
|
}
|
||||||
case TABLE:
|
if (oep != null) {
|
||||||
phId = OEPlaceholderAtom.Table;
|
clientData.removeChild(OEPlaceholderAtom.class);
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case CONTENT:
|
if (rtp != null) {
|
||||||
phId = OEPlaceholderAtom.Object;
|
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;
|
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ import org.apache.poi.hslf.record.TextHeaderAtom;
|
|||||||
import org.apache.poi.sl.draw.DrawFactory;
|
import org.apache.poi.sl.draw.DrawFactory;
|
||||||
import org.apache.poi.sl.draw.Drawable;
|
import org.apache.poi.sl.draw.Drawable;
|
||||||
import org.apache.poi.sl.usermodel.Notes;
|
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.ShapeType;
|
||||||
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
|
|
||||||
import org.apache.poi.sl.usermodel.Slide;
|
import org.apache.poi.sl.usermodel.Slide;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,7 +163,7 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe
|
|||||||
public void onCreate(){
|
public void onCreate(){
|
||||||
//initialize drawing group id
|
//initialize drawing group id
|
||||||
EscherDggRecord dgg = getSlideShow().getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
|
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);
|
EscherDgRecord dg = (EscherDgRecord) HSLFShape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
|
||||||
int dgId = dgg.getMaxDrawingGroupId() + 1;
|
int dgId = dgg.getMaxDrawingGroupId() + 1;
|
||||||
dg.setOptions((short)(dgId << 4));
|
dg.setOptions((short)(dgId << 4));
|
||||||
|
@ -1162,8 +1162,8 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
|
|||||||
// For position dependent records, hold where they were and now are
|
// For position dependent records, hold where they were and now are
|
||||||
// As we go along, update, and hand over, to any Position Dependent
|
// As we go along, update, and hand over, to any Position Dependent
|
||||||
// records we happen across
|
// records we happen across
|
||||||
Map<RecordTypes.Type,PositionDependentRecord> interestingRecords =
|
Map<RecordTypes,PositionDependentRecord> interestingRecords =
|
||||||
new HashMap<RecordTypes.Type,PositionDependentRecord>();
|
new HashMap<RecordTypes,PositionDependentRecord>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords);
|
_hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords);
|
||||||
|
@ -474,7 +474,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
|
|||||||
* May be null, if not needed.
|
* May be null, if not needed.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void updateAndWriteDependantRecords(OutputStream os, Map<RecordTypes.Type,PositionDependentRecord> interestingRecords)
|
public void updateAndWriteDependantRecords(OutputStream os, Map<RecordTypes,PositionDependentRecord> interestingRecords)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// For position dependent records, hold where they were and now are
|
// For position dependent records, hold where they were and now are
|
||||||
// As we go along, update, and hand over, to any Position Dependent
|
// 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
|
// Grab interesting records as they come past
|
||||||
// this will only save the very last record of each type
|
// this will only save the very last record of each type
|
||||||
RecordTypes.Type saveme = null;
|
RecordTypes saveme = null;
|
||||||
int recordType = (int)record.getRecordType();
|
int recordType = (int)record.getRecordType();
|
||||||
if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) {
|
if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) {
|
||||||
saveme = RecordTypes.PersistPtrIncrementalBlock;
|
saveme = RecordTypes.PersistPtrIncrementalBlock;
|
||||||
|
@ -95,14 +95,14 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
|
|||||||
|
|
||||||
EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
|
EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
|
||||||
AbstractEscherOptRecord opt = new EscherOptRecord();
|
AbstractEscherOptRecord opt = new EscherOptRecord();
|
||||||
opt.setRecordId((short)RecordTypes.EscherUserDefined);
|
opt.setRecordId(RecordTypes.EscherUserDefined.typeID);
|
||||||
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__TABLEPROPERTIES, 1));
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__TABLEPROPERTIES, 1));
|
||||||
EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES), false, null);
|
EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES), false, null);
|
||||||
p.setSizeOfElements(0x0004);
|
p.setSizeOfElements(0x0004);
|
||||||
p.setNumberOfElementsInArray(numRows);
|
p.setNumberOfElementsInArray(numRows);
|
||||||
p.setNumberOfElementsInMemory(numRows);
|
p.setNumberOfElementsInMemory(numRows);
|
||||||
opt.addEscherProperty(p);
|
opt.addEscherProperty(p);
|
||||||
spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor);
|
spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor.typeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,7 +157,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
|||||||
*
|
*
|
||||||
* @param paragraphStyle the master style reference
|
* @param paragraphStyle the master style reference
|
||||||
*
|
*
|
||||||
* @since 3.14-Beta1
|
* @since POI 3.14-Beta1
|
||||||
*/
|
*/
|
||||||
@Internal
|
@Internal
|
||||||
/* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {
|
/* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {
|
||||||
|
@ -76,7 +76,7 @@ public final class HSLFTextRun implements TextRun {
|
|||||||
*
|
*
|
||||||
* @param characterStyle the master style reference
|
* @param characterStyle the master style reference
|
||||||
*
|
*
|
||||||
* @since 3.14-Beta1
|
* @since POI 3.14-Beta1
|
||||||
*/
|
*/
|
||||||
@Internal
|
@Internal
|
||||||
/* package */ void setMasterStyleReference(TextPropCollection characterStyle) {
|
/* package */ void setMasterStyleReference(TextPropCollection characterStyle) {
|
||||||
|
@ -45,6 +45,7 @@ import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
|
|||||||
import org.apache.poi.sl.draw.DrawFactory;
|
import org.apache.poi.sl.draw.DrawFactory;
|
||||||
import org.apache.poi.sl.draw.DrawTextShape;
|
import org.apache.poi.sl.draw.DrawTextShape;
|
||||||
import org.apache.poi.sl.usermodel.Insets2D;
|
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.ShapeContainer;
|
||||||
import org.apache.poi.sl.usermodel.TextShape;
|
import org.apache.poi.sl.usermodel.TextShape;
|
||||||
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
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(){
|
public OEPlaceholderAtom getPlaceholderAtom(){
|
||||||
return getClientDataRecord(OEPlaceholderAtom.typeID);
|
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
|
* Assigns a hyperlink to this text shape
|
||||||
@ -644,7 +660,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
|
|||||||
if (oep != null) return true;
|
if (oep != null) return true;
|
||||||
|
|
||||||
//special case for files saved in Office 2007
|
//special case for files saved in Office 2007
|
||||||
RoundTripHFPlaceholder12 hldr = getClientDataRecord(RoundTripHFPlaceholder12.typeID);
|
RoundTripHFPlaceholder12 hldr = getHFPlaceholderAtom();
|
||||||
if (hldr != null) return true;
|
if (hldr != null) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -17,18 +17,22 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf;
|
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.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
|
||||||
import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
|
import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
|
||||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
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
|
* 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)
|
* @author Nick Burch (nick at torchbox dot com)
|
||||||
*/
|
*/
|
||||||
public final class TestReWrite extends TestCase {
|
public final class TestReWrite {
|
||||||
// HSLFSlideShow primed on the test data
|
// HSLFSlideShow primed on the test data
|
||||||
private HSLFSlideShowImpl hssA;
|
private HSLFSlideShowImpl hssA;
|
||||||
private HSLFSlideShowImpl hssB;
|
private HSLFSlideShowImpl hssB;
|
||||||
@ -46,7 +50,8 @@ public final class TestReWrite extends TestCase {
|
|||||||
private POIFSFileSystem pfsB;
|
private POIFSFileSystem pfsB;
|
||||||
private POIFSFileSystem pfsC;
|
private POIFSFileSystem pfsC;
|
||||||
|
|
||||||
public void setUp() throws Exception {
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
|
POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
|
||||||
|
|
||||||
@ -60,10 +65,12 @@ public final class TestReWrite extends TestCase {
|
|||||||
hssC = new HSLFSlideShowImpl(pfsC);
|
hssC = new HSLFSlideShowImpl(pfsC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testWritesOutTheSame() throws Exception {
|
public void testWritesOutTheSame() throws Exception {
|
||||||
assertWritesOutTheSame(hssA, pfsA);
|
assertWritesOutTheSame(hssA, pfsA);
|
||||||
assertWritesOutTheSame(hssB, pfsB);
|
assertWritesOutTheSame(hssB, pfsB);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception {
|
public void assertWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception {
|
||||||
// Write out to a byte array
|
// Write out to a byte array
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
@ -85,13 +92,15 @@ public final class TestReWrite extends TestCase {
|
|||||||
byte[] _nData = new byte[nProps.getSize()];
|
byte[] _nData = new byte[nProps.getSize()];
|
||||||
pfs.createDocumentInputStream("PowerPoint Document").read(_oData);
|
pfs.createDocumentInputStream("PowerPoint Document").read(_oData);
|
||||||
npfs.createDocumentInputStream("PowerPoint Document").read(_nData);
|
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));
|
//System.out.println(i + "\t" + Integer.toHexString(i));
|
||||||
assertEquals(_oData[i], _nData[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
|
// Check that they're apparently the same
|
||||||
assertSlideShowWritesOutTheSame(hssC, pfsC);
|
assertSlideShowWritesOutTheSame(hssC, pfsC);
|
||||||
|
|
||||||
@ -101,28 +110,25 @@ public final class TestReWrite extends TestCase {
|
|||||||
// Write out normally, will loose the macro stream
|
// Write out normally, will loose the macro stream
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
hssC.write(baos);
|
hssC.write(baos);
|
||||||
POIFSFileSystem pfsNew = new POIFSFileSystem(
|
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||||
new ByteArrayInputStream(baos.toByteArray()) );
|
POIFSFileSystem pfsNew = new POIFSFileSystem(bais);
|
||||||
|
assertFalse(pfsNew.getRoot().hasEntry("Macros"));
|
||||||
try {
|
pfsNew.close();
|
||||||
pfsNew.getRoot().getEntry("Macros");
|
|
||||||
fail();
|
|
||||||
} catch(FileNotFoundException e) {
|
|
||||||
// Good, as expected
|
|
||||||
}
|
|
||||||
|
|
||||||
// But if we write out with nodes preserved, will be there
|
// But if we write out with nodes preserved, will be there
|
||||||
baos = new ByteArrayOutputStream();
|
baos.reset();
|
||||||
hssC.write(baos, true);
|
hssC.write(baos, true);
|
||||||
pfsNew = new POIFSFileSystem(
|
bais = new ByteArrayInputStream(baos.toByteArray());
|
||||||
new ByteArrayInputStream(baos.toByteArray()) );
|
pfsNew = new POIFSFileSystem(bais);
|
||||||
assertNotNull( pfsNew.getRoot().getEntry("Macros") );
|
assertTrue( pfsNew.getRoot().hasEntry("Macros") );
|
||||||
|
pfsNew.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that simply opening a slideshow (usermodel) view of it
|
* Ensure that simply opening a slideshow (usermodel) view of it
|
||||||
* doesn't change things
|
* doesn't change things
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testSlideShowWritesOutTheSame() throws Exception {
|
public void testSlideShowWritesOutTheSame() throws Exception {
|
||||||
assertSlideShowWritesOutTheSame(hssA, pfsA);
|
assertSlideShowWritesOutTheSame(hssA, pfsA);
|
||||||
|
|
||||||
@ -130,9 +136,11 @@ public final class TestReWrite extends TestCase {
|
|||||||
// We need to identify and fix that first
|
// We need to identify and fix that first
|
||||||
//assertSlideShowWritesOutTheSame(hssB, pfsB);
|
//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
|
// Create a slideshow covering it
|
||||||
HSLFSlideShow ss = new HSLFSlideShow(hss);
|
@SuppressWarnings("resource")
|
||||||
|
HSLFSlideShow ss = new HSLFSlideShow(hss);
|
||||||
ss.getSlides();
|
ss.getSlides();
|
||||||
ss.getNotes();
|
ss.getNotes();
|
||||||
|
|
||||||
@ -161,17 +169,23 @@ public final class TestReWrite extends TestCase {
|
|||||||
System.out.println(i + "\t" + Integer.toHexString(i));
|
System.out.println(i + "\t" + Integer.toHexString(i));
|
||||||
assertEquals(_oData[i], _nData[i]);
|
assertEquals(_oData[i], _nData[i]);
|
||||||
}
|
}
|
||||||
|
npfs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void test48593() throws Exception {
|
@Test
|
||||||
HSLFSlideShow slideShow = new HSLFSlideShow();
|
public void test48593() throws IOException {
|
||||||
slideShow.createSlide();
|
HSLFSlideShow ppt1 = new HSLFSlideShow();
|
||||||
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
|
ppt1.createSlide();
|
||||||
slideShow.createSlide();
|
HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
|
||||||
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
|
ppt2.createSlide();
|
||||||
slideShow.createSlide();
|
HSLFSlideShow ppt3 = HSLFTestDataSamples.writeOutAndReadBack(ppt2);
|
||||||
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
|
ppt3.createSlide();
|
||||||
slideShow.createSlide();
|
HSLFSlideShow ppt4 = HSLFTestDataSamples.writeOutAndReadBack(ppt3);
|
||||||
slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
|
ppt4.createSlide();
|
||||||
|
HSLFTestDataSamples.writeOutAndReadBack(ppt4).close();
|
||||||
|
ppt4.close();
|
||||||
|
ppt3.close();
|
||||||
|
ppt2.close();
|
||||||
|
ppt1.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,40 +18,44 @@
|
|||||||
package org.apache.poi.hslf.record;
|
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
|
* 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() {
|
public void testPPTNameLookups() {
|
||||||
assertEquals("MainMaster", RecordTypes.recordName(1016));
|
assertEquals("MainMaster", RecordTypes.MainMaster.name());
|
||||||
assertEquals("TextBytesAtom", RecordTypes.recordName(4008));
|
assertEquals("TextBytesAtom", RecordTypes.TextBytesAtom.name());
|
||||||
assertEquals("VBAInfo", RecordTypes.recordName(1023));
|
assertEquals("VBAInfo", RecordTypes.VBAInfo.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testEscherNameLookups() {
|
public void testEscherNameLookups() {
|
||||||
assertEquals("EscherDggContainer", RecordTypes.recordName(0xf000));
|
assertEquals("EscherDggContainer", RecordTypes.EscherDggContainer.name());
|
||||||
assertEquals("EscherClientTextbox", RecordTypes.recordName(0xf00d));
|
assertEquals("EscherClientTextbox", RecordTypes.EscherClientTextbox.name());
|
||||||
assertEquals("EscherSelection", RecordTypes.recordName(0xf119));
|
assertEquals("EscherSelection", RecordTypes.EscherSelection.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testPPTClassLookups() {
|
public void testPPTClassLookups() {
|
||||||
assertEquals(Slide.class, RecordTypes.recordHandlingClass(1006));
|
assertEquals(Slide.class, RecordTypes.Slide.handlingClass);
|
||||||
assertEquals(TextCharsAtom.class, RecordTypes.recordHandlingClass(4000));
|
assertEquals(TextCharsAtom.class, RecordTypes.TextCharsAtom.handlingClass);
|
||||||
assertEquals(TextBytesAtom.class, RecordTypes.recordHandlingClass(4008));
|
assertEquals(TextBytesAtom.class, RecordTypes.TextBytesAtom.handlingClass);
|
||||||
assertEquals(SlideListWithText.class, RecordTypes.recordHandlingClass(4080));
|
assertEquals(SlideListWithText.class, RecordTypes.SlideListWithText.handlingClass);
|
||||||
|
|
||||||
// If this record is ever implemented, change to one that isn't!
|
// If this record is ever implemented, change to one that isn't!
|
||||||
// This is checking the "unhandled default" stuff works
|
// 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
|
// Should all come back with null, as DDF handles them
|
||||||
assertEquals(null, RecordTypes.recordHandlingClass(0xf000));
|
assertEquals(null, RecordTypes.EscherDggContainer.handlingClass);
|
||||||
assertEquals(null, RecordTypes.recordHandlingClass(0xf001));
|
assertEquals(null, RecordTypes.EscherBStoreContainer.handlingClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ package org.apache.poi.hslf.usermodel;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.awt.Color;
|
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.extractor.PowerPointExtractor;
|
||||||
import org.apache.poi.hslf.model.HeadersFooters;
|
import org.apache.poi.hslf.model.HeadersFooters;
|
||||||
import org.apache.poi.hslf.record.Document;
|
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.Record;
|
||||||
|
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
|
||||||
import org.apache.poi.hslf.record.SlideListWithText;
|
import org.apache.poi.hslf.record.SlideListWithText;
|
||||||
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
|
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
|
||||||
import org.apache.poi.hslf.record.TextHeaderAtom;
|
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;
|
||||||
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
||||||
import org.apache.poi.sl.usermodel.PictureData.PictureType;
|
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.Slide;
|
||||||
import org.apache.poi.sl.usermodel.SlideShow;
|
import org.apache.poi.sl.usermodel.SlideShow;
|
||||||
import org.apache.poi.sl.usermodel.SlideShowFactory;
|
import org.apache.poi.sl.usermodel.SlideShowFactory;
|
||||||
@ -777,6 +781,31 @@ public final class TestBugs {
|
|||||||
ex.close();
|
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 {
|
private static HSLFSlideShow open(String fileName) throws IOException {
|
||||||
File sample = HSLFTestDataSamples.getSampleFile(fileName);
|
File sample = HSLFTestDataSamples.getSampleFile(fileName);
|
||||||
|
@ -42,12 +42,11 @@ public final class TestNumberedList {
|
|||||||
@Test
|
@Test
|
||||||
public void testNumberedList() throws Exception {
|
public void testNumberedList() throws Exception {
|
||||||
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers.ppt"));
|
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers.ppt"));
|
||||||
assertTrue("No Exceptions while reading file", true);
|
|
||||||
|
|
||||||
final List<HSLFSlide> slides = ppt.getSlides();
|
final List<HSLFSlide> slides = ppt.getSlides();
|
||||||
assertEquals(2, slides.size());
|
assertEquals(2, slides.size());
|
||||||
checkSlide0(slides.get(0));
|
checkSlide0(slides.get(0));
|
||||||
checkSlide1(slides.get(1));
|
checkSlide1(slides.get(1));
|
||||||
|
ppt.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSlide0(final HSLFSlide s) {
|
private void checkSlide0(final HSLFSlide s) {
|
||||||
|
Loading…
Reference in New Issue
Block a user