123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- /* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ==================================================================== */
-
- package org.apache.poi.hssf.record;
-
- import java.util.Map;
- import java.util.Objects;
- import java.util.function.Supplier;
-
- import org.apache.poi.util.BitField;
- import org.apache.poi.util.BitFieldFactory;
- import org.apache.poi.util.GenericRecordUtil;
- import org.apache.poi.util.LittleEndianOutput;
- import org.apache.poi.util.StringUtil;
-
- /** Describes a font in the workbook */
- public final class FontRecord extends StandardRecord {
- // docs are wrong (0x231 Microsoft Support site article Q184647)
- public static final short sid = 0x0031;
- public static final short SS_NONE = 0;
- public static final short SS_SUPER = 1;
- public static final short SS_SUB = 2;
- public static final byte U_NONE = 0;
- public static final byte U_SINGLE = 1;
- public static final byte U_DOUBLE = 2;
- public static final byte U_SINGLE_ACCOUNTING = 0x21;
- public static final byte U_DOUBLE_ACCOUNTING = 0x22;
-
- // 0 0x01 - Reserved bit must be 0
- // is this font in italics
- private static final BitField italic = BitFieldFactory.getInstance(0x02);
-
- // 2 0x04 - reserved bit must be 0
- // is this font has a line through the center
- private static final BitField strikeout = BitFieldFactory.getInstance(0x08);
- // some weird macintosh thing....but who understands those mac people anyhow
- private static final BitField macoutline = BitFieldFactory.getInstance(0x10);
- private static final BitField macshadow = BitFieldFactory.getInstance(0x20);
-
- // in units of .05 of a point
- private short field_1_font_height;
- private short field_2_attributes;
-
- // 7-6 - reserved bits must be 0
- // the rest is unused
- private short field_3_color_palette_index;
- private short field_4_bold_weight;
- // 00none/01super/02sub
- private short field_5_super_sub_script;
- // 00none/01single/02double/21singleaccounting/22doubleaccounting
- private byte field_6_underline;
- // ?? defined by windows api logfont structure?
- private byte field_7_family;
- // ?? defined by windows api logfont structure?
- private byte field_8_charset;
- // must be 0
- private byte field_9_zero;
- /** possibly empty string never <code>null</code> */
- private String field_11_font_name;
-
- public FontRecord() {
- }
-
- public FontRecord(FontRecord other) {
- super(other);
- 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;
- field_4_bold_weight = other.field_4_bold_weight;
- field_5_super_sub_script = other.field_5_super_sub_script;
- field_6_underline = other.field_6_underline;
- field_7_family = other.field_7_family;
- field_8_charset = other.field_8_charset;
- field_9_zero = other.field_9_zero;
- field_11_font_name = other.field_11_font_name;
- }
-
- 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 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.
- *
- * @param source the record to clone the properties from
- */
- 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() {
- return Objects.hash(
- field_1_font_height
- , field_2_attributes
- , field_3_color_palette_index
- , field_4_bold_weight
- , field_5_super_sub_script
- , field_6_underline
- , field_7_family
- , field_8_charset
- , field_9_zero
- , field_11_font_name
- );
- }
-
- /**
- * Does this FontRecord have all the same font
- * properties as the supplied FontRecord?
- * Note that {@link #equals(Object)} will check
- * for exact objects, while this will check
- * for exact contents, because normally the
- * font record's position makes a big
- * difference too.
- *
- * @param other the record to compare with
- *
- * @return true, if the properties match
- */
- public boolean sameProperties(FontRecord other) {
-
- 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 &&
- field_4_bold_weight == other.field_4_bold_weight &&
- field_5_super_sub_script == other.field_5_super_sub_script &&
- field_6_underline == other.field_6_underline &&
- field_7_family == other.field_7_family &&
- field_8_charset == other.field_8_charset &&
- field_9_zero == other.field_9_zero &&
- Objects.equals(this.field_11_font_name, other.field_11_font_name)
- ;
- }
-
- public boolean equals(Object o) {
- return (o instanceof FontRecord) && sameProperties((FontRecord) o);
- }
-
- @Override
- public FontRecord copy() {
- return new FontRecord(this);
- }
-
- @Override
- public HSSFRecordTypes getGenericRecordType() {
- return HSSFRecordTypes.FONT;
- }
-
- @Override
- public Map<String, Supplier<?>> getGenericProperties() {
- return GenericRecordUtil.getGenericProperties(
- "fontHeight", this::getFontHeight,
- "attributes", GenericRecordUtil.getBitsAsString(this::getAttributes,
- new BitField[]{italic,strikeout,macoutline,macshadow},
- new String[]{"ITALIC","STRIKEOUT","MACOUTLINE","MACSHADOW"}),
- "colorPalette", this::getColorPaletteIndex,
- "boldWeight", this::getBoldWeight,
- "superSubScript", this::getSuperSubScript,
- "underline", this::getUnderline,
- "family", this::getFamily,
- "charset", this::getCharset,
- "fontName", this::getFontName
- );
- }
- }
|