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:
Andreas Beeker 2015-11-08 23:13:28 +00:00
parent 1a32b63fd3
commit e8d108ff22
10 changed files with 235 additions and 50 deletions

View File

@ -61,7 +61,7 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
protected XSLFGroupShape(CTGroupShape shape, XSLFSheet sheet){ protected XSLFGroupShape(CTGroupShape shape, XSLFSheet sheet){
super(shape,sheet); super(shape,sheet);
_shapes = sheet.buildShapes(shape); _shapes = XSLFSheet.buildShapes(shape, sheet);
_grpSpPr = shape.getGrpSpPr(); _grpSpPr = shape.getGrpSpPr();
} }

View File

@ -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();
}
}
}
}

View File

@ -90,20 +90,20 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
throw new IllegalStateException("SlideShow was not found"); 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>(); List<XSLFShape> shapes = new ArrayList<XSLFShape>();
for(XmlObject ch : spTree.selectPath("*")){ for(XmlObject ch : spTree.selectPath("*")){
if(ch instanceof CTShape){ // simple shape if(ch instanceof CTShape){ // simple shape
XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, this); XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, sheet);
shapes.add(shape); shapes.add(shape);
} else if (ch instanceof CTGroupShape){ } else if (ch instanceof CTGroupShape){
shapes.add(new XSLFGroupShape((CTGroupShape)ch, this)); shapes.add(new XSLFGroupShape((CTGroupShape)ch, sheet));
} else if (ch instanceof CTConnector){ } else if (ch instanceof CTConnector){
shapes.add(new XSLFConnectorShape((CTConnector)ch, this)); shapes.add(new XSLFConnectorShape((CTConnector)ch, sheet));
} else if (ch instanceof CTPicture){ } else if (ch instanceof CTPicture){
shapes.add(new XSLFPictureShape((CTPicture)ch, this)); shapes.add(new XSLFPictureShape((CTPicture)ch, sheet));
} else if (ch instanceof CTGraphicalObjectFrame){ } else if (ch instanceof CTGraphicalObjectFrame){
XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, this); XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, sheet);
shapes.add(shape); shapes.add(shape);
} }
} }
@ -156,7 +156,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
_drawing = new XSLFDrawing(this, cgs); _drawing = new XSLFDrawing(this, cgs);
} }
if (_shapes == null) { if (_shapes == null) {
_shapes = buildShapes(cgs); _shapes = buildShapes(cgs, this);
} }
} }

View File

@ -25,10 +25,15 @@ import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.awt.Color; import java.awt.Color;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; 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.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.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.xslf.XSLFTestDataSamples; 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.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
/**
* @author Yegor Kozlov
*/
public class TestXSLFTextShape { public class TestXSLFTextShape {
@Test @Test
@ -913,4 +915,16 @@ public class TestXSLFTextShape {
ppt.close(); 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);
}
} }

View File

@ -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;
}
}
}

View File

@ -499,4 +499,9 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@Override
public boolean getFollowMasterGraphics() {
return getFollowMasterObjects();
}
} }

View File

@ -17,8 +17,12 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import org.apache.poi.ddf.*; import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.sl.usermodel.*; 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. * Represents a TextFrame shape in PowerPoint.
@ -88,5 +92,4 @@ public class HSLFTextBox extends HSLFTextShape implements TextBox<HSLFShape,HSLF
setVerticalAlignment(VerticalAlignment.TOP); setVerticalAlignment(VerticalAlignment.TOP);
setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002); setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002);
} }
} }

View File

@ -993,6 +993,15 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
} }
return sb.toString(); 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 * Returns a new string with line breaks converted into internal ppt

View File

