<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:thr="http://purl.org/syndication/thread/1.0">
  <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html" />
  <link rel="self" type="application/atom+xml" href="http://www.insideria.com/atom.xml" />
  <id>tag:www.insideria.com,2009://34/tag:www.insideria.com,2009://34.34547-</id>
  <updated>2009-11-16T15:10:39Z</updated>
  <title>Comments for Flash Text Engine (http://www.insideria.com/2009/03/flash-text-engine.html)</title>
  <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.21-en</generator>
  <entry>
    <id>tag:www.insideria.com,2009://34.34547</id>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://blogs.oreilly.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=34/entry_id=34547" title="Flash Text Engine" />
    <published>2009-03-19T16:00:00Z</published>
    <updated>2009-10-13T01:09:20Z</updated>
    <title>Flash Text Engine</title>
    <summary>Note that every image with a blue border in this article launches a swf example. Read its caption to understand how it works. One of the most interesting sessions at MAX 2008 was Creating a Next-Generation Desktop News Reader by...</summary>
    <author>
      <name>Veronique Brossier</name>
      
    </author>
    
    <category term="Adobe Feed" />
    
    <category term="Features" />
    
    <content type="html" xml:lang="en" xml:base="http://www.insideria.com/">
      <![CDATA[<p><em>Note that every image with a blue border in this article launches a swf example. Read its caption to understand how it works.</em></p>

<p>One of the most interesting sessions at MAX 2008 was <a href="http://tv.adobe.com/#vi+f15385v1012">Creating a Next-Generation Desktop News Reader</a> by Jeremy Clark, Daniel Wabyick and Justin Van Slembrouck. It demonstrated a sophisticated and dynamic AIR news reader application using the International Herald Tribune's feeds and gave a taste of what to expect in the news delivery of the future. It also showcased the greatly improved text management of the latest Flash player 10.</p>

<p>In addition, Adobe Labs released in December 2008 the <a href="http://labs.adobe.com/technologies/textlayout/">Text Layout Framework</a> (previously known as Vellum then Text Component ActionScript Library) built on top of the FTE. With it you can use or extend text components built on top of the text engine for both Flex and Flash. The Text Layout Framework deserves an article of its own as it will be used by most developers but the intent of this article is to give an understanding of how the engine itself works.</p>

<p>The new text engine <em>flash.text.engine</em> was built from the ground-up. It co-exists with the current TextField object but works differently: it is a low-level access, highly flexible text layout engine. Device fonts can now be manipulated as if they were embedded. In fact, a lot of the same effects can be applied to device and embedded fonts. The text is print-quality typography for the web.</p>

<p>The engine supports many languages and alphabeths including the ones using right-to-left layout (Arabic and Hebrew) or vertical layout (Chinese, Japanese and Korean) but also complex ones (Tate-chu-yoko) which have horizontal blocks in vertical text. Additionally a combination of scripts, such as Japanese or Arabic, is possible.</p>

<p>The following classes are used to create, format and control your text (in addition, many other classes manage under the hood core text information such as Font or TextRenderer).</p>

<ul>
	<li>the TextBlock - the factory for building a paragraph of text</li>
         <li>the textLine - a line of text for the textBlock and a new displayObject</li>
	<li>the contentElement - holds the content (text or graphic) of the textBlock</li>
	<li>the ElementFormat - defines the format of the contentElement</li>
	<li>the fontDescription - defines properties of the font applied to the elementFormat</li>
</ul>

<p>This is some simple code using these classes to display text with all default settings:</p>
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">import</span> flash.<span class="category2">text</span>.engine.*;

<span class="category1">var</span> fd:FontDescription = <span class="category1">new</span> FontDescription();
<span class="category1">var</span> ef:ElementFormat = <span class="category1">new</span> ElementFormat(fd);
<span class="category1">var</span> te:TextElement = <span class="category1">new</span> TextElement("<span class="quote">Hello world</span>", ef);
<span class="category1">var</span> tb:TextBlock = <span class="category1">new</span> TextBlock();
tb.content = te;

<span class="category1">var</span> tl:TextLine = tb.createTextLine(<span class="category1">null</span>, 200);
addChild(tl);</pre>
</code>

</div></div>

<p></p>
<p></p>
<p><b><big>FontDescription</big></b><br>
This is where you define the font family <i>fontName</i> you want to use. For device font, you can select font styling such as italize <i>fontPosture</i> and bold <i>fontWeight</i>. For embedded font, you can take advantage of the enhanced screen rendering especially for small sizes <i>renderingMode.CFF</i> and strong horizontal stems to snap to a sub pixel grid especially important on LCD displays <i>cffHinting</i>. In RenderingMode.CFF mode, instead of the standard Flash renderer, "anti-alias for animation", used for vector art, Adobe's special glyph rendering technology is applied.

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="embedded.png" src="http://www.insideria.com/embedded.png" width="545" height="369" class="mt-image-none" style="" /></span></p>

Define the <i>fontLookup</i> propriety to tell the player where to look for the font. If the value is <i>DEVICE</i>, it uses the standard operating system API to locate the font based on the font name and style specified in the swf. If the value is <i>EMBEDDED_CFF</i>, it looks at font outlines embedded in the swf. Such font becomes represented as a subclass of the flash.text.Font class (abstract base class) and holds font information such as <em>fontName</em>, <em>fontStyle</em>, <em>fontType</em> and <em>hasGlyphs()</em>.</p>

<p>Note that fonts of type EMBEDDED can only be used by the TextField object (still maintained in the future but non longer improved). Only fonts of type EMBEDDED_CFF (Compact Font Format) can take advantage of the FTE features. In addtion to font outlines and information for Unicode mapping, they include a subset of <a href="http://partners.adobe.com/public/developer/opentype/index_table_formats.html">OpenType tables</a> needed to do things such as ligature substitutions, contextual writing systems like Arabic or Hebrew and GPOS/GSUB (Glyph Positioning table and Glyph Substitution table).</p>

<p> To see which fonts are available on your machine and in the swf, use the <i>enumerateFonts</i> method of the Font class. The method <i>isFontCompatible(fontName, fontWeight, fontPosture)</i> returns the availability of an embedded font in any style. Note that, for device font, the player has no interface to determine if the font provided by the OS has bold or italic face.</p>

<p><a href="http://www.insideria.com/enumerateFonts.swf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="emulatefonts.png" src="http://www.insideria.com/emulatefonts.png" width="545" class="mt-image-none" style="" /></span></a><div class="apcaption">This displays the embedded fonts in the swf as well as the device fonts installed on your computer.</div></p>

<p><div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">import</span> flash.<span class="category2">text</span>.Font;
<span class="category1">import</span> flash.<span class="category2">text</span>.engine.FontDescription;

<span class="linecomment">// all fonts</span>
<span class="category1">var</span> myFonts:<span class="category2">Array</span> = Font.enumerateFonts(<span class="category1">true</span>);
<span class="category1">for</span> (<span class="category1">var</span> i:<span class="category1">int</span> = 0; i &lt; myFonts.<span class="category2">length</span>; i++) {
 <span class="category1">if</span> (myFonts[i].fontType == "<span class="quote">device</span>") {
  <span class="category2">trace</span>("<span class="quote">I am a device font and my name is</span>", myFonts[i].fontName);
 }
}

<span class="linecomment">// embedded fonts only</span>
<span class="category1">var</span> myEmbeddedFonts:<span class="category2">Array</span> = Font.enumerateFonts(<span class="category1">false</span>);
<span class="category1">var</span> f:Font = myEmbeddedFonts[0];
<span class="category2">trace</span>(FontDescription.isFontCompatible(f.fontName, "<span class="quote">normal</span>", "<span class="quote">normal</span>"));
<span class="category2">trace</span>(FontDescription.isFontCompatible(f.fontName, "<span class="quote">bold</span>", "<span class="quote">normal</span>"));
<span class="category2">trace</span>(FontDescription.isFontCompatible(f.fontName, "<span class="quote">normal</span>", "<span class="quote">italic</span>"));</pre>
</code>

</div></div></p>

<p>Embedding fonts can be tricky. In Flex, embed the font and store it using DefineFont4 and font subsetting currently only supported by Gumbo. A future version of Flash will support it but in the meantime, a Gumbo SWC with the embedded font must be created then adding to your Flash CS4 project.</p>
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
[Embed(source="<span class="quote">assets/GaramondPremrPro.otf</span>",
                            fontFamily="<span class="quote">GaramondPremiere</span>",
                            mimeType="<span class="quote">application/x-font</span>",
                            cff="<span class="quote">true</span>")]
<span class="category1">private</span> const GaramondPremiere:Class;

<span class="category1">var</span> fd = <span class="category1">new</span> FontDescription();
fd.fontLookup = FontLookup.EMBEDDED_CFF;
fd.fontName = "<span class="quote">GaramondPremiere</span>";</pre>
</code>

</div></div>

<p>To display non-Roman text, Unicode character codes are converted to Strings. Unicode is a standard to represent text in most systems providing character information in an abstract way rather than graphically by assigning a unique number for every character in a language. The Flash player uses the font information to determine how to map the number to a glyph.</p>

<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">var</span> <span class="category2">text</span>:<span class="category2">String</span> = "<span class="quote">abc</span>" +
<span class="category2">String</span>.<span class="category2">fromCharCode</span>(0x05D0, 0x05D1, 0x05D2, 0x5185, 0x95A3, 0x5E9C);</pre>
</code>

</div></div>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="unicode.jpg" src="http://www.insideria.com/unicode.jpg" width="261" height="56" class="mt-image-none" style="" /></span></p>

<p>The font description is initially applied to an elementFormat (covered next) and locked. To make changes, a clone must be created:</p>

<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">import</span> flash.<span class="category2">text</span>.engine.*;
<span class="category1">import</span> flash.<span class="category2">text</span>.Font;

<span class="category1">var</span> fd = <span class="category1">new</span> FontDescription("<span class="quote">PALATINO</span>", FontWeight.BOLD);
fd.fontLookup =  FontLookup.DEVICE;
<span class="category1">var</span> ef = <span class="category1">new</span> ElementFormat(fd);

<span class="category1">var</span> te = <span class="category1">new</span> TextElement("<span class="quote">Hello world</span>", ef);
<span class="category1">var</span> tb = <span class="category1">new</span> TextBlock();
tb.content = te;

<span class="category1">var</span> firstLine = tb.createTextLine(<span class="category1">null</span>, 300);
firstLine.<span class="category2">y</span> = 50;
addChild(firstLine);

<span class="linecomment">// fd.fontWeight = FontWeight.NORMAL; // will throw an error</span>
<span class="linecomment">// Error 2185: FontDescription object is locked and cannot be modified	</span>

<span class="linecomment">// clone the font description</span>
<span class="category1">var</span> fdCloned = (fd.locked) ? fd.clone() : fd; 
fdCloned. fontWeight = FontWeight.NORMAL;
<span class="category1">var</span> ef2 = <span class="category1">new</span> ElementFormat(fdCloned);

tb.content.elementFormat = ef2;

<span class="category1">var</span> secondLine = tb. createTextLine (<span class="category1">null</span>, 300);
addChild(secondLine);
secondLine.<span class="category2">y</span> = 100;</pre>
</code>

</div></div>
<p> </p>

<p><b><big>ElementFormat</big></b><br>
This is where you define text styling and some of the layout of your content (ContentElement discussed next). They applied to both device and embedded fonts.</p>

<p>Some styling properties are self-explanatory such as <i>alpha</i>, <i>color</i>, <i>fontSize</i> and <i>typographicCase</i>. Others, maybe less familiar, take their root in typography <i>digitCase</i>, <i>digitWidth</i>,  <i>ligatureLevel</i>. The layout properties affects horizontal spacing between atoms <i>kerning</i>, <i>trackingRight</i>, <i>trackingLeft</i>, vertical positioning <i>baselineShift</i>, <i>alignmentBaseline</i>, <i>dominantBaseline</i>, and <i>textRotation</i>. <i>breakOpportunity</i> determines which characters to break when wrapping text over several lines.</p>
 
<p>The image below shows several elementFormats with different settings. Note that the intent of some of the ElementFormat properties is to accommodate for vertical or right-to-left scripts rather than design.

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="formats.png" src="http://www.insideria.com/formats.png" width="545" height="175" class="mt-image-none" style="" /></span></p>

<p>TextRotation on a elementFormat is only applied at a 90 degree angle so for a more detailed rotation such as moving text on a path, use the TextLine rotation. For <em>alpha</em> and <em>textRotation</em>, the final effect is the multiplication of several objects' property value.</p>

<p><a href="http://www.insideria.com/alphaMultiplication.swf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="alpha.png" src="http://www.insideria.com/alpha.png" width="545" class="mt-image-none" style="" /></span></a><div class="apcaption">This shows <em>alpha</em> multiplication with alpha set on both the ElementFormat and the textLine.</div></p>

<p>Like the fontDescription, once a ElementFormat is assigned, it is locked. It can however be cloned.</p>

<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">import</span> flash.<span class="category2">text</span>.engine.*;
<span class="category1">import</span> flash.<span class="category2">text</span>.Font;

<span class="category1">var</span> fd = <span class="category1">new</span> FontDescription("<span class="quote">PALATINO</span>");
fd.fontLookup = FontLookup.DEVICE;
<span class="category1">var</span> ef = <span class="category1">new</span> ElementFormat(fd);
ef.fontSize = 30;

<span class="category1">var</span> te = <span class="category1">new</span> TextElement("<span class="quote">Hello world</span>", ef);
<span class="category1">var</span> tb = <span class="category1">new</span> TextBlock();
tb.content = te;

<span class="category1">var</span> firstLine = tb.createTextLine(<span class="category1">null</span>, 300);
firstLine.<span class="category2">y</span> = 50;
addChild(firstLine);

<span class="linecomment">// ef.fontSize = 50; // will throw an error</span>
<span class="linecomment">// Error 2184: The ElementFormat object is locked and cannot be modified</span>

<span class="linecomment">// clone the element format</span>
<span class="category1">var</span> efClone = (ef.locked) ? ef.clone() : ef;
efClone.fontSize = 50;

<span class="linecomment">// applies the new format to the existing content</span>
tb.content.elementFormat = efClone;

<span class="category1">var</span> secondLine = tb. createTextLine (<span class="category1">null</span>, 300);
addChild(secondLine);
secondLine.<span class="category2">y</span> = 100;</pre>
</code>

</div></div>
<p></p>

<p><b><big>ContentElement</big></b><br>
is the content (text and graphic) stored in a block of text and is independent of how it is distributed over lines. The contentElement is an abstract base class and cannot be instantianted. Use one of its subclasses instead: TextElement, GraphicElement or GroupElement.</p>

Text Element
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">import</span> flash.<span class="category2">text</span>.engine.*;

<span class="category1">var</span> fd:FontDescription = <span class="category1">new</span> FontDescription();
<span class="category1">var</span> ef:ElementFormat = <span class="category1">new</span> ElementFormat(fd);
<span class="category1">var</span> te:TextElement = <span class="category1">new</span> TextElement("<span class="quote">This is the content to display</span>", ef);
<span class="category1">var</span> tb:TextBlock = <span class="category1">new</span> TextBlock();
tb.content = te;

<span class="category1">var</span> tl:TextLine = tb.createTextLine(<span class="category1">null</span>, 200);
addChild(tl);</pre>
</code>

</div></div>

GraphicElement
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">import</span> flash.<span class="category2">text</span>.engine.*;

<span class="category1">private</span> <span class="category1">var</span> loader:Loader;

<span class="category1">private</span> <span class="category1">function</span> loadImage():<span class="category1">void</span> {
 loader = <span class="category1">new</span> Loader();
 loader.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
 <span class="category1">var</span> <span class="category2">url</span>:<span class="category2">String</span> = "<span class="quote">http://www.google.com/images/nav_logo.png</span>";
 <span class="category1">var</span> urlReq:URLRequest = <span class="category1">new</span> URLRequest(<span class="category2">url</span>);
 loader.<span class="category2">load</span>(urlReq);
}
		    
<span class="category1">private</span> <span class="category1">function</span> done(e:Event):<span class="category1">void</span> {
 <span class="category1">var</span> graphicElement:GraphicElement = <span class="category1">new</span> GraphicElement(loader, loader.<span class="category2">width</span>, loader.<span class="category2">height</span>);
 addChild(loader);
 textBlock.content = graphicElement;
}</pre>
</code>

</div></div>

GroupElement
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">import</span> flash.<span class="category2">text</span>.engine.*;

<span class="linecomment">// create a ContentElement vector to store multiple textElements</span>
<span class="category1">var</span> content:Vector.&lt;ContentElement&gt; = <span class="category1">new</span> Vector.&lt;ContentElement&gt;();

<span class="category1">var</span> fd:FontDescription = <span class="category1">new</span> FontDescription();

<span class="category1">var</span> el1:ElementFormat = <span class="category1">new</span> ElementFormat(fd, 10);
content.<span class="category2">push</span>(<span class="category1">new</span> TextElement("<span class="quote">I a the first piece of content. </span>", el1));

<span class="category1">var</span> el2:ElementFormat = <span class="category1">new</span> ElementFormat(fd, 15);
content.<span class="category2">push</span>(<span class="category1">new</span> TextElement("<span class="quote">I am the second </span>", el2));

<span class="category1">var</span> el3:ElementFormat = <span class="category1">new</span> ElementFormat(fd, 20);
content.<span class="category2">push</span>(<span class="category1">new</span> TextElement("<span class="quote">And I am the third one.</span>", el3));

<span class="category1">var</span> tb:TextBlock = <span class="category1">new</span> TextBlock(<span class="category1">new</span> GroupElement(content));

<span class="category1">var</span> tbc = textBlock.content;
<span class="category2">trace</span>(tbc); <span class="linecomment">// [object GroupElement]</span>
<span class="category2">trace</span>(tbc.elementCount); <span class="linecomment">// 3</span>
<span class="category2">trace</span>(tbc.getElementAt(0)); <span class="linecomment">// [object TextElement]</span>

createTextLines(tb); <span class="linecomment">// create lines using the text line content</span></span></pre>
</code>

</div></div>

<p>Each element type has its specific mechanism. TextElement can replace its text.
GraphicElement can modify the height and width allocated to the graphic on the line <em>elementHeight</em> and <em>elementWidth</em>. GroupElement manages its various elements in different ways such as replace, merge and split.</p>

<p><a href="http://www.insideria.com/elementGroup2.swf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="group.png" src="http://www.insideria.com/group.png" width="545" class="mt-image-none" style="" /></span></a><div class="apcaption">This takes advantage of the <a href="http://www.flickr.com/services/api/">Flickr API</a> to search pictures and of the text engine to easily layout text and graphic elements together. Search one of the word displayed in the text and see how the string is replaced by the matching Flickr image. The GroupElement is re-organized to display the GraphicElement where the word was and the TextElements surrounding it.</div></p>

<p>If the content is changed after it was initially created, the elementFormat doesn't need to be defined again or cloned but the lines containing the content need to be broken and recreated (discussed under TextBlock).</p>

<p>The contentElement read-only information is its <em>text</em>, its <em>elementFormat</em>, its <em>groupElement</em> if it is part of a group as well as its <em>textBlock</em> and its <em>textBlockBeginIndex</em> (index for this particular contentElement in the textBlock). The <em>userData</em> provides a way to associate data with the element. The <em>eventMirror</em> object mirrors the events dispatched to the textLine and can be used to add logic and interactivity to your text (example under TextLine).</p>

<p><b><big>TextLine</big></b><br>
is a new DisplayObject used to render one line of content according to a variable width. A textLine can only be created via the textBlock function <em>createTextLine()</em>.</p>

<p>The TextLine is made of "atoms&#8221;: characters, groups of characters, graphic elements and indivisible elements. Methods to retrieve atoms information are available but it is important to <em>flushAtomData()</em> afterwards to avoid memory overhead.</p>

<p><a href="http://www.insideria.com/lineAtoms.swf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="atoms.png" src="http://www.insideria.com/atoms.png" width="545" class="mt-image-none" style="" /></span></a><div class="apcaption">This shows all the textLine information available. Click on an atom to display it. A yellow selection area is drawn using the atom bounds. A red line indicates the baseLine, a pink line the descent and a grey line the ascent.</div></p>

<p>The textLine can determine on mouseDown the atom selected by calling <em>getAtomIndexAtPoint(e.stageX, e.stageY)</em> but it has no knowledge of the content (text or/and graphic) corresponding to the atom. This information can be retrieved via the <em>textblock.content.text</em> and passing it the index position of the atom within the textBlock <em>getAtomTextBlockBeginIndex()</em>.</p>

<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">private</span> <span class="category1">function</span> createLine(tb:TextBlock, <span class="category2">x</span>:<span class="category1">int</span>, <span class="category2">y</span>:<span class="category1">int</span>, w:<span class="category1">int</span>, cont):<span class="category1">void</span> {
 
 <span class="linecomment">// create the textLine and a mouseEvent listener</span>
 <span class="category1">var</span> tl:TextLine = tb.createTextLine (<span class="category1">null</span>, w);
 tl.<span class="category2">x</span> = <span class="category2">x</span>;
 tl.<span class="category2">y</span> = <span class="category2">y</span>;
 cont.addChild(tl);
 tl.addEventListener(MouseEvent.CLICK, showMe);
}

<span class="linecomment">// get the atom clicked by point position</span>
<span class="category1">private</span> <span class="category1">function</span> showMe(e:MouseEvent):<span class="category1">void</span> {
 <span class="category1">var</span> tl:TextLine = e.<span class="category2">target</span> as TextLine;
 <span class="category1">var</span> atom:<span class="category1">int</span> = e.<span class="category2">target</span>.getAtomIndexAtPoint(e.stageX, e.stageY);
 
 <span class="linecomment">// draw a yellow box above the atom</span>
 <span class="category1">var</span> bounds:Rectangle = tl.getAtomBounds(atom);
 box.graphics.<span class="category2">beginFill</span>(0xFFFF00, 0.4);
 box.graphics.drawRect(bounds.left, bounds.top, bounds.<span class="category2">width</span>, bounds.<span class="category2">height</span>);  
 box.graphics.<span class="category2">endFill</span>();           	
 addChild(box);
 
 <span class="linecomment">// get the atom content via the textBlock.content.text</span>
 <span class="category1">var</span> <span class="category2">index</span>:<span class="category1">int</span> = textLine.getAtomTextBlockBeginIndex(i);
 <span class="category2">trace</span>( textLine.textBlock.content.<span class="category2">text</span>.<span class="category2">charAt</span>(<span class="category2">index</span>) );
}</pre>
</code>

</div></div>

<p>The contentElement, covered earlier, can defines an event dispatcher as a <em>mirrorRegion</em> to the TextLine so that it receives events received by the TextLine. This option is helpful to add interactivity (click, mouseOver and mouseOut only). The code below uses this mechanism to make some text linkable.</p>

<p>
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">var</span> dispatcher:EventDispatcher = <span class="category1">new</span> EventDispatcher();
dispatcher.addEventListener("<span class="quote">click</span>", clickHandler);

<span class="category1">var</span> te1:TextElement = <span class="category1">new</span> TextElement("<span class="quote">Here are more of</span>", someFormat);
<span class="category1">var</span> te2:TextElement = <span class="category1">new</span> TextElement("<span class="quote">Einstein's quotes</span>", someFormat);
te2.eventMirror = dispatcher;
te2.userData = "<span class="quote">http://rescomp.stanford.edu/~cheshire/EinsteinQuotes.html</span>";

<span class="linecomment">// code here to make the TextElements as content of the TextBlock</span>
<span class="linecomment">// and create TextLines</span>

<span class="category1">private</span> <span class="category1">function</span> clickHandler(event:MouseEvent):<span class="category1">void</span> {
 <span class="category1">var</span> line:TextLine = event.<span class="category2">target</span> as TextLine;       
 <span class="category1">var</span> region:TextLineMirrorRegion = line.getMirrorRegion(dispatcher);
 selected = region.element as TextElement;
 navigateToURL(selected.userdata);
}</pre>
</code>

</div></div>

<p>The text engine doesn't provide an interface to select text as with a traditional selectable text field. The (partial) code and swf below show how to add the cut, copy and paste functionality to the TextLine using the standard key commands. If you are developing for an AIR application, storing the text cut, copied or pasted is much simpler because you can take advantage of the <em>Clipboard.setData()</em> and <em>Clipboard.getData() </em> methods.</p>

<p><a href="http://www.insideria.com/cutcopy.swf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="cutpaste.png" src="http://www.insideria.com/cutpaste.png" width="545" class="mt-image-none" style="" /></span></a><div class="apcaption">Use the standard key commands to cut, copy and paste text within and between textLines. </div></p>

<p>
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="linecomment">// Vector to store textBlock index position of selected text</span>
<span class="category1">private</span> <span class="category1">var</span> selected:Vector.&lt;<span class="category1">int</span>&gt; = <span class="category1">new</span> Vector.&lt;<span class="category1">int</span>&gt;();

<span class="linecomment">// Vector to store cut or copied text</span>
<span class="category1">private</span> <span class="category1">var</span> stored:Vector.&lt;<span class="category2">String</span>&gt; = <span class="category1">new</span> Vector.&lt;<span class="category2">String</span>&gt;();

<span class="linecomment">// displayObject used to draw red marker and blue selection</span>
<span class="category1">private</span> <span class="category1">var</span> box:Sprite = <span class="category1">new</span> Sprite();

<span class="linecomment">// store cursor position to paste text on keyCommand</span>
<span class="category1">private</span> <span class="category1">var</span> lastAtom:<span class="category1">int</span> = -1;

textLine.addEventListener(MouseEvent.MOUSE_DOWN, trackSelection);
textLine.addEventListener(MouseEvent.MOUSE_UP, stopTracking);
textLine.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);

<span class="category1">private</span> <span class="category1">function</span> trackSelection(e:MouseEvent):<span class="category1">void</span> {
 e.<span class="category2">target</span>.removeEventListener(MouseEvent.MOUSE_DOWN, trackSelection);
 
 <span class="linecomment">// clear previous selection</span>
 selected.<span class="category2">splice</span>(0, selected.<span class="category2">length</span>);
 box.graphics.<span class="category2">clear</span>();
 
 <span class="category1">var</span> tl:TextLine = e.<span class="category2">target</span> as TextLine;
 <span class="category1">var</span> atom:<span class="category1">int</span> = tl.getAtomIndexAtPoint(e.stageX, e.stageY);
 <span class="category1">var</span> bounds:Rectangle = tl.getAtomBounds(atom);
 originX = bounds.<span class="category2">x</span> + tl.<span class="category2">x</span>;
 originY = bounds.<span class="category2">y</span> + tl.<span class="category2">y</span>;
 originW = 1;
 originH = tl.<span class="category2">height</span>;
 
 <span class="linecomment">// draw a red selection marker</span>
 box.graphics.<span class="category2">lineStyle</span>(1, 0xFF0000, 1);
 box.graphics.<span class="category2">moveTo</span>(originX, originY);
 box.graphics.<span class="category2">lineTo</span>(originX, originY+originH);
 
 <span class="linecomment">// nows listen to the mouseMove</span>
 e.<span class="category2">target</span>.addEventListener(MouseEvent.MOUSE_MOVE, drawSelection);
}

<span class="category1">private</span> <span class="category1">function</span> drawSelection(e:MouseEvent):<span class="category1">void</span> {
 <span class="category1">var</span> tl:TextLine = e.<span class="category2">target</span> as TextLine;
 
 <span class="linecomment">// get atom index in the line</span>
 <span class="category1">var</span> atom:<span class="category1">int</span> = tl.getAtomIndexAtPoint(e.stageX, e.stageY);
 
 <span class="linecomment">// get atom index in the TextBlock to copy text between all lines</span>
 <span class="category1">var</span> atomT:<span class="category1">int</span> = tl.getAtomTextBlockBeginIndex(atom);
 
 <span class="linecomment">// only store the atom once</span>
 <span class="category1">if</span> (atomT == oldAtom) {
  	 <span class="category1">return</span>;
 }
 oldAtom = atomT;
 
 <span class="linecomment">// draw the blue selection based on the atom bounds and previous selection</span>
 <span class="category1">var</span> bounds:Rectangle = tl.getAtomBounds(atom);
 box.graphics.<span class="category2">clear</span>();
 box.graphics.<span class="category2">beginFill</span>(0x7FBBF3, 0.4);
 box.graphics.drawRect(originX, originY, originW+bounds.<span class="category2">width</span>, originH);
 originW = originW+bounds.<span class="category2">width</span>;
 box.graphics.<span class="category2">endFill</span>();
 
 selected.<span class="category2">push</span>(atomT);
}

<span class="category1">private</span> <span class="category1">function</span> stopTracking(e:MouseEvent):<span class="category1">void</span> {
 e.<span class="category2">target</span>.removeEventListener(MouseEvent.MOUSE_MOVE, drawSelection);
 e.<span class="category2">target</span>.addEventListener(MouseEvent.MOUSE_DOWN, trackSelection);
 
 <span class="category1">var</span> tl:TextLine = e.<span class="category2">target</span> as TextLine;
 <span class="category1">var</span> atom:<span class="category1">int</span> = tl.getAtomIndexAtPoint(e.stageX, e.stageY);
 lastAtom = tl.getAtomTextBlockBeginIndex(atom);
}

<span class="linecomment">// cut, copy or paste text</span>
<span class="category1">private</span> <span class="category1">function</span> keyDownListener(e:KeyboardEvent):<span class="category1">void</span> {
 <span class="category1">if</span> (e.ctrlKey == <span class="category1">true</span>) {
  <span class="category1">switch</span>(e.keyCode) {
   <span class="category1">case</span> 88:
   <span class="category1">if</span> (selected.<span class="category2">length</span> &gt; 0) {
    stored.<span class="category2">splice</span>(0, stored.<span class="category2">length</span>);
    <span class="category1">var</span> cutString:<span class="category2">String</span> = "<span class="quote"></span>";
    <span class="category1">for</span> (<span class="category1">var</span> i:<span class="category1">int</span> = 0; i &lt; selected.<span class="category2">length</span>; i++) {
     <span class="linecomment">// store text cut for future use</span>
     stored[i] = textBlock.content.<span class="category2">text</span>.<span class="category2">charAt</span>(selected[i]);
     cutString += textBlock.content.<span class="category2">text</span>.<span class="category2">charAt</span>(selected[i]);
    }
    <span class="category1">var</span> c:TextElement = textBlock.content as TextElement;
    <span class="linecomment">// remove text from textBlock.content</span>
    c.replaceText(selected[0], cutString.<span class="category2">length</span> + selected[0], <span class="category1">null</span>);
    createLines();
   }
   <span class="category1">break</span>;
   <span class="category1">case</span> 67 :
   <span class="category1">if</span> (selected.<span class="category2">length</span> &gt; 0) {
    stored.<span class="category2">splice</span>(0, stored.<span class="category2">length</span>);
    <span class="category1">for</span> (<span class="category1">var</span> i:<span class="category1">int</span> = 0; i &lt; selected.<span class="category2">length</span>; i++) {
     <span class="linecomment">// store text for future use</span>
     stored[i] = textBlock.content.<span class="category2">text</span>.<span class="category2">charAt</span>(selected[i]);
    }
   }
   <span class="category1">break</span>;
   <span class="category1">case</span> 86:			
   <span class="category1">if</span> (lastAtom != -1) {
    <span class="category1">var</span> pasteString:<span class="category2">String</span> = "<span class="quote"></span>";
    <span class="category1">for</span> (<span class="category1">var</span> i:<span class="category1">int</span> = 0; i &lt; stored.<span class="category2">length</span>; i++) {
     pasteString += stored[i];
    }
    <span class="category1">var</span> c:TextElement = textBlock.content as TextElement;
    <span class="linecomment">// add text to textBlock.content</span>
    c.replaceText(lastAtom, lastAtom, pasteString);
    createLines();
   }
   <span class="category1">break</span>;
   <span class="category1">default</span>:
  }
 }
}</pre>
</code>

</div>
</div>
</p>

<p>Note that the <o>dump()</i> method which prints the textLine underlining information as an XML String can be handy during development (only available in debug mode).</p>

<p><b><big>TextBlock</big></b><br>
is the factory to create one single paragraph (the algorithms for formats such as directional and line-break only work on one paragraph).</p>

<p>This is where the direction (or directions if mixed) of the text is set up <em>bidiLevel</em>, the tab offset <em>tabStops</em>, the text justified including for Asian scripts <em>textJustifier</em> and <em>EastAsianJustifier</em>. The baseline  property <em>baselineZero</em> can be the Roman baseline, its ascent or descent and for scripts such as Chinese, ideographic top, center or bottom. The lineRotation can be modified by a 90 degree increment <em>lineRotation</em> and a special screen appearance turned on <em>applyNonLinearFontScaling</em>. The <em>userData</em> property is a handy way to associate some customized data to the textBlock like the text creation date or the name of the author.</p>

<p>With all these settings, the textBlock uses its <em>content</em> to create text, one textLine at a time at a given width. For each line created, a <em>textLineCreationResult</em> of type Success, Complete or Insufficient_Width is fired. The textLines must be added to the display list independently.</p>

<p>
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="category1">private</span> <span class="category1">function</span> displayLines(tb:TextBlock, sp:Sprite, <span class="category2">width</span>:<span class="category1">int</span>):<span class="category1">void</span> {
 
 <span class="category1">var</span> prevLine:TextLine;
 <span class="category1">var</span> tl:TextLine = tb.createTextLine(prevLine, <span class="category2">width</span>);
 
 <span class="category1">while</span> (tl != <span class="category1">null</span>) {
  	tl.<span class="category2">y</span> = prevLine ? prevLine.<span class="category2">y</span>+tl.<span class="category2">height</span> : tl.ascent;
  	sp.addChild(textLine);
  	prevLine = tl;	
  	tl = tb.createTextLine(prevLine, <span class="category2">width</span>);
 }
 
}</pre>
</code>

</div>
</div>
</p>

<p>After the initial creation, if the container's width changes or if a fontDescription, a textFormat or an elementContent is modified, the lines must be "broken" again.</p>

<p><a href="http://www.insideria.com/textlayout2.swf"><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="blocks.png" src="http://www.insideria.com/blocks.png" width="545" class="mt-image-none" style="" /></span></a><div class="apcaption">This example and the (partial) code below show three different text layouts based on the dimension of the window (resize to view changes). All the values are set dynamically using the image and the lines information. Note that the image (graphicElement) becomes the child of the text line so in this example, its position is accessible via _textBlock.firstLine.</div></p>

<p>
<div class="acode" style="overflow: auto; padding: 10px;" >
<div style="overflow-x: visible;">
<code language="perl">
<pre>
<span class="linecomment">// photoW and photoH are the dimensions of the image</span>
<span class="category1">private</span> <span class="category1">var</span> offset:<span class="category1">int</span> = 13; <span class="linecomment">// offset from top left corner</span>

<span class="linecomment">// small layout</span>
<span class="category1">var</span> prevLine:TextLine;
<span class="category1">var</span> textLine:TextLine = _textBlock.createTextLine(<span class="category1">null</span>, photoW);

<span class="category1">while</span> (textLine) {
 textLine.<span class="category2">x</span> = prevLine ? textLine.ascent : offset;
 textLine.<span class="category2">y</span> = prevLine ? prevLine.<span class="category2">y</span> + textLine.<span class="category2">height</span> : offset;
 <span class="linecomment">// add a gutter to the first line below the image</span>
 <span class="category1">if</span> (textLine.previousLine == _textBlock.firstLine) {
  textLine.<span class="category2">y</span> = prevLine.<span class="category2">y</span> + textLine.<span class="category2">height</span> + photoH + margin;
 }
 
 prevLine = textLine;
 addChild(textLine);
 textLine = _textBlock.createTextLine(textLine, photoW);
}


<span class="linecomment">// medium layout</span>
<span class="category1">var</span> isSecond:<span class="category2">Boolean</span> = <span class="category1">false</span>;
<span class="category1">var</span> prevLine:TextLine;
<span class="category1">var</span> currentWidth:<span class="category2">Number</span> = photoW -margin*10;
<span class="category1">var</span> refLine:TextLine;

<span class="category1">while</span> (textLine) {
 <span class="linecomment">// lines along the side of the image</span>
 <span class="category1">if</span> (isSecond == <span class="category1">false</span>) {
  textLine.<span class="category2">x</span> = prevLine ? prevLine.<span class="category2">x</span> : 13;
  textLine.<span class="category2">y</span> = prevLine ? prevLine.<span class="category2">y</span> + textLine.<span class="category2">height</span> : 13;
  <span class="linecomment">// first line after the image</span>
  <span class="category1">if</span> (textLine.previousLine == _textBlock.firstLine) {
   textLine.<span class="category2">x</span> = prevLine.<span class="category2">x</span> + photoW + margin;
   textLine.<span class="category2">y</span> = prevLine.<span class="category2">y</span> + textLine.<span class="category2">height</span>;
  }
  <span class="linecomment">// line reaching bottom of image</span>
  <span class="category1">if</span> (textLine.<span class="category2">y</span> &gt; _textBlock.firstLine.<span class="category2">height</span> &amp;&amp; isSecond == <span class="category1">false</span>) {
   isSecond = <span class="category1">true</span>;
   currentWidth = photoW + photoW-(margin*10) + margin;
   refLine = textLine;
  }
  <span class="linecomment">// lines below the image</span>
 } <span class="category1">else</span> {
  textLine.<span class="category2">x</span> = _textBlock.firstLine.<span class="category2">x</span>;
  textLine.<span class="category2">y</span> = prevLine.<span class="category2">y</span> + textLine.<span class="category2">height</span>;
  <span class="linecomment">// add a gutter to the first line below the image</span>
  <span class="category1">if</span> (refLine == textLine.previousLine) {
   textLine.<span class="category2">y</span> = prevLine.<span class="category2">y</span> + textLine.<span class="category2">height</span>+margin/3;
  }
 }
 
 prevLine = textLine;
 addChild(textLine);
 textLine = _textBlock.createTextLine(textLine, currentWidth);
}


<span class="linecomment">// large layout</span>
<span class="category1">var</span> isThird:<span class="category2">Boolean</span> = <span class="category1">false</span>;
<span class="category1">var</span> prevLine:TextLine;
 
<span class="category1">var</span> textLine:TextLine = _textBlock.createTextLine (<span class="category1">null</span>, photoW);
<span class="category1">while</span> (textLine) {
 textLine.<span class="category2">x</span> = prevLine ? prevLine.<span class="category2">x</span> : offset;
 textLine.<span class="category2">y</span> = prevLine ? prevLine.<span class="category2">y</span> + textLine.<span class="category2">height</span> : offset;
 <span class="linecomment">// first line after the image - create a second row</span>
 <span class="category1">if</span> (textLine.previousLine == _textBlock.firstLine) {
  textLine.<span class="category2">x</span> = prevLine.<span class="category2">x</span> + photoW + margin;
 }
 
 <span class="linecomment">// create a third row</span>
 <span class="category1">if</span> (textLine.<span class="category2">y</span> &gt; _textBlock.firstLine.<span class="category2">height</span> &amp;&amp; isThird == <span class="category1">false</span>) {
  textLine.<span class="category2">y</span> = _textBlock.firstLine.nextLine.<span class="category2">y</span>;
  textLine.<span class="category2">x</span> = textLine.previousLine.<span class="category2">x</span> + textLine.previousLine.<span class="category2">width</span> + margin;
  isThird = <span class="category1">true</span>;
 }
 
 prevLine = textLine;
 addChild(textLine);
 textLine = _textBlock.createTextLine(textLine, photoW);
}      
}</pre>
</code>

