You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ah...@apache.org on 2018/08/02 00:44:18 UTC

[royale-asjs] 15/29: emulation for RichText

This is an automated email from the ASF dual-hosted git repository.

aharui pushed a commit to branch feature/MXRoyale
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git

commit c3320bd1f4df8103227a0116a271439cb99d3a4d
Author: Alex Harui <ah...@apache.org>
AuthorDate: Tue Jul 31 21:35:37 2018 -0700

    emulation for RichText
---
 .../src/main/resources/spark-royale-manifest.xml   |    2 +
 .../src/main/royale/spark/components/RichText.as   | 1427 ++++++++++++++++++++
 2 files changed, 1429 insertions(+)

diff --git a/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml b/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml
index 3f30fce..41218ca 100644
--- a/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml
+++ b/frameworks/projects/SparkRoyale/src/main/resources/spark-royale-manifest.xml
@@ -41,6 +41,7 @@
     	<component id="RectangularDropShadow" class="spark.primitives.RectangularDropShadow"/>
     	<component id="Range" class="spark.components.supportClasses.Range"/>
     	<component id="RichEditableText" class="spark.components.RichEditableText"/>
+        <component id="RichText" class="spark.components.RichText"/>
 	<component id="Skin" class="spark.components.supportClasses.Skin"/>
     	<component id="SkinnableComponent" class="spark.components.supportClasses.SkinnableComponent"/>
 	<component id="ToggleButton" class="spark.components.ToggleButton"/>
@@ -68,4 +69,5 @@
     	<component id="DataGroup" class="spark.components.DataGroup"/>
 	<component id="VerticalLayout" class="spark.layouts.VerticalLayout"/>
 	<component id="BitmapImage" class="spark.primitives.BitmapImage"/>
+    
 </componentPackage>
