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:22 UTC
[02/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/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