awayjs-display
Version:
AwayJS displaylist classes
1,230 lines (1,118 loc) • 64.7 kB
text/typescript
import {AttributesBuffer} from "awayjs-core/lib/attributes/AttributesBuffer";
import {AttributesView} from "awayjs-core/lib/attributes/AttributesView";
import {Float2Attributes} from "awayjs-core/lib/attributes/Float2Attributes";
import {Byte4Attributes} from "awayjs-core/lib/attributes/Byte4Attributes";
import {Matrix3D} from "awayjs-core/lib/geom/Matrix3D";
import {Matrix} from "awayjs-core/lib/geom/Matrix";
import {ColorTransform} from "awayjs-core/lib/geom/ColorTransform";
import {Rectangle} from "awayjs-core/lib/geom/Rectangle";
import {Vector3D} from "awayjs-core/lib/geom/Vector3D";
import {Sampler2D} from "awayjs-core/lib/image/Sampler2D";
import {HierarchicalProperties} from "../base/HierarchicalProperties";
import {Style} from "../base/Style";
import {DisplayObject} from "../display/DisplayObject";
import {AntiAliasType} from "../text/AntiAliasType";
import {GridFitType} from "../text/GridFitType";
import {TextFieldAutoSize} from "../text/TextFieldAutoSize";
import {TextFieldType} from "../text/TextFieldType";
import {TextFormat} from "../text/TextFormat";
import {TextInteractionMode} from "../text/TextInteractionMode";
import {TextLineMetrics} from "../text/TextLineMetrics";
import {Sprite} from "../display/Sprite";
import {Graphics} from "../graphics/Graphics";
import {Graphic} from "../graphics/Graphic";
import {ElementsBase} from "../graphics/ElementsBase";
import {TriangleElements} from "../graphics/TriangleElements";
import {TesselatedFontChar} from "../text/TesselatedFontChar";
import {TextFormatAlign} from "../text/TextFormatAlign";
import {DisplayObjectContainer} from "../display/DisplayObjectContainer";
import {BitmapFontTable} from "../text/BitmapFontTable";
import {Single2DTexture} from "../textures/Single2DTexture";
import {IFontTable} from "../text/IFontTable";
import {TesselatedFontTable} from "../text/TesselatedFontTable";
import {BasicMaterial} from "../materials/BasicMaterial";
import {MaterialBase} from "../materials/MaterialBase";
/**
* The TextFieldMultiRender class is used to create display objects for text display and
* input. <ph outputclass="flexonly">You can use the TextFieldMultiRender class to
* perform low-level text rendering. However, in Flex, you typically use the
* Label, Text, TextArea, and TextInput controls to process text. <ph
* outputclass="flashonly">You can give a text field an instance name in the
* Property inspector and use the methods and properties of the TextFieldMultiRender
* class to manipulate it with ActionScript. TextFieldMultiRender instance names are
* displayed in the Movie Explorer and in the Insert Target Path dialog box in
* the Actions panel.
*
* <p>To create a text field dynamically, use the <code>TextFieldMultiRender()</code>
* constructor.</p>
*
* <p>The methods of the TextFieldMultiRender class let you set, select, and manipulate
* text in a dynamic or input text field that you create during authoring or
* at runtime. </p>
*
* <p>ActionScript provides several ways to format your text at runtime. The
* TextFormat class lets you set character and paragraph formatting for
* TextFieldMultiRender objects. You can apply Cascading Style Sheets(CSS) styles to
* text fields by using the <code>TextFieldMultiRender.styleSheet</code> property and the
* StyleSheet class. You can use CSS to style built-in HTML tags, define new
* formatting tags, or apply styles. You can assign HTML formatted text, which
* optionally uses CSS styles, directly to a text field. HTML text that you
* assign to a text field can contain embedded media(movie clips, SWF files,
* GIF files, PNG files, and JPEG files). The text wraps around the embedded
* media in the same way that a web browser wraps text around media embedded
* in an HTML document. </p>
*
* <p>Flash Player supports a subset of HTML tags that you can use to format
* text. See the list of supported HTML tags in the description of the
* <code>htmlText</code> property.</p>
*
* @event change Dispatched after a control value is
* modified, unlike the
* <code>textInput</code> event, which is
* dispatched before the value is modified.
* Unlike the W3C DOM Event Model version of
* the <code>change</code> event, which
* dispatches the event only after the
* control loses focus, the ActionScript 3.0
* version of the <code>change</code> event
* is dispatched any time the control
* changes. For example, if a user types text
* into a text field, a <code>change</code>
* event is dispatched after every keystroke.
* @event link Dispatched when a user clicks a hyperlink
* in an HTML-enabled text field, where the
* URL begins with "event:". The remainder of
* the URL after "event:" is placed in the
* text property of the LINK event.
*
* <p><b>Note:</b> The default behavior,
* adding the text to the text field, occurs
* only when Flash Player generates the
* event, which in this case happens when a
* user attempts to input text. You cannot
* put text into a text field by sending it
* <code>textInput</code> events.</p>
* @event scroll Dispatched by a TextFieldMultiRender object
* <i>after</i> the user scrolls.
* @event textInput Flash Player dispatches the
* <code>textInput</code> event when a user
* enters one or more characters of text.
* Various text input methods can generate
* this event, including standard keyboards,
* input method editors(IMEs), voice or
* speech recognition systems, and even the
* act of pasting plain text with no
* formatting or style information.
* @event textInteractionModeChange Flash Player dispatches the
* <code>textInteractionModeChange</code>
* event when a user changes the interaction
* mode of a text field. for example on
* Android, one can toggle from NORMAL mode
* to SELECTION mode using context menu
* options
*/
export class TextFieldMultiRender extends Sprite
{
private static _textFields:Array<TextFieldMultiRender> = new Array<TextFieldMultiRender>();
public static assetType:string = "[asset TextFieldMultiRender]";
private _explicitFormats:Array<TextFormat> = new Array<TextFormat>();
private _explicitFormatsRanges:Array<number> = new Array<number>();
private _line_indices:Array<number> = new Array<number>();
private _textGraphicsDirty:boolean;
private _bottomScrollV:number;
private _caretIndex:number;
private _length:number;
private _maxScrollH:number;
private _maxScrollV:number;
private _numLines:number;
private _selectionBeginIndex:number;
private _selectionEndIndex:number;
private _text:string = "";
private _textHeight:number;
private _textInteractionMode:TextInteractionMode;
private _textWidth:number;
private _charBoundaries:Rectangle;
private _charIndexAtPoint:number;
private _firstCharInParagraph:number;
private _imageReference:DisplayObject
private _lineIndexAtPoint:number;
private _lineIndexOfChar:number;
private _lineLength:number;
private _lineMetrics:TextLineMetrics;
private _lineOffset:number;
private _lineText:string;
private _paragraphLength:number;
private _textFormat:TextFormat;
private _textElements:TriangleElements;
private _textGraphic:Graphic;
/**
* When set to <code>true</code> and the text field is not in focus, Flash
* Player highlights the selection in the text field in gray. When set to
* <code>false</code> and the text field is not in focus, Flash Player does
* not highlight the selection in the text field.
*
* @default false
*/
public alwaysShowSelection:boolean;
/**
* The type of anti-aliasing used for this text field. Use
* <code>flash.text.AntiAliasType</code> constants for this property. You can
* control this setting only if the font is embedded(with the
* <code>embedFonts</code> property set to <code>true</code>). The default
* setting is <code>flash.text.AntiAliasType.NORMAL</code>.
*
* <p>To set values for this property, use the following string values:</p>
*/
public antiAliasType:AntiAliasType;
/**
* Controls automatic sizing and alignment of text fields. Acceptable values
* for the <code>TextFieldAutoSize</code> constants:
* <code>TextFieldAutoSize.NONE</code>(the default),
* <code>TextFieldAutoSize.LEFT</code>, <code>TextFieldAutoSize.RIGHT</code>,
* and <code>TextFieldAutoSize.CENTER</code>.
*
* <p>If <code>autoSize</code> is set to <code>TextFieldAutoSize.NONE</code>
* (the default) no resizing occurs.</p>
*
* <p>If <code>autoSize</code> is set to <code>TextFieldAutoSize.LEFT</code>,
* the text is treated as left-justified text, meaning that the left margin
* of the text field remains fixed and any resizing of a single line of the
* text field is on the right margin. If the text includes a line break(for
* example, <code>"\n"</code> or <code>"\r"</code>), the bottom is also
* resized to fit the next line of text. If <code>wordWrap</code> is also set
* to <code>true</code>, only the bottom of the text field is resized and the
* right side remains fixed.</p>
*
* <p>If <code>autoSize</code> is set to
* <code>TextFieldAutoSize.RIGHT</code>, the text is treated as
* right-justified text, meaning that the right margin of the text field
* remains fixed and any resizing of a single line of the text field is on
* the left margin. If the text includes a line break(for example,
* <code>"\n" or "\r")</code>, the bottom is also resized to fit the next
* line of text. If <code>wordWrap</code> is also set to <code>true</code>,
* only the bottom of the text field is resized and the left side remains
* fixed.</p>
*
* <p>If <code>autoSize</code> is set to
* <code>TextFieldAutoSize.CENTER</code>, the text is treated as
* center-justified text, meaning that any resizing of a single line of the
* text field is equally distributed to both the right and left margins. If
* the text includes a line break(for example, <code>"\n"</code> or
* <code>"\r"</code>), the bottom is also resized to fit the next line of
* text. If <code>wordWrap</code> is also set to <code>true</code>, only the
* bottom of the text field is resized and the left and right sides remain
* fixed.</p>
*
* @throws ArgumentError The <code>autoSize</code> specified is not a member
* of flash.text.TextFieldAutoSize.
*/
public autoSize:TextFieldAutoSize;
/**
*
* @returns {string}
*/
public get assetType():string
{
return TextFieldMultiRender.assetType;
}
private setFormatForRange(start:number, end:number, format:TextFormat)
{
var i:number=0;
var len:number=this._explicitFormats.length;
var is_added:boolean=false;
var new_formatslist:Array<TextFormat>=new Array<TextFormat>();
var new_formatsranges:Array<number>=new Array<number>();
var new_cnt=0;
for(i=0; i<len; i++){
if(!is_added){
if (this._explicitFormatsRanges[(i*2)]>start){
is_added=true;
new_formatslist[new_cnt]=format;
new_formatsranges[new_cnt*2]=start;
new_formatsranges[(new_cnt*2)+1]=end;
new_cnt++;
}
}
new_formatslist[new_cnt]=this._explicitFormats[i];
new_formatsranges[new_cnt*2]=this._explicitFormatsRanges[(i*2)];
new_formatsranges[(new_cnt*2)+1]=this._explicitFormatsRanges[(i*2)+1];
new_cnt++;
}
this._explicitFormats=new_formatslist;
this._explicitFormatsRanges=new_formatsranges;
}
private getFormatAtChar(char_pos:number):TextFormat
{
var i:number=0;
var len:number=this._explicitFormats.length;
var active_format:TextFormat=this.textFormat;
for(i=0; i<len; i++){
if((this._explicitFormatsRanges[(i*2)]<=char_pos)&&(this._explicitFormatsRanges[(i*2)+1]>=char_pos)){
active_format=this._explicitFormats[i];
}
}
return active_format;
}
/**
* Specifies whether the text field has a background fill. If
* <code>true</code>, the text field has a background fill. If
* <code>false</code>, the text field has no background fill. Use the
* <code>backgroundColor</code> property to set the background color of a
* text field.
*
* @default false
*/
public background:boolean;
/**
* The color of the text field background. The default value is
* <code>0xFFFFFF</code>(white). This property can be retrieved or set, even
* if there currently is no background, but the color is visible only if the
* text field has the <code>background</code> property set to
* <code>true</code>.
*/
public backgroundColor:number /*int*/;
/**
* Specifies whether the text field has a border. If <code>true</code>, the
* text field has a border. If <code>false</code>, the text field has no
* border. Use the <code>borderColor</code> property to set the border color.
*
* @default false
*/
public border:boolean;
/**
* The color of the text field border. The default value is
* <code>0x000000</code>(black). This property can be retrieved or set, even
* if there currently is no border, but the color is visible only if the text
* field has the <code>border</code> property set to <code>true</code>.
*/
public borderColor:number /*int*/;
/**
* An integer(1-based index) that indicates the bottommost line that is
* currently visible in the specified text field. Think of the text field as
* a window onto a block of text. The <code>scrollV</code> property is the
* 1-based index of the topmost visible line in the window.
*
* <p>All the text between the lines indicated by <code>scrollV</code> and
* <code>bottomScrollV</code> is currently visible in the text field.</p>
*/
public get bottomScrollV():number /*int*/
{
return this._bottomScrollV;
}
/**
* The index of the insertion point(caret) position. If no insertion point
* is displayed, the value is the position the insertion point would be if
* you restored focus to the field(typically where the insertion point last
* was, or 0 if the field has not had focus).
*
* <p>Selection span indexes are zero-based(for example, the first position
* is 0, the second position is 1, and so on).</p>
*/
public get caretIndex():number /*int*/
{
return this._caretIndex;
}
/**
* A Boolean value that specifies whether extra white space(spaces, line
* breaks, and so on) in a text field with HTML text is removed. The default
* value is <code>false</code>. The <code>condenseWhite</code> property only
* affects text set with the <code>htmlText</code> property, not the
* <code>text</code> property. If you set text with the <code>text</code>
* property, <code>condenseWhite</code> is ignored.
*
* <p>If <code>condenseWhite</code> is set to <code>true</code>, use standard
* HTML commands such as <code><BR></code> and <code><P></code> to place line
* breaks in the text field.</p>
*
* <p>Set the <code>condenseWhite</code> property before setting the
* <code>htmlText</code> property.</p>
*/
public condenseWhite:boolean;
/**
* Specifies the format applied to newly inserted text, such as text entered
* by a user or text inserted with the <code>replaceSelectedText()</code>
* method.
*
* <p><b>Note:</b> When selecting characters to be replaced with
* <code>setSelection()</code> and <code>replaceSelectedText()</code>, the
* <code>defaultTextFormat</code> will be applied only if the text has been
* selected up to and including the last character. Here is an example:</p>
* <pre xml:space="preserve"> public my_txt:TextFieldMultiRender new TextFieldMultiRender();
* my_txt.text = "Flash Macintosh version"; public my_fmt:TextFormat = new
* TextFormat(); my_fmt.color = 0xFF0000; my_txt.defaultTextFormat = my_fmt;
* my_txt.setSelection(6,15); // partial text selected - defaultTextFormat
* not applied my_txt.setSelection(6,23); // text selected to end -
* defaultTextFormat applied my_txt.replaceSelectedText("Windows version");
* </pre>
*
* <p>When you access the <code>defaultTextFormat</code> property, the
* returned TextFormat object has all of its properties defined. No property
* is <code>null</code>.</p>
*
* <p><b>Note:</b> You can't set this property if a style sheet is applied to
* the text field.</p>
*
* @throws Error This method cannot be used on a text field with a style
* sheet.
*/
public defaultTextFormat:TextFormat;
/**
* Specifies whether the text field is a password text field. If the value of
* this property is <code>true</code>, the text field is treated as a
* password text field and hides the input characters using asterisks instead
* of the actual characters. If <code>false</code>, the text field is not
* treated as a password text field. When password mode is enabled, the Cut
* and Copy commands and their corresponding keyboard shortcuts will not
* function. This security mechanism prevents an unscrupulous user from using
* the shortcuts to discover a password on an unattended computer.
*
* @default false
*/
public displayAsPassword:boolean;
/**
* Specifies whether to render by using embedded font outlines. If
* <code>false</code>, Flash Player renders the text field by using device
* fonts.
*
* <p>If you set the <code>embedFonts</code> property to <code>true</code>
* for a text field, you must specify a font for that text by using the
* <code>font</code> property of a TextFormat object applied to the text
* field. If the specified font is not embedded in the SWF file, the text is
* not displayed.</p>
*
* @default false
*/
public embedFonts:boolean;
/**
* The type of grid fitting used for this text field. This property applies
* only if the <code>flash.text.AntiAliasType</code> property of the text
* field is set to <code>flash.text.AntiAliasType.ADVANCED</code>.
*
* <p>The type of grid fitting used determines whether Flash Player forces
* strong horizontal and vertical lines to fit to a pixel or subpixel grid,
* or not at all.</p>
*
* <p>For the <code>flash.text.GridFitType</code> property, you can use the
* following string values:</p>
*
* @default pixel
*/
public gridFitType:GridFitType;
/**
* Contains the HTML representation of the text field contents.
*
* <p>Flash Player supports the following HTML tags:</p>
*
* <p>Flash Player and AIR also support explicit character codes, such as
* &(ASCII ampersand) and €(Unicode € symbol). </p>
*/
public htmlText:string;
/**
* The number of characters in a text field. A character such as tab
* (<code>\t</code>) counts as one character.
*/
public get length():number /*int*/
{
return this._length;
}
/**
* The maximum number of characters that the text field can contain, as
* entered by a user. A script can insert more text than
* <code>maxChars</code> allows; the <code>maxChars</code> property indicates
* only how much text a user can enter. If the value of this property is
* <code>0</code>, a user can enter an unlimited amount of text.
*
* @default 0
*/
public maxChars:number /*int*/;
/**
* The maximum value of <code>scrollH</code>.
*/
public maxScrollH():number /*int*/
{
return this._maxScrollH;
}
/**
* The maximum value of <code>scrollV</code>.
*/
public maxScrollV():number /*int*/
{
return this._maxScrollV;
}
/**
* A Boolean value that indicates whether Flash Player automatically scrolls
* multiline text fields when the user clicks a text field and rolls the
* mouse wheel. By default, this value is <code>true</code>. This property is
* useful if you want to prevent mouse wheel scrolling of text fields, or
* implement your own text field scrolling.
*/
public mouseWheelEnabled:boolean;
/**
* Indicates whether field is a multiline text field. If the value is
* <code>true</code>, the text field is multiline; if the value is
* <code>false</code>, the text field is a single-line text field. In a field
* of type <code>TextFieldType.INPUT</code>, the <code>multiline</code> value
* determines whether the <code>Enter</code> key creates a new line(a value
* of <code>false</code>, and the <code>Enter</code> key is ignored). If you
* paste text into a <code>TextFieldMultiRender</code> with a <code>multiline</code>
* value of <code>false</code>, newlines are stripped out of the text.
*
* @default false
*/
public multiline:boolean;
/**
* Defines the number of text lines in a multiline text field. If
* <code>wordWrap</code> property is set to <code>true</code>, the number of
* lines increases when text wraps.
*/
public get numLines():number /*int*/
{
return this._numLines;
}
/**
* Indicates the set of characters that a user can enter into the text field.
* If the value of the <code>restrict</code> property is <code>null</code>,
* you can enter any character. If the value of the <code>restrict</code>
* property is an empty string, you cannot enter any character. If the value
* of the <code>restrict</code> property is a string of characters, you can
* enter only characters in the string into the text field. The string is
* scanned from left to right. You can specify a range by using the hyphen
* (-) character. Only user interaction is restricted; a script can put any
* text into the text field. <ph outputclass="flashonly">This property does
* not synchronize with the Embed font options in the Property inspector.
*
* <p>If the string begins with a caret(^) character, all characters are
* initially accepted and succeeding characters in the string are excluded
* from the set of accepted characters. If the string does not begin with a
* caret(^) character, no characters are initially accepted and succeeding
* characters in the string are included in the set of accepted
* characters.</p>
*
* <p>The following example allows only uppercase characters, spaces, and
* numbers to be entered into a text field:</p>
* <pre xml:space="preserve"> my_txt.restrict = "A-Z 0-9"; </pre>
*
* <p>The following example includes all characters, but excludes lowercase
* letters:</p>
* <pre xml:space="preserve"> my_txt.restrict = "^a-z"; </pre>
*
* <p>You can use a backslash to enter a ^ or - verbatim. The accepted
* backslash sequences are \-, \^ or \\. The backslash must be an actual
* character in the string, so when specified in ActionScript, a double
* backslash must be used. For example, the following code includes only the
* dash(-) and caret(^):</p>
* <pre xml:space="preserve"> my_txt.restrict = "\\-\\^"; </pre>
*
* <p>The ^ can be used anywhere in the string to toggle between including
* characters and excluding characters. The following code includes only
* uppercase letters, but excludes the uppercase letter Q:</p>
* <pre xml:space="preserve"> my_txt.restrict = "A-Z^Q"; </pre>
*
* <p>You can use the <code>\u</code> escape sequence to construct
* <code>restrict</code> strings. The following code includes only the
* characters from ASCII 32(space) to ASCII 126(tilde).</p>
* <pre xml:space="preserve"> my_txt.restrict = "\u0020-\u007E"; </pre>
*
* @default null
*/
public restrict:string;
/**
* The current horizontal scrolling position. If the <code>scrollH</code>
* property is 0, the text is not horizontally scrolled. This property value
* is an integer that represents the horizontal position in pixels.
*
* <p>The units of horizontal scrolling are pixels, whereas the units of
* vertical scrolling are lines. Horizontal scrolling is measured in pixels
* because most fonts you typically use are proportionally spaced; that is,
* the characters can have different widths. Flash Player performs vertical
* scrolling by line because users usually want to see a complete line of
* text rather than a partial line. Even if a line uses multiple fonts, the
* height of the line adjusts to fit the largest font in use.</p>
*
* <p><b>Note: </b>The <code>scrollH</code> property is zero-based, not
* 1-based like the <code>scrollV</code> vertical scrolling property.</p>
*/
public scrollH:number;
/**
* The vertical position of text in a text field. The <code>scrollV</code>
* property is useful for directing users to a specific paragraph in a long
* passage, or creating scrolling text fields.
*
* <p>The units of vertical scrolling are lines, whereas the units of
* horizontal scrolling are pixels. If the first line displayed is the first
* line in the text field, scrollV is set to 1(not 0). Horizontal scrolling
* is measured in pixels because most fonts are proportionally spaced; that
* is, the characters can have different widths. Flash performs vertical
* scrolling by line because users usually want to see a complete line of
* text rather than a partial line. Even if there are multiple fonts on a
* line, the height of the line adjusts to fit the largest font in use.</p>
*/
public scrollV:number;
/**
* A Boolean value that indicates whether the text field is selectable. The
* value <code>true</code> indicates that the text is selectable. The
* <code>selectable</code> property controls whether a text field is
* selectable, not whether a text field is editable. A dynamic text field can
* be selectable even if it is not editable. If a dynamic text field is not
* selectable, the user cannot select its text.
*
* <p>If <code>selectable</code> is set to <code>false</code>, the text in
* the text field does not respond to selection commands from the mouse or
* keyboard, and the text cannot be copied with the Copy command. If
* <code>selectable</code> is set to <code>true</code>, the text in the text
* field can be selected with the mouse or keyboard, and the text can be
* copied with the Copy command. You can select text this way even if the
* text field is a dynamic text field instead of an input text field. </p>
*
* @default true
*/
public selectable:boolean;
/**
* The zero-based character index value of the first character in the current
* selection. For example, the first character is 0, the second character is
* 1, and so on. If no text is selected, this property is the value of
* <code>caretIndex</code>.
*/
public get selectionBeginIndex():number /*int*/
{
return this._selectionBeginIndex;
}
/**
* The zero-based character index value of the last character in the current
* selection. For example, the first character is 0, the second character is
* 1, and so on. If no text is selected, this property is the value of
* <code>caretIndex</code>.
*/
public get selectionEndIndex():number /*int*/
{
return this._selectionEndIndex;
}
/**
* The sharpness of the glyph edges in this text field. This property applies
* only if the <code>flash.text.AntiAliasType</code> property of the text
* field is set to <code>flash.text.AntiAliasType.ADVANCED</code>. The range
* for <code>sharpness</code> is a number from -400 to 400. If you attempt to
* set <code>sharpness</code> to a value outside that range, Flash sets the
* property to the nearest value in the range(either -400 or 400).
*
* @default 0
*/
public sharpness:number;
/**
* Attaches a style sheet to the text field. For information on creating
* style sheets, see the StyleSheet class and the <i>ActionScript 3.0
* Developer's Guide</i>.
*
* <p>You can change the style sheet associated with a text field at any
* time. If you change the style sheet in use, the text field is redrawn with
* the new style sheet. You can set the style sheet to <code>null</code> or
* <code>undefined</code> to remove the style sheet. If the style sheet in
* use is removed, the text field is redrawn without a style sheet. </p>
*
* <p><b>Note:</b> If the style sheet is removed, the contents of both
* <code>TextFieldMultiRender.text</code> and <code> TextFieldMultiRender.htmlText</code> change to
* incorporate the formatting previously applied by the style sheet. To
* preserve the original <code>TextFieldMultiRender.htmlText</code> contents without the
* formatting, save the value in a variable before removing the style
* sheet.</p>
*/
public styleSheet:StyleSheet;
/**
* A string that is the current text in the text field. Lines are separated
* by the carriage return character(<code>'\r'</code>, ASCII 13). This
* property contains unformatted text in the text field, without HTML tags.
*
* <p>To get the text in HTML form, use the <code>htmlText</code>
* property.</p>
*/
public get text():string
{
return this._text;
}
public set text(value:string)
{
value = value.toString();
if (this._text == value)
return;
this._text = value;
this._textGraphicsDirty = true;
}
public get textFormat():TextFormat
{
return this._textFormat;
}
public set textFormat(value:TextFormat)
{
if (this._textFormat == value)
return;
this._textFormat = value;
this._textGraphicsDirty = true;
}
/**
* The graphics used by the sprite that provides it with its shape.
*/
public get graphics():Graphics
{
if (this._textGraphicsDirty)
this.reConstruct();
return this._graphics;
}
/**
* The color of the text in a text field, in hexadecimal format. The
* hexadecimal color system uses six digits to represent color values. Each
* digit has 16 possible values or characters. The characters range from 0-9
* and then A-F. For example, black is <code>0x000000</code>; white is
* <code>0xFFFFFF</code>.
*
* @default 0(0x000000)
*/
public _textColor:number /*int*/;
public get textColor()
{
return this._textColor;
}
public set textColor(value:number)
{
this._textColor = value;
if(!this.transform.colorTransform)
this.transform.colorTransform = new ColorTransform();
this.transform.colorTransform.color = value;
this.pInvalidateHierarchicalProperties(HierarchicalProperties.COLOR_TRANSFORM);
}
/**
* The interaction mode property, Default value is
* TextInteractionMode.NORMAL. On mobile platforms, the normal mode implies
* that the text can be scrolled but not selected. One can switch to the
* selectable mode through the in-built context menu on the text field. On
* Desktop, the normal mode implies that the text is in scrollable as well as
* selection mode.
*/
public get textInteractionMode():TextInteractionMode
{
return this._textInteractionMode;
}
/**
* The width of the text in pixels.
*/
public get textWidth():number
{
return this._textWidth;
}
public set textWidth(value:number)
{
this._textWidth = value;
}
/**
* The width of the text in pixels.
*/
public get textHeight():number
{
return this._textHeight;
}
public set textHeight(value:number)
{
this._textHeight = value;
}
/**
* The thickness of the glyph edges in this text field. This property applies
* only when <code>AntiAliasType</code> is set to
* <code>AntiAliasType.ADVANCED</code>.
*
* <p>The range for <code>thickness</code> is a number from -200 to 200. If
* you attempt to set <code>thickness</code> to a value outside that range,
* the property is set to the nearest value in the range(either -200 or
* 200).</p>
*
* @default 0
*/
public thickness:number;
/**
* The type of the text field. Either one of the following TextFieldType
* constants: <code>TextFieldType.DYNAMIC</code>, which specifies a dynamic
* text field, which a user cannot edit, or <code>TextFieldType.INPUT</code>,
* which specifies an input text field, which a user can edit.
*
* @default dynamic
* @throws ArgumentError The <code>type</code> specified is not a member of
* flash.text.TextFieldType.
*/
public type:TextFieldType;
/**
* Specifies whether to copy and paste the text formatting along with the
* text. When set to <code>true</code>, Flash Player copies and pastes
* formatting(such as alignment, bold, and italics) when you copy and paste
* between text fields. Both the origin and destination text fields for the
* copy and paste procedure must have <code>useRichTextClipboard</code> set
* to <code>true</code>. The default value is <code>false</code>.
*/
public useRichTextClipboard:boolean;
/**
* A Boolean value that indicates whether the text field has word wrap. If
* the value of <code>wordWrap</code> is <code>true</code>, the text field
* has word wrap; if the value is <code>false</code>, the text field does not
* have word wrap. The default value is <code>false</code>.
*/
public wordWrap:boolean;
/**
*
*/
public get isEntity()
{
return true; //TODO do this better
}
/**
* Creates a new TextFieldMultiRender instance. After you create the TextFieldMultiRender instance,
* call the <code>addChild()</code> or <code>addChildAt()</code> method of
* the parent DisplayObjectContainer object to add the TextFieldMultiRender instance to
* the display list.
*
* <p>The default size for a text field is 100 x 100 pixels.</p>
*/
constructor()
{
super();
this.type = TextFieldType.STATIC;
}
public clear()
{
super.clear();
if (this._textElements)
this._textElements.clear();
}
/**
* @inheritDoc
*/
public dispose()
{
this.disposeValues();
TextFieldMultiRender._textFields.push(this);
}
/**
* @inheritDoc
*/
public disposeValues()
{
super.disposeValues();
this._textFormat = null;
this._textGraphic = null;
if (this._textElements) {
this._textElements.dispose();
this._textElements = null;
}
}
/**
* Reconstructs the Graphics for this Text-field.
*/
public reConstruct(useCanvas2dhack:boolean=false) {
/* temporary disabled this...
this._textGraphicsDirty = false;
if(this._textFormat == null)
return;
if (this._textGraphic) {
this._textGraphic.dispose();
this._textGraphic = null;
this._textElements.clear();
this._textElements.dispose();
this._textElements = null;
}
if(this._text == "")
return;
var activeFormat:TextFormat=null;
var newFormat:TextFormat=null;
// split text into lines
// todo: split at all sorts of linebreaks (incl escaped linebreaks like we do right now)
var textlines:Array<string> = this.text.toString().split("\\n");
var maxlineWidth:number=this.textWidth - (4 + this._textFormat.leftMargin + this._textFormat.rightMargin + this._textFormat.indent);
var tl_char_codes:Array<Array<number>> = [];
var tl_char_widths:Array<Array<number>> = [];
var tl_char_formats:Array<Array<TextFormat>> = [];
var tl_width:Array<number> = [];
var tl_height:Array<number> = [];
var tl_cnt:number=0;
var w:number=0;
var c:number=0;
var tl:number=0;
var words:Array<string>;
var char_cnt:number=0;
var char_width:number=0;
var numVertices:number = 0;
this._line_indices=[];
// sort all chars into final lines
for (tl = 0; tl < textlines.length; tl++) {
console.log("textline nr: "+tl+" : "+textlines[tl]);
this._line_indices[tl_cnt]=char_cnt;
tl_char_codes[tl_cnt]=[];
tl_char_widths[tl_cnt]=[];
tl_char_formats[tl_cnt]=[];
tl_width[tl_cnt]=0;
tl_height[tl_cnt]=0;
tl_cnt++;
words = textlines[tl].split(" ");
for (w = 0; w < words.length; w++) {
var word_width:number=0;
var char_widths:Array<number>=[];
var char_formats:Array<TextFormat>=[];
var max_word_height:number=0;
for (c = 0; c < words[w].length; c++) {
newFormat=this.getFormatAtChar(char_cnt);
if(newFormat!=activeFormat){
activeFormat=newFormat;
activeFormat.font_table.initFontSize(activeFormat.size);
}
char_formats[c]=activeFormat;
var lineHeight:number=activeFormat.font_table.getLineHeight();
if(lineHeight>max_word_height)max_word_height=lineHeight;
char_width = activeFormat.font_table.getCharWidth(words[w].charCodeAt(c).toString());
numVertices += activeFormat.font_table.getCharVertCnt(words[w].charCodeAt(c).toString());
char_widths[c]=char_width;
word_width += char_width;
char_cnt++;
}
// word fits into line, just add it to the last line
if((tl_width[tl_cnt-1]+word_width) <= maxlineWidth){
if(tl_width[tl_cnt-1]!=0){
// there is already a word in this line. we want to add a space
tl_char_codes[tl_cnt-1].push(32);
//todo: get correct format
tl_char_widths[tl_cnt-1].push(activeFormat.font_table.getCharWidth("32"));
tl_char_formats[tl_cnt-1].push(activeFormat);
tl_width[tl_cnt-1]+=activeFormat.font_table.getCharWidth("32");
}
for (c = 0; c < words[w].length; c++) {
tl_char_codes[tl_cnt-1].push(words[w].charCodeAt(c));
tl_char_widths[tl_cnt-1].push(char_widths[c]);
tl_char_formats[tl_cnt-1].push(char_formats[c]);
tl_width[tl_cnt-1]+=word_width;
}
if(tl_height[tl_cnt-1]<max_word_height)tl_height[tl_cnt-1]=max_word_height;
}
// word does not fit into line, but it is first word added to line, so we add it anyway.
// todo: respect auto--wrap / multiline settings + optional include 3rd party tool for splitting into sylibils
else if(tl_width[tl_cnt-1]==0){
for (c = 0; c < words[w].length; c++) {
tl_char_codes[tl_cnt-1].push(words[w].charCodeAt(c));
tl_char_widths[tl_cnt-1].push(char_widths[c]);
tl_char_formats[tl_cnt-1].push(char_formats[c]);
tl_width[tl_cnt-1]+=word_width;
}
if(tl_height[tl_cnt-1]<max_word_height)tl_height[tl_cnt-1]=max_word_height;
}
// word does not fit, and there are already words on this line
else{
tl_char_codes[tl_cnt]=[];
tl_char_widths[tl_cnt]=[];
tl_char_formats[tl_cnt]=[];
tl_width[tl_cnt]=0;
tl_height[tl_cnt]=0;
tl_cnt++;
for (c = 0; c < words[w].length; c++) {
tl_char_codes[tl_cnt-1].push(words[w].charCodeAt(c));
tl_char_widths[tl_cnt-1].push(char_widths[c]);
tl_char_formats[tl_cnt-1].push(char_formats[c]);
tl_width[tl_cnt-1]+=word_width;
}
if(tl_height[tl_cnt-1]<max_word_height)tl_height[tl_cnt-1]=max_word_height;
}
}
}
var tl_startx:Array<Array<number> >=[];
// calculate the final positions of the chars
for (tl = 0; tl < tl_width.length; tl++) {
var x_offset:number= 2 + this._textFormat.leftMargin + this._textFormat.indent;
var justify_addion:number=0;
if(this._textFormat.align=="center"){
x_offset=2 + this._textFormat.leftMargin + this._textFormat.indent+(maxlineWidth-tl_width[tl])/2;
}
else if(this._textFormat.align=="justify"){
/*if(final_lines_justify_bool[i]){
justify_addion=((maxlineWidth)-final_lines_width[i])/final_lines_justify[i];
}*//*
}
else if(this._textFormat.align=="right"){
x_offset=(this._textWidth-tl_width[tl])-(2 + this._textFormat.rightMargin);
}
tl_startx[tl]=[];
this.textHeight=0;
for (var c = 0; c < tl_char_codes[tl].length; c++) {
this.textHeight+=tl_height[tl];
tl_startx[tl][c]=x_offset;
x_offset+=tl_char_widths[tl][c];
// if this is a whitespace, we add the justify additional spacer
if(tl_char_codes[tl][c]==32){
x_offset+=justify_addion;
}
}
}
//todo: i tried to use the isAsset() function instead of comparing the strings myself, but this didnt seem to work. need to find out why
if(this._textFormat.font_table.assetType==TesselatedFontTable.assetType){
var tess_fontTable:TesselatedFontTable = <TesselatedFontTable>this._textFormat.font_table;
var elements:TriangleElements;
var j:number = 0;
var k:number = 0;
var y_offset:number=0;
var char_scale:number=0;
var vertices:Float32Array = new Float32Array(numVertices*3);
for (tl = 0; tl < tl_width.length; tl++) {
console.log("textline nr: "+tl+" : "+tl_char_codes[tl]);
//console.log("tl_width = "+tl_width[tl]);
y_offset+=tl_height[tl];
for (var c = 0; c < tl_char_codes[tl].length; c++) {
var this_char:TesselatedFontChar = tess_fontTable.getChar(tl_char_codes[tl][c].toString());
char_scale = tess_fontTable._size_multiply;
if (this_char != null) {
elements = this_char.elements;
if (elements != null) {
var buffer:Float32Array = new Float32Array(elements.concatenatedBuffer.buffer);
for (var v:number = 0; v < elements.numVertices; v++) {
vertices[j++] = buffer[v*3] * char_scale + tl_startx[tl][c];
vertices[j++] = buffer[v*3 + 1] * char_scale + y_offset-tl_height[tl];
vertices[j++] = buffer[v*3 + 2];
}
}
}
}
}
var attributesView:AttributesView = new AttributesView(Float32Array, 3);
attributesView.set(vertices);
var vertexBuffer:AttributesBuffer = attributesView.attributesBuffer;
attributesView.dispose();
this._textElements = new TriangleElements(vertexBuffer);
this._textElements.setPositions(new Float2Attributes(vertexBuffer));
this._textElements.setCustomAttributes("curves", new Byte4Attributes(vertexBuffer, false));
this._textGraphic = this._graphics.addGraphic(this._textElements);
this.material = this._textFormat.material;
var sampler:Sampler2D = new Sampler2D();
this.style = new Style();
this.style.addSamplerAt(sampler, this.material.getTextureAt(0));
this.style.uvMatrix = new Matrix(0,0,0,0, this._textFormat.uv_values[0], this._textFormat.uv_values[1]);
this.material.animateUVs = true;
}
else if(this._textFormat.font_table.assetType==BitmapFontTable.assetType){
console.log("contruct bitmap text = "+this._text);
var bitmap_fontTable:BitmapFontTable = <BitmapFontTable>this._textFormat.font_table;
if(!useCanvas2dhack){
var vertices:Float32Array = new Float32Array(numVertices*7);
var vert_cnt:number=0;
var y_offset:number=0;//2+(tess_fontTable.ascent-tess_fontTable.get_font_em_size())*char_scale;
for (tl = 0; tl < tl_width.length; tl++) {
console.log("textline nr: "+tl+" : "+tl_char_codes[tl]);
//console.log("tl_width = "+tl_width[tl]);
y_offset+=tl_height[tl];
for (var c = 0; c < tl_char_codes[tl].length; c++) {
//console.log("tl_char_codes[tl] = "+tl_char_codes[tl][c]);
//console.log("tl_startx[tl] = "+tl_startx[tl][c]);
//console.log("y_offset = "+y_offset);
//console.log("vert_cnt = "+vert_cnt);
var char_data:Array<number>=bitmap_fontTable.getCharData(tl_char_codes[tl][c].toString());
console.log("char_data = "+char_data);
vertices[vert_cnt++] = tl_startx[tl][c]+char_data[4];
vertices[vert_cnt++] = y_offset-tl_height[tl]+char_data[5];
vertices[vert_cnt++] = char_data[0];
vertices[vert_cnt++] = char_data[1];
vertices[vert_cnt++] = tl_startx[tl][c] + tl_char_widths[tl][c]+char_data[4];
vertices[vert_cnt++] = y_offset -tl_height[tl]+char_data[5];
vertices[vert_cnt++] = char_data[0] + char_data[2];
vertices[vert_cnt++] = char_data[1];
vertices[vert_cnt++] = tl_startx[tl][c] + tl_char_widths[tl][c]+char_data[4];
vertices[vert_cnt++] = y_offset;
vertices[vert_cnt++] = char_data[0] + char_data[2];
vertices[vert_cnt++] = char_data[1] + char_data[3];
vertices[vert_cnt++] = tl_startx[tl][c] + tl_char_widths[tl][c]+char_data[4];
vertices[vert_cnt++] = y_offset;
vertices[vert_cnt++] = char_data[0] + char_data[2];
vertices[vert_cnt++] = char_data[1] + char_data[3];
vertices[vert_cnt++] = tl_startx[tl][c]+char_data[4];
vertices[vert_cnt++] = y_offset;
vertices[vert_cnt++] = char_data[0];
vertices[vert_cnt++] = char_data[1] + char_data[3];
vertices[vert_cnt++] = tl_startx[tl][c]+char_data[4];
vertices[vert_cnt++] = y_offset -tl_height[tl]+char_data[5];
vertices[vert_cnt++] = char_data[0];
vertices[vert_cnt++] = char_data[1];
}
}
var attributesView:AttributesView = new AttributesView(Float32Array, 4);
attributesView.set(vertices);
var vertexBuffer:AttributesBuffer = attributesView.attributesBuffer;
attributesView.dispose();
this._textElements = new TriangleElements(vertexBuffer);
this._textElements.setPositions(new Float2Attributes(vertexBuffer));
//this._textElements.setCustomAttributes("curves", new Byte4Attributes(vertexBuffer, false));
//this._textElements.setCustomAttributes("curves", new Float3Attributes(vertexBuffer));
this._textElements.setUVs(new Float2Attributes(vertexBuffer));
this._textGraphic = this._graphics.addGraphic(this._textElements);
var basic_mat:BasicMaterial = new BasicMaterial();
basic_mat.texture = new Single2DTexture(bitmap_fontTable.get_page());
basic_mat.bothSides = true;
//basic_mat.preserveAlpha = true;
basic_mat.alphaBlending = true;
this.material = <MaterialBase>basic_mat;
//var sampler:Sampler2D = new Sampler2D();
//this.style = new Style();
//this.style.addSamplerAt(sampler, new Single2DTexture(bitmap_fontTable.get_page()));
//this.style.uvMatrix = new Matrix(0,0,0,0, 0, 0);
//this.material.animateUVs = true;
}
else{
var canvas:HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("myCanvas");
if (canvas==null){
canvas = document.createElement("canvas");
canvas.id = "myCanvas";
document.body.appendChild(canvas);
}
var ctx = canvas.getContext("2d");
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
//var transform_mx:Matrix3D=this.transform.matrix3D;
//ctx.setTransform(transform_mx.a,transform_mx.b,transform_mx.c,transform_mx.d,transform_mx.tx,transform_mx.ty);
ctx.rect(0, 0, this.textWidth, this.textHeight);
ctx.fillStyle = "black";
ctx.fill();
//ctx.drawImage(bitmap_fontTable.get_page().getCanvas(), 50, 50, 200, 200, 0, 0, 100, 100);
var y_offset:number=0;//2+(tess_fontTable.ascent-tess_fontTable.get_font_em_size())*char_scale;
for (tl = 0; tl < tl_width.length; tl++) {
console.log("textline nr: "+tl+" : "+tl_char_codes[tl]);
//console.log("tl_width = "+tl_width[tl]);
y_offset+=tl_height[tl];
for (var c = 0; c < tl_char_codes[tl].length; c++) {
var char_data:Array<number>=bitmap_fontTable.getCharDataCanvas(tl_char_codes[tl][c].toString());
ctx.drawImage(
bitmap_fontTable.get_page().getCanvas(),
char_data[0], char_data[1],
char_data[2], char_data[3],
tl_startx[tl][c] + char_data[4], y_offset - tl_height[tl] + char_data[5],
tl_char_widths[tl][c], tl_height[tl] - char_data[5]
);
}
}
}
}
*/
}
/**
* Appends the string specified by the <code>newText</code> parameter to the
* end of the text of the text field. This method is more efficient than an
* addition assignment(<code>+=</code>) on a <code>text</code> property
* (such as <code>someTextField.text += moreText</code>), particularly for a
* text field that contains a significant amount of content.
*
* @param newText The string to append to the existing text.
*/
public appendText(newText:string) {
this._text+=newText;
}
/**
* *tells the Textfield that a paragraph is defined completly.
* e.g. the textfield will start a new line for future added text.
*/
public closeParagraph()
{
//TODO
}
/**
* Returns a rectangle that is the bounding box of the character.
*
* @param charIndex The zero-based index value for the character(for
* example, the first position is 0, the second position is
* 1, and so on).
* @return A rectangle wi