properly update TextSpecInfoAtom when parent text is changed

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@656213 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2008-05-14 10:15:00 +00:00
parent 802a3df0b5
commit 643df24cfb
3 changed files with 222 additions and 12 deletions

View File

@ -45,7 +45,6 @@ public class TextRun
protected TextBytesAtom _byteAtom;
protected TextCharsAtom _charAtom;
protected StyleTextPropAtom _styleAtom;
protected TextSpecInfoAtom _specAtom;
protected boolean _isUnicode;
protected RichTextRun[] _rtRuns;
private SlideShow slideShow;
@ -361,6 +360,18 @@ public class TextRun
_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);
}
}
}
}
/**
@ -474,17 +485,6 @@ public class TextRun
_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());
}
}
}
/**

View File

@ -20,6 +20,7 @@ import org.apache.poi.util.LittleEndian;
import java.io.OutputStream;
import java.io.IOException;
import java.util.ArrayList;
/**
* The special info runs contained in this text.
@ -82,4 +83,118 @@ public class TextSpecInfoAtom extends RecordAtom {
public void setTextSize(int size){
LittleEndian.putInt(_data, 0, size);
}
/**
* Reset the content to one info run with the default values
* @param size the site of parent text
*/
public void reset(int size){
_data = new byte[10];
// 01 00 00 00
LittleEndian.putInt(_data, 0, size);
// 01 00 00 00
LittleEndian.putInt(_data, 4, 1); //mask
// 00 00
LittleEndian.putShort(_data, 8, (short)0); //langId
// Update the size (header bytes 5-8)
LittleEndian.putInt(_header, 4, _data.length);
}
/**
* Get the number of characters covered by this records
*
* @return the number of characters covered by this records
*/
public int getCharactersCovered(){
int covered = 0;
TextSpecInfoRun[] runs = getTextSpecInfoRuns();
for (int i = 0; i < runs.length; i++) covered += runs[i].len;
return covered;
}
public TextSpecInfoRun[] getTextSpecInfoRuns(){
ArrayList lst = new ArrayList();
int pos = 0;
int[] bits = {1, 0, 2};
while(pos < _data.length) {
TextSpecInfoRun run = new TextSpecInfoRun();
run.len = LittleEndian.getInt(_data, pos); pos += 4;
run.mask = LittleEndian.getInt(_data, pos); pos += 4;
for (int i = 0; i < bits.length; i++) {
if((run.mask & 1 << bits[i]) != 0){
switch (bits[i]){
case 0:
run.spellInfo = LittleEndian.getShort(_data, pos); pos += 2;
break;
case 1:
run.langId = LittleEndian.getShort(_data, pos); pos += 2;
break;
case 2:
run.altLangId = LittleEndian.getShort(_data, pos); pos += 2;
break;
}
}
}
lst.add(run);
}
return (TextSpecInfoRun[])lst.toArray(new TextSpecInfoRun[lst.size()]);
}
public static class TextSpecInfoRun {
//Length of special info run.
protected int len;
//Special info mask of this run;
protected int mask;
// info fields as indicated by the mask.
// -1 means the bit is not set
protected short spellInfo = -1;
protected short langId = -1;
protected short altLangId = -1;
/**
* Spelling status of this text. See Spell Info table below.
*
* <p>Spell Info Types:</p>
* <li>0 Unchecked
* <li>1 Previously incorrect, needs rechecking
* <li>2 Correct
* <li>3 Incorrect
*
* @return Spelling status of this text
*/
public short getSpellInfo(){
return spellInfo;
}
/**
* Windows LANGID for this text.
*
* @return Windows LANGID for this text.
*/
public short getLangId(){
return spellInfo;
}
/**
* Alternate Windows LANGID of this text;
* must be a valid non-East Asian LANGID if the text has an East Asian language,
* otherwise may be an East Asian LANGID or language neutral (zero).
*
* @return Alternate Windows LANGID of this text
*/
public short getAltLangId(){
return altLangId;
}
/**
* @return Length of special info run.
*/
public int length(){
return len;
}
}
}

View File

@ -0,0 +1,95 @@
/* ====================================================================
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 org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.util.HexDump;
import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
import java.util.LinkedList;
import java.util.Arrays;
/**
* Tests TextSpecInfoAtom
*
* @author Yegor Kozlov
*/
public class TestTextSpecInfoAtom extends TestCase {
//from a real file
private byte[] data_1 = new byte[] {
0x00, 0x00, (byte)0xAA, 0x0F, 0x2C, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
public void testRead() throws Exception {
TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);
TextSpecInfoAtom.TextSpecInfoRun[] run = spec.getTextSpecInfoRuns();
assertEquals(5, run.length);
assertEquals(10, run[0].length());
assertEquals(1, run[1].length());
assertEquals(70, run[2].length());
assertEquals(9, run[3].length());
assertEquals(32, run[4].length());
}
public void testWrite() throws Exception {
TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);
ByteArrayOutputStream out = new ByteArrayOutputStream();
spec.writeOut(out);
byte[] result = out.toByteArray();
assertTrue(Arrays.equals(result, data_1));
}
public void testReset() throws Exception {
TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);
spec.reset(32); //length of the parent text
TextSpecInfoAtom.TextSpecInfoRun[] run = spec.getTextSpecInfoRuns();
assertEquals(1, run.length);
assertEquals(32, run[0].length());
//serialize and read again
ByteArrayOutputStream out = new ByteArrayOutputStream();
spec.writeOut(out);
byte[] result = out.toByteArray();
TextSpecInfoAtom spec2 = new TextSpecInfoAtom(result, 0, result.length);
TextSpecInfoAtom.TextSpecInfoRun[] run2 = spec2.getTextSpecInfoRuns();
assertEquals(1, run2.length);
assertEquals(32, run2[0].length());
}
}