</div>
</div>
</p>

<p>Thank you to Nabeel Al-Shamma, Senior Director, Engineering at Adobe, for his information on fonts and to the late Albert Einstein and Ernst Haeckel for the memorable quotes and the beautiful jellyfish drawing.</p>
<p> </p>]]>
      
    </content>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2055647</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2055647" />
    <title>Comment from fontmania on 2009-03-20</title>
    <author>
        <name>fontmania</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Seems like the new low-level API is quite complex to handle. In general, it's interesting to observe that on the one hand new tools, such as Adobe Thermo/Catalyst, are developed which are supposed to simplify things and on the other hand the engineers are opening up more and more low-level access to certain functionalities (think of the Sound API or the here mentioned Text Engine) to build more powerful applications on top of it. Some developers will probably start building libraries around the complex stuff to make things easier and quicker again. In the end, hopefully more advanced but easier to use applications are developed.<br />
Anyway, for developers, it's quite hard to keep on being up-to-date with all these new APIs, where some of them could fill up a whole book. However, if developers are too limited in their possibilities they will start complaining and requesting new language features and APIs. No end...</p>]]>
    </content>
    <published>2009-03-20T20:48:53Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2055650</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2055650" />
    <title>Comment from Veronique Brossier on 2009-03-20</title>
    <author>
        <name>Veronique Brossier</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>This article was meant to introduce the API for the ones interested in using it as is and to provide some background (text is complex for software development in general, not just for Adobe products).</p>

