加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Flash文本引擎, 第一部分: 概述

发布时间:2020-12-15 17:59:28 所属栏目:百科 来源:网络整理
导读:[原文链接:?http://guyinthechair.com/2010/06/the-flash-text-engine-part-1/??] [原文作者:?Paul Taylor? ?原文时间:??Jun. 3,2010 ] [原创翻译:?http://www.smithfox.com/?e=73?,转载请保留此声明,谢谢] 我将写系列文章来介绍Flash文本引擎( Flash Text E

[原文链接:?http://guyinthechair.com/2010/06/the-flash-text-engine-part-1/??]
[原文作者:?Paul Taylor? ?原文时间:??Jun. 3,2010 ]
[原创翻译:?http://www.smithfox.com/?e=73?,转载请保留此声明,谢谢]

我将写系列文章来介绍Flash文本引擎( Flash Text Engine,Flash Player 10中新的低层API,以下简称FTE),本文是开篇:?第一部分,?第二部分,?第三部分.??

首先需要澄清,这些系列文章不是写Adobe的文本布局框架(Text Layout Framework,以下简称TLF)的,TLF是一个高级的排版和文字布局框架,TLF是建立在FTE(Flash Text Engine)之上的,FTE是一个低层的Player native API,它在flash.text.engine?package内.

FTE是用来渲染文本的 "文档样式" 的,它的主要目的是取代TextField,而不是提供一个完整的HTML渲染引擎规模的文本布局框架.?

FTE处理一种我称之为流(flow)的东西: 格式化,引起文本在段落内换行,我不知道这是不是官方术语,但似乎也挺适合. 它不处理布局相关的事,比如项目符号,缩进排版,图像环绕,padding等等. 它也不处理装饰之类的东西,比如,?下划线,删除线,背景颜色,选择高亮等. FTE将这些交给外层处理,我相信是因为:
1. 布局更为复杂和细致,这些功能不要在FlashPlayer核心中
2. 装饰不会使文本回流,或是引起文本换行

FTE遵循了一个小的MVC架构,大约有10个核心类,它们提供了大部分的功能,剩下的类是一些常量声明. 需要注意的是,所有的FTE的类都声明为final(译者注: 不可继承) ?:).

FTE Model(MVC之 model)

FTE模型的基础是ContentElement。 ContentElement的是一个抽象基类。你不能直接 new ContentElement()(这有点象DisplayObject),但可以实列化它的三个子类:TextElement、GraphicElement或GroupElement。这些类描述了文本树状层次结构,但在深入之前,我想先多谈一点ContentElement。

ContentElement

先看一下ContentElement的构造函数

ContentElement(elementFormat:ElementFormat = null,eventMirror:EventDispatcher = null,textRotation:String = "rotate0")

它有两个重要的参数,elementFormateventMirror(还有一个不太重要的第三个参数,只有当你想旋转文本时才会用到这个参数)。让我们先只看ElementFormat,后面我们再回来看eventMirror。

ElementFormat类描述了处理文本流所需的绝大部分属性。它有一个FontDescription成员,正如其名,在FontDescription中你能取到标准fontFamily、fontWeight、fontPosture(这相当于传统的Flash中的FontStyle),以及字体是如何检索自Flash播放器深度(紧凑字体格式或设备字体)的。

ElementFormat有alpha,color,baselineShift,kerning等属性,基本上都能够影响reflow(回流?)。

好的,上面描述了现在你需要知道的有关ElementFormat和FontDescription对象的内容。接下来让我们看一看你会用到的实现类。

TextElement

在这三个当中,TextElement的是最直接的。它只是接受一个文本字符串:

TextElement(text:String = null,elementFormat:ElementFormat = null,textRotation:String = "rotate0")

传入的的ElementFormat将应用于整个文本字符串。因此,如果你指定了一个红颜色的的ElementFormat,那整个文本字符串会呈现红色

GraphicElement

GraphicElement接受一个DisplayObject实例(实例!),以及它的宽度和高度:
GraphicElement(graphic:DisplayObject = null,elementWidth:Number = 15.0,elementHeight:Number = 15.0,textRotation:String = "rotate0")

ElementFormat的一些属性也适用于GraphicElement,如alpha、baselineShift等。显然,GraphicElement并不遵守FontDescription和ElementFormat的字体相关设置。

GroupElement

最后是GroupElement:

GroupElement(elements:Vector.<ContentElement> = null,textRotation:String = "rotate0")

GroupElement非常重要,它是TextElements、GraphicElements或其他GroupElements任意组合的集合。 GroupElement为FTE模型提供了树的功能。 TextElement的不能拥有孩子,它只控制一个字符串。同样,GraphicElement也只是描述了一个DisplayObject实例。 而GroupElements则把它绑在一起。
GroupElements提供了一套处理标准树的API函数,你可以提取,分割,合并,组合孩子。以我的经验,你不会经常用这个,除非你正在写一个可编辑的文本字段。如果你正在编写一个可编辑的文本字段,上帝保佑你(开玩笑的,it is hella fun)。
好,说够了模型,下面...


FTE View(MVC之view)

有两个(两个!)类构成了FTE的视图division: TextLine和TextLineMirrorRegion。现在你可以忘掉TextLineMirrorRegion,因为它是处理交互的,这是一个复杂的话题,我将在后面会详细地讨论。因此,现在只专注于TextLine。

TextLine

TextLine是一个DisplayObjectContainer。是的,这就意味着它有get/add/removeChild方法(他们仍然有效!)。TextLine也是在InteractiveObject,你可以侦听所有正常的交互事件。不过,尽管它继承自InteractiveObject,但有几个属性,是只读的。这些都已经详细地写在TextLine官方文档了。

TextLine增加了原子的概念,是指在一个TextLine不可分割的字符。单个字符以及任何图形是原子性的。重要的是要知道原子永远不能被行与行分裂。FTE测量单位最小是原子水平,没有更小。
保持原子信息可能是昂贵的,TextLine只呈现其文本,但它不知道它包含的任何原子,然而调用各种方法将引起TextLine创建原子数据。比如,你调用getAtomIndexAtPoint(),TextLine就会为每个原子创建相关信息,这样它才能计算你所指定的点是哪个原子。一旦你做完,一定要调用flushAtomData(),这样原子数据才会GC.
TextLine有指向上一行和下一行的引用,因为TextLine是一个双向链表! 多方便呀! 当然,如果没有前一个引用或是后一个引用,那自己分别就是第一个或是最后一个.
TextLine还有一个有效状态,用来表示该行从渲染后是否已经改变。有TextLineValidity类表示这个状态。

TextLine绝对不是Sprite. TextLine是DisplayObjectContainer. 这最重要的含义是: TextLine没有graphics上下文. 这意味着你不能调用textLine.graphics.draw. :( 哎!
虽然TextLine是一个具体类,你能直接用它,但你不能通过调用它的构造函数来实例化它. 你需要 ...


FTE Controller(MVC之C)

FTE controller部分可能只有一个类: TextBlock。我说是"可能",因为还有TextJustifier和TabStop类,但它们仅仅影响TextBlock的渲染,不...,嗯。好吧,我说服了我自己把它们也算着控制器类,但只有一点点.
请相信我,很快你也会认为TextLine是唯一的控制器类。
TextBlock的是一个相当标准的工厂模式的实现:TextBlock的主要工作是接受ContentElement作为输入然后输出一些你想要的给定宽度的TextLine。ContentElement-> TextBlock -> TextLines。明白了吗?我也没有。
TextBlock 有一个函数 createTextLine():

createTextLine(previousLine:TextLine = null,width:Number = 1000000,lineOffset:Number = 0.0,fitSomething:Boolean = false):TextLine

你所要做的就是将你刚创建的前一行作为第一个参数传入,再加一个参数表示你想让当前行有多宽,TextBlock就会为你丈量了一个新的TextLine. 你是否看到了双向链表了?

创建第一个TextLine时,你只需要传null作为第一个参数就可以了. 如果TextBlock的content属性有内容了,并且至少有一个原子(字符或是图形),那么传入null总是会返回一个TextLine. 如果已经没有新行需要创建,调用TextBlock.createTextLine() 将会返回 null.

下面的简单例子是一个宽度为200的TextBlock渲染行的过程

var y:Number = 0;
var line:TextLine = block.createTextLine(null,200);
while(line)
{
    addChild(line);
    y += line.height;
    line.height = y;
    line = block.createTextLine(line,200);
}


好吧,我已经说了很多了,该来一个例子了.

如果你看不到flash,你就直接到 http://www.smithfox.com/myopensource/fte/SimpleDemo1.swf

下面是这个例子的代码:

package
{
  import flash.display.Sprite;
  import flash.text.engine.ContentElement;
  import flash.text.engine.ElementFormat;
  import flash.text.engine.FontDescription;
  import flash.text.engine.FontPosture;
  import flash.text.engine.FontWeight;
  import flash.text.engine.GroupElement;
  import flash.text.engine.TextBlock;
  import flash.text.engine.TextElement;
  import flash.text.engine.TextLine;
 
  [SWF(width="450",height="32")]
  public class SimpleDemo1 extends Sprite
  {
    public function SimpleDemo1()
    {
      super();
 
      var e1:TextElement = new TextElement('Consider,what makes a text line a ',new ElementFormat(new FontDescription(),24));
      var e2:TextElement = new TextElement('text line',new ElementFormat(new FontDescription("_serif",FontWeight.NORMAL,FontPosture.ITALIC),24));
      var e3:TextElement = new TextElement('?',24));
 
      var e:Vector. = new Vector.();
      e.push(e1,e2,e3);
 
      var block:TextBlock = new TextBlock(new GroupElement(e));
      var line:TextLine = block.createTextLine(null,stage.stageWidth);
 
      var _y:Number = 0;
      while(line)
      {
        addChild(line);
        _y += line.height;
        line.y = _y;
        line = block.createTextLine(line,stage.stageWidth);
      }
    }
  }
}

Holy crap Batman!

正如你所看到,它需要三个TextElement一个GroupElement来完成一个中间有斜体文字和不同字体文字的文本行.

第二部分我将讲解互动相关内容,访问TextBlock,以及全部. 一直到你看到在github上的tinytlf项目. 它应该要有一次重大更新了,不过我很快就会和大家谈到它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读