protected TextBytesAtom _byteAtom;
protected TextCharsAtom _charAtom;
protected StyleTextPropAtom _styleAtom;
- protected TextSpecInfoAtom _specAtom;
protected boolean _isUnicode;
protected RichTextRun[] _rtRuns;
private SlideShow slideShow;
_isUnicode = true;
}
}
+ /**
+ * If TextSpecInfoAtom is present, we must update the text size in it,
+ * otherwise the ppt will be corrupted
+ */
+ if(_records != null) for (int i = 0; i < _records.length; i++) {
+ if(_records[i] instanceof TextSpecInfoAtom){
+ TextSpecInfoAtom specAtom = (TextSpecInfoAtom)_records[i];
+ if((s.length() + 1) != specAtom.getCharactersCovered()){
+ specAtom.reset(s.length() + 1);
+ }
+ }
+ }
}
/**
_rtRuns[0] = new RichTextRun(this,0,s.length());
}
- /**
- * If TextSpecInfoAtom is present, we must update the text size,
- * otherwise the ppt will be corrupted
- */
- if(_records != null) for (int i = 0; i < _records.length; i++) {
- if(_records[i] instanceof TextSpecInfoAtom){
- TextSpecInfoAtom specAtom = (TextSpecInfoAtom)_records[i];
- specAtom.setTextSize(s.length());
- }
-
- }
}
/**
\r
import java.io.OutputStream;\r
import java.io.IOException;\r
+import java.util.ArrayList;\r
\r
/**\r
* The special info runs contained in this text.\r
public void setTextSize(int size){\r
LittleEndian.putInt(_data, 0, size);\r
}\r
+\r
+ /**\r
+ * Reset the content to one info run with the default values\r
+ * @param size the site of parent text\r
+ */\r
+ public void reset(int size){\r
+ _data = new byte[10];\r
+ // 01 00 00 00\r
+ LittleEndian.putInt(_data, 0, size);\r
+ // 01 00 00 00\r
+ LittleEndian.putInt(_data, 4, 1); //mask\r
+ // 00 00\r
+ LittleEndian.putShort(_data, 8, (short)0); //langId\r
+\r
+ // Update the size (header bytes 5-8)\r
+ LittleEndian.putInt(_header, 4, _data.length);\r
+ }\r
+\r
+ /**\r
+ * Get the number of characters covered by this records\r
+ *\r
+ * @return the number of characters covered by this records\r
+ */\r
+ public int getCharactersCovered(){\r
+ int covered = 0;\r
+ TextSpecInfoRun[] runs = getTextSpecInfoRuns();\r
+ for (int i = 0; i < runs.length; i++) covered += runs[i].len;\r
+ return covered;\r
+ }\r
+\r
+ public TextSpecInfoRun[] getTextSpecInfoRuns(){\r
+ ArrayList lst = new ArrayList();\r
+ int pos = 0;\r
+ int[] bits = {1, 0, 2};\r
+ while(pos < _data.length) {\r
+ TextSpecInfoRun run = new TextSpecInfoRun();\r
+ run.len = LittleEndian.getInt(_data, pos); pos += 4;\r
+ run.mask = LittleEndian.getInt(_data, pos); pos += 4;\r
+ for (int i = 0; i < bits.length; i++) {\r
+ if((run.mask & 1 << bits[i]) != 0){\r
+ switch (bits[i]){\r
+ case 0:\r
+ run.spellInfo = LittleEndian.getShort(_data, pos); pos += 2;\r
+ break;\r
+ case 1:\r
+ run.langId = LittleEndian.getShort(_data, pos); pos += 2;\r
+ break;\r
+ case 2:\r
+ run.altLangId = LittleEndian.getShort(_data, pos); pos += 2;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ lst.add(run);\r
+ }\r
+ return (TextSpecInfoRun[])lst.toArray(new TextSpecInfoRun[lst.size()]);\r
+\r
+ }\r
+\r
+ public static class TextSpecInfoRun {\r
+ //Length of special info run.\r
+ protected int len;\r
+\r
+ //Special info mask of this run;\r
+ protected int mask;\r
+\r
+ // info fields as indicated by the mask.\r
+ // -1 means the bit is not set\r
+ protected short spellInfo = -1;\r
+ protected short langId = -1;\r
+ protected short altLangId = -1;\r
+\r
+ /**\r
+ * Spelling status of this text. See Spell Info table below.\r
+ *\r
+ * <p>Spell Info Types:</p>\r
+ * <li>0 Unchecked\r
+ * <li>1 Previously incorrect, needs rechecking\r
+ * <li>2 Correct\r
+ * <li>3 Incorrect\r
+ *\r
+ * @return Spelling status of this text\r
+ */\r
+ public short getSpellInfo(){\r
+ return spellInfo;\r
+ }\r
+\r
+ /**\r
+ * Windows LANGID for this text.\r
+ *\r
+ * @return Windows LANGID for this text.\r
+ */\r
+ public short getLangId(){\r
+ return spellInfo;\r
+ }\r
+\r
+ /**\r
+ * Alternate Windows LANGID of this text;\r
+ * must be a valid non-East Asian LANGID if the text has an East Asian language,\r
+ * otherwise may be an East Asian LANGID or language neutral (zero).\r
+ *\r
+ * @return Alternate Windows LANGID of this text\r
+ */\r
+ public short getAltLangId(){\r
+ return altLangId;\r
+ }\r
+\r
+ /**\r
+ * @return Length of special info run.\r
+ */\r
+ public int length(){\r
+ return len;\r
+ }\r
+ }\r
}\r
--- /dev/null
+\r
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+ \r
+\r
+\r
+package org.apache.poi.hslf.record;\r
+\r
+import org.apache.poi.hslf.HSLFSlideShow;\r
+import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;\r
+import org.apache.poi.hslf.model.textproperties.TextProp;\r
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;\r
+import org.apache.poi.hslf.record.StyleTextPropAtom.*;\r
+import org.apache.poi.hslf.usermodel.SlideShow;\r
+import org.apache.poi.util.HexDump;\r
+\r
+import junit.framework.TestCase;\r
+import java.io.ByteArrayOutputStream;\r
+import java.util.LinkedList;\r
+import java.util.Arrays;\r
+\r
+/**\r
+ * Tests TextSpecInfoAtom\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class TestTextSpecInfoAtom extends TestCase {\r
+\r
+ //from a real file\r
+ private byte[] data_1 = new byte[] {\r
+ 0x00, 0x00, (byte)0xAA, 0x0F, 0x2C, 0x00, 0x00, 0x00,\r
+ 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\r
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01,\r
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
+ };\r
+\r
+\r
+ public void testRead() throws Exception {\r
+ TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);\r
+ TextSpecInfoAtom.TextSpecInfoRun[] run = spec.getTextSpecInfoRuns();\r
+ assertEquals(5, run.length);\r
+\r
+ assertEquals(10, run[0].length());\r
+ assertEquals(1, run[1].length());\r
+ assertEquals(70, run[2].length());\r
+ assertEquals(9, run[3].length());\r
+ assertEquals(32, run[4].length());\r
+\r
+ }\r
+\r
+ public void testWrite() throws Exception {\r
+ TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);\r
+ ByteArrayOutputStream out = new ByteArrayOutputStream();\r
+ spec.writeOut(out);\r
+\r
+ byte[] result = out.toByteArray();\r
+ assertTrue(Arrays.equals(result, data_1));\r
+ }\r
+\r
+ public void testReset() throws Exception {\r
+ TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);\r
+ spec.reset(32); //length of the parent text\r
+\r
+ TextSpecInfoAtom.TextSpecInfoRun[] run = spec.getTextSpecInfoRuns();\r
+ assertEquals(1, run.length);\r
+\r
+ assertEquals(32, run[0].length());\r
+\r
+ //serialize and read again\r
+ ByteArrayOutputStream out = new ByteArrayOutputStream();\r
+ spec.writeOut(out);\r
+\r
+ byte[] result = out.toByteArray();\r
+ TextSpecInfoAtom spec2 = new TextSpecInfoAtom(result, 0, result.length);\r
+ TextSpecInfoAtom.TextSpecInfoRun[] run2 = spec2.getTextSpecInfoRuns();\r
+ assertEquals(1, run2.length);\r
+\r
+ assertEquals(32, run2[0].length());\r
+ }\r
+}\r