<p>I personally like the fact that the Adobe engineers give us access to low-level information. But I agree that is is important to also provide a framework to help make use of the API easier and accessible to all.</p>

<p>My next article will be about the Text Layout Framework which makes this API easier to use.</p>]]>
    </content>
    <published>2009-03-20T22:53:03Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2056742</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2056742" />
    <title>Comment from Likeyn on 2009-03-29</title>
    <author>
        <name>Likeyn</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Second, thank you for all these informations. I wasn't able to find such a level of concrete details about FTE anywhere else.</p>

<p>Third, I am in a hurry to read your next article about the Text Layout Framework.</p>

<p>Fourth, I also like having access to low-level information.</p>

<p>And First, please pardon me about my English level, I'm French :)</p>]]>
    </content>
    <published>2009-03-29T12:52:22Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2056752</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2056752" />
    <title>Comment from Veronique Brossier on 2009-03-29</title>
    <author>
        <name>Veronique Brossier</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Hi Likeyn,<br />
I am glad you find the article helpful.<br />
I am working on the second one.</p>

<p>Je suis francaise aussi et ton anglais est parfait!</p>]]>
    </content>
    <published>2009-03-29T15:29:20Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2057021</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2057021" />
    <title>Comment from George on 2009-04-03</title>
    <author>
        <name>George</name>
        <uri>http://www.neatfilm.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.neatfilm.com">
        <![CDATA[<p>Can I test this with Flex Builder 3?</p>

<p>I installed nightly build Flex 4.0 SDK, and try to create an ActionScript project in FB, but it seems failed to load new flash.text.engine package. Is there anything I missed?</p>

<p>I tried Flash CS4 no problem for sure. But I want to write code with FB.</p>

<p>Thanks,<br />
George</p>]]>
    </content>
    <published>2009-04-04T06:15:38Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2057038</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2057038" />
    <title>Comment from George on 2009-04-04</title>
    <author>
        <name>George</name>
        <uri>http://www.neatfilm.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.neatfilm.com">
        <![CDATA[<p>Ok, I know why, need to add player 10 playerglobal.swc manually.</p>]]>
    </content>
    <published>2009-04-04T20:17:52Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2057212</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2057212" />
    <title>Comment from Andrew on 2009-04-08</title>
    <author>
        <name>Andrew</name>
        <uri>http://www.fotagraft.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.fotagraft.com">
        <![CDATA[<p>Excellent article. Explained everything well. Some great examples that we can adapt to our own work and get started with the new Classes. I like wrapping my own frameworks around the AS3 Classes to further automate things. anyway, great job.</p>

<p> </p>]]>
    </content>
    <published>2009-04-08T21:32:25Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2057436</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2057436" />
    <title>Comment from Veronique Brossier on 2009-04-12</title>
    <author>
        <name>Veronique Brossier</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Thank you Andrew. Please post some links of your work using FTE.</p>]]>
    </content>
    <published>2009-04-13T00:19:42Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2059181</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2059181" />
    <title>Comment from Mikael Hultgren on 2009-05-09</title>
    <author>
        <name>Mikael Hultgren</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Very nice article, what would have helped tho was having the option of downloading the source code and follow along in that since some of the source code published above seems incomplete. Also the swf <a href="http://www.insideria.com/elementGroup2.swf">http://www.insideria.com/elementGroup2.swf</a> with the flick image integration shows only text and not an image.</p>]]>
    </content>
    <published>2009-05-09T09:29:20Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2059190</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2059190" />
    <title>Comment from Veronique Brossier on 2009-05-09</title>
    <author>
        <name>Veronique Brossier</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Mikael,<br />
