📄 fsdefinetext.java
字号:
/*
* FSDefineText.java
* Transform
*
* 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;
import java.util.*;
/**
FSDefineText defines one or more lines of text.
<p>The characters, style and layout information is defined using FSText objects. The FSDefineText class acts as a container for the text, defining the bounding rectangle that encloses the text along with a coordinate transform that can be used to change the size and orientation of the text when it is displayed.</p>
<table class="datasheet">
<tr><th align="left" colspan="2">Attributes</th></tr>
<tr>
<td><a name="FSDefineText_0">type</a></td>
<td>Identifies the data structure when it is encoded. Read-only.</td>
</tr>
<tr>
<td><a name="FSDefineText_1">identifier</a></td>
<td>An unique identifier for this object in the range 1..65535.</td>
</tr>
<tr>
<td><a name="FSDefineText_2">bounds</a></td>
<td>A bounding rectangle for the entire block of text defined in the object.</td>
</tr>
<tr>
<td><a name="FSDefineText_3">transform</a></td>
<td>A coordinate transform describing the placement, size and rotation of the text block.</td>
</tr>
<tr>
<td><a name="FSDefineText_4">objects</a></td>
<td>An array of FSText objects describing the characters to be displayed and their attributes.</td>
</tr>
</table>
<p>The bounding rectangle and transform controls how the text is laid out. Each FSText object in the textRecords array specifies an offset from the left and bottom edges of the bounding rectangle, allowing successive lines of text to be arranged as a block or paragraph. The coordinate transform can be used to control the size and orientation of the text when it is displayed.</p>
<h1 class="datasheet">Examples</h1>
<p>Creating a simple string. The creation and layout of the glyphs to create the text is too onerous to perform from scratch. It is easier and more convenient to use existing font definitions either by parsing an existing Flash file or by converting a font definition from a specification such as TrueType in order to obtain the glyphs and layout information.</p>
<p>This examples assumes a font definition that contains glyphs for the following set of characters ' ', 'a', 'b', 'c' .... 'x', 'y', 'z'. The font used fixed size for the spacing between glyphs .e.g. Courier.</p>
<pre>
int fontSize = 240;
int leading = 80;
ArrayList characters = new ArrayList();
ArrayList lines = new ArrayList();
characters.add(new FSCharacter(1, 120)); // 'a'
characters.add(new FSCharacter(0, 120)); // ' '
characters.add(new FSCharacter(19, 120)); // 's'
characters.add(new FSCharacter(10, 120)); // 't'
characters.add(new FSCharacter(18, 120)); // 'r'
characters.add(new FSCharacter(9, 120)); // 'i'
characters.add(new FSCharacter(14, 120)); // 'n'
characters.add(new FSCharacter(6, 120)); // 'g'
// Create the string setting the height to be 12-point (240 twips) and displaying the characters in black.
// the text is not indented or offset.
lines.add(new FSText(font.getIdentifier, FSColor.black()), 0, 0, fontSize, characters);
// Calculate the bounding rectangle that encloses the text.
// The width of the text by summing all the advances.
int width = 0;
int height = fontSize + leading;
for (Iterator i = characters.iterator(); i.hasNext();)
width += ((FSCharacter)i.next()).getAdvance();
FSBounds bounds = new FSBounds(0, 0, width, height);
// Define the text with no coordinate transformation (use the default unity transform which leaves
// the text unchanged.
FSDefineText text = new FSDefineText(movie.newIdentifier(), bounds, new FSCoordTransform(), lines);
</pre>
<h1 class="datasheet">History</h1>
<p>The FSDefineText class represents the DefineText tag from the Macromedia Flash (SWF) File Format Specification. It was introduced in Flash 1.</p>
*/
public class FSDefineText extends FSDefineObject
{
private FSBounds bounds = null;
private FSCoordTransform transform = null;
private ArrayList objects = null;
/**
* Construct an FSDefineText object, initalizing it with values decoded from
* an encoded object.
*
* @param coder an FSCoder containing the binary data.
*/
public FSDefineText(FSCoder coder)
{
super(FSMovieObject.DefineText, 0);
decode(coder);
}
/** Constructs an FSDefineText object with the specified bounding rectangle, coordinate transform and text records.
@param anIdentifier the unique identifier for this object. Must be in the range 1..65535
@param aBounds the bounding rectangle enclosing the text. Must not be null.
@param aTransform an FSCoordTransform to change the size and orientation of
the text. Must not be null.
@param array an array of FSText objects that define the text to be displayed.
Must not be null.
*/
public FSDefineText(int anIdentifier, FSBounds aBounds, FSCoordTransform aTransform, ArrayList array)
{
super(FSMovieObject.DefineText, anIdentifier);
setBounds(aBounds);
setTransform(aTransform);
setObjects(array);
}
/**
* Constructs an FSDefineText object by copying values from an existing
* object.
*
* @param obj an FSDefineText object.
*/
public FSDefineText(FSDefineText obj)
{
super(obj);
bounds = new FSBounds(obj.bounds);
transform = new FSCoordTransform(obj.transform);
objects = new ArrayList(obj.objects.size());
for (Iterator i = obj.objects.iterator(); i.hasNext();)
objects.add(((FSText)i.next()).clone());
}
/** Add a FSText object to the array of text records.
@param anObject an FSText object.
*/
public void add(FSText anObject) { objects.add(anObject); }
/** Gets the bounding rectangle that completely encloses the text to be displayed.
@return the bounding rectangle of the text.
*/
public FSBounds getBounds() { return bounds; }
/** Gets the coordinate transform that controls how the text is displayed.
@return the coordinate transform.
*/
public FSCoordTransform getTransform() { return transform; }
/** Gets the array of text records that define the text to be displayed as its attributes.
@return the array of text records (FSTextStyle and FSText objects).
*/
public ArrayList getObjects()
{
return objects;
}
/** Sets the bounding rectangle that encloses the text being displayed.
@param aBounds the bounding rectangle enclosing the text.
*/
public void setBounds(FSBounds aBounds)
{
bounds = aBounds;
}
/** Sets the coordinate transform that changes the orientation and size of the text displayed.
@param aTransform an FSCoordTransform to change the size and orientation of the text.
*/
public void setTransform(FSCoordTransform aTransform)
{
transform = aTransform;
}
/** Sets the array of text records that define the text to be displayed.
@param anArray an array of FSText objects that define the text to be displayed.
*/
public void setObjects(ArrayList anArray)
{
objects = anArray;
}
public Object clone()
{
FSDefineText anObject = (FSDefineText)super.clone();
anObject.bounds = (bounds != null) ? (FSBounds)bounds.clone() : null;
anObject.transform = (transform != null) ? (FSCoordTransform)transform.clone() : null;
anObject.objects = new ArrayList(objects.size());
for (Iterator i = objects.iterator(); i.hasNext();)
anObject.objects.add(((FSText)i.next()).clone());
return anObject;
}
public boolean equals(Object anObject)
{
boolean result = false;
if (super.equals(anObject))
{
FSDefineText typedObject = (FSDefineText)anObject;
if (bounds != null)
result = bounds.equals(typedObject.bounds);
else
result = bounds == typedObject.bounds;
if (transform != null)
result = result && transform.equals(typedObject.transform);
else
result = result && transform == typedObject.transform;
if (objects != null)
result = result && objects.equals(typedObject.objects);
else
result = result && objects == typedObject.objects;
}
return result;
}
public void appendDescription(StringBuffer buffer, int depth)
{
buffer.append(name());
if (depth > 0)
{
buffer.append(": { ");
Transform.append(buffer, "identifier", identifier);
Transform.append(buffer, "bounds", bounds, depth);
Transform.append(buffer, "transform", transform, depth);
Transform.append(buffer, "objects", objects, depth);
buffer.append("}");
}
}
public int length(FSCoder coder)
{
super.length(coder);
coder.context[FSCoder.NumberOfGlyphBits] = glyphBits();
coder.context[FSCoder.NumberOfAdvanceBits] = advanceBits();
length += bounds.length(coder);
length += transform.length(coder);
length += 2;
for (Iterator recordIterator = objects.iterator(); recordIterator.hasNext();)
length += ((FSTransformObject)recordIterator.next()).length(coder);
length += 1;
coder.context[FSCoder.NumberOfGlyphBits] = 0;
coder.context[FSCoder.NumberOfAdvanceBits] = 0;
return length;
}
public void encode(FSCoder coder)
{
super.encode(coder);
coder.context[FSCoder.NumberOfGlyphBits] = glyphBits();
coder.context[FSCoder.NumberOfAdvanceBits] = advanceBits();
bounds.encode(coder);
transform.encode(coder);
coder.writeWord(coder.context[FSCoder.NumberOfGlyphBits], 1);
coder.writeWord(coder.context[FSCoder.NumberOfAdvanceBits], 1);
for (Iterator recordIterator = objects.iterator(); recordIterator.hasNext();)
((FSTransformObject)recordIterator.next()).encode(coder);
coder.writeWord(0, 1);
coder.context[FSCoder.NumberOfGlyphBits] = 0;
coder.context[FSCoder.NumberOfAdvanceBits] = 0;
coder.endObject(name());
}
public void decode(FSCoder coder)
{
int glyphBits = 0;
int advanceBits = 0;
super.decode(coder);
// Mark the start of the tag body
/* location */ coder.getPointer();
bounds = new FSBounds(coder);
// This code is used to get round a bug in Flash - sometimes 16,
// 8-bit zeroes are written out before the transform. The root
// cause in Flash is unknown but seems to be related to the
// bounds not being set - all values are zero.
boolean bytesAreZero = true;
int start = coder.getPointer();
for (int i=0; i<16; i++)
{
if (coder.scanWord(1, false) != 0)
bytesAreZero = false;
coder.adjustPointer(8);
}
coder.setPointer(start);
if (bytesAreZero)
{
for (int i=0; i<16; i++)
{
coder.scanWord(1, false);
coder.adjustPointer(8);
}
}
// Back to reading the rest of the tag
transform = new FSCoordTransform(coder);
glyphBits = coder.readWord(1, false);
advanceBits = coder.readWord(1, false);
coder.context[FSCoder.NumberOfGlyphBits] = glyphBits;
coder.context[FSCoder.NumberOfAdvanceBits] = advanceBits;
/*
* Set the instance variable directly since Flash files can contain
* FSDefineText objects with no text records - this appears to be a
* bug in the Flash file.
*/
objects = new ArrayList();
while (coder.scanBits(8, false) != 0)
objects.add(new FSText(coder));
coder.readBits(8, false);
coder.context[FSCoder.NumberOfGlyphBits] = 0;
coder.context[FSCoder.NumberOfAdvanceBits] = 0;
coder.endObject(name());
}
private int glyphBits()
{
int numberOfBits = 0;
for (Iterator recordIterator = objects.iterator(); recordIterator.hasNext();)
numberOfBits = Math.max(numberOfBits, ((FSText)recordIterator.next()).glyphBits());
return numberOfBits;
}
private int advanceBits()
{
int numberOfBits = 1;
for (Iterator recordIterator = objects.iterator(); recordIterator.hasNext();)
numberOfBits = Math.max(numberOfBits, ((FSText)recordIterator.next()).advanceBits());
return numberOfBits;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -