]> source.dussan.org Git - poi.git/commitdiff
Bugzilla 47250 - Fixed FontRecord to expect unicode flags even when name length is...
authorJosh Micich <josh@apache.org>
Fri, 22 May 2009 21:30:50 +0000 (21:30 +0000)
committerJosh Micich <josh@apache.org>
Fri, 22 May 2009 21:30:50 +0000 (21:30 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@777717 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/record/FontRecord.java
src/testcases/org/apache/poi/hssf/record/TestFontRecord.java

index 2549d2c2873b215a343aed7052df74e7f9437eee..939ab49263a7738d43f7ed56c5cd09d33d526661 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <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">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>
index 5486266da60bc33fc6313f018d30c49928b38d76..481dce9d5058ca03ae90dc67c4a22fac76989109 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <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">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>
index 3b0b4f3e30703ad1212149768d18fcac36967eba..b4a9e267b1235db559e54256436ab0ff384682fc 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
 
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndianOutput;
 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)
  */
 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     SS_NONE             = 0;
-    public final static short     SS_SUPER            = 1;
-    public final static short     SS_SUB              = 2;
-    public final static byte      U_NONE              = 0;
-    public final static byte      U_SINGLE            = 1;
-    public final static byte      U_DOUBLE            = 2;
-    public final static byte      U_SINGLE_ACCOUNTING = 0x21;
-    public final static byte      U_DOUBLE_ACCOUNTING = 0x22;
-    private short                 field_1_font_height;        // in units of .05 of a point
-    private short                 field_2_attributes;
-
-    // 0 0x01 - Reserved bit must be 0
-    private static final BitField italic     = BitFieldFactory.getInstance(0x02); // is this font in italics
-
-    // 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 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
-
-    // 7-6 - reserved bits must be 0
-    // the rest is unused
-    private short                 field_3_color_palette_index;
-    private short                 field_4_bold_weight;
-    private short                 field_5_super_sub_script;   // 00none/01super/02sub
-    private byte                  field_6_underline;          // 00none/01single/02double/21singleaccounting/22doubleaccounting
-    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_9_zero = 0;           // must be 0
-    /** possibly empty string never <code>null</code> */
-    private String                field_11_font_name;         // whoa...the font name
-
-    public FontRecord() {
-    }
-
-    public FontRecord(RecordInputStream in) {
-        field_1_font_height         = in.readShort();
-        field_2_attributes          = in.readShort();
-        field_3_color_palette_index = in.readShort();
-        field_4_bold_weight         = in.readShort();
-        field_5_super_sub_script    = in.readShort();
-        field_6_underline           = in.readByte();
-        field_7_family              = in.readByte();
-        field_8_charset             = in.readByte();
-        field_9_zero                = in.readByte();
-        int field_10_font_name_len  = in.readUByte();
-        if (field_10_font_name_len > 0) {
-            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 = "";
-        }
-    }
-
-    /**
-     * sets the height of the font in 1/20th point units
-     *
-     * @param height  fontheight (in points/20)
-     */
-
-    public void setFontHeight(short height)
-    {
-        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();
+       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_SUPER            = 1;
+       public final static short     SS_SUB              = 2;
+       public final static byte      U_NONE              = 0;
+       public final static byte      U_SINGLE            = 1;
+       public final static byte      U_DOUBLE            = 2;
+       public final static byte      U_SINGLE_ACCOUNTING = 0x21;
+       public final static byte      U_DOUBLE_ACCOUNTING = 0x22;
+       private short                 field_1_font_height;        // in units of .05 of a point
+       private short                 field_2_attributes;
+
+       // 0 0x01 - Reserved bit must be 0
+       private static final BitField italic     = BitFieldFactory.getInstance(0x02); // is this font in italics
+
+       // 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 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
+
+       // 7-6 - reserved bits must be 0
+       // the rest is unused
+       private short                 field_3_color_palette_index;
+       private short                 field_4_bold_weight;
+       private short                 field_5_super_sub_script;   // 00none/01super/02sub
+       private byte                  field_6_underline;          // 00none/01single/02double/21singleaccounting/22doubleaccounting
+       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_9_zero = 0;           // must be 0
+       /** possibly empty string never <code>null</code> */
+       private String                field_11_font_name;
+
+       public FontRecord() {
+       }
+
+       public FontRecord(RecordInputStream in) {
+               field_1_font_height         = in.readShort();
+               field_2_attributes          = in.readShort();
+               field_3_color_palette_index = in.readShort();
+               field_4_bold_weight         = in.readShort();
+               field_5_super_sub_script    = in.readShort();
+               field_6_underline           = in.readByte();
+               field_7_family              = in.readByte();
+               field_8_charset             = in.readByte();
+               field_9_zero                = in.readByte();
+               int field_10_font_name_len  = in.readUByte();
+               int unicodeFlags            = in.readUByte(); // options byte present always (even if no character data)
+
+               if (field_10_font_name_len > 0) {
+                       if (unicodeFlags == 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 = "";
+               }
+       }
+
+       /**
+        * sets the height of the font in 1/20th point units
+        *
+        * @param height  fontheight (in points/20)
+        */
+       public void setFontHeight(short height) {
+               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 - 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) {
-               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);
-            }
+                       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;
                }
-    }
-    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()
-    {
-        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;
-    }
+
+               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() {
                final int prime = 31;
@@ -520,7 +454,7 @@ public final class FontRecord extends StandardRecord {
                result = prime * result + field_9_zero;
                return result;
        }
-       
+
        /**
         * Does this FontRecord have all the same font
         *  properties as the supplied FontRecord?
@@ -528,10 +462,10 @@ public final class FontRecord extends StandardRecord {
         *  for exact objects, while this will check
         *  for exact contents, because normally the
         *  font record's position makes a big
-        *  difference too.  
+        *  difference too.
         */
        public boolean sameProperties(FontRecord other) {
-               return 
+               return
                field_1_font_height         == other.field_1_font_height &&
                field_2_attributes          == other.field_2_attributes &&
                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)
                ;
        }
-
-       /**
-        * 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;
-       }
 }
index 3d5e053daa460693cf5c0592a3dae54e22e4a7ad..7791df3aa67fa1d1dc97b8184392907398c47619 100644 (file)
 package org.apache.poi.hssf.record;
 
 
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
+import org.apache.poi.util.HexRead;
+
 /**
  * Tests the serialization and deserialization of the {@link FontRecord}
  * class works correctly.  Test data taken directly from a real Excel file.
  */
 public final class TestFontRecord extends TestCase {
 
+    private static final int SID = 0x31;
     private static final byte[] data = {
             0xC8-256, 00,       // font height = xc8
             00, 00,             // attrs = 0
@@ -87,9 +91,7 @@ public final class TestFontRecord extends TestCase {
         record.setFontName("Arial");
 
         byte [] recordBytes = record.serialize();
-        assertEquals(recordBytes.length - 4, data.length);
-        for (int i = 0; i < data.length; i++)
-            assertEquals("At offset " + i, data[i], recordBytes[i+4]);
+        TestcaseRecordInputStream.confirmRecordEncoding(0x31, data, recordBytes);
     }
 
     public void testCloneOnto() {
@@ -104,7 +106,7 @@ public final class TestFontRecord extends TestCase {
             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 f2 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
 
@@ -120,4 +122,28 @@ public final class TestFontRecord extends TestCase {
         f2.setFontHeight((short)0xc8);
         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);
+    }
 }