Please read the instructions carefully on the elementGroup2.swf example. You are supposed to enter one of the words of the sentence in the text field and wait until the flickr API comes back with a matching image. Then the image will display. Note that the API is somewhat slow.</p>]]>
    </content>
    <published>2009-05-09T13:34:55Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2059191</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2059191" />
    <title>Comment from Veronique Brossier on 2009-05-09</title>
    <author>
        <name>Veronique Brossier</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Mikael,</p>

<p>Please read the instructions carefully on the elementGroup2.swf example. You are supposed to enter one of the words of the sentence in the text field and wait until the flickr API comes back with a matching image. Then the image will display. Note that the API is somewhat slow.</p>]]>
    </content>
    <published>2009-05-09T13:37:48Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2059257</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2059257" />
    <title>Comment from Mikael Hultgren on 2009-05-10</title>
    <author>
        <name>Mikael Hultgren</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Loading the elementGroup2.swf example shows no textfield to enter any text into, all it shows is the text that is preloaded. I did actually try the swf and read the instructions before posting.</p>]]>
    </content>
    <published>2009-05-10T15:06:52Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2059260</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2059260" />
    <title>Comment from Veronique Brossier on 2009-05-10</title>
    <author>
        <name>Veronique Brossier</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Thanks Mikael for the heads up. The issue seems to happen only when the movie example is loaded in a separate window or a new tab. It works properly if it is loaded in the same window.</p>]]>
    </content>
    <published>2009-05-10T16:44:15Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2059460</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2059460" />
    <title>Comment from Adrian Parr on 2009-05-12</title>
    <author>
        <name>Adrian Parr</name>
        <uri>http://www.adrianparr.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.adrianparr.com">
        <![CDATA[<p>Hi Veronique,</p>

<p>I am currently working on a project for the BBC where I am required to localise several existing instructional animations in to Arabic and Persian. I am using the Flash CS4 IDE and all the textfields that need translating are static ones.</p>

<p>Is it possible to display right-to-left text in static textfields in Flash CS4, or can it only be done using AS3 and the FTE classes?</p>

<p>Many thanks in advance,</p>

<p>Adrian</p>]]>
    </content>
    <published>2009-05-12T20:39:27Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2060403</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2060403" />
    <title>Comment from Rob McCardle on 2009-05-26</title>
    <author>
        <name>Rob McCardle</name>
        <uri>http://www.robmccardle.com</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.robmccardle.com">
        <![CDATA[<p>Thanks for the useful article. I've written a little round up called "Flash Player 10 AS3 Text Layout Engine Dynamic Selectable Embedded TTF’s" clearing a few things up and linked to you...</p>

<p><a href="http://www.robmccardle.com/wp/?p=59">http://www.robmccardle.com/wp/?p=59</a></p>

<p>Demo & source there - hope this is useful to someone,</p>

<p>Cheers,</p>

<p>Rob </p>

<p>www.robmccardle.com</p>]]>
    </content>
    <published>2009-05-26T14:27:34Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2060407</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2060407" />
    <title>Comment from Veronique Brossier on 2009-05-26</title>
    <author>
        <name>Veronique Brossier</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Hi Adrian,<br />