diff --git a/frameworks/projects/SparkRoyale/src/main/royale/spark/components/RichText.as b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/RichText.as
new file mode 100644
index 0000000..5292fd0
--- /dev/null
+++ b/frameworks/projects/SparkRoyale/src/main/royale/spark/components/RichText.as
@@ -0,0 +1,1427 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.components
+{
+/*
+import flash.display.DisplayObject;
+import flash.text.TextFormat;
+
+import flashx.textLayout.compose.ISWFContext;
+import flashx.textLayout.conversion.ConversionType;
+import flashx.textLayout.conversion.ITextExporter;
+import flashx.textLayout.conversion.ITextImporter;
+import flashx.textLayout.conversion.TextConverter;
+import flashx.textLayout.elements.Configuration;
+import flashx.textLayout.elements.GlobalSettings;
+import flashx.textLayout.elements.TextFlow;
+import flashx.textLayout.events.DamageEvent;
+import flashx.textLayout.factory.StringTextLineFactory;
+import flashx.textLayout.factory.TextFlowTextLineFactory;
+import flashx.textLayout.factory.TextLineFactoryBase;
+import flashx.textLayout.factory.TruncationOptions;
+import flashx.textLayout.formats.ITextLayoutFormat;
+import flashx.textLayout.tlf_internal;
+
+import mx.core.IEmbeddedFontRegistry;
+import mx.core.IFlexModuleFactory;
+import mx.core.IUIComponent;
+import mx.core.Singleton;
+import mx.core.UIComponent;
+
+import spark.core.CSSTextLayoutFormat;
+import spark.core.MaskType;
+import spark.utils.MaskUtil;
+import spark.utils.TextUtil;
+
+use namespace tlf_internal
+*/
+import spark.components.supportClasses.TextBase;
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+//--------------------------------------
+//  Styles
+//--------------------------------------
+/*
+include "../styles/metadata/BasicInheritingTextStyles.as"
+include "../styles/metadata/BasicNonInheritingTextStyles.as"
+include "../styles/metadata/AdvancedInheritingTextStyles.as"
+include "../styles/metadata/AdvancedNonInheritingTextStyles.as"
+*/
+//--------------------------------------
+//  Other metadata
+//--------------------------------------
+
+[DefaultProperty("content")]
+
+//[IconFile("RichText.png")]
+
+//[DiscouragedForProfile("mobileDevice")]
+
+/**
+ *  RichText is a low-level UIComponent that can display one or more lines
+ *  of richly-formatted text and embedded images.
+ *
+ *  <p>For performance reasons, it does not support scrolling,
+ *  selection, editing, clickable hyperlinks, or images loaded from URLs.
+ *  If you need those capabilities, please see the RichEditableText
+ *  class.</p>
+ *
+ *  <p>RichText uses the Text Layout Framework (TLF) library, which in turn builds on
+ *  the Flash Text Engine (FTE) in Flash Player 10.
+ *  In combination, they provide rich text layout using
+ *  high-quality international typography.</p>
+ *
+ *  <p>The Spark architecture provides three text "primitives" -- 
+ *  Label, RichText, and RichEditableText.
+ *  Label is the fastest and most lightweight
+ *  because it uses only FTE, not TLF,
+ *  but it is limited in its capabilities: no rich text,
+ *  no scrolling, no selection, and no editing.
+ *  RichText adds the ability to display rich text
+ *  with complex layout, but is still completely non-interactive.
+ *  RichEditableText is the heaviest-weight,
+ *  but offers most of what TLF can do.
+ *  You should use the lightest-weight text primitive that meets your needs.</p>
+ *
+ *  <p>RichText is similar to the MX control mx.controls.Text.
+ *  The Text control uses the older TextField class, instead of TLF,
+ *  to display text.</p>
+ *
+ *  <p>The most important differences between RichText and Text are:
+ *  <ul>
+ *    <li>RichText offers better typography, better support
+ *        for international languages, and better text layout than Text.</li>
+ *    <li>RichText has an object-oriented model of what it displays,
+ *        while Text does not.</li>
+ *    <li>Text is selectable, while RichText does not support selection.</li>
+ *  </ul></p>
+ *
+ *  <p>RichText uses TLF's object-oriented model of rich text,
+ *  in which text layout elements such as divisions, paragraphs, spans,
+ *  and images are represented at runtime by ActionScript objects
+ *  which can be programmatically accessed and manipulated.
+ *  The central object in TLF for representing rich text is a
+ *  TextFlow, and you specify what RichText should display
+ *  by setting its <code>textFlow</code> property to a TextFlow instance.
+ *  (Please see the description of the <code>textFlow</code>
+ *  property for information about how to create one.)
+ *  You can also set the <code>text</code> property that
+ *  is inherited from TextBase, but if you don't need
+ *  the richness of a TextFlow, you should consider using
+ *  Label instead.</p>
+ *
+ *  <p>At compile time, you can put TLF markup tags inside
+ *  the RichText tag, as the following example shows:
+ *  <pre>
+ *  &lt;s:RichText&gt;Hello &lt;s:span fontWeight="bold"&gt;World!&lt;/s:span&gt;&lt;/s:RichText&gt;
+ *  </pre>
+ *  In this case, the MXML compiler sets the <code>content</code>
+ *  property, causing a TextFlow to be automatically created
+ *  from the FlowElements that you specify.</p>
+ *
+ *  <p>The default text formatting is determined by CSS styles
+ *  such as <code>fontFamily</code>, <code>fontSize</code>.
+ *  Any formatting information in the TextFlow overrides
+ *  the default formatting provided by the CSS styles.</p>
+ *
+ *  <p>You can control the spacing between lines with the
+ *  <code>lineHeight</code> style and the spacing between
+ *  paragraphs with the <code>paragraphSpaceBefore</code>
+ *  and <code>paragraphSpaceAfter</code> styles.
+ *  You can align or justify the text using the <code>textAlign</code>
+ *  and <code>textAlignLast</code> styles.
+ *  You can inset the text from the component's edges using the
+ *  <code>paddingLeft</code>, <code>paddingTop</code>, 
+ *  <code>paddingRight</code>, and <code>paddingBottom</code> styles.</p>
+ *
+ *  <p>If you don't specify any kind of width for a RichText,
+ *  then the longest line, as determined by these explicit line breaks,
+ *  determines the width of the Label.</p>
+ *
+ *  <p>When you specify a width, the text wraps at the right
+ *  edge of the component and the text is clipped when there is more
+ *  text than fits.
+ *  If you set the <code>lineBreak</code> style to <code>explicit</code>,
+ *  new lines will start only at explicit lines breaks, such as
+ *  if you use CR (<code>\r</code>), LF (<code>\n</code>),
+ *  or CR+LF (<code>\r\n</code>) in <code>text</code>
+ *  or if you use <code>&lt;p&gt;</code> and <code>&lt;br/&gt;</code>
+ *  in TLF markup. In that case, lines that are wider than the control
+ *  are clipped.</p>
+ *
+ *  <p>If you have more text than you have room to display it,
+ *  RichText can truncate the text for you.
+ *  Truncating text means replacing excess text
+ *  with a truncation indicator such as "...".
+ *  See the inherited properties <code>maxDisplayedLines</code>
+ *  and <code>isTruncated</code>.</p>
+ *
+ *  <p>By default,RichText has no background,
+ *  but you can draw one using the <code>backgroundColor</code>
+ *  and <code>backgroundAlpha</code> styles.
+ *  Borders are not supported.
+ *  If you need a border, or a more complicated background, use a separate
+ *  graphic element, such as a Rect, behind the RichText.</p>
+ *
+ *  <p>Because RichText uses TLF,
+ *  it supports displaying left-to-right (LTR) text such as French,
+ *  right-to-left (RTL) text such as Arabic, and bidirectional text
+ *  such as a French phrase inside of an Arabic one.
+ *  If the predominant text direction is right-to-left,
+ *  set the <code>direction</code> style to <code>rtl</code>.
+ *  The <code>textAlign</code> style defaults to <code>"start"</code>,
+ *  which makes the text left-aligned when <code>direction</code>
+ *  is <code>ltr</code> and right-aligned when <code>direction</code>
+ *  is <code>rtl</code>.
+ *  To get the opposite alignment,
+ *  set <code>textAlign</code> to <code>end</code>.</p>
+ *
+ *  <p>RichText uses TLF's StringTextFlowFactory and TextFlowTextLineFactory
+ *  classes to create one or more TextLine objects to statically display
+ *  its text.
+ *  For performance, its TextLines do not contain information
+ *  about individual glyphs; for more info, see the TextLineValidity class.</p>
+ *
+ *  <p>To use this component in a list-based component, such as a List or DataGrid, 
+ *  create an item renderer.
+ *  For information about creating an item renderer, see 
+ *  <a href="http://help.adobe.com/en_US/flex/using/WS4bebcd66a74275c3-fc6548e124e49b51c4-8000.html">
+ *  Custom Spark item renderers</a>. </p>
+ *  
+ *  @mxml
+ *
+ *  <p>The <code>&lt;s:RichText&gt;</code> tag inherits all of the tag 
+ *  attributes of its superclass and adds the following tag attributes:</p>
+ *
+ *  <pre>
+ *  &lt;s:RichText
+ *    <strong>Properties</strong>
+ *    luminosityClip="false"
+ *    luminosityInvert="false"
+ *    maskType="MaskType.CLIP"
+ *    textFlow="<i>TextFlow</i>"
+ *  /&gt;
+ *  </pre>
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ *
+ *  @see spark.components.RichEditableText
+ *  @see spark.components.Label
+ *  @see flash.text.engine.TextLineValidity
+ *  
+ *  @includeExample examples/RichTextExample.mxml
+ */
+public class RichText extends TextBase
+{
+//    include "../core/Version.as";
+
+    //--------------------------------------------------------------------------
+    //
+    //  Class variables
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    //private static var classInitialized:Boolean = false;
+    
+    /**
+     *  @private
+     *  This TLF object composes TextLines from a text String.
+     *  We use it when the 'text' property is set to a String
+     *  that doesn't contain linebreaks.
+     */
+    //private static var staticStringFactory:StringTextLineFactory;
+    
+    /**
+     *  @private
+     *  This TLF object composes TextLines from a TextFlow.
+     *  We use it when the 'textFlow' or 'content' property is set,
+     *  and when the 'text' property is set to a String
+     *  that contains linebreaks (and therefore is interpreted
+     *  as multiple paragraphs).
+     */
+    //private static var staticTextFlowFactory:TextFlowTextLineFactory;
+    
+    /**
+     *  @private
+     *  This TLF object is used to import a 'text' String
+     *  containing linebreaks to create a multiparagraph TextFlow.
+     */
+    //private static var staticPlainTextImporter:ITextImporter;
+    
+    /**
+     *  @private
+     *  This TLF object is used to export a TextFlow as plain 'text',
+     *  by walking the leaf FlowElements in the TextFlow.
+     */
+    //private static var staticPlainTextExporter:ITextExporter;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Class methods
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     *  This method initializes the static vars of this class.
+     *  Rather than calling it at static initialization time,
+     *  we call it in the constructor to do the class initialization
+     *  when the first instance is created.
+     *  (It does an immediate return if it has already run.)
+     *  By doing so, we avoid any static initialization issues
+     *  related to whether this class or the TLF classes
+     *  that it uses are initialized first.
+    private static function initClass():void
+    {
+        if (classInitialized)
+            return;
+            
+        // Set the TLF hook used for localizing runtime error messages.
+        // TLF itself has English-only messages,
+        // but higher layers like Flex can provide localized versions.
+        GlobalSettings.resourceStringFunction = TextUtil.getResourceString;
+
+        // Set the TLF hook used to specify the callback used for changing 
+        // the FontLookup based on SWFContext.  
+        GlobalSettings.resolveFontLookupFunction = TextUtil.resolveFontLookup;
+
+        // Pre-FP10.1, set default tab stops in TLF.  Without this, if there
+        // is a tab and TLF is measuring width, the tab will
+        // measure as the rest of the remaining width up to 10000.
+        GlobalSettings.enableDefaultTabStops = !Configuration.playerEnablesArgoFeatures;
+        
+        staticStringFactory = new StringTextLineFactory();
+        
+        staticTextFlowFactory = new TextFlowTextLineFactory();
+        
+        staticPlainTextImporter =
+            TextConverter.getImporter(TextConverter.PLAIN_TEXT_FORMAT);
+        
+        staticPlainTextExporter =
+            TextConverter.getExporter(TextConverter.PLAIN_TEXT_FORMAT);
+            
+        classInitialized = true;
+    }
+     */
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor. 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function RichText()
+    {
+        super();
+        
+//        initClass();
+        
+        text = "";
+    }
+     
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     *  This object determines the default text formatting used
+     *  by this component, based on its CSS styles.
+     *  It is set to null by stylesInitialized() and styleChanged(),
+     *  and recreated whenever necessary in commitProperties().
+     */
+    //private var hostFormat:ITextLayoutFormat;
+
+    /**
+     *  @private
+     *  Holds the last recorded value of the textFlow generation for _textFlow.  
+     *  Used to determine whether to return immediately from damage event if 
+     *  there have been no changes.
+     */
+    //private var lastGeneration:uint = 0;    // 0 means not set
+        
+    /**
+     *  @private
+     *  Holds the last recorded value of the module factory
+     *  used to create the font.
+     */
+    //mx_internal var embeddedFontContext:IFlexModuleFactory;
+    
+    /**
+     *  @private
+     *  Specifies whether the StringTextLineFactory
+     *  or the TextFlowTextLineFactory is used to create the TextLines.
+     *  A StringTextLineFactory is more efficient; it is used
+     *  by default to render the default text ""
+     *  and when 'text' is set to a string without linebreaks;
+     *  otherwise, a TextFlowTextLineFactory is used.
+     */
+    //private var factory:TextLineFactoryBase;
+
+    /**
+     *  @private
+     *  If true, the damage handler will return immediately.
+     */
+    //private var ignoreDamageEvent:Boolean;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  text
+    //----------------------------------
+
+    // Compiler will strip leading and trailing whitespace from text string.
+    [CollapseWhiteSpace]
+    
+    // The _text storage var is mx_internal in TextBase.
+    
+    /**
+     *  @private
+     */
+    private var textChanged:Boolean = false;
+    
+    /**
+     *  @private
+     *  Source of text: one of "text", "textFlow" or "content".* 
+     */
+    private var source:String = "";
+    
+    /**
+     *  @private
+     */
+    override public function get text():String
+    {
+        // Extracting the plaintext from a TextFlow is somewhat expensive,
+        // as it involves iterating over the leaf FlowElements in the TextFlow.
+        // Therefore we do this extraction only when necessary, namely when
+        // you first set the 'content' or the 'textFlow'
+        // (or mutate the TextFlow), and then get the 'text'.
+        /*
+        if (_text == null)
+        {
+            // If 'content' was last set,
+            // we have to first turn that into a TextFlow.
+            if (contentChanged)
+            {
+                _textFlow = createTextFlowFromContent(_content);
+                lastGeneration = _textFlow.generation;
+            }
+                    
+            // Once we have a TextFlow, we can export its plain text.
+            _text = staticPlainTextExporter.export(
+                _textFlow, ConversionType.STRING_TYPE) as String;
+        }
+        */
+        
+        return _text;
+    }
+
+    /**
+     *  @private
+     *  This will create a TextFlow with a single paragraph with a single span 
+     *  with exactly the text specified.  If there is whitespace and line 
+     *  breaks in the text, they will remain, regardless of the settings of
+     *  the lineBreak and whiteSpaceCollapse styles.
+     */
+    override public function set text(value:String):void
+    {
+        // Treat setting the 'text' to null
+        // as if it were set to the empty String
+        // (which is the default state).
+        if (value == null)
+            value = "";
+        
+        // If the most recent change to _text was caused by calling this method,
+        // then it's safe to short-cicuit in the same way that TextBase does.
+        if ((source == "text") && (value == _text))
+            return;
+        
+        // Don't return early if value is the same as _text,
+        // because _text might have been produced from setting
+        // 'textFlow' or 'content'.
+        // For example, if you set a TextFlow corresponding to
+        // "Hello <span color="OxFF0000">World</span>"
+        // and then get the 'text', it will be the String "Hello World"
+        // But if you then set the 'text' to "Hello World"
+        // this represents a change: the "World" should no longer be red.
+        
+        _text = value;
+        textChanged = true;
+        source = "text";
+        
+        /*
+        // If more than one of 'text', 'textFlow', and 'content' is set,
+        // the last one set wins.
+        textFlowChanged = false;
+        contentChanged = false;
+        
+        // If there was a textFlow remove its damage handler.
+        removeDamageHandler();
+
+        // The other two are now invalid and must be recalculated when needed.
+        _textFlow = null;
+        _content = null;
+        
+        factory = staticStringFactory;
+        
+        invalidateTextLines();
+        invalidateProperties();
+        invalidateSize();
+        invalidateDisplayList();
+        */
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  content
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the content property.
+     */
+    protected var _content:Object;
+    
+    /**
+     *  @private
+     */
+    private var contentChanged:Boolean = false;
+    
+    /**
+     *  @private
+     *  This metadata tells the MXML compiler to disable some of its default
+     *  interpretation of the value specified for the 'content' property.
+     *  Normally, for properties of type Object, it assumes that things
+     *  looking like numbers are numbers and things looking like arrays
+     *  are arrays. But <content>1</content> should generate code to set the
+     *  content to  the String "1", not the int 1, and <content>[1]</content>
+     *  should set it to the String "[1]", not the Array [ 1 ].
+     *  However, {...} continues to be interpreted as a databinding
+     *  expression, and @Resource(...), @Embed(...), etc.
+     *  as compiler directives.
+     *  Similar metadata on TLF classes causes the same rules to apply
+     *  within <p>, <span>, etc.
+     */
+    [RichTextContent]
+    
+    /**
+     *  This property is intended for use in MXML at compile time;
+     *  to get or set rich text content at runtime,
+     *  please use the <code>textFlow</code> property instead.
+     *
+     *  <p>The <code>content</code> property is the default property
+     *  for RichText, so that you can write MXML such as
+     *  <pre>
+     *  &lt;s:RichText&gt;Hello &lt;s:span fontWeight="bold"/&gt;World&lt;/s:span&gt;&lt;/s:RichText&gt;
+     *  </pre>
+     *  and have the String and SpanElement that you specify
+     *  as the content be used to create a TextFlow.</p>
+     *
+     *  <p>This property is typed as Object because you can set it to
+     *  to a String, a FlowElement, or an Array of Strings and FlowElements.
+     *  In the example above, you are specifying the content
+     *  to be a 2-element Array whose first element is the String
+     *  "Hello" and whose second element is a SpanElement with the text
+     *  "World" in boldface.</p>
+     * 
+     *  <p>No matter how you specify the content, it gets converted
+     *  into a TextFlow, and when you get this property, you will get
+     *  the resulting TextFlow.</p>
+     * 
+     *  <p>Adobe recommends using <code>textFlow</code> property
+     *  to get and set rich text content at runtime,
+     *  because it is strongly typed as a TextFlow
+     *  rather than as an Object.
+     *  A TextFlow is the canonical representation
+     *  for rich text content in the Text Layout Framework.</p>
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get content():Object
+    {
+        return textFlow;
+    }
+    
+    /**
+     *  @private
+     */   
+    public function set content(value:Object):void
+    {
+        // Treat setting the 'content' to null
+        // as if 'text' were being set to the empty String
+        // (which is the default state).
+        if (value == null)
+        {
+            text = "";
+            return;
+        }
+        
+        if (value == _content)
+            return;
+        
+        _content = value;
+        contentChanged = true;
+        source = "content";
+        
+        // If more than one of 'text', 'textFlow', and 'content' is set,
+        // the last one set wins.
+        textChanged = false;
+        textFlowChanged = false;
+        
+        // If there was a textFlow remove its damage handler.
+        //removeDamageHandler();
+
+        // The other two are now invalid and must be recalculated when needed.
+        _text = null;
+        _textFlow = null;
+        
+        /*
+        factory = staticTextFlowFactory;
+        
+        invalidateTextLines();
+        invalidateProperties();
+        invalidateSize();
+        invalidateDisplayList();
+        */
+    }
+    
+    //----------------------------------
+    //  mask
+    //----------------------------------
+    
+    /**
+     *  @private
+     */
+    //private var maskChanged:Boolean;
+       
+    /**
+     *  @private
+    override public function set mask(value:DisplayObject):void
+    {
+        if (super.mask == value)
+            return;
+        
+        var oldMask:UIComponent = super.mask as UIComponent;
+        
+        super.mask = value;      
+                
+        // If the old mask was attached by us, then we need to 
+        // undo the attachment logic        
+        if (oldMask && oldMask.$parent === this)
+        {       
+            if (oldMask.parent is UIComponent)
+                UIComponent(oldMask.parent).childRemoved(oldMask);
+            oldMask.$parent.removeChild(oldMask);
+        }     
+                
+        maskChanged = true;
+        maskTypeChanged = true;
+                
+        invalidateProperties();
+        invalidateDisplayList();
+    }
+         */
+
+    //----------------------------------
+    //  maskType
+    //----------------------------------
+    
+    /**
+     *  @private
+     *  Storage for the maskType property.
+     */
+    //private var _maskType:String = MaskType.CLIP;
+    
+    /**
+     *  @private
+     */
+    //private var maskTypeChanged:Boolean;
+    
+    [Inspectable(defaultValue="clip", enumeration="clip,alpha,luminosity")]
+
+    /**
+     *  <p>The maskType defines how the mask is applied to the component.</p> 
+     * 
+     *  <p>The possible values are <code>MaskType.CLIP</code>, <code>MaskType.ALPHA</code> and 
+     *  <code>MaskType.LUMINOSITY</code>.</p>  
+     * 
+     *  <p><strong>Clip Masking</strong></p>
+     * 
+     *  <p>When masking in clip mode, a clipping masks is reduced to 1-bit.  This means that a mask will 
+     *  not affect the opacity of a pixel in the source content; it either leaves the value unmodified, 
+     *  if the corresponding pixel in the mask is has a non-zero alpha value, or makes it fully 
+     *  transparent, if the mask pixel value has an alpha value of zero.</p>
+     * 
+     *  <p>When clip masking is used, only the actual path and shape vectors and fills defined by the
+     *  mask are used to determine the effect on the source content.  strokes and bitmap filters 
+     *  defined on the mask are ignored.  Any filled region in the mask is considered filled, and renders 
+     *  the source content.  The type and parameters of the fill is irrelevant;  a solid color fill, 
+     *  gradient fill, or bitmap fill in a mask will all render the underlying source content, regardless 
+     *  of the alpha values of the mask fill.</p>
+     *  
+     *  <p>BitmapGraphics are treated as bitmap filled rectangles when used in a clipping mask.  As a 
+     *  result, the alpha channel of the source bitmap is irrelevant when part of a mask -- the bitmap 
+     *  affects the mask in the same manner as solid filled rectangle of equivalent dimensions.</p>
+     * 
+     *  <p><strong>Alpha Masking</strong></p>
+     * 
+     *  <p>In alpha mode, the opacity of each pixel in the source content is multiplied by the opacity 
+     *  of the corresponding region of the mask.  i.e., a pixel in the source content with an opacity of 
+     *  1 that is masked by a region of opacity of .5 will have a resulting opacity of .5.  A source pixel 
+     *  with an opacity of .8 masked by a region with opacity of .5 will have a resulting opacity of .4.</p>
+     * 
+     *  <p>Conceptually, alpha masking is equivalent to rendering the transformed mask and source content 
+     *  into separate RGBA surfaces, and multiplying the alpha channel of the mask content into the alpha 
+     *  channel of the source content.  All of the mask content is rendered into its surface before 
+     *  compositing into the source content's surface. As a result, all FXG features, such as strokes, 
+     *  bitmap filters, and fill opacity will affect the final composited content.</p>
+     * 
+     *  <p>When in alpha mode, the alpha channel of any bitmap data is composited normally into the mask 
+     *  alpha channel, and will affect the final rendered content. This holds true for both BitmapGraphics 
+     *  and bitmap filled shapes and paths.</p>
+     * 
+     *  <p><strong>Luminosity Masking</strong></p>
+     * 
+     *  <p>A luminosity mask, sometimes called a 'soft mask', works very similarly to an alpha mask
+     *  except that both the opacity and RGB color value of a pixel in the source content is multiplied
+     *  by the opacity and RGB color value of the corresponding region in the mask.</p>
+     * 
+     *  <p>Conceptually, luminosity masking is equivalent to rendering the transformed mask and source content 
+     *  into separate RGBA surfaces, and multiplying the alpha channel and the RGB color value of the mask 
+     *  content into the alpha channel and RGB color value of the source content.  All of the mask content is 
+     *  rendered into its surface before compositing into the source content's surface. As a result, all FXG 
+     *  features, such as strokes, bitmap filters, and fill opacity will affect the final composited 
+     *  content.</p>
+     * 
+     *  <p>Luminosity masking is not native to Flash but is common in Adobe Creative Suite tools like Adobe 
+     *  Illustrator and Adobe Photoshop. In order to accomplish the visual effect of a luminosity mask in 
+     *  Flash-rendered content, a graphic element specifying a luminosity mask actually instantiates a shader
+     *  filter that mimics the visual look of a luminosity mask as rendered in Adobe Creative Suite tools.</p>
+     * 
+     *  <p>Objects being masked by luminosity masks can set properties to control the RGB color value and 
+     *  clipping of the mask. See the luminosityInvert and luminosityClip attributes.</p>
+     * 
+     *  @see spark.core.MaskType
+     * 
+     *  @default MaskType.CLIP
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+    public function get maskType():String
+    {
+        return _maskType;
+    }
+         */
+
+    /**
+     *  @private
+    public function set maskType(value:String):void
+    {
+        if (_maskType == value)
+            return;
+        
+        _maskType = value;
+        maskTypeChanged = true;
+        invalidateProperties();
+    }
+     */
+    
+    //----------------------------------
+    //  luminosityInvert
+    //----------------------------------
+    
+    /**
+     *  @private
+     *  Storage for the luminosityInvert property.
+     */
+    //private var _luminosityInvert:Boolean = false; 
+    
+    /**
+     *  @private
+     */
+    //private var luminositySettingsChanged:Boolean;
+
+    [Inspectable(defaultValue="false")]
+
+    /**
+     *  A property that controls the calculation of the RGB 
+     *  color value of a graphic element being masked by 
+     *  a luminosity mask. If true, the RGB color value of a  
+     *  pixel in the source content is inverted and multipled  
+     *  by the corresponding region in the mask. If false, 
+     *  the source content's pixel's RGB color value is used 
+     *  directly. 
+     * 
+     *  @default false 
+     *  @see #maskType 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+    public function get luminosityInvert():Boolean
+    {
+        return _luminosityInvert;
+    }
+     */
+    
+    /**
+     *  @private
+    public function set luminosityInvert(value:Boolean):void
+    {
+        if (_luminosityInvert == value)
+            return;
+        
+        _luminosityInvert = value;
+        luminositySettingsChanged = true; 
+    }
+     */
+    
+    //----------------------------------
+    //  luminosityClip
+    //----------------------------------
+    
+    /**
+     *  @private
+     *  Storage for the luminosityClip property.
+     */
+    //private var _luminosityClip:Boolean = false; 
+        
+    [Inspectable(defaultValue="false")]
+
+    /**
+     *  A property that controls whether the luminosity 
+     *  mask clips the masked content. This property can 
+     *  only have an effect if the graphic element has a 
+     *  mask applied to it that is of type 
+     *  <code>MaskType.LUMINOSITY</code>.  
+     * 
+     *  @default false 
+     *  @see #maskType 
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+    public function get luminosityClip():Boolean
+    {
+        return _luminosityClip;
+    }
+     */
+    
+    /**
+     *  @private
+    public function set luminosityClip(value:Boolean):void
+    {
+        if (_luminosityClip == value)
+            return;
+        
+        _luminosityClip = value;
+        luminositySettingsChanged = true; 
+    }
+     */
+    
+    //----------------------------------
+    //  textFlow
+    //----------------------------------
+    
+    /**
+     *  @private
+     *  Storage for the textFlow property.
+     */
+    private var _textFlow:String // TextFlow;
+    
+    /**
+     *  @private
+     */
+    private var textFlowChanged:Boolean = false;
+    
+    /**
+     *  The TextFlow representing the rich text displayed by this component.
+     * 
+     *  <p>A TextFlow is the most important class
+     *  in the Text Layout Framework (TLF).
+     *  It is the root of a tree of FlowElements
+     *  representing rich text content.</p>
+     *
+     *  <p>You normally create a TextFlow from TLF markup
+     *  using the <code>TextFlowUtil.importFromString()</code>
+     *  or <code>TextFlowUtil.importFromXML()</code> methods.
+     *  Alternately, you can use TLF's TextConverter class
+     *  (which can import a subset of HTML) or build a TextFlow
+     *  using methods like <code>addChild()</code> on TextFlow.</p>
+     * 
+     *  <p>Setting this property affects the <code>text</code> property
+     *  and vice versa.</p>
+     *
+     *  <p>If you set the <code>textFlow</code> and get the <code>text</code>,
+     *  the text in each paragraph will be separated by a single
+     *  LF (<code>\n</code>).</p>
+     *
+     *  <p>If you set the <code>text</code> to a String such as
+     *  <code>"Hello World"</code> and get the <code>textFlow</code>,
+     *  it will be a TextFlow containing a single ParagraphElement
+     *  with a single SpanElement.</p>
+     *
+     *  <p>If the text contains explicit line breaks --
+     *  CR (<code>\r</code>), LF (<code>\n</code>), or CR+LF (<code>\r\n</code>) --
+     *  then the content will be set to a TextFlow
+     *  which contains multiple paragraphs, each with one span.</p>
+     *
+     *  <p>To turn a TextFlow object into TLF markup,
+     *  use the markup returned from the <code>TextFlowUtil.export()</code> method.</p>
+     *
+     *  @see spark.utils.TextFlowUtil#importFromString()
+     *  @see spark.utils.TextFlowUtil#importFromXML()
+     *  @see spark.components.RichEditableText#text
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function get textFlow():String //TextFlow
+    {
+        // We might not have a valid _textFlow for two reasons:
+        // either because the 'text' was set (which is the state
+        // after construction) or because the 'content' was set.
+        if (!_textFlow)
+        {
+            /*
+            if (_content != null)
+                _textFlow = createTextFlowFromContent(_content);
+            else
+                _textFlow = staticPlainTextImporter.importToFlow(_text);
+            
+            lastGeneration = _textFlow ? _textFlow.generation : 0;
+            */
+        }
+        /*
+        _textFlow.addEventListener(DamageEvent.DAMAGE,
+                                   textFlow_damageHandler);
+              
+        // Ensure our textFlow has the most appropriate
+        // swf context associated with it.                           
+        if (_textFlow.flowComposer)
+        {
+            _textFlow.flowComposer.swfContext = 
+                ISWFContext(getEmbeddedFontContext());  
+        }                    
+        */
+        return _textFlow;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set textFlow(value:String /*TextFlow*/):void
+    {
+        // Treat setting the 'textFlow' to null
+        // as if 'text' were being set to the empty String
+        // (which is the default state).
+        if (value == null)
+        {
+            text = "";
+            return;
+        }
+        
+        if (value == _textFlow)
+            return;
+                    
+        // If there was a textFlow remove its damage handler.
+        //removeDamageHandler();
+        
+        _textFlow = value;
+        textFlowChanged = true;
+        source = "textFlow";
+        
+        // If more than one of 'text', 'textFlow', and 'content' is set,
+        // the last one set wins.
+        textChanged = false;
+        contentChanged = false;
+        
+        // The other two are now invalid and must be recalculated when needed.
+        _text = null
+        _content = null;
+        
+        /*
+        factory = staticTextFlowFactory;
+
+        invalidateTextLines();
+        invalidateProperties();
+        invalidateSize();
+        invalidateDisplayList();
+        */
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: UIComponent
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+    override protected function commitProperties():void
+    {
+        super.commitProperties();
+        
+        // Only one of textChanged, textFlowChanged, and contentChanged
+        // will be true; the other two will be false because each setter
+        // guarantees this.
+        if (textChanged)
+        {
+            // If the text has linebreaks (CR, LF, or CF+LF)
+            // create a multi-paragraph TextFlow from it
+            // and use the TextFlowTextLineFactory to render it.
+            // Otherwise the StringTextLineFactory will put
+            // all of the lines into a single paragraph
+            // and FTE performance will degrade on a large paragraph.
+            if (_text.indexOf("\n") != -1 || _text.indexOf("\r") != -1)
+            {
+                _textFlow = staticPlainTextImporter.importToFlow(_text);
+                factory = staticTextFlowFactory;
+            }
+            textChanged = false;
+        }
+        else if (textFlowChanged)
+        {
+            // Nothing to do at commitProperties() time.
+            textFlowChanged = false;
+        }
+        else if (contentChanged)
+        {
+            _textFlow = createTextFlowFromContent(_content);
+            contentChanged = false;
+        }
+    
+        lastGeneration = _textFlow ? _textFlow.generation : 0;
+        
+        // At this point we know which TextLineFactory we're going to use
+        // and we know the _text or _textFlow that it will compose.
+                    
+        // If the styles have changed, hostFormat will have
+        // been set to null to indicate that it is invalid.
+        // In that case, create a new one.
+        if (!hostFormat)
+        {
+            hostFormat = new CSSTextLayoutFormat(this);
+            // Note: CSSTextLayoutFormat has special processing
+            // for the fontLookup style. If it is "auto",
+            // the fontLookup format is set to either
+            // "device" or "embedded" depending on whether
+            // embeddedFontContext is null or non-null.
+        }
+        
+        if (_textFlow)
+        {
+            // We might have a new TextFlow, or a new hostFormat,
+            // so attach the latter to the former.
+            _textFlow.hostFormat = hostFormat;
+    
+            // Add a damage handler.
+            _textFlow.addEventListener(DamageEvent.DAMAGE, 
+                                       textFlow_damageHandler);
+        }
+        
+        if (maskChanged)
+        {
+            if (mask && !mask.parent)
+            {
+                addChild(mask);
+                MaskUtil.applyMask(mask, null);
+            }
+            maskChanged = false;            
+        }        
+        
+        if (luminositySettingsChanged)
+        {
+            MaskUtil.applyLuminositySettings(
+                mask, _maskType, _luminosityInvert, _luminosityClip);
+
+            luminositySettingsChanged = false;             
+        }
+
+        if (maskTypeChanged)
+        {
+            MaskUtil.applyMaskType(
+                mask, _maskType, _luminosityInvert, _luminosityClip, this);
+
+            maskTypeChanged = false;
+        }
+    }
+         */
+
+    /**
+     *  @private
+    override public function stylesInitialized():void
+    {
+        super.stylesInitialized();
+
+        // The old hostFormat is invalid
+        // and a new one must be created.
+        hostFormat = null;
+    }
+     */
+
+    /**
+     *  @private
+    override public function styleChanged(styleProp:String):void
+    {
+        super.styleChanged(styleProp);
+
+        // The old hostFormat is invalid
+        // and a new one must be created.
+        hostFormat = null;
+        
+        invalidateTextLines();
+        invalidateProperties();
+        invalidateSize();
+        invalidateDisplayList();
+    }
+     */
+
+    /**
+     *  @private
+    override protected function updateDisplayList(unscaledWidth:Number, 
+                                                  unscaledHeight:Number):void
+    {
+        // The factory will compose just enough lines to fill the 
+        // compositionHeight.  If not all the text is composed, the reported
+        // contentHeight will be an estimate of what the height will be when
+        // it is all composed and there will not be textLines to back it up.
+        // There is no easy way to tell if the contentHeight is the actual
+        // value or an estimated value.
+        if (!isNaN(_composeHeight) && unscaledHeight != _composeHeight)
+        {
+            invalidateTextLines();
+        }
+
+        super.updateDisplayList(unscaledWidth, unscaledHeight);
+    }    
+     */
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods: TextBase
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     *  Returns true to indicate all lines were composed.
+    override mx_internal function composeTextLines(width:Number = NaN,
+                                                   height:Number = NaN):Boolean
+    {   
+        // If there is no explicit width but there is an explicit
+        // maxWidth use that.
+        if (isNaN(width) && !isNaN(explicitMaxWidth))
+            width = explicitMaxWidth;
+        
+        super.composeTextLines(width, height);
+        
+        // Ignore damage events while we're re-composing the text lines.
+        ignoreDamageEvent = true;
+
+        // Set the composition bounds to be used by createTextLines().
+        // If there is no explicit width, and there is no explicit maxWidth,
+        // the width will be computed by this method.
+        // If the height is NaN, it will be computed by this method
+        // by the time it returns.
+        // The bounds are then used by the addTextLines() method
+        // to determine the isOverset flag.
+        // The composition bounds are also reported by the measure() method.
+        
+        bounds.x = 0;
+        bounds.y = 0;
+        bounds.width = width;
+        bounds.height = height;
+        
+        removeTextLines();
+        releaseTextLines();
+        
+        createTextLines();
+        
+        // Truncation only done if not measuring width and line breaks are
+        // toFit.  So if we are measuring, create the text lines to figure
+        // out their size and then recreate them using this size so truncation 
+        // will be done.
+        if (maxDisplayedLines != 0 && !isTruncated &&
+            getStyle("lineBreak") == "toFit")
+        {
+            var bp:String = getStyle("blockProgression");
+            if ((isNaN(width) && bp == "tb") || (isNaN(height) && bp != "tb"))
+            {
+                textLines.length = 0;
+                // bounds contains the measured size of the lines created above
+                createTextLines();
+            }
+        }
+        
+        // Add the new text lines to the container.
+        addTextLines();
+        
+        // Figure out if the text overruns the available space for composition.
+        isOverset = isTextOverset(width, height);
+        
+        // Just recomposed so reset.
+        invalidateCompose = false;
+        
+        // Listen for "damage" events in case the textFlow is 
+        // modified programatically.
+        ignoreDamageEvent = false;
+        
+        // Created all lines.
+        return true;      
+    }
+     */
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+    private function createTextFlowFromContent(content:Object):TextFlow
+    {
+        var textFlow:TextFlow ;
+        
+        if (content is TextFlow)
+        {
+            textFlow = content as TextFlow;
+        }
+        else if (content is Array)
+        {
+            textFlow = new TextFlow();
+            textFlow.whiteSpaceCollapse = getStyle("whiteSpaceCollapse");
+            textFlow.mxmlChildren = content as Array;
+            textFlow.whiteSpaceCollapse = undefined;
+        }
+        else
+        {
+            textFlow = new TextFlow();
+            textFlow.whiteSpaceCollapse = getStyle("whiteSpaceCollapse");
+            textFlow.mxmlChildren = [ content ];
+            textFlow.whiteSpaceCollapse = undefined;
+        }
+        
+        return textFlow;
+    }
+     */
+    
+    /**
+     *  @private
+     *  Uses TextLineFactory to compose the textFlow
+     *  into as many TextLines as fit into the bounds.
+    private function createTextLines():void
+    {
+        // Clear any previously generated TextLines from the textLines Array.
+        textLines.length = 0;
+        
+        // Note: Even if we have nothing to compose, we nevertheless
+        // use the StringTextLineFactory to compose an empty string.
+        // Since it appends the paragraph terminator "\u2029",
+        // it actually creates and measures one TextLine.
+        // Its width is 0 but its height is equal to the font's
+        // ascent plus descent.
+        
+        factory.compositionBounds = bounds;   
+        
+        // Set up the truncation options.
+        var truncationOptions:TruncationOptions;
+        if (maxDisplayedLines != 0)
+        {
+            truncationOptions = new TruncationOptions();
+            truncationOptions.lineCountLimit = maxDisplayedLines;
+            truncationOptions.truncationIndicator =
+                TextBase.truncationIndicatorResource;
+        }        
+        factory.truncationOptions = truncationOptions;
+        
+        // If the CSS styles for this component specify an embedded font,
+        // embeddedFontContext will be set to the module factory that
+        // should create TextLines (since they must be created in the
+        // SWF where the embedded font is). Otherwise, this will be null.
+        embeddedFontContext = getEmbeddedFontContext();
+       
+        if (factory is StringTextLineFactory)
+        {
+            // We know text is non-null since it got this far.
+            staticStringFactory.text = _text;
+            staticStringFactory.textFlowFormat = hostFormat;
+            staticStringFactory.swfContext = ISWFContext(embeddedFontContext);
+            staticStringFactory.createTextLines(addTextLine);
+        }
+        else if (factory is TextFlowTextLineFactory)
+        {
+            if (_textFlow && _textFlow.flowComposer)
+            {
+                _textFlow.flowComposer.swfContext = 
+                    ISWFContext(embeddedFontContext);
+            }
+            
+            staticTextFlowFactory.swfContext = ISWFContext(embeddedFontContext);
+            staticTextFlowFactory.createTextLines(addTextLine, _textFlow);
+        }
+        
+        bounds = factory.getContentBounds();
+        setIsTruncated(factory.isTruncated);
+    }
+     */
+
+    /**
+     *  @private
+     *  Uses StringTextLineFactory to compose an empty string so we can 
+     *  determine the baseline from the text line.  The height is important
+     *  if the text is vertically aligned.
+    override mx_internal function createEmptyTextLine(height:Number=NaN):void
+
+    {
+        // Clear any previously generated TextLines from the textLines Array.
+        textLines.length = 0;
+        
+        // Note: 
+        // Use the StringTextLineFactory to compose an empty string.
+        // Since it appends the paragraph terminator "\u2029",
+        // it actually creates and measures one TextLine.
+        // Its width is 0 but its height is equal to the font's
+        // ascent plus descent.
+        // Note:  Prior to TLF2, the factory would callback addTextLine 
+        // when width=0 but that has been optimized out.  Now width to NaN.
+        
+        bounds.x = 0;
+        bounds.y = 0;
+        bounds.width = width ? width : NaN;
+        bounds.height = height;
+        
+        staticStringFactory.compositionBounds = bounds;   
+        
+        // Set up the truncation options.
+        staticStringFactory.truncationOptions = null;
+        
+        staticStringFactory.text = "";
+        staticStringFactory.textFlowFormat = hostFormat;
+        staticStringFactory.createTextLines(addTextLine);
+    }
+     */
+
+    /**
+     *  @private
+     *  Callback passed to createTextLines().
+    private function addTextLine(textLine:DisplayObject):void
+    {
+        textLines.push(textLine);
+    }
+     */
+
+    /**
+     *  @private
+     *  Make sure to remove the damage handler before resetting the text flow.
+    private function removeDamageHandler():void
+    {
+        // Could check factory is TextFlowTextLineFactory but be safe and 
+        // try to remove whenever there is a text flow.
+        if (_textFlow != null)
+        {
+            _textFlow.removeEventListener(DamageEvent.DAMAGE,
+                textFlow_damageHandler);
+        }
+    }
+     */
+
+    //--------------------------------------------------------------------------
+    //
+    //  Event handlers
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     *  Called when the TextFlow dispatches a 'damage' event
+     *  to indicate it has been modified.  This could mean the styles changed
+     *  or the content changed, or both changed.
+    private function textFlow_damageHandler(event:DamageEvent):void
+    {
+        // If there are no changes to the generation, don't recompose.  
+        // The TextFlowFactory createTextLines dispatches damage events every 
+        // time the textFlow is composed, even if there are no changes.
+        if (ignoreDamageEvent || _textFlow.generation == lastGeneration)
+            return;
+        
+        // Update the last know generation for _textFlow.
+        lastGeneration = _textFlow.generation;
+
+        // Invalidate _text and _content.
+        _text = null;
+        _content = null;
+        
+        // After the TextFlow has been mutated,
+        // we must render it, not the 'text' String.
+        factory = staticTextFlowFactory;
+        
+        // Force recompose since text and/or styles may have changed.
+        invalidateTextLines();
+        
+        // We don't need to call invalidateProperties()
+        // because the hostFormat and the _textFlow are still valid.
+
+        // This is smart enough not to remeasure if the explicit width/height
+        // were specified.
+        invalidateSize();
+        
+        invalidateDisplayList();  
+    }    
+     */
+}
+
+}