tabStops.addNewTab().setPos(Units.toEMU(value));\r
}\r
\r
- /**\r
- * This element specifies the vertical line spacing that is to be used within a paragraph.\r
- * This may be specified in two different ways, percentage spacing and font point spacing:\r
- * <p>\r
- * If linespacing >= 0, then linespacing is a percentage of normal line height\r
- * If linespacing < 0, the absolute value of linespacing is the spacing in points\r
- * </p>\r
- * Examples:\r
- * <pre><code>\r
- * // spacing will be 120% of the size of the largest text on each line\r
- * paragraph.setLineSpacing(120);\r
- *\r
- * // spacing will be 200% of the size of the largest text on each line\r
- * paragraph.setLineSpacing(200);\r
- *\r
- * // spacing will be 48 points\r
- * paragraph.setLineSpacing(-48.0);\r
- * </code></pre>\r
- * \r
- * @param linespacing the vertical line spacing\r
- */\r
+ @Override\r
public void setLineSpacing(double linespacing){\r
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
CTTextSpacing spc = CTTextSpacing.Factory.newInstance();\r
pr.setLnSpc(spc);\r
}\r
\r
- /**\r
- * Returns the vertical line spacing that is to be used within a paragraph.\r
- * This may be specified in two different ways, percentage spacing and font point spacing:\r
- * <p>\r
- * If linespacing >= 0, then linespacing is a percentage of normal line height.\r
- * If linespacing < 0, the absolute value of linespacing is the spacing in points\r
- * </p>\r
- *\r
- * @return the vertical line spacing.\r
- */\r
+ @Override\r
public double getLineSpacing(){\r
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){\r
public boolean fetch(CTTextParagraphProperties props){\r
* Set the true/false status of the subproperty with the given index
*/
public void setSubValue(boolean value, int idx) {
- if(subPropMatches[idx] == value) { return; }
- if(value) {
- dataValue += subPropMasks[idx];
- } else {
- dataValue -= subPropMasks[idx];
- }
- subPropMatches[idx] = value;
+ if (subPropMatches[idx] == value) return;
+ subPropMatches[idx] = value;
+ dataValue ^= subPropMasks[idx];
}
@Override
return newObj;
}
+
+ public BitMaskTextProp cloneAll(){
+ return (BitMaskTextProp)super.clone();
+ }
}
\ No newline at end of file
this.reservedField = other.reservedField;
this.textPropList.clear();
for (TextProp tp : other.textPropList) {
- TextProp tpCopy = tp.clone();
- if (tpCopy instanceof BitMaskTextProp) {
- BitMaskTextProp bmt = (BitMaskTextProp)tpCopy;
- boolean matches[] = ((BitMaskTextProp)tp).getSubPropMatches();
- for (int i=0; i<matches.length; i++) {
- bmt.setSubValue(matches[i], i);
- }
- }
+ TextProp tpCopy = (tp instanceof BitMaskTextProp)
+ ? ((BitMaskTextProp)tp).cloneAll()
+ : tp.clone();
this.textPropList.add(tpCopy);
}
}
/**
* 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
StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
// Then the mask field
int mask = maskSpecial;
- for(int i=0; i<textPropList.size(); i++) {
- TextProp textProp = textPropList.get(i);
+ for(TextProp textProp : textPropList) {
//sometimes header indicates that the bitmask is present but its value is 0
-
if (textProp instanceof BitMaskTextProp) {
if(mask == 0) mask |= textProp.getWriteMask();
}
StyleTextPropAtom.writeLittleEndian(mask,o);
// Then the contents of all the properties
- for(int i=0; i<textPropList.size(); i++) {
- TextProp textProp = textPropList.get(i);
- int val = textProp.getValue();
- if(textProp.getSize() == 2) {
- StyleTextPropAtom.writeLittleEndian((short)val,o);
- } else if(textProp.getSize() == 4){
- StyleTextPropAtom.writeLittleEndian(val,o);
- }
+ for (TextProp potProp : potentialProperties) {
+ for(TextProp textProp : textPropList) {
+ if (!textProp.getName().equals(potProp.getName())) continue;
+ int val = textProp.getValue();
+ 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);
+ } else if (textProp.getSize() == 4) {
+ StyleTextPropAtom.writeLittleEndian(val,o);
+ }
+ }
}
}
package org.apache.poi.hslf.record;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.LinkedList;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
import org.apache.poi.hslf.model.textproperties.*;
-import org.apache.poi.util.HexDump;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.POILogger;
+import org.apache.poi.util.*;
/**
* A StyleTextPropAtom (type 4001). Holds basic character properties
* Characters the paragraph covers, and also contains the TextProps
* that actually define the styling of the paragraph.
*/
- private LinkedList<TextPropCollection> paragraphStyles;
- public LinkedList<TextPropCollection> getParagraphStyles() { return paragraphStyles; }
+ private List<TextPropCollection> paragraphStyles;
+ public List<TextPropCollection> getParagraphStyles() { return paragraphStyles; }
/**
* Updates the link list of TextPropCollections which make up the
* 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.
* Each entry is a TextPropCollection, which tells you how many
* Characters the character styling covers, and also contains the
* TextProps that actually define the styling of the characters.
*/
- private LinkedList<TextPropCollection> charStyles;
- public LinkedList<TextPropCollection> getCharacterStyles() { return charStyles; }
+ private List<TextPropCollection> charStyles;
+ public List<TextPropCollection> getCharacterStyles() { return charStyles; }
/**
* Updates the link list of TextPropCollections which make up the
* 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
public int getCharacterTextLengthCovered() {
return getCharactersCovered(charStyles);
}
- private int getCharactersCovered(LinkedList<TextPropCollection> styles) {
+ private int getCharactersCovered(List<TextPropCollection> styles) {
int length = 0;
for(TextPropCollection tpc : styles) {
length += tpc.getCharactersCovered();
System.arraycopy(source,start+8,rawContents,0,rawContents.length);
reserved = new byte[0];
- // Set empty linked lists, ready for when they call setParentTextSize
- paragraphStyles = new LinkedList<TextPropCollection>();
- charStyles = new LinkedList<TextPropCollection>();
+ // Set empty lists, ready for when they call setParentTextSize
+ paragraphStyles = new ArrayList<TextPropCollection>();
+ charStyles = new ArrayList<TextPropCollection>();
}
LittleEndian.putInt(_header,4,10);
// Set empty paragraph and character styles
- paragraphStyles = new LinkedList<TextPropCollection>();
- charStyles = new LinkedList<TextPropCollection>();
+ paragraphStyles = new ArrayList<TextPropCollection>();
+ charStyles = new ArrayList<TextPropCollection>();
TextPropCollection defaultParagraphTextProps =
new TextPropCollection(parentTextSize, (short)0);
// First up, we need to serialise the paragraph properties
for(int i=0; i<paragraphStyles.size(); i++) {
TextPropCollection tpc = paragraphStyles.get(i);
- tpc.writeOut(baos);
+ tpc.writeOut(baos, paragraphTextPropTypes);
}
// Now, we do the character ones
for(int i=0; i<charStyles.size(); i++) {
TextPropCollection tpc = charStyles.get(i);
- tpc.writeOut(baos);
+ tpc.writeOut(baos, characterTextPropTypes);
}
rawContents = baos.toByteArray();
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- pr.writeOut(baos);
+ pr.writeOut(baos, paragraphTextPropTypes);
byte[] b = baos.toByteArray();
out.append(HexDump.dump(b, 0, 0));
} catch (Exception e ) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- pr.writeOut(baos);
+ pr.writeOut(baos, characterTextPropTypes);
byte[] b = baos.toByteArray();
out.append(HexDump.dump(b, 0, 0));
} catch (Exception e ) {
* @param shape
*/
protected void onAddTextShape(HSLFTextShape shape) {
-
}
/**
return getParaTextPropVal("bullet.font");\r
}\r
\r
- /**\r
- * Sets the line spacing.\r
- * <p>\r
- * If linespacing >= 0, then linespacing is a percentage of normal line height.\r
- * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates.\r
- * </p>\r
- */\r
- public void setLineSpacing(int val) {\r
- setParaTextPropVal("linespacing", val);\r
+ @Override\r
+ public void setLineSpacing(double lineSpacing) {\r
+ // if lineSpacing < 0, we need to convert points (common interface) to master units (hslf)\r
+ if (lineSpacing < 0) {\r
+ lineSpacing = (lineSpacing*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);\r
+ }\r
+ setParaTextPropVal("linespacing", (int)lineSpacing);\r
}\r
\r
- /**\r
- * Returns the line spacing\r
- * <p>\r
- * If linespacing >= 0, then linespacing is a percentage of normal line height.\r
- * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates.\r
- * </p>\r
- *\r
- * @return the spacing between lines\r
- */\r
@Override\r
public double getLineSpacing() {\r
- int val = getParaTextPropVal("linespacing");\r
- return val == -1 ? 0 : val;\r
+ double val = getParaTextPropVal("linespacing");\r
+ // if lineSpacing < 0, we need to convert master units (hslf) to points (common interface)\r
+ if (val == -1) return 0;\r
+ if (val < -1) val *= HSLFShape.POINT_DPI/((double)HSLFShape.MASTER_DPI);\r
+ return val;\r
}\r
\r
/**\r
throw new RuntimeException("child record not found - malformed container record");\r
}\r
cr[idx] = newRecord;\r
+ \r
+ if (newRecord == byteAtom) {\r
+ charAtom = null;\r
+ } else {\r
+ byteAtom = null;\r
+ }\r
}\r
\r
// Ensure a StyleTextPropAtom is present, adding if required\r
}\r
for (HSLFTextRun tr : para.getTextRuns()) {\r
TextPropCollection rtpc = tr.getCharacterStyle();\r
+ rtpc.updateTextSize(0);\r
if (!rtpc.equals(lastRTPC)) {\r
lastRTPC = styleAtom.addCharacterTextPropCollection(0);\r
lastRTPC.copy(rtpc);\r
* \r
* @param text the text string used by this object.\r
*/\r
- protected static void appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {\r
+ protected static HSLFTextRun appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {\r
text = toInternalString(text);\r
+\r
+ // check paragraphs\r
+ assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());\r
\r
- // init paragraphs\r
- assert(!paragraphs.isEmpty());\r
+ HSLFTextParagraph htp = paragraphs.get(paragraphs.size()-1);\r
+ HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size()-1);\r
+\r
+ if (newParagraph) {\r
+ htr.setText(htr.getRawText()+"\n");\r
+ }\r
\r
- HSLFTextParagraph lastHTP = paragraphs.get(paragraphs.size()-1);\r
- HSLFTextRun lastHTR = lastHTP.getTextRuns().get(lastHTP.getTextRuns().size()-1);\r
- HSLFTextParagraph htp = (newParagraph) ? new HSLFTextParagraph(lastHTP) : lastHTP;\r
- HSLFTextRun htr = new HSLFTextRun(htp);\r
- htr.setText(text);\r
- htr.getCharacterStyle().copy(lastHTR.getCharacterStyle());\r
- htp.addTextRun(htr);\r
+ boolean isFirst = !newParagraph;\r
+ for (String rawText : text.split("(?<=\r)")) {\r
+ if (!isFirst) {\r
+ TextPropCollection tpc = htp.getParagraphStyle();\r
+ HSLFTextParagraph prevHtp = htp;\r
+ htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom, htp._styleAtom);\r
+ htp.getParagraphStyle().copy(tpc);\r
+ htp.setParentShape(prevHtp.getParentShape());\r
+ htp.setShapeId(prevHtp.getShapeId());\r
+ htp.supplySheet(prevHtp.getSheet());\r
+ paragraphs.add(htp);\r
+ isFirst = false;\r
+ }\r
+ TextPropCollection tpc = htr.getCharacterStyle();\r
+ // special case, last text run is empty, we will reuse it\r
+ if (htr.getLength() > 0) {\r
+ htr = new HSLFTextRun(htp);\r
+ htr.getCharacterStyle().copy(tpc);\r
+ htp.addTextRun(htr);\r
+ }\r
+ htr.setText(rawText);\r
+ }\r
+ \r
+ return htr;\r
}\r
\r
/**\r
* \r
* @param text the text string used by this object.\r
*/\r
- public static void setText(List<HSLFTextParagraph> paragraphs, String text) {\r
+ public static HSLFTextRun setText(List<HSLFTextParagraph> paragraphs, String text) {\r
text = HSLFTextParagraph.toInternalString(text);\r
\r
- // init paragraphs\r
- assert(!paragraphs.isEmpty());\r
+ // check paragraphs\r
+ assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());\r
\r
Iterator<HSLFTextParagraph> paraIter = paragraphs.iterator();\r
- HSLFTextParagraph firstHTP = paraIter.next(); // keep first\r
- assert(firstHTP != null);\r
+ HSLFTextParagraph htp = paraIter.next(); // keep first\r
+ assert(htp != null);\r
while (paraIter.hasNext()) {\r
paraIter.next();\r
paraIter.remove();\r
}\r
\r
- Iterator<HSLFTextRun> runIter = firstHTP.getTextRuns().iterator();\r
- HSLFTextRun firstHTR = runIter.next();\r
- assert(firstHTR != null);\r
+ Iterator<HSLFTextRun> runIter = htp.getTextRuns().iterator();\r
+ HSLFTextRun htr = runIter.next();\r
+ htr.setText("");\r
+ assert(htr != null);\r
while (runIter.hasNext()) {\r
runIter.next();\r
runIter.remove();\r
}\r
\r
- firstHTR.setText(text);\r
+ return appendText(paragraphs, text, false);\r
}\r
\r
public static String getRawText(List<HSLFTextParagraph> paragraphs) {\r
for (HSLFTextRun r : p.getTextRuns()) {\r
sb.append(r.getRawText());\r
}\r
- sb.append("\r");\r
}\r
- sb.deleteCharAt(sb.length()-1); // remove last line break\r
return sb.toString(); \r
}\r
\r
return paragraphCollection;\r
}\r
\r
- for (int slwtIndex = 0; recordIdx < records.length-2; slwtIndex++) {\r
+ for (int slwtIndex = 0; recordIdx < records.length; slwtIndex++) {\r
List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>();\r
paragraphCollection.add(paragraphs);\r
\r
\r
if (tbytes == null && tchars == null) {\r
tbytes = new TextBytesAtom();\r
+ header.getParentRecord().addChildAfter(tbytes, header);\r
logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving.");\r
}\r
\r
String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();\r
\r
- for (String para : rawText.split("\r")) {\r
+ // split, but keep delimiter\r
+ for (String para : rawText.split("(?<=\r)")) {\r
HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles);\r
paragraphs.add(tpara);\r
tpara.setStyleTextProp9Atom(styleTextProp9Atom);\r
\r
protected static void applyCharacterStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> charStyles) {\r
int paraIdx = 0, runIdx = 0;\r
- for (TextPropCollection p : charStyles) {\r
+ HSLFTextRun trun;\r
+ \r
+ for (int csIdx=0; csIdx<charStyles.size(); csIdx++) {\r
+ TextPropCollection p = charStyles.get(csIdx);\r
for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle; ) {\r
HSLFTextParagraph para = paragraphs.get(paraIdx);\r
List<HSLFTextRun> runs = para.getTextRuns();\r
- HSLFTextRun trun = runs.get(runIdx);\r
+ trun = runs.get(runIdx);\r
int len = trun.getLength();\r
\r
- if (runIdx+1 >= runs.size()) {\r
- // need to add +1 to the last run of the paragraph\r
- len++;\r
- }\r
- \r
- TextPropCollection pCopy = new TextPropCollection(1);\r
- pCopy.copy(p);\r
if (ccRun+len <= ccStyle) {\r
- trun.setCharacterStyle(pCopy);\r
- pCopy.updateTextSize(len);\r
ccRun += len;\r
} else {\r
String text = trun.getRawText();\r
trun.setText(text.substring(0,ccStyle-ccRun));\r
- pCopy.updateTextSize(ccStyle-ccRun);\r
- trun.setCharacterStyle(pCopy);\r
\r
HSLFTextRun nextRun = new HSLFTextRun(para);\r
nextRun.setText(text.substring(ccStyle-ccRun));\r
ccRun += ccStyle-ccRun;\r
}\r
\r
- // need to compare it again, in case a run has been added afer\r
- if (++runIdx >= runs.size()) {\r
+ TextPropCollection pCopy = new TextPropCollection(0);\r
+ pCopy.copy(p);\r
+ trun.setCharacterStyle(pCopy);\r
+\r
+ len = trun.getLength();\r
+ if (paraIdx == paragraphs.size()-1 && runIdx == runs.size()-1) {\r
+ if (csIdx < charStyles.size()-1) {\r
+ // special case, empty trailing text run\r
+ HSLFTextRun nextRun = new HSLFTextRun(para);\r
+ nextRun.setText("");\r
+ runs.add(nextRun);\r
+ } else {\r
+ // need to add +1 to the last run of the last paragraph\r
+ len++;\r
+ ccRun++;\r
+ }\r
+ }\r
+ pCopy.updateTextSize(len);\r
+ \r
+ // need to compare it again, in case a run has been added after\r
+ if (++runIdx == runs.size()) {\r
paraIdx++;\r
runIdx = 0;\r
}\r
int paraIdx = 0;\r
for (TextPropCollection p : paraStyles) {\r
for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) {\r
- HSLFTextParagraph para = paragraphs.get(paraIdx);\r
- TextPropCollection pCopy = new TextPropCollection(1);\r
+ if (paraIdx >= paragraphs.size() || ccPara >= ccStyle-1) return;\r
+ HSLFTextParagraph htp = paragraphs.get(paraIdx);\r
+ TextPropCollection pCopy = new TextPropCollection(0);\r
pCopy.copy(p);\r
+ htp.setParagraphStyle(pCopy);\r
int len = 0;\r
- for (HSLFTextRun trun : para.getTextRuns()) {\r
+ for (HSLFTextRun trun : htp.getTextRuns()) {\r
len += trun.getLength();\r
}\r
- pCopy.updateTextSize(len+1);\r
- para.setParagraphStyle(pCopy);\r
- ccPara += len+1;\r
+ if (paraIdx == paragraphs.size()-1) len++;\r
+ pCopy.updateTextSize(len);\r
+ ccPara += len;\r
}\r
}\r
}\r
tha.setParentRecord(wrapper);\r
wrapper.appendChildRecord(tha);\r
\r
- TextCharsAtom tca = new TextCharsAtom();\r
- wrapper.appendChildRecord(tca);\r
+ TextBytesAtom tba = new TextBytesAtom();\r
+ tba.setText("\r".getBytes());\r
+ wrapper.appendChildRecord(tba);\r
\r
- StyleTextPropAtom sta = new StyleTextPropAtom(0);\r
+ StyleTextPropAtom sta = new StyleTextPropAtom(1);\r
+ TextPropCollection paraStyle = sta.addParagraphTextPropCollection(1);\r
+ TextPropCollection charStyle = sta.addCharacterTextPropCollection(1);\r
wrapper.appendChildRecord(sta);\r
\r
- HSLFTextParagraph htp = new HSLFTextParagraph(tha, null, tca, sta);\r
+ HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta);\r
+ htp.setParagraphStyle(paraStyle);\r
htp._records = new Record[0];\r
+ htp.setBullet(false);\r
+ htp.setLineSpacing(100);\r
+ htp.setLeftMargin(0);\r
+ htp.setIndent(0);\r
+ // set wrap flags\r
+ \r
HSLFTextRun htr = new HSLFTextRun(htp);\r
+ htr.setCharacterStyle(charStyle);\r
+ htr.setText("\r");\r
+ htr.setFontColor(Color.black);\r
htp.addTextRun(htr);\r
\r
return Arrays.asList(htp);\r
/** The TextRun we belong to */
private HSLFTextParagraph parentParagraph;
- private String _runText = "\r";
+ private String _runText = "";
private String _fontname;
/**
* Our paragraph and character style.
* 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
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
-import java.awt.geom.Rectangle2D.Double;
import java.io.IOException;
import java.util.*;
-import org.apache.poi.POIXMLException;
import org.apache.poi.ddf.*;
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.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTextShape;
protected void afterInsert(HSLFSheet sh){
super.afterInsert(sh);
+ storeText();
+
EscherTextboxWrapper _txtbox = getEscherTextboxWrapper();
if(_txtbox != null){
+ _escherContainer.addChildRecord(_txtbox.getEscherRecord());
+
PPDrawing ppdrawing = sh.getPPDrawing();
ppdrawing.addTextboxWrapper(_txtbox);
// Ensure the escher layer knows about the added records
*
* @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
List<HSLFTextParagraph> paras = getTextParagraphs();
- HSLFTextParagraph.appendText(paras, text, newParagraph);
+ return HSLFTextParagraph.appendText(paras, text, newParagraph);
}
/**
* Uses the properties of the first paragraph / textrun
*
* @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
List<HSLFTextParagraph> paras = getTextParagraphs();
- HSLFTextParagraph.setText(paras, text);
+ HSLFTextRun htr = HSLFTextParagraph.setText(paras, text);
setTextId(text.hashCode());
+ return htr;
}
/**
// negative value means the absolute spacing in points\r
y += -spaceBefore;\r
}\r
- isFirstLine = false;\r
}\r
+ isFirstLine = false;\r
\r
dp.setPosition(x, y);\r
dp.draw(graphics);\r
* This may be specified in two different ways, percentage spacing and font point spacing:\r
* <p>\r
* If spaceBefore >= 0, then space is a percentage of normal line height.\r
- * If spaceBefore < 0, the absolute value of linespacing is the spacing in points\r
+ * If spaceBefore < 0, the absolute value in points\r
* </p>\r
*\r
* @return the vertical white space before the paragraph\r
* @return the vertical line spacing.\r
*/\r
double getLineSpacing();\r
+ \r
+ /**\r
+ * This element specifies the vertical line spacing that is to be used within a paragraph.\r
+ * This may be specified in two different ways, percentage spacing and font point spacing:\r
+ * <p>\r
+ * If linespacing >= 0, then linespacing is a percentage of normal line height\r
+ * If linespacing < 0, the absolute value of linespacing is the spacing in points\r
+ * </p>\r
+ * Examples:\r
+ * <pre><code>\r
+ * // spacing will be 120% of the size of the largest text on each line\r
+ * paragraph.setLineSpacing(120);\r
+ *\r
+ * // spacing will be 200% of the size of the largest text on each line\r
+ * paragraph.setLineSpacing(200);\r
+ *\r
+ * // spacing will be 48 points\r
+ * paragraph.setLineSpacing(-48.0);\r
+ * </code></pre>\r
+ * \r
+ * @param linespacing the vertical line spacing\r
+ */\r
+ void setLineSpacing(double lineSpacing);\r
\r
String getDefaultFontFamily();\r
\r
import static org.junit.Assert.*;
import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Rectangle2D.Double;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
}
}
+ @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
* and set some of the style attributes
for (HSLFShape sh : sld.getShapes()) {
if (sh instanceof HSLFTextShape){
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));