You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SSSlideInfoAtom.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hslf.record;
  16. import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
  17. import java.io.IOException;
  18. import java.io.OutputStream;
  19. import java.util.Arrays;
  20. import java.util.Map;
  21. import java.util.function.Supplier;
  22. import org.apache.poi.util.GenericRecordUtil;
  23. import org.apache.poi.util.LittleEndian;
  24. import org.apache.poi.util.LittleEndianConsts;
  25. /**
  26. * A SlideShowSlideInfo Atom (type 1017).<br>
  27. * <br>
  28. *
  29. * An atom record that specifies which transition effects to perform
  30. * during a slide show, and how to advance to the next presentation slide.<br>
  31. * <br>
  32. *
  33. * Combination of effectType and effectDirection:
  34. * <table>
  35. * <caption>Combination of effectType and effectDirection</caption>
  36. * <tr><th>type</th><th>description</th><th>direction</th></tr>
  37. * <tr><td>0</td><td>cut</td><td>0x00 = no transition, 0x01 = black transition</td></tr>
  38. * <tr><td>1</td><td>random</td><td>0x00</td></tr>
  39. * <tr><td>2</td><td>blinds</td><td>0x00 = vertical, 0x01 = horizontal</td></tr>
  40. * <tr><td>3</td><td>checker</td><td>like blinds</td></tr>
  41. * <tr><td>4</td><td>cover</td><td>0x00 = left, 0x01 = up, 0x02 = right, 0x03 = down, 0x04 = left/up, 0x05 = right/up, 0x06 left/down, 0x07 = left/down</td></tr>
  42. * <tr><td>5</td><td>dissolve</td><td>0x00</td></tr>
  43. * <tr><td>6</td><td>fade</td><td>0x00</td></tr>
  44. * <tr><td>7</td><td>uncover</td><td>like cover</td></tr>
  45. * <tr><td>8</td><td>random bars</td><td>like blinds</td></tr>
  46. * <tr><td>9</td><td>strips</td><td>like 0x04 - 0x07 of cover</td></tr>
  47. * <tr><td>10</td><td>wipe</td><td>like 0x00 - 0x03 of cover</td></tr>
  48. * <tr><td>11</td><td>box in/out</td><td>0x00 = out, 0x01 = in</td></tr>
  49. * <tr><td>13</td><td>split</td><td>0x00 = horizontally out, 0x01 = horizontally in, 0x02 = vertically out, 0x03 = vertically in</td></tr>
  50. * <tr><td>17</td><td>diamond</td><td>0x00</td></tr>
  51. * <tr><td>18</td><td>plus</td><td>0x00</td></tr>
  52. * <tr><td>19</td><td>wedge</td><td>0x00</td></tr>
  53. * <tr><td>20</td><td>push</td><td>like 0x00 - 0x03 of cover</td></tr>
  54. * <tr><td>21</td><td>comb</td><td>like blinds</td></tr>
  55. * <tr><td>22</td><td>newsflash</td><td>0x00</td></tr>
  56. * <tr><td>23</td><td>alphafade</td><td>0x00</td></tr>
  57. * <tr><td>26</td><td>wheel</td><td>number of radial divisions (0x01,0x02,0x03,0x04,0x08)</td></tr>
  58. * <tr><td>27</td><td>circle</td><td>0x00</td></tr>
  59. * <tr><td>255</td><td>undefined</td><td>0x00</td></tr>
  60. * </table>
  61. */
  62. public class SSSlideInfoAtom extends RecordAtom {
  63. /**
  64. * A bit that specifies whether the presentation slide can be
  65. * manually advanced by the user during the slide show.
  66. */
  67. public static final int MANUAL_ADVANCE_BIT = 1 << 0;
  68. /**
  69. * A bit that specifies whether the corresponding slide is
  70. * hidden and is not displayed during the slide show.
  71. */
  72. public static final int HIDDEN_BIT = 1 << 2;
  73. /**
  74. * A bit that specifies whether to play the sound specified by soundIfRef.
  75. */
  76. public static final int SOUND_BIT = 1 << 4;
  77. /**
  78. * A bit that specifies whether the sound specified by soundIdRef is
  79. * looped continuously when playing until the next sound plays.
  80. */
  81. public static final int LOOP_SOUND_BIT = 1 << 6;
  82. /**
  83. * A bit that specifies whether to stop any currently playing
  84. * sound when the transition starts.
  85. */
  86. public static final int STOP_SOUND_BIT = 1 << 8;
  87. /**
  88. * A bit that specifies whether the slide will automatically
  89. * advance after slideTime milliseconds during the slide show.
  90. */
  91. public static final int AUTO_ADVANCE_BIT = 1 << 10;
  92. /**
  93. * A bit that specifies whether to display the cursor during
  94. * the slide show.
  95. */
  96. public static final int CURSOR_VISIBLE_BIT = 1 << 12;
  97. // public static int RESERVED1_BIT = 1 << 1;
  98. // public static int RESERVED2_BIT = 1 << 3;
  99. // public static int RESERVED3_BIT = 1 << 5;
  100. // public static int RESERVED4_BIT = 1 << 7;
  101. // public static int RESERVED5_BIT = 1 << 9;
  102. // public static int RESERVED6_BIT = 1 << 11;
  103. // public static int RESERVED7_BIT = 1 << 13 | 1 << 14 | 1 << 15;
  104. private static final int[] EFFECT_MASKS = {
  105. MANUAL_ADVANCE_BIT,
  106. HIDDEN_BIT,
  107. SOUND_BIT,
  108. LOOP_SOUND_BIT,
  109. STOP_SOUND_BIT,
  110. AUTO_ADVANCE_BIT,
  111. CURSOR_VISIBLE_BIT
  112. };
  113. private static final String[] EFFECT_NAMES = {
  114. "MANUAL_ADVANCE",
  115. "HIDDEN",
  116. "SOUND",
  117. "LOOP_SOUND",
  118. "STOP_SOUND",
  119. "AUTO_ADVANCE",
  120. "CURSOR_VISIBLE"
  121. };
  122. private static final long _type = RecordTypes.SSSlideInfoAtom.typeID;
  123. private final byte[] _header;
  124. /**
  125. * A signed integer that specifies an amount of time, in milliseconds, to wait
  126. * before advancing to the next presentation slide. It MUST be greater than or equal to 0 and
  127. * less than or equal to 86399000. It MUST be ignored unless AUTO_ADVANCE_BIT is TRUE.
  128. */
  129. private int _slideTime;
  130. /**
  131. * A SoundIdRef that specifies which sound to play when the transition starts.
  132. */
  133. private int _soundIdRef;
  134. /**
  135. * A byte that specifies the variant of effectType. In combination of the effectType
  136. * there are further restriction and specification of this field.
  137. */
  138. private short _effectDirection; // byte
  139. /**
  140. * A byte that specifies which transition is used when transitioning to the
  141. * next presentation slide during a slide show. Exact rendering of any transition is
  142. * determined by the rendering application. As such, the same transition can have
  143. * many variations depending on the implementation.
  144. */
  145. private short _effectType; // byte
  146. /**
  147. * Various flags - see bitmask for more details
  148. */
  149. private short _effectTransitionFlags;
  150. /**
  151. * A byte value that specifies how long the transition takes to run.
  152. * (0x00 = 0.75 seconds, 0x01 = 0.5 seconds, 0x02 = 0.25 seconds)
  153. */
  154. private short _speed; // byte
  155. private final byte[] _unused; // 3-byte
  156. public SSSlideInfoAtom() {
  157. _header = new byte[8];
  158. LittleEndian.putShort(_header, 0, (short)0);
  159. LittleEndian.putShort(_header, 2, (short)_type);
  160. LittleEndian.putShort(_header, 4, (short)0x10);
  161. LittleEndian.putShort(_header, 6, (short)0);
  162. _unused = new byte[3];
  163. }
  164. public SSSlideInfoAtom(byte[] source, int offset, int len) {
  165. int ofs = offset;
  166. // Sanity Checking
  167. if(len != 24) len = 24;
  168. if (source.length < offset+len) {
  169. throw new IllegalArgumentException("Need at least " + (offset + len) +
  170. " bytes with offset " + offset + ", length " + len + " and array-size " + source.length);
  171. }
  172. // Get the header
  173. _header = Arrays.copyOfRange(source, ofs, ofs+8);
  174. ofs += _header.length;
  175. if (LittleEndian.getShort(_header, 0) != 0) {
  176. LOG.debug("Invalid data for SSSlideInfoAtom at offset 0: {}", LittleEndian.getShort(_header, 0));
  177. }
  178. if (LittleEndian.getShort(_header, 2) != RecordTypes.SSSlideInfoAtom.typeID) {
  179. LOG.debug("Invalid data for SSSlideInfoAtom at offset 2: {}", LittleEndian.getShort(_header, 2));
  180. }
  181. if (LittleEndian.getShort(_header, 4) != 0x10) {
  182. LOG.debug("Invalid data for SSSlideInfoAtom at offset 4: {}", LittleEndian.getShort(_header, 4));
  183. }
  184. if (LittleEndian.getShort(_header, 6) == 0) {
  185. LOG.debug("Invalid data for SSSlideInfoAtom at offset 6: {}", LittleEndian.getShort(_header, 6));
  186. }
  187. _slideTime = LittleEndian.getInt(source, ofs);
  188. if (_slideTime < 0 || _slideTime > 86399000) {
  189. LOG.debug("Invalid data for SSSlideInfoAtom - invalid slideTime: {}", _slideTime);
  190. }
  191. ofs += LittleEndianConsts.INT_SIZE;
  192. _soundIdRef = LittleEndian.getInt(source, ofs);
  193. ofs += LittleEndianConsts.INT_SIZE;
  194. _effectDirection = LittleEndian.getUByte(source, ofs);
  195. ofs += LittleEndianConsts.BYTE_SIZE;
  196. _effectType = LittleEndian.getUByte(source, ofs);
  197. ofs += LittleEndianConsts.BYTE_SIZE;
  198. _effectTransitionFlags = LittleEndian.getShort(source, ofs);
  199. ofs += LittleEndianConsts.SHORT_SIZE;
  200. _speed = LittleEndian.getUByte(source, ofs);
  201. ofs += LittleEndianConsts.BYTE_SIZE;
  202. _unused = Arrays.copyOfRange(source, ofs,ofs+3);
  203. }
  204. /**
  205. * Write the contents of the record back, so it can be written
  206. * to disk
  207. */
  208. @Override
  209. public void writeOut(OutputStream out) throws IOException {
  210. // Header - size or type unchanged
  211. out.write(_header);
  212. writeLittleEndian(_slideTime, out);
  213. writeLittleEndian(_soundIdRef, out);
  214. byte[] byteBuf = new byte[LittleEndianConsts.BYTE_SIZE];
  215. LittleEndian.putUByte(byteBuf, 0, _effectDirection);
  216. out.write(byteBuf);
  217. LittleEndian.putUByte(byteBuf, 0, _effectType);
  218. out.write(byteBuf);
  219. writeLittleEndian(_effectTransitionFlags, out);
  220. LittleEndian.putUByte(byteBuf, 0, _speed);
  221. out.write(byteBuf);
  222. assert(_unused.length == 3);
  223. out.write(_unused);
  224. }
  225. /**
  226. * We are of type 1017
  227. */
  228. @Override
  229. public long getRecordType() { return _type; }
  230. public int getSlideTime() {
  231. return _slideTime;
  232. }
  233. public void setSlideTime(int slideTime) {
  234. this._slideTime = slideTime;
  235. }
  236. public int getSoundIdRef() {
  237. return _soundIdRef;
  238. }
  239. public void setSoundIdRef(int soundIdRef) {
  240. this._soundIdRef = soundIdRef;
  241. }
  242. public short getEffectDirection() {
  243. return _effectDirection;
  244. }
  245. public void setEffectDirection(short effectDirection) {
  246. this._effectDirection = effectDirection;
  247. }
  248. public short getEffectType() {
  249. return _effectType;
  250. }
  251. public void setEffectType(short effectType) {
  252. this._effectType = effectType;
  253. }
  254. public short getEffectTransitionFlags() {
  255. return _effectTransitionFlags;
  256. }
  257. public void setEffectTransitionFlags(short effectTransitionFlags) {
  258. this._effectTransitionFlags = effectTransitionFlags;
  259. }
  260. /**
  261. * Use one of the bitmasks MANUAL_ADVANCE_BIT ... CURSOR_VISIBLE_BIT
  262. */
  263. public void setEffectTransitionFlagByBit(int bitmask, boolean enabled) {
  264. if (enabled) {
  265. _effectTransitionFlags |= bitmask;
  266. } else {
  267. _effectTransitionFlags &= (0xFFFF ^ bitmask);
  268. }
  269. }
  270. public boolean getEffectTransitionFlagByBit(int bitmask) {
  271. return ((_effectTransitionFlags & bitmask) != 0);
  272. }
  273. public short getSpeed() {
  274. return _speed;
  275. }
  276. public void setSpeed(short speed) {
  277. this._speed = speed;
  278. }
  279. @Override
  280. public Map<String, Supplier<?>> getGenericProperties() {
  281. return GenericRecordUtil.getGenericProperties(
  282. "effectTransitionFlags", getBitsAsString(this::getEffectTransitionFlags, EFFECT_MASKS, EFFECT_NAMES),
  283. "slideTime", this::getSlideTime,
  284. "soundIdRef", this::getSoundIdRef,
  285. "effectDirection", this::getEffectDirection,
  286. "effectType", this::getEffectType,
  287. "speed", this::getSpeed
  288. );
  289. }
  290. }