some more tweaks for bug 30311. Set some (unused) bits in FontFormatting to match Excel.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@646194 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-04-09 05:56:50 +00:00
parent e77898fa7c
commit cb99b3e409
3 changed files with 474 additions and 530 deletions

View File

@ -26,14 +26,11 @@ import org.apache.poi.util.LittleEndian;
/** /**
* Font Formatting Block of the Conditional Formatting Rule Record. * Font Formatting Block of the Conditional Formatting Rule Record.
* *
* Created on January 22, 2008, 10:05 PM
*
* @author Dmitriy Kumshayev * @author Dmitriy Kumshayev
*/ */
public final class FontFormatting
public class FontFormatting
{ {
private byte [] record; private byte[] _rawData;
private static final int OFFSET_FONT_NAME = 0; private static final int OFFSET_FONT_NAME = 0;
private static final int OFFSET_FONT_HEIGHT = 64; private static final int OFFSET_FONT_HEIGHT = 64;
@ -46,8 +43,11 @@ public class FontFormatting
private static final int OFFSET_ESCAPEMENT_TYPE_MODIFIED = 92; private static final int OFFSET_ESCAPEMENT_TYPE_MODIFIED = 92;
private static final int OFFSET_UNDERLINE_TYPE_MODIFIED = 96; private static final int OFFSET_UNDERLINE_TYPE_MODIFIED = 96;
private static final int OFFSET_FONT_WEIGHT_MODIFIED = 100; private static final int OFFSET_FONT_WEIGHT_MODIFIED = 100;
private static final int OFFSET_NOT_USED = 104; private static final int OFFSET_NOT_USED1 = 104;
private static final int OFFSET_NOT_USED2 = 108;
private static final int OFFSET_NOT_USED3 = 112; // for some reason Excel always writes 0x7FFFFFFF at this offset
private static final int OFFSET_FONT_FORMATING_END = 116; private static final int OFFSET_FONT_FORMATING_END = 116;
private static final int RAW_DATA_SIZE = 118;
public final static int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF; public final static int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF;
@ -65,104 +65,89 @@ public class FontFormatting
private static final BitField shadowModified = BitFieldFactory.getInstance(0x00000010); private static final BitField shadowModified = BitFieldFactory.getInstance(0x00000010);
private static final BitField cancellationModified = BitFieldFactory.getInstance(0x00000080); private static final BitField cancellationModified = BitFieldFactory.getInstance(0x00000080);
/** /** Escapement type - None */
* Escapement type - None public static final short SS_NONE = 0;
*/ /** Escapement type - Superscript */
public final static short SS_NONE = 0; public static final short SS_SUPER = 1;
/** Escapement type - Subscript */
/** public static final short SS_SUB = 2;
* Escapement type - Superscript /** Underline type - None */
*/ public static final byte U_NONE = 0;
public final static short SS_SUPER = 1; /** Underline type - Single */
public static final byte U_SINGLE = 1;
/** /** Underline type - Double */
* Escapement type - Subscript public static final byte U_DOUBLE = 2;
*/ /** Underline type - Single Accounting */
public final static short SS_SUB = 2; public static final byte U_SINGLE_ACCOUNTING = 0x21;
/** Underline type - Double Accounting */
/** public static final byte U_DOUBLE_ACCOUNTING = 0x22;
* Underline type - None /** Normal boldness (not bold) */
*/ private static final short FONT_WEIGHT_NORMAL = 0x190;
public final static byte U_NONE = 0;
/**
* Underline type - Single
*/
public final static byte U_SINGLE = 1;
/**
* Underline type - Double
*/
public final static byte U_DOUBLE = 2;
/**
* Underline type - Single Accounting
*/
public final static byte U_SINGLE_ACCOUNTING = 0x21;
/**
* Underline type - Double Accounting
*/
public final static byte U_DOUBLE_ACCOUNTING = 0x22;
/**
* Normal boldness (not bold)
*/
protected final static short FONT_WEIGHT_NORMAL = 0x190;
/** /**
* Bold boldness (bold) * Bold boldness (bold)
*/ */
private static final short FONT_WEIGHT_BOLD = 0x2bc;
protected final static short FONT_WEIGHT_BOLD = 0x2bc; private FontFormatting(byte[] rawData) {
_rawData = rawData;
}
public FontFormatting() public FontFormatting()
{ {
this(new byte[118]); this(new byte[RAW_DATA_SIZE]);
this.setFontHeight((short)-1); setFontHeight(-1);
this.setItalic(false); setItalic(false);
this.setFontWieghtModified(false); setFontWieghtModified(false);
this.setOutline(false); setOutline(false);
this.setShadow(false); setShadow(false);
this.setStrikeout(false); setStrikeout(false);
this.setEscapementType((short)0); setEscapementType((short)0);
this.setUnderlineType((byte)0); setUnderlineType((byte)0);
this.setFontColorIndex((short)-1); setFontColorIndex((short)-1);
this.setFontStyleModified(false); setFontStyleModified(false);
this.setFontOutlineModified(false); setFontOutlineModified(false);
this.setFontShadowModified(false); setFontShadowModified(false);
this.setFontCancellationModified(false); setFontCancellationModified(false);
this.setEscapementTypeModified(false); setEscapementTypeModified(false);
this.setUnderlineTypeModified(false); setUnderlineTypeModified(false);
LittleEndian.putShort(record, OFFSET_FONT_NAME, (short)0); setShort(OFFSET_FONT_NAME, 0);
LittleEndian.putInt(record, OFFSET_NOT_USED, 0x00000001); setInt(OFFSET_NOT_USED1, 0x00000001);
LittleEndian.putShort(record, OFFSET_FONT_FORMATING_END, (short)0x0001); setInt(OFFSET_NOT_USED2, 0x00000000);
} setInt(OFFSET_NOT_USED3, 0x7FFFFFFF);// for some reason Excel always writes 0x7FFFFFFF at this offset
setShort(OFFSET_FONT_FORMATING_END, 0x0001);
/** Creates new FontFormatting */
private FontFormatting(byte[] record)
{
this.record = record;
} }
/** Creates new FontFormatting */ /** Creates new FontFormatting */
public FontFormatting(RecordInputStream in) public FontFormatting(RecordInputStream in)
{ {
record = new byte[118]; this(new byte[RAW_DATA_SIZE]);
for (int i = 0; i != record.length; i++) for (int i = 0; i < _rawData.length; i++)
{ {
record[i] = in.readByte(); _rawData[i] = in.readByte();
} }
} }
private short getShort(int offset) {
return LittleEndian.getShort( _rawData, offset);
}
private void setShort(int offset, int value) {
LittleEndian.putShort( _rawData, offset, (short)value);
}
private int getInt(int offset) {
return LittleEndian.getInt( _rawData, offset);
}
private void setInt(int offset, int value) {
LittleEndian.putInt( _rawData, offset, value);
}
public byte[] getRawRecord() public byte[] getRawRecord()
{ {
return record; return _rawData;
} }
/** /**
@ -172,9 +157,9 @@ public class FontFormatting
* @param height fontheight (in points/20); or -1 to preserve the cell font height * @param height fontheight (in points/20); or -1 to preserve the cell font height
*/ */
public void setFontHeight(short height) public void setFontHeight(int height)
{ {
LittleEndian.putInt(record, OFFSET_FONT_HEIGHT, height); setInt(OFFSET_FONT_HEIGHT, height);
} }
/** /**
@ -182,21 +167,21 @@ public class FontFormatting
* *
* @return fontheight (in points/20); or -1 if not modified * @return fontheight (in points/20); or -1 if not modified
*/ */
public short getFontHeight() public int getFontHeight()
{ {
return (short) LittleEndian.getInt(record, OFFSET_FONT_HEIGHT); return getInt(OFFSET_FONT_HEIGHT);
} }
private void setFontOption(boolean option, BitField field) private void setFontOption(boolean option, BitField field)
{ {
int options = LittleEndian.getInt(record,OFFSET_FONT_OPTIONS); int options = getInt(OFFSET_FONT_OPTIONS);
options = field.setBoolean(options, option); options = field.setBoolean(options, option);
LittleEndian.putInt(record,OFFSET_FONT_OPTIONS, options); setInt(OFFSET_FONT_OPTIONS, options);
} }
private boolean getFontOption(BitField field) private boolean getFontOption(BitField field)
{ {
int options = LittleEndian.getInt(record,OFFSET_FONT_OPTIONS); int options = getInt(OFFSET_FONT_OPTIONS);
return field.isSet(options); return field.isSet(options);
} }
@ -274,11 +259,12 @@ public class FontFormatting
* @param bw - a number between 100-1000 for the fonts "boldness" * @param bw - a number between 100-1000 for the fonts "boldness"
*/ */
private void setFontWeight(short bw) private void setFontWeight(short pbw)
{ {
short bw = pbw;
if( bw<100) { bw=100; } if( bw<100) { bw=100; }
if( bw>1000){ bw=1000; } if( bw>1000){ bw=1000; }
LittleEndian.putShort(record,OFFSET_FONT_WEIGHT, bw); setShort(OFFSET_FONT_WEIGHT, bw);
} }
/** /**
@ -300,7 +286,7 @@ public class FontFormatting
public short getFontWeight() public short getFontWeight()
{ {
return LittleEndian.getShort(record,OFFSET_FONT_WEIGHT); return getShort(OFFSET_FONT_WEIGHT);
} }
/** /**
@ -324,7 +310,7 @@ public class FontFormatting
*/ */
public short getEscapementType() public short getEscapementType()
{ {
return LittleEndian.getShort(record,OFFSET_ESCAPEMENT_TYPE); return getShort(OFFSET_ESCAPEMENT_TYPE);
} }
/** /**
@ -337,7 +323,7 @@ public class FontFormatting
*/ */
public void setEscapementType( short escapementType) public void setEscapementType( short escapementType)
{ {
LittleEndian.putShort(record,OFFSET_ESCAPEMENT_TYPE, escapementType); setShort(OFFSET_ESCAPEMENT_TYPE, escapementType);
} }
/** /**
@ -354,13 +340,13 @@ public class FontFormatting
public short getUnderlineType() public short getUnderlineType()
{ {
return LittleEndian.getShort(record,OFFSET_UNDERLINE_TYPE); return getShort(OFFSET_UNDERLINE_TYPE);
} }
/** /**
* set the type of underlining type for the font * set the type of underlining type for the font
* *
* @param u super or subscript option * @param underlineType underline option
* *
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE
* @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE
@ -370,23 +356,23 @@ public class FontFormatting
*/ */
public void setUnderlineType( short underlineType) public void setUnderlineType( short underlineType)
{ {
LittleEndian.putShort(record,OFFSET_UNDERLINE_TYPE, underlineType); setShort(OFFSET_UNDERLINE_TYPE, underlineType);
} }
public short getFontColorIndex() public short getFontColorIndex()
{ {
return (short)LittleEndian.getInt(record,OFFSET_FONT_COLOR_INDEX); return (short)getInt(OFFSET_FONT_COLOR_INDEX);
} }
public void setFontColorIndex(short fci ) public void setFontColorIndex(short fci )
{ {
LittleEndian.putInt(record,OFFSET_FONT_COLOR_INDEX,fci); setInt(OFFSET_FONT_COLOR_INDEX,fci);
} }
private boolean getOptionFlag(BitField field) private boolean getOptionFlag(BitField field)
{ {
int optionFlags = LittleEndian.getInt(record,OFFSET_OPTION_FLAGS); int optionFlags = getInt(OFFSET_OPTION_FLAGS);
int value = field.getValue(optionFlags); int value = field.getValue(optionFlags);
return value==0? true : false ; return value==0? true : false ;
} }
@ -394,9 +380,9 @@ public class FontFormatting
private void setOptionFlag(boolean modified, BitField field) private void setOptionFlag(boolean modified, BitField field)
{ {
int value = modified? 0 : 1; int value = modified? 0 : 1;
int optionFlags = LittleEndian.getInt(record,OFFSET_OPTION_FLAGS); int optionFlags = getInt(OFFSET_OPTION_FLAGS);
optionFlags = field.setValue(optionFlags, value); optionFlags = field.setValue(optionFlags, value);
LittleEndian.putInt(record,OFFSET_OPTION_FLAGS, optionFlags); setInt(OFFSET_OPTION_FLAGS, optionFlags);
} }
@ -443,35 +429,35 @@ public class FontFormatting
public void setEscapementTypeModified(boolean modified) public void setEscapementTypeModified(boolean modified)
{ {
int value = modified? 0 : 1; int value = modified? 0 : 1;
LittleEndian.putInt(record,OFFSET_ESCAPEMENT_TYPE_MODIFIED, value); setInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED, value);
} }
public boolean isEscapementTypeModified() public boolean isEscapementTypeModified()
{ {
int escapementModified = LittleEndian.getInt(record,OFFSET_ESCAPEMENT_TYPE_MODIFIED); int escapementModified = getInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED);
return escapementModified == 0; return escapementModified == 0;
} }
public void setUnderlineTypeModified(boolean modified) public void setUnderlineTypeModified(boolean modified)
{ {
int value = modified? 0 : 1; int value = modified? 0 : 1;
LittleEndian.putInt(record,OFFSET_UNDERLINE_TYPE_MODIFIED, value); setInt(OFFSET_UNDERLINE_TYPE_MODIFIED, value);
} }
public boolean isUnderlineTypeModified() public boolean isUnderlineTypeModified()
{ {
int underlineModified = LittleEndian.getInt(record,OFFSET_UNDERLINE_TYPE_MODIFIED); int underlineModified = getInt(OFFSET_UNDERLINE_TYPE_MODIFIED);
return underlineModified == 0; return underlineModified == 0;
} }
public void setFontWieghtModified(boolean modified) public void setFontWieghtModified(boolean modified)
{ {
int value = modified? 0 : 1; int value = modified? 0 : 1;
LittleEndian.putInt(record,OFFSET_FONT_WEIGHT_MODIFIED, value); setInt(OFFSET_FONT_WEIGHT_MODIFIED, value);
} }
public boolean isFontWeightModified() public boolean isFontWeightModified()
{ {
int fontStyleModified = LittleEndian.getInt(record,OFFSET_FONT_WEIGHT_MODIFIED); int fontStyleModified = getInt(OFFSET_FONT_WEIGHT_MODIFIED);
return fontStyleModified == 0; return fontStyleModified == 0;
} }
@ -551,55 +537,13 @@ public class FontFormatting
} }
buffer.append(" .color index = ").append("0x"+Integer.toHexString(getFontColorIndex()).toUpperCase()).append("\n"); buffer.append(" .color index = ").append("0x"+Integer.toHexString(getFontColorIndex()).toUpperCase()).append("\n");
buffer.append(" ====\n");
buffer.append(" ["+OFFSET_FONT_HEIGHT+"] FONT HEIGHT: "+intToHex(OFFSET_FONT_HEIGHT)+"\n");
buffer.append(" ["+OFFSET_FONT_OPTIONS+"] FONT OPTIONS: "+intToHex(OFFSET_FONT_OPTIONS)+"\n");
buffer.append(" ["+OFFSET_FONT_WEIGHT+"] FONT WEIGHT: "+shortToHex(OFFSET_FONT_WEIGHT)+"\n");
buffer.append(" ["+OFFSET_ESCAPEMENT_TYPE+"] FONT ESCAPEMENT: "+shortToHex(OFFSET_ESCAPEMENT_TYPE)+"\n");
buffer.append(" ["+OFFSET_UNDERLINE_TYPE+"] FONT UNDERLINE: "+byteToHex(OFFSET_UNDERLINE_TYPE)+"\n");
buffer.append(" ["+(OFFSET_UNDERLINE_TYPE+1)+"] FONT NOT USED: "+byteToHex(OFFSET_UNDERLINE_TYPE+1)+"\n");
buffer.append(" ["+(OFFSET_UNDERLINE_TYPE+2)+"] FONT NOT USED: "+byteToHex(OFFSET_UNDERLINE_TYPE+2)+"\n");
buffer.append(" ["+(OFFSET_UNDERLINE_TYPE+3)+"] FONT NOT USED: "+byteToHex(OFFSET_UNDERLINE_TYPE+3)+"\n");
buffer.append(" ["+OFFSET_FONT_COLOR_INDEX+"] FONT COLIDX: "+intToHex(OFFSET_FONT_COLOR_INDEX)+"\n");
buffer.append(" ["+(OFFSET_FONT_COLOR_INDEX+4)+"] FONT NOT USED: "+intToHex(OFFSET_FONT_COLOR_INDEX+4)+"\n");
buffer.append(" ["+OFFSET_OPTION_FLAGS+"] FONT OPTIONS: "+intToHex(OFFSET_OPTION_FLAGS)+"\n");
buffer.append(" ["+OFFSET_ESCAPEMENT_TYPE_MODIFIED+"] FONT ESC MOD: "+intToHex(OFFSET_ESCAPEMENT_TYPE_MODIFIED)+"\n");
buffer.append(" ["+OFFSET_UNDERLINE_TYPE_MODIFIED+"] FONT UND MOD: "+intToHex(OFFSET_UNDERLINE_TYPE_MODIFIED)+"\n");
buffer.append(" ["+OFFSET_FONT_WEIGHT+"] FONT WGH MOD: "+intToHex(OFFSET_FONT_WEIGHT)+"\n");
buffer.append(" ["+OFFSET_NOT_USED+"] FONT NOT USED: "+intToHex(OFFSET_NOT_USED)+"\n");
buffer.append(" ["+(OFFSET_NOT_USED+4)+"] FONT NOT USED: "+intToHex(OFFSET_NOT_USED+4)+"\n");
buffer.append(" ["+(OFFSET_NOT_USED+8)+"] FONT NOT USED: "+intToHex(OFFSET_NOT_USED+8)+"\n");
buffer.append(" ["+OFFSET_FONT_FORMATING_END+"] FONT FORMATTING END: "+shortToHex(OFFSET_FONT_FORMATING_END)+"\n");
buffer.append(" ====\n");
buffer.append(" [/Font Formatting]\n"); buffer.append(" [/Font Formatting]\n");
return buffer.toString(); return buffer.toString();
} }
public Object clone() public Object clone()
{ {
FontFormatting rec = new FontFormatting(); byte[] rawData = (byte[]) _rawData.clone();
if( record != null) return new FontFormatting(rawData);
{
byte[] clone = new byte[record.length];
System.arraycopy(record, 0, clone, 0, record.length);
rec.record = clone;
} }
return rec;
}
private String intToHex(int offset)
{
return Integer.toHexString(LittleEndian.getInt(record, offset));
}
private String shortToHex(int offset)
{
return Integer.toHexString(LittleEndian.getShort(record, offset)&0xFFFF);
}
private String byteToHex(int offset)
{
return Integer.toHexString(record[offset]&0xFF);
}
} }

View File

@ -88,7 +88,7 @@ public final class HSSFFontFormatting
* *
* @return fontheight (in points/20); or -1 if not modified * @return fontheight (in points/20); or -1 if not modified
*/ */
public short getFontHeight() public int getFontHeight()
{ {
return fontFormatting.getFontHeight(); return fontFormatting.getFontHeight();
} }
@ -308,7 +308,7 @@ public final class HSSFFontFormatting
* @param height * @param height
* @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(short) * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(short)
*/ */
public void setFontHeight(short height) public void setFontHeight(int height)
{ {
fontFormatting.setFontHeight(height); fontFormatting.setFontHeight(height);
} }

View File

@ -230,7 +230,7 @@ public final class TestCFRuleRecord extends TestCase
fontFormatting.setFontColorIndex((short)10); fontFormatting.setFontColorIndex((short)10);
assertEquals(10,fontFormatting.getFontColorIndex()); assertEquals(10,fontFormatting.getFontColorIndex());
fontFormatting.setFontHeight((short)100); fontFormatting.setFontHeight(100);
assertEquals(100,fontFormatting.getFontHeight()); assertEquals(100,fontFormatting.getFontHeight());
fontFormatting.setFontOutlineModified(false); fontFormatting.setFontOutlineModified(false);