About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Jan

    27

    TextBlockTextEditor 使用 Flash Text Engine 显示文本,这是一个基于软加速的矢量字体渲染器,具有许多高级功能。可以使用设备字体或嵌入的字体(TTF 或 OTF 格式)。flash.text.engine.TextBlock 被 draw 到一个 BitmapData 对象,然后转换成 Starling 纹理图提交到 GPU 。这个文本编辑器与 Starling 是“深度整合”的,这意味着当文本编辑器聚焦时,不会像 StageTextTextEditor 那样出现“叠加”效果。

    (有一个“快照”的概念:这个快照大概意思是基于软加速的矢量文本,即使没有出现在原生舞台的显示列表上,也一样可以被 draw,然后 BitmapData 会直接转成 Starling 所需要的纹理格式上传至 GPU 更新文本编辑器的纹理,这是深度整合的原理,我猜的,你猜我猜的对不对?

    优缺点:

    Flash Text Engine 可以使用设备字体显示文本,对某些具有很多字符轮廓的语言(如中文),当嵌入字体需要太多内存时,设备字体就可能成了唯一的选择。Flash Text Engine 可以很好的支持从右向左排版的文字或双向文字,而 flash.text.TextField 就有可以无法正常显示。

    由于 Adobe AIR 运行时的功能限制,此文本编辑器不能在移动设备上使用。当文本对象获取焦点时,Adobe AIR 没有提供 API 可以调用 iOS 的软键盘功能,此文本编辑器仅适用于桌面应用开发。

    更改基于矢量的文本对象比使用位图字体要慢,因为矢量内容需要被 draw 到一个 BitmapData 对象,然后提交到 GPU 才能成为 Starling 显示的纹理图。如果用户输入较长的文本内容,在性能比较低的设备上转换成为纹理图、并上传纹理到 GPU 的时间可能会成为性能瓶颈。

    因为每段矢量文本需要被绘制到 BitmapData 对象,每个独立的渲染器在 GPU 上都需要一份单独的纹理图。如果在同一个屏幕上有多个 TextBlockTextEditor 实例,过的状态改变或 Starling 的渲染 / 绘制请求,可能会影响性能。

    Flash Text Engine 有时可能会比 flash.text.TextField 渲染的慢一些,一般来说,这种性能差异是可以忽略的,并且 FTE 引擎提供的更高级功能通常比牺牲一点点性能更划算。

    高级字体样式:

    该部份备注资料直接参考《TextBlockTextRenderer 一些备注》(是一样的)。

    一个文本渲染器的父组件有多个状态,如何更改它的高级字体样式:

    该部份备注资料直接参考《TextBlockTextRenderer 一些备注》(是一样的)。

    使用嵌入字体:

    该部份备注资料直接参考《TextBlockTextRenderer 一些备注》(是一样的)。

    Jan

    27

    StageTextTextEditor  通过 flash.text.StageText 对象渲染文本,StageText 已经为 iOS 与 Android 移动设备进行了优化,可以使用移动设备的本机文本输入功能。StageText 支持本机原生的复制 / 粘贴,自动更正,自动完成,文本选择和其他高级文本输入功能。

    当 TextInput 组件获得焦点时,StageText 实例就会出现在 Starling 层上面,当失去焦点的时候,文本框就会被 draw 到一个 BitmapData 对象,然后转换成为 Starling 需要的纹理格式,再提交到 GPU。TextInput 允许被添加到滚动容器中,因为最终显示的只是一个 Starling 显示对象,所以是可以被剪裁的。

    优缺点:

    StageTextTextEditor 使用设备字体,对某些具有很多字符轮廓的语言(如中文),当嵌入字体需要太多内存时,设备字体就可能成了唯一的选择。没有正式支持嵌入字体的功能,如果要在移动设备上使用嵌入字体的功能需使用 TextFieldTextEditor 。

    StageTextTextEditor 可以用于桌面应用开发,但在桌面上建义使用其它文本编辑器,因为其它的文本编辑器可以提供更多的功能和版式需求。StageText  在每个平台上的可用的功能和行为并不相同,具体的参考 API 手册

    当文本编辑器获得焦点时,StageText 实例就会出现,因为在 Starling 层上面,所以既便当失去焦点时,TextInput 组件是在其它组件的下面,只要获得焦点,这个 StageText 实例就一定会在所有 Starling 内容的上面。一般来说,这种情况不会经常发生(除非开发者的布局设计本身有能是有问题的)。

    每段矢量文本都会被 draw 到 BitmapData 对象,然后转换成为 Starling 需要的纹理格式,再提交到 GPU。因此,当屏幕中有多个 StageTextTextEditor 实例时,经常性的更改文本内容,可能会导致性能问题。

    高级字体样式:

    通常,是对一个文本渲染器的父组件使用 starling.text.TextFormat 类设置文本样式,例如设置一个 TextInput 的文本样式:

    input.fontStyles = new TextFormat( "Helvetica"20, 0xcc0000 );

    但是 starling.text.TextFormat 并不能设置文本编辑器的所有字体样式。如果想要进行高级的字体样式设置,可以参考下面的资料。以 TextInput 组件为例,设置 textEditorFactory 属性: 

    var input:TextInput = new TextInput();
    input.textEditorFactory = function():ITextEditor
    {
        var textEditor:StageTextTextEditor = new StageTextTextEditor();
        //为避免与主题文件中默认设置的样式冲突,先删除 styleProvider 提供的样式
        //textEditorFactory 会先执行,然后再执行主题文件中的代码,styleProvider 设为null 后,可以避免被覆盖
        textEditor.styleProvider = null;
        //设置高级字体样式
        return textEditor;
    };

    文本编辑器的高级字体样式设置可以是 fontFamily、fontSize、color 等属性,如: 

    textEditor.fontFamily = "Arial";
    textEditor.fontSize = 16;
    textEditor.color = 0xcccccc;

    StageTextTextEditor 还有其它更多的属性可以设置,具体的参考 API 手册

    Jan

    27

    Adobe Flash运行时提供了多种方式来编辑文本,并且有多种不同的方法在 GPU 上渲染文本,但并没有一最佳的方式,所以允许开发者自行根据需要选择最适合的“文本编辑器”(text editors)。在选择不同的文本编辑器时应考虑以下几个因素:

    1、应用是运行在移动设备上或桌面设备上。
    2、是否需要嵌入字体。
    3、使用是什么样的语言。

     这些因素会涉及到性能与内存的使用量,具体取决于选择的文本编辑器。

    Feathers 提供了 4 种不同的文本编辑器

    1、StageTextTextEditor :它使用的是 flash.text.StageText 对象,StageText  使用的是本机支持的原生文本输入,所以适用于所有平台,特别是在移动设备上。当一个文本输入框获得焦点时,StageText  就会显示在 Starling 层的上面。当文本框失去焦点的时候,文本框就会被 draw 到一个 BitmapData 对象,然后提交到 GPU 成为 Starling 显示的纹理图。

    2、TextFieldTextEditor :它使用的是 flash.text.TextField 对象,TextField 原生舞台对象,适用于所有平台。当一个文本输入框获得焦点时,TextField 就会显示在 Starling 层的上面。当文本框失去焦点的时候,文本框就会被 draw 到一个 BitmapData 对象,然后提交到 GPU 成为 Starling 显示的纹理图。

    3、TextBlockTextEditor :它使用的是 FTE 文本引擎(Flash Text Engine)是软渲染的,然后将结果 draw 到一个 BitmapData 对象,然后提交到 GPU 成为 Starling 显示的纹理图。此文本编辑器与移动应用不兼容(只能用于桌面 APP 开发)。

    4、BitmapFontTextEditor :它使用的是位图字体,每个字符对应的是一个独立的矩形子纹理图,通过 Image 对象显示的。此文本编辑器与移动应用不兼容(只能用于桌面 APP 开发)。

    每个文本编辑器都有不同的功能,所以一定要仔细区分,选择一个最佳的文本编辑器应用到开发中。

    默认的文本编辑器:

    通常情况下,应用程序中的大多数文本输入组件将使用相同类型的文本编辑器。为避免重复的在每个组件中单独设置文本编辑器,可以先设置一个全局的文本编辑器告诉所有组件默认情况下使用某种文本编辑器。只有当遇到某个组件不需要默认的文本编辑器时,才给它传递入特殊的文本编辑器,覆盖默认的类型。

    如果未经手动修改过,默认情况下会使用 StageTextTextEditor 对象,StageTextTextEditor 在移动开发时比较合适(它也能在桌面开发应用时良好的运行)。当使用主题文件时(theme),应该检查默认的文本编辑器。主题文件中通常会嵌入一种自定义字体,可能用于为了保持风格一体化或风格特殊化。

    当一个组件没有单独设置文本编辑器的时候,它会调用 FeathersControl.defaultTextEditorFactory() 方法。FeathersControl.defaultTextEditorFactory 是一个静态变量,可以根据需要任意的更改为不同的函数,默认它就是这样子:

    function():ITextEditor
    {
        return new StageTextTextEditor();
    }

     根据需要,也可以更改为 TextFieldTextEditor 作为默认的文本编辑器:

    FeathersControl.defaultTextEditorFactory = function():ITextEditor
    {
        return new TextFieldTextEditor();
    };

    在单个组件上使用不同的文本编辑器:

    可以给特定的组件指定特殊的文本编辑器,不使用(覆盖)默认的文本编辑器,比如一个 TextInput 对象:

    input.textEditorFactory = function():ITextEditor
    {
        return new TextFieldTextEditor();
    }

    甚至可以在返回文本编辑器之前,对文本编辑器设置字体相关的高级选项:

    input.textEditorFactory = function():ITextEditor
    {
        var textEditor:TextFieldTextEditor = new TextFieldTextEditor();
        textEditor.antiAliasType = AntiAliasType.NORMAL;
        textEditor.gridFitType = GridFitType.SUBPIXEL;
        return textEditor;
    }

    如果正在使用主题文件进行开发,需要小心:当对单个组件设置 textEditorFactory 属性时,可能被主题文件中的样式覆盖,因为主题文件中样式的使用是在单个组件设置 textEditorFactory 之后。可以在设置 textEditorFactory 属性时,对单个组件的自定义的文本编辑器的 styleProvider 属性设置为 null,这样可以避免被主题文件中的代码覆盖。

    自定义文本编辑器:

    如果想不同的方法渲染文本,需要实现 ITextEditor 接口类。除非自定义的文本编辑器能直接在 GPU 上进行渲染,否则就需要像 StageTextTextEditor 或 TextFieldTextEditor 类一样需要“快照”,draw 到一个 BitmapData 对象后,再上传到 GPU。(因为Feathers是开源的,可以随时参考 StageTextTextEditor 或 TextFieldTextEditor 类的代码)。

    请注意:除非你在自定义时能找到一种比使用 StageText 或 TextField 更好的方法,否则你就会无法访问移动设备的本机软键盘。如果没有了软键盘,自定义的文本编辑器可能只适用于桌面应用(或者提供一个自定义的备用软键盘用于移动应用)。

    多行文本编辑器:

    在移动设备上,StageTextTextEditor 可以提供用于编辑多行的文本功能,只要将 multiline 属性设为 true 即可,底层被包装的 StageText 对象就会自动提供滚动功能。

    在进行桌面应用开发时,TextArea 可能被使用,必要时它也可以被用于移动开发,但只推荐将它使用在桌面应用开发时。

    TextArea 支持特殊的文本编辑器,需要实现 ITextEditorViewPort 接口。目前 Feathers 内置也提供了一个 TextFieldTextEditorViewPort 类,它是默认的 TextArea 类的文本编辑器,类似于 TextFieldTextEditor,它是通过 flash.text.TextField 来进行渲染的。

    Jan

    26

    如果那么多的内置布局类都无法满足你的需求,Feathers 容器也支持自定义布局。

    Introduction to custom Feathers layouts

    ILayoutDisplayObject and ILayoutData

    Creating virtualized custom Feathers layouts

    我认为在 Adobe 彻底抛弃 AS3 之前,我都不会用到它了……

    Jan

    26

    HorizontalSpinnerLayout 与 VerticalSpinnerLayout 布局使用方法基本一致,都是用于 SpinnerList 组件布局的,只是前者是水平横向布局的,后者是竖向垂直布局的。都提供了用于调整间距、边距、对齐的属性 API,支持虚拟化布局。

    Jan

    26

    Feathers3 ScrollText 一些备注

    • 0 Comments
    • Flash Platform

    ScrollText 的主要功能目的是为了显示大段的文字,当遇到大段大段的长文本时,TextBlockTextRenderer 与 TextFieldTextRenderer 将有可能需要太多的性能消耗与内存需求。BitmapFontTextRenderer 可能是一个不错的选择,但首先它要有足够多的字符对应的轮廓,一般来说英文不成问题,中文就会成问题; 另外更多的 BitmapFontTextRenderer 的缺点参考《BitmapFontTextRenderer 一些备注》。ScrollText 作为一种文本显示的备用方案,它在原生舞台上传统的显示列表中显示文本对象,ScrollText 的缺点概述参考《“文本渲染器” 一些概述备注》。

    var scrollText:ScrollText = new ScrollText();
    scrollText.text = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
    this.addChild( scrollText );

    创建了一个 ScrollText 对象并添加到了 Starling 显示列表上,但这只是一个假象,实际上创建了一个 flash.text.TextField 对象添加到了原生舞台上(只是它通过自动计算将坐标匹配到 Starling 对象)。

    如果我们设置这个对象的 width 属性,它的 height 值会自动增加。如果同时设置宽与高,却它的高度小于文本的高度,ScrollText 的文本内容就会自动允许滚动。

    因为它是一个基于传统的原生 TextField 对象的包装,所以它能支持一个 HTML 标签的子集。其它大量的 TextField 的属性也能用于 ScrollText 对象上。如antiAliasType、backgroundColor、borderColor、gridFitType、styleSheet、sharpness、thickness 等等。完整的属性列表参考 API 手册

    其它滚动条相关的资料,如滚动策略、滚动条显示模式、交互模式等与其它组件的滚动条资料基本一致。

    Jan

    26

    TextFieldTextRenderer 是 Feathers3 组件提供的内置文本渲染器(也被称为“文本呈现器”,text renderers)之一。先使用的是 flash.text.TextField 软渲染,然后将结果 draw 下来变成位图数据对象(BitmapData),再转换成 Starling 需要的纹理格式后提交到 GPU 使用,TextField 可以支持一个 HTML 标签的子集,但它的版式功能很有限。每个实例需要一份单独的纹理对象,因此,如果场景中有多个对象使用了这种文本渲染器,它不仅会增加原生 API 的 draw 次数,也同样会增加 Starling 的 draw 次数(文本生成的位图面积越大,性能与内存开销越大)。

    优缺点:

    传统原生的 TextField 对象可以使用设备字体,对于有许多字符的字体而言(如汉字),嵌入字体会使用大量的内存,使用设备字体可能是最佳选择。类似的,有些情况是嵌入矢量字体比嵌入位图字体能更少的占用资源,可以使用嵌入矢量字体。

    将矢量文字 draw 后提交到 GPU 转换成为 Starling 的纹理对象在性能上会慢于位图字体。但是,一旦成功的上传到 GPU 后,就可以变的流畅了。如果经常需要更改文本的内容,那么就需要重复的 draw 和提交,上传纹理的延迟时间可能会成为性能的瓶颈。

    每段矢量文本都会被 draw 到 BitmapData 对象,再转换成 Starling 需要的纹理格式后提交到 GPU 使用。因此,当屏幕中有多个 TextFieldTextRenderer 实例时,经常性的更改文本内容,可能会导致严重的性能问题。

    flash.text.TextField 有时候性能会好于 Flash Text Engine,但这种性能差异可以忽略的。

    flash.text.TextField 有一些已知的问题和限制:

    1、TextField 实际上是有延迟的(不是同步的,虽然 Adobe 官方的 API 手册上没有说明),当 TextField 对象的某些属性更改后,如果立即 draw 到一个 BitmapData 对象中,可能就会产生错误。如果一定要使用的话,作为一种解决方法就是延迟一帧再 draw(这种延迟一般不会产生问题,因为不仔细看是不会注意到的)

    2、有些语言是从右向左排版的文字或双向排版的文字,它提供的功能很有限,对这类语言只能推荐使用 Flash Text Engine。

    TextFieldTextRenderer 支持有限的 HTML 标签子集,利用这一点,可以用于使用多种字体样式呈现更丰富的文本。

    高级字体样式:

    通常,是对一个文本渲染器的父组件使用 starling.text.TextFormat 类设置文本样式,例如设置一个按钮的文本样式:

    button.fontStyles = new TextFormat( "Helvetica"20, 0xcc0000 );

    直接在按钮上设置了 fontStyles 属性,而不是在文本渲染器上设置。但是 starling.text.TextFormat 并不能设置文本渲染器的所有字体样式。如果想要进行高级的字体样式设置,可以参考下面的资料。以 Button 组件为例,设置 labelFactory 属性值:

    var button:Button = new Button();
    button.label = "Click Me";
    button.labelFactory = function():ITextRenderer
    {
        var textRenderer:TextBlockTextRenderer = new TextBlockTextRenderer();
        //为避免与主题文件中默认设置的样式冲突,先删除 styleProvider 提供的样式
        //labelFactory 会先执行,然后再执行主题文件中的代码,styleProvider 设为null 后,可以避免被覆盖
        textRenderer.styleProvider = null;

        //在这里设置高级字体样式
        //……

        return textRenderer;
    };

    高级字体样式可能是通过 flash.text.TextFormat  类设置文本渲染器的 elementFormat 属性提供的,如:

    textRenderer.textFormat = new TextFormat( "Source Sans Pro"16, 0xcccccc );

    TextFormat 对象允许设置字号、颜色、对齐方式等:

    var format:TextFormat = new TextFormat( "Helvetica" );
    format.size = 20;
    format.color = 0xc4c4c4;
    format.align = TextFormatAlign.CENTER;

    TextFieldTextRenderer 的 text 属性支持一个 HTML 标签的子集(isHTML 属性必须设为 true):

    textRenderer.text = "<span class='heading'>hello</span> world!";
    textRenderer.isHTML = true;

    TextFieldTextRenderer 其它更多高级的功能参看 API 手册

    一个文本渲染器的父组件有多个状态,如何更改它的高级字体样式:

    一些组件类似 Button 和 TextInput,文本渲染器的父对象有多个状态。可以提供多个 TextFormat 对象给 TextFieldTextRenderer 。再次以 Button 组件为例,通过 setElementFormatForState() 方法,给“按下”状态一个不同的字体样式:

    var defaultFormat:TextFormat = new TextFormat( "Helvetica"20, 0xc4c4c4 );
    textRenderer.textFormat = defaultFormat;

    var downFormat:TextFormat = new TextFormat( "Helvetica"20, 0x343434 );
    textRenderer.setTextFormatForState( ButtonState.DOWN, downFormat );

    其它的如 HOVER 状态、DISABLED 状态设置方法都一样。

    使用嵌入字体:

    为一个 TextBlockTextRenderer 对象使用嵌入的 TTF 或 OTF 格式的字体,使用 [Embed] 元标签,如:

    [Embed(source="my-font.ttf",fontFamily="My Font Name",fontWeight="normal",fontStyle="normal",mimeType="application/x-font",embedAsCFF="false")]
    private static const MY_FONT:Class;

    source :是 TTF 或 OTF 字体的路径。

    fontFamily :给字体一个名称,TextFormat 构造函数中需要用到。

    fontWeight :嵌入的是否为粗体。

    fontStyle :嵌入的是否为斜体。

    mimeType :必须设为 “application/x-font”。

    embedAsCFF :当使用传统的原生 TextField 对象时必须设为 false。

    TextFieldTextRenderer 使用嵌入字体时,将嵌入字体的 fontFamily 传入给 TextFormat 构造函数,如:

    textRenderer.textFormat = new TextFormat( "My Font Name"16, 0xcccccc );
    textRenderer.embedFonts = true;

    embedFonts 属性必须设为 true。(如果在设置字体样式时使用的是 starling.text.TextFormat 类,会自动检测是否嵌入了字体;只有当使用 flash.text.TextFormat 对象设置高级字体样式时需要设置 embedFonts 属性)。

    Jan

    26

    BitmapFontTextRenderer 是 Feathers3 组件提供的内置文本渲染器(也被称为“文本呈现器”,text renderers)之一,使用位图字体(bitmap fonts)作为文本渲染器的内容。

    优缺点:

    位图字体将每个字符的图形轮廓作为纹理集中的子纹理,如果具有特殊的样式(如渐变、投影等)可以提供最佳性能(不需要运行时动态生成,可以节省性能)。

    位图字体比较适合用于游戏开发,一般只有少量的文字(没有大段大段的文字),比如 HP 值、积分、弹药数量等等,可以快速的切换显示需要的字符轮廓图形纹理,而不需要重复的将纹理提交 GPU。

    位图字体有时候也可以用于大段的文字(比如有统一的字体、字号和样式),因为每个字符对应的是一个单独的子纹理,所以可以重复的使用,以节省 GPU 的显存。但是由于每一个纹理显示时都会对应有一个 Starling 显示列表上的 Image 对象,随着字符数量的增加,所有这些单独的显示对象的变换计算可能最终会很消耗 CPU (如果有可能的话,需要测试以确定一台设备的CPU可以一次处理多少个字符)。

    英语只有 26 个字母(除了一些需要用到的标点或其它特定的字符),一些语言可能需要成百上千,比如说中文……由于 GPU 纹理尺寸限制,除了使用其它文本渲染器外,就别无选择了。

    位图字体是可以被缩放的,但一般中人推荐缩小(因为放大模糊会比缩小模糊的更快)。可能会失去文本的细节,在较小号的字体时使用矢量字体有更好的清晰度,文字清晰了就更易于阅读。对相同字体但不同字号的情况,通常是制作多份字体的纹理集,但这会需要更多的内存。

    在同一个位图文本渲染器中,不支持多种字体样式(即一个字符只对应一个字符的轮廓图形)。

    高级字体样式

    通常,是对一个文本渲染器的父组件使用 starling.text.TextFormat 类设置文本样式,例如设置一个按钮的文本样式:

    button.fontStyles = new TextFormat( "Helvetica"20, 0xcc0000 );

    直接在按钮上设置了 fontStyles 属性,而不是在文本渲染器上设置。但是 starling.text.TextFormat 并不能设置文本渲染器的所有字体样式。如果想要进行高级的字体样式设置,可以参考下面的资料。以 Button 组件为例,设置 labelFactory 属性值:

    var button:Button = new Button();

    button.label = "Click Me";

    button.labelFactory = function():ITextRenderer
    {
        var textRenderer:TextBlockTextRenderer = new TextBlockTextRenderer();

        //为避免与主题文件中默认设置的样式冲突,先删除 styleProvider 提供的样式
        //labelFactory 会先执行,然后再执行主题文件中的代码,styleProvider 设为null 后,可以避免被覆盖
        textRenderer.styleProvider = null;

        //在这里设置高级字体样式
        //……

        return textRenderer;
    };

    高级字体样式可以通过一个 BitmapFontTextFormat 对象来自定义,然后将这个对象赋值给位图文本渲染器的 textFormat 属性:

    var format:BitmapFontTextFormat = new BitmapFontTextFormat( "FontName" );

    位图字体的名称通过 TextField.registerBitmapFont() 方法注册。位图字体如未注册过,也可以使用 starling.text.BitmapFont 类。

    可以给位图字体设置颜色值,这个颜色值会被预乘(multiplied)到纹理的颜色,效果类似 starling.display.BlendMode.MULTIPLY 混合模式 :

    format.color = 0xc4c4c4;

    为了最大范围的颜色设置,位图字体纹理在导出时最好是纯白色导出的。

    可以使用align属性自定义文本的对齐方式:

    format.align = TextFormatAlign.CENTER;

    位图字体可以设置字号大小,但缩放的时候不会像矢量字体那样“美观”(清晰):

    format.size = 18;

    在大多数情况下不需要设置 size 的值,会自动检测字号的大小。对相同字体但不同字号的情况,通常是制作多份字体的纹理集,位图字体注册不同的名称,但这会需要更多的内存。

    其它更多的高级字体样式功能参考 BitmapFontTextRenderer API 和 BitmapFontTextFormat API 

    一个文本渲染器的父组件有多个状态,如何更改它的高级字体样式:

    一些组件类似 Button 和 TextInput,文本渲染器的父对象有多个状态。可以传递多个 BitmapFontTextFormat 对象给 BitmapFontTextRenderer 对象。再次以 Button 组件为例,通过 setElementFormatForState() 方法,给“按下”状态一个不同的字体样式: 

    var defaultFormat:BitmapFontTextFormat = new BitmapFontTextFormat( "FontName"20, 0xc4c4c4 );
    textRenderer.textFormat = defaultFormat;

    var downFormat:BitmapFontTextFormat = new BitmapFontTextFormat( "FontName"20, 0x343434 );
    textRenderer.setTextFormatForState( ButtonState.DOWN, downFormat );

    其它的如 HOVER 状态、DISABLED 状态设置方法都一样。

    Jan

    26

    TextBlockTextRenderer 是 Feathers3 组件提供的内置文本渲染器(也被称为“文本呈现器”,text renderers)之一,它使用 Flash 内置的文本引擎(Flash Text Engine), CPU 软渲染基于矢量字体(可以使用高级排版功能),矢量的字体可以是系经内安装的字体或开发者嵌入的字体(TTF 或 OTF 格式)。文本先被 draw 到 BitmapData 对象,然后再被转换成 Starling 纹理对象。 

    优缺点

    Flash Text Engine 可以使用设备字体进行渲染,而类似像中文字这样字符量非常庞大,渲染动态未知的文本使用设备字体可能是唯一选择(因为嵌入中文字体文件会变的很大,而且运行时占用内存也会变的非常大)。类似的,有些情况是嵌入矢量字体比嵌入位图字体能更少的占用资源,可以使用嵌入矢量字体。

    Flash Text Engine 能最好的支持从右向左排版的文字和双向(bi-directional)排版的文字,flash.text.TextField 类可能会无法正确的呈现。

    将矢量文字 draw 到 BitmapData 对象,然后转换成为 Starling 需要的纹理格式,提交到 GPU。在性能上会慢于位图字体。但是,一旦成功的上传到 GPU 后,就可以变的流畅了。如果经常需要更改文本的内容,那么就需要重复的 draw 、转换纹理、再提交,上传纹理的延迟时间可能会成为性能的瓶颈。

    每段矢量文本都会被单独 draw 到不同的 BitmapData 对象,然后转换成 Starling 纹理对象提交到 GPU。因此,当屏幕中有多个 TextBlockTextRenderer 实例时,经常性的更改文本内容,可能会导致严重的性能问题。

    Flash Text Engine 有时可能会比 flash.text.TextField 渲染的慢一些,但这种性能差异是可以忽略的,并且FTE 引擎的更高级功能带来的好处,通常比更小的性能降低风险更有说服力。

    TextBlockTextRenderer 可选的支持富文本功能,但需要手动创建和添加多个 TextElement 对象到 GroupElement 对象,每一段可以有不同的 ElementFormat 值。

    高级字体样式:

    通常,是对一个文本渲染器的父组件使用 starling.text.TextFormat 类设置文本样式,例如设置一个按钮的文本样式:

    button.fontStyles = new TextFormat( "Helvetica"20, 0xcc0000 );

    直接在按钮上设置了 fontStyles 属性,而不是在文本渲染器上设置。但是 starling.text.TextFormat 并不能设置文本渲染器的所有字体样式。如果想要进行高级的字体样式设置,可以参考下面的资料。以 Button 组件为例,设置 labelFactory 属性值:

    var button:Button = new Button();
    button.label = "Click Me";
    button.labelFactory = function():ITextRenderer
    {
        var textRenderer:TextBlockTextRenderer = new TextBlockTextRenderer();
        //为避免与主题文件中默认设置的样式冲突,先删除 styleProvider 提供的样式
        //labelFactory 会先执行,然后再执行主题文件中的代码,styleProvider 设为null 后,可以避免被覆盖
        textRenderer.styleProvider = null;

        //在这里设置高级字体样式
        //……

        return textRenderer;
    };

    高级字体样式可能是通过 flash.text.engine.ElementFormat 类设置文本渲染器的 elementFormat 属性提供的,如:

    var font:FontDescription = new FontDescription("Source Sans Pro", FontWeight.BOLD, FontPosture.ITALIC );
    textRenderer.elementFormat = new ElementFormat( font, 16, 0xcccccc );

    ElementFormat 构造函数的第一个参数是一个 FontDescription 对象,这个类提供字体的必要信息,被 FTE 引擎用于字体查询,包括字体的名称、粗细、是否斜体、是否嵌入的或设备字体。

    ElementFormat 定义字体的字号、颜色、透明度等等,如:

    var format:ElementFormat = new ElementFormat( fontDescription );
    format.fontSize = 20;
    format.color = 0xc4c4c4;
    format.alpha = 0.5;

    但文本对齐的设置并不包含在 FontDescription 与 ElementFormat 对象中,而是直接在文本渲染器上设置 textAlign 属性值,如:

    textRenderer.textAlign = TextBlockTextRenderer.TEXT_ALIGN_CENTER;

    TextBlockTextRenderer 提供了一系列高级属性用于自定义,参考 API 手册吧。

    一个文本渲染器的父组件有多个状态,如何更改它的高级字体样式

    一些组件类似 Button 和 TextInput,文本渲染器的父对象有多个状态。可以提供多个 ElementFormat 对象给 TextBlockTextRenderer 。再次以 Button 组件为例,通过 setElementFormatForState() 方法,给“按下”状态一个不同的字体样式:

    var defaultFormat:ElementFormat = new ElementFormat( fontDescription, 20, 0xc4c4c4 );
    textRenderer.elementFormat = defaultFormat;

    var downFormat:ElementFormat = new ElementFormat( fontDescription, 20, 0x343434 );
    textRenderer.setElementFormatForState( ButtonState.DOWN, downFormat );

    其它的如 HOVER 状态、DISABLED 状态设置方法都一样。

    使用嵌入字体

    为一个 TextBlockTextRenderer 对象使用嵌入的 TTF 或 OTF 格式的字体,使用 [Embed] 元标签,如:

    [Embed(source="my-font.ttf",fontFamily="My Font Name",fontWeight="normal",fontStyle="normal",mimeType="application/x-font",embedAsCFF="true")]
    private static const MY_FONT:Class;

    source :是 TTF 或 OTF 字体的路径。

    fontFamily :给字体一个名称,FontDescription 构造函数中需要用到。

    fontWeight :嵌入的是否为粗体。

    fontStyle :嵌入的是否为斜体。

    mimeType :必须设为 “application/x-font”。

    embedAsCFF :当使用 FTE 文本引擎(Flash Text Engine)时必须设为 true。

    TextBlockTextRenderer 使用嵌入字体时,将嵌入字体的 fontFamily 传入给 FontDescription 构造函数,如:

    var font:FontDescription = new FontDescription("My Font Name", FontWeight.BOLD, FontPosture.ITALIC );
    font.fontLookup = FontLookup.EMBEDDED_CFF;

    确保将 FontDescription 对象的 fontLookup 属性设为 FontLookup.EMBEDDED_CFF。(如果在设置字体样式时使用的是 starling.text.TextFormat 类,会自动检测是否嵌入了字体;只有当使用 flash.text.engine.ElementFormat 对象设置高级字体样式时需要设置 fontLookup 属性)。

    Jan

    26

    文本渲染器(也有人称“文本呈现器”,text renderers)在 Feathers 的帮助页面上列在了“核心内容”部份,这个核心的意思大概是指文本渲染器涉及到多个组件的组成部份。在 GPU 上显示文本有多种方式,但每一种方式都有优点与缺点,并没有任何一种最好的方式,所以凡是涉及到文本的组件,都给开发者提供了对应的 API 允许开发者自己选择不同的文本渲染器。

    在选择不同的文本渲染器时应考虑以下几个因素:

    1、文本的长度
    2、多更新一次文本(文本更新的频率)
    3、文本所显示的语言

     这些因素可能会影响性能与内存的使用量,具体取决于选择的文本渲染器。在单个场景中不同组件可以混合使用不同的文本渲染器,以达到最佳效果。

    Feathers 提供了 3 种不同的文本渲染器

    1、BitmapFontTextRenderer:使用位图字体(bitmap fonts)作为文本渲染器的内容。它的好处是同一张纹理图可以用于多个文本渲染器实例,多个实例同时使用时可以大大减少绘制命令的调用(Starling 对相同纹理的渲染有优化);运行时的动态生成的渐变、滤镜效果等是很占性能的、且需要更多系统资源的,所以可以对位图字体先预处理效果,将渐变、滤镜等特效变成位图字体的一部份,这样就能大大提高性能、并节省系统资源。缺点是它一般不推荐用在需要大量的字符的情况下,比如汉字……或者需在大量不同字体字号的的情况下。

    2、TextBlockTextRenderer:先使用 Flash 内置的文本 Engine(Flash Text Engine)软渲染,然后将结果 draw 下来变成位图数据对象(BitmapData),再转换成 Starling 需要的纹理格式提交到 GPU 使用,它提供的版式功能是最丰富的,包括像亚洲字体从左向右的版式都可以有,但每个实例需要一份单独的纹理对象,因此,如果场景中有多个对象使用了这种文本渲染器,它不仅会增加原生 API 的 draw 次数,也同样会增加 Starling 的 draw 次数(当然文本生成的位图面积越大,性能与内存开销越大)。

    3、TextFieldTextRenderer:先使用的是 flash.text.TextField 软渲染,然后将结果 draw 下来变成位图数据对象(BitmapData),再转换成 Starling 需要的纹理格式提交到 GPU 使用,TextField 可以支持一个 HTML 标签的子集,但它的版式功能很有限。每个实例需要一份单独的纹理对象,因此,如果场景中有多个对象使用了这种文本渲染器,它不仅会增加原生 API 的 draw 次数,也同样会增加 Starling 的 draw 次数(同样 TextBlockTextRenderer 一样,文本生成的位图面积越大,性能与内存开销越大)。

    每一种文本渲染器的功能并不相同,所以一定要仔细区分,选择一个最佳的文本渲染器应用到开发中。

    默认的文本渲染引擎:

    通常情况下,应用程序中的大多数组件将使用相同类型的文本渲染器。为避免重复的在每个组件中单独设置文本渲染器,可以先设置一个全局的文本渲染器告诉所有组件默认情况下使用某种文本渲染器。只有当遇到某个组件不需要默认的文本渲染器时,才给它传递入特殊的文本渲染器,覆盖默认的类型。

    推荐使用 BitmapFontTextRenderer,Starling 与 Feathers 的使用目的主要目标之一就是开发游戏,字符串比较短(相当于 draw 的面积比较小),并且需要经常性的更新。

    当使用主题文件时(theme),应该检查默认的文本渲染器。主题文件中通常会嵌入一种自定义字体,通用于组件的文本渲染,保持风格一体化。

    当一个组件没有单独设置文本渲染器的时候,它会调用 FeathersControl.defaultTextRendererFactory() 方法。FeathersControl.defaultTextRendererFactory 是一个静态变量,可以根据需要任意的更改为不同的函数,默认它就是这样子:

    function():ITextRenderer
    {
        return new BitmapFontTextRenderer();
    }

     根据需要,也可以更改为 TextBlockTextRenderer 作为默认的文本渲染器:

    FeathersControl.defaultTextRendererFactory = function():ITextRenderer
    {
        return new TextBlockTextRenderer();
    };

    在单个组件上使用不同的文本渲染器:

    可以给特定的组件指定特殊的文本渲染器,不使用(覆盖)默认的文本渲染器,比如一个按钮:

    button.labelFactory = function():ITextRenderer
    {
        return new TextFieldTextRenderer();
    }

    甚至可以在返回文本渲染器之前,对文本渲染器设置字体相关的高级选项:

    button.labelFactory = function():ITextRenderer
    {
        var textRenderer:TextFieldTextRenderer = new TextFieldTextRenderer();
        textRenderer.antiAliasType = AntiAliasType.NORMAL;
        textRenderer.gridFitType = GridFitType.SUBPIXEL;
        return textRenderer;
    }

    如果正在使用主题文件进行开发,需要小心:当对单个组件设置 labelFactory 属性时,可能被主题文件中的样式覆盖,因为主题文件中样式的使用是在单个组件设置 labelFactory 之后

    不同的组件在指定文本渲染器时可能会有不同的属性名称,比如一个 Header 对象,它不叫 labelFactory,而是叫 titleFactory。任何组件的文本渲染器样式工厂属性名称可以通过查询 API 手册

    Label 组件

    Label 组件是一个具体的组件,它可以非常方便和简单的显示文本,但它本身不是文本渲染器,但它包含了文本渲染器实例。

    通常,我们不会去直接使用一个 BitmapFontTextRenderer 对象,Label 组件可以很好的抽象出具体使用功能但分离文本渲染器,文本渲染器应该脱离实际的应用开发,这样可以快速的切换不同的主题文件、应用不同的样式等操作。Label 组件有一个 fontStyles 样式属性,它可以接受一个 starling.text.TextFormat 对象,不同的对象可以接受不同的格式化相关的类,如 flash.text.engine.ElementFormat 或 feathers.text.BitmapFontTextFormat 类。特别是当大批的文本对象使用的时候,如果后期要更改与前期选择的文本渲染器不同的,那么可能要在很多不同的类文件中一个一个的去修改……

    自定义文本渲染器

    自定义文本渲染器的时候,需要实现 ITextRenderer 接口类,它有一些预置的方法,比如将字符串赋值给文本渲染器,文字的测量。一个自定义的文本渲染器可能是基于 Text Layout Framework (TLF) 的,它提供了更高级的功能。除非自定义的文本渲染器是能够直接渲染到 GPU 的,否则就需要一个“快照”,类似前面的 TextFieldTextRenderer 或 TextBlockTextRenderer ,先 draw 到一个位图数据,再转换成 Starling 需要的纹理格式提交到 GPU 使用(Feathers 是开源的,可以参考它内置的文本渲染器源码)。

    其它的备用方案

    在显示文本方面,还有其它一些备用方案,但它们和前面提供的几个文本渲染器一样,都有它们各自的优点与缺点。

    Feathers 的 ScrollText 组件:因为纹理图有尺寸限制,有时候我们的文本对象可能太宽或太高超出了限制,或者整体尺寸过大,没有足够的 GPU 显存可能存储纹理;极少数的时候,我们可能可以用 BitmapFontTextRenderer 对象来解决这种问题,但它并不适合矢量对象。此时,我们应该考虑一下使用 ScrollText 组件,它的文本渲染引擎是一个原生舞台上的 flash.text.TextField 对象,原生舞台始终在 Stage3D 层上面(CPU 软渲染的)。它会被自动计算匹配到 Starling 对象的坐标系统中。

    a、ScrollText 最大的缺点就是它在移动设备上渲染大量文本时可能会跟不上性能,比如滚动时可能会无法“平滑”,出现跳帧。

    b、ScrollText 另外的缺点就是原生舞台层始终在 Stage3D 层上面,所以无法在 ScrollText 组件上添加其它 Starling 对象。

    c、另外一些潜在的问题,如在安卓设备上,原生层与Stage3D 层帧频设置对半分,以及 Starling 的 skipUnchangedFrames 属性很可能会被禁用等。

    关于 skipUnchangedFrames 属性被禁用的资料请参看《skipUnchangedFrames 属性局限性》。