You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ha...@apache.org on 2017/03/16 13:37:49 UTC

[29/42] flex-asjs git commit: And here’s TLF…

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/ImportExportConfiguration.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/ImportExportConfiguration.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/ImportExportConfiguration.as
new file mode 100644
index 0000000..84d328c
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/ImportExportConfiguration.as
@@ -0,0 +1,125 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.conversion
+{
+
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.formats.WhiteSpaceCollapse;
+
+
+
+	/** 
+	 * Configure for import/export of standard components.
+	 * Configures the import/export package so it can export all the standard FlowElements.
+	 *  
+	 * @see org.apache.flex.textLayout.elements.Configuration
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class ImportExportConfiguration 
+	{
+		/** 
+		 * array of FlowElementInfo objects (key = name, value = FlowElementInfo) 
+		 * */	
+		public var flowElementInfoList:Object = {};	
+		public var flowElementClassList:Object= {};	
+		public var classToNameMap:Object = {};
+		
+		/**
+		 * Whitespace collapse export setting
+		 * @default WhiteSpaceCollapse.PRESERVE
+		 **/
+		public var whiteSpaceCollapse:String = WhiteSpaceCollapse.PRESERVE;
+
+		/** 
+		 * Constructor.
+		 * 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		 */
+		public function ImportExportConfiguration()
+		{
+		}
+		
+		/** 
+		 * Add a parser for a new FlowElement type. This allows FlowElements to be added from outside the main system,
+		 * and still have the main system be able to import them from XML.
+		 * 
+		 * @param name		the name of the FlowElement class, as it appear in the XML
+		 * @param flowClass	the class of the FlowElement
+		 * @param parser	function fpr importing the XML into a FlowElement
+		 * @param exporter  function for exporting a FlowElement into XML
+		 * @private
+		 */
+		public function addIEInfo(name:String, flowClass:Class, parser:Function, exporter:Function):void
+		{
+			var info:FlowElementInfo = new FlowElementInfo(flowClass, parser, exporter);
+			if (name)
+			{
+				CONFIG::debug { assert (lookup(name) == null, "FlowElementInfo already exists");}
+				flowElementInfoList[name] = info;
+			}
+			if (flowClass)
+			{
+				CONFIG::debug { assert (lookupByClass(info.flowClassName) == null, "FlowElementInfo already exists");}
+				flowElementClassList[info.flowClassName] = info;				
+			}
+			if (name && flowClass)
+				classToNameMap[info.flowClassName] = name;
+		}
+		
+		/** 
+		 * Return the information being held about the FlowElement, as a FlowElementInfo.
+		 * 
+		 * @param name				the name of the FlowElement class, as it appears in the XML
+		 * @return FlowElementInfo	the information being held, as it was supplied to addParseInfo
+		 * @private
+		 */
+		public function lookup(name:String):FlowElementInfo
+		{
+			return flowElementInfoList[name];
+		}
+
+		/** 
+		 * Return the element name for the class
+		 * 
+		 * @param classToMatch		fully qualified class name of the FlowElement
+		 * @return name				export name to use for class
+		 * @private
+		 */
+		public function lookupName(classToMatch:String):String
+		{
+			return classToNameMap[classToMatch];
+		}
+
+		/** 
+		 * Return the information being held about the FlowElement, as a FlowElementInfo.
+		 * 
+		 * @param classToMatch		fully qualified class name of the FlowElement
+		 * @return FlowElementInfo	the information being held, as it was supplied to addParseInfo
+		 * @private
+		 */
+		public function lookupByClass(classToMatch:String):FlowElementInfo
+		{
+			return flowElementClassList[classToMatch];
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextExporter.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextExporter.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextExporter.as
new file mode 100644
index 0000000..a746cfd
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextExporter.as
@@ -0,0 +1,142 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.conversion
+{
+	import org.apache.flex.textLayout.elements.IFlowLeafElement;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.elements.ITextFlow;
+
+	
+
+	
+	/** 
+	 * Export converter for plain text format. This class provides an alternative to
+	 * the <code>TextConverter.export()</code> static method for exporting plain text.
+	 *  The PlainTextExporter class's <code>export()</code> method results in the 
+	 * same output string as the <code>TextConverter.export()</code> static method 
+	 * if the two properties of the PlainTextExporter class, the <code>PARAGRAPH_SEPARATOR_PROPERTY</code>
+	 * and the <code>STRIP_DISCRETIONARY_HYPHENS_PROPERTY</code> properties, contain their
+	 * default values of <code>"\n"</code> and <code>true</code>, respectively.
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class PlainTextExporter extends ConverterBase implements IPlainTextExporter	
+	{
+		private var _stripDiscretionaryHyphens:Boolean;
+		private var _paragraphSeparator:String;
+		
+		static private var _discretionaryHyphen:String = String.fromCharCode(0x00AD);
+		
+
+		
+		/**
+		 * Constructor 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		public function PlainTextExporter()
+		{
+			_stripDiscretionaryHyphens = true;
+			_paragraphSeparator = "\n";
+		}
+		 
+		/** @copy IPlainTextExporter#stripDiscretionaryHyphens
+  		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0-
+		 */
+		public function get stripDiscretionaryHyphens():Boolean
+		{ return _stripDiscretionaryHyphens; }
+		public function set stripDiscretionaryHyphens(value:Boolean):void
+		{ _stripDiscretionaryHyphens = value; }
+
+		/** @copy IPlainTextExporter#paragraphSeparator
+ 		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSeparator():String
+		{ return _paragraphSeparator; }
+		public function set paragraphSeparator(value:String):void
+		{ _paragraphSeparator = value; }
+
+		/** @copy ITextExporter#export()
+		 */
+		public function export(source:ITextFlow, conversionType:String):Object
+		{
+			clear();
+			if (conversionType == ConversionType.STRING_TYPE)
+				return exportToString(source);
+			return null;
+		}
+		
+		/** Export text content as a string
+		 * @param source	the text to export
+		 * @return String	the exported content
+		 * 
+  		 * @private
+		 */
+		protected function exportToString(source:ITextFlow):String
+		{
+			var rslt:String = "";
+			var leaf:IFlowLeafElement = source.getFirstLeaf(); 
+			
+			while (leaf)
+			{
+            	var p:IParagraphElement = leaf.getParagraph();
+            	while (true)
+            	{
+            		var curString:String = leaf.text;
+            		
+            		//split out discretionary hyphen and put string back together
+            		if (_stripDiscretionaryHyphens)
+            		{
+						var temparray:Array = curString.split(_discretionaryHyphen);
+						curString = temparray.join("");
+            		}
+					
+	               	rslt += curString;
+					var nextLeaf:IFlowLeafElement = leaf.getNextLeaf(p);
+					if (!nextLeaf)
+						break; // end of para
+					
+					leaf = nextLeaf;
+            	}
+            	
+            	leaf = leaf.getNextLeaf();
+            	if (leaf) // not the last para
+                   	rslt += _paragraphSeparator; 
+   			}
+			
+			if (useClipboardAnnotations)
+			{
+				// Append a final paragraph separator if the last paragraph is not marked as a partial element
+				var lastPara:IParagraphElement = source.getLastLeaf().getParagraph();
+				if (lastPara.getStyle(ConversionConstants.MERGE_TO_NEXT_ON_PASTE) != "true")
+					rslt += _paragraphSeparator;
+				
+			}
+   			return rslt;
+		}
+	}
+		
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextImporter.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextImporter.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextImporter.as
new file mode 100644
index 0000000..b98c43d
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/PlainTextImporter.as
@@ -0,0 +1,116 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.conversion {
+	import org.apache.flex.textLayout.factory.TLFFactory;
+	import org.apache.flex.textLayout.elements.IFlowLeafElement;
+	import org.apache.flex.textLayout.elements.IConfiguration;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.elements.ISpanElement;
+	import org.apache.flex.textLayout.elements.TextFlow;
+	import org.apache.flex.textLayout.elements.ITextFlow;
+	import org.apache.flex.textLayout.elements.ElementHelper;
+
+
+	// import container.TextFrame;
+	
+
+
+	// [ExcludeClass]
+	/** 
+	 * @private
+	 * PlainText import converter. Use this to import simple unformatted Unicode text.
+	 * Newlines will be converted to paragraphs. Using the PlainTextImporter directly
+	 * is equivalent to calling TextConverter.importToFlow(TextConverter.PLAIN_TEXT_FORMAT).
+	 */
+	internal class PlainTextImporter extends ConverterBase implements ITextImporter
+	{
+		protected var _config:IConfiguration = null;
+		
+		/** Constructor */
+		public function PlainTextImporter()
+		{
+		}
+		
+		/** @copy ITextImporter#importToFlow()
+		 */
+		public function importToFlow(source:Object):ITextFlow
+		{
+			if (source is String)
+				return importFromString(String(source));
+			return null;
+		}
+		
+		/**
+		 * The <code>configuration</code> property contains the IConfiguration instance that
+		 * the importerd needs when creating new ITextFlow instances. This property
+		 * is initially set to <code>null</code>.
+		 * @see ITextFlow constructor
+		 * @playerversion Flash 10.2
+		 * @playerversion AIR 2.0
+		 * @langversion 3.0
+		 */
+		public function get configuration():IConfiguration
+		{
+			return _config;
+		}
+		
+		public function set configuration(value:IConfiguration):void
+		{
+			_config = value;
+		}
+		
+		
+		// LF or CR or CR+LF. Equivalently, LF or CR, the latter optionally followed by LF
+//TODO regex
+		private static const _newLineRegex:RegExp = /foo/;// /\u000A|\u000D\u000A?/g;
+		// private static const _newLineRegex:RegExp = /\u000A|\u000D\u000A?/g;
+		
+		/** Import text content, from an external source, and convert it into a ITextFlow.
+		 * @param source		source data to convert
+		 * @return textFlows[]	an array of ITextFlow objects that were created from the source.
+		 */
+		protected function importFromString(source:String):ITextFlow
+		{
+			var paragraphStrings:Array = source.split(_newLineRegex);
+
+			var textFlow:ITextFlow = new TextFlow(TLFFactory.defaultTLFFactory,_config);
+			var paraText:String;
+			for each (paraText in paragraphStrings)
+			{
+				var paragraph:IParagraphElement  = ElementHelper.getParagraph();	// No PMD
+				var span:ISpanElement = ElementHelper.getSpan();	// No PMD
+				span.replaceText(0, 0, paraText);
+				paragraph.replaceChildren(0, 0, span);			
+				textFlow.replaceChildren(textFlow.numChildren, textFlow.numChildren, paragraph);
+			}
+
+			// Mark partial last paragraph (string doesn't end in paragraph terminator)
+			if (useClipboardAnnotations && 
+				source.lastIndexOf('\u000A', source.length - 1) != source.length - 1)
+			{
+				var lastLeaf:IFlowLeafElement = textFlow.getLastLeaf();
+				lastLeaf.setStyle(ConversionConstants.MERGE_TO_NEXT_ON_PASTE, "true");
+				lastLeaf.parent.setStyle(ConversionConstants.MERGE_TO_NEXT_ON_PASTE, "true");
+				textFlow.setStyle(ConversionConstants.MERGE_TO_NEXT_ON_PASTE, "true");
+			}
+			return textFlow;			
+		}
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/SingletonAttributeImporter.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/SingletonAttributeImporter.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/SingletonAttributeImporter.as
new file mode 100644
index 0000000..e5db66b
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/SingletonAttributeImporter.as
@@ -0,0 +1,46 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.conversion
+{
+	// [ExcludeClass]
+	/**
+	 * @private  
+	 */
+	internal class SingletonAttributeImporter implements IFormatImporter
+	{
+		private var _keyToMatch:String;
+		private var _rslt:String = null;
+		
+		public function SingletonAttributeImporter(key:String)
+		{ _keyToMatch =  key; }
+		public function reset():void
+		{ _rslt = null; }
+		public function get result():Object
+		{ return _rslt; }
+		public function importOneFormat(key:String,val:String):Boolean
+		{
+			if (key == _keyToMatch)
+			{
+				_rslt = val;
+				return true;
+			}
+			return false; 
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TLFormatImporter.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TLFormatImporter.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TLFormatImporter.as
new file mode 100644
index 0000000..1a2df81
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TLFormatImporter.as
@@ -0,0 +1,65 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.conversion
+{
+	import org.apache.flex.textLayout.property.Property;
+	import org.apache.flex.textLayout.debug.assert;
+	// [ExcludeClass]
+	/**
+	 * @private  
+	 */
+	public class TLFormatImporter implements IFormatImporter
+	{
+		private var _classType:Class;
+		private var _description:Object;
+		
+		private var _rslt:Object;
+		
+		public function TLFormatImporter(classType:Class,description:Object)
+		{ 
+			_classType = classType;
+			_description = description;
+		}
+		
+		public function get classType():Class
+		{ return _classType; }
+				
+		public function reset():void
+		{ 
+			_rslt = null;
+		}
+		public function get result():Object
+		{ 
+			return _rslt; 
+		}
+		public function importOneFormat(key:String,val:String):Boolean
+		{ 
+			if (_description.hasOwnProperty(key))
+			{
+				if (_rslt == null)
+					_rslt = new _classType();
+	
+				CONFIG::debug { assert((_description[key] as Property) != null,"Bad description in TLFormatImporter"); }
+				_rslt[key] =  _description[key].setHelper(undefined,val);
+				return true;
+			}
+			return false; 
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextConverter.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextConverter.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextConverter.as
new file mode 100644
index 0000000..21c12db
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextConverter.as
@@ -0,0 +1,649 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.conversion
+{
+	import org.apache.flex.textLayout.elements.IConfiguration;
+	import org.apache.flex.textLayout.elements.ITextFlow;
+	import org.apache.flex.textLayout.elements.TextFlow;
+
+	
+
+	
+	/** 
+	 * This is the gateway class for handling import and export. It serves as a unified access point to the 
+	 * conversion functionality in the Text Layout Framework. It contains a registry for predefined as well
+	 * as user defined input and/or output converters, plus a set of conversion methods.
+	 * <p>
+	 * The format of the converted data is not predefined; user written converters are free to accept and return
+	 * any format of their choice. Common formats are strings, XML, and ByteArray instances. Converter authors 
+	 * should document which formats are supported.
+	 * </p>
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class TextConverter
+	{
+		/** 
+		 * HTML format.
+		 * Use this for importing from, or exporting to, a TextFlow using the HTML fomat.
+		 * The Text Layout Framework HTML supports a subset of the tags and attributes supported by
+		 * the TextField class in the <code>flash.text</code> package.
+		 * <p>The following table lists the HTML tags and attributes supported for the import
+		 * and export process (tags and attributes supported by TextField, but not supported by 
+		 * the Text Layout Framework are specifically described as not supported):</p>
+		 * 
+		 * 
+		 * <table class="innertable" width="640">
+		 * 
+		 * <tr>
+		 * 
+		 * <th>
+		 * Tag
+		 * </th>
+		 * 
+		 * <th>
+		 * Description
+		 * </th>
+		 * 
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Anchor tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;a&gt;</code> tag creates a hypertext link and supports the following attributes:
+		 * <ul>
+		 * 
+		 * <li>
+		 * <code>target</code>: Specifies the name of the target window where you load the page. 
+		 * Options include <code>_self</code>, <code>_blank</code>, <code>_parent</code>, and 
+		 * <code>_top</code>. The <code>_self</code> option specifies the current frame in the current window, 
+		 * <code>_blank</code> specifies a new window, <code>_parent</code> specifies the parent of the 
+		 * current frame, and <code>_top</code> specifies the top-level frame in the current window. 
+		 * </li>
+		 *
+		 * <li>
+		 * <code>href</code>: Specifies a URL. The URL can 
+		 * be either absolute or relative to the location of the SWF file that 
+		 * is loading the page. An example of an absolute reference to a URL is 
+		 * <code>http://www.adobe.com</code>; an example of a relative reference is 
+		 * <code>/index.html</code>. Absolute URLs must be prefixed with 
+		 * http://; otherwise, Flash treats them as relative URLs. 
+		 * <strong>Note: Unlike the TextField class, </strong>ActionScript <code>link</code> events 
+		 * are not supported. Neither are
+		 * <code>a:link</code>, <code>a:hover</code>, and <code>a:active</code> styles.
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Bold tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;b&gt;</code> tag renders text as bold. A bold typeface must be available for the font used.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Break tag
+		 * </td>
+		 * <td>
+		 * The <code>&lt;br&gt;</code> tag creates a line break in the text.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Font tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;font&gt;</code> tag specifies a font or list of fonts to display the text.The font tag 
+		 * supports the following attributes:
+		 * <ul>
+		 * 
+		 * <li>
+		 * <code>color</code>: Only hexadecimal color (<code>#FFFFFF</code>) values are supported. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>face</code>: Specifies the name of the font to use. As shown in the following example, 
+		 * you can specify a list of comma-delimited font names, in which case Flash Player selects the first available 
+		 * font. If the specified font is not installed on the local computer system or isn't embedded in the SWF file, 
+		 * Flash Player selects a substitute font. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>size</code>: Specifies the size of the font. You can use absolute pixel sizes, such as 16 or 18 
+		 * or relative point sizes, such as +2 or -4. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>letterspacing</code>: Specifies the tracking (manual kerning) in pixels to be applied to the right of each character. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>kerning</code>: Specifies whether kerning is enabled or disabled. A non-zero value enables kerning, while zero disables it.  
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Image tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;img&gt;</code> tag lets you embed external image files (JPEG, GIF, PNG), SWF files, and 
+		 * movie clips inside text.  
+		 * 
+		 *  <p>The <code>&lt;img&gt;</code> tag supports the following attributes: </p>
+		 * 
+		 * <ul >
+		 * 
+		 * <li>
+		 * <code>src</code>: Specifies the URL to an image or SWF file, or the linkage identifier for a movie clip 
+		 * symbol in the library. This attribute is required; all other attributes are optional. External files (JPEG, GIF, PNG, 
+		 * and SWF files) do not show until they are downloaded completely. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>width</code>: The width of the image, SWF file, or movie clip being inserted, in pixels. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>height</code>: The height of the image, SWF file, or movie clip being inserted, in pixels. 
+		 * </li>
+		 * </ul>
+		 * <p><strong>Note: </strong> Unlike the TextField class, the following attributes are not supported:
+		 * <code>align</code>, <code>hspace</code>, <code>vspace</code>,  <code>id</code>, and <code>checkPolicyFile</code>.</p>
+		 *
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Italic tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;i&gt;</code> tag displays the tagged text in italics. An italic typeface must be available 
+		 * for the font used.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * <em>List item tag</em>
+		 * </td>
+		 * 
+		 * <td>
+		 * <strong>Note: </strong> Unlike the TextField class, the List item tag is not supported.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Paragraph tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;p&gt;</code> tag creates a new paragraph. 
+		 * 
+		 * The <code>&lt;p&gt;</code> tag supports the following attributes:
+		 * <ul >
+		 * 
+		 * <li>
+		 * align: Specifies alignment of text within the paragraph; valid values are <code>left</code>, <code>right</code>, <code>justify</code>, and <code>center</code>. 
+		 * </li>
+		 * 
+		 * <li>
+		 * class: Specifies a class name that can be used for styling 
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Span tag
+		 * </td>
+		 * 
+		 * <td>
+		 * 
+		 * The <code>&lt;span&gt;</code> tag supports the following attributes:
+		 * 
+		 * <ul>
+		 * 
+		 * <li>
+		 * class: Specifies a class name that can be used for styling. While span tags are often used to set a style defined in a style sheet,
+		 * TLFTextField instances do not support style sheets. The span tag is available for TLFTextField instances to refer to a class with 
+		 * style properties.</li>
+		 * <li> You can also put properties directly in the span tag: 
+		 * <code>&lt;span fontFamily="Arial"&gt;Hi there&lt;/span&gt;</code>. However, nested span tags are not supported.
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Text format tag
+		 * </td>
+		 * 
+		 * <td>
+		 *  <p>The <code>&lt;textformat&gt;</code> tag lets you use a subset of paragraph formatting 
+		 * properties of the TextFormat class within text fields, including line leading, indentation, 
+		 * margins, and tab stops. You can combine <code>&lt;textformat&gt;</code> tags with the 
+		 * built-in HTML tags. </p>
+		 * 
+		 *  <p>The <code>&lt;textformat&gt;</code> tag has the following attributes: </p>
+		 * <ul >
+		 * 
+		 * 
+		 * <li>
+		 * <code>indent</code>: Specifies the indentation from the left margin to the first character 
+		 * in the paragraph; corresponds to <code>TextFormat.indent</code>. Both positive and negative 
+		 * numbers are acceptable. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>blockindent</code>: Specifies the indentation applied to all lines of the paragraph.
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>leftmargin</code>: Specifies the left margin of the paragraph, in points; corresponds 
+		 * to <code>TextFormat.leftMargin</code>. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>rightmargin</code>: Specifies the right margin of the paragraph, in points; corresponds 
+		 * to <code>TextFormat.rightMargin</code>. 
+		 * </li>
+		 * 
+		 * 	<li>
+		 * <code>leading</code>: Specifies the leading (line height) measured in pixels between a line's ascent and the previous line's descent
+		 * </li>
+		 * 
+		 * 	<li>
+		 * <code>tabstops</code>: Specifies a comma-separated list of tab stop positions for the paragraph. 
+		 * </li>
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Underline tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;u&gt;</code> tag underlines the tagged text.
+		 * </td>
+		 * </tr>
+		 * 
+		 * </table>
+		 * 
+		 * <p>When an unknown tag is imported the <code>textFieldHTMLFormat</code> importer will either set a single FlowElement's typeName property to that tag name
+		 * or create a DivElement or a SubParagraphGroupElement with its typeName property set to the tag name.</p>
+		 * <p>The <code>textFieldHTMLFormat</code> exporter will export <code>typeName</code> as the XML tag when it is different from the default.</p>
+		 * 
+		 * @see org.apache.flex.textLayout.elements.FlowElement#typeName
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public static const TEXT_FIELD_HTML_FORMAT:String = "textFieldHTMLFormat";
+
+		/** 
+		 * Plain text format.
+		 * Use this for creating a TextFlow from a simple, unformatted String, 
+		 * or for creating a simple, unformatted String from a TextFlow.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public static const PLAIN_TEXT_FORMAT:String = "plainTextFormat";
+
+		/** 
+		 * TextLayout Format.
+		 * Use this for importing from, or exporting to, a TextFlow using the TextLayout markup format.
+		 * Text Layout format will detect the following errors:
+		 * <ul>
+		 * <li>Unexpected namespace</li>
+		 * <li>Unknown element</li>
+		 * <li>Unknown attribute</li>
+		 * </ul>
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public static const TEXT_LAYOUT_FORMAT:String = "textLayoutFormat";
+		
+		// Descriptors - ordered list of all FormatDescriptors
+		/** @private */
+		static public var _descriptors:Array = [];
+
+		// register standard importers and exporters
+		setFormatsToDefault();
+		
+		/** @private */
+		static public function setFormatsToDefault():void	// No PMD
+		{
+			_descriptors = [];
+			addFormat(TEXT_LAYOUT_FORMAT, TextLayoutImporter, TextLayoutExporter, TEXT_LAYOUT_FORMAT);
+			addFormat(TEXT_FIELD_HTML_FORMAT, TextFieldHtmlImporter,  TextFieldHtmlExporter, null);
+			addFormat(PLAIN_TEXT_FORMAT, PlainTextImporter, PlainTextExporter, "air:text");
+		}
+		
+		/** 
+		 * Creates a TextFlow from source content in a specified format.
+		 * <p>Use one of the static constants supplied with this class, a MIME type,
+		 * to specify the <code>format</code> parameter, or use a user defined
+		 * value for user-registered importers:
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * @param source	Source content
+		 * @param format	Format of source content
+		 * @param config    IConfiguration to use when creating new TextFlows
+		 * @return TextFlow that was created from the source, or null on errors.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 */
+		public static function importToFlow(source:Object, format:String, config:IConfiguration = null):ITextFlow
+		{
+			var parser:ITextImporter = getImporter(format, config);
+			if (!parser)
+				return null;
+			parser.throwOnError = false;
+			return parser.importToFlow(source);
+		}
+		
+		/** 
+		 * Exports a TextFlow to a specified format. 
+		 * <p>Use one of the static constants supplied with this class, a MIME type,
+		 * or a user defined format for user defined exporters to specify 
+		 * the <code>format</code> parameter:
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * <p>Specify the type of the exported data in the <code>conversionType</code> parameter 
+		 * with one of the static constants supplied by the ConversionType class, or a user defined
+		 * data type for user defined exporters:
+		 * <ul>
+		 * <li>ConversionType.STRING_TYPE</li>
+		 * <li>ConversionType.XML_TYPE</li>
+		 * </ul>
+		 * </p>
+		 * 
+		 * Returns a representation of the TextFlow in the specified format, or null on errors.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 * @param source	Source content
+		 * @param format	Output format
+		 * @param conversionType	Type of exported data
+		 * @return Object	Exported form of the TextFlow, or null on errors
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 * @see org.apache.flex.textLayout.conversion.ConversionType
+		 */
+		public static function export(source:TextFlow, format:String, conversionType:String) : Object
+		{
+			var exporter:ITextExporter = getExporter(format);
+			if (!exporter)
+				return null;
+			exporter.throwOnError = false;
+			return exporter.export(source, conversionType);
+		}
+		
+		/** 
+		 * Creates and returns an import converter, which you can then use to import from a 
+		 * source string, an XML object, or any user defined data formats to a TextFlow. 
+		 * Use this method if you have many separate imports to perform, or if you want to 
+		 * handle errors during import. It is equivalent to calling 
+		 * <code>org.apache.flex.textLayout.conversion.TextConverter.importToFlow()</code>.
+		 * <p>Use one of the static constants supplied with this class
+		 * to specify the <code>format</code> parameter, a MIME type, or a user defined
+		 * data format.
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * <p>If the format has been added multiple times, the first one found will be used.</p>
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 * @param format	Format of source content. Use constants from 
+		 * 					org.apache.flex.textLayout.conversion.TextConverter.TEXT_LAYOUT_FORMAT, PLAIN_TEXT_FORMAT, TEXT_FIELD_HTML_FORMAT etc,
+		 * 					a MIME type, or a user defined format.
+		 * @param config    configuration to use during this import. null means take the current default.
+		 * 					You can also set the configuration via the <code>ITextImporter.configuration</code>
+		 * 					property.
+		 * @return ITextImporter	Text importer that can import the source data
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 */
+		public static function getImporter(format:String,config:IConfiguration =  null): ITextImporter
+		{
+			var importer:ITextImporter = null;
+			var i:int = findFormatIndex(format);
+			if (i >= 0)
+			{
+				var descriptor:FormatDescriptor = _descriptors[i];
+				if (descriptor && descriptor.importerClass)
+				{
+					importer = new descriptor.importerClass();
+					importer.configuration = config;
+				}
+			}
+			return importer;
+		}
+
+		/** 
+		 * Creates and returns an export converter, which you can then use to export from 
+		 * a TextFlow to a source string or XML object. Use this function if 
+		 * you have many separate exports to perform. It is equivalent to calling 
+		 * <code>org.apache.flex.textLayout.conversion.TextConverter.export()</code>.
+		 * <p>Use one of the static constants supplied with this class
+		 * to specify the <code>format</code> parameter:
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * <p>If the format has been added multiple times, the first one found will be used.</p>
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 * @param format	Target format for exported data
+		 * @return ITextExporter	Text exporter that can export in the specified format
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 */
+		public static function getExporter(format:String) : ITextExporter
+		{
+			var exporter:ITextExporter = null;
+			var i:int = findFormatIndex(format);
+			if (i >= 0)
+			{
+				var descriptor:FormatDescriptor = _descriptors[i];
+				if (descriptor && descriptor.exporterClass)
+					exporter = new descriptor.exporterClass();
+			}
+			return exporter;
+		}
+
+		/**
+		 * Register a new format for import/export, at the specified location.
+		 * Location can be significant for clients that have multiple 
+		 * choices for which format to use, such as when importing from the external clipboard. 
+		 * Lower numbers indicate higher priority; these converters will be tried first.
+		 * The new format may support importing and/or exporting.
+		 * If the format has already been added, then it will be present in multiple locations. The 
+		 * first one found will be used.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 * @param importClass    The import converter class to register or null
+		 * @param exportClass    The export converter class to register or null
+		 * @param format         The format string tagging the converter classes
+		 * @param clipboardFormat	The string used as the clipboard format when converting to/from the clipboard. Make this null if the format doesn't support clipboard access.
+		 */
+		public static function addFormatAt(index:int, format:String, importerClass:Class, exporterClass:Class = null, clipboardFormat:String = null):void
+		{
+			var descriptor:FormatDescriptor = new FormatDescriptor(format, importerClass, exporterClass, clipboardFormat);
+			_descriptors.splice(index, 0, descriptor);
+		}
+		
+		/**
+		 * Register a new format for import/export. The new format will be added at the end,
+		 * as the lowest priority. Location can be significant for clients that have multiple 
+		 * choices for which format to use, such as when importing from the external clipboard. 
+		 * The new format may support importing and/or exporting.
+		 * If the format has already been added, then it will be present in multiple locations. The 
+		 * first one found will be used.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 * @param importClass    The import converter class to register or null
+		 * @param exportClass    The export converter class to register or null
+		 * @param format         The format string tagging the converter classes. Formats can be any name, but must be unique. 
+		 * @param clipboardFormat	The string used as the clipboard format when converting to/from the clipboard. Make this null if the format doesn't support clipboard access.
+		 */
+		public static function addFormat(format:String, importerClass:Class, exporterClass:Class, clipboardFormat:String):void
+		{
+			addFormatAt(_descriptors.length, format, importerClass, exporterClass, clipboardFormat);
+		}
+		
+		/**
+		 * Remove the format at the index location. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 * @param index     The format to remove
+		 */
+		public static function removeFormatAt(index:int):void
+		{
+			if (index >= 0 && index < _descriptors.length)
+				_descriptors.splice(index, 1);
+		}
+
+		private static function findFormatIndex(format:String):int
+		{
+			for (var i:int = 0; i < numFormats; i++)
+			{
+				if (_descriptors[i].format == format)
+					return i;
+			}
+			return -1;
+		}
+		/**
+		 * Remove the format. 
+		 * If a format was added multiple times, only the first one found is removed.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 * @param format     The converter format string to remove
+		 */
+		public static function removeFormat(format:String):void
+		{
+			removeFormatAt(findFormatIndex(format));
+		}
+		
+		/** Returns the format name for the index'th format.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+	     */
+		public static function getFormatAt(index:int):String
+		{
+			return _descriptors[index].format;
+		}
+
+		/** Returns the FormatDescriptor for the index'th format. 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0 
+		*/
+		public static function getFormatDescriptorAt(index:int):FormatDescriptor
+		{
+			return _descriptors[index];
+		}
+	
+		/** Number of formats.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0 
+		*/
+		public static function get numFormats():int
+		{
+			return _descriptors.length;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextFieldHtmlExporter.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextFieldHtmlExporter.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextFieldHtmlExporter.as
new file mode 100644
index 0000000..2587649
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/conversion/TextFieldHtmlExporter.as
@@ -0,0 +1,580 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 org.apache.flex.textLayout.conversion
+{
+	import org.apache.flex.textLayout.elements.ListElement;
+	import org.apache.flex.textLayout.elements.IFlowGroupElement;
+	import org.apache.flex.reflection.getQualifiedClassName;
+	import org.apache.flex.text.engine.Kerning;
+	import org.apache.flex.text.engine.TabAlignment;
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.elements.BreakElement;
+	import org.apache.flex.textLayout.elements.DivElement;
+	import org.apache.flex.textLayout.elements.FlowGroupElement;
+	import org.apache.flex.textLayout.elements.IFlowElement;
+	import org.apache.flex.textLayout.elements.IFlowLeafElement;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.elements.InlineGraphicElement;
+	import org.apache.flex.textLayout.elements.LinkElement;
+	import org.apache.flex.textLayout.elements.IListElement;
+	import org.apache.flex.textLayout.elements.ListItemElement;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.elements.SpanElement;
+	import org.apache.flex.textLayout.elements.SubParagraphGroupElement;
+	import org.apache.flex.textLayout.elements.SubParagraphGroupElementBase;
+	import org.apache.flex.textLayout.elements.TCYElement;
+	import org.apache.flex.textLayout.elements.TabElement;
+	import org.apache.flex.textLayout.elements.ITextFlow;
+	import org.apache.flex.textLayout.formats.Direction;
+	import org.apache.flex.textLayout.formats.Float;
+	import org.apache.flex.textLayout.formats.FormatValue;
+	import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+	import org.apache.flex.textLayout.formats.LeadingModel;
+	import org.apache.flex.textLayout.formats.TabStopFormat;
+	import org.apache.flex.textLayout.formats.TextAlign;
+	import org.apache.flex.textLayout.formats.TextLayoutFormat;
+
+	// [ExcludeClass]
+	/** 
+	* @private
+	* Export converter for HTML format. 
+	*/
+	public class TextFieldHtmlExporter extends ConverterBase implements ITextExporter	
+	{
+		/** @private */
+		public static var _config:ImportExportConfiguration;
+		
+		public function TextFieldHtmlExporter()
+		{
+			if (!_config)
+			{
+				_config = new ImportExportConfiguration();
+				_config.addIEInfo(null, DivElement, null, exportDiv);
+				_config.addIEInfo(null, IParagraphElement, null, exportParagraph);
+				_config.addIEInfo(null, LinkElement, null, exportLink);
+				_config.addIEInfo(null, TCYElement, null, exportTCY);
+				_config.addIEInfo(null, SubParagraphGroupElement, null, exportSPGE);
+				_config.addIEInfo(null, SpanElement, null, exportSpan);
+				_config.addIEInfo(null, InlineGraphicElement, null, exportImage);
+				_config.addIEInfo(null, TabElement, null, exportTab);
+				_config.addIEInfo(null, BreakElement, null, exportBreak);
+				_config.addIEInfo(null, ListElement, null, exportList);
+				_config.addIEInfo(null, ListItemElement, null, exportListItem);
+			}
+		}
+		 
+		/** @copy ITextExporter#export()
+		 */
+		public function export(source:ITextFlow, conversionType:String):Object
+		{
+			var result:XML = exportToXML(source);
+			return conversionType == ConversionType.STRING_TYPE ? BaseTextLayoutExporter.convertXMLToString(result) : result;
+		}
+		
+		/** Export text content of a TextFlow into HTML format.
+		 * @param source	the text to export
+		 * @return XML	the exported content
+		 * @private
+		 */
+		public function exportToXML(textFlow:ITextFlow) : XML
+		{
+			var html:XML = <HTML/>;
+			
+			if (textFlow.numChildren != 0)
+			{
+				if (textFlow.getChildAt(0).typeName != "BODY")
+				{
+					var body:XML = <BODY/>;
+					html.appendChild(body);
+					exportChildren(textFlow,body);
+				}
+				else
+					exportChildren(textFlow,html);
+			}
+			
+			return html;
+		}
+		
+		/** create the XMl tag for an element. @private */
+		static public function makeTaggedTypeName(elem:IFlowElement,defaultTag:String):XML
+		{
+			if (elem.typeName == elem.defaultTypeName)
+				return <{defaultTag}/>;
+			return <{elem.typeName.toUpperCase()}/>;
+		}
+		
+		/** export styleName and id @private */
+		public static function exportStyling(elem:IFlowElement, xml:XML):void
+		{
+			if (elem.id != null)
+				xml.@id = elem.id;
+//TODO @
+			// if (elem.styleName != null)
+			// 	xml.@["class"] = elem.styleName;
+		}
+		
+		/** export FlowGroupElement children into parentXML. @private */
+		public function exportChildren(elem:IFlowGroupElement,parentXML:XML):void
+		{
+			for (var idx:int = 0; idx < elem.numChildren; idx++)
+			{
+				var child:IFlowElement = elem.getChildAt(idx);
+				exportElement(child,parentXML);
+			}
+		}
+		
+		/** Export a List @private */
+		public function exportList(list:IListElement, parentXML:XML):void
+		{
+			var xml:XML;
+			if (list.isNumberedList())
+				xml = <OL/>;
+			else
+				xml = <UL/>;
+			exportStyling(list, xml);
+			exportChildren(list, xml);
+			
+			if (list.typeName != list.defaultTypeName)
+			{
+				var typeNameXML:XML = <{list.typeName}/>;
+				typeNameXML.appendChild(xml);
+				parentXML.appendChild(typeNameXML);
+			}
+			else
+				parentXML.appendChild(xml);
+		}
+
+		
+		/** Export a ListItem @private */
+		public function exportListItem(li:ListItemElement, parentXML:XML):void
+		{
+			// WARNING: no solution for a listitem with a custom typeName - loose the typeName
+			var xml:XML = <LI/>;
+			exportStyling(li, xml);
+			exportChildren(li, xml);
+			
+			// if we've got exactly one P promote its child directly into the LI.  It causes TextField to add an extra paragraph.  Ugly.
+			var children:XMLList = xml.children();
+			if (children.length() == 1)
+			{
+				var child:XML = children[0];
+				if (child.name().localName == "P")
+				{
+					var paraChildren:XMLList = child.children();
+					if (paraChildren.length() == 1)
+					{
+						xml = <LI/>;
+						xml.appendChild(paraChildren[0]);
+					}
+				}
+			}
+			parentXML.appendChild(xml);
+		}
+		
+		/** Export a DIV element */
+		public function exportDiv(div:DivElement, parentXML:XML):void
+		{
+			var xml:XML = makeTaggedTypeName(div,"DIV");			
+			exportStyling(div, xml);
+			exportChildren(div, xml);
+			parentXML.appendChild(xml);			
+		}
+		
+		/** Export a paragraph
+		 * @private
+		 */
+		public function exportParagraph(para:IParagraphElement, parentXML:XML):void
+		{
+			// Exported as a <P/>
+			// Some paragraph-level formats (such as textAlign) are exported as attributes of <P/>, 
+			// Others (such as textIndent) are exported as attributes of the <TEXTFORMAT/> parent of <P/>
+			// Some character-level formats (such as fontSize) are exported as attributes of the <FONT/> child of <P/>
+			// Children of the IParagraphElement are nested inside the <FONT/>
+			var xml:XML = makeTaggedTypeName(para,"P");
+			exportStyling(para, xml);
+			
+			var fontXML:XML = exportFont(para.computedFormat);
+			CONFIG::debug { assert(fontXML != null, "Expect exportFont to return non-null xml if second parameter (ifDifferentFromFormat) is null"); }
+			exportSubParagraphChildren(para, fontXML);
+			nest(xml, fontXML);
+			
+			parentXML.appendChild(exportParagraphFormat(xml, para));
+		}
+		
+		/** Export a link
+		 * @private
+		 */
+		public function exportLink(link:LinkElement, parentXML:XML):void
+		{
+			// Exported as an <A/> with HREF and TARGET attributes
+			// Children of the LinkElement are nested inside the <A/>
+			// If the computed values of certain character-level formats differ from the corresponding computed values for the
+			// containing paragraph, these are exported as attributes of a <FONT/> which (in this case) parents the <A/>.
+			var xml:XML = <A/>;
+
+			if (link.href)
+				xml.@HREF= link.href;
+			if (link.target)
+				xml.@TARGET = link.target;
+			else
+			{
+				// TextField uses _self as the default target  
+				// while TLF uses null (funcionally identical to _blank). Account for this difference.
+				xml.@TARGET = "_blank";
+			}
+			exportSubParagraphElement(link, xml, parentXML);
+		}
+		
+		/** Export a tcy element
+		 * @private
+		 */
+		public function exportTCY(tcy:TCYElement, parentXML:XML):void
+		{
+			// make it a custom element - this will round trip it
+			// note if the element has a custom typeName that typeName is going to be built as a parent
+			var xml:XML = <TCY/>;
+			exportSubParagraphElement(tcy, xml, parentXML);
+		}
+		
+		
+		/** Export a SubParagraphGroupElement
+		 * @private
+		 */
+		public function exportSPGE(spge:SubParagraphGroupElement, parentXML:XML):void
+		{
+			var xml:XML = spge.typeName != spge.defaultTypeName ? <{spge.typeName}/> : <SPAN/>;
+			exportSubParagraphElement(spge, xml, parentXML, false);
+		}
+		
+		public function exportSubParagraphElement(elem:SubParagraphGroupElementBase, xml:XML, parentXML:XML, checkTypeName:Boolean=true):void
+		{
+			exportStyling(elem, xml);
+			exportSubParagraphChildren(elem, xml);
+			
+			var format:ITextLayoutFormat = elem.computedFormat;
+			var ifDifferentFromFormat:ITextLayoutFormat = elem.parent.computedFormat;
+			
+			var font:XML = exportFont(format, ifDifferentFromFormat);	
+			var childXML:XML = font ? nest(font, xml) : xml;
+			
+			if (checkTypeName && elem.typeName != elem.defaultTypeName)
+			{
+				var typeNameXML:XML = <{elem.typeName}/>;
+				typeNameXML.appendChild(childXML);
+				parentXML.appendChild(typeNameXML);				
+			}
+			else
+				parentXML.appendChild(childXML);
+		}
+		
+		/** @private */
+//TODO regex
+		static public const brRegEx:RegExp = /foo/;
+		// static public const brRegEx:RegExp = /\u2028/;
+		
+		/** Gets the xml element used to represent a character in the export format
+		 * @private
+		 */
+		static public function getSpanTextReplacementXML(ch:String):XML
+		{
+			CONFIG::debug {assert(ch == '\u2028', "Did not recognize character to be replaced with XML"); }
+			return <BR/>;
+		}
+		
+		/** Export a span
+		 * @private
+		 */
+		public function exportSpan(span:SpanElement, parentXML:XML):void
+		{
+			// Span text is exported as a text node (or text nodes delimited by <BR/> elements for any occurences of U+2028)
+			// These text nodes and <BR/> elements are optionally nested in formatting elements
+			var xml:XML  = makeTaggedTypeName(span, "SPAN"); 
+			exportStyling(span, xml);
+			BaseTextLayoutExporter.exportSpanText(xml, span, brRegEx, getSpanTextReplacementXML);
+			
+			// for brevity, do not export attribute-less <span> tags; export just their children
+			if (span.id == null && span.styleName == null && span.typeName == span.defaultTypeName)
+			{
+				var children:Object = xml.children();
+					
+				// Workaround for bug 1852072 : extraneous tags can appear around a string child added after an XML element 
+				if (children.length() == 1 && children[0].nodeKind() == "text")
+					children = xml.text()[0];
+					
+				parentXML.appendChild(exportSpanFormat(children, span));
+			}
+			else
+				parentXML.appendChild(exportSpanFormat(xml, span));
+		}
+		
+		/** Export an inline graphic
+		 * @private
+		 */
+		public function exportImage(image:InlineGraphicElement, parentXML:XML):void
+		{
+			// Exported as an <IMG/> with SRC, WIDTH, HEIGHT and ALIGN attributes
+			var xml:XML = <IMG/>;
+			exportStyling(image, xml);
+			if (image.source)
+				xml.@SRC = image.source;
+			if (image.width !== undefined && image.width != FormatValue.AUTO) 
+				xml.@WIDTH = image.width;
+			// xml.@WIDTH = image.actualWidth;
+			if (image.height !== undefined && image.height != FormatValue.AUTO) 
+				xml.@HEIGHT = image.height;
+			// xml.@HEIGHT = image.actualHeight;	
+			if (image.computedFloat != Float.NONE)
+				xml.@ALIGN = image.float;
+			
+			if (image.typeName != image.defaultTypeName)
+			{
+				var typeNameXML:XML = <{image.typeName}/>;
+				typeNameXML.appendChild(xml);
+				parentXML.appendChild(typeNameXML);
+			}
+			else
+				parentXML.appendChild(xml);
+		}
+	
+		/** Export a break
+		 * Is this ever called: BreakElements are either merged with adjacent spans or become spans? 
+		 * @private
+		 */		
+		public function exportBreak(breakElement:BreakElement,parentXML:XML):void
+		{
+			parentXML.appendChild(<BR/>);
+		}
+		
+		/** Export a tab
+		 * Is this ever called: TabElements are either merged with adjacent spans or become spans? 
+		 * @private
+		 */	
+		public function exportTab(tabElement:TabElement, parentXML:XML):void
+		{
+			// Export as a span
+			exportSpan(tabElement, parentXML);
+		}
+		
+		/** @private */
+		public function exportTextFormatAttribute (textFormatXML:XML, attrName:String, attrVal:*):XML
+		{
+			if (!textFormatXML)
+				textFormatXML = <TEXTFORMAT/>;
+
+//TODO @
+			// textFormatXML.@[attrName] = attrVal;
+			
+			return textFormatXML;	
+		}
+		
+		/** Exports the paragraph-level format for a paragraph  
+		 * @param xml xml to decorate with attributes or add nest in formatting elements
+		 * @para the paragraph
+		 * @return XML	the outermost XML element after exporting 
+		 * @private
+		 */	
+		public function exportParagraphFormat(xml:XML, para:IParagraphElement):XML
+		{	
+			var paraFormat:ITextLayoutFormat = para.computedFormat;
+			
+			var textAlignment:String;
+			switch(paraFormat.textAlign)
+			{
+				case TextAlign.START:
+					textAlignment = (paraFormat.direction == Direction.LTR) ? TextAlign.LEFT : TextAlign.RIGHT;
+					break;
+				case TextAlign.END:
+					textAlignment = (paraFormat.direction == Direction.LTR) ? TextAlign.RIGHT : TextAlign.LEFT;
+					break;
+				default:
+					textAlignment = paraFormat.textAlign;
+			}
+			xml.@ALIGN = textAlignment;
+					
+			var textFormat:XML;
+			
+			if (paraFormat.paragraphStartIndent != 0)
+				textFormat = exportTextFormatAttribute (textFormat, paraFormat.direction == Direction.LTR ? "LEFTMARGIN" : "RIGHTMARGIN", paraFormat.paragraphStartIndent);
+			
+			if (paraFormat.paragraphEndIndent != 0)
+				 textFormat = exportTextFormatAttribute (textFormat, paraFormat.direction == Direction.LTR ? "RIGHTMARGIN" : "LEFTMARGIN", paraFormat.paragraphEndIndent);
+			
+			if (paraFormat.textIndent != 0)
+				textFormat = exportTextFormatAttribute(textFormat, "INDENT", paraFormat.textIndent);
+				
+			if (paraFormat.leadingModel == LeadingModel.APPROXIMATE_TEXT_FIELD)
+			{
+				var firstLeaf:IFlowLeafElement = para.getFirstLeaf();
+				if (firstLeaf)
+				{
+					var lineHeight:Number = TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(firstLeaf.computedFormat.lineHeight,firstLeaf.getEffectiveFontSize());
+					if (lineHeight != 0)
+						textFormat = exportTextFormatAttribute(textFormat, "LEADING", lineHeight);
+				}
+			}
+			
+			var tabStops:Array = paraFormat.tabStops;
+			if (tabStops)
+			{
+				var tabStopsString:String = "";
+				for each (var tabStop:TabStopFormat in tabStops)
+				{
+					if (tabStop.alignment != TabAlignment.START)
+						break;
+					
+					if (tabStopsString.length)
+						tabStopsString += ", ";
+					
+					tabStopsString += tabStop.position;
+				}
+				
+				if (tabStopsString.length)
+					textFormat = exportTextFormatAttribute(textFormat, "TABSTOPS", tabStopsString);
+			}
+			
+			return textFormat ? nest(textFormat, xml) : xml;
+		}
+		
+		/** Exports the character-level format for a span  
+		 * @param xml xml/xmlList to nest in formatting elements
+		 * @span the span
+		 * @return XML	the outermost XML element after exporting 
+		 * @private
+		 */	
+		public function exportSpanFormat(xml:Object, span:SpanElement):Object
+		{
+			// These are optionally nested in a <FONT/> with appopriate attributes ,			 
+			
+			var format:ITextLayoutFormat = span.computedFormat;
+			var outerElement:Object = xml;
+			
+			// Nest in <B/>, <I/>, or <U/> if applicable
+			if (format.textDecoration.toString() == org.apache.flex.textLayout.formats.TextDecoration.UNDERLINE)
+				outerElement = nest (<U/>, outerElement);
+//TODO get HTML based on styles
+//			if (format.fontStyle.toString() == org.apache.flex.text.engine.FontPosture.ITALIC)
+//				outerElement = nest (<I/>, outerElement);
+//			if (format.fontWeight.toString() == org.apache.flex.text.engine.FontWeight.BOLD)
+//				outerElement = nest (<B/>, outerElement);
+				
+			// Nest in <FONT/> if the computed values of certain character-level formats 
+			// differ from the corresponding computed values for the containing parent that's exported
+			// A span can be contained in a TCY, link, or paragraph. Of these, TCY is not exported, so only
+			// check link and paragraph.
+			var exportedParent:IFlowElement = span.getParentByType("LinkElement");
+			if (!exportedParent)
+				exportedParent = span.getParagraph();
+	
+			var font:XML = exportFont(format, exportedParent.computedFormat);	
+			if (font)
+				outerElement = nest(font, outerElement);	
+
+			return outerElement;			   	
+		}	
+		
+		/** @private */
+		public function exportFontAttribute (fontXML:XML, attrName:String, attrVal:*):XML
+		{
+			if (!fontXML)
+				fontXML = <FONT/>;
+				
+//TODO @
+			// fontXML.@[attrName] = attrVal;
+			
+			return fontXML;	
+		}
+		
+		/**  
+		 * Exports certain character level formats as a <FONT/> with appropriate attributes
+		 * @param format format to export
+		 * @param ifDifferentFromFormat if non-null, a value in format is exported only if it differs from the corresponding value in ifDifferentFromFormat
+		 * @return XML	the populated XML element
+		 * @private
+		 */	
+		public function exportFont(format:ITextLayoutFormat, ifDifferentFromFormat:ITextLayoutFormat=null):XML
+		{
+			var font:XML;
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.fontFamily != format.fontFamily)
+				font = exportFontAttribute(font, "FACE", format.fontFamily);
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.fontSize != format.fontSize)
+				font = exportFontAttribute(font, "SIZE", format.fontSize);
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.color != format.color)
+			{
+				var rgb:String = format.color.toString(16);
+				while (rgb.length < 6) 
+					rgb = "0" + rgb; // pad with leading zeros
+				rgb = "#" + rgb;
+				font = exportFontAttribute(font, "COLOR", rgb);
+			}
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.trackingRight != format.trackingRight)
+				font = exportFontAttribute(font, "LETTERSPACING", format.trackingRight); 
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.kerning != format.kerning)
+				font = exportFontAttribute(font, "KERNING", format.kerning == Kerning.OFF ? "0" : "1");
+						
+			return font;				
+		}
+			
+		/** Exports the flow element by finding the appropriate exporter
+		 * @param flowElement	Element to export
+		 * @return Object	XML/XMLList for the flowElement
+		 * @private
+		 */
+		public function exportElement(flowElement:IFlowElement, parentXML:XML):void
+		{
+			var className:String = getQualifiedClassName(flowElement);
+			var info:FlowElementInfo = _config.lookupByClass(className);
+			if (info)
+				info.exporter(flowElement, parentXML);
+			else 
+			{
+				CONFIG::debug { assert(flowElement is FlowGroupElement,"Bad element in HtmlExport.exportElement"); }
+				var xml:XML = <{flowElement.typeName.toUpperCase()}/>;
+				exportChildren(flowElement as FlowGroupElement, xml);
+				parentXML.appendChild(xml);
+			}
+		}
+		
+		/** Exports the children of a flow group element
+		 * @param xml XML to append children to
+		 * @param flowGroupElement	the flow group element
+		 * @private
+		 */
+		public function exportSubParagraphChildren(flowGroupElement:IFlowGroupElement, parentXML:XML):void
+		{
+			for(var i:int=0; i < flowGroupElement.numChildren; ++i)
+			{
+				exportElement(flowGroupElement.getChildAt(i),parentXML);
+			}
+		}
+		
+		/** Helper to establish a parent-child relationship between two xml elements
+		 * and return the parent
+		 * @param parent the intended parent
+		 * @param children the intended children (XML or XMLList)
+		 * @return the parent
+		 * @private
+		 */
+		static public function nest (parent:XML, children:Object):XML
+		{
+			parent.setChildren(children);
+			return parent;
+		}
+		
+ 	}
+}
\ No newline at end of file