TLF Branch 3.0 is available on SourceForge.net

TLF branch 3.0 has been posted on the source forge, http://sourceforge.net/projects/tlf.adobe/files/3.0/

There are performance improvements and new features in TLF 3.0 branch. TLF team is still working on the new features of TLF 3.0.

In the ContainerBreaks and ColumnBreaks feature, we have added a way for users to force the text to break and continue on the next column or container. There are two ways for us to choose, the attribute way and the content way. We chose the first one at last for two reasons. First, it have much better compatibility and flexibility with the CSS definition. And the second is it makes the client easier to use this feature which has no effect on the content.

The W3C also got a draft document to define the column break. We bought in some kind of their definition and expand them to be the column break and container break. We got the following attributes:

  1. ColumnBreakBefore
  2. ColumnBreakAfter
  3. ContainerBreakBefore
  4. ContainerBreakAfter

Each of the attributes can be set as following two values:

AUTO: Neither force nor forbid a container break/column break before(after) the generated box.

ALWAYS: Always force a container break/column break before(after) the generated box.

BTW, in order to fix some bugs, some API are changed in TLF 3.0,

  1. [API changed]when linebreak=”toFit”, the contentBounds will include the tailing whitespaces.
  2. [API added]add color=’red’ or [black, blue, green, gray, silver, lime, olive, white, yellow, maroon, navy, purple, teal, fuchsia, aqua, magenta, cyan] property support in paragraph element.
  3. [API added]add custom cursor support for FP10.2, users could have custom cursor by override Configuration:cursorFunction.

You can get more details from the release notes of TLF 3.0.

TLF branch 2.1 is available on SourceForge.net

TLF branch 2.1 has been posted on the source forge http://sourceforge.net/projects/tlf.adobe/files/2.1/.

 In Branch 2.1, four high servility bugs are fixed,

  1. Fix unreported crash that happens when composeToContainer is followed by updateToContainer.
  2. Fix a crash using floats, Also fixed a bug where an inline graphic was stopped, but not removed from the display list.
  3. Fix when lineBreak=”toFit” the contentBounds width does not include the trailing whitespace.
  4. Fix when the TextLine is INVALID and cannot be used to access the current state of the TextBlock.

TLF Samples Now On SourceForge

Our SourceForge site now has code and projects for TLF example applications. These were previously only posted here on the TLF blog, now there will be a samples set for every build. The “sdk” folder contains most of these examples, and they are available as a download.

The sdk folder is divided into two main sections, one for applications that only rely on TLF and the Flash Player, and one for applications that use the Flex Framework for their user interface, but otherwise call into TLF directly. The first group are in the “actionscript” folder, and the second group are in the “flex” folder.

The actionscript folder has these applications:
FTE applications FTEHelloWorld and FTEParagraph. These are very simple applications that create and display simple text content using only the Flash Player (no use of TLF).
Pagination. This application uses TLF to display a book-length text that is divided into chapters, and allows the user to page through the text, advance or backup by chapters, and resize the window.
TextLayout. This is a set of applications that use TLF, each illustrating different aspects of the framework:

  • ContextMenuText shows how to make custom context menus.
  • CustomImportMarkup shows simple import and customization using the Configuration class.
  • CustomLinkEventHandler shows how to customize clicks on links.
  • EditText shows setting up an editable text component.
  • EventMirrorExample shows setting up event handlers on group elements.
  • ExplicitFormField shows how to set up form-field style text that doesn’t wrap lines.
  • HelloWorld shows setting up a read-only text component based on static text.
  • ImportMarkup shows setting up a read-only text component based on markup.
  • InlineGraphic creates a graphic that appears inline with the text, and shows how to handle the asynchronous load process and automatic sizing.
  • LinkedContainers shows how to flow text from one container to another, for when you want a single text stream to appear in a sequence of rectangular areas.
  • LinkEventExample shows how to set up a link to send custom events.
  • MultipleColumns has a text with a headline and body text that appears in multiple columns.
  • ParagraphBorder shows how to draw an ornament around a paragraph, which requires figuring out the area on the stage that is occupied by the paragraph.
  • ParagraphBounds shows how to figure out how much vertical space is required to display a paragraph.
  • SelectText shows how to make a very simple read-only selectable text component.
  • StaticHelloWorld shows how to use the StringTextLineFactory to display some static text in a string. This is more efficient than the HelloWorld example.
  • StaticTextFlow shows how to use the TextFlowTextLineFactory to display a static TextFlow object.

The flex folder has applications that use Flex for the user interface, but call into TLF directly:

  • SimpleEditor is an editable text component with simple buttons for setting the font family, font size, text alignment,indent, line spacing, and similar attributes.
  • SimpleEditorWithCSS is similar to SimpleEditor, but it also allows setting of the styleName and id, and mapping of these with a CSS stylesheet.
  • TextLayoutEditor is a text editor that allows editing of text and almost all attributes you can set in TLF. It uses swcs that are in the other two folders, textLayout_editBar and textLayout_ui.

Building the Sample Code
The code is available as a download, but you can also build it yourself if you prefer. Each folder has a build file in it that you can run from Ant.

