fixed HSLF text handling
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1677496 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f0d95c3f8d
commit
02e70fdbfe
@ -490,27 +490,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
|
|||||||
tabStops.addNewTab().setPos(Units.toEMU(value));
|
tabStops.addNewTab().setPos(Units.toEMU(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* This element specifies the vertical line spacing that is to be used within a paragraph.
|
|
||||||
* This may be specified in two different ways, percentage spacing and font point spacing:
|
|
||||||
* <p>
|
|
||||||
* If linespacing >= 0, then linespacing is a percentage of normal line height
|
|
||||||
* If linespacing < 0, the absolute value of linespacing is the spacing in points
|
|
||||||
* </p>
|
|
||||||
* Examples:
|
|
||||||
* <pre><code>
|
|
||||||
* // spacing will be 120% of the size of the largest text on each line
|
|
||||||
* paragraph.setLineSpacing(120);
|
|
||||||
*
|
|
||||||
* // spacing will be 200% of the size of the largest text on each line
|
|
||||||
* paragraph.setLineSpacing(200);
|
|
||||||
*
|
|
||||||
* // spacing will be 48 points
|
|
||||||
* paragraph.setLineSpacing(-48.0);
|
|
||||||
* </code></pre>
|
|
||||||
*
|
|
||||||
* @param linespacing the vertical line spacing
|
|
||||||
*/
|
|
||||||
public void setLineSpacing(double linespacing){
|
public void setLineSpacing(double linespacing){
|
||||||
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
|
||||||
CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
|
CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
|
||||||
@ -519,16 +499,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
|
|||||||
pr.setLnSpc(spc);
|
pr.setLnSpc(spc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns the vertical line spacing that is to be used within a paragraph.
|
|
||||||
* This may be specified in two different ways, percentage spacing and font point spacing:
|
|
||||||
* <p>
|
|
||||||
* If linespacing >= 0, then linespacing is a percentage of normal line height.
|
|
||||||
* If linespacing < 0, the absolute value of linespacing is the spacing in points
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return the vertical line spacing.
|
|
||||||
*/
|
|
||||||
public double getLineSpacing(){
|
public double getLineSpacing(){
|
||||||
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
|
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
|
||||||
public boolean fetch(CTTextParagraphProperties props){
|
public boolean fetch(CTTextParagraphProperties props){
|
||||||
|
@ -82,13 +82,9 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
|
|||||||
* Set the true/false status of the subproperty with the given index
|
* Set the true/false status of the subproperty with the given index
|
||||||
*/
|
*/
|
||||||
public void setSubValue(boolean value, int idx) {
|
public void setSubValue(boolean value, int idx) {
|
||||||
if(subPropMatches[idx] == value) { return; }
|
if (subPropMatches[idx] == value) return;
|
||||||
if(value) {
|
|
||||||
dataValue += subPropMasks[idx];
|
|
||||||
} else {
|
|
||||||
dataValue -= subPropMasks[idx];
|
|
||||||
}
|
|
||||||
subPropMatches[idx] = value;
|
subPropMatches[idx] = value;
|
||||||
|
dataValue ^= subPropMasks[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,4 +97,8 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
|
|||||||
|
|
||||||
return newObj;
|
return newObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BitMaskTextProp cloneAll(){
|
||||||
|
return (BitMaskTextProp)super.clone();
|
||||||
|
}
|
||||||
}
|
}
|
@ -160,14 +160,9 @@ public class TextPropCollection {
|
|||||||
this.reservedField = other.reservedField;
|
this.reservedField = other.reservedField;
|
||||||
this.textPropList.clear();
|
this.textPropList.clear();
|
||||||
for (TextProp tp : other.textPropList) {
|
for (TextProp tp : other.textPropList) {
|
||||||
TextProp tpCopy = tp.clone();
|
TextProp tpCopy = (tp instanceof BitMaskTextProp)
|
||||||
if (tpCopy instanceof BitMaskTextProp) {
|
? ((BitMaskTextProp)tp).cloneAll()
|
||||||
BitMaskTextProp bmt = (BitMaskTextProp)tpCopy;
|
: tp.clone();
|
||||||
boolean matches[] = ((BitMaskTextProp)tp).getSubPropMatches();
|
|
||||||
for (int i=0; i<matches.length; i++) {
|
|
||||||
bmt.setSubValue(matches[i], i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.textPropList.add(tpCopy);
|
this.textPropList.add(tpCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,7 +178,7 @@ public class TextPropCollection {
|
|||||||
/**
|
/**
|
||||||
* Writes out to disk the header, and then all the properties
|
* Writes out to disk the header, and then all the properties
|
||||||
*/
|
*/
|
||||||
public void writeOut(OutputStream o) throws IOException {
|
public void writeOut(OutputStream o, TextProp[] potentialProperties) throws IOException {
|
||||||
// First goes the number of characters we affect
|
// First goes the number of characters we affect
|
||||||
StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
|
StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
|
||||||
|
|
||||||
@ -194,10 +189,8 @@ public class TextPropCollection {
|
|||||||
|
|
||||||
// Then the mask field
|
// Then the mask field
|
||||||
int mask = maskSpecial;
|
int mask = maskSpecial;
|
||||||
for(int i=0; i<textPropList.size(); i++) {
|
for(TextProp textProp : textPropList) {
|
||||||
TextProp textProp = textPropList.get(i);
|
|
||||||
//sometimes header indicates that the bitmask is present but its value is 0
|
//sometimes header indicates that the bitmask is present but its value is 0
|
||||||
|
|
||||||
if (textProp instanceof BitMaskTextProp) {
|
if (textProp instanceof BitMaskTextProp) {
|
||||||
if(mask == 0) mask |= textProp.getWriteMask();
|
if(mask == 0) mask |= textProp.getWriteMask();
|
||||||
}
|
}
|
||||||
@ -208,16 +201,21 @@ public class TextPropCollection {
|
|||||||
StyleTextPropAtom.writeLittleEndian(mask,o);
|
StyleTextPropAtom.writeLittleEndian(mask,o);
|
||||||
|
|
||||||
// Then the contents of all the properties
|
// Then the contents of all the properties
|
||||||
for(int i=0; i<textPropList.size(); i++) {
|
for (TextProp potProp : potentialProperties) {
|
||||||
TextProp textProp = textPropList.get(i);
|
for(TextProp textProp : textPropList) {
|
||||||
|
if (!textProp.getName().equals(potProp.getName())) continue;
|
||||||
int val = textProp.getValue();
|
int val = textProp.getValue();
|
||||||
if(textProp.getSize() == 2) {
|
if (textProp instanceof BitMaskTextProp && val == 0) {
|
||||||
|
// don't add empty properties, as they can't be recognized while reading
|
||||||
|
continue;
|
||||||
|
} else if (textProp.getSize() == 2) {
|
||||||
StyleTextPropAtom.writeLittleEndian((short)val,o);
|
StyleTextPropAtom.writeLittleEndian((short)val,o);
|
||||||
} else if (textProp.getSize() == 4) {
|
} else if (textProp.getSize() == 4) {
|
||||||
StyleTextPropAtom.writeLittleEndian(val,o);
|
StyleTextPropAtom.writeLittleEndian(val,o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public short getReservedField(){
|
public short getReservedField(){
|
||||||
return reservedField;
|
return reservedField;
|
||||||
|
@ -17,15 +17,12 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.record;
|
package org.apache.poi.hslf.record;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
import java.util.ArrayList;
|
||||||
import java.io.OutputStream;
|
import java.util.List;
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
import org.apache.poi.hslf.model.textproperties.*;
|
import org.apache.poi.hslf.model.textproperties.*;
|
||||||
import org.apache.poi.util.HexDump;
|
import org.apache.poi.util.*;
|
||||||
import org.apache.poi.util.LittleEndian;
|
|
||||||
import org.apache.poi.util.POILogger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A StyleTextPropAtom (type 4001). Holds basic character properties
|
* A StyleTextPropAtom (type 4001). Holds basic character properties
|
||||||
@ -64,26 +61,26 @@ public final class StyleTextPropAtom extends RecordAtom
|
|||||||
* Characters the paragraph covers, and also contains the TextProps
|
* Characters the paragraph covers, and also contains the TextProps
|
||||||
* that actually define the styling of the paragraph.
|
* that actually define the styling of the paragraph.
|
||||||
*/
|
*/
|
||||||
private LinkedList<TextPropCollection> paragraphStyles;
|
private List<TextPropCollection> paragraphStyles;
|
||||||
public LinkedList<TextPropCollection> getParagraphStyles() { return paragraphStyles; }
|
public List<TextPropCollection> getParagraphStyles() { return paragraphStyles; }
|
||||||
/**
|
/**
|
||||||
* Updates the link list of TextPropCollections which make up the
|
* Updates the link list of TextPropCollections which make up the
|
||||||
* paragraph stylings
|
* paragraph stylings
|
||||||
*/
|
*/
|
||||||
public void setParagraphStyles(LinkedList<TextPropCollection> ps) { paragraphStyles = ps; }
|
public void setParagraphStyles(List<TextPropCollection> ps) { paragraphStyles = ps; }
|
||||||
/**
|
/**
|
||||||
* The list of all the different character stylings we code for.
|
* The list of all the different character stylings we code for.
|
||||||
* Each entry is a TextPropCollection, which tells you how many
|
* Each entry is a TextPropCollection, which tells you how many
|
||||||
* Characters the character styling covers, and also contains the
|
* Characters the character styling covers, and also contains the
|
||||||
* TextProps that actually define the styling of the characters.
|
* TextProps that actually define the styling of the characters.
|
||||||
*/
|
*/
|
||||||
private LinkedList<TextPropCollection> charStyles;
|
private List<TextPropCollection> charStyles;
|
||||||
public LinkedList<TextPropCollection> getCharacterStyles() { return charStyles; }
|
public List<TextPropCollection> getCharacterStyles() { return charStyles; }
|
||||||
/**
|
/**
|
||||||
* Updates the link list of TextPropCollections which make up the
|
* Updates the link list of TextPropCollections which make up the
|
||||||
* character stylings
|
* character stylings
|
||||||
*/
|
*/
|
||||||
public void setCharacterStyles(LinkedList<TextPropCollection> cs) { charStyles = cs; }
|
public void setCharacterStyles(List<TextPropCollection> cs) { charStyles = cs; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns how many characters the paragraph's
|
* Returns how many characters the paragraph's
|
||||||
@ -105,7 +102,7 @@ public final class StyleTextPropAtom extends RecordAtom
|
|||||||
public int getCharacterTextLengthCovered() {
|
public int getCharacterTextLengthCovered() {
|
||||||
return getCharactersCovered(charStyles);
|
return getCharactersCovered(charStyles);
|
||||||
}
|
}
|
||||||
private int getCharactersCovered(LinkedList<TextPropCollection> styles) {
|
private int getCharactersCovered(List<TextPropCollection> styles) {
|
||||||
int length = 0;
|
int length = 0;
|
||||||
for(TextPropCollection tpc : styles) {
|
for(TextPropCollection tpc : styles) {
|
||||||
length += tpc.getCharactersCovered();
|
length += tpc.getCharactersCovered();
|
||||||
@ -197,9 +194,9 @@ public final class StyleTextPropAtom extends RecordAtom
|
|||||||
System.arraycopy(source,start+8,rawContents,0,rawContents.length);
|
System.arraycopy(source,start+8,rawContents,0,rawContents.length);
|
||||||
reserved = new byte[0];
|
reserved = new byte[0];
|
||||||
|
|
||||||
// Set empty linked lists, ready for when they call setParentTextSize
|
// Set empty lists, ready for when they call setParentTextSize
|
||||||
paragraphStyles = new LinkedList<TextPropCollection>();
|
paragraphStyles = new ArrayList<TextPropCollection>();
|
||||||
charStyles = new LinkedList<TextPropCollection>();
|
charStyles = new ArrayList<TextPropCollection>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -217,8 +214,8 @@ public final class StyleTextPropAtom extends RecordAtom
|
|||||||
LittleEndian.putInt(_header,4,10);
|
LittleEndian.putInt(_header,4,10);
|
||||||
|
|
||||||
// Set empty paragraph and character styles
|
// Set empty paragraph and character styles
|
||||||
paragraphStyles = new LinkedList<TextPropCollection>();
|
paragraphStyles = new ArrayList<TextPropCollection>();
|
||||||
charStyles = new LinkedList<TextPropCollection>();
|
charStyles = new ArrayList<TextPropCollection>();
|
||||||
|
|
||||||
TextPropCollection defaultParagraphTextProps =
|
TextPropCollection defaultParagraphTextProps =
|
||||||
new TextPropCollection(parentTextSize, (short)0);
|
new TextPropCollection(parentTextSize, (short)0);
|
||||||
@ -377,13 +374,13 @@ public final class StyleTextPropAtom extends RecordAtom
|
|||||||
// First up, we need to serialise the paragraph properties
|
// First up, we need to serialise the paragraph properties
|
||||||
for(int i=0; i<paragraphStyles.size(); i++) {
|
for(int i=0; i<paragraphStyles.size(); i++) {
|
||||||
TextPropCollection tpc = paragraphStyles.get(i);
|
TextPropCollection tpc = paragraphStyles.get(i);
|
||||||
tpc.writeOut(baos);
|
tpc.writeOut(baos, paragraphTextPropTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, we do the character ones
|
// Now, we do the character ones
|
||||||
for(int i=0; i<charStyles.size(); i++) {
|
for(int i=0; i<charStyles.size(); i++) {
|
||||||
TextPropCollection tpc = charStyles.get(i);
|
TextPropCollection tpc = charStyles.get(i);
|
||||||
tpc.writeOut(baos);
|
tpc.writeOut(baos, characterTextPropTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
rawContents = baos.toByteArray();
|
rawContents = baos.toByteArray();
|
||||||
@ -454,7 +451,7 @@ public final class StyleTextPropAtom extends RecordAtom
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
pr.writeOut(baos);
|
pr.writeOut(baos, paragraphTextPropTypes);
|
||||||
byte[] b = baos.toByteArray();
|
byte[] b = baos.toByteArray();
|
||||||
out.append(HexDump.dump(b, 0, 0));
|
out.append(HexDump.dump(b, 0, 0));
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
@ -475,7 +472,7 @@ public final class StyleTextPropAtom extends RecordAtom
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
pr.writeOut(baos);
|
pr.writeOut(baos, characterTextPropTypes);
|
||||||
byte[] b = baos.toByteArray();
|
byte[] b = baos.toByteArray();
|
||||||
out.append(HexDump.dump(b, 0, 0));
|
out.append(HexDump.dump(b, 0, 0));
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
|
@ -270,7 +270,6 @@ public abstract class HSLFSheet implements Sheet<HSLFShape,HSLFSlideShow> {
|
|||||||
* @param shape
|
* @param shape
|
||||||
*/
|
*/
|
||||||
protected void onAddTextShape(HSLFTextShape shape) {
|
protected void onAddTextShape(HSLFTextShape shape) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -553,30 +553,22 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
return getParaTextPropVal("bullet.font");
|
return getParaTextPropVal("bullet.font");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the line spacing.
|
public void setLineSpacing(double lineSpacing) {
|
||||||
* <p>
|
// if lineSpacing < 0, we need to convert points (common interface) to master units (hslf)
|
||||||
* If linespacing >= 0, then linespacing is a percentage of normal line height.
|
if (lineSpacing < 0) {
|
||||||
* If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates.
|
lineSpacing = (lineSpacing*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);
|
||||||
* </p>
|
}
|
||||||
*/
|
setParaTextPropVal("linespacing", (int)lineSpacing);
|
||||||
public void setLineSpacing(int val) {
|
|
||||||
setParaTextPropVal("linespacing", val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the line spacing
|
|
||||||
* <p>
|
|
||||||
* If linespacing >= 0, then linespacing is a percentage of normal line height.
|
|
||||||
* If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return the spacing between lines
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public double getLineSpacing() {
|
public double getLineSpacing() {
|
||||||
int val = getParaTextPropVal("linespacing");
|
double val = getParaTextPropVal("linespacing");
|
||||||
return val == -1 ? 0 : val;
|
// if lineSpacing < 0, we need to convert master units (hslf) to points (common interface)
|
||||||
|
if (val == -1) return 0;
|
||||||
|
if (val < -1) val *= HSLFShape.POINT_DPI/((double)HSLFShape.MASTER_DPI);
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -722,6 +714,12 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
throw new RuntimeException("child record not found - malformed container record");
|
throw new RuntimeException("child record not found - malformed container record");
|
||||||
}
|
}
|
||||||
cr[idx] = newRecord;
|
cr[idx] = newRecord;
|
||||||
|
|
||||||
|
if (newRecord == byteAtom) {
|
||||||
|
charAtom = null;
|
||||||
|
} else {
|
||||||
|
byteAtom = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure a StyleTextPropAtom is present, adding if required
|
// Ensure a StyleTextPropAtom is present, adding if required
|
||||||
@ -750,6 +748,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
}
|
}
|
||||||
for (HSLFTextRun tr : para.getTextRuns()) {
|
for (HSLFTextRun tr : para.getTextRuns()) {
|
||||||
TextPropCollection rtpc = tr.getCharacterStyle();
|
TextPropCollection rtpc = tr.getCharacterStyle();
|
||||||
|
rtpc.updateTextSize(0);
|
||||||
if (!rtpc.equals(lastRTPC)) {
|
if (!rtpc.equals(lastRTPC)) {
|
||||||
lastRTPC = styleAtom.addCharacterTextPropCollection(0);
|
lastRTPC = styleAtom.addCharacterTextPropCollection(0);
|
||||||
lastRTPC.copy(rtpc);
|
lastRTPC.copy(rtpc);
|
||||||
@ -783,20 +782,44 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
*
|
*
|
||||||
* @param text the text string used by this object.
|
* @param text the text string used by this object.
|
||||||
*/
|
*/
|
||||||
protected static void appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {
|
protected static HSLFTextRun appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {
|
||||||
text = toInternalString(text);
|
text = toInternalString(text);
|
||||||
|
|
||||||
// init paragraphs
|
// check paragraphs
|
||||||
assert(!paragraphs.isEmpty());
|
assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());
|
||||||
|
|
||||||
HSLFTextParagraph lastHTP = paragraphs.get(paragraphs.size()-1);
|
HSLFTextParagraph htp = paragraphs.get(paragraphs.size()-1);
|
||||||
HSLFTextRun lastHTR = lastHTP.getTextRuns().get(lastHTP.getTextRuns().size()-1);
|
HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size()-1);
|
||||||
HSLFTextParagraph htp = (newParagraph) ? new HSLFTextParagraph(lastHTP) : lastHTP;
|
|
||||||
HSLFTextRun htr = new HSLFTextRun(htp);
|
if (newParagraph) {
|
||||||
htr.setText(text);
|
htr.setText(htr.getRawText()+"\n");
|
||||||
htr.getCharacterStyle().copy(lastHTR.getCharacterStyle());
|
}
|
||||||
|
|
||||||
|
boolean isFirst = !newParagraph;
|
||||||
|
for (String rawText : text.split("(?<=\r)")) {
|
||||||
|
if (!isFirst) {
|
||||||
|
TextPropCollection tpc = htp.getParagraphStyle();
|
||||||
|
HSLFTextParagraph prevHtp = htp;
|
||||||
|
htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom, htp._styleAtom);
|
||||||
|
htp.getParagraphStyle().copy(tpc);
|
||||||
|
htp.setParentShape(prevHtp.getParentShape());
|
||||||
|
htp.setShapeId(prevHtp.getShapeId());
|
||||||
|
htp.supplySheet(prevHtp.getSheet());
|
||||||
|
paragraphs.add(htp);
|
||||||
|
isFirst = false;
|
||||||
|
}
|
||||||
|
TextPropCollection tpc = htr.getCharacterStyle();
|
||||||
|
// special case, last text run is empty, we will reuse it
|
||||||
|
if (htr.getLength() > 0) {
|
||||||
|
htr = new HSLFTextRun(htp);
|
||||||
|
htr.getCharacterStyle().copy(tpc);
|
||||||
htp.addTextRun(htr);
|
htp.addTextRun(htr);
|
||||||
}
|
}
|
||||||
|
htr.setText(rawText);
|
||||||
|
}
|
||||||
|
|
||||||
|
return htr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets (overwrites) the current text.
|
* Sets (overwrites) the current text.
|
||||||
@ -804,29 +827,30 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
*
|
*
|
||||||
* @param text the text string used by this object.
|
* @param text the text string used by this object.
|
||||||
*/
|
*/
|
||||||
public static void setText(List<HSLFTextParagraph> paragraphs, String text) {
|
public static HSLFTextRun setText(List<HSLFTextParagraph> paragraphs, String text) {
|
||||||
text = HSLFTextParagraph.toInternalString(text);
|
text = HSLFTextParagraph.toInternalString(text);
|
||||||
|
|
||||||
// init paragraphs
|
// check paragraphs
|
||||||
assert(!paragraphs.isEmpty());
|
assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());
|
||||||
|
|
||||||
Iterator<HSLFTextParagraph> paraIter = paragraphs.iterator();
|
Iterator<HSLFTextParagraph> paraIter = paragraphs.iterator();
|
||||||
HSLFTextParagraph firstHTP = paraIter.next(); // keep first
|
HSLFTextParagraph htp = paraIter.next(); // keep first
|
||||||
assert(firstHTP != null);
|
assert(htp != null);
|
||||||
while (paraIter.hasNext()) {
|
while (paraIter.hasNext()) {
|
||||||
paraIter.next();
|
paraIter.next();
|
||||||
paraIter.remove();
|
paraIter.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<HSLFTextRun> runIter = firstHTP.getTextRuns().iterator();
|
Iterator<HSLFTextRun> runIter = htp.getTextRuns().iterator();
|
||||||
HSLFTextRun firstHTR = runIter.next();
|
HSLFTextRun htr = runIter.next();
|
||||||
assert(firstHTR != null);
|
htr.setText("");
|
||||||
|
assert(htr != null);
|
||||||
while (runIter.hasNext()) {
|
while (runIter.hasNext()) {
|
||||||
runIter.next();
|
runIter.next();
|
||||||
runIter.remove();
|
runIter.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
firstHTR.setText(text);
|
return appendText(paragraphs, text, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getRawText(List<HSLFTextParagraph> paragraphs) {
|
public static String getRawText(List<HSLFTextParagraph> paragraphs) {
|
||||||
@ -835,9 +859,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
for (HSLFTextRun r : p.getTextRuns()) {
|
for (HSLFTextRun r : p.getTextRuns()) {
|
||||||
sb.append(r.getRawText());
|
sb.append(r.getRawText());
|
||||||
}
|
}
|
||||||
sb.append("\r");
|
|
||||||
}
|
}
|
||||||
sb.deleteCharAt(sb.length()-1); // remove last line break
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,7 +969,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
return paragraphCollection;
|
return paragraphCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int slwtIndex = 0; recordIdx < records.length-2; slwtIndex++) {
|
for (int slwtIndex = 0; recordIdx < records.length; slwtIndex++) {
|
||||||
List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>();
|
List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>();
|
||||||
paragraphCollection.add(paragraphs);
|
paragraphCollection.add(paragraphs);
|
||||||
|
|
||||||
@ -985,12 +1007,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
|
|
||||||
if (tbytes == null && tchars == null) {
|
if (tbytes == null && tchars == null) {
|
||||||
tbytes = new TextBytesAtom();
|
tbytes = new TextBytesAtom();
|
||||||
|
header.getParentRecord().addChildAfter(tbytes, header);
|
||||||
logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving.");
|
logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving.");
|
||||||
}
|
}
|
||||||
|
|
||||||
String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();
|
String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();
|
||||||
|
|
||||||
for (String para : rawText.split("\r")) {
|
// split, but keep delimiter
|
||||||
|
for (String para : rawText.split("(?<=\r)")) {
|
||||||
HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles);
|
HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles);
|
||||||
paragraphs.add(tpara);
|
paragraphs.add(tpara);
|
||||||
tpara.setStyleTextProp9Atom(styleTextProp9Atom);
|
tpara.setStyleTextProp9Atom(styleTextProp9Atom);
|
||||||
@ -1021,29 +1045,21 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
|
|
||||||
protected static void applyCharacterStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> charStyles) {
|
protected static void applyCharacterStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> charStyles) {
|
||||||
int paraIdx = 0, runIdx = 0;
|
int paraIdx = 0, runIdx = 0;
|
||||||
for (TextPropCollection p : charStyles) {
|
HSLFTextRun trun;
|
||||||
|
|
||||||
|
for (int csIdx=0; csIdx<charStyles.size(); csIdx++) {
|
||||||
|
TextPropCollection p = charStyles.get(csIdx);
|
||||||
for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle; ) {
|
for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle; ) {
|
||||||
HSLFTextParagraph para = paragraphs.get(paraIdx);
|
HSLFTextParagraph para = paragraphs.get(paraIdx);
|
||||||
List<HSLFTextRun> runs = para.getTextRuns();
|
List<HSLFTextRun> runs = para.getTextRuns();
|
||||||
HSLFTextRun trun = runs.get(runIdx);
|
trun = runs.get(runIdx);
|
||||||
int len = trun.getLength();
|
int len = trun.getLength();
|
||||||
|
|
||||||
if (runIdx+1 >= runs.size()) {
|
|
||||||
// need to add +1 to the last run of the paragraph
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextPropCollection pCopy = new TextPropCollection(1);
|
|
||||||
pCopy.copy(p);
|
|
||||||
if (ccRun+len <= ccStyle) {
|
if (ccRun+len <= ccStyle) {
|
||||||
trun.setCharacterStyle(pCopy);
|
|
||||||
pCopy.updateTextSize(len);
|
|
||||||
ccRun += len;
|
ccRun += len;
|
||||||
} else {
|
} else {
|
||||||
String text = trun.getRawText();
|
String text = trun.getRawText();
|
||||||
trun.setText(text.substring(0,ccStyle-ccRun));
|
trun.setText(text.substring(0,ccStyle-ccRun));
|
||||||
pCopy.updateTextSize(ccStyle-ccRun);
|
|
||||||
trun.setCharacterStyle(pCopy);
|
|
||||||
|
|
||||||
HSLFTextRun nextRun = new HSLFTextRun(para);
|
HSLFTextRun nextRun = new HSLFTextRun(para);
|
||||||
nextRun.setText(text.substring(ccStyle-ccRun));
|
nextRun.setText(text.substring(ccStyle-ccRun));
|
||||||
@ -1052,8 +1068,27 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
ccRun += ccStyle-ccRun;
|
ccRun += ccStyle-ccRun;
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to compare it again, in case a run has been added afer
|
TextPropCollection pCopy = new TextPropCollection(0);
|
||||||
if (++runIdx >= runs.size()) {
|
pCopy.copy(p);
|
||||||
|
trun.setCharacterStyle(pCopy);
|
||||||
|
|
||||||
|
len = trun.getLength();
|
||||||
|
if (paraIdx == paragraphs.size()-1 && runIdx == runs.size()-1) {
|
||||||
|
if (csIdx < charStyles.size()-1) {
|
||||||
|
// special case, empty trailing text run
|
||||||
|
HSLFTextRun nextRun = new HSLFTextRun(para);
|
||||||
|
nextRun.setText("");
|
||||||
|
runs.add(nextRun);
|
||||||
|
} else {
|
||||||
|
// need to add +1 to the last run of the last paragraph
|
||||||
|
len++;
|
||||||
|
ccRun++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pCopy.updateTextSize(len);
|
||||||
|
|
||||||
|
// need to compare it again, in case a run has been added after
|
||||||
|
if (++runIdx == runs.size()) {
|
||||||
paraIdx++;
|
paraIdx++;
|
||||||
runIdx = 0;
|
runIdx = 0;
|
||||||
}
|
}
|
||||||
@ -1065,16 +1100,18 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
int paraIdx = 0;
|
int paraIdx = 0;
|
||||||
for (TextPropCollection p : paraStyles) {
|
for (TextPropCollection p : paraStyles) {
|
||||||
for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) {
|
for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) {
|
||||||
HSLFTextParagraph para = paragraphs.get(paraIdx);
|
if (paraIdx >= paragraphs.size() || ccPara >= ccStyle-1) return;
|
||||||
TextPropCollection pCopy = new TextPropCollection(1);
|
HSLFTextParagraph htp = paragraphs.get(paraIdx);
|
||||||
|
TextPropCollection pCopy = new TextPropCollection(0);
|
||||||
pCopy.copy(p);
|
pCopy.copy(p);
|
||||||
|
htp.setParagraphStyle(pCopy);
|
||||||
int len = 0;
|
int len = 0;
|
||||||
for (HSLFTextRun trun : para.getTextRuns()) {
|
for (HSLFTextRun trun : htp.getTextRuns()) {
|
||||||
len += trun.getLength();
|
len += trun.getLength();
|
||||||
}
|
}
|
||||||
pCopy.updateTextSize(len+1);
|
if (paraIdx == paragraphs.size()-1) len++;
|
||||||
para.setParagraphStyle(pCopy);
|
pCopy.updateTextSize(len);
|
||||||
ccPara += len+1;
|
ccPara += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1101,15 +1138,28 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
tha.setParentRecord(wrapper);
|
tha.setParentRecord(wrapper);
|
||||||
wrapper.appendChildRecord(tha);
|
wrapper.appendChildRecord(tha);
|
||||||
|
|
||||||
TextCharsAtom tca = new TextCharsAtom();
|
TextBytesAtom tba = new TextBytesAtom();
|
||||||
wrapper.appendChildRecord(tca);
|
tba.setText("\r".getBytes());
|
||||||
|
wrapper.appendChildRecord(tba);
|
||||||
|
|
||||||
StyleTextPropAtom sta = new StyleTextPropAtom(0);
|
StyleTextPropAtom sta = new StyleTextPropAtom(1);
|
||||||
|
TextPropCollection paraStyle = sta.addParagraphTextPropCollection(1);
|
||||||
|
TextPropCollection charStyle = sta.addCharacterTextPropCollection(1);
|
||||||
wrapper.appendChildRecord(sta);
|
wrapper.appendChildRecord(sta);
|
||||||
|
|
||||||
HSLFTextParagraph htp = new HSLFTextParagraph(tha, null, tca, sta);
|
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta);
|
||||||
|
htp.setParagraphStyle(paraStyle);
|
||||||
htp._records = new Record[0];
|
htp._records = new Record[0];
|
||||||
|
htp.setBullet(false);
|
||||||
|
htp.setLineSpacing(100);
|
||||||
|
htp.setLeftMargin(0);
|
||||||
|
htp.setIndent(0);
|
||||||
|
// set wrap flags
|
||||||
|
|
||||||
HSLFTextRun htr = new HSLFTextRun(htp);
|
HSLFTextRun htr = new HSLFTextRun(htp);
|
||||||
|
htr.setCharacterStyle(charStyle);
|
||||||
|
htr.setText("\r");
|
||||||
|
htr.setFontColor(Color.black);
|
||||||
htp.addTextRun(htr);
|
htp.addTextRun(htr);
|
||||||
|
|
||||||
return Arrays.asList(htp);
|
return Arrays.asList(htp);
|
||||||
|
@ -37,14 +37,14 @@ public final class HSLFTextRun implements TextRun {
|
|||||||
|
|
||||||
/** The TextRun we belong to */
|
/** The TextRun we belong to */
|
||||||
private HSLFTextParagraph parentParagraph;
|
private HSLFTextParagraph parentParagraph;
|
||||||
private String _runText = "\r";
|
private String _runText = "";
|
||||||
private String _fontname;
|
private String _fontname;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Our paragraph and character style.
|
* Our paragraph and character style.
|
||||||
* Note - we may share these styles with other RichTextRuns
|
* Note - we may share these styles with other RichTextRuns
|
||||||
*/
|
*/
|
||||||
private TextPropCollection characterStyle = new TextPropCollection(1);
|
private TextPropCollection characterStyle = new TextPropCollection(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new wrapper around a rich text string
|
* Create a new wrapper around a rich text string
|
||||||
|
@ -22,14 +22,11 @@ import static org.apache.poi.hslf.record.RecordTypes.*;
|
|||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.font.FontRenderContext;
|
import java.awt.font.FontRenderContext;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.geom.Rectangle2D.Double;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.apache.poi.POIXMLException;
|
|
||||||
import org.apache.poi.ddf.*;
|
import org.apache.poi.ddf.*;
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
|
||||||
import org.apache.poi.hslf.record.*;
|
import org.apache.poi.hslf.record.*;
|
||||||
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;
|
||||||
@ -139,8 +136,12 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape
|
|||||||
protected void afterInsert(HSLFSheet sh){
|
protected void afterInsert(HSLFSheet sh){
|
||||||
super.afterInsert(sh);
|
super.afterInsert(sh);
|
||||||
|
|
||||||
|
storeText();
|
||||||
|
|
||||||
EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
|
EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
|
||||||
if(_txtbox != null){
|
if(_txtbox != null){
|
||||||
|
_escherContainer.addChildRecord(_txtbox.getEscherRecord());
|
||||||
|
|
||||||
PPDrawing ppdrawing = sh.getPPDrawing();
|
PPDrawing ppdrawing = sh.getPPDrawing();
|
||||||
ppdrawing.addTextboxWrapper(_txtbox);
|
ppdrawing.addTextboxWrapper(_txtbox);
|
||||||
// Ensure the escher layer knows about the added records
|
// Ensure the escher layer knows about the added records
|
||||||
@ -712,10 +713,10 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape
|
|||||||
*
|
*
|
||||||
* @param text the text string used by this object.
|
* @param text the text string used by this object.
|
||||||
*/
|
*/
|
||||||
public void appendText(String text, boolean newParagraph) {
|
public HSLFTextRun appendText(String text, boolean newParagraph) {
|
||||||
// init paragraphs
|
// init paragraphs
|
||||||
List<HSLFTextParagraph> paras = getTextParagraphs();
|
List<HSLFTextParagraph> paras = getTextParagraphs();
|
||||||
HSLFTextParagraph.appendText(paras, text, newParagraph);
|
return HSLFTextParagraph.appendText(paras, text, newParagraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -723,12 +724,15 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape
|
|||||||
* Uses the properties of the first paragraph / textrun
|
* Uses the properties of the first paragraph / textrun
|
||||||
*
|
*
|
||||||
* @param text the text string used by this object.
|
* @param text the text string used by this object.
|
||||||
|
*
|
||||||
|
* @return the last text run of the splitted text
|
||||||
*/
|
*/
|
||||||
public void setText(String text) {
|
public HSLFTextRun setText(String text) {
|
||||||
// init paragraphs
|
// init paragraphs
|
||||||
List<HSLFTextParagraph> paras = getTextParagraphs();
|
List<HSLFTextParagraph> paras = getTextParagraphs();
|
||||||
HSLFTextParagraph.setText(paras, text);
|
HSLFTextRun htr = HSLFTextParagraph.setText(paras, text);
|
||||||
setTextId(text.hashCode());
|
setTextId(text.hashCode());
|
||||||
|
return htr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,8 +104,8 @@ public class DrawTextShape<T extends TextShape<? extends TextParagraph<? extends
|
|||||||
// negative value means the absolute spacing in points
|
// negative value means the absolute spacing in points
|
||||||
y += -spaceBefore;
|
y += -spaceBefore;
|
||||||
}
|
}
|
||||||
isFirstLine = false;
|
|
||||||
}
|
}
|
||||||
|
isFirstLine = false;
|
||||||
|
|
||||||
dp.setPosition(x, y);
|
dp.setPosition(x, y);
|
||||||
dp.draw(graphics);
|
dp.draw(graphics);
|
||||||
|
@ -113,7 +113,7 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
|
|||||||
* This may be specified in two different ways, percentage spacing and font point spacing:
|
* This may be specified in two different ways, percentage spacing and font point spacing:
|
||||||
* <p>
|
* <p>
|
||||||
* If spaceBefore >= 0, then space is a percentage of normal line height.
|
* If spaceBefore >= 0, then space is a percentage of normal line height.
|
||||||
* If spaceBefore < 0, the absolute value of linespacing is the spacing in points
|
* If spaceBefore < 0, the absolute value in points
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @return the vertical white space before the paragraph
|
* @return the vertical white space before the paragraph
|
||||||
@ -175,6 +175,29 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
|
|||||||
*/
|
*/
|
||||||
double getLineSpacing();
|
double getLineSpacing();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This element specifies the vertical line spacing that is to be used within a paragraph.
|
||||||
|
* This may be specified in two different ways, percentage spacing and font point spacing:
|
||||||
|
* <p>
|
||||||
|
* If linespacing >= 0, then linespacing is a percentage of normal line height
|
||||||
|
* If linespacing < 0, the absolute value of linespacing is the spacing in points
|
||||||
|
* </p>
|
||||||
|
* Examples:
|
||||||
|
* <pre><code>
|
||||||
|
* // spacing will be 120% of the size of the largest text on each line
|
||||||
|
* paragraph.setLineSpacing(120);
|
||||||
|
*
|
||||||
|
* // spacing will be 200% of the size of the largest text on each line
|
||||||
|
* paragraph.setLineSpacing(200);
|
||||||
|
*
|
||||||
|
* // spacing will be 48 points
|
||||||
|
* paragraph.setLineSpacing(-48.0);
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* @param linespacing the vertical line spacing
|
||||||
|
*/
|
||||||
|
void setLineSpacing(double lineSpacing);
|
||||||
|
|
||||||
String getDefaultFontFamily();
|
String getDefaultFontFamily();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,8 @@ package org.apache.poi.hslf.model;
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.awt.geom.Rectangle2D.Double;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -136,6 +138,48 @@ public final class TestShapes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParagraphs() throws Exception {
|
||||||
|
HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
|
HSLFSlide slide = ppt.createSlide();
|
||||||
|
HSLFTextBox shape = new HSLFTextBox();
|
||||||
|
HSLFTextRun p1r1 = shape.setText("para 1 run 1. ");
|
||||||
|
HSLFTextRun p1r2 = shape.appendText("para 1 run 2.", false);
|
||||||
|
HSLFTextRun p2r1 = shape.appendText("para 2 run 1. ", true);
|
||||||
|
HSLFTextRun p2r2 = shape.appendText("para 2 run 2. ", false);
|
||||||
|
p1r1.setFontColor(Color.black);
|
||||||
|
p1r2.setFontColor(Color.red);
|
||||||
|
p2r1.setFontColor(Color.yellow);
|
||||||
|
p2r2.setStrikethrough(true);
|
||||||
|
// run 3 has same text properties as run 2 and will be merged when saving
|
||||||
|
HSLFTextRun p2r3 = shape.appendText("para 2 run 3.", false);
|
||||||
|
shape.setAnchor(new Rectangle2D.Double(100,100,100,10));
|
||||||
|
slide.addShape(shape);
|
||||||
|
shape.resizeToFitText();
|
||||||
|
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
ppt.write(bos);
|
||||||
|
|
||||||
|
ppt = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray()));
|
||||||
|
slide = ppt.getSlides().get(0);
|
||||||
|
HSLFTextBox tb = (HSLFTextBox)slide.getShapes().get(0);
|
||||||
|
List<HSLFTextParagraph> para = tb.getTextParagraphs();
|
||||||
|
HSLFTextRun tr = para.get(0).getTextRuns().get(0);
|
||||||
|
assertEquals("para 1 run 1. ", tr.getRawText());
|
||||||
|
assertEquals(Color.black, tr.getFontColor());
|
||||||
|
tr = para.get(0).getTextRuns().get(1);
|
||||||
|
assertEquals("para 1 run 2.\r", tr.getRawText());
|
||||||
|
assertEquals(Color.red, tr.getFontColor());
|
||||||
|
tr = para.get(1).getTextRuns().get(0);
|
||||||
|
assertEquals("para 2 run 1. ", tr.getRawText());
|
||||||
|
assertEquals(Color.yellow, tr.getFontColor());
|
||||||
|
tr = para.get(1).getTextRuns().get(1);
|
||||||
|
assertEquals("para 2 run 2. para 2 run 3.", tr.getRawText());
|
||||||
|
assertEquals(Color.black, tr.getFontColor());
|
||||||
|
assertTrue(tr.isStrikethrough());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that we can add TextBox shapes to a slide
|
* Verify that we can add TextBox shapes to a slide
|
||||||
* and set some of the style attributes
|
* and set some of the style attributes
|
||||||
@ -235,7 +279,11 @@ public final class TestShapes {
|
|||||||
for (HSLFShape sh : sld.getShapes()) {
|
for (HSLFShape sh : sld.getShapes()) {
|
||||||
if (sh instanceof HSLFTextShape){
|
if (sh instanceof HSLFTextShape){
|
||||||
HSLFTextShape tbox = (HSLFTextShape)sh;
|
HSLFTextShape tbox = (HSLFTextShape)sh;
|
||||||
lst2.add(tbox.getText());
|
for (HSLFTextParagraph p : tbox.getTextParagraphs()) {
|
||||||
|
for (HSLFTextRun r : p) {
|
||||||
|
lst2.add(r.getRawText());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertTrue(lst1.containsAll(lst2));
|
assertTrue(lst1.containsAll(lst2));
|
||||||
|
Loading…
Reference in New Issue
Block a user