improved handling of StyleTextPropAtom bit masks, added more read-write roundtrip tests

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@691180 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2008-09-02 09:59:53 +00:00
parent d3f7cc38ef
commit 7c1b5604d9
4 changed files with 677 additions and 681 deletions

View File

@ -35,19 +35,19 @@ public class CharFlagsTextProp extends BitMaskTextProp {
public static String NAME = "char_flags";
public CharFlagsTextProp() {
super(2,0xffff, NAME, new String[] {
"bold", // 0x0001
"italic", // 0x0002
"underline", // 0x0004
"char_unknown_1",// 0x0008
"shadow", // 0x0010
"char_unknown_2",// 0x0020
"char_unknown_3",// 0x0040
"char_unknown_4",// 0x0080
"strikethrough", // 0x0100
"relief", // 0x0200
"reset_numbering", // 0x0400
"enable_numbering_1", // 0x0800
"enable_numbering_2", // 0x1000
"bold", // 0x0001 A bit that specifies whether the characters are bold.
"italic", // 0x0002 A bit that specifies whether the characters are italicized.
"underline", // 0x0004 A bit that specifies whether the characters are underlined.
"char_unknown_1", // 0x0008 Undefined and MUST be ignored.
"shadow", // 0x0010 A bit that specifies whether the characters have a shadow effect.
"fehint", // 0x0020 A bit that specifies whether characters originated from double-byte input.
"char_unknown_2", // 0x0040 Undefined and MUST be ignored.
"kumi", // 0x0080 A bit that specifies whether Kumimoji are used for vertical text.
"strikethrough", // 0x0100 Undefined and MUST be ignored.
"emboss", // 0x0200 A bit that specifies whether the characters are embossed.
"char_unknown_3", // 0x0400 Undefined and MUST be ignored.
"char_unknown_4", // 0x0800 Undefined and MUST be ignored.
"char_unknown_5", // 0x1000 Undefined and MUST be ignored.
}
);
}

View File

@ -34,6 +34,7 @@ public class TextPropCollection {
private int charactersCovered;
private short reservedField;
private LinkedList textPropList;
private int maskSpecial = 0;
/** Fetch the number of characters this styling applies to */
public int getCharactersCovered() { return charactersCovered; }
@ -94,20 +95,27 @@ public class TextPropCollection {
// If we do, decode that, save it, and shuffle on
for(int i=0; i<potentialProperties.length; i++) {
// Check there's still data left to read
if(dataOffset+bytesPassed >= data.length) {
// Out of data, can't be any more properties to go
return bytesPassed;
}
// Check if this property is found in the mask
if((containsField & potentialProperties[i].getMask()) != 0) {
if(dataOffset+bytesPassed >= data.length) {
// Out of data, can't be any more properties to go
// remember the mask and return
maskSpecial |= potentialProperties[i].getMask();
return bytesPassed;
}
// Bingo, data contains this property
TextProp prop = (TextProp)potentialProperties[i].clone();
int val = 0;
if(prop.getSize() == 2) {
val = LittleEndian.getShort(data,dataOffset+bytesPassed);
} else {
} else if(prop.getSize() == 4){
val = LittleEndian.getInt(data,dataOffset+bytesPassed);
} else if (prop.getSize() == 0){
//remember "special" bits.
maskSpecial |= potentialProperties[i].getMask();
continue;
}
prop.setValue(val);
bytesPassed += prop.getSize();
@ -161,14 +169,17 @@ public class TextPropCollection {
}
// Then the mask field
int mask = 0;
int mask = maskSpecial;
for(int i=0; i<textPropList.size(); i++) {
TextProp textProp = (TextProp)textPropList.get(i);
//sometimes header indicates that the bitmask is present but its value is 0
if (textProp instanceof BitMaskTextProp)
mask |= (textProp.getWriteMask() == 0 ? 1 : textProp.getWriteMask());
else
if (textProp instanceof BitMaskTextProp) {
if(mask == 0) mask |= textProp.getWriteMask();
}
else {
mask |= textProp.getWriteMask();
}
}
StyleTextPropAtom.writeLittleEndian(mask,o);
@ -178,7 +189,7 @@ public class TextPropCollection {
int val = textProp.getValue();
if(textProp.getSize() == 2) {
StyleTextPropAtom.writeLittleEndian((short)val,o);
} else {
} else if(textProp.getSize() == 4){
StyleTextPropAtom.writeLittleEndian(val,o);
}
}

View File

@ -124,6 +124,10 @@ public class StyleTextPropAtom extends RecordAtom
/** All the different kinds of paragraph properties we might handle */
public static TextProp[] paragraphTextPropTypes = new TextProp[] {
new TextProp(0, 0x1, "hasBullet"),
new TextProp(0, 0x2, "hasBulletFont"),
new TextProp(0, 0x4, "hasBulletColor"),
new TextProp(0, 0x8, "hasBulletSize"),
new ParagraphFlagsTextProp(),
new TextProp(2, 0x80, "bullet.char"),
new TextProp(2, 0x10, "bullet.font"),
@ -131,35 +135,38 @@ public class StyleTextPropAtom extends RecordAtom
new TextProp(4, 0x20, "bullet.color"),
new AlignmentTextProp(),
new TextProp(2, 0x100, "text.offset"),
new TextProp(2, 0x200, "para_unknown_2"),
new TextProp(2, 0x400, "bullet.offset"),
new TextProp(2, 0x1000, "linespacing"),
new TextProp(2, 0x2000, "spacebefore"),
new TextProp(2, 0x4000, "spaceafter"),
new TextProp(2, 0x8000, "para_unknown_4"),
new TextProp(2, 0x10000, "para_unknown_5"),
new TextProp(2, 0xA0000, "para_unknown_6"),
new TextProp(2, 0x200000, "para_unknown_7")
new TextProp(2, 0x8000, "defaultTabSize"),
new TextProp(2, 0x100000, "tabStops"),
new TextProp(2, 0x10000, "fontAlign"),
new TextProp(2, 0xA0000, "wrapFlags"),
new TextProp(2, 0x200000, "textDirection")
};
/** All the different kinds of character properties we might handle */
public static TextProp[] characterTextPropTypes = new TextProp[] {
new TextProp(0, 0x1, "bold"),
new TextProp(0, 0x2, "italic"),
new TextProp(0, 0x4, "underline"),
new TextProp(0, 0x8, "unused1"),
new TextProp(0, 0x10, "shadow"),
new TextProp(0, 0x20, "fehint"),
new TextProp(0, 0x40, "unused2"),
new TextProp(0, 0x80, "kumi"),
new TextProp(0, 0x100, "unused3"),
new TextProp(0, 0x200, "emboss"),
new CharFlagsTextProp(),
new TextProp(2, 0x10000, "font.index"),
new TextProp(2, 0x200000, "asian_or_complex"),
new TextProp(2, 0x400000, "char_unknown_2"),
new TextProp(2, 0x800000, "symbol"),
new TextProp(0, 0x100000, "pp10ext"),
new TextProp(2, 0x200000, "asian.font.index"),
new TextProp(2, 0x400000, "ansi.font.index"),
new TextProp(2, 0x800000, "symbol.font.index"),
new TextProp(2, 0x20000, "font.size"),
new TextProp(4, 0x40000, "font.color"),
new TextProp(2, 0x80000, "superscript"),
new TextProp(2, 0x100000, "char_unknown_1"),
new TextProp(2, 0x1000000, "char_unknown_3"),
new TextProp(2, 0x2000000, "char_unknown_4"),
new TextProp(2, 0x4000000, "char_unknown_5"),
new TextProp(2, 0x8000000, "char_unknown_6"),
new TextProp(2, 0x10000000, "char_unknown_7"),
new TextProp(2, 0x20000000, "char_unknown_8"),
new TextProp(2, 0x40000000, "char_unknown_9"),
new TextProp(2, 0x80000000, "char_unknown_10"),
};
/* *************** record code follows ********************** */
@ -269,8 +276,7 @@ public class StyleTextPropAtom extends RecordAtom
textHandled += textLen;
pos += 4;
// Fetch the 2 byte value that is safe to ignore as 0
short paraIgn = LittleEndian.getShort(rawContents,pos);
short indent = LittleEndian.getShort(rawContents,pos);
pos += 2;
// Grab the 4 byte value that tells us what properties follow
@ -278,7 +284,7 @@ public class StyleTextPropAtom extends RecordAtom
pos += 4;
// Now make sense of those properties
TextPropCollection thisCollection = new TextPropCollection(textLen, paraIgn);
TextPropCollection thisCollection = new TextPropCollection(textLen, indent);
int plSize = thisCollection.buildTextPropList(
paraFlags, paragraphTextPropTypes, rawContents, pos);
pos += plSize;

View File

@ -31,6 +31,7 @@ import org.apache.poi.util.HexDump;
import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
import java.util.LinkedList;
import java.util.Arrays;
/**
* Tests that StyleTextPropAtom works properly
@ -642,60 +643,6 @@ public class TestStyleTextPropAtom extends TestCase {
stpa.writeOut(baos);
byte[] b = baos.toByteArray();
assertEquals(data_b.length, b.length);
for(int i=0; i<data_b.length; i++) {
System.out.println(i + "\t" + b[i] + "\t" + data_b[i] + "\t" + Integer.toHexString(b[i]) );
assertEquals(data_b[i],b[i]);
}
}
public void testWriteA() throws Exception {
StyleTextPropAtom stpa = new StyleTextPropAtom(data_a,0,data_a.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
stpa.writeOut(baos);
byte[] b = baos.toByteArray();
assertEquals(data_a.length, b.length);
for(int i=0; i<data_a.length; i++) {
assertEquals(data_a[i],b[i]);
}
}
public void testLoadWriteA() throws Exception {
StyleTextPropAtom stpa = new StyleTextPropAtom(data_a,0,data_a.length);
stpa.setParentTextSize(data_a_text_len);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
stpa.writeOut(baos);
byte[] b = baos.toByteArray();
assertEquals(data_a.length, b.length);
for(int i=0; i<data_a.length; i++) {
assertEquals(data_a[i],b[i]);
}
}
public void testWriteB() throws Exception {
StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
stpb.writeOut(baos);
byte[] b = baos.toByteArray();
assertEquals(data_b.length, b.length);
for(int i=0; i<data_b.length; i++) {
assertEquals(data_b[i],b[i]);
}
}
public void testLoadWriteB() throws Exception {
StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
stpb.setParentTextSize(data_b_text_len);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
stpb.writeOut(baos);
byte[] b = baos.toByteArray();
assertEquals(data_b.length, b.length);
for(int i=0; i<data_b.length; i++) {
//System.out.println(i + "\t" + b[i] + "\t" + data_b[i] + "\t" + Integer.toHexString(b[i]) );
@ -703,6 +650,47 @@ public class TestStyleTextPropAtom extends TestCase {
}
}
public void testWriteA() throws Exception {
doReadWrite(data_a, -1);
}
public void testLoadWriteA() throws Exception {
doReadWrite(data_b, data_b_text_len);
}
public void testWriteB() throws Exception {
doReadWrite(data_b, -1);
}
public void testLoadWriteB() throws Exception {
doReadWrite(data_b, data_b_text_len);
}
public void testLoadWriteC() throws Exception {
doReadWrite(data_c, data_c_text_len);
}
public void testLoadWriteD() throws Exception {
doReadWrite(data_d, data_d_text_len);
}
protected void doReadWrite(byte[] data, int textlen) throws Exception {
StyleTextPropAtom stpb = new StyleTextPropAtom(data, 0,data.length);
if(textlen != -1) stpb.setParentTextSize(textlen);
ByteArrayOutputStream out = new ByteArrayOutputStream();
stpb.writeOut(out);
byte[] bytes = out.toByteArray();
assertEquals(data.length, bytes.length);
try {
assertTrue(Arrays.equals(data, bytes));
} catch (Throwable e){
//print hex dump if failed
assertEquals(HexDump.toHex(data), HexDump.toHex(bytes));
}
}
public void testNotEnoughDataProp() throws Exception {
// We don't have enough data in the record to cover
@ -732,8 +720,8 @@ public class TestStyleTextPropAtom extends TestCase {
assertEquals(1, chprops.findByName("char_flags").getValue());
assertEquals(1, chprops.findByName("font.index").getValue());
assertEquals(20, chprops.findByName("font.size").getValue());
assertEquals(0, chprops.findByName("asian_or_complex").getValue());
assertEquals(1, chprops.findByName("char_unknown_2").getValue());
assertEquals(0, chprops.findByName("asian.font.index").getValue());
assertEquals(1, chprops.findByName("ansi.font.index").getValue());
}
/**
@ -747,16 +735,7 @@ public class TestStyleTextPropAtom extends TestCase {
0x00 , 0x00 , 0x13 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x63 , 0x00 ,
0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x0F , 0x00
};
StyleTextPropAtom stpa = new StyleTextPropAtom(data,0,data.length);
stpa.setParentTextSize(length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
stpa.writeOut(baos);
byte[] b = baos.toByteArray();
assertEquals(data.length, b.length);
for(int i=0; i<data.length; i++) {
assertEquals(data[i],b[i]);
}
doReadWrite(data, length);
}
}