Introduction to Feathers text editors
The Flash runtimes provide more than one way to edit text, and there are multiple different approaches to rendering text on the GPU. None of these approaches are ultimately better than the others. To allow you to choose the method that works best in your app, Feathers provides APIs that allow you to choose the appropriate text editor for the TextInput
component based on your project's requirements.
Different text editors may be more appropriate for some situations than others. You should keep a number of factors in mind when choosing a text editor, including (but not necessarily limited to) the following:
whether the app is running on mobile or desktop
whether you need to use embedded fonts or not
the language of the text that needs to be displayed
These factors may impact things like performance and memory usage, depending on which text editor that you choose. Additionally, some text editors are better suited to mobile or desktop, and they may not work well on other platforms. What works for one app may be very inappropriate for another.
Feathers provides four different text editors. We'll learn the capabilities of each, along with their advantages and disadvantages. These text editors are listed below:
StageTextTextEditor
usesflash.text.StageText
to natively support entering text on all platforms, but especially on mobile. When theTextInput
has focus, theStageText
is displayed above Starling. Without focus, theTextField
is drawn toBitmapData
and uploaded as a texture to the GPU.TextFieldTextEditor
usesflash.text.TextField
to natively support entering text on all platforms. When theTextInput
has focus, it is added to the classic display list above Starling. Without focus, theTextField
is drawn toBitmapData
and uploaded as a texture to the GPU.TextBlockTextEditor
usesflash.text.engine.TextBlock
to render text in software and the result is drawn toBitmapData
and uploaded as a texture to the GPU. This text editor is not compatible with mobile apps.BitmapFontTextEditor
uses bitmap fonts to display characters as separate textured quads. This text editor is not compatible with mobile apps.
We'll look at the capabilities of each text editor in more detail a bit later, and we'll even consider options for creating custom text editors.
The default text editor factory
In many cases, most of the TextInput
components in your app will use the same type of text editor. To keep from repeating yourself by passing the same factory (a function that creates the text editor) to each TextInput
separately, you can specify a global default text editor factory to tell all TextInput
components in your app how to create a new text editor. Then, if some of your TextInput
components need a different text editor, you can pass them a separate factory that will override the default one.
If you don't replace it, the default text editor factory returns a StageTextTextEditor
. However, when using a theme, you should check which text editor is selected as the default. Themes may be targeted at desktop, where there are better alternatives to StageText
, or they may have special font requirements that require a different text editor. It is completely up to the theme which text editor it wants to use by default with TextInput
.
When an individual component doesn't have a custom text editor factory specified, it calls the function FeathersControl.defaultTextEditorFactory()
. This is a static variable that references a Function
, and it can be changed to a different function, as needed. The default implementation of this function looks like this:
function():ITextEditor
{
return new StageTextTextEditor();
}
If you would prefer to use a different text editor as the default in your app, you can easily change the variable to point to a different function. For instance, you might want to add this code to your application to use the TextFieldTextEditor
instead:
FeathersControl.defaultTextEditorFactory = function():ITextEditor
{
return new TextFieldTextEditor();
};
Using a different text editor on an individual TextInput
You can tell a specific TextInput
not to use the default text editor. For instance, you can pass in a custom textEditorFactory
that will be used to create the input's text editor:
input.textEditorFactory = function():ITextEditor
{
return new TextFieldTextEditor();
}
You can even apply font styles and other properties in the factory before returning the text editor:
input.textEditorFactory = function():ITextEditor
{
var editor:TextFieldTextEditor = new TextFieldTextEditor();
editor.textFormat = new TextFormat( "Source Sans Pro", 16, 0xffffff );
editor.embedFonts = true;
return editor;
}
Be careful, if you're using a theme. The theme applies its styles after this function returns. That means that the theme may end up replacing any properties that you set in the factory. See Extending Feathers Themes for details about how to customize an existing theme's styles.
StageTextTextEditor
The StageTextTextEditor
implementation uses flash.text.StageText
. StageText
is optimized to use the native text input controls on mobile platforms. StageText
supports native copy/paste, auto-correction, auto-completion, text selection, and other advanced text input capabilities. When the TextInput
has focus, the StageText
instance is displayed on the classic display list above other Starling content. When focus is lost, the StageText
is drawn to BitmapData
and converted to a Starling Texture
to display as a snapshot within the Starling display list. This allows the TextInput
to be added to a scrolling container, and it will be properly clipped without the StageText
appearing above the other Starling content.
StageTextTextEditor
may use device fonts (the fonts installed on the user's operating system), but embedded fonts are not supported. If you need embedded fonts on mobile, you should use TextFieldTextEditor
instead.
StageTextTextEditor
may be used in desktop apps, but other text editors are recommended because they provide more features.
Features of StageText
vary both in availability and behavior per platform. On some platforms, some properties may be completely ignored. Check the StageText
API documentation for full details.
Using StageTextTextEditor
To edit text with flash.text.StageText
, use the TextFieldTextEditor
class.
input.textEditorFactory = function():ITextEditor
{
var editor:StageTextTextEditor = new StageTextTextEditor();
return editor;
};
Font styles may be customized using properties like fontFamily
, fontSize
, and color
. Many of the property names defined by StageText
are duplicated on StageTextTextEditor
:
editor.fontFamily = "Arial";
editor.fontSize = 16;
editor.color = 0xcccccc;
StageTextTextEditor
provides a number of other advanced properties that may be customized, but aren't included in this quick introduction. For complete details about available properties, please take a look at the StageTextTextEditor
API reference.
TextFieldTextEditor
The TextFieldTextEditor
implementation uses flash.text.TextField
with its type
property set to TextFieldType.INPUT
. When the TextInput
has focus, the TextField
instance is displayed on the classic display list above other Starling content. When focus is lost, the TextField
is drawn to BitmapData
and converted to a Starling Texture
to display as a snapshot within the Starling display list. This allows the TextInput
to be added to a scrolling container, and it will be properly clipped without the TextField
appearing above the other Starling content.
TextFieldTextEditor
may use device fonts (the fonts installed on the user's operating system), and it supports embedded fonts in TTF or OTF formats. For some languages with many characters, device fonts may be the only option if the number of characters would require too much memory to embedding a custom font.
TextFieldTextEditor
provides a slightly less native experience on mobile than StageTextTextEditor
. More advanced capabilities like copy and paste may not be available on all platforms when using TextFieldTextEditor
. TextFieldTextEditor
is best suited for situations where StageTextTextEditor
lacks capabilities that your app requires.
TextField
offers limited support for some languages, including right-to-left and bidirectional languages, and StageText
or Flash Text Engine is recommended for these languages.
Using TextFieldTextEditor
To edit text with flash.text.TextField
, use the TextFieldTextEditor
class.
input.textEditorFactory = function():ITextEditor
{
var editor:TextFieldTextEditor = new TextFieldTextEditor();
return editor;
};
Font styles may be customized using the native flash.text.TextFormat
class. Many of the property names defined by TextField
are duplicated on TextFieldTextEditor
, including (but not limited to) textFormat
and embedFonts
:
editor.textFormat = new TextFormat( "Source Sans Pro", 16, 0xcccccc );
editor.embedFonts = true;
TextFieldTextEditor
provides a number of other advanced properties that may be customized, but aren't included in this quick introduction. For complete details about available properties, please take a look at the TextFieldTextEditor
API reference.
TextBlockTextEditor
The TextBlockTextEditor
implementation uses flash.text.engine.TextBlock
. This text editor is fully integrated with the Starling display list. The TextBlock
is drawn to BitmapData
and converted to a Starling Texture
to display as a snapshot within the Starling display list. When the TextInput
has focus, nothing is added to the classic display list above Starling.
TextFieldBlockEditor
may use device fonts (the fonts installed on the user's operating system), and it supports embedded fonts in TTF or OTF formats. For some languages with many characters, device fonts may be the only option if the number of characters would require too much memory to embedding a custom font.
Using TextBlockTextEditor
To edit text with flash.text.engine.TextBlock
, use the TextBlockTextEditor
class.
input.textEditorFactory = function():ITextEditor
{
var editor:TextBlockTextEditor = new TextBlockTextEditor();
return editor;
};
Many font styles may be customized using the native flash.text.engine.ElementFormat
class. Pass an instance of ElementFormat
to the elementFormat
property:
var fontDescription:FontDescription = new FontDescription( "Source Sans Pro", FontWeight.NORMAL, FontPosture.NORMAL, FontLookup.EMBEDDED_CFF, RenderingMode.CFF, CFFHinting.NONE );
editor.elementFormat = new ElementFormat( fontDescription, 16, 0xcccccc );
The first parameter to the ElementFormat
constructor is a FontDescription
object. This class is provided by Flash Text Engine to handle font lookup, including name, weight, posture, whether the font is embedded or not, and how the font is rendered.
TextBlockTextEditor
provides a number of other advanced properties that may be customized, but aren't included in this quick introduction. For complete details about available properties, please take a look at the TextBlockTextEditor
API reference.
BitmapFontTextEditor
The BitmapFontTextEditor
implementation uses bitmap fonts. This text editor is fully integrated with the Starling display list. When the TextInput
has focus, nothing is added to the classic display list above Starling.
Bitmap fonts separate each character into sub-textures inside an atlas. These sub-textures are displayed as images placed next to each other to form words and paragraphs. If the text has a particularly stylized appearance, such as gradients and outlines, bitmap fonts provide the best performance because the styles can be calculated at design time rather than runtime.
While the English language has only 26 letters in the alphabet (in addition to any punctuation and other supporting characters that you might need), some languages require many hundreds of characters. A texture that contains all of those characters may be impossible to use with bitmap fonts because it hits texture memory limits imposed by the Flash runtime or the GPU. In these situations, you may have no choice but to use device fonts.
Bitmap fonts may be scaled, but because they use bitmaps, only scaling down is recommended. Even then, you may lose out on text hinting that would make vector fonts more readable at smaller sizes. It's common to include separate font sizes as separate textures for bitmap fonts to achieve the best looking results, and that can require a lot of memory.
BitmapFontTextEditor
does not support multiple font styles. A BitmapFontTextEditor
must use a single bitmap font to render its entire text.
Using BitmapFontTextEditor
To edit text using bitmap fonts, use the BitmapFontTextEditor
class.
input.textEditorFactory = function():ITextEditor
{
var editor:BitmapFontTextEditor = new BitmapFontTextEditor();
return editor;
};
Font styles may be customized by passing a BitmapFontTextFormat
instance to the textFormat
property. The first parameter of the constructor accepts either name of a font registered with TextField.registerBitmapFont()
or any BitmapFont
instance, regardless of whether it has been registered or not. Additionally, you may specify the font size (or set it to NaN
to use the original font size) and the color of the text. The text color is applied using Starling's tinting capabilities.
editor.textFormat = new BitmapFontTextFormat( "FontName", 14, 0xcccccc );
BitmapFontTextEditor
provides a number of other advanced properties that may be customized, but aren't included in this quick introduction. For complete details about available properties, please take a look at the BitmapFontTextEditor
API reference.
Custom Text Editors
If you'd like to use a different approach to rendering text, you may implement the ITextEditor
interface. This interface provides a simple API for communicating with the TextInput
component.
Unless your custom editor is capable of drawing directly to the GPU, chances are that you will need to implement some form of texture snapshots, similar to the StageTextTextEditor
or TextFieldTextEditor
. Since Feathers is open source, feel free to look through the source code for one of these text editor classes for inspiration.
Please note that unless you find a way to take advantage of StageText
or TextField
in your custom text editor, you will not be able to access the native soft keyboard on mobile. Without the soft keyboard, the text editor may be limited to desktop, unless you can provide an alternate keyboard.
Multiline Text Editors
The TextArea
component introduced in Feathers 1.1 allows you edit multiline text in desktop apps. It supports text editors with an extended the ITextEditorViewPort
interface. Currently, the only supported text editor for TextArea
is TextFieldTextEditorViewPort
. Similar to TextFieldTextEditor
, it uses a flash.display.TextField
.
On mobile, you generally should not use TextArea
. It is designed specifically for desktop, and it may not behave as expected on mobile. Instead, use the TextInput
component with a StageTextTextEditor
. Set its multiline
property to true
. The underlying StageText
will provide its own native scroll bar.