So try out these samples, and let us know what you think! If there are additional samples you’d like to see, please let us know what they are.

Spell Checking TLF with Squiggly

There’s a new prerelease version of the Squiggly spell checking library available on Adobe Labs. This new version of Squiggly (0.5) has support for spell checking in TLF applications. Check it out!

TLF 2.0 Changes: SubParagraphGroupElements and typeName applied to TextFieldHTMLImporter and CSSFormatResolver

Changes made to the TLF 2.0 are being used to improve theTextFieldHTML importer. First note that this importer is intended for compatibility with the TextField.htmlText property. It’s not intended to be a general purpose HTML importer.

The SubParagraphGroupElement

In TLF 1.1 and earlier There was no equivalent of HTML’s nested spans. TLF 2.0 adds the SubPargraphGroupElement (in markup <g>). SubParagraphGroupElements can be a child of a ParagraphElement, LinkElement, TCYElement or another SubParagraphGroupElement. These are useful for creating nested text elements that share some formatting.

The FlowElement typeName property

All TLF elements now have a typeName property. This property is initialized to the string used when exporting TLF markup. This table shows the default class names and default typeNames for new instances of that class. Note that typeName is a read/write property and clients may manipulate it.

DivElement div
InlineGraphicElement img
LinkElement a
ListElement list
ListItemElement li
ParagraphElement p
SpanElement span
SubParagraphGroupElement g
TabElement tab
TextFlow TextFlow

Note that TLF always converts TabElement and BreakElement elements into the tab and newline character so normally they disappear from the TextFlow and are left off this table.

HTMLImporter Changes to Support Unknown Tags

The HTML importer now preserves unrecognized element tags, for example <foo>Text</foo>, by creating a TLF element and setting its typeName to be an element of that tag. The goal of this is to allow importing of HTML with custom tags and connecting a stylesheet with typename selectors that match through an IFormatResolver. When the importer encounters an unknown tag the rule it uses is if the unknown tag has one child element that child gets its typeName set to the unknown tag. If two or more elements are created than a <div> or a <g> as the parent of the children with its typeName set.

For example :

Import this HTML:
<foo>Text<foo>
to create TLFMarkup:
<p typeName=”foo”><span>Text</span></p>

Import this HTML:
<foo><p>Hello</p>World</foo>
to create TLFMarkup:
<div typeName=”foo”><p><span>Hello</span></p><p><span>World</span></p></div>

Import this HTML:
<p><foo><b>bold</b>normal</foo></p>
to create TLFMarkup::
<p><g typeName=”foo”><span fontWeight=”bold”>bold</span><span>normal</span></g></p>

Import this HTML:
<p><foo>asdf</foo></p>
to create TLFMarkup::
<p><span typeName=”foo”>asdf</span></p>

Warning: TLF’s HTMLExporter converts all tag names to uppercase. So typeName=”foo” exports to <FOO>. The TLF markup exporter preserves case as shown above.

SubPargraphGroupElement and the HTML Importer

Previously the importer was unable to preserve nested span elements with formatting. For example:
<font size=”18″><span>Normal <font color=”#0000ff”>BLUE</font> Normal</span></font>

In 1.0 this content created 3 spans with different formatting like this:
<p><span fontSize=”18″>Normal </span><span color=”#0000ff” fontSize=”18″>BLUE</span><span fontSize=”18″> Normal</span></p>

In 2.0 this content creates a group with three span elements:
<p><g fontSize=”18″ typeName=”span”><span>Normal </span><span color=”#0000ff”>BLUE</span><span> Normal</span></g></p>

This example becomes even more interesting if the <span> is changed to a <foo> and CSS formatting is connected.

typeName and CSSFormatResolver

This can all be used to improve the connection of CSS stylesheets to a TextFlow using the IFormatResolver interface. This was originally described in an older blog post.

I’ve updated the Flex based CSSFormatResolver example to leverage the typeName property as well as including a demonstration of a styled “foo” tag. It’s attached here. Note: You will have to adjust the library paths.

For those requesting a non-Flex version of CSSFormatResolver I attached a sample here. Note: You will have to adjust the library paths.

Decoration Example

There are a lot of cases where you might want to add additional DisplayObjects to the line when it is displayed. Sometimes these are called decorations or ornaments. We got this example from one of our users, Will Lin of Silicon Publishing. Will wanted to have a bulleted list, but he needed his list to work with TLF 1.1, which doesn’t have list support. So he added a decoration to the lines that adds the bullet at the start of the paragraph. Here’s how it works.

TLF’s ContainerController class takes the TextLines generated from composition and adds them to the container. To do this, it has a function, addTextLine, that is called on each TextLine as it is added. Will made a new class, BulletsContainerController, that inherits from ContainerController and overrides the addTextLine method. For each line that is added, he checks to see if the line is at the beginning of the paragraph. If it is, he generates a new DisplayObject for the bullet and makes it a child of the TextLine.

In the main body of his application, when he creates the TextFlow, instead of adding a controller that is a ContainerController instance he adds a BulletContainerController instead.

That’s pretty much all there is to it. Thanks to Will and to Silicon Publishing for making this example public!

BulletsExample