Sorry for the late response. Somehow I missed your post.</p>

<p>Yes you can display text right-to-left using the beta software available on the Adobe labs: <a href="http://labs.adobe.com/downloads/textlayout.html">http://labs.adobe.com/downloads/textlayout.html</a><br />
Install both the Text Layout Framework and the Text Layout Component.</p>

<p>You may choose to develop in pure ActionScript by adding the FTL library to your Flash environment. To do so, select File > Publish Settings > Flash > Settings > LibraryPath, select the swc icon and navigate to the textLayout.swc in the libs directory of your downloaded files.</p>

<p>If you install the Text Layout Component mentioned earlier, you can use in two ways. You can create an instance of the Text Layout Component and extend its functionality by adding your own code or if you don't want to do any coding, place the TextLayout component from the components panel to the stage, single-click it then select the Text Layout panel from Window > Other Panels. Select "get from Stage" to bring the component data to the panel and layout it out visually and "send to Stage" to push it back.</p>

<p>Let me know if any of this is not clear. Keep in mind that this product is still in beta so some of it may changed.</p>]]>
    </content>
    <published>2009-05-26T14:53:25Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2066204</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2066204" />
    <title>Comment from lance on 2009-06-15</title>
    <author>
        <name>lance</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Hey,</p>

<p>any ideas how to do something like StyleSheet on the Label in flex?</p>

