/* * 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; import com.jswiff.io.InputBitStream; import com.jswiff.io.OutputBitStream; import java.io.IOException; import java.io.Serializable; /** * A TextRecord contains a group of characters which share the same style and * are on the same text line. It is used within <code>DefineText</code> and * <code>DefineText2</code> tags. * * @see com.jswiff.swfrecords.tags.DefineText * @see com.jswiff.swfrecords.tags.DefineText2 */ public final class TextRecord implements Serializable { private boolean hasXOffset; private short xOffset; private boolean hasYOffset; private short yOffset; private boolean hasFont; private int fontId; private int textHeight; private boolean hasColor; private Color textColor; private GlyphEntry[] glyphEntries; /** * Creates a new TextRecord instance. The text contained in this instance is * defined by a list of references to entries from the text font's glyph * table. * * @param glyphEntries glyph entries (indexes in glyph table) */ public TextRecord(GlyphEntry[] glyphEntries) { this.glyphEntries = glyphEntries; } /** * Reads a new TextRecord instance from a bit stream. * * @param stream source stream * @param glyphBits bit count used for glyph index representation * @param advanceBits bit count used for advance value representation * @param hasAlpha specifies whether transparency is supported or not * * @throws IOException if an I/O error has occured */ public TextRecord( InputBitStream stream, short glyphBits, short advanceBits, boolean hasAlpha) throws IOException { stream.readUnsignedBits(4); // ignore first 4 bits hasFont = stream.readBooleanBit(); hasColor = stream.readBooleanBit(); hasYOffset = stream.readBooleanBit(); hasXOffset = stream.readBooleanBit(); if (hasFont) { fontId = stream.readUI16(); } if (hasColor) { textColor = (hasAlpha) ? ((Color) new RGBA(stream)) : ((Color) new RGB(stream)); } if (hasXOffset) { xOffset = stream.readSI16(); } if (hasYOffset) { yOffset = stream.readSI16(); } if (hasFont) { textHeight = stream.readUI16(); } int glyphCount = stream.readUI8(); glyphEntries = new GlyphEntry[glyphCount]; for (int i = 0; i < glyphCount; i++) { glyphEntries[i] = new GlyphEntry(stream, glyphBits, advanceBits); } stream.align(); } /** * Sets the font of the text. If omitted, the preceding text record's font is * used. * * @param fontId character ID of the font * @param textHeight font height in twips (1/20 px) */ public void setFont(int fontId, int textHeight) { this.fontId = fontId; this.textHeight = textHeight; hasFont = true; } /** * Returns the character ID of the font used. Check with * <code>hasFont()</code> first if the font has been specified. The font can * be omitted when the font doesn't change between succeeding text records * (e.g. after a line break). * * @return character ID of used font */ public int getFontId() { return fontId; } /** * Returns the glyph entries, i.e. a list of references to entries from the * used font's glyph table. The text characters contained in a text record * are defined by this list. * * @return glyph entries (indexes in glyph table) */ public GlyphEntry[] getGlyphEntries() { return glyphEntries; } /** * Sets the color of the text. Can be an <code>RGB</code> (if used within * <code>DefineText</code>) or an <code>RGBA</code> instance (if used within * <code>DefineText2</code>). * * @param textColor text color */ public void setTextColor(Color textColor) { this.textColor = textColor; hasColor = true; } /** * Returns the color of the text. Can be an <code>RGB</code> (if used within * <code>DefineText</code>) or an <code>RGBA</code> instance (if used within * <code>DefineText2</code>). * * @return color of text */ public Color getTextColor() { return textColor; } /** * Returns the text height (the font size in twips). Check with * <code>hasFont()</code> first if the font and its size has been specified. * The font can be omitted when the font doesn't change between succeeding * text records (e.g. after a line break). * * @return font size in twips (1/20 px) */ public int getTextHeight() { return textHeight; } /** * Sets the horizontal offset from the left of the text bounds (specified in * <code>DefineText</code> / <code>DefineText2</code>) to the reference * point of the first glyph (in twips). Used for indented or * non-left-justified text. * * @param offset x offset of text in twips (1/20 px) */ public void setXOffset(short offset) { xOffset = offset; hasXOffset = true; } /** * Returns the horizontal offset from the left of the text bounds (specified * in <code>DefineText</code> / <code>DefineText2</code>) to the reference * point of the first glyph (in twips). Used for indented or * non-left-justified text. * * @return horizontal offset */ public short getXOffset() { return xOffset; } /** * Sets the vertical offset from the top of the text bounds (specified in * <code>DefineText</code> / <code>DefineText2</code>) to the reference * point of the first glyph (in twips). Used e.g. for line breaks. * * @param offset y offset of text in twips (1/20 px) */ public void setYOffset(short offset) { yOffset = offset; hasYOffset = true; } /** * Returns the vertical offset from the top of the text bounds (specified in * <code>DefineText</code> / <code>DefineText2</code>) to the reference * point of the first glyph (in twips). Used e.g. for line breaks. * * @return vertical offset */ public short getYOffset() { return yOffset; } /** * Checks if the text color has been specified. * * @return <code>true</code> if text color specified, else <code>false</code> */ public boolean hasColor() { return hasColor; } /** * Checks whether the text font (ID and size) has been specified. * * @return <code>true</code> if font specified, else <code>false</code> */ public boolean hasFont() { return hasFont; } /** * Checks if an x offset has been specified. * * @return <code>true</code> if x offset specified, else <code>false</code> */ public boolean hasXOffset() { return hasXOffset; } /** * Checks if an y offset has been specified. * * @return <code>true</code> if y offset specified, else <code>false</code> */ public boolean hasYOffset() { return hasYOffset; } /** * Writes text record to a bit stream. * * @param stream target bit stream * @param glyphBits bit count used for glyph index representation * @param advanceBits bit count used for advance value representation * * @throws IOException if an I/O error has occured */ public void write(OutputBitStream stream, short glyphBits, short advanceBits) throws IOException { stream.writeUnsignedBits(1, 1); stream.writeUnsignedBits(0, 3); stream.writeBooleanBit(hasFont); stream.writeBooleanBit(hasColor); stream.writeBooleanBit(hasYOffset); stream.writeBooleanBit(hasXOffset); if (hasFont) { stream.writeUI16(fontId); } if (hasColor) { textColor.write(stream); } if (hasXOffset) { stream.writeSI16(xOffset); } if (hasYOffset) { stream.writeSI16(yOffset); } if (hasFont) { stream.writeUI16(textHeight); } stream.writeUI8((short) glyphEntries.length); for (int i = 0; i < glyphEntries.length; i++) { glyphEntries[i].write(stream, glyphBits, advanceBits); } stream.align(); } }