S extends Shape<S,P>,
P extends TextParagraph<S,P,? extends TextRun>
> extends Sheet<S,P> {
-
+ /**
+ * Return the placeholder shape for the specified type
+ *
+ * @return the shape or {@code null} if it is not defined in this mastersheet
+ *
+ * @since POI 4.0.0
+ */
+ SimpleShape<S,P> getPlaceholder(Placeholder type);
}
--- /dev/null
+/* ====================================================================
+ 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.sl.usermodel;
+
+public interface TabStop {
+
+ enum TabStopType {
+ LEFT(0,1), CENTER(1,2), RIGHT(2,3), DECIMAL(3,4);
+ public final int nativeId;
+ public final int ooxmlId;
+
+ TabStopType(int nativeId, int ooxmlId) {
+ this.nativeId = nativeId;
+ this.ooxmlId = ooxmlId;
+ }
+ public static TabStopType fromNativeId(final int nativeId) {
+ for (TabStopType tst : values()) {
+ if (tst.nativeId == nativeId) {
+ return tst;
+ }
+ }
+ return null;
+ }
+ public static TabStopType fromOoxmlId(final int ooxmlId) {
+ for (TabStopType tst : values()) {
+ if (tst.ooxmlId == ooxmlId) {
+ return tst;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Gets the position in points relative to the left side of the paragraph.
+ *
+ * @return position in points
+ */
+ double getPositionInPoints();
+
+ /**
+ * Sets the position in points relative to the left side of the paragraph
+ *
+ * @param position position in points
+ */
+ void setPositionInPoints(double position);
+
+ TabStopType getType();
+
+ void setType(TabStopType type);
+}
* @since POI 3.15-beta2
*/
boolean isHeaderOrFooter();
+
+
+ /**
+ * Get the {@link TabStop TabStops} - the list can't be and it's entries shouldn't be modified.
+ * Opposed to other properties, this method is not cascading to the master sheet,
+ * if the property is not defined on the normal slide level, i.e. the tabstops on
+ * different levels aren't merged.
+ *
+ * @return the tabstop collection or {@code null} if no tabstops are defined
+ *
+ * @since POI 4.0.0
+ */
+ List<? extends TabStop> getTabStops();
+
+ /**
+ * Set the {@link TabStop} collection
+ *
+ * @param tabStops the {@link TabStop} collection
+ *
+ * @since POI 4.0.0
+ */
+ void addTabStops(double positionInPoints, TabStop.TabStopType tabStopType);
+
+ /**
+ * Removes the tabstops of this paragraphs.
+ * This doesn't affect inherited tabstops, e.g. inherited by the slide master
+ *
+ * @since POI 4.0.0
+ */
+ void clearTabStops();
}
\ No newline at end of file
return null;
}
+ public XSLFSimpleShape getPlaceholder(Placeholder ph) {
+ return getPlaceholderByType(ph.ooxmlId);
+ }
+
XSLFSimpleShape getPlaceholder(CTPlaceholder ph) {
XSLFSimpleShape shape = null;
if(ph.isSetIdx()) {
--- /dev/null
+/* ====================================================================
+ 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 org.apache.poi.sl.usermodel.TabStop;
+import org.apache.poi.util.Units;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStop;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextTabAlignType;
+
+public class XSLFTabStop implements TabStop {
+
+ final CTTextTabStop tabStop;
+
+ XSLFTabStop(CTTextTabStop tabStop) {
+ this.tabStop = tabStop;
+ }
+
+ /** position in EMUs */
+ public int getPosition() {
+ return tabStop.getPos();
+ }
+
+ /** position in EMUs */
+ public void setPosition(final int position) {
+ tabStop.setPos(position);
+ }
+
+ @Override
+ public double getPositionInPoints() {
+ return Units.toPoints(getPosition());
+ }
+
+ @Override
+ public void setPositionInPoints(final double points) {
+ setPosition(Units.toEMU(points));
+ }
+
+ public TabStopType getType() {
+ return TabStopType.fromOoxmlId(tabStop.getAlgn().intValue());
+ }
+
+ public void setType(final TabStopType tabStopType) {
+ tabStop.setAlgn(STTextTabAlignType.Enum.forInt(tabStopType.ooxmlId) );
+ }
+}
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.sl.usermodel.TabStop.TabStopType;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xslf.model.ParagraphPropertyFetcher;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextAutonumberBullet;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePercent;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePoint;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharBullet;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStop;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStopList;
-import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
-import org.openxmlformats.schemas.drawingml.x2006.main.STTextAutonumberScheme;
-import org.openxmlformats.schemas.drawingml.x2006.main.STTextFontAlignType;
+import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
private <T> boolean fetchParagraphProperty(ParagraphPropertyFetcher<T> visitor){
boolean ok = false;
- XSLFTextShape shape = getParentShape();
- XSLFSheet sheet = shape.getSheet();
+ final XSLFTextShape shape = getParentShape();
+ final XSLFSheet sheet = shape.getSheet();
- if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr());
- if (ok) return true;
-
- ok = shape.fetchShapeProperty(visitor);
- if (ok) return true;
-
-
- CTPlaceholder ph = shape.getCTPlaceholder();
- if(ph == null){
- // if it is a plain text box then take defaults from presentation.xml
- @SuppressWarnings("resource")
- XMLSlideShow ppt = sheet.getSlideShow();
- CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel());
- if (themeProps != null) ok = visitor.fetch(themeProps);
+ if (!(sheet instanceof XSLFSlideMaster)) {
+ if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr());
+ if (ok) return true;
+
+ ok = shape.fetchShapeProperty(visitor);
+ if (ok) return true;
+
+
+ CTPlaceholder ph = shape.getCTPlaceholder();
+ if(ph == null){
+ // if it is a plain text box then take defaults from presentation.xml
+ @SuppressWarnings("resource")
+ XMLSlideShow ppt = sheet.getSlideShow();
+ CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel());
+ if (themeProps != null) ok = visitor.fetch(themeProps);
+ }
+ if (ok) return true;
}
- if (ok) return true;
// defaults for placeholders are defined in the slide master
CTTextParagraphProperties defaultProps = getDefaultMasterStyle();
}
}
}
-
+
+ @Override
+ public List<XSLFTabStop> getTabStops() {
+ ParagraphPropertyFetcher<List<XSLFTabStop>> fetcher = new ParagraphPropertyFetcher<List<XSLFTabStop>>(getIndentLevel()){
+ public boolean fetch(CTTextParagraphProperties props) {
+ if (props.isSetTabLst()) {
+ final List<XSLFTabStop> list = new ArrayList<>();
+ for (final CTTextTabStop ta : props.getTabLst().getTabArray()) {
+ list.add(new XSLFTabStop(ta));
+ }
+ setValue(list);
+ return true;
+ }
+ return false;
+ }
+ };
+ fetchParagraphProperty(fetcher);
+ return fetcher.getValue();
+ }
+
+ @Override
+ public void addTabStops(double positionInPoints, TabStopType tabStopType) {
+ final XSLFSheet sheet = getParentShape().getSheet();
+ final CTTextParagraphProperties tpp;
+ if (sheet instanceof XSLFSlideMaster) {
+ tpp = getDefaultMasterStyle();
+ } else {
+ final CTTextParagraph xo = getXmlObject();
+ tpp = (xo.isSetPPr()) ? xo.getPPr() : xo.addNewPPr();
+ }
+ final CTTextTabStopList stl = (tpp.isSetTabLst()) ? tpp.getTabLst() : tpp.addNewTabLst();
+ XSLFTabStop tab = new XSLFTabStop(stl.addNewTab());
+ tab.setPositionInPoints(positionInPoints);
+ tab.setType(tabStopType);
+ }
+
+ @Override
+ public void clearTabStops() {
+ final XSLFSheet sheet = getParentShape().getSheet();
+ CTTextParagraphProperties tpp = (sheet instanceof XSLFSlideMaster) ? getDefaultMasterStyle() : getXmlObject().getPPr();
+ if (tpp != null && tpp.isSetTabLst()) {
+ tpp.unsetTabLst();
+ }
+ }
+
/**
* Helper method for appending text and keeping paragraph and character properties.
* The character properties are moved to the end paragraph marker
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.usermodel.BaseTestSlideShow;
+import org.apache.poi.sl.usermodel.SlideShow;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
xmlComments.close();
xml.close();
}
+
+ public SlideShow<?, ?> reopen(SlideShow<?, ?> show) {
+ return reopen((XMLSlideShow)show);
+ }
+
+ public static XMLSlideShow reopen(XMLSlideShow show) {
+ try {
+ BufAccessBAOS bos = new BufAccessBAOS();
+ show.write(bos);
+ return new XMLSlideShow(new ByteArrayInputStream(bos.getBuf()));
+ } catch (IOException e) {
+ fail(e.getMessage());
+ return null;
+ }
+ }
+
+ private static class BufAccessBAOS extends ByteArrayOutputStream {
+ public byte[] getBuf() {
+ return buf;
+ }
+ }
}
--- /dev/null
+/* ====================================================================
+ 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.textproperties;
+
+import org.apache.poi.sl.usermodel.TabStop;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.Units;
+
+@Internal
+public class HSLFTabStop implements TabStop, Cloneable {
+ /**
+ * A signed integer that specifies an offset, in master units, of the tab stop.
+ *
+ * If the TextPFException record that contains this TabStop structure also contains a
+ * leftMargin, then the value of position is relative to the left margin of the paragraph;
+ * otherwise, the value is relative to the left side of the paragraph.
+ *
+ * If a TextRuler record contains this TabStop structure, the value is relative to the
+ * left side of the text ruler.
+ */
+ private int position;
+
+ /**
+ * A enumeration that specifies how text aligns at the tab stop.
+ */
+ private TabStopType type;
+
+ public HSLFTabStop(int position, TabStopType type) {
+ this.position = position;
+ this.type = type;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+ public void setPosition(final int position) {
+ this.position = position;
+ }
+
+ @Override
+ public double getPositionInPoints() {
+ return Units.masterToPoints(getPosition());
+ }
+
+ @Override
+ public void setPositionInPoints(final double points) {
+ setPosition(Units.pointsToMaster(points));
+ }
+
+ @Override
+ public TabStopType getType() {
+ return type;
+ }
+
+ @Override
+ public void setType(TabStopType type) {
+ this.type = type;
+ }
+
+ @Override
+ public HSLFTabStop clone() {
+ try {
+ return (HSLFTabStop)super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + position;
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof HSLFTabStop)) {
+ return false;
+ }
+ HSLFTabStop other = (HSLFTabStop) obj;
+ if (position != other.position) {
+ return false;
+ }
+ if (type != other.type) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return type + " @ " + position;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.textproperties;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.sl.usermodel.TabStop.TabStopType;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
+import org.apache.poi.util.LittleEndianOutputStream;
+
+/**
+ * Container for tabstop lists
+ */
+@Internal
+public class HSLFTabStopPropCollection extends TextProp {
+ public static final String NAME = "tabStops";
+
+ private final List<HSLFTabStop> tabStops = new ArrayList<>();
+
+ public HSLFTabStopPropCollection() {
+ super(0, 0x100000, NAME);
+ }
+
+ public HSLFTabStopPropCollection(final HSLFTabStopPropCollection copy) {
+ super(0, copy.getMask(), copy.getName());
+ for (HSLFTabStop ts : copy.tabStops) {
+ tabStops.add(ts.clone());
+ }
+ }
+
+ /**
+ * Parses the tabstops from TxMasterStyle record
+ *
+ * @param data the data stream
+ * @param offset the offset within the data
+ */
+ public void parseProperty(byte data[], int offset) {
+ tabStops.addAll(readTabStops(new LittleEndianByteArrayInputStream(data, offset)));
+ }
+
+ public static List<HSLFTabStop> readTabStops(final LittleEndianInput lei) {
+ final int count = lei.readUShort();
+ final List<HSLFTabStop> tabs = new ArrayList<>(count);
+ for (int i=0; i<count; i++) {
+ final int position = lei.readShort();
+ final TabStopType type = TabStopType.fromNativeId(lei.readShort());
+ tabs.add(new HSLFTabStop(position, type));
+ }
+ return tabs;
+ }
+
+
+ public void writeProperty(OutputStream out) {
+ writeTabStops(new LittleEndianOutputStream(out), tabStops);
+ }
+
+ public static void writeTabStops(final LittleEndianOutput leo, List<HSLFTabStop> tabStops) {
+ final int count = tabStops.size();
+ leo.writeShort(count);
+ for (HSLFTabStop ts : tabStops) {
+ leo.writeShort(ts.getPosition());
+ leo.writeShort(ts.getType().nativeId);
+ }
+
+ }
+
+ @Override
+ public int getValue() { return tabStops.size(); }
+
+
+ @Override
+ public int getSize() {
+ return LittleEndianConsts.SHORT_SIZE + tabStops.size()*LittleEndianConsts.INT_SIZE;
+ }
+
+ public List<HSLFTabStop> getTabStops() {
+ return tabStops;
+ }
+
+ public void clearTabs() {
+ tabStops.clear();
+ }
+
+ public void addTabStop(HSLFTabStop ts) {
+ tabStops.add(ts);
+ }
+
+ @Override
+ public HSLFTabStopPropCollection clone() {
+ return new HSLFTabStopPropCollection(this);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result
+ + ((tabStops == null) ? 0 : tabStops.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof HSLFTabStopPropCollection)) {
+ return false;
+ }
+ HSLFTabStopPropCollection other = (HSLFTabStopPropCollection) obj;
+ if (!super.equals(other)) {
+ return false;
+ }
+
+ return tabStops.equals(other.tabStops);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder(super.toString());
+ sb.append(" [ ");
+ boolean isFirst = true;
+ for (HSLFTabStop tabStop : tabStops) {
+ if (!isFirst) {
+ sb.append(", ");
+ }
+ sb.append(tabStop.getType());
+ sb.append(" @ ");
+ sb.append(tabStop.getPosition());
+ isFirst = false;
+ }
+ sb.append(" ]");
+
+ return sb.toString();
+ }
+
+}
+++ /dev/null
-/* ====================================================================
- 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.textproperties;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.LittleEndianConsts;
-
-/**
- * Container for tabstop lists
- */
-public class TabStopPropCollection extends TextProp {
- public enum TabStopType {
- LEFT(0), CENTER(1), RIGHT(2), DECIMAL(3);
- private final int val;
- TabStopType(int val) {
- this.val = val;
- }
- public static TabStopType fromRecordVal(int val) {
- for (TabStopType tst : values()) {
- if (tst.val == val) return tst;
- }
- return LEFT;
- }
- }
-
- public static class TabStop {
- /**
- * If the TextPFException record that contains this TabStop structure also contains a
- * leftMargin, then the value of position is relative to the left margin of the paragraph;
- * otherwise, the value is relative to the left side of the paragraph.
- *
- * If a TextRuler record contains this TabStop structure, the value is relative to the
- * left side of the text ruler.
- */
- private int position;
-
- /**
- * A enumeration that specifies how text aligns at the tab stop.
- */
- private TabStopType type;
-
- public TabStop(int position, TabStopType type) {
- this.position = position;
- this.type = type;
- }
-
- public int getPosition() {
- return position;
- }
-
- public void setPosition(int position) {
- this.position = position;
- }
-
- public TabStopType getType() {
- return type;
- }
-
- public void setType(TabStopType type) {
- this.type = type;
- }
- }
-
- private List<TabStop> tabStops = new ArrayList<>();
-
- public TabStopPropCollection() {
- super(0, 0x100000, "tabStops");
- }
-
- /**
- * Parses the tabstops from TxMasterStyle record
- *
- * @param data the data stream
- * @param offset the offset within the data
- */
- public void parseProperty(byte data[], int offset) {
- int count = LittleEndian.getUShort(data, offset);
- int off = offset + LittleEndianConsts.SHORT_SIZE;
- for (int i=0; i<count; i++) {
- int position = LittleEndian.getShort(data, off);
- off += LittleEndianConsts.SHORT_SIZE;
- int recVal = LittleEndian.getShort(data, off);
- TabStopType type = TabStopType.fromRecordVal(recVal);
- off += LittleEndianConsts.SHORT_SIZE;
- tabStops.add(new TabStop(position, type));
-
- }
- }
-
- @Override
- public int getSize() {
- return LittleEndianConsts.SHORT_SIZE + tabStops.size()*LittleEndianConsts.INT_SIZE;
- }
-
- @Override
- public TabStopPropCollection clone() {
- TabStopPropCollection other = (TabStopPropCollection)super.clone();
- other.tabStops = new ArrayList<>();
- for (TabStop ts : tabStops) {
- TabStop tso = new TabStop(ts.getPosition(), ts.getType());
- other.tabStops.add(tso);
- }
- return other;
- }
-}
try {
return (TextProp)super.clone();
} catch(CloneNotSupportedException e) {
- throw new InternalError(e.getMessage());
+ throw new IllegalStateException(e);
}
}
@Override
public String toString() {
int len;
- switch (sizeOfDataBlock) {
+ switch (getSize()) {
case 1: len = 4; break;
case 2: len = 6; break;
default: len = 10; break;
}
- return String.format(Locale.ROOT, "%s = %d (%0#"+len+"X mask / %d bytes)", propName, dataValue, maskInHeader, sizeOfDataBlock);
+ return String.format(Locale.ROOT, "%s = %d (%0#"+len+"X mask / %d bytes)", getName(), getValue(), getMask(), getSize());
}
}
\ No newline at end of file
// 0x200 - Undefined and MUST be ignored
new TextProp(2, 0x400, "bullet.offset"), // indent
new TextProp(2, 0x8000, "defaultTabSize"),
- new TabStopPropCollection(), // tabstops size is variable!
+ new HSLFTabStopPropCollection(), // tabstops size is variable!
new FontAlignmentProp(),
new WrapFlagsTextProp(),
new TextProp(2, 0x200000, "textDirection"),
}
/** Fetch the TextProp with this name, or null if it isn't present */
- public final TextProp findByName(String textPropName) {
- return textProps.get(textPropName);
+ @SuppressWarnings("unchecked")
+ public final <T extends TextProp> T findByName(String textPropName) {
+ return (T)textProps.get(textPropName);
}
- public final TextProp removeByName(String name) {
- return textProps.remove(name);
+ @SuppressWarnings("unchecked")
+ public final <T extends TextProp> T removeByName(String name) {
+ return (T)textProps.remove(name);
}
public final TextPropType getTextPropType() {
* @param name the property name
* @return if found, the property template to copy from
*/
- private TextProp validatePropName(String name) {
+ @SuppressWarnings("unchecked")
+ private <T extends TextProp> T validatePropName(final String name) {
for (TextProp tp : getPotentialProperties()) {
if (tp.getName().equals(name)) {
- return tp;
+ return (T)tp;
}
}
String errStr =
}
/** Add the TextProp with this name to the list */
- public final TextProp addWithName(String name) {
+ @SuppressWarnings("unchecked")
+ public final <T extends TextProp> T addWithName(final String name) {
// Find the base TextProp to base on
- TextProp existing = findByName(name);
+ T existing = findByName(name);
if (existing != null) return existing;
// Add a copy of this property
- TextProp textProp = validatePropName(name).clone();
+ T textProp = (T)validatePropName(name).clone();
textProps.put(name,textProp);
return textProp;
}
// Bingo, data contains this property
TextProp prop = tp.clone();
int val = 0;
- if (prop.getSize() == 2) {
+ if (prop instanceof HSLFTabStopPropCollection) {
+ ((HSLFTabStopPropCollection)prop).parseProperty(data, dataOffset+bytesPassed);
+ } else if (prop.getSize() == 2) {
val = LittleEndian.getShort(data,dataOffset+bytesPassed);
} else if(prop.getSize() == 4) {
val = LittleEndian.getInt(data,dataOffset+bytesPassed);
- } else if (prop.getSize() == 0 && !(prop instanceof TabStopPropCollection)) {
+ } else if (prop.getSize() == 0) {
//remember "special" bits.
maskSpecial |= tp.getMask();
continue;
if (prop instanceof BitMaskTextProp) {
((BitMaskTextProp)prop).setValueWithMask(val, containsField);
- } else if (prop instanceof TabStopPropCollection) {
- ((TabStopPropCollection)prop).parseProperty(data, dataOffset+bytesPassed);
- } else {
+ } else if (!(prop instanceof HSLFTabStopPropCollection)) {
prop.setValue(val);
}
bytesPassed += prop.getSize();
StyleTextPropAtom.writeLittleEndian((short)val,o);
} else if (textProp.getSize() == 4) {
StyleTextPropAtom.writeLittleEndian(val,o);
+ } else if (textProp instanceof HSLFTabStopPropCollection) {
+ ((HSLFTabStopPropCollection)textProp).writeProperty(o);
}
}
}
out.append(" indent level: "+getIndentLevel()+"\n");
}
for(TextProp p : getTextPropList()) {
- out.append(" " + p.getName() + " = " + p.getValue() );
- out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n");
+ out.append(" ");
+ out.append(p.toString());
+ out.append("\n");
if (p instanceof BitMaskTextProp) {
BitMaskTextProp bm = (BitMaskTextProp)p;
int i = 0;
package org.apache.poi.hslf.record;
+import static org.apache.poi.util.BitFieldFactory.getInstance;
+
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
-import org.apache.poi.util.IOUtils;
+import org.apache.poi.hslf.model.textproperties.HSLFTabStop;
+import org.apache.poi.hslf.model.textproperties.HSLFTabStopPropCollection;
+import org.apache.poi.util.BitField;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianOutputStream;
import org.apache.poi.util.POILogger;
/**
//arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000;
+
+ private static final BitField DEFAULT_TAB_SIZE = getInstance(0x0001);
+ private static final BitField C_LEVELS = getInstance(0x0002);
+ private static final BitField TAB_STOPS = getInstance(0x0004);
+ private static final BitField[] LEFT_MARGIN = {
+ getInstance(0x0008), getInstance(0x0010), getInstance(0x0020),
+ getInstance(0x0040), getInstance(0x0080),
+ };
+ private static final BitField[] INDENT = {
+ getInstance(0x0100), getInstance(0x0200), getInstance(0x0400),
+ getInstance(0x0800), getInstance(0x1000),
+ };
/**
* Record header.
*/
- private byte[] _header;
-
- /**
- * Record data.
- */
- private byte[] _data;
+ private final byte[] _header = new byte[8];
//ruler internals
- private int defaultTabSize;
- private int numLevels;
- private int[] tabStops;
- private int[] bulletOffsets = new int[5];
- private int[] textOffsets = new int[5];
+ private Integer defaultTabSize;
+ private Integer numLevels;
+ private final List<HSLFTabStop> tabStops = new ArrayList<>();
+ //bullet.offset
+ private final Integer[] leftMargin = new Integer[5];
+ //text.offset
+ private final Integer[] indent = new Integer[5];
/**
* Constructs a new empty ruler atom.
*/
public TextRulerAtom() {
- _header = new byte[8];
- _data = new byte[0];
-
LittleEndian.putShort(_header, 2, (short)getRecordType());
- LittleEndian.putInt(_header, 4, _data.length);
}
/**
* @param start the start offset into the byte array.
* @param len the length of the slice in the byte array.
*/
- protected TextRulerAtom(byte[] source, int start, int len) {
- // Get the header.
- _header = new byte[8];
- System.arraycopy(source,start,_header,0,8);
-
- // Get the record data.
- _data = IOUtils.safelyAllocate(len-8, MAX_RECORD_LENGTH);
- System.arraycopy(source,start+8,_data,0,len-8);
+ protected TextRulerAtom(final byte[] source, final int start, final int len) {
+ final LittleEndianByteArrayInputStream leis = new LittleEndianByteArrayInputStream(source, start, Math.min(len, MAX_RECORD_LENGTH));
+
try {
- read();
- } catch (Exception e){
+ // Get the header.
+ leis.read(_header);
+
+ // Get the record data.
+ read(leis);
+ } catch (IOException e){
logger.log(POILogger.ERROR, "Failed to parse TextRulerAtom: " + e.getMessage());
}
}
*
* @return the record type.
*/
+ @Override
public long getRecordType() {
return RecordTypes.TextRulerAtom.typeID;
}
* @param out the output stream to write to.
* @throws java.io.IOException if an error occurs.
*/
- public void writeOut(OutputStream out) throws IOException {
+ @Override
+ public void writeOut(final OutputStream out) throws IOException {
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream(200);
+ final LittleEndianOutputStream lbos = new LittleEndianOutputStream(bos);
+ int mask = 0;
+ mask |= writeIf(lbos, numLevels, C_LEVELS);
+ mask |= writeIf(lbos, defaultTabSize, DEFAULT_TAB_SIZE);
+ mask |= writeIf(lbos, tabStops, TAB_STOPS);
+ for (int i=0; i<5; i++) {
+ mask |= writeIf(lbos, leftMargin[i], LEFT_MARGIN[i]);
+ mask |= writeIf(lbos, indent[i], INDENT[i]);
+ }
+ LittleEndian.putInt(_header, 4, bos.size()+4);
out.write(_header);
- out.write(_data);
+ LittleEndian.putUShort(mask, out);
+ LittleEndian.putUShort(0, out);
+ bos.writeTo(out);
}
+ private static int writeIf(final LittleEndianOutputStream lbos, Integer value, BitField bit) {
+ boolean isSet = false;
+ if (value != null) {
+ lbos.writeShort(value);
+ isSet = true;
+ }
+ return bit.setBoolean(0, isSet);
+ }
+
+ private static int writeIf(final LittleEndianOutputStream lbos, List<HSLFTabStop> value, BitField bit) {
+ boolean isSet = false;
+ if (value != null && !value.isEmpty()) {
+ HSLFTabStopPropCollection.writeTabStops(lbos, value);
+ isSet = true;
+ }
+ return bit.setBoolean(0, isSet);
+ }
+
/**
* Read the record bytes and initialize the internal variables
*/
- private void read(){
- int pos = 0;
- short mask = LittleEndian.getShort(_data); pos += 4;
- short val;
- int[] bits = {1, 0, 2, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12};
- for (int i = 0; i < bits.length; i++) {
- if((mask & 1 << bits[i]) != 0){
- switch (bits[i]){
- case 0:
- //defaultTabSize
- defaultTabSize = LittleEndian.getShort(_data, pos); pos += 2;
- break;
- case 1:
- //numLevels
- numLevels = LittleEndian.getShort(_data, pos); pos += 2;
- break;
- case 2:
- //tabStops
- val = LittleEndian.getShort(_data, pos); pos += 2;
- tabStops = new int[val*2];
- for (int j = 0; j < tabStops.length; j++) {
- tabStops[j] = LittleEndian.getUShort(_data, pos); pos += 2;
- }
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- //bullet.offset
- val = LittleEndian.getShort(_data, pos); pos += 2;
- bulletOffsets[bits[i]-3] = val;
- break;
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- //text.offset
- val = LittleEndian.getShort(_data, pos); pos += 2;
- textOffsets[bits[i]-8] = val;
- break;
- default:
- break;
- }
- }
+ private void read(final LittleEndianByteArrayInputStream leis) {
+ final int mask = leis.readInt();
+ numLevels = readIf(leis, mask, C_LEVELS);
+ defaultTabSize = readIf(leis, mask, DEFAULT_TAB_SIZE);
+ if (TAB_STOPS.isSet(mask)) {
+ tabStops.addAll(HSLFTabStopPropCollection.readTabStops(leis));
+ }
+ for (int i=0; i<5; i++) {
+ leftMargin[i] = readIf(leis, mask, LEFT_MARGIN[i]);
+ indent[i] = readIf(leis, mask, INDENT[i]);
}
}
+ private static Integer readIf(final LittleEndianByteArrayInputStream leis, final int mask, final BitField bit) {
+ return (bit.isSet(mask)) ? (int)leis.readShort() : null;
+ }
+
/**
* Default distance between tab stops, in master coordinates (576 dpi).
*/
public int getDefaultTabSize(){
- return defaultTabSize;
+ return defaultTabSize == null ? 0 : defaultTabSize;
}
/**
* Number of indent levels (maximum 5).
*/
public int getNumberOfLevels(){
- return numLevels;
+ return numLevels == null ? 0 : numLevels;
}
/**
* Default distance between tab stops, in master coordinates (576 dpi).
*/
- public int[] getTabStops(){
+ public List<HSLFTabStop> getTabStops(){
return tabStops;
}
/**
* Paragraph's distance from shape's left margin, in master coordinates (576 dpi).
*/
- public int[] getTextOffsets(){
- return textOffsets;
+ public Integer[] getTextOffsets(){
+ return indent;
}
/**
* First line of paragraph's distance from shape's left margin, in master coordinates (576 dpi).
*/
- public int[] getBulletOffsets(){
- return bulletOffsets;
+ public Integer[] getBulletOffsets(){
+ return leftMargin;
}
public static TextRulerAtom getParagraphInstance(){
- byte[] data = new byte[] {
- 0x00, 0x00, (byte)0xA6, 0x0F, 0x0A, 0x00, 0x00, 0x00,
- 0x10, 0x03, 0x00, 0x00, (byte)0xF9, 0x00, 0x41, 0x01, 0x41, 0x01
- };
- return new TextRulerAtom(data, 0, data.length);
+ final TextRulerAtom tra = new TextRulerAtom();
+ tra.indent[0] = 249;
+ tra.indent[1] = tra.leftMargin[1] = 321;
+ return tra;
}
- public void setParagraphIndent(short tetxOffset, short bulletOffset){
- LittleEndian.putShort(_data, 4, tetxOffset);
- LittleEndian.putShort(_data, 6, bulletOffset);
- LittleEndian.putShort(_data, 8, bulletOffset);
+ public void setParagraphIndent(short leftMargin, short indent) {
+ Arrays.fill(this.leftMargin, null);
+ Arrays.fill(this.indent, null);
+ this.leftMargin[0] = (int)leftMargin;
+ this.indent[0] = (int)indent;
+ this.indent[1] = (int)indent;
}
}
package org.apache.poi.hslf.usermodel;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.SheetContainer;
-import org.apache.poi.hslf.model.textproperties.TextProp;
+import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.sl.usermodel.MasterSheet;
/**
* The superclass of all master sheets - Slide masters, Notes masters, etc.
- *
- * For now it's empty. When we understand more about masters in ppt we will add the common functionality here.
- *
- * @author Yegor Kozlov
*/
public abstract class HSLFMasterSheet extends HSLFSheet implements MasterSheet<HSLFShape,HSLFTextParagraph> {
public HSLFMasterSheet(SheetContainer container, int sheetNo){
}
/**
- * Pickup a style attribute from the master.
- * This is the "workhorse" which returns the default style attrubutes.
+ * Find the master collection for the given txtype/level/name.
+ * This is the "workhorse" which returns the default style attributes.
+ * If {@code name = "*"} return the current collection, otherwise if the name is not found
+ * in the current selection of txtype/level/name, first try lower levels then try parent types,
+ * if it wasn't found there return {@code null}.
+ *
+ * @param txtype the {@link TextHeaderAtom} type
+ * @param level the indent level of the paragraph, if the level is not defined for the found
+ * collection, the highest existing level will be used
+ * @param name the property name,
+ * @param isCharacter if {@code true} use character styles, otherwise use paragraph styles
*/
- public abstract TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) ;
+ public abstract TextPropCollection getPropCollection(int txtype, int level, String name, boolean isCharacter);
/**
}
/**
- * Pickup a style attribute from the master.
+ * Find the master collection for the given txtype/level/name.
* This is the "workhorse" which returns the default style attributes.
+ * If {@code name = "*"} return the current collection, otherwise if the name is not found
+ * in the current selection of txtype/level/name, first try lower levels then try parent types,
+ * if it wasn't found there return {@code null}.
+ *
+ * @param txtype the {@link TextHeaderAtom} type
+ * @param level the indent level of the paragraph, if the level is not defined for the found
+ * collection, the highest existing level will be used
+ * @param name the property name,
+ * @param isCharacter if {@code true} use character styles, otherwise use paragraph styles
*/
@Override
- public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
- if (_txmaster.length <= txtype) {
- return null;
- }
- TxMasterStyleAtom t = _txmaster[txtype];
- List<TextPropCollection> styles = isCharacter ? t.getCharacterStyles() : t.getParagraphStyles();
-
- TextProp prop = null;
- for (int i = Math.min(level, styles.size()-1); prop == null && i >= 0; i--) {
- prop = styles.get(i).findByName(name);
+ public TextPropCollection getPropCollection(final int txtype, final int level, final String name, final boolean isCharacter) {
+ if (txtype < _txmaster.length) {
+ final TxMasterStyleAtom t = _txmaster[txtype];
+ final List<TextPropCollection> styles = isCharacter ? t.getCharacterStyles() : t.getParagraphStyles();
+ // TODO: what is the reaction for readOnly=false and styles.isEmpty()?
+ final int minLevel = Math.min(level, styles.size()-1);
+ if ("*".equals(name)) {
+ return styles.get(minLevel);
+ }
+
+ for (int i=minLevel; i >= 0; i--) {
+ final TextPropCollection col = styles.get(i);
+ final TextProp tp = col.findByName(name);
+ if (tp != null) {
+ return col;
+ }
+ }
}
- if (prop != null) {
- return prop;
- }
-
switch (txtype) {
case TextHeaderAtom.CENTRE_BODY_TYPE:
case TextHeaderAtom.HALF_BODY_TYPE:
case TextHeaderAtom.QUARTER_BODY_TYPE:
- txtype = TextHeaderAtom.BODY_TYPE;
- break;
+ return getPropCollection(TextHeaderAtom.BODY_TYPE, level, name, isCharacter);
case TextHeaderAtom.CENTER_TITLE_TYPE:
- txtype = TextHeaderAtom.TITLE_TYPE;
- break;
+ return getPropCollection(TextHeaderAtom.TITLE_TYPE, level, name, isCharacter);
default:
return null;
}
-
- return getStyleAttribute(txtype, level, name, isCharacter);
}
-
+
/**
* Assign SlideShow for this slide master.
*/
_txmaster[txType] = txrec[i];
}
}
-
+
for (List<HSLFTextParagraph> paras : getTextParagraphs()) {
for (HSLFTextParagraph htp : paras) {
int txType = htp.getRunType();
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 java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
import org.apache.poi.common.usermodel.fonts.FontGroup;
import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
import org.apache.poi.hslf.model.textproperties.FontAlignmentProp;
+import org.apache.poi.hslf.model.textproperties.HSLFTabStop;
+import org.apache.poi.hslf.model.textproperties.HSLFTabStopPropCollection;
import org.apache.poi.hslf.model.textproperties.IndentProp;
import org.apache.poi.hslf.model.textproperties.ParagraphFlagsTextProp;
import org.apache.poi.hslf.model.textproperties.TextAlignmentProp;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
-import org.apache.poi.hslf.record.ColorSchemeAtom;
-import org.apache.poi.hslf.record.EscherTextboxWrapper;
-import org.apache.poi.hslf.record.InteractiveInfo;
-import org.apache.poi.hslf.record.MasterTextPropAtom;
-import org.apache.poi.hslf.record.OutlineTextRefAtom;
-import org.apache.poi.hslf.record.PPDrawing;
-import org.apache.poi.hslf.record.Record;
-import org.apache.poi.hslf.record.RecordContainer;
-import org.apache.poi.hslf.record.RecordTypes;
-import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
-import org.apache.poi.hslf.record.SlideListWithText;
-import org.apache.poi.hslf.record.SlidePersistAtom;
-import org.apache.poi.hslf.record.StyleTextProp9Atom;
-import org.apache.poi.hslf.record.StyleTextPropAtom;
-import org.apache.poi.hslf.record.TextBytesAtom;
-import org.apache.poi.hslf.record.TextCharsAtom;
-import org.apache.poi.hslf.record.TextHeaderAtom;
-import org.apache.poi.hslf.record.TextRulerAtom;
-import org.apache.poi.hslf.record.TextSpecInfoAtom;
-import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
+import org.apache.poi.hslf.record.*;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
-import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.Placeholder;
+import org.apache.poi.sl.usermodel.TabStop;
+import org.apache.poi.sl.usermodel.TabStop.TabStopType;
import org.apache.poi.sl.usermodel.TextParagraph;
-import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.StringUtil;
private TextBytesAtom _byteAtom;
private TextCharsAtom _charAtom;
private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
- private TextPropCollection _masterStyle;
protected TextRulerAtom _ruler;
protected final List<HSLFTextRun> _runs = new ArrayList<>();
private final List<HSLFTextParagraph> parentList;
+ private class HSLFTabStopDecorator implements TabStop {
+ final HSLFTabStop tabStop;
+
+ HSLFTabStopDecorator(final HSLFTabStop tabStop) {
+ this.tabStop = tabStop;
+ }
+
+ public double getPositionInPoints() {
+ return tabStop.getPositionInPoints();
+ }
+
+ public void setPositionInPoints(double position) {
+ tabStop.setPositionInPoints(position);
+ setDirty();
+ }
+
+ public TabStopType getType() {
+ return tabStop.getType();
+ }
+
+ public void setType(TabStopType type) {
+ tabStop.setType(type);
+ setDirty();
+ }
+ }
+
+
/**
* Constructs a Text Run from a Unicode text block.
* Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided.
_paragraphStyle.copy(paragraphStyle);
}
- /**
- * Setting a master style reference
- *
- * @param paragraphStyle the master style reference
- *
- * @since POI 3.14-Beta1
- */
- @Internal
- /* package */ void setMasterStyleReference(TextPropCollection masterStyle) {
- _masterStyle = masterStyle;
- }
-
/**
* Supply the Sheet we belong to, which might have an assigned SlideShow
* Also passes it on to our child RichTextRuns
@Override
public Double getLeftMargin() {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "text.offset");
+ TextProp tp = getPropVal(_paragraphStyle, "text.offset");
return (tp == null) ? null : Units.masterToPoints(tp.getValue());
}
@Override
public Double getIndent() {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.offset");
+ TextProp tp = getPropVal(_paragraphStyle, "bullet.offset");
return (tp == null) ? null : Units.masterToPoints(tp.getValue());
}
if (fontInfo == null) {
fontInfo = HSLFFontInfoPredefined.ARIAL;
}
-
+
return fontInfo.getTypeface();
}
@Override
public TextAlign getTextAlign() {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "alignment");
+ TextProp tp = getPropVal(_paragraphStyle, "alignment");
if (tp == null) {
return null;
}
@Override
public FontAlign getFontAlign() {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, FontAlignmentProp.NAME);
+ TextProp tp = getPropVal(_paragraphStyle, FontAlignmentProp.NAME);
if (tp == null) {
return null;
}
* Returns the bullet character
*/
public Character getBulletChar() {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.char");
+ TextProp tp = getPropVal(_paragraphStyle, "bullet.char");
return (tp == null) ? null : (char)tp.getValue();
}
* Returns the bullet color
*/
public Color getBulletColor() {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.color");
+ TextProp tp = getPropVal(_paragraphStyle, "bullet.color");
boolean hasColor = getFlag(ParagraphFlagsTextProp.BULLET_HARDCOLOR_IDX);
if (tp == null || !hasColor) {
// if bullet color is undefined, return color of first run
*/
public void setBulletFont(String typeface) {
if (typeface == null) {
- setPropVal(_paragraphStyle, _masterStyle, "bullet.font", null);
+ setPropVal(_paragraphStyle, "bullet.font", null);
setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, false);
return;
}
* Returns the bullet font
*/
public String getBulletFont() {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, "bullet.font");
+ TextProp tp = getPropVal(_paragraphStyle, "bullet.font");
boolean hasFont = getFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX);
if (tp == null || !hasFont) {
return getDefaultFontFamily();
return null;
}
+
+ @Override
+ public List<? extends TabStop> getTabStops() {
+ final List<HSLFTabStop> tabStops;
+ final TextRulerAtom textRuler;
+ if (getSheet() instanceof HSLFSlideMaster) {
+ final HSLFTabStopPropCollection tpc = getMasterPropVal(_paragraphStyle, HSLFTabStopPropCollection.NAME);
+ if (tpc == null) {
+ return null;
+ }
+ tabStops = tpc.getTabStops();
+ textRuler = null;
+ } else {
+ textRuler = (TextRulerAtom)_headerAtom.getParentRecord().findFirstOfType(RecordTypes.TextRulerAtom.typeID);
+ if (textRuler == null) {
+ return null;
+ }
+ tabStops = textRuler.getTabStops();
+ }
+
+ return tabStops.stream().map((tabStop) -> new HSLFTabStopDecorator(tabStop)).collect(Collectors.toList());
+ }
+
+ @Override
+ public void addTabStops(final double positionInPoints, final TabStopType tabStopType) {
+ final HSLFTabStop ts = new HSLFTabStop(0, tabStopType);
+ ts.setPositionInPoints(positionInPoints);
+
+ if (getSheet() instanceof HSLFSlideMaster) {
+ final Consumer<HSLFTabStopPropCollection> con = (tp) -> tp.addTabStop(ts);
+ setPropValInner(_paragraphStyle, HSLFTabStopPropCollection.NAME, con);
+ } else {
+ final RecordContainer cont = _headerAtom.getParentRecord();
+ TextRulerAtom textRuler = (TextRulerAtom)cont.findFirstOfType(RecordTypes.TextRulerAtom.typeID);
+ if (textRuler == null) {
+ textRuler = TextRulerAtom.getParagraphInstance();
+ cont.appendChildRecord(textRuler);
+ }
+ textRuler.getTabStops().add(ts);
+ }
+ }
+
+ @Override
+ public void clearTabStops() {
+ if (getSheet() instanceof HSLFSlideMaster) {
+ setPropValInner(_paragraphStyle, HSLFTabStopPropCollection.NAME, null);
+ } else {
+ final RecordContainer cont = _headerAtom.getParentRecord();
+ final TextRulerAtom textRuler = (TextRulerAtom)cont.findFirstOfType(RecordTypes.TextRulerAtom.typeID);
+ if (textRuler == null) {
+ return;
+ }
+ textRuler.getTabStops().clear();
+ }
+ }
+
private Double getPctOrPoints(String propName) {
- TextProp tp = getPropVal(_paragraphStyle, _masterStyle, propName);
+ TextProp tp = getPropVal(_paragraphStyle, propName);
if (tp == null) {
return null;
}
}
private boolean getFlag(int index) {
- BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, _masterStyle, ParagraphFlagsTextProp.NAME);
+ BitMaskTextProp tp = getPropVal(_paragraphStyle, ParagraphFlagsTextProp.NAME);
return (tp == null) ? false : tp.getSubValue(index);
}
* The propName can be a comma-separated list, in case multiple equivalent values
* are queried
*/
- protected TextProp getPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) {
+ protected <T extends TextProp> T getPropVal(TextPropCollection props, String propName) {
String propNames[] = propName.split(",");
for (String pn : propNames) {
- TextProp prop = props.findByName(pn);
+ T prop = props.findByName(pn);
if (isValidProp(prop)) {
return prop;
}
}
- return getMasterPropVal(props, masterProps, propName);
+ return getMasterPropVal(props, propName);
}
- private TextProp getMasterPropVal(TextPropCollection props, TextPropCollection masterProps, String propName) {
+ private <T extends TextProp> T getMasterPropVal(final TextPropCollection props, final String propName) {
boolean isChar = props.getTextPropType() == TextPropType.character;
// check if we can delegate to master for the property
if (!isChar) {
- BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME);
+ BitMaskTextProp maskProp = props.findByName(ParagraphFlagsTextProp.NAME);
boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);
if (hardAttribute) {
return null;
}
}
- String propNames[] = propName.split(",");
- if (masterProps == null) {
- HSLFSheet sheet = getSheet();
- int txtype = getRunType();
- HSLFMasterSheet master = sheet.getMasterSheet();
+ final String propNames[] = propName.split(",");
+ final HSLFSheet sheet = getSheet();
+ final int txtype = getRunType();
+ final HSLFMasterSheet master;
+ if (sheet instanceof HSLFMasterSheet) {
+ master = (HSLFMasterSheet)sheet;
+ } else {
+ master = sheet.getMasterSheet();
if (master == null) {
logger.log(POILogger.WARN, "MasterSheet is not available");
return null;
}
+ }
- for (String pn : propNames) {
- TextProp prop = master.getStyleAttribute(txtype, getIndentLevel(), pn, isChar);
- if (isValidProp(prop)) {
- return prop;
- }
- }
- } else {
- for (String pn : propNames) {
- TextProp prop = masterProps.findByName(pn);
+ for (String pn : propNames) {
+ TextPropCollection masterProps = master.getPropCollection(txtype, getIndentLevel(), pn, isChar);
+ if (masterProps != null) {
+ T prop = masterProps.findByName(pn);
if (isValidProp(prop)) {
return prop;
}
}
}
-
return null;
}
* @param name the name of the TextProp to fetch/add
* @param val the value, null if unset
*/
- protected void setPropVal(TextPropCollection props, TextPropCollection masterProps, String name, Integer val) {
- TextPropCollection pc = props;
- if (getSheet() instanceof MasterSheet && masterProps != null) {
- pc = masterProps;
+ protected void setPropVal(final TextPropCollection props, final String name, final Integer val) {
+ setPropValInner(props, name, val == null ? null : tp -> tp.setValue(val));
+ }
+
+ private void setPropValInner(final TextPropCollection props, final String name, Consumer<? extends TextProp> handler) {
+ final boolean isChar = props.getTextPropType() == TextPropType.character;
+
+ final TextPropCollection pc;
+ if (_sheet instanceof HSLFMasterSheet) {
+ pc = ((HSLFMasterSheet)_sheet).getPropCollection(getRunType(), getIndentLevel(), "*", isChar);
+ if (pc == null) {
+ throw new HSLFException("Master text property collection can't be determined.");
+ }
+ } else {
+ pc = props;
}
- if (val == null) {
+ if (handler == null) {
pc.removeByName(name);
- return;
+ } else {
+ // Fetch / Add the TextProp
+ handler.accept(pc.addWithName(name));
}
-
- // Fetch / Add the TextProp
- TextProp tp = pc.addWithName(name);
- tp.setValue(val);
+ setDirty();
}
+
/**
* Check and add linebreaks to text runs leading other paragraphs
*
* @param val The value to set for the TextProp
*/
public void setParagraphTextPropVal(String propName, Integer val) {
- setPropVal(_paragraphStyle, _masterStyle, propName, val);
+ setPropVal(_paragraphStyle, propName, val);
setDirty();
}
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.sl.usermodel.TextShape;
-import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
*/
private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character);
- private TextPropCollection masterStyle;
-
/**
* Create a new wrapper around a rich text string
* @param parentParagraph the parent paragraph
this.characterStyle.updateTextSize(_runText.length());
}
- /**
- * Setting a master style reference
- *
- * @param characterStyle the master style reference
- *
- * @since POI 3.14-Beta1
- */
- @Internal
- /* package */ void setMasterStyleReference(TextPropCollection masterStyle) {
- this.masterStyle = masterStyle;
- }
-
-
/**
* Supply the SlideShow we belong to
*/
}
protected boolean getFlag(int index) {
- if (characterStyle == null) {
- return false;
- }
-
- BitMaskTextProp prop = (BitMaskTextProp)characterStyle.findByName(CharFlagsTextProp.NAME);
+ BitMaskTextProp prop = (characterStyle == null) ? null : characterStyle.findByName(CharFlagsTextProp.NAME);
if (prop == null || !prop.getSubPropMatches()[index]) {
- int txtype = parentParagraph.getRunType();
- HSLFSheet sheet = parentParagraph.getSheet();
- if (sheet != null) {
- HSLFMasterSheet master = sheet.getMasterSheet();
- if (master != null){
- prop = (BitMaskTextProp)master.getStyleAttribute(txtype, parentParagraph.getIndentLevel(), CharFlagsTextProp.NAME, true);
- }
- } else {
- logger.log(POILogger.WARN, "MasterSheet is not available");
- }
+ prop = getMasterProp(CharFlagsTextProp.NAME);
}
return prop == null ? false : prop.getSubValue(index);
}
+ private <T extends TextProp> T getMasterProp(final String name) {
+ final int txtype = parentParagraph.getRunType();
+ final HSLFSheet sheet = parentParagraph.getSheet();
+ if (sheet == null) {
+ logger.log(POILogger.ERROR, "Sheet is not available");
+ return null;
+ }
+
+ final HSLFMasterSheet master = sheet.getMasterSheet();
+ if (master == null) {
+ logger.log(POILogger.WARN, "MasterSheet is not available");
+ return null;
+ }
+
+ final TextPropCollection col = master.getPropCollection(txtype, parentParagraph.getIndentLevel(), name, true);
+ return (col == null) ? null : col.findByName(name);
+ }
+
+
/**
* Set the value of the given flag in the CharFlagsTextProp, adding
* it if required.
* @param val The value to set for the TextProp
*/
public void setCharTextPropVal(String propName, Integer val) {
- getTextParagraph().setPropVal(characterStyle, masterStyle, propName, val);
- getTextParagraph().setDirty();
+ getTextParagraph().setPropVal(characterStyle, propName, val);
}
* @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript
*/
public int getSuperscript() {
- TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "superscript");
+ TextProp tp = getTextParagraph().getPropVal(characterStyle, "superscript");
return tp == null ? 0 : tp.getValue();
}
@Override
public Double getFontSize() {
- TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "font.size");
+ TextProp tp = getTextParagraph().getPropVal(characterStyle, "font.size");
return tp == null ? null : (double)tp.getValue();
}
* Gets the font index
*/
public int getFontIndex() {
- TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "font.index");
+ TextProp tp = getTextParagraph().getPropVal(characterStyle, "font.index");
return tp == null ? -1 : tp.getValue();
}
break;
}
- TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, propName);
+ TextProp tp = getTextParagraph().getPropVal(characterStyle, propName);
return (tp != null) ? slideShow.getFont(tp.getValue()) : null;
}
*/
@Override
public SolidPaint getFontColor() {
- TextProp tp = getTextParagraph().getPropVal(characterStyle, masterStyle, "font.color");
+ TextProp tp = getTextParagraph().getPropVal(characterStyle, "font.color");
if (tp == null) {
return null;
}
import java.util.ArrayList;
import java.util.List;
-import org.apache.poi.hslf.model.textproperties.TextProp;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.SlideAtom;
/**
* Delegate the call to the underlying slide master.
*/
@Override
- public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
- HSLFMasterSheet master = getMasterSheet();
- return (master == null) ? null : master.getStyleAttribute(txtype, level, name, isCharacter);
+ public TextPropCollection getPropCollection(final int txtype, final int level, final String name, final boolean isCharacter) {
+ final HSLFMasterSheet master = getMasterSheet();
+ return (master == null) ? null : master.getPropCollection(txtype, level, name, isCharacter);
}
-
+
/**
* Returns the slide master for this title master.
*/
package org.apache.poi.hslf.model;
+import static org.apache.poi.hslf.record.TextHeaderAtom.BODY_TYPE;
+import static org.apache.poi.hslf.record.TextHeaderAtom.CENTER_TITLE_TYPE;
+import static org.apache.poi.hslf.record.TextHeaderAtom.CENTRE_BODY_TYPE;
+import static org.apache.poi.hslf.record.TextHeaderAtom.TITLE_TYPE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
+import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.record.Environment;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.usermodel.HSLFMasterSheet;
*/
@Test
public void testSlideMaster() throws IOException {
- HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
+ final HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
- Environment env = ppt.getDocumentRecord().getEnvironment();
+ final Environment env = ppt.getDocumentRecord().getEnvironment();
- List<HSLFSlideMaster> master = ppt.getSlideMasters();
- assertEquals(2, master.size());
+ assertEquals(2, ppt.getSlideMasters().size());
//character attributes
- assertEquals(40, master.get(0).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.size", true).getValue());
- assertEquals(48, master.get(1).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.size", true).getValue());
+ assertEquals(40, getMasterVal(ppt, 0, TITLE_TYPE, "font.size", true));
+ assertEquals(48, getMasterVal(ppt, 1, TITLE_TYPE, "font.size", true));
- int font1 = master.get(0).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.index", true).getValue();
- int font2 = master.get(1).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.index", true).getValue();
+ int font1 = getMasterVal(ppt, 0, TITLE_TYPE, "font.index", true);
+ int font2 = getMasterVal(ppt, 1, TITLE_TYPE, "font.index", true);
assertEquals("Arial", env.getFontCollection().getFontInfo(font1).getTypeface());
assertEquals("Georgia", env.getFontCollection().getFontInfo(font2).getTypeface());
- CharFlagsTextProp prop1 = (CharFlagsTextProp)master.get(0).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "char_flags", true);
+ CharFlagsTextProp prop1 = getMasterProp(ppt, 0, TITLE_TYPE, "char_flags", true);
assertEquals(false, prop1.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(true, prop1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
- CharFlagsTextProp prop2 = (CharFlagsTextProp)master.get(1).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "char_flags", true);
+ CharFlagsTextProp prop2 = getMasterProp(ppt, 1, TITLE_TYPE, "char_flags", true);
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(true, prop2.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
//now paragraph attributes
- assertEquals(0x266B, master.get(0).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.char", false).getValue());
- assertEquals(0x2022, master.get(1).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.char", false).getValue());
+ assertEquals(0x266B, getMasterVal(ppt, 0, BODY_TYPE, "bullet.char", false));
+ assertEquals(0x2022, getMasterVal(ppt, 1, BODY_TYPE, "bullet.char", false));
- int b1 = master.get(0).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.font", false).getValue();
- int b2 = master.get(1).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.font", false).getValue();
+ int b1 = getMasterVal(ppt, 0, BODY_TYPE, "bullet.font", false);
+ int b2 = getMasterVal(ppt, 1, BODY_TYPE, "bullet.font", false);
assertEquals("Arial", env.getFontCollection().getFontInfo(b1).getTypeface());
assertEquals("Georgia", env.getFontCollection().getFontInfo(b2).getTypeface());
ppt.close();
}
+ @SuppressWarnings("unchecked")
+ private static <T extends TextProp> T getMasterProp(HSLFSlideShow ppt, int masterIdx, int txtype, String propName, boolean isCharacter) {
+ return (T)ppt.getSlideMasters().get(masterIdx).getPropCollection(txtype, 0, propName, isCharacter).findByName(propName);
+ }
+
+ private static int getMasterVal(HSLFSlideShow ppt, int masterIdx, int txtype, String propName, boolean isCharacter) {
+ return getMasterProp(ppt, masterIdx, txtype, propName, isCharacter).getValue();
+ }
+
+
/**
* Test we can read default text attributes for a title master sheet
*/
@Test
public void testTitleMasterTextAttributes() throws IOException {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
- List<HSLFTitleMaster> master = ppt.getTitleMasters();
- assertEquals(1, master.size());
+ assertEquals(1, ppt.getTitleMasters().size());
- assertEquals(32, master.get(0).getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "font.size", true).getValue());
- CharFlagsTextProp prop1 = (CharFlagsTextProp)master.get(0).getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "char_flags", true);
- assertEquals(true, prop1.getSubValue(CharFlagsTextProp.BOLD_IDX));
+ assertEquals(40, getMasterVal(ppt, 0, CENTER_TITLE_TYPE, "font.size", true));
+ CharFlagsTextProp prop1 = getMasterProp(ppt, 0, CENTER_TITLE_TYPE, "char_flags", true);
+ assertEquals(false, prop1.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(true, prop1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
- assertEquals(20, master.get(0).getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "font.size", true).getValue());
- CharFlagsTextProp prop2 = (CharFlagsTextProp)master.get(0).getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "char_flags", true);
- assertEquals(true, prop2.getSubValue(CharFlagsTextProp.BOLD_IDX));
+ assertEquals(32, getMasterVal(ppt, 0, CENTRE_BODY_TYPE, "font.size", true));
+ CharFlagsTextProp prop2 = getMasterProp(ppt, 0, CENTRE_BODY_TYPE, "char_flags", true);
+ assertEquals(false, prop2.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
package org.apache.poi.hslf.record;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import java.io.ByteArrayOutputStream;
+import java.util.List;
-import junit.framework.TestCase;
+import org.apache.poi.hslf.model.textproperties.HSLFTabStop;
+import org.junit.Test;
-/**
- * Tests TextRulerAtom
- *
- * @author Yegor Kozlov
- */
-public final class TestTextRulerAtom extends TestCase {
+public final class TestTextRulerAtom {
//from a real file
private final byte[] data_1 = new byte[] {
private final byte[] data_2 = new byte[] {
0x00, 0x00, (byte)0xA6, 0x0F, 0x0A, 0x00, 0x00, 0x00,
- 0x10, 0x03, 0x00, 0x00, (byte)0xF9, 0x00, 0x41, 0x01, 0x41, 0x01
+ 0x08, 0x03, 0x00, 0x00, (byte)0xF9, 0x00, 0x41, 0x01, 0x41, 0x01
};
+ @Test
public void testReadRuler() {
TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length);
assertEquals(ruler.getNumberOfLevels(), 0);
assertEquals(ruler.getDefaultTabSize(), 0);
- int[] tabStops = ruler.getTabStops();
- assertNull(tabStops);
+ List<HSLFTabStop> tabStops = ruler.getTabStops();
+ assertNotNull(tabStops);
- int[] textOffsets = ruler.getTextOffsets();
- assertArrayEquals(new int[]{226, 451, 903, 1129, 1526}, textOffsets);
+ Integer[] textOffsets = ruler.getTextOffsets();
+ assertArrayEquals(new Integer[]{226, 451, 903, 1129, 1526}, textOffsets);
- int[] bulletOffsets = ruler.getBulletOffsets();
- assertArrayEquals(new int[]{117, 345, 794, 1016, 1526}, bulletOffsets);
+ Integer[] bulletOffsets = ruler.getBulletOffsets();
+ assertArrayEquals(new Integer[]{117, 345, 794, 1016, 1526}, bulletOffsets);
}
+ @Test
public void testWriteRuler() throws Exception {
TextRulerAtom ruler = new TextRulerAtom(data_1, 0, data_1.length);
ByteArrayOutputStream out = new ByteArrayOutputStream();
assertArrayEquals(result, data_1);
}
+ @Test
public void testRead2() throws Exception {
TextRulerAtom ruler = TextRulerAtom.getParagraphInstance();
ruler.setParagraphIndent((short)249, (short)321);
ruler.writeOut(out);
byte[] result = out.toByteArray();
- assertArrayEquals(result, data_2);
+ assertArrayEquals(data_2, result);
}
}
package org.apache.poi.hslf.usermodel;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import org.apache.poi.sl.usermodel.BaseTestSlideShow;
+import org.apache.poi.sl.usermodel.SlideShow;
import org.junit.Test;
public class TestHSLFSlideShow extends BaseTestSlideShow {
public void dummy() {
assertNotNull(createSlideShow());
}
+
+ public SlideShow<?, ?> reopen(SlideShow<?, ?> show) {
+ return reopen((HSLFSlideShow)show);
+ }
+
+ public static HSLFSlideShow reopen(HSLFSlideShow show) {
+ try {
+ BufAccessBAOS bos = new BufAccessBAOS();
+ show.write(bos);
+ return new HSLFSlideShow(new ByteArrayInputStream(bos.getBuf()));
+ } catch (IOException e) {
+ fail(e.getMessage());
+ return null;
+ }
+ }
+
+ private static class BufAccessBAOS extends ByteArrayOutputStream {
+ public byte[] getBuf() {
+ return buf;
+ }
+ }
}
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import java.awt.Color;
+import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import org.apache.poi.POIDataSamples;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.sl.usermodel.TabStop.TabStopType;
import org.junit.Test;
public abstract class BaseTestSlideShow {
protected static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
public abstract SlideShow<?, ?> createSlideShow();
+
+ public abstract SlideShow<?, ?> reopen(SlideShow<?, ?> show);
@Test
public void addPicture_File() throws IOException {
show.close();
}
+
+ @Test
+ public void addTabStops() throws IOException {
+ try (final SlideShow<?,?> show1 = createSlideShow()) {
+ // first set the TabStops in the Master sheet
+ final MasterSheet<?, ?> master1 = show1.getSlideMasters().get(0);
+ final AutoShape<?, ?> master1_as = (AutoShape<?,?>)master1.getPlaceholder(Placeholder.BODY);
+ final TextParagraph<?, ?, ? extends TextRun> master1_tp = master1_as.getTextParagraphs().get(0);
+ master1_tp.clearTabStops();
+ int i1 = 0;
+ for (final TabStopType tst : TabStopType.values()) {
+ master1_tp.addTabStops(10+i1*10, tst);
+ i1++;
+ }
+
+ // then set it on a normal slide
+ final Slide<?,?> slide1 = show1.createSlide();
+ final AutoShape<?, ?> slide1_as = slide1.createAutoShape();
+ slide1_as.setText("abc");
+ slide1_as.setAnchor(new Rectangle2D.Double(100,100,100,100));
+ final TextParagraph<?, ?, ? extends TextRun> slide1_tp = slide1_as.getTextParagraphs().get(0);
+ slide1_tp.getTextRuns().get(0).setFontColor(new Color(0x563412));
+ slide1_tp.clearTabStops();
+ int i2 = 0;
+ for (final TabStopType tst : TabStopType.values()) {
+ slide1_tp.addTabStops(15+i2*5, tst);
+ i2++;
+ }
+
+ try (final SlideShow<?, ?> show2 = reopen(show1)) {
+ final MasterSheet<?, ?> master2 = show2.getSlideMasters().get(0);
+ final AutoShape<?, ?> master2_as = (AutoShape<?,?>)master2.getPlaceholder(Placeholder.BODY);
+ final TextParagraph<?, ?, ? extends TextRun> master2_tp = master2_as.getTextParagraphs().get(0);
+ final List<? extends TabStop> master2_tabStops = master2_tp.getTabStops();
+ assertNotNull(master2_tabStops);
+ int i3 = 0;
+ for (final TabStopType tst : TabStopType.values()) {
+ final TabStop ts = master2_tabStops.get(i3);
+ assertEquals(10+i3*10, ts.getPositionInPoints(), 0.0);
+ assertEquals(tst, ts.getType());
+ i3++;
+ }
+
+
+ final Slide<?,?> slide2 = show2.getSlides().get(0);
+ final AutoShape<?,?> slide2_as = (AutoShape<?,?>)slide2.getShapes().get(0);
+ final TextParagraph<?, ?, ? extends TextRun> slide2_tp = slide2_as.getTextParagraphs().get(0);
+ final List<? extends TabStop> slide2_tabStops = slide2_tp.getTabStops();
+ assertNotNull(slide2_tabStops);
+ int i4 = 0;
+ for (final TabStopType tst : TabStopType.values()) {
+ final TabStop ts = slide2_tabStops.get(i4);
+ assertEquals(15+i4*5, ts.getPositionInPoints(), 0.0);
+ assertEquals(tst, ts.getType());
+ i4++;
+ }
+ }
+ }
+ }
}