Add support for HSLF metro blobs
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1713318 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1a32b63fd3
commit
e8d108ff22
@ -61,7 +61,7 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
|
||||
|
||||
protected XSLFGroupShape(CTGroupShape shape, XSLFSheet sheet){
|
||||
super(shape,sheet);
|
||||
_shapes = sheet.buildShapes(shape);
|
||||
_shapes = XSLFSheet.buildShapes(shape, sheet);
|
||||
_grpSpPr = shape.getGrpSpPr();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,60 @@
|
||||
/* ====================================================================
|
||||
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.xslf.usermodel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||
import org.apache.poi.openxml4j.opc.PackagePartName;
|
||||
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
|
||||
import org.apache.poi.sl.usermodel.Shape;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
|
||||
|
||||
/**
|
||||
* Experimental class for metro blobs, i.e. an alternative escher property
|
||||
* containing an ooxml representation of the shape.
|
||||
* This is the helper class for HSLFMetroShape to dive into OOXML classes
|
||||
*/
|
||||
@Internal
|
||||
public class XSLFMetroShape {
|
||||
/*
|
||||
* parses the metro bytes to a XSLF shape
|
||||
*/
|
||||
public static Shape<?,?> parseShape(byte metroBytes[])
|
||||
throws InvalidFormatException, IOException, XmlException {
|
||||
PackagePartName shapePN = PackagingURIHelper.createPartName("/drs/shapexml.xml");
|
||||
OPCPackage pkg = null;
|
||||
try {
|
||||
pkg = OPCPackage.open(new ByteArrayInputStream(metroBytes));
|
||||
PackagePart shapePart = pkg.getPart(shapePN);
|
||||
CTGroupShape gs = CTGroupShape.Factory.parse(shapePart.getInputStream());
|
||||
XSLFGroupShape xgs = new XSLFGroupShape(gs, null);
|
||||
return xgs.getShapes().get(0);
|
||||
} finally {
|
||||
if (pkg != null) {
|
||||
pkg.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -90,20 +90,20 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
|
||||
throw new IllegalStateException("SlideShow was not found");
|
||||
}
|
||||
|
||||
protected List<XSLFShape> buildShapes(CTGroupShape spTree){
|
||||
protected static List<XSLFShape> buildShapes(CTGroupShape spTree, XSLFSheet sheet){
|
||||
List<XSLFShape> shapes = new ArrayList<XSLFShape>();
|
||||
for(XmlObject ch : spTree.selectPath("*")){
|
||||
if(ch instanceof CTShape){ // simple shape
|
||||
XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, this);
|
||||
XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, sheet);
|
||||
shapes.add(shape);
|
||||
} else if (ch instanceof CTGroupShape){
|
||||
shapes.add(new XSLFGroupShape((CTGroupShape)ch, this));
|
||||
shapes.add(new XSLFGroupShape((CTGroupShape)ch, sheet));
|
||||
} else if (ch instanceof CTConnector){
|
||||
shapes.add(new XSLFConnectorShape((CTConnector)ch, this));
|
||||
shapes.add(new XSLFConnectorShape((CTConnector)ch, sheet));
|
||||
} else if (ch instanceof CTPicture){
|
||||
shapes.add(new XSLFPictureShape((CTPicture)ch, this));
|
||||
shapes.add(new XSLFPictureShape((CTPicture)ch, sheet));
|
||||
} else if (ch instanceof CTGraphicalObjectFrame){
|
||||
XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, this);
|
||||
XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, sheet);
|
||||
shapes.add(shape);
|
||||
}
|
||||
}
|
||||
@ -156,7 +156,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
|
||||
_drawing = new XSLFDrawing(this, cgs);
|
||||
}
|
||||
if (_shapes == null) {
|
||||
_shapes = buildShapes(cgs);
|
||||
_shapes = buildShapes(cgs, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,15 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.hslf.usermodel.HSLFTextShape;
|
||||
import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
|
||||
import org.apache.poi.sl.usermodel.SlideShow;
|
||||
import org.apache.poi.sl.usermodel.SlideShowFactory;
|
||||
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
|
||||
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.xslf.XSLFTestDataSamples;
|
||||
@ -40,9 +45,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestXSLFTextShape {
|
||||
|
||||
@Test
|
||||
@ -913,4 +915,16 @@ public class TestXSLFTextShape {
|
||||
|
||||
ppt.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void metroBlob() throws IOException {
|
||||
File f = POIDataSamples.getSlideShowInstance().getFile("bug52297.ppt");
|
||||
SlideShow<?,?> ppt = SlideShowFactory.create(f);
|
||||
HSLFTextShape sh = (HSLFTextShape)ppt.getSlides().get(1).getShapes().get(3);
|
||||
XSLFAutoShape xsh = (XSLFAutoShape)sh.getMetroShape();
|
||||
String textExp = " ___ ___ ___ ________ __ _______ ___ ___________ __________ __ _____ ___ ___ ___ _______ ____ ______ ___________ _____________ ___ _______ ______ ____ ______ __ ___________ __________ ___ _________ _____ ________ __________ ___ _______ __________ ";
|
||||
String textAct = xsh.getText();
|
||||
ppt.close();
|
||||
assertEquals(textExp, textAct);
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hslf.model;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.poi.ddf.AbstractEscherOptRecord;
|
||||
import org.apache.poi.ddf.EscherComplexProperty;
|
||||
import org.apache.poi.ddf.EscherProperties;
|
||||
import org.apache.poi.ddf.EscherTertiaryOptRecord;
|
||||
import org.apache.poi.hslf.usermodel.HSLFShape;
|
||||
import org.apache.poi.sl.usermodel.Shape;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
/**
|
||||
* Experimental class for metro blobs, i.e. an alternative escher property
|
||||
* containing an ooxml representation of the shape
|
||||
*/
|
||||
@Internal
|
||||
public class HSLFMetroShape<T extends Shape<?,?>> {
|
||||
private static final POILogger LOGGER = POILogFactory.getLogger(HSLFMetroShape.class);
|
||||
|
||||
private final HSLFShape shape;
|
||||
|
||||
public HSLFMetroShape(HSLFShape shape) {
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the bytes of the metro blob, which are bytes of an OPCPackage, i.e. a zip stream
|
||||
*/
|
||||
public byte[] getMetroBytes() {
|
||||
AbstractEscherOptRecord opt = shape.getEscherChild(EscherTertiaryOptRecord.RECORD_ID);
|
||||
if (opt != null) {
|
||||
EscherComplexProperty ep = (EscherComplexProperty)opt.lookup(EscherProperties.GROUPSHAPE__METROBLOB);
|
||||
if (ep != null) {
|
||||
return ep.getComplexData();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the metro blob shape or null if either there's no metro blob or the ooxml classes
|
||||
* aren't in the classpath
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T getShape() {
|
||||
byte metroBytes[] = getMetroBytes();
|
||||
if (metroBytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// org.apache.poi.xslf.usermodel.XSLFMetroShape
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Class<?> ms = cl.loadClass("org.apache.poi.xslf.usermodel.XSLFMetroShape");
|
||||
Method m = ms.getMethod("parseShape", byte[].class);
|
||||
return (T)m.invoke(null, new Object[]{metroBytes});
|
||||
} catch (Exception e) {
|
||||
LOGGER.log(POILogger.ERROR, "can't process metro blob, check if all dependencies for POI OOXML are in the classpath.", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -499,4 +499,9 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFollowMasterGraphics() {
|
||||
return getFollowMasterObjects();
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,12 @@
|
||||
|
||||
package org.apache.poi.hslf.usermodel;
|
||||
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.sl.usermodel.*;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherProperties;
|
||||
import org.apache.poi.sl.usermodel.ShapeContainer;
|
||||
import org.apache.poi.sl.usermodel.ShapeType;
|
||||
import org.apache.poi.sl.usermodel.TextBox;
|
||||
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
||||
|
||||
/**
|
||||
* Represents a TextFrame shape in PowerPoint.
|
||||
@ -88,5 +92,4 @@ public class HSLFTextBox extends HSLFTextShape implements TextBox<HSLFShape,HSLF
|
||||
setVerticalAlignment(VerticalAlignment.TOP);
|
||||
setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -994,6 +994,15 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (HSLFTextRun r : getTextRuns()) {
|
||||
sb.append(r.getRawText());
|
||||
}
|
||||
return toExternalString(sb.toString(), getRunType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new string with line breaks converted into internal ppt
|
||||
* representation
|
||||
|
@ -34,6 +34,7 @@ import org.apache.poi.ddf.EscherProperties;
|
||||
import org.apache.poi.ddf.EscherSimpleProperty;
|
||||
import org.apache.poi.ddf.EscherTextboxRecord;
|
||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||
import org.apache.poi.hslf.model.HSLFMetroShape;
|
||||
import org.apache.poi.hslf.record.EscherTextboxWrapper;
|
||||
import org.apache.poi.hslf.record.InteractiveInfo;
|
||||
import org.apache.poi.hslf.record.InteractiveInfoAtom;
|
||||
@ -881,4 +882,14 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get alternative representation of text shape stored as metro blob escher property.
|
||||
* The returned shape is the first shape in stored group shape of the metro blob
|
||||
*
|
||||
* @return null, if there's no alternative representation, otherwise the text shape
|
||||
*/
|
||||
public TextShape<?,?> getMetroShape() {
|
||||
HSLFMetroShape<TextShape<?,?>> mbs = new HSLFMetroShape<TextShape<?,?>>(this);
|
||||
return mbs.getShape();
|
||||
}
|
||||
}
|
BIN
test-data/slideshow/bug52297.ppt
Normal file
BIN
test-data/slideshow/bug52297.ppt
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user