flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ha...@apache.org
Subject [02/42] flex-asjs git commit: And here’s TLF…
Date Thu, 16 Mar 2017 13:37:22 GMT
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/PropertyUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/PropertyUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/PropertyUtil.as
new file mode 100644
index 0000000..2a33c1d
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/PropertyUtil.as
@@ -0,0 +1,177 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.property
+{
+	import org.apache.flex.textLayout.elements.GlobalSettings;
+	public class PropertyUtil
+	{
+
+		public static var errorHandler:Function = defaultErrorHandler;
+		public static function defaultErrorHandler(p:Property,value:Object):void
+		{
+			throw(new RangeError(createErrorString(p,value)));
+		}
+		public static function createErrorString(p:Property,value:Object):String
+		{
+			return GlobalSettings.resourceStringFunction("badPropertyValue",[ p.name, value.toString() ]);
+		}
+		public static function defaultConcatHelper(currVal:*,concatVal:*):*
+		{ return currVal === undefined || currVal == "inherit" ? concatVal : currVal; }
+
+		// /////////////////////////////////////////////
+		// Following static functions are used by Format classes to 
+		// perform functions that iterate over all the attributes.
+		// They are driven by the attributes metadata object that contains
+		// definitions for all the properties.
+		// /////////////////////////////////////////////
+			
+		/** Helper function to initialize all property values from defaults. */
+		static public function defaultsAllHelper(description:Object,current:Object):void
+		{
+			for each (var prop:Property in description)
+				current[prop.name] = prop.defaultValue;
+		}
+		
+		/** Helper function to compare two sets of properties. */
+		static public function equalAllHelper(description:Object,p1:Object,p2:Object):Boolean
+		{
+			if (p1 == p2)
+				return true;
+			// these could be "equal" if all attributes of p1 or p2 are null
+			if (p1 == null || p2 == null)
+				return false;
+			for each (var prop:Property in description)
+			{
+				var name:String = prop.name;
+				if (!(prop.equalHelper(p1[name],p2[name])))
+					return false;
+			}
+			return true;
+		}
+
+		static public function extractInCategory(formatClass:Class,description:Object,props:Object,category:String,legacy:Boolean = true):Object
+		{
+			var rslt:Object = null;
+			for each (var prop:Property in description)
+			{
+				if (props[prop.name] == null)
+					continue;
+				
+				if (legacy)
+				{
+					if (prop.category != category)
+						continue;
+				}
+				else if (prop.categories.indexOf(category) == -1)
+					continue;
+				
+				if (rslt == null)
+					rslt = new formatClass();
+				rslt[prop.name] = props[prop.name];
+			}
+			return rslt;
+		}
+		
+		/** @private Copy an object */
+		static public function shallowCopy(src:Object):Object
+		{
+			// make a shallow copy
+			var rslt:Object = {};
+			for (var val:Object in src)
+				rslt[val] = src[val]; 
+			return rslt;
+		}
+		
+		/** @private Copy properties from src to result if a property of the same name exists in filter */
+		static public function shallowCopyInFilter(src:Object,filter:Object):Object
+		{
+			// make a shallow copy
+			var rslt:Object = {};
+			for (var val:Object in src)
+			{
+				if (filter.hasOwnProperty(val))
+					rslt[val] = src[val];
+			}
+			return rslt;
+		}
+		
+		/** @private Copy properties from src to result if a property of the same name exists in filter */
+		static public function shallowCopyNotInFilter(src:Object,filter:Object):Object
+		{
+			// make a shallow copy
+			var rslt:Object = {};
+			for (var val:Object in src)
+			{
+				if (!filter.hasOwnProperty(val))
+					rslt[val] = src[val];
+			}
+			return rslt;
+		}
+		
+		static private function compareStylesLoop(o1:Object,o2:Object,description:Object):Boolean
+		{
+			for (var val:String in o1)
+			{
+				var o1val:Object = o1[val];
+				var o2val:Object = o2[val];
+				if (o1val != o2val)
+				{
+					if (!(o1val is Array) || !(o2val is Array) || o1val.length != o2val.length || !description)
+						return false;	// different
+					var prop:ArrayProperty = description[val];
+					if (!prop || !equalAllHelper(prop.memberType["description"],o1val,o2val))
+						return false;
+				}
+			}
+			return true;
+		}
+		/** @private */
+		static public const nullStyleObject:Object = {};
+		/** @private */
+		static public function equalStyles(o1:Object,o2:Object,description:Object):Boolean
+		{
+			if (o1 == null)
+				o1 = nullStyleObject;
+			if (o2 == null)
+				o2 = nullStyleObject;
+			// Use of prototype chains and bug https://bugzilla.mozilla.org/show_bug.cgi?id=447673 requires this two way compare
+			return compareStylesLoop(o1,o2,description) && compareStylesLoop(o2,o1,description);
+		}
+		
+		/** @private */
+		static public function toNumberIfPercent(o:Object):Number
+		{
+			if (!(o is String))
+				return NaN;
+			var s:String = String(o);
+			var len:int = s.length;
+			
+			return len != 0 && s.charAt(len-1) == "%" ? parseFloat(s) : NaN;
+		}
+		
+		static private var prototypeFactory:Function = function():void{};
+		
+		/** @private Create an object with specified prototype parent */
+		static public function createObjectWithPrototype(parent:Object):Object
+		{
+			prototypeFactory.prototype = parent;
+			return new prototypeFactory();
+		}
+	}
+}
\ 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/property/SpacingLimitPropertyHandler.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/SpacingLimitPropertyHandler.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/SpacingLimitPropertyHandler.as
new file mode 100644
index 0000000..93c76d6
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/SpacingLimitPropertyHandler.as
@@ -0,0 +1,137 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.property {
+
+	
+
+	
+	// [ExcludeClass]
+	public class SpacingLimitPropertyHandler extends PropertyHandler
+	{
+		override public function get className():String
+		{
+			return "SpacingLimitPropertyHandler";
+		}
+		private var _minPercentValue:String;
+		private var _maxPercentValue:String;
+		
+		public function SpacingLimitPropertyHandler(minPercentValue:String, maxPercentValue:String)
+		{ 
+			_minPercentValue = minPercentValue; 
+			_maxPercentValue = maxPercentValue; 
+		}
+		
+		// check to see if this handler has a custom exporter that must be used when owningHandlerCheck is true
+		public override function get customXMLStringHandler():Boolean
+		{ return true; }
+		
+		public override function toXMLString(val:Object):String
+		{ 
+			if (val.hasOwnProperty("optimumSpacing") && val.hasOwnProperty("minimumSpacing") && val.hasOwnProperty("maximumSpacing"))
+				return val.optimumSpacing.toString() + ',' + val.minimumSpacing.toString() + ',' + val.maximumSpacing.toString();
+			return val.toString();
+		}
+		
+		/** matches a single spacing limit value */
+		static private  const _spacingLimitPattern:RegExp = /\d+%/g;
+		/** matches an array of 1-3 spacing limit values, separated by commas */
+		static private  const _spacingLimitArrayPattern:RegExp = /^\s*(\d+%)(\s*,\s*)(\d+%)?(\s*,\s*)(\d+%)?\s*$/;
+		
+		// return a value if this handler "owns" this property - otherwise return undefined
+		public override function owningHandlerCheck(newVal:*):*
+		{ 
+			if (newVal is String)
+			{
+				if (_spacingLimitArrayPattern.test(newVal))
+					return newVal;
+			}
+			
+			else if (newVal.hasOwnProperty("optimumSpacing") && newVal.hasOwnProperty("minimumSpacing") && newVal.hasOwnProperty("maximumSpacing"))
+				return newVal;
+
+			return undefined;
+		}
+		
+		private function checkValue(value:*):Boolean
+		{
+			var minLegalValue:Number = PropertyUtil.toNumberIfPercent(_minPercentValue);
+			var maxLegalValue:Number = PropertyUtil.toNumberIfPercent(_maxPercentValue);
+			
+			// Check that the 3 values don't exceed the minimum or maximum percentages allowed
+			var optValue:Number = PropertyUtil.toNumberIfPercent(value.optimumSpacing);
+			if (optValue < minLegalValue || optValue > maxLegalValue)
+				return false;
+			
+			var minValue:Number = PropertyUtil.toNumberIfPercent(value.minimumSpacing);
+			if (minValue < minLegalValue || minValue > maxLegalValue)
+				return false;
+
+			var maxValue:Number = PropertyUtil.toNumberIfPercent(value.maximumSpacing);
+			if (maxValue < minLegalValue || maxValue > maxLegalValue)
+				return false;
+			
+			// Check that optimum is between minimum & maximum
+			if (optValue < minValue || optValue > maxValue)
+				return false;
+			
+			// Check that minimum is below maximum
+			if (minValue > maxValue)
+				return false;
+			
+			return true;
+		}
+		
+		/** parse the input string and create a valid input value */
+		public override function setHelper(newVal:*):*
+		{ 
+			var s:String = newVal as String;
+			
+			if (s == null)
+				return newVal;	// assume its an object that's been parsed already
+			
+			if (_spacingLimitArrayPattern.test(newVal))
+			{
+				// Incoming string is comma-delimited list of 1-3 percentage values. 
+				// If the incoming string specifies just one value, its the optimumSpacing, and minimumSpacing and maximumSpacing get the default values.
+				// If the incoming string specifies two values, the first one is optimumSpacing and minimumSpacing and the second is maximumSpacing
+				// If the incoming string specifies three values, the first one is optimumSpacing and the second is minimumSpacing and the third is maximumSpacing
+				var result:Object = {};
+				var splits:Array = s.match(_spacingLimitPattern);
+				if (splits.length  == 1)
+				{
+					result.optimumSpacing = splits[0];
+					result.minimumSpacing = result.optimumSpacing;
+					result.maximumSpacing = result.optimumSpacing;
+				}
+				else if (splits.length == 3)
+				{
+					result.optimumSpacing = splits[0];
+					result.minimumSpacing = splits[1];
+					result.maximumSpacing = splits[2];
+				}
+				else 
+					return undefined;
+				if (checkValue(result))
+					return result;
+			}
+
+			return undefined;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/StringPropertyHandler.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/StringPropertyHandler.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/StringPropertyHandler.as
new file mode 100644
index 0000000..e3e0185
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/StringPropertyHandler.as
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.property {
+	
+	// [ExcludeClass]
+	/** A property handler with a String as its value @private */
+	public class StringPropertyHandler extends PropertyHandler
+	{
+		override public function get className():String
+		{
+			return "StringPropertyHandler";
+		}
+		/** @private */
+		public override function owningHandlerCheck(newVal:*):*
+		{ 
+			return newVal is String ? newVal : undefined;
+		}	
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/TabStopsProperty.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/TabStopsProperty.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/TabStopsProperty.as
new file mode 100644
index 0000000..9eb4223
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/TabStopsProperty.as
@@ -0,0 +1,202 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.property {
+	import org.apache.flex.textLayout.formats.FormatValue;
+	import org.apache.flex.textLayout.formats.TabStopFormat;
+		
+	// [ExcludeClass]
+	/** Property for tab stops. Extends ArrayProperty; setter takes a string representation of tab stops in addition to an array. @private */
+	public class TabStopsProperty extends ArrayProperty
+	{
+		public function TabStopsProperty(nameValue:String, defaultValue:Array, inherited:Boolean, categories:Vector.<String>)
+		{ 
+			super(nameValue, defaultValue, inherited, categories, TabStopFormat);
+		}
+			
+		/** Helper function when setting the property */
+		public override function setHelper(currVal:*,newVal:*):*
+		{
+			// null is a real value - DO NOT map to undefined like the others
+			
+			// null, undefined and INHERIT are all valid for arrays
+			if (newVal == null || newVal == FormatValue.INHERIT)
+				return newVal;
+				
+			// Accepts either an array or a string representation
+			var tabStops:Array = newVal as Array;
+			if (tabStops)
+			{
+				if (!checkArrayTypes(tabStops))
+				{
+					PropertyUtil.errorHandler(this,newVal);
+					return currVal;
+				}
+			}
+			else
+			{
+				var valString:String = newVal as String;
+				if (!valString)
+				{
+					PropertyUtil.errorHandler(this,newVal);
+					return currVal;
+				}
+					
+				// Parse the string representation and create an equivalent array
+				tabStops = new Array();
+				
+				// Replace escape sequences (\ followed by a space or \) with placeholder strings
+				// that can't naturally occur in the passed-in string 
+				valString = valString.replace(_escapeBackslashRegex, _backslashPlaceHolder);
+				valString = valString.replace(_escapeSpaceRegex, _spacePlaceHolder);
+				
+				_tabStopRegex.lastIndex = 0;
+				var lookup:Object = {
+					"s":"start",
+					"c":"center",
+					"e":"end",
+					"d":"decimal"
+				};
+				do
+				{
+					var result:Object = _tabStopRegex.exec(valString);
+					if (!result)
+						break; // no more matches
+						
+					var tabStop:TabStopFormat = new TabStopFormat();
+					tabStop.alignment = lookup[result[1].toLowerCase()] || "start";
+					// switch (result[1].toLowerCase())
+					// {
+					// 	case "s":
+					// 	case "": // START is the default
+					// 		tabStop.alignment = "start";
+					// 		break;
+					// 	case "c":
+					// 		tabStop.alignment = "center";
+					// 		break;
+					// 	case "e":
+					// 		tabStop.alignment = "end";
+					// 		break;
+					// 	case "d":
+					// 		tabStop.alignment = "decimal";
+					// 		break;
+					// }
+					
+					var position:Number = Number(result[2]); 
+					if (isNaN(position))
+					{
+						PropertyUtil.errorHandler(this,newVal);
+						return currVal;
+					}
+					tabStop.position = position;
+
+					if (tabStop.alignment == "decimal")
+					{
+						if (result[3] == "")
+							tabStop.decimalAlignmentToken = "."; //default
+						else
+						{
+							// strip the leading vertical bar and restore \ and space characters where intended
+							tabStop.decimalAlignmentToken = result[3].slice(1).replace(_backslashPlaceholderRegex, "\\");
+							tabStop.decimalAlignmentToken = tabStop.decimalAlignmentToken.replace(_spacePlaceholderRegex, " ");
+						}
+					}
+					else if (result[3] != "")
+					{
+						PropertyUtil.errorHandler(this,newVal);
+						return currVal; // if alignment is not decimal, the alignment token is not allowed
+					}
+						
+					tabStops.push(tabStop);
+				
+				} while (true);
+			
+			}
+
+			return tabStops.sort(compareTabStopFormats);
+		}
+		
+		/** @private */
+		public override function toXMLString(val:Object):String
+		{
+			var str:String = "";
+			var lookup:Object = {
+				"start":"s",
+				"center":"c",
+				"end":"e",
+				"decimal":"d"
+			};
+			var tabStops:Array = val as Array;
+			for each (var tabStop:TabStopFormat in tabStops)
+			{
+				if (str.length)
+					str += " ";
+				str += lookup[tabStop.alignment];
+				// switch (tabStop.alignment)
+				// {
+				// 	case TabAlignment.START:
+				// 		str += "s";
+				// 		break;
+				// 	case TabAlignment.CENTER:
+				// 		str += "c";
+				// 		break;
+				// 	case TabAlignment.END:
+				// 		str += "e";
+				// 		break;
+				// 	case TabAlignment.DECIMAL:
+				// 		str += "d";
+				// 		break;
+				// }
+				
+				str += tabStop.position.toString();
+				
+				if (tabStop.alignment == "decimal")
+				{
+					var escapedAlignmentToken:String = tabStop.decimalAlignmentToken.replace(_backslashRegex, "\\\\");
+					escapedAlignmentToken = escapedAlignmentToken.replace(_spaceRegex, "\\ ");
+					str += "|" + escapedAlignmentToken;
+				}
+			}
+			
+			return str;
+		}
+		
+		private static function compareTabStopFormats(a:TabStopFormat, b:TabStopFormat):Number
+		{
+			return a.position == b.position ? 0 : a.position < b.position ? -1 : 1;
+		}
+		
+		// Alignment type: [sScCeEdD]?  - Atmost 1 occurance of one of s/c/e/d (or upper-case equivalents)
+		// Position: [^| ]+ - At least character which is not a space or | (further validation is done by the Number constructor)
+		// Alignment token and separator:(|[^ ]*)? - Atmost one occurance of a | followed by 0 or more non-space characters
+		// Delimiter: ( |$) - A space or end-of-string
+		private static const _tabStopRegex:RegExp = /([sScCeEdD]?)([^| ]+)(|[^ ]*)?( |$)/g;
+		private static const _escapeBackslashRegex:RegExp = /\\\\/g;
+		private static const _escapeSpaceRegex:RegExp = /\\ /g;
+		private static const _backslashRegex:RegExp = /\\/g;
+		private static const _spaceRegex:RegExp = / /g;
+		private static const _backslashPlaceholderRegex:RegExp = /\uE000/g;
+		private static const _spacePlaceholderRegex:RegExp = /\uE001/g;
+		
+		// Replace escape sequences (\ followed by a space or \) with placeholder strings
+		// containing characters from Unicode private use area (won't naturally occur in the passed-in string) 
+		private static const _backslashPlaceHolder:String = String.fromCharCode(0xE000);
+		private static const _spacePlaceHolder:String = String.fromCharCode(0xE001);
+				
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UintPropertyHandler.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UintPropertyHandler.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UintPropertyHandler.as
new file mode 100644
index 0000000..993072b
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UintPropertyHandler.as
@@ -0,0 +1,75 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.property
+{
+
+		
+
+
+	// [ExcludeClass]
+	/** A property description with an unsigned integer as its value.  Typically used for color. @private */
+	public class UintPropertyHandler extends PropertyHandler
+	{	
+		override public function get className():String
+		{
+			return "UintPropertyHandler";
+		}
+		public override function get customXMLStringHandler():Boolean
+		{ return true; }
+		
+		public override function toXMLString(val:Object):String
+		{		
+			var result:String = val.toString(16);
+			if (result.length < 6)
+				result = "000000".substr(0, 6 - result.length) + result;
+			result = "#" + result;
+			return result;
+		}
+		
+		/** @private */
+		public override function owningHandlerCheck(newVal:*):*
+		{			
+			if (newVal is uint)
+				return newVal;
+			
+			var newRslt:Number;
+			if (newVal is String)
+			{
+				var str:String = String(newVal);
+				// Normally, we could just cast a string to a uint. However, the casting technique only works for
+				// normal numbers and numbers preceded by "0x". We can encounter numbers of the form "#ffffffff"					
+				if (str.substr(0, 1) == "#")
+					str = "0x" + str.substr(1, str.length-1);
+				newRslt = (str.toLowerCase().substr(0, 2) == "0x") ? parseInt(str) : NaN;
+			}
+			else if (newVal is Number || newVal is int)
+				newRslt = Number(newVal);
+			else
+				return undefined;
+			
+			if (isNaN(newRslt))
+				return undefined;
+
+			if (newRslt < 0 || newRslt > 0xffffffff)
+				return undefined;
+			
+			return newRslt;			
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UndefinedPropertyHandler.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UndefinedPropertyHandler.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UndefinedPropertyHandler.as
new file mode 100644
index 0000000..8655df0
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/property/UndefinedPropertyHandler.as
@@ -0,0 +1,44 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.property
+{
+	import org.apache.flex.textLayout.debug.assert;
+		
+	// [ExcludeClass]
+	/** An property description with an enumerated string as its value. @private */
+	public class UndefinedPropertyHandler extends PropertyHandler
+	{
+		override public function get className():String
+		{
+			return "UndefinedPropertyHandler";
+		}
+		/** @private */
+		public override function owningHandlerCheck(newVal:*):*
+		{ 
+			return newVal === null || newVal === undefined ? true : undefined;
+		}
+
+		/** @private */
+		public override function setHelper(newVal:*):*
+		{ 
+			CONFIG::debug{ assert(newVal == true,"Bad call to UndefinedPropertyHandler.setHelper"); }
+			return undefined;
+		}	
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/tlf_internal.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/tlf_internal.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/tlf_internal.as
new file mode 100644
index 0000000..28b21e3
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/tlf_internal.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+
+	/**
+	 *  This namespace is used for undocumented APIs -- usually implementation
+	 *  details -- which can't be private because they need to visible
+	 *  to other classes.
+	 *  APIs in this namespace are completely unsupported and are likely to
+	 *  change in future versions of TextLayout.
+	 * 
+	 *  @private
+	 */
+	public namespace tlf_internal =
+		"http://ns.adobe.com/textLayout/internal/2008";
+}
+

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/BackgroundUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/BackgroundUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/BackgroundUtil.as
new file mode 100644
index 0000000..34def7c
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/BackgroundUtil.as
@@ -0,0 +1,262 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	import org.apache.flex.geom.Rectangle;
+	import org.apache.flex.text.engine.ITextBlock;
+	import org.apache.flex.text.engine.ITextLine;
+	import org.apache.flex.textLayout.compose.IFactoryComposer;
+	import org.apache.flex.textLayout.compose.IFlowComposer;
+	import org.apache.flex.textLayout.compose.ITextFlowLine;
+	import org.apache.flex.textLayout.compose.ITextFlowTableBlock;
+	import org.apache.flex.textLayout.compose.ParcelList;
+	import org.apache.flex.textLayout.container.IContainerController;
+	import org.apache.flex.textLayout.container.ITextContainerManager;
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.elements.IBackgroundManager;
+	import org.apache.flex.textLayout.elements.IFlowElement;
+	import org.apache.flex.textLayout.elements.IFlowGroupElement;
+	import org.apache.flex.textLayout.elements.IFlowLeafElement;
+	import org.apache.flex.textLayout.elements.IParagraphElement;
+	import org.apache.flex.textLayout.elements.ITableCellElement;
+	import org.apache.flex.textLayout.elements.ITableRowElement;
+	import org.apache.flex.textLayout.elements.ITextFlow;
+	import org.apache.flex.textLayout.elements.ITableElement;
+	import org.apache.flex.textLayout.formats.BackgroundColor;
+	import org.apache.flex.textLayout.formats.BorderColor;
+	import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+
+	public class BackgroundUtil
+	{
+		public static function collectTableBlock(_textFlow:ITextFlow, block:ITextFlowTableBlock, controller:IContainerController):void
+		{
+			// add block rect for each cell in table block
+
+			var bb:IBackgroundManager;
+			var r:Rectangle;
+			// var composer:IFlowComposer;
+
+			var cells:Vector.<ITableCellElement> = block.getTableCells();
+			for each (var cell:ITableCellElement in cells)
+			{
+				if (hasBorderOrBackground(cell))
+				{
+					if (!_textFlow.backgroundManager)
+						_textFlow.getBackgroundManager();
+					bb = _textFlow.backgroundManager;
+
+					bb.addBlockElement(cell);
+
+					var row:ITableRowElement = cell.getRow();
+					r = new Rectangle(cell.x, cell.y + block.y, cell.width, row.composedHeight);
+					bb.addBlockRect(cell, r, controller);
+				}
+			}
+			// block.y;
+		}
+		
+		/**
+		 * @flexjsignorecoercion org.apache.flex.textLayout.elements.ITableElement
+		 */
+		public static function collectBlock(_textFlow:ITextFlow, elem:IFlowGroupElement, _parcelList:ParcelList = null, tableComposeNotFromBeginning:Boolean = false, tableOutOfView:Boolean = false):void
+		{
+			var bb:IBackgroundManager;
+			var r:Rectangle;
+			// var controller:IContainerController;
+			var composer:IFlowComposer;
+
+			if (elem)
+			{
+				if (hasBorderOrBackground(elem))
+				{
+					// mark the paragraph that has border or background
+					if (!_textFlow.backgroundManager)
+						_textFlow.getBackgroundManager();
+					bb = _textFlow.backgroundManager;
+
+					// IBackgroundManager should not be null here
+					CONFIG::debug
+					{
+						assert(_textFlow.backgroundManager != null, "IBackgroundManager should not be null");
+					}
+
+					bb.addBlockElement(elem);
+
+					composer = _textFlow.flowComposer;
+					if (composer && elem.textLength > 1)
+					{
+						if (elem is ITableElement)
+						{
+							// Do we need to do anything for table elements? Not sure...
+							var tab:ITableElement = elem as ITableElement;
+						}
+						else // for elements like ParagraphElement, DivElement, ListItemElement, ListElement, TextFlow
+						{
+							var tb:ITextBlock = null;
+							var p:IParagraphElement = elem.getFirstLeaf().getParagraph();
+							if (p)
+								tb = p.getTextBlock();
+							while (!tb && p)
+							{
+								p = p.getNextParagraph();
+								tb = p.getTextBlock();
+							}
+
+							if (composer is IFlowComposer && composer.numLines > 0)
+							{
+								// get the first line and the last line
+								var firstLine:ITextFlowLine = null;
+								var lastLine:ITextFlowLine = null;
+
+								if (tb && tb.firstLine)
+								{
+									firstLine = tb.firstLine.userData;
+
+									do
+									{
+										tb = p.getTextBlock();
+										if (tb && tb.lastLine)
+											lastLine = tb.lastLine.userData;
+										var leaf:IFlowLeafElement = p.getLastLeaf().getNextLeaf(elem);
+										if (leaf)
+											p = leaf.getParagraph();
+										else
+											p = null;
+									} while (p);
+								}
+								if (firstLine && lastLine)
+								{
+									var startColumnIndex:int = firstLine.columnIndex;
+									var startController:IContainerController = firstLine.controller;
+									var endColumnIndex:int = lastLine.columnIndex;
+									var endController:IContainerController = lastLine.controller;
+									if (startController && endController)
+									{
+										if (startController == endController && endColumnIndex == startColumnIndex)
+										{
+											r = startController.columnState.getColumnAt(startColumnIndex);
+											r.top = firstLine.y;
+											r.bottom = lastLine.y + lastLine.height;
+											bb.addBlockRect(elem, r, startController);
+										}
+										else
+										{
+											// start part
+											if (startController != endController)
+											{
+												for (var sIdx:int = startController.columnCount - 1; sIdx > startColumnIndex; sIdx--)
+												{
+													r = startController.columnState.getColumnAt(sIdx);
+													bb.addBlockRect(elem, r, startController);
+												}
+											}
+											if (endColumnIndex != startColumnIndex)
+											{
+												r = startController.columnState.getColumnAt(startColumnIndex);
+												r.top = firstLine.y;
+												bb.addBlockRect(elem, r, startController);
+											}
+											// center part, all parcel should be painted
+											var passFirstController:Boolean = false;
+											for (var aidx:Number = 0; aidx < composer.numControllers; aidx++)
+											{
+												var cc:IContainerController = composer.getControllerAt(aidx);
+												if (passFirstController)
+												{
+													for (var cidx:int = 0; cidx < cc.columnCount; cidx++)
+													{
+														r = cc.columnState.getColumnAt(cidx);
+														bb.addBlockRect(elem, r, cc);
+													}
+												}
+												if (cc == endController)
+													break;
+												if (cc == startController)
+													passFirstController = true;
+											}
+											// end part
+											if (startController != endController)
+											{
+												for (var eIdx:int = 0; eIdx < endColumnIndex; eIdx++)
+												{
+													r = endController.columnState.getColumnAt(eIdx);
+													bb.addBlockRect(elem, r, endController);
+												}
+											}
+											r = endController.columnState.getColumnAt(endColumnIndex);
+											r.bottom = lastLine.y + lastLine.height;
+											bb.addBlockRect(elem, r, endController);
+										}
+									}
+								}
+							}
+							// the first time display for TCM
+							else if (composer is IFactoryComposer)
+							{
+								var fLine:ITextLine = null;
+								var lLine:ITextLine = null;
+
+								if (tb && tb.firstLine)
+								{
+									fLine = tb.firstLine;
+
+									do
+									{
+										tb = p.getTextBlock();
+										if (tb && tb.lastLine)
+											lLine = tb.lastLine;
+										var leafF:IFlowLeafElement = p.getLastLeaf().getNextLeaf(elem);
+										if (leafF)
+											p = leafF.getParagraph();
+										else
+											p = null;
+									} while (p);
+								}
+								if (fLine && lLine)
+								{
+									if ((composer as Object).hasOwnProperty("tcm"))
+									{
+										var tcm:ITextContainerManager = (composer as Object).tcm;
+										if (tcm)
+										{
+											r = new Rectangle(0, fLine.y - fLine.height, tcm.compositionWidth, lLine.y - fLine.y + fLine.height);
+											bb.addBlockRect(elem, r, composer.getControllerAt(0));
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+
+		public static function hasBorderOrBackground(elem:IFlowElement):Boolean
+		{
+			var format:ITextLayoutFormat = elem.computedFormat;
+			if (format.backgroundColor != BackgroundColor.TRANSPARENT)
+				return true;
+
+			if (format.borderLeftWidth != 0 || format.borderRightWidth != 0 || format.borderTopWidth != 0 || format.borderBottomWidth != 0)
+				if (format.borderLeftColor != BorderColor.TRANSPARENT || format.borderRightColor != BorderColor.TRANSPARENT || format.borderTopColor != BorderColor.TRANSPARENT || format.borderBottomColor != BorderColor.TRANSPARENT)
+					return true;
+			return false;
+		}
+	}
+}
\ 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/utils/CharacterUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/CharacterUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/CharacterUtil.as
new file mode 100644
index 0000000..5d4b8a7
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/CharacterUtil.as
@@ -0,0 +1,167 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	/** 
+	 * Utilities for managing and getting information about characters.
+	 * The methods of this class are static and must be called using
+	 * the syntax <code>CharacterUtil.method(<em>parameter</em>)</code>.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public final class CharacterUtil
+	{
+		/** 
+		 * Returns <code>true</code> if the <code>charCode</code> argument is a high word in a surrogate pair. 
+		 * A surrogate pair represents a character with a code point that requires more
+		 * than sixteen bits to express and thus requires a combination
+		 * of two 16-bit words, a high surrogate and a low surrogate, to embody its code point.
+		 * <p>This method can be used when processing a series of characters to
+		 * ensure that you do not inadvertently divide a surrogate pair
+		 * into incomplete halves.</p>
+		 * 
+		 *
+		 * @param charCode An integer that represents a character code.
+		 * Character codes are usually represented in hexadecimal format.
+		 * For example, the space character's character code can be
+		 * represented by the number <code>0x0020</code>.
+		 * @return <code>true</code> if <code>charCode</code> is the high surrogate in a surrogate pair.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isHighSurrogate(charCode:int):Boolean
+		{
+			return (charCode >= 0xD800 && charCode <= 0xDBFF);
+		}
+		
+		/** 
+		 * Returns <code>true</code> if the <code>charCode</code> argument is a low word in a surrogate pair. 
+		 * A surrogate pair represents a character with a code point that requires more
+		 * than sixteen bits to express and thus requires a combination
+		 * of two 16-bit words, a high surrogate and a low surrogate, to embody its code point.
+		 * <p>This method can be used when processing a series of characters to
+		 * ensure that you do not inadvertently divide a surrogate pair
+		 * into incomplete halves.</p>
+		 *
+		 * @param charCode An integer that represents a character code.
+		 * Character codes are usually represented in hexadecimal format.
+		 * For example, the space character's character code can be
+		 * represented by the number <code>0x0020</code>.
+		 * @return <code>true</code> if <code>charCode</code> is the low surrogate in a surrogate pair.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isLowSurrogate (charCode:int):Boolean
+		{
+			return (charCode >= 0xDC00 && charCode <= 0xDFFF);
+		}
+
+		static private var whiteSpaceObject:Object = createWhiteSpaceObject();
+		
+		static private function createWhiteSpaceObject():Object
+		{
+			var rslt:Object = {};
+			//members of SpaceSeparator category
+			rslt[0x0020] =  true;  //SPACE
+			rslt[0x1680] =  true;  //OGHAM SPACE MARK
+			rslt[0x180E] =  true;  //MONGOLIAN VOWEL SEPARATOR
+			rslt[0x2000] =  true;  //EN QUAD
+			rslt[0x2001] =  true;  //EM QUAD
+			rslt[0x2002] =  true;  //EN SPACE
+			rslt[0x2003] =  true;  //EM SPACE
+			rslt[0x2004] =  true;  //THREE-PER-EM SPACE
+			rslt[0x2005] =  true;  //FOUR-PER-EM SPACE
+			rslt[0x2006] =  true;  //SIZE-PER-EM SPACE
+			rslt[0x2007] =  true;  //FIGURE SPACE
+			rslt[0x2008] =  true;  //PUNCTUATION SPACE
+			rslt[0x2009] =  true;  //THIN SPACE
+			rslt[0x200A] =  true;  //HAIR SPACE
+			rslt[0x202F] =  true;  //NARROW NO-BREAK SPACE
+			rslt[0x205F] =  true;  //MEDIUM MATHEMATICAL SPACE
+			rslt[0x3000] =  true;  //IDEOGRAPHIC SPACE
+			//members of LineSeparator category
+			rslt[0x2028] =  true;  //LINE SEPARATOR
+			//members of ParagraphSeparator category
+			rslt[0x2029] =  true;
+			//Other characters considered to be a space
+			rslt[0x0009] =  true; //CHARACTER TABULATION
+			rslt[0x000A] =  true; //LINE FEED
+			rslt[0x000B] =  true; //LINE TABULATION
+			rslt[0x000C] =  true; //FORM FEED
+			rslt[0x000D] =  true; //CARRIAGE RETURN
+			rslt[0x0085] =  true; //NEXT LINE
+			rslt[0x00A0] =  true; //NO-BREAK SPACE	
+			return rslt;
+		}
+		/** 
+		 * Returns <code>true</code> if <code>charCode</code> is a whitespace character. 
+		 * <p>The following table describes all characters that this
+		 * method considers a whitespace character.
+		 * </p>
+		 * <table class="innertable">
+		 *     <tr><th>Character Code</th><th>Unicode Character Name</th><th>Category</th></tr>
+		 *     <tr><td><code>0x0020</code></td><td>SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x1680</code></td><td>OGHAM SPACE MARK</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x180E</code></td><td>MONGOLIAN VOWEL SEPARATOR</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2000</code></td><td>EN QUAD</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2001</code></td><td>EM QUAD</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2002</code></td><td>EN SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2003</code></td><td>EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2004</code></td><td>THREE-PER-EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2005</code></td><td>FOUR-PER-EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2006</code></td><td>SIX-PER-EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2007</code></td><td>FIGURE SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2008</code></td><td>PUNCTUATION SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2009</code></td><td>THIN SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x200A</code></td><td>HAIR SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x202F</code></td><td>NARROW NO-BREAK SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x205F</code></td><td>MEDIUM MATHEMATICAL SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x3000</code></td><td>IDEOGRAPHIC SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2028</code></td><td>LINE SEPARATOR</td><td>Line Separator</td></tr>
+		 *     <tr><td><code>0x2029</code></td><td>PARAGRAPH SEPARATOR</td><td>Paragraph Separator</td></tr>
+		 *     <tr><td><code>0x0009</code></td><td>CHARACTER TABULATION</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000A</code></td><td>LINE FEED</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000B</code></td><td>LINE TABULATION</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000C</code></td><td>FORM FEED</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000D</code></td><td>CARRIAGE RETURN</td><td>Other</td></tr>
+		 *     <tr><td><code>0x0085</code></td><td>NEXT LINE</td><td>Other</td></tr>
+		 *     <tr><td><code>0x00A0</code></td><td>NO-BREAK SPACE</td><td>Other</td></tr>
+		 *  </table>
+
+		 *
+		 * @param charCode An integer that represents a character code.
+		 * Character codes are usually represented in hexadecimal format.
+		 * For example, the space character's character code can be
+		 * represented by the number <code>0x0020</code>.
+		 *
+		 * @return <code>true</code> if <code>charCode</code> is a whitespace character. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isWhitespace(charCode:int):Boolean
+		{			
+			return whiteSpaceObject[charCode];
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/ComposeUtils.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/ComposeUtils.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/ComposeUtils.as
new file mode 100644
index 0000000..8a1bc66
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/ComposeUtils.as
@@ -0,0 +1,48 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	import org.apache.flex.textLayout.compose.ComposeState;
+	import org.apache.flex.textLayout.compose.IComposer;
+	public class ComposeUtils
+	{
+		
+		// a single ComposeState that is checked out and checked in
+		static private var _sharedComposeState:IComposer;
+
+		/** @private */
+		static public function getComposeState():IComposer
+		{
+			var rslt:IComposer = _sharedComposeState;
+			if (rslt)
+			{
+				_sharedComposeState = null;
+				return rslt;
+			}
+			return new ComposeState();
+		}
+		
+		/** @private */
+		static public function releaseComposeState(state:IComposer):void
+		{
+			state.releaseAnyReferences();
+			_sharedComposeState = state;
+		}				
+	}
+}
\ 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/utils/ConfigUtils.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/ConfigUtils.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/ConfigUtils.as
new file mode 100644
index 0000000..eb158b3
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/ConfigUtils.as
@@ -0,0 +1,24 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	public class ConfigUtils
+	{
+	}
+}
\ 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/utils/CreateTLFUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/CreateTLFUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/CreateTLFUtil.as
new file mode 100644
index 0000000..4fc8d88
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/CreateTLFUtil.as
@@ -0,0 +1,197 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.formats.FormatValue;
+	import org.apache.flex.textLayout.formats.ITextLayoutFormat;
+	import org.apache.flex.textLayout.formats.TextLayoutFormat;
+	import org.apache.flex.textLayout.property.Property;
+	import org.apache.flex.textLayout.property.PropertyUtil;
+	public class CreateTLFUtil
+	{
+		public static function createTLF(localStyles:ITextLayoutFormat, parentPrototype:TextLayoutFormat):TextLayoutFormat
+		{
+			var parentPrototypeUsable:Boolean = true;
+			var hasStylesSet:Boolean = false;
+			// the actual prototype to use
+			var parentStylesPrototype:Object;
+			// create a new stylesObject with a parentPrototype
+			if (parentPrototype)
+			{
+				parentStylesPrototype = parentPrototype.getStyles();
+				if (parentStylesPrototype.hasNonInheritedStyles !== undefined)
+				{
+					// its either a boolean or if its been used once an object that has the non-inheriting styles reset
+					if (parentStylesPrototype.hasNonInheritedStyles === true)
+					{
+						// create a modified prototype and give it all default non-inherited values
+						var noInheritParentStylesPrototype:Object = PropertyUtil.createObjectWithPrototype(parentStylesPrototype);
+						TextLayoutFormat.resetModifiedNoninheritedStyles(noInheritParentStylesPrototype);
+						// now save it in the parent for reuse
+						parentStylesPrototype.hasNonInheritedStyles = noInheritParentStylesPrototype;
+						parentStylesPrototype = noInheritParentStylesPrototype;
+					}
+					else
+					{
+						parentStylesPrototype = parentStylesPrototype.hasNonInheritedStyles;
+					}
+					parentPrototypeUsable = false;	// can't use it
+				}
+			}
+			else
+			{
+				parentPrototype = TextLayoutFormat.defaultFormat as TextLayoutFormat;
+				parentStylesPrototype = parentPrototype.getStyles();
+			}
+
+			var stylesObject:Object = PropertyUtil.createObjectWithPrototype(parentStylesPrototype);
+
+			var key:String;
+			var val:*;
+			var prop:Property;
+			// has nonInherited Styles that are *different* from the default
+			var hasNonInheritedStyles:Boolean = false;
+
+			// two cases depending on how localStyles are supplied
+			if (localStyles != null)
+			{
+				var lvh:TextLayoutFormat = localStyles as TextLayoutFormat;
+				if (lvh)
+				{
+					var coreStyles:Object = lvh.getStyles();
+
+					for (key in coreStyles)
+					{
+						val = coreStyles[key];
+						if (val == FormatValue.INHERIT)
+						{
+							if (parentPrototype)
+							{
+								prop = TextLayoutFormat.description[key];
+								if (prop && !prop.inherited)
+								{
+									// actually do the inheritance - might have been wiped out above!
+									val = parentPrototype[key];
+									if (stylesObject[key] != val)
+									{
+										stylesObject[key] = val;
+										hasNonInheritedStyles = true;
+										hasStylesSet = true;
+										// CONFIG::debug { assert(val != prop.defaultValue,"Unexpected non-inheritance"); }
+									}
+								}
+							}
+						}
+						else
+						{
+							if (stylesObject[key] != val)
+							{
+								prop = TextLayoutFormat.description[key];
+								if (prop && !prop.inherited)
+								{
+									// CONFIG::debug { assert(val != prop.defaultValue,"Unexpected non-inheritance"); }
+									hasNonInheritedStyles = true;
+								}
+								stylesObject[key] = val;
+								hasStylesSet = true;	// doesn't matter if inherited or not
+							}
+						}
+					}
+				}
+				else
+				{
+					for each (prop in TextLayoutFormat.description)
+					{
+						key = prop.name;
+						val = localStyles[key];
+						if (val !== undefined)
+						{
+							if (val == FormatValue.INHERIT)
+							{
+								if (parentPrototype)
+								{
+									if (!prop.inherited)
+									{
+										// actually do the inheritance - might have been wiped out above!
+										val = parentPrototype[key];
+										if (stylesObject[key] != val)
+										{
+											stylesObject[key] = val;
+											hasNonInheritedStyles = true;
+											hasStylesSet = true;
+											// CONFIG::debug { assert(val != prop.defaultValue,"Unexpected non-inheritance"); }
+										}
+									}
+								}
+							}
+							else
+							{
+								if (stylesObject[key] != val)
+								{
+									if (!prop.inherited)
+									{
+										// CONFIG::debug { assert(val != prop.defaultValue,"Unexpected non-inheritance"); }
+										hasNonInheritedStyles = true;
+									}
+									stylesObject[key] = val;
+									hasStylesSet = true;	// doesn't matter if inherited or not
+								}
+							}
+						}
+					}
+				}
+			}
+
+			var rslt:TextLayoutFormat;
+
+			if (!hasStylesSet)
+			{
+				// nothing has changed from the parent so just reuse it
+				CONFIG::debug{ assert(hasNonInheritedStyles == false, "stylesCount mismatch with hasNonInheritedStyles"); }
+				if (parentPrototypeUsable)
+					return parentPrototype;
+				// we can use the parentStylesPrototype but not the parentPrototype
+				rslt = new TextLayoutFormat();
+				rslt.setStyles(stylesObject, true);
+				return rslt;
+			}
+
+			if (hasNonInheritedStyles)
+			{
+				// if its not identical in stylesObject need to set it
+				CONFIG::debug
+				{
+					assert(stylesObject.hasNonInheritedStyles !== hasNonInheritedStyles, "unexpected nonInheritedStyles"); }
+				stylesObject.hasNonInheritedStyles = true;
+				stylesObject.setPropertyIsEnumerable("hasNonInheritedStyles", false);
+			}
+			else if (stylesObject.hasNonInheritedStyles !== undefined)
+			{
+				stylesObject.hasNonInheritedStyles = undefined;
+				stylesObject.setPropertyIsEnumerable("hasNonInheritedStyles", false);
+			}
+
+			rslt = new TextLayoutFormat();
+			rslt.setStyles(stylesObject, false);
+			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/utils/FactoryUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/FactoryUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/FactoryUtil.as
new file mode 100644
index 0000000..6819b86
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/FactoryUtil.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.utils
+{
+	import org.apache.flex.textLayout.compose.FactoryComposer;
+	import org.apache.flex.textLayout.factory.ITLFFactory;
+	import org.apache.flex.textLayout.factory.StandardTLFFactory;
+	public class FactoryUtil
+	{
+		/** @private */
+		public static function getDefaultFlowComposerClass():Class
+		{
+			return FactoryComposer;
+		}
+		
+		private static var _defaultTLFFactory:ITLFFactory;
+		
+		public static function get defaultTLFFactory():ITLFFactory
+		{
+			if(!_defaultTLFFactory)
+				_defaultTLFFactory = new StandardTLFFactory();
+			return _defaultTLFFactory; 
+		}
+
+		public static function set defaultTLFFactory(value:ITLFFactory):void
+		{
+			_defaultTLFFactory = value;
+		}
+	}
+}
\ 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/utils/GeometryUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/GeometryUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/GeometryUtil.as
new file mode 100644
index 0000000..628ef70
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/GeometryUtil.as
@@ -0,0 +1,128 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	import org.apache.flex.geom.Rectangle;
+	import org.apache.flex.text.engine.ITextLine;
+	
+	import org.apache.flex.textLayout.compose.IFlowComposer;
+	import org.apache.flex.textLayout.compose.ITextFlowLine;
+	import org.apache.flex.textLayout.elements.TextRange;
+
+	
+
+	/** 
+	 * Utilities for getting information about text geometry and bounds.
+	 * The methods of this class are static and must be called using
+	 * the syntax <code>GeometryUtil.method(<em>parameter</em>)</code>.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	//  [ExcludeClass]
+	public final class GeometryUtil
+	{
+		/**
+		 * Returns an array of line/rectangle object pairs describing the highlight area of the text 
+		 * based on the content bounded within the indicies. The rectangles are the same as those which would be 
+		 * created if the text were selected. May return one or more pair per line.
+		 * 
+		 * 
+		 * @param range	- a TextRange describing the TextFlow as well as the beginning and end indicies
+		 * @return Array - An array of TextLine and Rectangle pairs. The objects can be referenced as:
+		 * 		obj.textLine - to access the TextLine object
+		 *		obj.rect - to access the rectangle describing the selection in TextLine coordinates
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * Example Usage:
+		 *  var theRect:Rectangle = returnArray[0].rect.clone(); 
+		 *  var textLine:TextLine = returnArray[0].textLine; 
+		 * 	var globalStart:Point = new Point(theRect.x, theRect.y);
+		 *  globalStart = textLine.localToGlobal(globalStart);
+		 *  globalStart = textLine.parent.globalToLocal(globalStart);
+		 *  theRect.x = globalStart.x;
+		 *  theRect.y = globalStart.y;
+		 * 
+		 *  [Make a new shape and draw the path into it. See flash.display.graphics]
+		 *  textLine.parent.addChild(newShape);
+		 */
+		public static function getHighlightBounds(range:TextRange):Array
+		{
+			var flowComposer:IFlowComposer = range.textFlow.flowComposer;
+			if (!flowComposer)
+				return null;
+			
+			
+			var resultShapes:Array = new Array();
+			
+			var begLine:int = flowComposer.findLineIndexAtPosition(range.absoluteStart);
+			var endLine:int = range.absoluteStart == range.absoluteEnd ? begLine : flowComposer.findLineIndexAtPosition(range.absoluteEnd);
+			
+			// watch for going past the end
+			if (endLine >= flowComposer.numLines)
+				endLine = flowComposer.numLines-1;
+					
+			var prevLine:ITextFlowLine = begLine > 0 ? flowComposer.getLineAt(begLine-1) : null;
+			var nextLine:ITextFlowLine;
+
+			var line:ITextFlowLine = flowComposer.getLineAt(begLine); 			
+			
+			var mainRects:Array = [];
+			
+			for (var curLineIndex:int = begLine; curLineIndex <= endLine; curLineIndex++)
+			{
+				nextLine = curLineIndex != (flowComposer.numLines - 1) ? flowComposer.getLineAt(curLineIndex + 1) : null;
+				
+				
+				var heightAndAdj:Array = line.getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
+				
+				var textLine:ITextLine = line.getTextLine(true);
+
+				line.calculateSelectionBounds(textLine, mainRects, 
+					range.absoluteStart < line.absoluteStart ? line.absoluteStart - line.paragraph.getAbsoluteStart()
+ 															 : range.absoluteStart - line.paragraph.getAbsoluteStart(), 
+					range.absoluteEnd > (line.absoluteStart + line.textLength) ? line.absoluteStart + line.textLength - line.paragraph.getAbsoluteStart()
+																			   : range.absoluteEnd - line.paragraph.getAbsoluteStart(), 
+					range.textFlow.computedFormat.blockProgression, heightAndAdj);
+				
+					
+				for each(var rect:Rectangle in mainRects)
+				{
+					var obj:Object = {};	// NO PMD
+					obj.textLine = textLine;
+					obj.rect = rect.clone();
+					
+					resultShapes.push(obj);
+				}
+				mainRects.length = 0;
+				
+				var temp:ITextFlowLine = line;
+				line = nextLine;
+				prevLine = temp;
+			}
+			
+			return resultShapes;
+		}
+	}
+	
+}
\ 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/utils/HitTestArea.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/HitTestArea.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/HitTestArea.as
new file mode 100644
index 0000000..4eba8b9
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/HitTestArea.as
@@ -0,0 +1,287 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils {
+	import org.apache.flex.geom.Rectangle;
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.elements.FlowElement;
+
+	
+
+	
+	// [ExcludeClass]
+	/**
+	 * The HitTestArea class is a lightweight implementation of the Warnock
+	 * algorithm for rectangles. It is used for hit-testing in FlowElements, which 
+	 * may contain multiple child elements. The algorithm attempts to set the logical
+	 * midpoint to be outside of a bounding rectangle to avoid having to split too many rectangles.
+	 * Note that the code is optimized for non-overlapping rectangles;
+	 * the determination of the logical midpoint does not work well for overlapping
+	 * rectangles because the algorithm breaks once it found a rectangle that contains
+	 * the geometric midpoint.
+	 * 
+	 * The pseudocode for this algorithm is:
+	 * 
+	 * if !(point in this rectangle) return false;
+	 * if !(hasKids) return true;
+	 * determine the quadrant where the point is in (top left "tl", top right "tr",
+	 * bottom left "bl", or bottom right "br");
+	 * if this[quadrant] == null, return false; // no rectangle covers this area
+	 * else return this[quadrant].hitTest(x,y);
+	 * 
+	 * To avoid having to create a 4-element array for the four quadrants, the code
+	 * constructs the property name and accesses the property with dynamic lookup.
+	 */
+	public class HitTestArea
+	{
+//		private var tl:HitTestArea = null;	// top left quadrant	// NO PMD
+//		private var tr:HitTestArea = null;	// top right quadrant	// NO PMD
+//		private var bl:HitTestArea = null;	// bottom left quadrant	// NO PMD
+//		private var br:HitTestArea = null;	// bottom right quadrant	// NO PMD
+		
+		private var _rect:Rectangle;	// the bounding rectangle
+		private var _xm:Number;			// logical midpoint
+		private var _ym:Number;
+		
+		/**
+		 * The owning FlowElement is the element whose area this HitTestArea
+		 * covers. This variable is set for a rectangle if the structure passed
+		 * in to the constructor contains an "owner" property. If it is null,
+		 * the instance has child quadrants.
+		 */
+		private var _owner:FlowElement = null;
+		
+		CONFIG::debug
+		{
+//			static private var _depth:int = 0;
+			/**
+			 * This array takes the counts for recursion depths on hit testing.
+			 */
+			static public const depths:Array = [];	
+		}		
+		/**
+		 * Create a HitTestArea with an object containing enumerable property objects as a rectangle
+		 * in a "rect" property, and a a FlowElement in its "owner" property. First, 
+		 * determine the bounding rectangle; then, determine the midpoint, and fill
+		 * in each quadrant with the intersecting rectangles.
+		 * @param obj    An object containing {rect:Rectangle, owner:FlowElement} objects as property values.
+		 */
+		public function HitTestArea(objects:Object)
+		{
+			initialize(objects);
+		}
+		
+		/** @private */
+		public function initialize(objects:Object):void
+		{
+			var obj:Object;
+			// determine the number of objects; all we need to know is 0, 1, or more
+			var count:int = 0;
+			if (objects)
+			{
+				for (obj in objects)
+				{
+					if (++count > 1)
+						break;
+				}
+			}
+			
+			if (count == 0)
+			{
+				_rect = new Rectangle();
+				_xm = _ym = 0;
+				return;
+			}
+			
+			// Determine the bounding rectangle
+			// if the object only has one element, it is easy
+			if (count == 1)
+			{
+				for each (obj in objects)
+				{
+					_rect = obj.rect;
+					_xm = _rect.left;
+					_ym = _rect.top;
+					_owner = obj.owner;
+					CONFIG::debug { assert(_owner != null, "No owner given"); }
+					return;
+				}
+			}
+			
+			var r:Rectangle;
+			// if more than one element, we need to calulate and fill
+			for each (obj in objects)
+			{
+				r = obj.rect;
+				if (!_rect)
+					_rect = r;
+				else
+					_rect = _rect.union(r);
+			}
+			
+			// Set the geometric midpoint
+			_xm = Math.ceil(_rect.left + _rect.width / 2);
+			_ym = Math.ceil(_rect.top + _rect.height / 2);
+			
+			// Hard stop here: if the bounding rectangle is < 3 pixels in any direction,
+			// we consider it to be a single rectangle.
+			if (_rect.width <= 3 || _rect.height <= 3)
+			{
+				// Here, we set the owner to the first element's owner
+				for each (obj in objects)
+				{
+					_owner = obj.owner;
+					CONFIG::debug { assert(_owner != null, "No owner given"); }
+					return;
+				}
+			}
+			
+			// Determine the logical midpoint. This point is as close to
+			// the geometric midpoint as possible. If the midpoint is inside 
+			// a rectangle, the midpoint is adjusted to the nearest point 
+			// outside of the rectangle if possible to avoid excessive 
+			// splitting of rectangles. The first point is used as the new
+			// midpoint to avoid having to deal with overlapping rectangles,
+			// which should usually not appear at all.
+			for each (obj in objects)
+			{
+				r = obj.rect;
+				if (r.equals(_rect))
+					continue;
+				
+				if (r.contains(_xm, _ym))
+				{
+					// The midpoint is over a rectangle; find the closest
+					// rectangle boundary and move the midpoint there
+					var dxLower:Number = _xm - r.left;
+					var dxUpper:Number = r.right - _xm;
+					var dyLower:Number = _ym - r.top;
+					var dyUpper:Number = r.bottom - _ym;
+					// this may lead to _xm and/or _ym being equal to left/top
+					_xm = (dxLower > dxUpper) ? _xm + dxUpper : _xm - dxLower;
+					_ym = (dyLower > dyUpper) ? _ym + dyUpper : _ym - dyLower;
+					// this should be changed if overlapping rectangles need to be supported
+					// in that case, all rectangles that have a hit shouldd be checked to
+					// determine the closest boundary
+					break;
+				}
+			}
+			
+			// Insert all rectangles into the respective quadrants
+			var quadrant:Rectangle = new Rectangle(_rect.left, _rect.top, _xm - _rect.left, _ym - _rect.top);
+			addQuadrant(objects, "tl", quadrant);
+			quadrant.left = _xm;
+			quadrant.right = _rect.right;
+			addQuadrant(objects, "tr", quadrant);
+			quadrant.left = _rect.left;
+			quadrant.top = _ym;
+			quadrant.right = _xm;
+			quadrant.bottom = _rect.bottom;
+			addQuadrant(objects, "bl", quadrant);
+			quadrant.left = _xm;
+			quadrant.right = _rect.right;
+			addQuadrant(objects, "br", quadrant);
+		}
+		
+		/**
+		 * Do a hit test. If the point is within this rectangle, determine
+		 * the quadrant of the point. If the quadrant is empty, the hit test
+		 * is true. If not, recurse into that quadrant.
+		 * @param x    the X coordinate
+		 * @param y    the Y coordinate
+		 * @return     the owner if the hit test succeeds, null otherwise
+		 */
+		public function hitTest(x:Number, y:Number):FlowElement
+		{
+			if (!_rect.contains(x, y))
+				return null;
+			// if there are no kids (the owner is set), the rectangle has been hit
+			// no need to attempt to retrieve the quadrant
+			if (_owner)
+				return _owner;
+			// determine quadrant
+			var quadrantName:String = (y < _ym) ? "t" : "b";
+			quadrantName += (x < _xm) ? "l" : "r";
+			var quadrant:HitTestArea = this[quadrantName];
+			// there is no child rectangle here: no hit
+			if (quadrant == null)
+				return null;
+			// ask the child
+			return quadrant.hitTest(x, y);
+		}
+
+		/* Use this version to track hit testing in debug code
+		public function hitTest(x:Number, y:Number, depth:int=1):FlowElement
+		{
+			if (!_rect.contains(x, y))
+			{
+				trace("Depth " + depth + ": " + x + "," + y);
+				return null;
+			}
+			// if there are no kids (the owner is set), the rectangle has been hit
+			// no need to attempt to retrieve the quadrant
+			if (_owner)
+			{
+				trace("Depth " + depth + ": " + x + "," + y + ": " + _owner);
+				if (depths[depth] == undefined)
+					depths[depth] = 0;
+				depths[depth]++;
+				return _owner;
+			}
+			// determine quadrant
+			var quadrantName:String = (y < _ym) ? "t" : "b";
+			quadrantName += (x < _xm) ? "l" : "r";
+			var quadrant:HitTestArea = this[quadrantName];
+			// there is no child rectangle here: no hit
+			if (quadrant == null)
+			{
+				trace("Depth " + depth + ": " + x + "," + y);
+				return null;
+			}
+			// ask the child
+			return quadrant.hitTest(x, y, depth+1);
+		}
+		*/
+		/** @private
+		 * Add the given objects of rectangles to the given quadrant. Create an array of
+		 * intersecting rectangles, and, if that array if not empty, create a new
+		 * HitTestArea covering these rectangles, and store it into the quadrant
+		 * property. Note that this method is recursive.
+		 * @param arr        An object of rectangle objects.
+		 * @param propName   The name of the quadrant property (tl, tr, bl, br).
+		 * @param quadrant   The bounding rectangle for this quadrant.
+		 */
+		private function addQuadrant(objects:Object, propName:String, quadrant:Rectangle):void
+		{
+			if (quadrant.isEmpty())
+				return;
+			
+			// Collect the objects of intersecting rectangles
+			var qrects:Object = {};
+			var i:int = 0;
+			for each (var obj:Object in objects)
+			{
+				var intersect:Rectangle = obj.rect.intersection(quadrant);
+				if (!intersect.isEmpty())
+					qrects[i++] = {owner:obj.owner, rect:intersect};
+			}
+			if (i > 0)
+				this[propName] = new HitTestArea(qrects);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/fd08d137/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/LocaleUtil.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/LocaleUtil.as b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/LocaleUtil.as
new file mode 100644
index 0000000..c0e3fe0
--- /dev/null
+++ b/frameworks/projects/TLF/src/main/flex/org/apache/flex/textLayout/utils/LocaleUtil.as
@@ -0,0 +1,211 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	import org.apache.flex.text.engine.JustificationStyle;
+	
+	import org.apache.flex.textLayout.debug.assert;
+	import org.apache.flex.textLayout.formats.JustificationRule;
+	import org.apache.flex.textLayout.formats.LeadingModel;
+
+	
+	
+
+	/** 
+	 * Utilities for managing and getting information about Locale based defaults.
+	 * The methods of this class are static and must be called using
+	 * the syntax <code>LocaleUtil.method(<em>parameter</em>)</code>.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	// [ExcludeClass]
+	public final class LocaleUtil
+	{
+		public function LocaleUtil()
+		{
+		}
+		
+		
+		/** @private */
+		static private var _localeSettings:Object = null;
+		static private var _lastLocaleKey:String = "";
+		static private var _lastLocale:LocaleSettings = null;
+		
+		static public function justificationRule(locale:String):String 
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.justificationRule;
+		}
+		
+		static public function justificationStyle(locale:String):String
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.justificationStyle;
+		}
+		
+		static public function leadingModel(locale:String):String
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.leadingModel;
+		}
+		
+		
+		static public function dominantBaseline(locale:String):String
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.dominantBaseline;
+		}
+		
+		
+		/** @private */
+		static private function addLocale(locale:String):LocaleSettings
+		{
+			CONFIG::debug{ assert(_localeSettings[locale] == null, "Cannot add a new locale property set when it already exists.  Locale == " + locale); }
+			_localeSettings[locale] = new LocaleSettings();
+			return _localeSettings[locale];
+		}
+		
+		/** @private */
+		static private function initializeDefaultLocales():void
+		{
+			CONFIG::debug{ assert(_localeSettings == null, "Should not call initializeDefaultLocales when dictionary exists!"); }
+			_localeSettings = {};
+			
+			{
+				var locale:LocaleSettings = addLocale("en");
+				CONFIG::debug{ assert(locale != null, "Failed to create new locale for 'en'!"); }
+	
+				locale.justificationRule = JustificationRule.SPACE;
+				locale.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU;
+				locale.leadingModel = LeadingModel.ROMAN_UP;
+				locale.dominantBaseline = "roman";
+				
+				locale = addLocale("ja");
+				CONFIG::debug{ assert(locale != null, "Failed to create new locale for 'ja'!"); }
+	
+				locale.justificationRule = JustificationRule.EAST_ASIAN;
+				locale.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU;
+				locale.leadingModel = LeadingModel.IDEOGRAPHIC_TOP_DOWN;
+				locale.dominantBaseline = "ideographicCenter";
+				
+				locale = addLocale("zh");
+				CONFIG::debug{ assert(locale != null, "Failed to create new locale for 'zh'!"); }
+	
+				locale.justificationRule = JustificationRule.EAST_ASIAN;
+				locale.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU;
+				locale.leadingModel = LeadingModel.IDEOGRAPHIC_TOP_DOWN;
+				locale.dominantBaseline = "ideographicCenter";
+			}		
+		}
+		
+		/** @private */
+		static private function getLocale(locale:String):LocaleSettings
+		{
+			var lowerLocale:String = locale.toLowerCase().substr(0,2);
+			var rslt:LocaleSettings = _localeSettings[lowerLocale];
+			return rslt == null ? _localeSettings["en"] : rslt;
+		}
+		
+		/** @private */
+		static private function fetchLocaleSet(locale:String):LocaleSettings
+		{
+			if(_localeSettings == null)
+				initializeDefaultLocales();
+			
+			if(locale == _lastLocaleKey)
+				return _lastLocale;
+			
+			var localeSet:LocaleSettings = getLocale(locale);
+			
+			//update the last locale data
+			_lastLocale = localeSet;
+			_lastLocaleKey = locale;
+			return localeSet;
+		}
+	}
+}
+
+
+import org.apache.flex.textLayout.debug.assert;
+
+import org.apache.flex.textLayout.formats.TextLayoutFormat;
+
+
+
+class LocaleSettings
+{
+	public function LocaleSettings()
+	{}
+	
+	private var _justificationRule:String = null;
+	private var _justificationStyle:String = null;
+	private var _leadingModel:String = null;
+	private var _dominantBaseline:String = null;
+	
+	public function get justificationRule():String { return _justificationRule; }
+	public function set justificationRule(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.justificationRuleProperty.setHelper(_justificationRule,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid JustificationRule!"); }
+		
+		_justificationRule = setValue == null ? null : (setValue as String);
+	}
+	
+	public function get justificationStyle():String { return _justificationStyle; }
+	public function set justificationStyle(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.justificationStyleProperty.setHelper(_justificationStyle,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid LeadingDirection!"); }
+		
+		_justificationStyle = setValue == null ? null : (setValue as String);
+	}
+	
+	public function get leadingModel():String { return _leadingModel; }
+	public function set leadingModel(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.leadingModelProperty.setHelper(_leadingModel,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid JustificationStyle!"); }
+		
+		_leadingModel = setValue == null ? null : (setValue as String);
+	}
+	
+	
+	public function get dominantBaseline():String { return _dominantBaseline; }
+	public function set dominantBaseline(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.dominantBaselineProperty.setHelper(_dominantBaseline,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid TextBaseline!"); }
+		
+		_dominantBaseline = setValue == null ? null : (setValue as String);
+	}
+}
\ No newline at end of file


Mime
View raw message