} else {
rt.getTextParagraph().setBullet(true);
rt.setFontSize(12d);
- rt.getTextParagraph().setAlignment(TextAlign.LEFT);
+ rt.getTextParagraph().setTextAlign(TextAlign.LEFT);
cell.setHorizontalCentered(false);
}
cell.setVerticalAlignment(VerticalAlignment.MIDDLE);
/**\r
* Returns the alignment that is applied to the paragraph.\r
*\r
- * If this attribute is omitted, then a value of left is implied.\r
- * @return ??? alignment that is applied to the paragraph\r
+ * If this attribute is omitted, then null is returned.\r
+ * User code can imply the value {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign#LEFT} then.\r
+ *\r
+ * @return alignment that is applied to the paragraph\r
*/\r
TextAlign getTextAlign();\r
- \r
+\r
+ /**\r
+ * Specifies the alignment that is to be applied to the paragraph.\r
+ * Possible values for this include left, right, centered, justified and distributed,\r
+ * see {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign}.\r
+ *\r
+ * @param align text align\r
+ */ \r
+ void setTextAlign(TextAlign align);\r
\r
/**\r
* Returns the font alignment that is applied to the paragraph.\r
return run;\r
}\r
\r
- /**\r
- * Returns the alignment that is applied to the paragraph.\r
- *\r
- * If this attribute is omitted, then null is returned.\r
- * User code can imply the value {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign#LEFT} then.\r
- *\r
- * @return alignment that is applied to the paragraph\r
- */\r
+ @Override\r
public TextAlign getTextAlign(){\r
ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getIndentLevel()){\r
public boolean fetch(CTTextParagraphProperties props){\r
return fetcher.getValue();\r
}\r
\r
- /**\r
- * Specifies the alignment that is to be applied to the paragraph.\r
- * Possible values for this include left, right, centered, justified and distributed,\r
- * see {@link org.apache.poi.sl.usermodel.TextParagraph.TextAlign}.\r
- *\r
- * @param align text align\r
- */\r
- public void setTextAlign(TextAlign align){\r
+ @Override\r
+ public void setTextAlign(TextAlign align) {\r
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
if(align == null) {\r
if(pr.isSetAlgn()) pr.unsetAlgn();\r
CTPlaceholder ph = shape.getCTPlaceholder();\r
if(ph == null){\r
// if it is a plain text box then take defaults from presentation.xml\r
+ @SuppressWarnings("resource")\r
XMLSlideShow ppt = sheet.getSlideShow();\r
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel());\r
if (themeProps != null) ok = visitor.fetch(themeProps);\r
package org.apache.poi.hslf.model.textproperties;
-import java.io.*;
-import java.util.*;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.StyleTextPropAtom;
* Clones the given text properties
*/
public void copy(TextPropCollection other) {
+ if (other == null) {
+ throw new HSLFException("trying to copy null TextPropCollection");
+ }
if (this == other) return;
this.charactersCovered = other.charactersCovered;
this.indentLevel = other.indentLevel;
charactersCovered = textSize;
}
+ /**
+ * Writes out to disk the header, and then all the properties
+ */
+ public void writeOut(OutputStream o) throws IOException {
+ writeOut(o, false);
+ }
+
/**
* Writes out to disk the header, and then all the properties
*/
- public void writeOut(OutputStream o) throws IOException {
- // First goes the number of characters we affect
- StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
+ public void writeOut(OutputStream o, boolean isMasterStyle) throws IOException {
+ if (!isMasterStyle) {
+ // First goes the number of characters we affect
+ // MasterStyles don't have this field
+ StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
+ }
// Then we have the indentLevel field if it's a paragraph collection
if (textPropType == TextPropType.paragraph && indentLevel > -1) {
package org.apache.poi.hslf.record;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
+import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianOutputStream;
/**
* TxMasterStyleAtom atom (4003).
paragraphStyles = new ArrayList<TextPropCollection>(levels);
charStyles = new ArrayList<TextPropCollection>(levels);
- for(short j = 0; j < levels; j++) {
+ for(short i = 0; i < levels; i++) {
TextPropCollection prprops = new TextPropCollection(0, TextPropType.paragraph); // getParagraphProps(type, j)
if (type >= TextHeaderAtom.CENTRE_BODY_TYPE) {
// Fetch the 2 byte value, that is safe to ignore for some types of text
pos += chprops.buildTextPropList( head, _data, pos);
charStyles.add(chprops);
}
-
}
/**
- * Paragraph properties for the specified text type and
- * indent level
- * Depending on the level and type, it may be our special
- * ones, or the standard StyleTextPropAtom ones
- */
-// protected TextProp[] getParagraphProps(int type, int level){
-// return StyleTextPropAtom.paragraphTextPropTypes;
-// return (level != 0 || type >= MAX_INDENT)
-// ? StyleTextPropAtom.paragraphTextPropTypes
-// : paragraphSpecialPropTypes;
-// }
-
- /**
- * Character properties for the specified text type and
- * indent level.
- * Depending on the level and type, it may be our special
- * ones, or the standard StyleTextPropAtom ones
+ * Updates the rawdata from the modified paragraph/character styles
+ *
+ * @since 3.14-beta1
*/
-// protected TextProp[] getCharacterProps(int type, int level){
-// return StyleTextPropAtom.characterTextPropTypes;
-// return (level != 0 || type >= MAX_INDENT)
-// ? StyleTextPropAtom.characterTextPropTypes
-// : characterSpecialPropTypes;
-// }
+ public void updateStyles() {
+ int type = getTextType();
+
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ LittleEndianOutputStream leos = new LittleEndianOutputStream(bos);
+ int levels = paragraphStyles.size();
+ leos.writeShort(levels);
+
+ TextPropCollection prdummy = new TextPropCollection(0, TextPropType.paragraph);
+ TextPropCollection chdummy = new TextPropCollection(0, TextPropType.character);
+
+ for (int i=0; i<levels; i++) {
+ prdummy.copy(paragraphStyles.get(i));
+ chdummy.copy(charStyles.get(i));
+ if (type >= TextHeaderAtom.CENTRE_BODY_TYPE) {
+ leos.writeShort(prdummy.getIndentLevel());
+ }
+
+ // Indent level is not written for master styles
+ prdummy.setIndentLevel((short)-1);
+ prdummy.writeOut(bos, true);
+ chdummy.writeOut(bos, true);
+ }
+
+ _data = bos.toByteArray();
+ leos.close();
+
+ LittleEndian.putInt(_header, 4, _data.length);
+ } catch (IOException e) {
+ throw new HSLFException("error in updating master style properties", e);
+ }
+ }
}
import org.apache.poi.ddf.EscherDgRecord;
import org.apache.poi.ddf.EscherDggRecord;
import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.CString;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.Sheet;
+import org.apache.poi.util.Internal;
/**
* This class defines the common format of "Sheets" in a powerpoint
/**
* Set the SlideShow we're attached to.
- * Also passes it on to our child RichTextRuns
+ * Also passes it on to our child text paragraphs
*/
- public void setSlideShow(HSLFSlideShow ss) {
+ @Internal
+ protected void setSlideShow(HSLFSlideShow ss) {
+ if (_slideShow != null) {
+ throw new HSLFException("Can't change existing slideshow reference");
+ }
+
_slideShow = ss;
List<List<HSLFTextParagraph>> trs = getTextParagraphs();
if (trs == null) return;
import java.util.ArrayList;
import java.util.List;
+import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.*;
+import org.apache.poi.util.Internal;
/**
* SlideMaster determines the graphics, layout, and formatting for all the slides in a given presentation.
/**
* Pickup a style attribute from the master.
- * This is the "workhorse" which returns the default style attrubutes.
+ * This is the "workhorse" which returns the default style attributes.
*/
public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
if (_txmaster.length <= txtype) return null;
return getStyleAttribute(txtype, level, name, isCharacter);
}
-
+
/**
* Assign SlideShow for this slide master.
- * (Used interanlly)
*/
- public void setSlideShow(HSLFSlideShow ss) {
+ @Internal
+ @Override
+ protected void setSlideShow(HSLFSlideShow ss) {
super.setSlideShow(ss);
//after the slide show is assigned collect all available style records
- if (_txmaster == null) {
- _txmaster = new TxMasterStyleAtom[9];
+ assert (_txmaster == null);
+ _txmaster = new TxMasterStyleAtom[9];
- TxMasterStyleAtom txdoc = getSlideShow().getDocumentRecord().getEnvironment().getTxMasterStyleAtom();
- _txmaster[txdoc.getTextType()] = txdoc;
+ TxMasterStyleAtom txdoc = getSlideShow().getDocumentRecord().getEnvironment().getTxMasterStyleAtom();
+ _txmaster[txdoc.getTextType()] = txdoc;
- TxMasterStyleAtom[] txrec = ((MainMaster)getSheetContainer()).getTxMasterStyleAtoms();
- for (int i = 0; i < txrec.length; i++) {
- int txType = txrec[i].getTextType();
- if(_txmaster[txType] == null) _txmaster[txType] = txrec[i];
+ TxMasterStyleAtom[] txrec = ((MainMaster)getSheetContainer()).getTxMasterStyleAtoms();
+ for (int i = 0; i < txrec.length; i++) {
+ int txType = txrec[i].getTextType();
+ if (txType < _txmaster.length && _txmaster[txType] == null) {
+ _txmaster[txType] = txrec[i];
+ }
+ }
+
+ for (List<HSLFTextParagraph> paras : getTextParagraphs()) {
+ for (HSLFTextParagraph htp : paras) {
+ int txType = htp.getRunType();
+ if (txType >= _txmaster.length || _txmaster[txType] == null) {
+ throw new HSLFException("Master styles not initialized");
+ }
+
+ int level = htp.getIndentLevel();
+
+ List<TextPropCollection> charStyles = _txmaster[txType].getCharacterStyles();
+ List<TextPropCollection> paragraphStyles = _txmaster[txType].getParagraphStyles();
+ if (charStyles == null || paragraphStyles == null ||
+ charStyles.size() <= level || paragraphStyles.size() <= level) {
+ throw new HSLFException("Master styles not initialized");
+ }
+
+ htp.setMasterStyleReference(paragraphStyles.get(level));
+ for (HSLFTextRun htr : htp.getTextRuns()) {
+ htr.setMasterStyleReference(charStyles.get(level));
+ }
}
}
}
import org.apache.poi.hslf.record.SlideListWithText;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
import org.apache.poi.hslf.record.SlidePersistAtom;
+import org.apache.poi.hslf.record.TxMasterStyleAtom;
import org.apache.poi.hslf.record.UserEditAtom;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
for (HSLFSlide sl : getSlides()) {
writeDirtyParagraphs(sl);
}
+
+ for (HSLFSlideMaster sl : getSlideMasters()) {
+ boolean isDirty = false;
+ for (List<HSLFTextParagraph> paras : sl.getTextParagraphs()) {
+ for (HSLFTextParagraph p : paras) {
+ isDirty |= p.isDirty();
+ }
+ }
+ if (isDirty) {
+ for (TxMasterStyleAtom sa : sl.getTxMasterStyleAtoms()) {
+ if (sa != null) {
+ // not all master style atoms are set - index 3 is typically null
+ sa.updateStyles();
+ }
+ }
+ }
+ }
_hslfSlideShow.write(out);
}
import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.TextParagraph;\r
+import org.apache.poi.util.Internal;\r
import org.apache.poi.util.LocaleUtil;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
private final TextHeaderAtom _headerAtom;\r
private TextBytesAtom _byteAtom;\r
private TextCharsAtom _charAtom;\r
- private final TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);\r
+ private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);\r
\r
protected TextRulerAtom _ruler;\r
protected final List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();\r
_paragraphStyle.copy(paragraphStyle);\r
}\r
\r
+ /**\r
+ * Setting a master style reference\r
+ *\r
+ * @param paragraphStyle the master style reference\r
+ * \r
+ * @since 3.14-Beta1\r
+ */\r
+ @Internal\r
+ /* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {\r
+ _paragraphStyle = paragraphStyle;\r
+ }\r
+ \r
/**\r
* Supply the Sheet we belong to, which might have an assigned SlideShow\r
* Also passes it on to our child RichTextRuns\r
return (d != null) ? d : 12d;\r
}\r
\r
- /**\r
- * Sets the type of horizontal alignment for the paragraph.\r
- *\r
- * @param align - the type of alignment\r
- */\r
- public void setAlignment(org.apache.poi.sl.usermodel.TextParagraph.TextAlign align) {\r
+ @Override\r
+ public void setTextAlign(TextAlign align) {\r
Integer alignInt = null;\r
if (align != null) switch (align) {\r
default:\r
}\r
\r
@Override\r
- public org.apache.poi.sl.usermodel.TextParagraph.TextAlign getTextAlign() {\r
+ public TextAlign getTextAlign() {\r
TextProp tp = getPropVal(_paragraphStyle, "alignment", this);\r
if (tp == null) return null;\r
switch (tp.getValue()) {\r
if (styleTextProp9Atom == null) return null;\r
TextPFException9[] ant = styleTextProp9Atom.getAutoNumberTypes();\r
int level = getIndentLevel();\r
- if (ant == null || level >= ant.length) return null;\r
+ if (ant == null || level == -1 || level >= ant.length) return null;\r
return ant[level].getAutoNumberScheme();\r
}\r
\r
HSLFTextParagraph para = paragraphs.get(paraIdx);\r
List<HSLFTextRun> runs = para.getTextRuns();\r
trun = runs.get(runIdx);\r
- int len = trun.getLength();\r
+ final int len = trun.getLength();\r
\r
if (ccRun + len <= ccStyle) {\r
ccRun += len;\r
ccRun += ccStyle - ccRun;\r
}\r
\r
- TextPropCollection pCopy = new TextPropCollection(0, TextPropType.character);\r
- pCopy.copy(p);\r
- trun.setCharacterStyle(pCopy);\r
+ trun.setCharacterStyle(p);\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
ccRun++;\r
} else {\r
// need to add +1 to the last run of the last paragraph\r
- len++;\r
+ trun.getCharacterStyle().updateTextSize(trun.getLength()+1);\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
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.TextRun;
+import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
}
public void setCharacterStyle(TextPropCollection characterStyle) {
- assert(characterStyle != null);
- this.characterStyle = characterStyle;
+ this.characterStyle.copy(characterStyle);
+ this.characterStyle.updateTextSize(_runText.length());
}
+ /**
+ * Setting a master style reference
+ *
+ * @param characterStyle the master style reference
+ *
+ * @since 3.14-Beta1
+ */
+ @Internal
+ /* package */ void setMasterStyleReference(TextPropCollection characterStyle) {
+ this.characterStyle = characterStyle;
+ }
+
+
/**
* Supply the SlideShow we belong to
*/
import static org.junit.Assert.assertTrue;
import java.awt.Color;
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Set;
-import org.apache.poi.POIDataSamples;
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherArrayProperty;
import org.apache.poi.ddf.EscherColorRef;
import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.sl.usermodel.TextBox;
import org.apache.poi.sl.usermodel.TextParagraph;
+import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
* @author Yegor Kozlov
*/
public final class TestBugs {
- private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
-
/**
* Bug 41384: Array index wrong in record creation
*/
HSLFTextParagraph tp = cell.getTextParagraphs().get(0);
tp.setBulletStyle('%', tp0.getBulletColor(), tp0.getBulletFont(), tp0.getBulletSize());
tp.setIndent(tp0.getIndent());
- tp.setAlignment(tp0.getTextAlign());
+ tp.setTextAlign(tp0.getTextAlign());
tp.setIndentLevel(tp0.getIndentLevel());
tp.setSpaceAfter(tp0.getSpaceAfter());
tp.setSpaceBefore(tp0.getSpaceBefore());
ppt2.close();
}
+ @Test
+ public void bug47904() throws IOException {
+ HSLFSlideShow ppt1 = new HSLFSlideShow();
+ HSLFSlideMaster sm = ppt1.getSlideMasters().get(0);
+ HSLFAutoShape as = (HSLFAutoShape)sm.getShapes().get(0);
+ HSLFTextParagraph tp = as.getTextParagraphs().get(0);
+ HSLFTextRun tr = tp.getTextRuns().get(0);
+ tr.setFontFamily("Tahoma");
+ tr.setShadowed(true);
+ tr.setFontSize(44.);
+ tr.setFontColor(Color.red);
+ tp.setTextAlign(TextAlign.RIGHT);
+ ppt1.createSlide().addTitle().setText("foobaa");
+
+ HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
+ ppt1.close();
+
+ HSLFTextShape ts = (HSLFTextShape)ppt2.getSlides().get(0).getShapes().get(0);
+ tp = ts.getTextParagraphs().get(0);
+ tr = tp.getTextRuns().get(0);
+ assertEquals(44., tr.getFontSize(), 0);
+ assertEquals("Tahoma", tr.getFontFamily());
+ Color colorAct = DrawPaint.applyColorTransform(tr.getFontColor().getSolidColor());
+ assertEquals(Color.red, colorAct);
+ assertEquals(TextAlign.RIGHT, tp.getTextAlign());
+ assertEquals("foobaa", tr.getRawText());
+ ppt2.close();
+ }
+
private static HSLFSlideShow open(String fileName) throws IOException {
- return (HSLFSlideShow)SlideShowFactory.create(_slTests.getFile(fileName));
+ File sample = HSLFTestDataSamples.getSampleFile(fileName);
+ return (HSLFSlideShow)SlideShowFactory.create(sample);
}
}
package org.apache.poi.hslf.usermodel;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import java.io.IOException;
import java.util.List;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.model.textproperties.TextPFException9;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.record.EscherTextboxWrapper;
+import org.apache.poi.hslf.record.StyleTextProp9Atom;
+import org.apache.poi.hslf.record.StyleTextPropAtom;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.junit.Test;
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
@Test
- public void testNumberedList() throws Exception {
+ public void testNumberedList() throws IOException {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers3.ppt"));
assertTrue("No Exceptions while reading file", true);
assertEquals(1, slides.size());
final HSLFSlide slide = slides.get(0);
checkSlide(slide);
+ ppt.close();
}
private void checkSlide(final HSLFSlide s) {
final StyleTextProp9Atom[] numberedListArray = s.getNumberedListInfo();