001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hssf.record;
019:
020: import org.apache.poi.util.LittleEndian;
021: import org.apache.poi.util.StringUtil;
022: import org.apache.poi.util.BitField;
023: import org.apache.poi.util.BitFieldFactory;
024:
025: /**
026: * Title: Font Record - descrbes a font in the workbook (index = 0-3,5-infinity - skip 4)<P>
027: * Description: An element in the Font Table<P>
028: * REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
029: * @author Andrew C. Oliver (acoliver at apache dot org)
030: * @version 2.0-pre
031: */
032:
033: public class FontRecord extends Record {
034: public final static short sid = 0x31; // docs are wrong (0x231 Microsoft Support site article Q184647)
035: public final static short SS_NONE = 0;
036: public final static short SS_SUPER = 1;
037: public final static short SS_SUB = 2;
038: public final static byte U_NONE = 0;
039: public final static byte U_SINGLE = 1;
040: public final static byte U_DOUBLE = 2;
041: public final static byte U_SINGLE_ACCOUNTING = 0x21;
042: public final static byte U_DOUBLE_ACCOUNTING = 0x22;
043: private short field_1_font_height; // in units of .05 of a point
044: private short field_2_attributes;
045:
046: // 0 0x01 - Reserved bit must be 0
047: static final private BitField italic = BitFieldFactory
048: .getInstance(0x02); // is this font in italics
049:
050: // 2 0x04 - reserved bit must be 0
051: static final private BitField strikeout = BitFieldFactory
052: .getInstance(0x08); // is this font has a line through the center
053: static final private BitField macoutline = BitFieldFactory
054: .getInstance(0x10); // some weird macintosh thing....but who understands those mac people anyhow
055: static final private BitField macshadow = BitFieldFactory
056: .getInstance(0x20); // some weird macintosh thing....but who understands those mac people anyhow
057:
058: // 7-6 - reserved bits must be 0
059: // the rest is unused
060: private short field_3_color_palette_index;
061: private short field_4_bold_weight;
062: private short field_5_super _sub_script; // 00none/01super/02sub
063: private byte field_6_underline; // 00none/01single/02double/21singleaccounting/22doubleaccounting
064: private byte field_7_family; // ?? defined by windows api logfont structure?
065: private byte field_8_charset; // ?? defined by windows api logfont structure?
066: private byte field_9_zero = 0; // must be 0
067: private byte field_10_font_name_len; // length of the font name
068: private String field_11_font_name; // whoa...the font name
069:
070: public FontRecord() {
071: }
072:
073: /**
074: * Constructs a Font record and sets its fields appropriately.
075: *
076: * @param in the RecordInputstream to read the record from
077: */
078:
079: public FontRecord(RecordInputStream in) {
080: super (in);
081: }
082:
083: protected void validateSid(short id) {
084: if (id != sid) {
085: throw new RecordFormatException("NOT A FONT RECORD");
086: }
087: }
088:
089: protected void fillFields(RecordInputStream in) {
090: field_1_font_height = in.readShort();
091: field_2_attributes = in.readShort();
092: field_3_color_palette_index = in.readShort();
093: field_4_bold_weight = in.readShort();
094: field_5_super _sub_script = in.readShort();
095: field_6_underline = in.readByte();
096: field_7_family = in.readByte();
097: field_8_charset = in.readByte();
098: field_9_zero = in.readByte();
099: field_10_font_name_len = in.readByte();
100: if (field_10_font_name_len > 0) {
101: if (in.readByte() == 0) { // is compressed unicode
102: field_11_font_name = in
103: .readCompressedUnicode(LittleEndian
104: .ubyteToInt(field_10_font_name_len));
105: } else { // is not compressed unicode
106: field_11_font_name = in
107: .readUnicodeLEString(field_10_font_name_len);
108: }
109: }
110: }
111:
112: /**
113: * sets the height of the font in 1/20th point units
114: *
115: * @param height fontheight (in points/20)
116: */
117:
118: public void setFontHeight(short height) {
119: field_1_font_height = height;
120: }
121:
122: /**
123: * set the font attributes (see individual bit setters that reference this method)
124: *
125: * @param attributes the bitmask to set
126: */
127:
128: public void setAttributes(short attributes) {
129: field_2_attributes = attributes;
130: }
131:
132: // attributes bitfields
133:
134: /**
135: * set the font to be italics or not
136: *
137: * @param italics - whether the font is italics or not
138: * @see #setAttributes(short)
139: */
140:
141: public void setItalic(boolean italics) {
142: field_2_attributes = italic.setShortBoolean(field_2_attributes,
143: italics);
144: }
145:
146: /**
147: * set the font to be stricken out or not
148: *
149: * @param strike - whether the font is stricken out or not
150: * @see #setAttributes(short)
151: */
152:
153: public void setStrikeout(boolean strike) {
154: field_2_attributes = strikeout.setShortBoolean(
155: field_2_attributes, strike);
156: }
157:
158: /**
159: * whether to use the mac outline font style thing (mac only) - Some mac person
160: * should comment this instead of me doing it (since I have no idea)
161: *
162: * @param mac - whether to do that mac font outline thing or not
163: * @see #setAttributes(short)
164: */
165:
166: public void setMacoutline(boolean mac) {
167: field_2_attributes = macoutline.setShortBoolean(
168: field_2_attributes, mac);
169: }
170:
171: /**
172: * whether to use the mac shado font style thing (mac only) - Some mac person
173: * should comment this instead of me doing it (since I have no idea)
174: *
175: * @param mac - whether to do that mac font shadow thing or not
176: * @see #setAttributes(short)
177: */
178:
179: public void setMacshadow(boolean mac) {
180: field_2_attributes = macshadow.setShortBoolean(
181: field_2_attributes, mac);
182: }
183:
184: /**
185: * set the font's color palette index
186: *
187: * @param cpi - font color index
188: */
189:
190: public void setColorPaletteIndex(short cpi) {
191: field_3_color_palette_index = cpi;
192: }
193:
194: /**
195: * set the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is
196: * 0x190 for normal and 0x2bc for bold
197: *
198: * @param bw - a number between 100-1000 for the fonts "boldness"
199: */
200:
201: public void setBoldWeight(short bw) {
202: field_4_bold_weight = bw;
203: }
204:
205: /**
206: * set the type of super or subscript for the font
207: *
208: * @param sss super or subscript option
209: * @see #SS_NONE
210: * @see #SS_SUPER
211: * @see #SS_SUB
212: */
213:
214: public void setSuperSubScript(short sss) {
215: field_5_super _sub_script = sss;
216: }
217:
218: /**
219: * set the type of underlining for the font
220: *
221: * @param u super or subscript option
222: *
223: * @see #U_NONE
224: * @see #U_SINGLE
225: * @see #U_DOUBLE
226: * @see #U_SINGLE_ACCOUNTING
227: * @see #U_DOUBLE_ACCOUNTING
228: */
229:
230: public void setUnderline(byte u) {
231: field_6_underline = u;
232: }
233:
234: /**
235: * set the font family (TODO)
236: *
237: * @param f family
238: */
239:
240: public void setFamily(byte f) {
241: field_7_family = f;
242: }
243:
244: /**
245: * set the character set
246: *
247: * @param charset - characterset
248: */
249:
250: public void setCharset(byte charset) {
251: field_8_charset = charset;
252: }
253:
254: /**
255: * set the length of the fontname string
256: *
257: * @param len length of the font name
258: * @see #setFontName(String)
259: */
260:
261: public void setFontNameLength(byte len) {
262: field_10_font_name_len = len;
263: }
264:
265: /**
266: * set the name of the font
267: *
268: * @param fn - name of the font (i.e. "Arial")
269: */
270:
271: public void setFontName(String fn) {
272: field_11_font_name = fn;
273: }
274:
275: /**
276: * gets the height of the font in 1/20th point units
277: *
278: * @return fontheight (in points/20)
279: */
280:
281: public short getFontHeight() {
282: return field_1_font_height;
283: }
284:
285: /**
286: * get the font attributes (see individual bit getters that reference this method)
287: *
288: * @return attribute - the bitmask
289: */
290:
291: public short getAttributes() {
292: return field_2_attributes;
293: }
294:
295: /**
296: * get whether the font is to be italics or not
297: *
298: * @return italics - whether the font is italics or not
299: * @see #getAttributes()
300: */
301:
302: public boolean isItalic() {
303: return italic.isSet(field_2_attributes);
304: }
305:
306: /**
307: * get whether the font is to be stricken out or not
308: *
309: * @return strike - whether the font is stricken out or not
310: * @see #getAttributes()
311: */
312:
313: public boolean isStruckout() {
314: return strikeout.isSet(field_2_attributes);
315: }
316:
317: /**
318: * whether to use the mac outline font style thing (mac only) - Some mac person
319: * should comment this instead of me doing it (since I have no idea)
320: *
321: * @return mac - whether to do that mac font outline thing or not
322: * @see #getAttributes()
323: */
324:
325: public boolean isMacoutlined() {
326: return macoutline.isSet(field_2_attributes);
327: }
328:
329: /**
330: * whether to use the mac shado font style thing (mac only) - Some mac person
331: * should comment this instead of me doing it (since I have no idea)
332: *
333: * @return mac - whether to do that mac font shadow thing or not
334: * @see #getAttributes()
335: */
336:
337: public boolean isMacshadowed() {
338: return macshadow.isSet(field_2_attributes);
339: }
340:
341: /**
342: * get the font's color palette index
343: *
344: * @return cpi - font color index
345: */
346:
347: public short getColorPaletteIndex() {
348: return field_3_color_palette_index;
349: }
350:
351: /**
352: * get the bold weight for this font (100-1000dec or 0x64-0x3e8). Default is
353: * 0x190 for normal and 0x2bc for bold
354: *
355: * @return bw - a number between 100-1000 for the fonts "boldness"
356: */
357:
358: public short getBoldWeight() {
359: return field_4_bold_weight;
360: }
361:
362: /**
363: * get the type of super or subscript for the font
364: *
365: * @return super or subscript option
366: * @see #SS_NONE
367: * @see #SS_SUPER
368: * @see #SS_SUB
369: */
370:
371: public short getSuperSubScript() {
372: return field_5_super _sub_script;
373: }
374:
375: /**
376: * get the type of underlining for the font
377: *
378: * @return super or subscript option
379: *
380: * @see #U_NONE
381: * @see #U_SINGLE
382: * @see #U_DOUBLE
383: * @see #U_SINGLE_ACCOUNTING
384: * @see #U_DOUBLE_ACCOUNTING
385: */
386:
387: public byte getUnderline() {
388: return field_6_underline;
389: }
390:
391: /**
392: * get the font family (TODO)
393: *
394: * @return family
395: */
396:
397: public byte getFamily() {
398: return field_7_family;
399: }
400:
401: /**
402: * get the character set
403: *
404: * @return charset - characterset
405: */
406:
407: public byte getCharset() {
408: return field_8_charset;
409: }
410:
411: /**
412: * get the length of the fontname string
413: *
414: * @return length of the font name
415: * @see #getFontName()
416: */
417:
418: public byte getFontNameLength() {
419: return field_10_font_name_len;
420: }
421:
422: /**
423: * get the name of the font
424: *
425: * @return fn - name of the font (i.e. "Arial")
426: */
427:
428: public String getFontName() {
429: return field_11_font_name;
430: }
431:
432: public String toString() {
433: StringBuffer buffer = new StringBuffer();
434:
435: buffer.append("[FONT]\n");
436: buffer.append(" .fontheight = ").append(
437: Integer.toHexString(getFontHeight())).append("\n");
438: buffer.append(" .attributes = ").append(
439: Integer.toHexString(getAttributes())).append("\n");
440: buffer.append(" .italic = ").append(isItalic())
441: .append("\n");
442: buffer.append(" .strikout = ").append(isStruckout())
443: .append("\n");
444: buffer.append(" .macoutlined= ")
445: .append(isMacoutlined()).append("\n");
446: buffer.append(" .macshadowed= ")
447: .append(isMacshadowed()).append("\n");
448: buffer.append(" .colorpalette = ").append(
449: Integer.toHexString(getColorPaletteIndex())).append(
450: "\n");
451: buffer.append(" .boldweight = ").append(
452: Integer.toHexString(getBoldWeight())).append("\n");
453: buffer.append(" .supersubscript = ").append(
454: Integer.toHexString(getSuperSubScript())).append("\n");
455: buffer.append(" .underline = ").append(
456: Integer.toHexString(getUnderline())).append("\n");
457: buffer.append(" .family = ").append(
458: Integer.toHexString(getFamily())).append("\n");
459: buffer.append(" .charset = ").append(
460: Integer.toHexString(getCharset())).append("\n");
461: buffer.append(" .namelength = ").append(
462: Integer.toHexString(getFontNameLength())).append("\n");
463: buffer.append(" .fontname = ").append(getFontName())
464: .append("\n");
465: buffer.append("[/FONT]\n");
466: return buffer.toString();
467: }
468:
469: public int serialize(int offset, byte[] data) {
470: int realflen = getFontNameLength() * 2;
471:
472: LittleEndian.putShort(data, 0 + offset, sid);
473: LittleEndian.putShort(data, 2 + offset,
474: (short) (15 + realflen + 1)); // 19 - 4 (sid/len) + font name length = datasize
475:
476: // undocumented single byte (1)
477: LittleEndian.putShort(data, 4 + offset, getFontHeight());
478: LittleEndian.putShort(data, 6 + offset, getAttributes());
479: LittleEndian.putShort(data, 8 + offset, getColorPaletteIndex());
480: LittleEndian.putShort(data, 10 + offset, getBoldWeight());
481: LittleEndian.putShort(data, 12 + offset, getSuperSubScript());
482: data[14 + offset] = getUnderline();
483: data[15 + offset] = getFamily();
484: data[16 + offset] = getCharset();
485: data[17 + offset] = field_9_zero;
486: data[18 + offset] = getFontNameLength();
487: data[19 + offset] = (byte) 1;
488: if (getFontName() != null) {
489: StringUtil.putUnicodeLE(getFontName(), data, 20 + offset);
490: }
491: return getRecordSize();
492: }
493:
494: public int getRecordSize() {
495: return (getFontNameLength() * 2) + 20;
496: }
497:
498: public short getSid() {
499: return sid;
500: }
501: }
|