TLF 1.0 Markup Specification

TLF_Specification_1.1

We now have a standalone specification of the Text Layout Framework markup for TLF 1.0 and TLF 1.1. This should be helpful to anyone who is trying to figure out what the XML format is for serializing and deserializing TLF text content.

TLF FlowElement LinkElement Events and EventMirrors

Examples are posted here:

LinkElements

TLF includes support for LinkElements. A LinkElement similar to an html <a> element can have a URL and respond to hover events and click events. The URL is invoked on click. The rendering of the LinkElement will change if a linkHoverFormat or linkActiveFormat is specified. This markup will turn the link red on hover and green on click:

<TextFlow version="2.0.0" xmlns="http://ns.adobe.com/textLayout/2008">
<p><a href="http://www.google.com">
<linkActiveFormat><TextLayoutFormat color="0xff00"/></linkActiveFormat>
<linkHoverFormat><TextLayoutFormat color="0xff0000"/></linkHoverFormat>
TestLink</a></p>
</TextFlow>

LinkElements and event: syntax

LinkElements can also be used to generate events on the click that a client can intercept. This is done by specifying the LinkElement.href property as "event:eventName". Client code can then attach a listener to the textFlow for eventName.

In the examples zip LinkEventExample.as demonstrates changing the color of the text when a link is clicked.

Note that if an EditManager is attached to the textFlow then LinkElements only respond if the CTRL key (on windows) or Command key (on Mac) is pressed.

EventMirrors

Several TLF elements also support event mirrors. This allows a client to attach listeners directly to FlowElements for various events defined in the FlowElementMouseEvent class. These events events are generated by TLF by observing the MouseEvents that occur over the TextLines and mapped to the FlowElements. The events that can be listened for are defined in FlowElementMouseEvent. These events are: MOUSE_DOWN, MOUSE_UP, ROLL_OVER, ROLL_OUT and CLICK. Listeners are attached by calling getEventMirror on a FlowElement with support. getEventMirror returns an IEventDispatcher on which the listener can be attached. Only the following FlowElements support getEventMirror: LinkElement, TCYElement, SubParagraphGroupElement, SpanElement and InlineGraphicElement.

In the examples zip EventMirrorExample.as file demonstrates the use of event mirrors.

Note that getEventMirror is a tlf_internal function. Event mirror support is still experimental in TLF 2.0 though there are no known bugs with dispatching events. Less well tested is how event mirrors withstand editing operations as well as cut, copy and paste. Copy, for example will not have event mirrors on the new copy. Splitting a FlowElement will only preserve the mirrors on one of the elements. Unlike the event: syntax on LinkElements event mirrors are not imported and exported in XML.

For various reasons TLF does not use FTE eventMirrors. The main one is that an eventual goal of TLF is to permit data binding to a TextFlow so that a single TextFlow can be displayed in multiple views. This event mirror architecture is a necessary step in that direction.

Padding Changes in TLF 2.0

TLF has 4 padding properties: paddingLeft, paddingRight, paddingTop and paddingBottom. In TLF 1.0 the padding properties only applied to TextFlow and ContainerController objects. The effective padding on each side of each container is the sum of the two paddings.

TLF 2.0 adds additional support for padding on DivElements, ParagraphElements, InlineGraphicElements as well as the new list related elements ListElement and ListItemElement. Each element will have a padding specified inset around it.

During import of TLF markup padding properties are ignored on these additional classes unless the attribute version="2.0.0" is specified on the TextFlow tag. The goal is that existing markup won’t render differently if padding properties were specified on elements that didn’t implement padding in 1.0.

The padding properties don’t inherit by default. If not specified they have their default value. In 1.0 and 1.1 the default value was "0". In TLF 2.0 this default value is "auto". For all elements except ListElement "auto" is interpreted as "0".

For ListElements "auto" is "0" except on the start side of the list where the value of the new listAutoPadding property is used. The default value of listAutoPadding is 40. This was done to give lists a default indent.

The following markup creates a list with the marker placed outside the box of the ListItem.

<TextFlow><list><li>First list item</li></list></TextFlow>

Without listAutoPadding the list item would have no padding and the marker would be to the left of the clip and would not be visible. TLF 2.0 applies the listAutoPadding to the start side and indents the list 40 pixels and places the outside marker in the visible area to the left side of the indentation.

Word spacing

Word spacing is a new feature that allows you to better control the how much space is left between words. In unjustified text, the space between words is set by the size of the space character in the font. Different fonts may look better with more or less space, and so the font designer specifies a preferred width for the space the font is created. But you can choose to have your text set looser or tighter by adjusting the space between the words as a percentage of what is defined in the font.

In justified text, the text is aligned on both edges to the margin, and the width of the spaces is adjusted to make this happen. Spaces may be compressed or expanded so that the text may best fit the column. Now you can control the minimum and maximum size of the spaces in justified text, as a percentage of the size of the space in the font.

The new property is called wordSpacing. It goes on paragraphs (or it can be inherited from the TextFlow, div or list that the paragraph is in) and it is an array of three percentages. The first is the desired or optimal space width. The second is the minimum space width, and the last is the maximum space width. Continue reading…