<p>textFlow.styleSheet = "path/to/stylesheet.css"</p>

<p>If not, can you do ...?</p>

<p>If not, how do you create text styles?</p>

<p>THANKS!</p>]]>
    </content>
    <published>2009-06-15T07:16:04Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2066758</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2066758" />
    <title>Comment from web design company on 2009-06-22</title>
    <author>
        <name>web design company</name>
        <uri>http://www.vijayinfo.in</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.vijayinfo.in">
        <![CDATA[<p>your post is helpful and informative  </p>]]>
    </content>
    <published>2009-06-23T05:38:16Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2067343</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2067343" />
    <title>Comment from Ezinez on 2009-06-28</title>
    <author>
        <name>Ezinez</name>
        <uri>http://ezinez.co.cc</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://ezinez.co.cc">
        <![CDATA[<p>Wow very great scripts, lots of example, beautiful and easy to apply now.<br />
Thank for share.<br />
--------------<br />
<a href="http://ezinez.co.cc">Ezinez</a></p>]]>
    </content>
    <published>2009-06-28T11:14:25Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2067664</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2067664" />
    <title>Comment from Neil on 2009-07-02</title>
    <author>
        <name>Neil</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Hello,</p>

<p>Great article for low level knowledge, any news on your next article - Text Layout Framework</p>

<p>Thanks<br />
</p>]]>
    </content>
    <published>2009-07-02T12:55:36Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2068597</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2068597" />
    <title>Comment from Mike on 2009-07-19</title>
    <author>
        <name>Mike</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Veronique -</p>

<p>Thank you! Thank You! Thank You! I've been looking all over the place for a comprehensive explanation of the new Text Engine. This helps a lot more than anything else I've read. </p>]]>
    </content>
    <published>2009-07-19T22:44:38Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2068996</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2068996" />
    <title>Comment from A1A on 2009-07-25</title>
    <author>
        <name>A1A</name>
        <uri>http://a1article.co.cc</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://a1article.co.cc">
        <![CDATA[<p>I like the way you coding, all are very bright and easy to apply.<br />
Thank you.</p>]]>
    </content>
    <published>2009-07-25T09:21:09Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2070299</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2070299" />
    <title>Comment from barbara on 2009-08-13</title>
    <author>
        <name>barbara</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Hy,<br />
I'm having a stupid problem that i can't find a way to solve.<br />
so the thing is:<br />
I'm trying to do a dynamic text with a UIScrollBar.<br />
a can do it perfectly good except that id love to be able to put text breaks (spaces between the lines), and if a just put in a normal break nothing works any more.<br />
since it's a huge text it would be really boring to read...</p>

