Flash completely dominates CSS/HTML/JS for rendering text accurately

Get Adobe Flash player

EDIT!  The SWF above is just an animation I made of two screenshots; one of Word, one of Flash text engine results.  It is 100% to make the text selectable, but this particular animation does not showcase that.

A Flash generated bit of text overlaid on top of Microsoft Word.  Every word of the paragraph matches pixel-perfect.  It’s actually rather hard to notice–when the red squiggly lines disappear, that’s when you are looking at the flash text.  When they reappear, that’s when you are looking at Word text.

 

I never thought this day would come, but go ahead and consider me a convert… 

The new flash.text.engine namespace within Flash 10 is the typographically correct way to render text for the web.  Anyone who has attempted to render a simple paragraph across multiple browsers quickly realizes how little control we as developers have over the rendering of text on the web.  Just take a look at Font Rendering Differences: Firefox vs. IE vs. Safari if this problem doesn’t resonate with you.

With flash.text.engine, persistent problems such as lack of support for custom fonts and kerning go away entirely. Pixel-perfect rending across browsers is achievable–the only question left is whether flash is acceptable to you and your Web 2.0 philosophies.

If you are still with me, then let’s explore flash.text.engine a little more deeply…

Because the new Flash text engine provides such accurate text rendering, a web application can now exert minute control over the layout of text, therefore having the capability to render formats that assume access to print-quality text rendering. For example, say we wanted to render an uploaded Microsoft Word file in a web page, with faithful reproduction of the pagination and positioning of every element in the document, as rendered by the Word application itself. If one were to inspect a Microsoft Word document, they would see that it contains information about font size, family, page margins, and the actual text contained in the document, but does not explicitly indicate on which page any element within the document falls (such as paragraphs, tables, and images). Word instead figures out pagination as it loads and renders a given document . So, your web application would have to be able to mimic the Word rendering engine to pull this off! Good luck trying to do that with only HTML, CSS, and Javascript. (to be fair, good luck trying that with any technology, but we are going to try our luck with Flex for the sake of this article).

Let’s back up a second and look at basic usage of the Flash text engine. At the heart of the text engine is the TextBlock class. It makes rendering paragraphs of a set width very straightforward.

To use it, set up the TextBlock with font information and the text to render:


var text:String = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ut odio. Curabitur faucibus, orci ut adipiscing lacinia, ipsum arcu suscipit nulla, vitae mollis sapien lectus ac nulla. Suspendisse eget massa. Fusce auctor nunc. Sed in nisl. In at dui. Nulla elementum gravida quam. Nullam scelerisque lacus ac mi."
// For our example, we'll use Times New Roman, Size 16, kerning on
var fontDescription:FontDescription = new FontDescription("Times New Roman");
var format:ElementFormat = new ElementFormat(fontDescription, 16.0); 
format.kerning = flash.text.engine.Kerning.ON;
// create a text element, which TextBlock will consume in order to begin rendering lines
var textElement:TextElement = new TextElement(text, format);
var block:TextBlock = new TextBlock(textElement, null, null, "rotate0", "roman", 0, true, null, 16.0);
// render a paragraph of the text using a width of 400px
var previousLine:TextLine = null;
while(true)
{
    var textLine:TextLine = block.createTextLine(previousLine, 400.0);
    if(textLine != null && block.textLineCreationResult == TextLineCreationResult.SUCCESS)
    {
        trace("new line of text:" + this.text.substr(textLine.textBlockBeginIndex, textLine.rawTextLength));
        // align text 100px from the left, and offset each line from the last by a factor of 1.15 * font size
        textLine.x += 100px;
        textLine.y += linePosition;
        this.addChild(textLine);
        // TextBlock uses the previous line to know where it should start in the supplied TextElement,
        // for the next call to createTextLine
        previousLine = textLine; 
    }
    else if (textLine == null && this.block.textLineCreationResult == TextLineCreationResult.COMPLETE) 
    {   
        // no more text left to render as TextLine                      
        break;
    }
}       

 
This code results in the following:

 

With that small bit of effort, a paragraph is now created which represents the string of text and accompanying font information.

 
Taking this code a bit further to account for page margins, one can, as near as I can tell, recreate perfectly a paragraph found within Word by using the flash.text.engine, as shown at the top of this post.

By specifying the same paragraph width as parsed from the Word document, same font size and family, line breaks naturally occurred in our test application exactly where they occurred within Word, creating a very promising avenue to someday displaying a Word document in a web page, without the need for any special client software.

A very trivial example project is available with build script (assumes the Flex SDK bin directory is in your path).