diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
index 60ab2b120..79ef820ac 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
@@ -32,6 +32,7 @@ import org.apache.poi.hslf.record.HeadersFootersContainer;
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.SSSlideInfoAtom;
import org.apache.poi.hslf.record.SlideAtom;
import org.apache.poi.hslf.record.StyleTextProp9Atom;
import org.apache.poi.hslf.record.TextHeaderAtom;
@@ -488,4 +489,25 @@ public final class Slide extends Sheet
public EscherTextboxWrapper[] getTextboxWrappers() {
return this.getPPDrawing().getTextboxWrappers();
}
+
+ public void setHidden(boolean hidden) {
+ org.apache.poi.hslf.record.Slide cont = getSlideRecord();
+
+ SSSlideInfoAtom slideInfo =
+ (SSSlideInfoAtom)cont.findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID);
+ if (slideInfo == null) {
+ slideInfo = new SSSlideInfoAtom();
+ cont.addChildAfter(slideInfo, cont.findFirstOfType(RecordTypes.SlideAtom.typeID));
+ }
+
+ slideInfo.setEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT, hidden);
+ }
+
+ public boolean getHidden() {
+ SSSlideInfoAtom slideInfo =
+ (SSSlideInfoAtom)getSlideRecord().findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID);
+ return (slideInfo == null)
+ ? false
+ : slideInfo.getEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT);
+ }
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
index 455e261c2..2b2dc4bdd 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
@@ -46,7 +46,7 @@ public final class RecordTypes {
public static final Type SlidePersistAtom = new Type(1011,SlidePersistAtom.class);
public static final Type SSlideLayoutAtom = new Type(1015,null);
public static final Type MainMaster = new Type(1016,MainMaster.class);
- public static final Type SSSlideInfoAtom = new Type(1017,null);
+ public static final Type SSSlideInfoAtom = new Type(1017,SSSlideInfoAtom.class);
public static final Type SlideViewInfo = new Type(1018,null);
public static final Type GuideAtom = new Type(1019,null);
public static final Type ViewInfo = new Type(1020,null);
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/SSSlideInfoAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/SSSlideInfoAtom.java
new file mode 100644
index 000000000..0fbc7ff75
--- /dev/null
+++ b/src/scratchpad/src/org/apache/poi/hslf/record/SSSlideInfoAtom.java
@@ -0,0 +1,289 @@
+/* ====================================================================
+ 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.record;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianConsts;
+
+/**
+ * A SlideShowSlideInfo Atom (type 1017).
+ *
+ *
+ * An atom record that specifies which transition effects to perform
+ * during a slide show, and how to advance to the next presentation slide.
+ *
+ *
+ * Combination of effectType and effectDirection:
+ *
+ * type | description | direction |
+ * 0 | cut | 0x00 = no transition, 0x01 = black transition |
+ * 1 | random | 0x00 |
+ * 2 | blinds | 0x00 = vertical, 0x01 = horizontal |
+ * 3 | checker | like blinds |
+ * 4 | cover | 0x00 = left, 0x01 = up, 0x02 = right, 0x03 = down, 0x04 = left/up, 0x05 = right/up, 0x06 left/down, 0x07 = left/down |
+ * 5 | dissolve | 0x00 |
+ * 6 | fade | 0x00 |
+ * 7 | uncover | like cover |
+ * 8 | random bars | like blinds |
+ * 9 | strips | like 0x04 - 0x07 of cover |
+ * 10 | wipe | like 0x00 - 0x03 of cover |
+ * 11 | box in/out | 0x00 = out, 0x01 = in |
+ * 13 | split | 0x00 = horizontally out, 0x01 = horizontally in, 0x02 = vertically out, 0x03 = vertically in |
+ * 17 | diamond | 0x00 |
+ * 18 | plus | 0x00 |
+ * 19 | wedge | 0x00 |
+ * 20 | push | like 0x00 - 0x03 of cover |
+ * 21 | comb | like blinds |
+ * 22 | newsflash | 0x00 |
+ * 23 | alphafade | 0x00 |
+ * 26 | wheel | number of radial divisions (0x01,0x02,0x03,0x04,0x08) |
+ * 27 | circle | 0x00 |
+ * 255 | undefined | 0x00 |
+ *
+ */
+public class SSSlideInfoAtom extends RecordAtom {
+ /**
+ * A bit that specifies whether the presentation slide can be
+ * manually advanced by the user during the slide show.
+ */
+ public static int MANUAL_ADVANCE_BIT = 1 << 0;
+
+ /**
+ * A bit that specifies whether the corresponding slide is
+ * hidden and is not displayed during the slide show.
+ */
+ public static int HIDDEN_BIT = 1 << 2;
+
+ /**
+ * A bit that specifies whether to play the sound specified by soundIfRef.
+ */
+ public static int SOUND_BIT = 1 << 4;
+
+ /**
+ * A bit that specifies whether the sound specified by soundIdRef is
+ * looped continuously when playing until the next sound plays.
+ */
+ public static int LOOP_SOUND_BIT = 1 << 6;
+
+ /**
+ * A bit that specifies whether to stop any currently playing
+ * sound when the transition starts.
+ */
+ public static int STOP_SOUND_BIT = 1 << 8;
+
+ /**
+ * A bit that specifies whether the slide will automatically
+ * advance after slideTime milliseconds during the slide show.
+ */
+ public static int AUTO_ADVANCE_BIT = 1 << 10;
+
+ /**
+ * A bit that specifies whether to display the cursor during
+ * the slide show.
+ */
+ public static int CURSOR_VISIBLE_BIT = 1 << 12;
+
+ // public static int RESERVED1_BIT = 1 << 1;
+ // public static int RESERVED2_BIT = 1 << 3;
+ // public static int RESERVED3_BIT = 1 << 5;
+ // public static int RESERVED4_BIT = 1 << 7;
+ // public static int RESERVED5_BIT = 1 << 9;
+ // public static int RESERVED6_BIT = 1 << 11;
+ // public static int RESERVED7_BIT = 1 << 13 | 1 << 14 | 1 << 15;
+
+ private static long _type = RecordTypes.SSSlideInfoAtom.typeID;
+
+ private byte[] _header;
+
+ /**
+ * A signed integer that specifies an amount of time, in milliseconds, to wait
+ * before advancing to the next presentation slide. It MUST be greater than or equal to 0 and
+ * less than or equal to 86399000. It MUST be ignored unless AUTO_ADVANCE_BIT is TRUE.
+ */
+ private int _slideTime = 0;
+
+ /**
+ * A SoundIdRef that specifies which sound to play when the transition starts.
+ */
+ private int _soundIdRef = 0;
+
+ /**
+ * A byte that specifies the variant of effectType. In combination of the effectType
+ * there are further restriction and specification of this field.
+ */
+ private short _effectDirection = 0; // byte
+
+ /**
+ * A byte that specifies which transition is used when transitioning to the
+ * next presentation slide during a slide show. Exact rendering of any transition is
+ * determined by the rendering application. As such, the same transition can have
+ * many variations depending on the implementation.
+ */
+ private short _effectType = 0; // byte
+
+ /**
+ * Various flags - see bitmask for more details
+ */
+ private short _effectTransitionFlags = 0;
+
+ /**
+ * A byte value that specifies how long the transition takes to run.
+ * (0x00 = 0.75 seconds, 0x01 = 0.5 seconds, 0x02 = 0.25 seconds)
+ */
+ private short _speed = 0; // byte
+ private byte[] _unused; // 3-byte
+
+ public SSSlideInfoAtom() {
+ _header = new byte[8];
+ LittleEndian.putShort(_header, 0, (short)0);
+ LittleEndian.putShort(_header, 2, (short)_type);
+ LittleEndian.putShort(_header, 4, (short)0x10);
+ LittleEndian.putShort(_header, 6, (short)0);
+ _unused = new byte[3];
+ }
+
+ public SSSlideInfoAtom(byte[] source, int offset, int len) {
+ int ofs = offset;
+
+ // Sanity Checking
+ if(len != 24) len = 24;
+ assert(source.length >= offset+len);
+
+ // Get the header
+ _header = LittleEndian.getByteArray(source,ofs,8);
+ ofs += _header.length;
+
+ assert(LittleEndian.getShort(_header, 0) == 0);
+ assert(LittleEndian.getShort(_header, 2) == RecordTypes.SSSlideInfoAtom.typeID);
+ assert(LittleEndian.getShort(_header, 4) == 0x10);
+ assert(LittleEndian.getShort(_header, 6) == 0);
+
+ _slideTime = LittleEndian.getInt(source, ofs);
+ assert(0 <= _slideTime && _slideTime <= 86399000);
+ ofs += LittleEndianConsts.INT_SIZE;
+ _soundIdRef = LittleEndian.getInt(source, ofs);
+ ofs += LittleEndianConsts.INT_SIZE;
+ _effectDirection = LittleEndian.getUByte(source, ofs);
+ ofs += LittleEndianConsts.BYTE_SIZE;
+ _effectType = LittleEndian.getUByte(source, ofs);
+ ofs += LittleEndianConsts.BYTE_SIZE;
+ _effectTransitionFlags = LittleEndian.getShort(source, ofs);
+ ofs += LittleEndianConsts.SHORT_SIZE;
+ _speed = LittleEndian.getUByte(source, ofs);
+ ofs += LittleEndianConsts.BYTE_SIZE;
+ _unused = LittleEndian.getByteArray(source,ofs,3);
+ }
+
+ /**
+ * Write the contents of the record back, so it can be written
+ * to disk
+ */
+ public void writeOut(OutputStream out) throws IOException {
+ // Header - size or type unchanged
+ out.write(_header);
+ writeLittleEndian(_slideTime, out);
+ writeLittleEndian(_soundIdRef, out);
+
+ byte byteBuf[] = new byte[LittleEndianConsts.BYTE_SIZE];
+ LittleEndian.putUByte(byteBuf, 0, _effectDirection);
+ out.write(byteBuf);
+ LittleEndian.putUByte(byteBuf, 0, _effectType);
+ out.write(byteBuf);
+
+ writeLittleEndian(_effectTransitionFlags, out);
+ LittleEndian.putUByte(byteBuf, 0, _speed);
+ out.write(byteBuf);
+
+ assert(_unused.length == 3);
+ out.write(_unused);
+ }
+
+ /**
+ * We are of type 1017
+ */
+ public long getRecordType() { return _type; }
+
+
+ public int getSlideTime() {
+ return _slideTime;
+ }
+
+ public void setSlideTime(int slideTime) {
+ this._slideTime = slideTime;
+ }
+
+ public int getSoundIdRef() {
+ return _soundIdRef;
+ }
+
+ public void setSoundIdRef(int soundIdRef) {
+ this._soundIdRef = soundIdRef;
+ }
+
+ public short getEffectDirection() {
+ return _effectDirection;
+ }
+
+ public void setEffectDirection(short effectDirection) {
+ this._effectDirection = effectDirection;
+ }
+
+ public short getEffectType() {
+ return _effectType;
+ }
+
+ public void setEffectType(short effectType) {
+ this._effectType = effectType;
+ }
+
+ public short getEffectTransitionFlags() {
+ return _effectTransitionFlags;
+ }
+
+ public void setEffectTransitionFlags(short effectTransitionFlags) {
+ this._effectTransitionFlags = effectTransitionFlags;
+ }
+
+ /**
+ * Use one of the bitmasks MANUAL_ADVANCE_BIT ... CURSOR_VISIBLE_BIT
+ * @param bitmask
+ * @param enabled
+ */
+ public void setEffectTransitionFlagByBit(int bitmask, boolean enabled) {
+ if (enabled) {
+ _effectTransitionFlags |= bitmask;
+ } else {
+ _effectTransitionFlags &= (0xFFFF ^ bitmask);
+ }
+ }
+
+ public boolean getEffectTransitionFlagByBit(int bitmask) {
+ return ((_effectTransitionFlags & bitmask) != 0);
+ }
+
+ public short getSpeed() {
+ return _speed;
+ }
+
+ public void setSpeed(short speed) {
+ this._speed = speed;
+ }
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestSlideAtom.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestSlideAtom.java
index 28b122aba..26e608bc3 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestSlideAtom.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestSlideAtom.java
@@ -17,10 +17,14 @@
package org.apache.poi.hslf.record;
-import org.apache.poi.hslf.record.SlideAtom.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
import junit.framework.TestCase;
-import java.io.ByteArrayOutputStream;
+
+import org.apache.poi.hslf.record.SlideAtom.SSlideLayoutAtom;
+import org.apache.poi.hslf.usermodel.SlideShow;
/**
* Tests that SlideAtom works properly
@@ -71,4 +75,19 @@ public final class TestSlideAtom extends TestCase {
assertEquals(data_a[i],b[i]);
}
}
+
+ public void testSSSlideInfoAtom() throws Exception {
+ SlideShow ss = new SlideShow();
+ org.apache.poi.hslf.model.Slide slide1 = ss.createSlide(), slide2 = ss.createSlide();
+ slide2.setHidden(true);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
+ ss.write(bos);
+ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ ss = new SlideShow(bis);
+ slide1 = ss.getSlides()[0];
+ slide2 = ss.getSlides()[1];
+ assertFalse(slide1.getHidden());
+ assertTrue(slide2.getHidden());
+ }
}