<p>but i just can't manage it!</p>

<p>please help me I'm getting frustrated at this!</p>

<p>thank in advanced!<br />
Barbara<br />
:)</p>]]>
    </content>
    <published>2009-08-13T11:06:19Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2092052</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2092052" />
    <title>Comment from basel on 2009-09-10</title>
    <author>
        <name>basel</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Can we render HTML using this text engine? how?</p>]]>
    </content>
    <published>2009-09-10T19:41:59Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2104524</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2104524" />
    <title>Comment from dbam on 2009-09-18</title>
    <author>
        <name>dbam</name>
        <uri>http://no.ne</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://no.ne">
        <![CDATA[<p>Veronique, thank You for this FULL_SCALE review on the new engine!</p>

<p>I'm puzzled about one thing though, and can't find appropriate reference on the topic, and i really HOPE You, or somebody reading this article can help.</p>

<p>You state in Your article: <br />
" In RenderingMode.CFF mode, instead of the standard Flash renderer, "anti-alias for animation", used for vector art, Adobe's special glyph rendering technology is applied. "</p>

<p>Does this mean, that using the new flash.text.engine one can't set the anti-alias parameters, or change the type used?<br />
How to deal with it in FTE / this special glyph rendering tech?</p>

<p>Adobe has some mystical hints "here 'n there" on their pages regarding anti-aliasing, but no real statements nor description ( as far i could see ).</p>

<p>Sorry to add "just another question" in the row...</p>

<p>Cheers,<br />
dbam</p>]]>
    </content>
    <published>2009-09-18T20:07:09Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2122600</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2122600" />
    <title>Comment from Veronique on 2009-09-30</title>
    <author>
        <name>Veronique</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>A (late) response to your questions.</p>

<p>No CSS support in FTE. Please look at the ongoing development of the Text Framework.</p>

<p>To add a break in text (not specific to FTE), use "\n" as part of your string or <br /> if using html text.</p>

<p>About the RenderingMode.CFF, the FTE offers an alternate method to rendering type. It doesn't have to do with anti-alias per say, or only, but more about the placement of the text in the context of the display (screen). The ultimate goal is to make the text look as readable and attractive as possible. If you want to think of it in the simplest form, the challenge is how to make a letter (i.e. the curve on the letter e) round and smooth on a display which only offers square pixels.</p>

<p>"Anti-alias for animation" was the name used by Macromedia when they started offering alternative endering techniques.</p>]]>
    </content>
    <published>2009-09-30T14:32:26Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.34547-comment:2122635</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.34547" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/03/flash-text-engine.html#comment-2122635" />
    <title>Comment from Anonymous on 2009-09-30</title>
    <author>
        <name>Anonymous</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>I should qualify that previous comment.<br />
There is much more to rendering that my grossly simplified example!</p>]]>
    </content>
    <published>2009-09-30T15:17:37Z</published>
  </entry>

</feed
