📄 fstextconstructor.java
字号:
/*
* FSTextConstructor.java
* Transform Utilities
*
* Copyright (c) 2001-2006 Flagstone Software Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Flagstone Software Ltd. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.flagstone.transform.util;
import com.flagstone.transform.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
/**
* The FSTextConstructor class greatly simplifies the use of fonts and text when
* creating Flash files. Font definitions can be created in three ways:
*
* <ol>
* <li>Using TrueType or OpenType font definition stored in a file.</li>
* <li>Using a font definition stored in an existing Flash file.</li>
* <li>Using a given Java AWT font as a template.</li>
* </ol>
*
* <P>Font definitions from TrueType, OpenType or Flash files are created by
* specifying the name of the file:</p>
*
* <pre>
* FSTextConstructor font = new FSTextConstructor(id, trueTypeFile.getPath());
* FSTextConstructor font = new FSTextConstructor(id, swfFile.getPath());
* </pre>
*
* <P>The OpenType or TrueType file is parsed to construct the font definition.
* Files with the extensions ".otf" or ".ttf" may be used. Files containing
* collections of fonts ".otc" are not currently supported. For Flash files the
* first font definition encountered is used and all the text definition objects
* associated with the font are used to obtain the advance information for each
* character. An example Flash file can be found in the resources directory
* included in this release.</p>
*
* <P>Font definitions from AWT templates are created by passing a font object:</p>
*
* <pre>
* FSTextConstructor font = new FSTextConstructor(id, new Font("Arial", Font.PLAIN, 1));
* </pre>
*
* <p>Only the font or file name needs to specified. Unlike Java fonts, font
* definitions in Flash are size independent, the size and colour in which a
* given string in rendered is specified in the object that defines the text to
* be displayed avoiding the need to create multiple font definitions for the
* same font name.</p>
*
* <P>An array of FSGlyph objects are created from the font definition. Each
* object contains the glyph for the font, the associated character code and
* information used to lay out each glyph when it is displayed.</P>
*
* <P>Once a font has been created text strings can be generated:</p>
*
* <pre>
* int fontSize = 280; // twips
* FSColor fontColor = FSColorTable.black();
* FSDefineText2 aString = font.defineText("This is a string", fontSize, fontColor);
* </pre>
*
* <P>The defineText method returns FSDefineText2 objects since they support
* transparent colours, while FSDefineText only supports opaque colours.</P>
*
* <P>Once all the strings to be displayed have been generated the font
* definition object containing the glyphs can be generated.</p>
*
* <pre>
* FSDefineFont2 defineFont = font.defineFont();
* </pre>
*
* <P>Remember however that objects in a Flash file must be defined before they
* are used so the font object must be added to the file before the first
* FSDefineText object that references the glyphs in the font.</p>
*
* <P>To reduce the size of the Flash file only the glyphs actually displayed
* can be included in a font definition object. When a FSDefineText object is
* created the glyphs used are marked. This is why the text definition objects
* are generated before the font definition.</P>
*
* <P>Glyphs are included in the font in the order they are used with each
* FSDefineText2 object referencing a glyph by its position in the array of
* glyphs contained in a font definition. Any unused glyphs can then easily be
* omitted.</P>
*
* <P>When the font definition is created only the glyphs used (up to that
* point) are included. If subsequent FSDefineText objects are generated that
* include glyphs not previously used then the text will not be displayed
* correctly.</p>
*
* <b>Text Fields</b><br/>
*
* <P>When creating text fields using the FSDefineTextField class, there are two
* options when specifying the font used to display the characters entered into
* the field:
*
* <ol>
* <li>The glyphs for the font may be loaded from the host platform.</li>
* <li>The glyphs for the font are taken from a font definition object.</li>
* </ol>
*
* <P>Using the glyphs loaded from the host platform is by far the easiest way
* of using text fields. First a font definition is created that specifies only
* the name of the font which will be loaded from the host platform. Then
* creating the text fields set the useFontGlyphs attribute to false.</P>
*
* <pre>
* FSDefineFont2 fontDefinition = new FSDefineFont2(movie.newIdentifier(), "Arial");
*
* FSDefineTextField textField = new FSDefineTextField(movie.newIdentifier(), bounds);
*
* textField.setUseFontGlyphs(false);
* </pre>
*
* <P>This approach only works if the font is defined on the host platform
* otherwise the Flash Player will substitute a default font.</P>
*
* <P>When using a font definition contained in the Flash file obviously the
* glyphs for all possible characters must be defined otherwise the character
* will not be displayed correctly. When using text fields the characters must
* be defined in the font, sorted by ascending character code, otherwise the
* text will not be displayed correctly. To do this the FSCharacterTable class
* provides arrays of characters sorted in the correct order. The array is
* passed to the willDisplay() method and the FSTextConstructor will add the
* glyphs for the characters in the order they appear in the array:</p>
*
* <pre>
* char[] characterSet = FSCharacterTable.ascii();
*
* textConstructor.willDisplay(characterSet);
* </pre>
*
* <P>This will add ALL of the characters in the array to the font definition.
* Several character sets are provided in the FSCharacterTable class but any
* array of characters could be passed to the willDisplay() method - allowing
* smaller font definitions to be created when only a few characters are
* displayed.</p>
*
* <b>Missing Characters</b><br/>
*
* <P>Characters that cannot be displayed using the font are handled by a
* displaying a default glyph which typically represents a space or an empty
* box. Both Java AWT and True/Open Type definitions explicitly define the
* missing glyph. For fonts parsed from Flash files the missing glyph is assumed
* (by default) to be the first glyph in the font definition.</p>
*
* <P>When a font is loaded the missing glyph is added automatically to the font
* definition so there is no need to explicitly include it by creating a text
* object to force it to be included. The missing glyph will always be the first
* glyph in the font definition generated by the FSTextConstructor object so it
* may be substituted by another suitable shape if required.</P>
*
* <P>Whether a string can be displayed using a font can be determined by the
* <em>canDisplay()</em> method which returns the index of the first character
* that cannot be displayed (the missing glyph will be displayed instead) or -1
* if all the characters are represented in the font.</P>
*/
public class FSTextConstructor
{
private static final int OS_2 = 0x4F532F32;
private static final int HEAD = 0x68656164;
private static final int HHEA = 0x68686561;
private static final int MAXP = 0x6D617870;
private static final int LOCA = 0x6C6F6361;
private static final int CMAP = 0x636D6170;
private static final int HMTX = 0x686D7478;
private static final int NAME = 0x6E616D65;
private static final int GLYF = 0x676C7966;
private static final int ITLF_SHORT = 0;
private static final int ITLF_LONG = 1;
private static final int FONT_WEIGHT_THIN = 100;
private static final int FONT_WEIGHT_EXTRALIGHT = 200;
private static final int FONT_WEIGHT_LIGHT = 300;
private static final int FONT_WEIGHT_NORMAL = 400;
private static final int FONT_WEIGHT_MEDIUM = 500;
private static final int FONT_WEIGHT_SEMIBOLD = 600;
private static final int FONT_WEIGHT_BOLD = 700;
private static final int FONT_WEIGHT_EXTRABOLD = 800;
private static final int FONT_WEIGHT_BLACK = 900;
private static final int ON_CURVE = 0x01;
private static final int X_SHORT = 0x02;
private static final int Y_SHORT = 0x04;
private static final int REPEAT_FLAG = 0x08;
private static final int X_SAME = 0x10;
private static final int Y_SAME = 0x20;
private static final int X_POSITIVE = 0x10;
private static final int Y_POSITIVE = 0x20;
private static final int ARG_1_AND_2_ARE_WORDS = 0x01;
private static final int ARGS_ARE_XY_VALUES = 0x02;
private static final int WE_HAVE_A_SCALE = 0x08;
private static final int WE_HAVE_AN_X_AND_Y_SCALE = 0x40;
private static final int WE_HAVE_A_TWO_BY_TWO = 0x80;
private static final int MORE_COMPONENTS = 0x10;
private static final int NUMBER_OF_METRICS = 0;
private static final int SCALE = 1;
private static final int GLYPH_OFFSET_SIZE = 2;
private class FSGlyph
{
FSShape shape = null;
FSBounds bounds = new FSBounds(0, 0, 0, 0);
int advance = 0;
int[] xCoordinates = null;
int[] yCoordinates = null;
boolean[] onCurve = null;
int[] endPoints = null;
FSGlyph()
{
shape = new FSShape();
bounds = new FSBounds(0, 0, 0, 0);
advance = 0;
xCoordinates = new int[] {};
yCoordinates = new int[] {};
onCurve = new boolean[] {};
endPoints = new int[] {};
}
FSGlyph(FSShape aShape, FSBounds aBounds)
{
shape = aShape;
bounds = aBounds;
advance = 0;
xCoordinates = new int[] {};
yCoordinates = new int[] {};
onCurve = new boolean[] {};
endPoints = new int[] {};
}
};
private int identifier = 0;
private String name = "";
private int encoding = 0;
private float size = 0.0f;
private boolean isBold = false;
private boolean isItalic = false;
private int baseline = 0;
private float ascent = 0;
private float descent = 0;
private float leading = 0;
private short[] orderTable = new short[65536];
private short[] characterTable = new short[65536];
private FSGlyph[] glyphTable = null;
private int numberOfGlyphs = 0;
private int missingGlyph = 0;
private ArrayList kernings = new ArrayList();
private int[] attributes = new int[8];
/**
* Creates a new FSTextConstructor object using the specified font.
*
* <P>The fontName can be used to identify a particular font in two ways,
* either specifying:
*
* <ol>
* <li>the name of a file containing a TrueType or OpenType font definition.</li>
* <li>the name of a Flash file containing font definition.</li>
* </ol>
*
* IMPORTANT: This method previously allowed the name of a AWT Font to be
* specified as an argument. This will no longer be supported in future
* releases, use the FSTextCOnstructor(int, Font) method instead.
*
* @param anIdentifier a unique identifier that will be assigned to the
* font definition object generated and referenced by all the text object
* generated.
*
* @param filename either the name of a Flash, TrueType or OpenType file
* containing an existing font definition.
*
* @throws FileNotFoundException if the fontName specifies a file and the
* file cannot be found or opened.
*
* @throws IOException if the fontName specifies a file and an error occurs while
* reading the file from disk.
*
* @throws DataFormatException if the fontName specifies a file and an error occurs while
* parsing the font definition.
*/
public FSTextConstructor(int anIdentifier, String filename) throws IOException, DataFormatException
{
identifier = anIdentifier;
for (int i=0; i<65536; i++)
orderTable[i] = -1;
if (filename.toLowerCase().endsWith(".swf"))
decodeSWFFont(filename);
else if (filename.toLowerCase().endsWith(".otf"))
decodeOpenTypeFont(filename);
else if (filename.toLowerCase().endsWith(".ttf"))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -