Bugzilla 47250 - Fixed FontRecord to expect unicode flags even when name length is zero
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@777717 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0cc03d5e13
commit
5a9db459c4
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.5-beta6" date="2009-??-??">
|
<release version="3.5-beta6" date="2009-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">47250 - Fixed FontRecord to expect unicode flags even when name length is zero</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">47198 - Fixed formula evaluator comparison of -0.0 and 0.0</action>
|
<action dev="POI-DEVELOPERS" type="add">47198 - Fixed formula evaluator comparison of -0.0 and 0.0</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">47229 - Fixed ExternalNameRecord to handle DDE links</action>
|
<action dev="POI-DEVELOPERS" type="add">47229 - Fixed ExternalNameRecord to handle DDE links</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">46287 - Control of header and footer extraction in ExcelExtractor / XSSFExcelExtractor</action>
|
<action dev="POI-DEVELOPERS" type="add">46287 - Control of header and footer extraction in ExcelExtractor / XSSFExcelExtractor</action>
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.5-beta6" date="2009-??-??">
|
<release version="3.5-beta6" date="2009-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">47250 - Fixed FontRecord to expect unicode flags even when name length is zero</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">47198 - Fixed formula evaluator comparison of -0.0 and 0.0</action>
|
<action dev="POI-DEVELOPERS" type="add">47198 - Fixed formula evaluator comparison of -0.0 and 0.0</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">47229 - Fixed ExternalNameRecord to handle DDE links</action>
|
<action dev="POI-DEVELOPERS" type="add">47229 - Fixed ExternalNameRecord to handle DDE links</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">46287 - Control of header and footer extraction in ExcelExtractor / XSSFExcelExtractor</action>
|
<action dev="POI-DEVELOPERS" type="add">46287 - Control of header and footer extraction in ExcelExtractor / XSSFExcelExtractor</action>
|
||||||
|
@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
|
|||||||
|
|
||||||
import org.apache.poi.util.BitField;
|
import org.apache.poi.util.BitField;
|
||||||
import org.apache.poi.util.BitFieldFactory;
|
import org.apache.poi.util.BitFieldFactory;
|
||||||
|
import org.apache.poi.util.HexDump;
|
||||||
import org.apache.poi.util.LittleEndianOutput;
|
import org.apache.poi.util.LittleEndianOutput;
|
||||||
import org.apache.poi.util.StringUtil;
|
import org.apache.poi.util.StringUtil;
|
||||||
|
|
||||||
@ -30,477 +31,410 @@ import org.apache.poi.util.StringUtil;
|
|||||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||||
*/
|
*/
|
||||||
public final class FontRecord extends StandardRecord {
|
public final class FontRecord extends StandardRecord {
|
||||||
public final static short sid = 0x0031; // docs are wrong (0x231 Microsoft Support site article Q184647)
|
public final static short sid = 0x0031; // docs are wrong (0x231 Microsoft Support site article Q184647)
|
||||||
public final static short SS_NONE = 0;
|
public final static short SS_NONE = 0;
|
||||||
public final static short SS_SUPER = 1;
|
public final static short SS_SUPER = 1;
|
||||||
public final static short SS_SUB = 2;
|
public final static short SS_SUB = 2;
|
||||||
public final static byte U_NONE = 0;
|
public final static byte U_NONE = 0;
|
||||||
public final static byte U_SINGLE = 1;
|
public final static byte U_SINGLE = 1;
|
||||||
public final static byte U_DOUBLE = 2;
|
public final static byte U_DOUBLE = 2;
|
||||||
public final static byte U_SINGLE_ACCOUNTING = 0x21;
|
public final static byte U_SINGLE_ACCOUNTING = 0x21;
|
||||||
public final static byte U_DOUBLE_ACCOUNTING = 0x22;
|
public final static byte U_DOUBLE_ACCOUNTING = 0x22;
|
||||||
private short field_1_font_height; // in units of .05 of a point
|
private short field_1_font_height; // in units of .05 of a point
|
||||||
private short field_2_attributes;
|
private short field_2_attributes;
|
||||||
|
|
||||||
// 0 0x01 - Reserved bit must be 0
|
// 0 0x01 - Reserved bit must be 0
|
||||||
private static final BitField italic = BitFieldFactory.getInstance(0x02); // is this font in italics
|
private static final BitField italic = BitFieldFactory.getInstance(0x02); // is this font in italics
|
||||||
|
|
||||||
// 2 0x04 - reserved bit must be 0
|
// 2 0x04 - reserved bit must be 0
|
||||||
private static final BitField strikeout =BitFieldFactory.getInstance(0x08); // is this font has a line through the center
|
private static final BitField strikeout =BitFieldFactory.getInstance(0x08); // is this font has a line through the center
|
||||||
private static final BitField macoutline = BitFieldFactory.getInstance(0x10); // some weird macintosh thing....but who understands those mac people anyhow
|
private static final BitField macoutline = BitFieldFactory.getInstance(0x10); // some weird macintosh thing....but who understands those mac people anyhow
|
||||||
private static final BitField macshadow = BitFieldFactory.getInstance(0x20); // some weird macintosh thing....but who understands those mac people anyhow
|
private static final BitField macshadow = BitFieldFactory.getInstance(0x20); // some weird macintosh thing....but who understands those mac people anyhow
|
||||||
|
|
||||||
// 7-6 - reserved bits must be 0
|
// 7-6 - reserved bits must be 0
|
||||||
// the rest is unused
|
// the rest is unused
|
||||||
private short field_3_color_palette_index;
|
private short field_3_color_palette_index;
|
||||||
private short field_4_bold_weight;
|
private short field_4_bold_weight;
|
||||||
private short field_5_super_sub_script; // 00none/01super/02sub
|
private short field_5_super_sub_script; // 00none/01super/02sub
|
||||||
private byte field_6_underline; // 00none/01single/02double/21singleaccounting/22doubleaccounting
|
private byte field_6_underline; // 00none/01single/02double/21singleaccounting/22doubleaccounting
|
||||||
private byte field_7_family; // ?? defined by windows api logfont structure?
|
private byte field_7_family; // ?? defined by windows api logfont structure?
|
||||||
private byte field_8_charset; // ?? defined by windows api logfont structure?
|
private byte field_8_charset; // ?? defined by windows api logfont structure?
|
||||||
private byte field_9_zero = 0; // must be 0
|
private byte field_9_zero = 0; // must be 0
|
||||||
/** possibly empty string never <code>null</code> */
|
/** possibly empty string never <code>null</code> */
|
||||||
private String field_11_font_name; // whoa...the font name
|
private String field_11_font_name;
|
||||||
|
|
||||||
public FontRecord() {
|
public FontRecord() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public FontRecord(RecordInputStream in) {
|
public FontRecord(RecordInputStream in) {
|
||||||
field_1_font_height = in.readShort();
|
field_1_font_height = in.readShort();
|
||||||
field_2_attributes = in.readShort();
|
field_2_attributes = in.readShort();
|
||||||
field_3_color_palette_index = in.readShort();
|
field_3_color_palette_index = in.readShort();
|
||||||
field_4_bold_weight = in.readShort();
|
field_4_bold_weight = in.readShort();
|
||||||
field_5_super_sub_script = in.readShort();
|
field_5_super_sub_script = in.readShort();
|
||||||
field_6_underline = in.readByte();
|
field_6_underline = in.readByte();
|
||||||
field_7_family = in.readByte();
|
field_7_family = in.readByte();
|
||||||
field_8_charset = in.readByte();
|
field_8_charset = in.readByte();
|
||||||
field_9_zero = in.readByte();
|
field_9_zero = in.readByte();
|
||||||
int field_10_font_name_len = in.readUByte();
|
int field_10_font_name_len = in.readUByte();
|
||||||
if (field_10_font_name_len > 0) {
|
int unicodeFlags = in.readUByte(); // options byte present always (even if no character data)
|
||||||
if (in.readByte() == 0) { // is compressed unicode
|
|
||||||
field_11_font_name = in.readCompressedUnicode(field_10_font_name_len);
|
|
||||||
} else { // is not compressed unicode
|
|
||||||
field_11_font_name = in.readUnicodeLEString(field_10_font_name_len);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
field_11_font_name = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (field_10_font_name_len > 0) {
|
||||||
* sets the height of the font in 1/20th point units
|
if (unicodeFlags == 0) { // is compressed unicode
|
||||||
*
|
field_11_font_name = in.readCompressedUnicode(field_10_font_name_len);
|
||||||
* @param height fontheight (in points/20)
|
} else { // is not compressed unicode
|
||||||
*/
|
field_11_font_name = in.readUnicodeLEString(field_10_font_name_len);
|
||||||
|
}
|
||||||
public void setFontHeight(short height)
|
} else {
|
||||||
{
|
field_11_font_name = "";
|
||||||
field_1_font_height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the font attributes (see individual bit setters that reference this method)
|
|
||||||
*
|
|
||||||
* @param attributes the bitmask to set
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setAttributes(short attributes)
|
|
||||||
{
|
|
||||||
field_2_attributes = attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// attributes bitfields
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the font to be italics or not
|
|
||||||
*
|
|
||||||
* @param italics - whether the font is italics or not
|
|
||||||
* @see #setAttributes(short)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setItalic(boolean italics)
|
|
||||||
{
|
|
||||||
field_2_attributes = italic.setShortBoolean(field_2_attributes, italics);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the font to be stricken out or not
|
|
||||||
*
|
|
||||||
* @param strike - whether the font is stricken out or not
|
|
||||||
* @see #setAttributes(short)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setStrikeout(boolean strike)
|
|
||||||
{
|
|
||||||
field_2_attributes = strikeout.setShortBoolean(field_2_attributes, strike);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* whether to use the mac outline font style thing (mac only) - Some mac person
|
|
||||||
* should comment this instead of me doing it (since I have no idea)
|
|
||||||
*
|
|
||||||
* @param mac - whether to do that mac font outline thing or not
|
|
||||||
* @see #setAttributes(short)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setMacoutline(boolean mac)
|
|
||||||
{
|
|
||||||
field_2_attributes = macoutline.setShortBoolean(field_2_attributes, mac);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* whether to use the mac shado font style thing (mac only) - Some mac person
|
|
||||||
* should comment this instead of me doing it (since I have no idea)
|
|
||||||
*
|
|
||||||
* @param mac - whether to do that mac font shadow thing or not
|
|
||||||
* @see #setAttributes(short)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setMacshadow(boolean mac)
|
|
||||||
{
|
|
||||||
field_2_attributes = macshadow.setShortBoolean(field_2_attributes, mac);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the font's color palette index
|
|
||||||
*
|
|
||||||
* @param cpi - font color index
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setColorPaletteIndex(short cpi)
|
|
||||||
{
|
|
||||||
field_3_color_palette_index = cpi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is
|
|
||||||
* 0x190 for normal and 0x2bc for bold
|
|
||||||
*
|
|
||||||
* @param bw - a number between 100-1000 for the fonts "boldness"
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setBoldWeight(short bw)
|
|
||||||
{
|
|
||||||
field_4_bold_weight = bw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the type of super or subscript for the font
|
|
||||||
*
|
|
||||||
* @param sss super or subscript option
|
|
||||||
* @see #SS_NONE
|
|
||||||
* @see #SS_SUPER
|
|
||||||
* @see #SS_SUB
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setSuperSubScript(short sss)
|
|
||||||
{
|
|
||||||
field_5_super_sub_script = sss;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the type of underlining for the font
|
|
||||||
*
|
|
||||||
* @param u super or subscript option
|
|
||||||
*
|
|
||||||
* @see #U_NONE
|
|
||||||
* @see #U_SINGLE
|
|
||||||
* @see #U_DOUBLE
|
|
||||||
* @see #U_SINGLE_ACCOUNTING
|
|
||||||
* @see #U_DOUBLE_ACCOUNTING
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setUnderline(byte u)
|
|
||||||
{
|
|
||||||
field_6_underline = u;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the font family (TODO)
|
|
||||||
*
|
|
||||||
* @param f family
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setFamily(byte f)
|
|
||||||
{
|
|
||||||
field_7_family = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the character set
|
|
||||||
*
|
|
||||||
* @param charset - characterset
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setCharset(byte charset)
|
|
||||||
{
|
|
||||||
field_8_charset = charset;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the name of the font
|
|
||||||
*
|
|
||||||
* @param fn - name of the font (i.e. "Arial")
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void setFontName(String fn)
|
|
||||||
{
|
|
||||||
field_11_font_name = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets the height of the font in 1/20th point units
|
|
||||||
*
|
|
||||||
* @return fontheight (in points/20)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public short getFontHeight()
|
|
||||||
{
|
|
||||||
return field_1_font_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the font attributes (see individual bit getters that reference this method)
|
|
||||||
*
|
|
||||||
* @return attribute - the bitmask
|
|
||||||
*/
|
|
||||||
|
|
||||||
public short getAttributes()
|
|
||||||
{
|
|
||||||
return field_2_attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get whether the font is to be italics or not
|
|
||||||
*
|
|
||||||
* @return italics - whether the font is italics or not
|
|
||||||
* @see #getAttributes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
public boolean isItalic()
|
|
||||||
{
|
|
||||||
return italic.isSet(field_2_attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get whether the font is to be stricken out or not
|
|
||||||
*
|
|
||||||
* @return strike - whether the font is stricken out or not
|
|
||||||
* @see #getAttributes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
public boolean isStruckout()
|
|
||||||
{
|
|
||||||
return strikeout.isSet(field_2_attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* whether to use the mac outline font style thing (mac only) - Some mac person
|
|
||||||
* should comment this instead of me doing it (since I have no idea)
|
|
||||||
*
|
|
||||||
* @return mac - whether to do that mac font outline thing or not
|
|
||||||
* @see #getAttributes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
public boolean isMacoutlined()
|
|
||||||
{
|
|
||||||
return macoutline.isSet(field_2_attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* whether to use the mac shado font style thing (mac only) - Some mac person
|
|
||||||
* should comment this instead of me doing it (since I have no idea)
|
|
||||||
*
|
|
||||||
* @return mac - whether to do that mac font shadow thing or not
|
|
||||||
* @see #getAttributes()
|
|
||||||
*/
|
|
||||||
|
|
||||||
public boolean isMacshadowed()
|
|
||||||
{
|
|
||||||
return macshadow.isSet(field_2_attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the font's color palette index
|
|
||||||
*
|
|
||||||
* @return cpi - font color index
|
|
||||||
*/
|
|
||||||
|
|
||||||
public short getColorPaletteIndex()
|
|
||||||
{
|
|
||||||
return field_3_color_palette_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is
|
|
||||||
* 0x190 for normal and 0x2bc for bold
|
|
||||||
*
|
|
||||||
* @return bw - a number between 100-1000 for the fonts "boldness"
|
|
||||||
*/
|
|
||||||
|
|
||||||
public short getBoldWeight()
|
|
||||||
{
|
|
||||||
return field_4_bold_weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the type of super or subscript for the font
|
|
||||||
*
|
|
||||||
* @return super or subscript option
|
|
||||||
* @see #SS_NONE
|
|
||||||
* @see #SS_SUPER
|
|
||||||
* @see #SS_SUB
|
|
||||||
*/
|
|
||||||
|
|
||||||
public short getSuperSubScript()
|
|
||||||
{
|
|
||||||
return field_5_super_sub_script;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the type of underlining for the font
|
|
||||||
*
|
|
||||||
* @return super or subscript option
|
|
||||||
*
|
|
||||||
* @see #U_NONE
|
|
||||||
* @see #U_SINGLE
|
|
||||||
* @see #U_DOUBLE
|
|
||||||
* @see #U_SINGLE_ACCOUNTING
|
|
||||||
* @see #U_DOUBLE_ACCOUNTING
|
|
||||||
*/
|
|
||||||
|
|
||||||
public byte getUnderline()
|
|
||||||
{
|
|
||||||
return field_6_underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the font family (TODO)
|
|
||||||
*
|
|
||||||
* @return family
|
|
||||||
*/
|
|
||||||
|
|
||||||
public byte getFamily()
|
|
||||||
{
|
|
||||||
return field_7_family;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the character set
|
|
||||||
*
|
|
||||||
* @return charset - characterset
|
|
||||||
*/
|
|
||||||
|
|
||||||
public byte getCharset()
|
|
||||||
{
|
|
||||||
return field_8_charset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the name of the font
|
|
||||||
*
|
|
||||||
* @return fn - name of the font (i.e. "Arial")
|
|
||||||
*/
|
|
||||||
|
|
||||||
public String getFontName()
|
|
||||||
{
|
|
||||||
return field_11_font_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
|
|
||||||
buffer.append("[FONT]\n");
|
|
||||||
buffer.append(" .fontheight = ")
|
|
||||||
.append(Integer.toHexString(getFontHeight())).append("\n");
|
|
||||||
buffer.append(" .attributes = ")
|
|
||||||
.append(Integer.toHexString(getAttributes())).append("\n");
|
|
||||||
buffer.append(" .italic = ").append(isItalic())
|
|
||||||
.append("\n");
|
|
||||||
buffer.append(" .strikout = ").append(isStruckout())
|
|
||||||
.append("\n");
|
|
||||||
buffer.append(" .macoutlined= ").append(isMacoutlined())
|
|
||||||
.append("\n");
|
|
||||||
buffer.append(" .macshadowed= ").append(isMacshadowed())
|
|
||||||
.append("\n");
|
|
||||||
buffer.append(" .colorpalette = ")
|
|
||||||
.append(Integer.toHexString(getColorPaletteIndex())).append("\n");
|
|
||||||
buffer.append(" .boldweight = ")
|
|
||||||
.append(Integer.toHexString(getBoldWeight())).append("\n");
|
|
||||||
buffer.append(" .supersubscript = ")
|
|
||||||
.append(Integer.toHexString(getSuperSubScript())).append("\n");
|
|
||||||
buffer.append(" .underline = ")
|
|
||||||
.append(Integer.toHexString(getUnderline())).append("\n");
|
|
||||||
buffer.append(" .family = ")
|
|
||||||
.append(Integer.toHexString(getFamily())).append("\n");
|
|
||||||
buffer.append(" .charset = ")
|
|
||||||
.append(Integer.toHexString(getCharset())).append("\n");
|
|
||||||
buffer.append(" .fontname = ").append(getFontName())
|
|
||||||
.append("\n");
|
|
||||||
buffer.append("[/FONT]\n");
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void serialize(LittleEndianOutput out) {
|
|
||||||
|
|
||||||
out.writeShort(getFontHeight());
|
|
||||||
out.writeShort(getAttributes());
|
|
||||||
out.writeShort(getColorPaletteIndex());
|
|
||||||
out.writeShort(getBoldWeight());
|
|
||||||
out.writeShort(getSuperSubScript());
|
|
||||||
out.writeByte(getUnderline());
|
|
||||||
out.writeByte(getFamily());
|
|
||||||
out.writeByte(getCharset());
|
|
||||||
out.writeByte(field_9_zero);
|
|
||||||
int fontNameLen = field_11_font_name.length();
|
|
||||||
out.writeByte(fontNameLen);
|
|
||||||
if (fontNameLen > 0) {
|
|
||||||
boolean hasMultibyte = StringUtil.hasMultibyte(field_11_font_name);
|
|
||||||
out.writeByte(hasMultibyte ? 0x01 : 0x00);
|
|
||||||
if (hasMultibyte) {
|
|
||||||
StringUtil.putUnicodeLE(field_11_font_name, out);
|
|
||||||
} else {
|
|
||||||
StringUtil.putCompressedUnicode(field_11_font_name, out);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected int getDataSize() {
|
|
||||||
int size = 15; // 5 shorts + 5 bytes
|
|
||||||
int fontNameLen = field_11_font_name.length();
|
|
||||||
if (fontNameLen < 1) {
|
|
||||||
// options byte is not encoded if no character data
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
size ++; // options byte
|
|
||||||
|
|
||||||
boolean hasMultibyte = StringUtil.hasMultibyte(field_11_font_name);
|
|
||||||
return size + fontNameLen * (hasMultibyte ? 2 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getSid()
|
/**
|
||||||
{
|
* sets the height of the font in 1/20th point units
|
||||||
return sid;
|
*
|
||||||
}
|
* @param height fontheight (in points/20)
|
||||||
|
*/
|
||||||
/**
|
public void setFontHeight(short height) {
|
||||||
* Clones all the font style information from another
|
field_1_font_height = height;
|
||||||
* FontRecord, onto this one. This
|
}
|
||||||
* will then hold all the same font style options.
|
|
||||||
*/
|
/**
|
||||||
public void cloneStyleFrom(FontRecord source) {
|
* set the font attributes (see individual bit setters that reference this method)
|
||||||
field_1_font_height = source.field_1_font_height;
|
*
|
||||||
field_2_attributes = source.field_2_attributes;
|
* @param attributes the bitmask to set
|
||||||
field_3_color_palette_index = source.field_3_color_palette_index;
|
*/
|
||||||
field_4_bold_weight = source.field_4_bold_weight;
|
public void setAttributes(short attributes) {
|
||||||
field_5_super_sub_script = source.field_5_super_sub_script;
|
field_2_attributes = attributes;
|
||||||
field_6_underline = source.field_6_underline;
|
}
|
||||||
field_7_family = source.field_7_family;
|
|
||||||
field_8_charset = source.field_8_charset;
|
// attributes bitfields
|
||||||
field_9_zero = source.field_9_zero;
|
|
||||||
field_11_font_name = source.field_11_font_name;
|
/**
|
||||||
}
|
* set the font to be italics or not
|
||||||
|
*
|
||||||
|
* @param italics - whether the font is italics or not
|
||||||
|
* @see #setAttributes(short)
|
||||||
|
*/
|
||||||
|
public void setItalic(boolean italics) {
|
||||||
|
field_2_attributes = italic.setShortBoolean(field_2_attributes, italics);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the font to be stricken out or not
|
||||||
|
*
|
||||||
|
* @param strike - whether the font is stricken out or not
|
||||||
|
* @see #setAttributes(short)
|
||||||
|
*/
|
||||||
|
public void setStrikeout(boolean strike) {
|
||||||
|
field_2_attributes = strikeout.setShortBoolean(field_2_attributes, strike);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether to use the mac outline font style thing (mac only) - Some mac person
|
||||||
|
* should comment this instead of me doing it (since I have no idea)
|
||||||
|
*
|
||||||
|
* @param mac - whether to do that mac font outline thing or not
|
||||||
|
* @see #setAttributes(short)
|
||||||
|
*/
|
||||||
|
public void setMacoutline(boolean mac) {
|
||||||
|
field_2_attributes = macoutline.setShortBoolean(field_2_attributes, mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether to use the mac shado font style thing (mac only) - Some mac person
|
||||||
|
* should comment this instead of me doing it (since I have no idea)
|
||||||
|
*
|
||||||
|
* @param mac - whether to do that mac font shadow thing or not
|
||||||
|
* @see #setAttributes(short)
|
||||||
|
*/
|
||||||
|
public void setMacshadow(boolean mac) {
|
||||||
|
field_2_attributes = macshadow.setShortBoolean(field_2_attributes, mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the font's color palette index
|
||||||
|
*
|
||||||
|
* @param cpi - font color index
|
||||||
|
*/
|
||||||
|
public void setColorPaletteIndex(short cpi) {
|
||||||
|
field_3_color_palette_index = cpi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is
|
||||||
|
* 0x190 for normal and 0x2bc for bold
|
||||||
|
*
|
||||||
|
* @param bw - a number between 100-1000 for the fonts "boldness"
|
||||||
|
*/
|
||||||
|
public void setBoldWeight(short bw) {
|
||||||
|
field_4_bold_weight = bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the type of super or subscript for the font
|
||||||
|
*
|
||||||
|
* @param sss super or subscript option
|
||||||
|
* @see #SS_NONE
|
||||||
|
* @see #SS_SUPER
|
||||||
|
* @see #SS_SUB
|
||||||
|
*/
|
||||||
|
public void setSuperSubScript(short sss) {
|
||||||
|
field_5_super_sub_script = sss;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the type of underlining for the font
|
||||||
|
*
|
||||||
|
* @param u super or subscript option
|
||||||
|
*
|
||||||
|
* @see #U_NONE
|
||||||
|
* @see #U_SINGLE
|
||||||
|
* @see #U_DOUBLE
|
||||||
|
* @see #U_SINGLE_ACCOUNTING
|
||||||
|
* @see #U_DOUBLE_ACCOUNTING
|
||||||
|
*/
|
||||||
|
public void setUnderline(byte u) {
|
||||||
|
field_6_underline = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the font family (TODO)
|
||||||
|
*
|
||||||
|
* @param f family
|
||||||
|
*/
|
||||||
|
public void setFamily(byte f) {
|
||||||
|
field_7_family = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the character set
|
||||||
|
*
|
||||||
|
* @param charset - character set
|
||||||
|
*/
|
||||||
|
public void setCharset(byte charset) {
|
||||||
|
field_8_charset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the name of the font
|
||||||
|
*
|
||||||
|
* @param fn - name of the font (i.e. "Arial")
|
||||||
|
*/
|
||||||
|
public void setFontName(String fn) {
|
||||||
|
field_11_font_name = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the height of the font in 1/20th point units
|
||||||
|
*
|
||||||
|
* @return fontheight (in points/20)
|
||||||
|
*/
|
||||||
|
public short getFontHeight() {
|
||||||
|
return field_1_font_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the font attributes (see individual bit getters that reference this method)
|
||||||
|
*
|
||||||
|
* @return attribute - the bitmask
|
||||||
|
*/
|
||||||
|
public short getAttributes() {
|
||||||
|
return field_2_attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get whether the font is to be italics or not
|
||||||
|
*
|
||||||
|
* @return italics - whether the font is italics or not
|
||||||
|
* @see #getAttributes()
|
||||||
|
*/
|
||||||
|
public boolean isItalic() {
|
||||||
|
return italic.isSet(field_2_attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get whether the font is to be stricken out or not
|
||||||
|
*
|
||||||
|
* @return strike - whether the font is stricken out or not
|
||||||
|
* @see #getAttributes()
|
||||||
|
*/
|
||||||
|
public boolean isStruckout(){
|
||||||
|
return strikeout.isSet(field_2_attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether to use the mac outline font style thing (mac only) - Some mac person
|
||||||
|
* should comment this instead of me doing it (since I have no idea)
|
||||||
|
*
|
||||||
|
* @return mac - whether to do that mac font outline thing or not
|
||||||
|
* @see #getAttributes()
|
||||||
|
*/
|
||||||
|
public boolean isMacoutlined(){
|
||||||
|
return macoutline.isSet(field_2_attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether to use the mac shado font style thing (mac only) - Some mac person
|
||||||
|
* should comment this instead of me doing it (since I have no idea)
|
||||||
|
*
|
||||||
|
* @return mac - whether to do that mac font shadow thing or not
|
||||||
|
* @see #getAttributes()
|
||||||
|
*/
|
||||||
|
public boolean isMacshadowed(){
|
||||||
|
return macshadow.isSet(field_2_attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the font's color palette index
|
||||||
|
*
|
||||||
|
* @return cpi - font color index
|
||||||
|
*/
|
||||||
|
public short getColorPaletteIndex(){
|
||||||
|
return field_3_color_palette_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is
|
||||||
|
* 0x190 for normal and 0x2bc for bold
|
||||||
|
*
|
||||||
|
* @return bw - a number between 100-1000 for the fonts "boldness"
|
||||||
|
*/
|
||||||
|
public short getBoldWeight(){
|
||||||
|
return field_4_bold_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the type of super or subscript for the font
|
||||||
|
*
|
||||||
|
* @return super or subscript option
|
||||||
|
* @see #SS_NONE
|
||||||
|
* @see #SS_SUPER
|
||||||
|
* @see #SS_SUB
|
||||||
|
*/
|
||||||
|
public short getSuperSubScript(){
|
||||||
|
return field_5_super_sub_script;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the type of underlining for the font
|
||||||
|
*
|
||||||
|
* @return super or subscript option
|
||||||
|
*
|
||||||
|
* @see #U_NONE
|
||||||
|
* @see #U_SINGLE
|
||||||
|
* @see #U_DOUBLE
|
||||||
|
* @see #U_SINGLE_ACCOUNTING
|
||||||
|
* @see #U_DOUBLE_ACCOUNTING
|
||||||
|
*/
|
||||||
|
public byte getUnderline() {
|
||||||
|
return field_6_underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the font family (TODO)
|
||||||
|
*
|
||||||
|
* @return family
|
||||||
|
*/
|
||||||
|
public byte getFamily() {
|
||||||
|
return field_7_family;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the character set
|
||||||
|
*
|
||||||
|
* @return charset - character set
|
||||||
|
*/
|
||||||
|
public byte getCharset() {
|
||||||
|
return field_8_charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the name of the font
|
||||||
|
*
|
||||||
|
* @return fn - name of the font (i.e. "Arial")
|
||||||
|
*/
|
||||||
|
public String getFontName() {
|
||||||
|
return field_11_font_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
sb.append("[FONT]\n");
|
||||||
|
sb.append(" .fontheight = ").append(HexDump.shortToHex(getFontHeight())).append("\n");
|
||||||
|
sb.append(" .attributes = ").append(HexDump.shortToHex(getAttributes())).append("\n");
|
||||||
|
sb.append(" .italic = ").append(isItalic()).append("\n");
|
||||||
|
sb.append(" .strikout = ").append(isStruckout()).append("\n");
|
||||||
|
sb.append(" .macoutlined= ").append(isMacoutlined()).append("\n");
|
||||||
|
sb.append(" .macshadowed= ").append(isMacshadowed()).append("\n");
|
||||||
|
sb.append(" .colorpalette = ").append(HexDump.shortToHex(getColorPaletteIndex())).append("\n");
|
||||||
|
sb.append(" .boldweight = ").append(HexDump.shortToHex(getBoldWeight())).append("\n");
|
||||||
|
sb.append(" .supersubscript= ").append(HexDump.shortToHex(getSuperSubScript())).append("\n");
|
||||||
|
sb.append(" .underline = ").append(HexDump.byteToHex(getUnderline())).append("\n");
|
||||||
|
sb.append(" .family = ").append(HexDump.byteToHex(getFamily())).append("\n");
|
||||||
|
sb.append(" .charset = ").append(HexDump.byteToHex(getCharset())).append("\n");
|
||||||
|
sb.append(" .fontname = ").append(getFontName()).append("\n");
|
||||||
|
sb.append("[/FONT]\n");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void serialize(LittleEndianOutput out) {
|
||||||
|
|
||||||
|
out.writeShort(getFontHeight());
|
||||||
|
out.writeShort(getAttributes());
|
||||||
|
out.writeShort(getColorPaletteIndex());
|
||||||
|
out.writeShort(getBoldWeight());
|
||||||
|
out.writeShort(getSuperSubScript());
|
||||||
|
out.writeByte(getUnderline());
|
||||||
|
out.writeByte(getFamily());
|
||||||
|
out.writeByte(getCharset());
|
||||||
|
out.writeByte(field_9_zero);
|
||||||
|
int fontNameLen = field_11_font_name.length();
|
||||||
|
out.writeByte(fontNameLen);
|
||||||
|
boolean hasMultibyte = StringUtil.hasMultibyte(field_11_font_name);
|
||||||
|
out.writeByte(hasMultibyte ? 0x01 : 0x00);
|
||||||
|
if (fontNameLen > 0) {
|
||||||
|
if (hasMultibyte) {
|
||||||
|
StringUtil.putUnicodeLE(field_11_font_name, out);
|
||||||
|
} else {
|
||||||
|
StringUtil.putCompressedUnicode(field_11_font_name, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected int getDataSize() {
|
||||||
|
int size = 16; // 5 shorts + 6 bytes
|
||||||
|
int fontNameLen = field_11_font_name.length();
|
||||||
|
if (fontNameLen < 1) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasMultibyte = StringUtil.hasMultibyte(field_11_font_name);
|
||||||
|
return size + fontNameLen * (hasMultibyte ? 2 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getSid() {
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clones all the font style information from another
|
||||||
|
* FontRecord, onto this one. This
|
||||||
|
* will then hold all the same font style options.
|
||||||
|
*/
|
||||||
|
public void cloneStyleFrom(FontRecord source) {
|
||||||
|
field_1_font_height = source.field_1_font_height;
|
||||||
|
field_2_attributes = source.field_2_attributes;
|
||||||
|
field_3_color_palette_index = source.field_3_color_palette_index;
|
||||||
|
field_4_bold_weight = source.field_4_bold_weight;
|
||||||
|
field_5_super_sub_script = source.field_5_super_sub_script;
|
||||||
|
field_6_underline = source.field_6_underline;
|
||||||
|
field_7_family = source.field_7_family;
|
||||||
|
field_8_charset = source.field_8_charset;
|
||||||
|
field_9_zero = source.field_9_zero;
|
||||||
|
field_11_font_name = source.field_11_font_name;
|
||||||
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
@ -520,7 +454,7 @@ public final class FontRecord extends StandardRecord {
|
|||||||
result = prime * result + field_9_zero;
|
result = prime * result + field_9_zero;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this FontRecord have all the same font
|
* Does this FontRecord have all the same font
|
||||||
* properties as the supplied FontRecord?
|
* properties as the supplied FontRecord?
|
||||||
@ -528,10 +462,10 @@ public final class FontRecord extends StandardRecord {
|
|||||||
* for exact objects, while this will check
|
* for exact objects, while this will check
|
||||||
* for exact contents, because normally the
|
* for exact contents, because normally the
|
||||||
* font record's position makes a big
|
* font record's position makes a big
|
||||||
* difference too.
|
* difference too.
|
||||||
*/
|
*/
|
||||||
public boolean sameProperties(FontRecord other) {
|
public boolean sameProperties(FontRecord other) {
|
||||||
return
|
return
|
||||||
field_1_font_height == other.field_1_font_height &&
|
field_1_font_height == other.field_1_font_height &&
|
||||||
field_2_attributes == other.field_2_attributes &&
|
field_2_attributes == other.field_2_attributes &&
|
||||||
field_3_color_palette_index == other.field_3_color_palette_index &&
|
field_3_color_palette_index == other.field_3_color_palette_index &&
|
||||||
@ -544,17 +478,4 @@ public final class FontRecord extends StandardRecord {
|
|||||||
field_11_font_name.equals(other.field_11_font_name)
|
field_11_font_name.equals(other.field_11_font_name)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Only returns two for the same exact object -
|
|
||||||
* creating a second FontRecord with the same
|
|
||||||
* properties won't be considered equal, as
|
|
||||||
* the record's position in the record stream
|
|
||||||
* matters.
|
|
||||||
*/
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,18 @@
|
|||||||
package org.apache.poi.hssf.record;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
|
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.poi.util.HexRead;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the serialization and deserialization of the {@link FontRecord}
|
* Tests the serialization and deserialization of the {@link FontRecord}
|
||||||
* class works correctly. Test data taken directly from a real Excel file.
|
* class works correctly. Test data taken directly from a real Excel file.
|
||||||
*/
|
*/
|
||||||
public final class TestFontRecord extends TestCase {
|
public final class TestFontRecord extends TestCase {
|
||||||
|
|
||||||
|
private static final int SID = 0x31;
|
||||||
private static final byte[] data = {
|
private static final byte[] data = {
|
||||||
0xC8-256, 00, // font height = xc8
|
0xC8-256, 00, // font height = xc8
|
||||||
00, 00, // attrs = 0
|
00, 00, // attrs = 0
|
||||||
@ -87,9 +91,7 @@ public final class TestFontRecord extends TestCase {
|
|||||||
record.setFontName("Arial");
|
record.setFontName("Arial");
|
||||||
|
|
||||||
byte [] recordBytes = record.serialize();
|
byte [] recordBytes = record.serialize();
|
||||||
assertEquals(recordBytes.length - 4, data.length);
|
TestcaseRecordInputStream.confirmRecordEncoding(0x31, data, recordBytes);
|
||||||
for (int i = 0; i < data.length; i++)
|
|
||||||
assertEquals("At offset " + i, data[i], recordBytes[i+4]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCloneOnto() {
|
public void testCloneOnto() {
|
||||||
@ -104,7 +106,7 @@ public final class TestFontRecord extends TestCase {
|
|||||||
assertEquals("At offset " + i, data[i], recordBytes[i+4]);
|
assertEquals("At offset " + i, data[i], recordBytes[i+4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSameProperties() throws Exception {
|
public void testSameProperties() {
|
||||||
FontRecord f1 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
|
FontRecord f1 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
|
||||||
FontRecord f2 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
|
FontRecord f2 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
|
||||||
|
|
||||||
@ -120,4 +122,28 @@ public final class TestFontRecord extends TestCase {
|
|||||||
f2.setFontHeight((short)0xc8);
|
f2.setFontHeight((short)0xc8);
|
||||||
assertTrue(f1.sameProperties(f2));
|
assertTrue(f1.sameProperties(f2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bugzilla 47250 suggests that the unicode options byte should be present even when the name
|
||||||
|
* length is zero. The OOO documentation seems to agree with this and POI had no test data
|
||||||
|
* samples to say otherwise.
|
||||||
|
*/
|
||||||
|
public void testEmptyName_bug47250() {
|
||||||
|
byte[] emptyNameData = HexRead.readFromString(
|
||||||
|
"C8 00 00 00 FF 7F 90 01 00 00 00 00 00 00 "
|
||||||
|
+ "00" // zero length
|
||||||
|
+ "00" // unicode options byte
|
||||||
|
);
|
||||||
|
|
||||||
|
RecordInputStream in = TestcaseRecordInputStream.create(SID, emptyNameData);
|
||||||
|
FontRecord fr = new FontRecord(in);
|
||||||
|
if (in.available() == 1) {
|
||||||
|
throw new AssertionFailedError("Identified bug 47250");
|
||||||
|
}
|
||||||
|
assertEquals(0, in.available());
|
||||||
|
|
||||||
|
assertEquals(0, fr.getFontName().length());
|
||||||
|
byte[] recordBytes = fr.serialize();
|
||||||
|
TestcaseRecordInputStream.confirmRecordEncoding(SID, emptyNameData, recordBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user