/*
* 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 java.io.IOException;
/**
* <p>
* This tag 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>
* With this mapping available, you can choose to use the specified device font
* if available and use the glyph font as fallback by passing the
* <code>devicefont</code> parameter to the flash player (within the object
* tag: <code><param name="devicefont"
* value="true"></code>). With dynamic text, this parameter is
* not needed anymore, as this option can be specified within the
* <code>DefineEditText</code> tag.
* </p>
*
* <p>
* Note: Consider using <code>DefineFont2</code> instead of the
* <code>DefineFont</code> - <code>DefineFontInfo</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 DefineFont
* @see DefineFont2
* @see DefineEditText
* @since SWF 1
*/
public final class DefineFontInfo extends Tag {
private int fontId;
private String fontName;
private boolean smallText;
private boolean shiftJIS;
private boolean ansi;
private boolean italic;
private boolean bold;
private char[] codeTable;
/**
* Creates a new DefineFontInfo 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
*/
public DefineFontInfo(int fontId, String fontName, char[] codeTable) {
code = TagConstants.DEFINE_FONT_INFO;
this.fontId = fontId;
this.fontName = fontName;
this.codeTable = codeTable;
}
DefineFontInfo() {
// empty
}
/**
* Sets the value of the ANSI flag. If ANSI is set, the shiftJIS flag is
* cleared. If neither ANSI nor shiftJIS are set, UCS-2 is used.
*
* @param ansi <code>true</code> if flag set, else <code>false</code>
*/
public void setANSI(boolean ansi) {
this.ansi = ansi;
if (ansi) {
shiftJIS = false;
}
}
/**
* Checks if the ANSI flag is set. If neither ANSI nor shiftJIS are set,
* UCS-2 is used.
*
* @return <code>true</code> if flag set, else <code>false</code>
*/
public boolean isANSI() {
return ansi;
}
/**
* 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 this tag specifies attributes for.
*
* @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 value of the shiftJIS flag. If shiftJIS is set, then ANSI is
* cleared. If neither ANSI nor shiftJIS are set, UCS-2 is used.
*
* @param shiftJIS <code>true</code> if flag set, else <code>false</code>
*/
public void setShiftJIS(boolean shiftJIS) {
this.shiftJIS = shiftJIS;
if (shiftJIS) {
ansi = false;
}
}
/**
* Checks if the shiftJIS flag is set. If neither ANSI nor shiftJIS are
* set, UCS-2 is used.
*
* @return <code>true</code> if flag set, else <code>false</code>
*/
public boolean isShiftJIS() {
return shiftJIS;
}
/**
* 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);
outStream.writeBooleanBit(smallText);
outStream.writeBooleanBit(shiftJIS);
outStream.writeBooleanBit(ansi);
outStream.writeBooleanBit(italic);
outStream.writeBooleanBit(bold);
boolean wideCodes = (!(shiftJIS || ansi)); // if shiftJIS or ansi set, then false; else true
outStream.writeBooleanBit(wideCodes);
if (wideCodes) {
for (int i = 0; i < codeTable.length; i++) {
outStream.writeUI16(codeTable[i]);
}
} else {
for (int i = 0; i < codeTable.length; i++) {
outStream.writeUI8((short) 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();
shiftJIS = inStream.readBooleanBit();
ansi = inStream.readBooleanBit();
italic = inStream.readBooleanBit();
bold = inStream.readBooleanBit();
boolean wideCodes = inStream.readBooleanBit();
if (wideCodes) {
int codeTableSize = (int) ((data.length - inStream.getOffset()) / 2);
codeTable = new char[codeTableSize];
for (int i = 0; i < codeTableSize; i++) {
codeTable[i] = (char) inStream.readUI16();
}
} else {
int codeTableSize = (int) (data.length - inStream.getOffset());
codeTable = new char[codeTableSize];
for (int i = 0; i < codeTableSize; i++) {
codeTable[i] = (char) inStream.readUI8();
}
}
}
}