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>
+ * <s:RichText>Hello <s:span fontWeight="bold">World!</s:span></s:RichText>
+ * </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><p></code> and <code><br/></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><s:RichText></code> tag inherits all of the tag
+ * attributes of its superclass and adds the following tag attributes:</p>
+ *
+ * <pre>
+ * <s:RichText
+ * <strong>Properties</strong>
+ * luminosityClip="false"
+ * luminosityInvert="false"
+ * maskType="MaskType.CLIP"
+ * textFlow="<i>TextFlow</i>"
+ * />
+ * </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>
+ * <s:RichText>Hello <s:span fontWeight="bold"/>World</s:span></s:RichText>
+ * </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();
+ }
+ */
+}
+
+}