/* * JSwiff is an open source Java API for Macromedia Flash file generation * and manipulation * * Copyright (C) 2004-2005 Ralf Terdic (contact@jswiff.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.jswiff.swfrecords.tags; import com.jswiff.io.InputBitStream; import com.jswiff.io.OutputBitStream; import com.jswiff.swfrecords.LangCode; import java.io.IOException; /** * <p> * Like <code>DefineFontInfo</code>, this tag also maps a glyph font (defined * with <code>DefineFont</code>) to a device font, providing a font name, * style attributes (e.g. bold, italic) and a table of characters matching the * glyph shape table contained in the corresponding <code>DefineFont</code> * tag, thereby defining a one-to-one mapping between glyphs and characters. * </p> * * <p> * Unlike <code>DefineFontInfo</code>, <code>DefineFontInfo2</code> contains a * field for a language code, making text behavior independent on the locale * in which Flash Player is running. This field is considered e.g. when * determining line breaking rules. Also, the ANSI and ShiftJIS encodings are * not available anymore, as Unicode encoding is used. * </p> * * <p> * Note: Consider using <code>DefineFont2</code> instead of the * <code>DefineFont</code> - <code>DefineFontInfo2</code> tag pair, as it * incorporates the same functionality in a single tag. * </p> * * <p> * Note: despite its name, this tag isn't a definition tag. It doesn't define a * new character, it specifies attributes for an existing character. * </p> * * @see DefineFontInfo * @see DefineFont * @see DefineFont2 * @since SWF 6 */ public final class DefineFontInfo2 extends Tag { private int fontId; private String fontName; private boolean smallText; // glyphs aligned on pixel boundaries private boolean italic; private boolean bold; private LangCode langCode; private char[] codeTable; /** * Creates a new DefineFontInfo2 tag. * * @param fontId character ID from <code>DefineFont</code> * @param fontName font name, direct (e.g. 'Times New Roman') or indirect * (e.g. '_serif') * @param codeTable table of characters matching the glyph shape table of * the font * @param langCode font language code */ public DefineFontInfo2( int fontId, String fontName, char[] codeTable, LangCode langCode) { code = TagConstants.DEFINE_FONT_INFO_2; this.fontId = fontId; this.fontName = fontName; this.codeTable = codeTable; this.langCode = langCode; } DefineFontInfo2() { // empty } /** * Sets/clears bold style. * * @param bold <code>true</code> for bold, otherwise <code>false</code> */ public void setBold(boolean bold) { this.bold = bold; } /** * Checks if the text is bold. * * @return <code>true</code> if text is bold, otherwise <code>false</code> */ public boolean isBold() { return bold; } /** * Sets the font's code table containing a character for each glyph. * * @param codeTable code table of font */ public void setCodeTable(char[] codeTable) { this.codeTable = codeTable; } /** * Returns the font's code table containing a character for each glyph. * * @return code table of font */ public char[] getCodeTable() { return codeTable; } /** * Sets the character ID of the font this tag specifies attributes for. * * @param fontId character ID of font */ public void setFontId(int fontId) { this.fontId = fontId; } /** * Returns the character ID of the font. * * @return font's character ID */ public int getFontId() { return fontId; } /** * Sets the name of the font. This can be either a direct (e.g. 'Times New * Roman') or an indirect font name (e.g. '_serif'). * * @param fontName font name as string */ public void setFontName(String fontName) { this.fontName = fontName; } /** * Returns the name of the font. This can be either a direct (e.g. 'Times * New Roman') or an indirect font name (e.g. '_serif'). * * @return font name as string */ public String getFontName() { return fontName; } /** * Sets/clears italic style. * * @param italic <code>true</code> for italic, otherwise <code>false</code> */ public void setItalic(boolean italic) { this.italic = italic; } /** * Checks if the text is italic. * * @return <code>true</code> if text is italic, otherwise * <code>false</code> */ public boolean isItalic() { return italic; } /** * Sets the language code of the font. * * @param langCode font language code */ public void setLangCode(LangCode langCode) { this.langCode = langCode; } /** * Returns the language code of the font. * * @return font language code */ public LangCode getLangCode() { return langCode; } /** * Sets the value of the smallFont flag. When this flag is set, the font is * optimized for small text (anti-aliasing is disabled). * * @param smallText <code>true</code> if flag set, else <code>false</code> */ public void setSmallText(boolean smallText) { this.smallText = smallText; } /** * Checks the smallFont flag. When this flag is set, the font is optimized * for small text (anti-aliasing is disabled). * * @return <code>true</code> if set, else <code>false</code> */ public boolean isSmallText() { return smallText; } protected void writeData(OutputBitStream outStream) throws IOException { outStream.writeUI16(fontId); byte[] fontNameBuffer = (fontName != null) ? fontName.getBytes("UTF-8") : new byte[0]; outStream.writeUI8((short) (fontNameBuffer.length)); // font name length, not null terminated! outStream.writeBytes(fontNameBuffer); outStream.writeUnsignedBits(0, 2); // 2 reserved bits outStream.writeBooleanBit(smallText); outStream.writeUnsignedBits(0, 2); // shiftJIS and ansi not set outStream.writeBooleanBit(italic); outStream.writeBooleanBit(bold); outStream.writeBooleanBit(true); // wideCodes always set outStream.writeUI8(langCode.getLanguageCode()); for (int i = 0; i < codeTable.length; i++) { outStream.writeUI16(codeTable[i]); } } void setData(byte[] data) throws IOException { InputBitStream inStream = new InputBitStream(data); fontId = inStream.readUI16(); short fontNameLen = inStream.readUI8(); // not null-terminated! fontName = new String(inStream.readBytes(fontNameLen), "UTF-8"); inStream.readUnsignedBits(2); // 2 reserved bits smallText = inStream.readBooleanBit(); inStream.readBooleanBit(); // shiftJIS, always 0 inStream.readBooleanBit(); // ANSI, always 0 italic = inStream.readBooleanBit(); bold = inStream.readBooleanBit(); // dataStream.align(); // wideCodes always true - but align not needed before readUI8() langCode = new LangCode((byte) inStream.readUI8()); int codeTableSize = (int) ((data.length - inStream.getOffset()) / 2); codeTable = new char[codeTableSize]; for (int i = 0; i < codeTableSize; i++) { codeTable[i] = (char) inStream.readUI16(); } } }