@ -34,6 +34,7 @@ import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherSimpleProperty; import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherTextboxRecord; import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.exceptions.HSLFException; 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.EscherTextboxWrapper;
import org.apache.poi.hslf.record.InteractiveInfo; import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.InteractiveInfoAtom; import org.apache.poi.hslf.record.InteractiveInfoAtom;
@ -102,7 +103,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
*/ */
public static final int WrapThrough = 4; public static final int WrapThrough = 4;
/** /**
* TextRun object which holds actual text and format data * TextRun object which holds actual text and format data
*/ */
@ -116,11 +117,11 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
/** /**
* This setting is used for supporting a deprecated alignment * This setting is used for supporting a deprecated alignment
* *
* @see <a href=""></a> * @see <a href=""></a>
*/ */
boolean alignToBaseline = false; boolean alignToBaseline = false;
/** /**
* Used to calculate text bounds * Used to calculate text bounds
*/ */
@ -176,11 +177,11 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
super.afterInsert(sh); super.afterInsert(sh);
storeText(); storeText();
EscherTextboxWrapper thisTxtbox = getEscherTextboxWrapper(); EscherTextboxWrapper thisTxtbox = getEscherTextboxWrapper();
if(thisTxtbox != null){ if(thisTxtbox != null){
_escherContainer.addChildRecord(thisTxtbox.getEscherRecord()); _escherContainer.addChildRecord(thisTxtbox.getEscherRecord());
PPDrawing ppdrawing = sh.getPPDrawing(); PPDrawing ppdrawing = sh.getPPDrawing();
ppdrawing.addTextboxWrapper(thisTxtbox); ppdrawing.addTextboxWrapper(thisTxtbox);
// Ensure the escher layer knows about the added records // Ensure the escher layer knows about the added records
@ -199,10 +200,10 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
protected EscherTextboxWrapper getEscherTextboxWrapper(){ protected EscherTextboxWrapper getEscherTextboxWrapper(){
if(_txtbox != null) return _txtbox; if(_txtbox != null) return _txtbox;
EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID); EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID);
if (textRecord == null) return null; if (textRecord == null) return null;
HSLFSheet sheet = getSheet(); HSLFSheet sheet = getSheet();
if (sheet != null) { if (sheet != null) {
PPDrawing drawing = sheet.getPPDrawing(); PPDrawing drawing = sheet.getPPDrawing();
@ -219,7 +220,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
} }
} }
} }
_txtbox = new EscherTextboxWrapper(textRecord); _txtbox = new EscherTextboxWrapper(textRecord);
return _txtbox; return _txtbox;
} }
@ -236,15 +237,15 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
anchor.setSize(200, (int)anchor.getHeight()); anchor.setSize(200, (int)anchor.getHeight());
setAnchor(anchor); setAnchor(anchor);
} }
double height = getTextHeight(); double height = getTextHeight();
height += 1; // add a pixel to compensate rounding errors height += 1; // add a pixel to compensate rounding errors
anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height); anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height);
setAnchor(anchor); setAnchor(anchor);
return anchor; return anchor;
} }
/** /**
* Returns the type of the text, from the TextHeaderAtom. * Returns the type of the text, from the TextHeaderAtom.
* Possible values can be seen from TextHeaderAtom * Possible values can be seen from TextHeaderAtom
@ -271,7 +272,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
paras.get(0).setRunType(type); paras.get(0).setRunType(type);
} }
} }
/** /**
* Returns the type of vertical alignment for the text. * Returns the type of vertical alignment for the text.
* One of the <code>Anchor*</code> constants defined in this class. * One of the <code>Anchor*</code> constants defined in this class.
@ -310,7 +311,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
alignToBaseline = (align == AnchorBottomBaseline || align == AnchorBottomCenteredBaseline alignToBaseline = (align == AnchorBottomBaseline || align == AnchorBottomCenteredBaseline
|| align == AnchorTopBaseline || align == AnchorTopCenteredBaseline); || align == AnchorTopBaseline || align == AnchorTopCenteredBaseline);
return align; return align;
} }
@ -334,15 +335,15 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
align = new int[]{AnchorBottom, AnchorBottomCentered, AnchorBottomBaseline, AnchorBottomCenteredBaseline}; align = new int[]{AnchorBottom, AnchorBottomCentered, AnchorBottomBaseline, AnchorBottomCenteredBaseline};
break; break;
} }
int align2 = align[(isCentered ? 1 : 0)+(alignToBaseline ? 2 : 0)]; int align2 = align[(isCentered ? 1 : 0)+(alignToBaseline ? 2 : 0)];
setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align2); setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align2);
} }
/** /**
* @return true, if vertical alignment is relative to baseline * @return true, if vertical alignment is relative to baseline
* this is only used for older versions less equals Office 2003 * this is only used for older versions less equals Office 2003
*/ */
public boolean isAlignToBaseline() { public boolean isAlignToBaseline() {
getAlignment(); getAlignment();
@ -358,7 +359,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
this.alignToBaseline = alignToBaseline; this.alignToBaseline = alignToBaseline;
setAlignment(isHorizontalCentered(), getVerticalAlignment()); setAlignment(isHorizontalCentered(), getVerticalAlignment());
} }
@Override @Override
public boolean isHorizontalCentered() { public boolean isHorizontalCentered() {
int va = getAlignment(); int va = getAlignment();
@ -378,7 +379,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
public void setHorizontalCentered(Boolean isCentered) { public void setHorizontalCentered(Boolean isCentered) {
setAlignment(isCentered, getVerticalAlignment()); setAlignment(isCentered, getVerticalAlignment());
} }
@Override @Override
public VerticalAlignment getVerticalAlignment() { public VerticalAlignment getVerticalAlignment() {
int va = getAlignment(); int va = getAlignment();
@ -492,7 +493,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
* Returns the distance (in points) between the edge of the text frame * Returns the distance (in points) between the edge of the text frame
* and the edge of the inscribed rectangle of the shape that contains the text. * and the edge of the inscribed rectangle of the shape that contains the text.
* Default value is 1/20 inch. * Default value is 1/20 inch.
* *
* @param propId the id of the inset edge * @param propId the id of the inset edge
* @return the inset in points * @return the inset in points
*/ */
@ -500,7 +501,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
AbstractEscherOptRecord opt = getEscherOptRecord(); AbstractEscherOptRecord opt = getEscherOptRecord();
EscherSimpleProperty prop = getEscherProperty(opt, propId); EscherSimpleProperty prop = getEscherProperty(opt, propId);
int val = prop == null ? (int)(Units.toEMU(Units.POINT_DPI)*defaultInch) : prop.getPropertyValue(); int val = prop == null ? (int)(Units.toEMU(Units.POINT_DPI)*defaultInch) : prop.getPropertyValue();
return Units.toPoints(val); return Units.toPoints(val);
} }
/** /**
@ -509,8 +510,8 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
*/ */
private void setInset(short propId, double margin){ private void setInset(short propId, double margin){
setEscherProperty(propId, Units.toEMU(margin)); setEscherProperty(propId, Units.toEMU(margin));
} }
/** /**
* Returns the value indicating word wrap. * Returns the value indicating word wrap.
* *
@ -524,7 +525,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT); EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
return prop == null ? WrapSquare : prop.getPropertyValue(); return prop == null ? WrapSquare : prop.getPropertyValue();
} }
/** /**
* Specifies how the text should be wrapped * Specifies how the text should be wrapped
* *
@ -545,7 +546,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
public void setWordWrap(boolean wrap) { public void setWordWrap(boolean wrap) {
setWordWrapEx(wrap ? WrapSquare : WrapNone); setWordWrapEx(wrap ? WrapSquare : WrapNone);
} }
/** /**
* @return id for the text. * @return id for the text.
*/ */
@ -567,7 +568,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
@Override @Override
public List<HSLFTextParagraph> getTextParagraphs(){ public List<HSLFTextParagraph> getTextParagraphs(){
if (!_paragraphs.isEmpty()) return _paragraphs; if (!_paragraphs.isEmpty()) return _paragraphs;
_txtbox = getEscherTextboxWrapper(); _txtbox = getEscherTextboxWrapper();
if (_txtbox == null) { if (_txtbox == null) {
_paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph()); _paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph());
@ -578,7 +579,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
// there are actually TextBoxRecords without extra data - see #54722 // there are actually TextBoxRecords without extra data - see #54722
_paragraphs = HSLFTextParagraph.createEmptyParagraph(_txtbox); _paragraphs = HSLFTextParagraph.createEmptyParagraph(_txtbox);
} }
if (_paragraphs.isEmpty()) { if (_paragraphs.isEmpty()) {
logger.log(POILogger.WARN, "TextRecord didn't contained any text lines"); logger.log(POILogger.WARN, "TextRecord didn't contained any text lines");
} }
@ -594,7 +595,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
for (HSLFTextParagraph p : _paragraphs) { for (HSLFTextParagraph p : _paragraphs) {
p.setParentShape(this); p.setParentShape(this);
} }
return _paragraphs; return _paragraphs;
} }
@ -675,7 +676,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
// them to \n // them to \n
String text = rawText.replace('\r','\n').replace('\u000b', replChr); String text = rawText.replace('\r','\n').replace('\u000b', replChr);
*/ */
/** /**
* Return <code>OEPlaceholderAtom</code>, the atom that describes a placeholder. * Return <code>OEPlaceholderAtom</code>, the atom that describes a placeholder.
* *
@ -777,13 +778,13 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
return HSLFTextParagraph.toExternalString(rawText, getRunType()); return HSLFTextParagraph.toExternalString(rawText, getRunType());
} }
// Update methods follow // Update methods follow
/** /**
* Adds the supplied text onto the end of the TextParagraphs, * Adds the supplied text onto the end of the TextParagraphs,
* creating a new RichTextRun for it to sit in. * creating a new RichTextRun for it to sit in.
* *
* @param text the text string used by this object. * @param text the text string used by this object.
*/ */
public HSLFTextRun appendText(String text, boolean newParagraph) { public HSLFTextRun appendText(String text, boolean newParagraph) {
@ -800,7 +801,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
setTextId(text.hashCode()); setTextId(text.hashCode());
return htr; return htr;
} }
/** /**
* Saves the modified paragraphs/textrun to the records. * Saves the modified paragraphs/textrun to the records.
* Also updates the styles to the correct text length. * Also updates the styles to the correct text length.
@ -813,7 +814,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
/** /**
* Returns the array of all hyperlinks in this text run * Returns the array of all hyperlinks in this text run
* *
* @return the array of all hyperlinks in this text run or <code>null</code> * @return the array of all hyperlinks in this text run or <code>null</code>
* if not found. * if not found.
*/ */
@ -880,5 +881,15 @@ 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();
}
} }

Binary file not shown.