You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by bi...@apache.org on 2014/09/17 03:25:30 UTC

[6/7] Add support for LinearGradient for AS and JS versions. Includes support for gradient rotation as well. Elliptical Arc (A) property of Path does not support gradient rotations (yet) in the AS version

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/9999c237/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/AdvancedLayoutFeatures.as
----------------------------------------------------------------------
diff --git a/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/AdvancedLayoutFeatures.as b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/AdvancedLayoutFeatures.as
new file mode 100644
index 0000000..14cc5af
--- /dev/null
+++ b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/AdvancedLayoutFeatures.as
@@ -0,0 +1,1140 @@
+/**
+ * Licensed 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.core.graphics.utils
+{
+	import flash.events.Event;
+	import flash.geom.Matrix;
+	import flash.geom.Matrix3D;
+	import flash.geom.Point;
+	import flash.geom.Vector3D;
+	import flash.system.Capabilities;
+	
+	import org.apache.flex.core.graphics.utils.IAssetLayoutFeatures;
+	
+	
+	/**
+	 *  @private
+	 *  Transform Offsets can be assigned to any Component or GraphicElement to modify the transform
+	 *  of the object beyond where its parent layout places it.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	public class AdvancedLayoutFeatures implements IAssetLayoutFeatures
+	{
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		/**
+		 *  Constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function AdvancedLayoutFeatures()
+		{
+			layout = new CompoundTransform();
+		}
+		
+		
+		
+		/**
+		 * @private
+		 * a flag for use by the owning object indicating whether the owning object has a pending update
+		 * to the computed matrix.  it is the owner's responsibility to set this flag.
+		 */
+		public var updatePending:Boolean = false;
+		
+		/**
+		 * storage for the depth value. Layering is considered 'advanced' layout behavior, and not something
+		 * that gets used by the majority of the components out there.  So if a component has a non-zero depth,
+		 * it will allocate a AdvancedLayoutFeatures object and store the value here.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public var depth:Number = 0;
+		
+		/**
+		 * @private
+		 * slots for the various 2D and 3D matrices for layout, offset, and computed transforms.  Note that 
+		 * these are only allocated and computed on demand -- many component instances will never use a 3D
+		 * matrix, for example. 
+		 */
+		protected var _computedMatrix:Matrix;
+		protected var _computedMatrix3D:Matrix3D;
+		
+		/**
+		 * @private
+		 * the layout visible transform as defined by the user and parent layout.
+		 */
+		protected var layout:CompoundTransform;
+		
+		/**
+		 * @private
+		 * offset values applied by the user
+		 */
+		private var _postLayoutTransformOffsets:TransformOffsets;
+		
+		/**
+		 * @private
+		 * bit field flags for indicating which transforms are valid -- the layout properties, the matrices,
+		 * and the 3D matrices.  Since developers can set any of the three programmatically, the last one set
+		 * will always be valid, and the others will be invalid until validated on demand.
+		 */
+		private static const COMPUTED_MATRIX_VALID:uint     = 0x1;
+		private static const COMPUTED_MATRIX3D_VALID:uint   = 0x2;
+		
+		/**
+		 * @private
+		 * general storage for all of our flags.  
+		 */
+		private var _flags:uint = 0;
+		
+		/**
+		 * @private
+		 * static data used by utility methods below
+		 */
+		private static var reVT:Vector3D = new Vector3D(0,0,0);
+		private static var reVR:Vector3D = new Vector3D(0,0,0);
+		private static var reVS:Vector3D = new Vector3D(1,1,1);
+		
+		private static var reV:Vector.<Vector3D> = new Vector.<Vector3D>();
+		reV.push(reVT);
+		reV.push(reVR);
+		reV.push(reVS);
+		
+		
+		private static const RADIANS_PER_DEGREES:Number = Math.PI / 180;
+		
+		private static const ZERO_REPLACEMENT_IN_3D:Number = .00000000000001;
+		
+		private static var tempLocalPosition:Vector3D;
+		
+		/**
+		 * @private
+		 * a pointer to the function we use to transform vectors, to work around a bug
+		 * in early versions of the flash player.
+		 */
+		private static var transformVector:Function = initTransformVectorFunction;
+		
+		/**
+		 * @private
+		 * an actionscript implementation to transform a vector by a matrix. Bugs in early versions of 
+		 * flash 10's implementation of Matrix.transformVector force us to do it ourselves in actionscript. 
+		 */
+		private static function pre10_0_22_87_transformVector(m:Matrix3D,v:Vector3D):Vector3D
+		{
+			var r:Vector.<Number> = m.rawData;
+			return new Vector3D(
+				r[0] * v.x + r[4] * v.y + r[8] * v.z + r[12], 
+				r[1] * v.x + r[5] * v.y + r[9] * v.z + r[13], 
+				r[2] * v.x + r[6] * v.y + r[10] * v.z + r[14],
+				1); 
+		}
+		
+		/**
+		 * @private
+		 * a  function to transform vectors using the built in player API, if we're in a late enough player version
+		 * that we won't run into bugs.s
+		 */
+		private static function nativeTransformVector(m:Matrix3D,v:Vector3D):Vector3D
+		{
+			return m.transformVector(v);
+		}
+		
+		/**
+		 * @private
+		 * the first time someone calls transformVector, they'll get this function.  It checks the player version,
+		 * and if decides which implementation to use based on whether a bug is present or not.
+		 */
+		private static function initTransformVectorFunction(m:Matrix3D,v:Vector3D):Vector3D
+		{
+			var canUseNative:Boolean = false;
+			var version:Array = Capabilities.version.split(' ')[1].split(',');
+			if (parseFloat(version[0]) > 10)
+				canUseNative  = true;
+			else if (parseFloat(version[1]) > 0)
+				canUseNative  = true;
+			else if (parseFloat(version[2]) > 22)
+				canUseNative  = true;
+			else if (parseFloat(version[3]) >= 87)
+				canUseNative  = true;
+			if (canUseNative)
+				transformVector = nativeTransformVector;
+			else
+				transformVector = pre10_0_22_87_transformVector;
+			
+			return transformVector(m,v);
+		}
+		
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 * layout transform convenience property.  Represents the x value of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutX(value:Number):void
+		{
+			layout.x = value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutX():Number
+		{
+			return layout.x;
+		}
+		/**
+		 * layout transform convenience property.  Represents the y value of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutY(value:Number):void
+		{
+			layout.y = value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutY():Number
+		{
+			return layout.y;
+		}
+		
+		/**
+		 * layout transform convenience property.  Represents the z value of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutZ(value:Number):void
+		{
+			layout.z = value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutZ():Number
+		{
+			return layout.z;
+		}
+		
+		//----------------------------------
+		//  layoutWidth
+		//----------------------------------
+		
+		private var _layoutWidth:Number = 0;
+		
+		/**
+		 *  Used by the mirroring transform.   See the mirror property.
+		 *  @default 0
+		 */
+		public function get layoutWidth():Number
+		{
+			return _layoutWidth;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set layoutWidth(value:Number):void
+		{
+			if (value == _layoutWidth)
+				return;
+			_layoutWidth = value;
+			invalidate();
+		}
+		
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 * @private
+		 * the x value of the point around which any rotation and scale is performed in both the layout and computed matrix.
+		 */
+		public function set transformX(value:Number):void
+		{
+			layout.transformX = value;
+			invalidate();
+		}
+		/**
+		 * @private
+		 */
+		public function get transformX():Number
+		{
+			return layout.transformX;
+		}
+		
+		/**
+		 * @private
+		 * the y value of the point around which any rotation and scale is performed in both the layout and computed matrix.
+		 */
+		public function set transformY(value:Number):void
+		{
+			layout.transformY = value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get transformY():Number
+		{
+			return layout.transformY;
+		}
+		
+		/**
+		 * @private
+		 * the z value of the point around which any rotation and scale is performed in both the layout and computed matrix.
+		 */
+		public function set transformZ(value:Number):void
+		{
+			layout.transformZ = value;  
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get transformZ():Number
+		{
+			return layout.transformZ;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		
+		/**
+		 * layout transform convenience property.  Represents the rotation around the X axis of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutRotationX(value:Number):void
+		{
+			layout.rotationX= value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutRotationX():Number
+		{
+			return layout.rotationX;
+		}
+		
+		/**
+		 * layout transform convenience property.  Represents the rotation around the Y axis of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutRotationY(value:Number):void
+		{
+			layout.rotationY= value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutRotationY():Number
+		{
+			return layout.rotationY;
+		}
+		
+		/**
+		 * layout transform convenience property.  Represents the rotation around the Z axis of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutRotationZ(value:Number):void
+		{
+			layout.rotationZ= value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutRotationZ():Number
+		{
+			return layout.rotationZ;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		
+		/**
+		 * layout transform convenience property.  Represents the scale along the X axis of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutScaleX(value:Number):void
+		{
+			layout.scaleX = value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutScaleX():Number
+		{
+			return layout.scaleX;
+		}
+		
+		/**
+		 * layout transform convenience property.  Represents the scale along the Y axis of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutScaleY(value:Number):void
+		{
+			layout.scaleY= value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutScaleY():Number
+		{
+			return layout.scaleY;
+		}
+		
+		
+		/**
+		 * layout transform convenience property.  Represents the scale along the Z axis of the layout matrix used in layout and in 
+		 * the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set layoutScaleZ(value:Number):void
+		{
+			layout.scaleZ= value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutScaleZ():Number
+		{
+			return layout.scaleZ;
+		}
+		
+		/**
+		 * @private
+		 * The 2D matrix used during layout calculations to determine the layout and size of the component and its parent and siblings.
+		 * If the convenience properties are set, this matrix is built from those properties.  
+		 * If the matrix is set directly, the convenience properties will be updated to values derived from this matrix.
+		 * This matrix is used in the calculation of the computed transform if possible. Under certain circumstances, such as when 
+		 * offsets are provided, the decomposed layout properties will be used instead.
+		 */
+		public function set layoutMatrix(value:Matrix):void
+		{
+			layout.matrix = value;
+			invalidate();
+		}
+		
+		
+		/**
+		 * @private
+		 */
+		public function get layoutMatrix():Matrix
+		{
+			return layout.matrix;
+			
+		}
+		
+		
+		/**
+		 * @private
+		 * The 3D matrix used during layout calculations to determine the layout and size of the component and its parent and siblings.
+		 * This matrix is only used by parents that respect 3D layoyut.
+		 * If the convenience properties are set, this matrix is built from those properties.  
+		 * If the matrix is set directly, the convenience properties will be updated to values derived from this matrix.
+		 * This matrix is used in the calculation of the computed transform if possible. Under certain circumstances, such as when 
+		 * offsets are provided, the decomposed layout properties will be used instead.
+		 */
+		public function set layoutMatrix3D(value:Matrix3D):void
+		{
+			layout.matrix3D = value;
+			invalidate();
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get layoutMatrix3D():Matrix3D
+		{
+			return layout.matrix3D;
+		}
+		
+		/**
+		 * true if the computed transform has 3D values.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get is3D():Boolean
+		{
+			return (layout.is3D || (postLayoutTransformOffsets != null && postLayoutTransformOffsets.is3D));
+		}
+		
+		/**
+		 * true if the layout transform has 3D values.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get layoutIs3D():Boolean
+		{
+			return layout.is3D;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		/** offsets to the transform convenience properties that are applied when a component is rendered. If this 
+		 * property is set, its values will be added to the layout transform properties to determine the true matrix used to render
+		 * the component
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set postLayoutTransformOffsets(value:TransformOffsets):void
+		{
+			if (_postLayoutTransformOffsets != null)
+			{
+				_postLayoutTransformOffsets.removeEventListener(Event.CHANGE,postLayoutTransformOffsetsChangedHandler);
+				_postLayoutTransformOffsets.owner = null;
+			}
+			_postLayoutTransformOffsets = value;
+			if (_postLayoutTransformOffsets != null)
+			{
+				_postLayoutTransformOffsets.addEventListener(Event.CHANGE,postLayoutTransformOffsetsChangedHandler);
+				_postLayoutTransformOffsets.owner = this;
+			}
+			invalidate();       
+		}
+		
+		public function get postLayoutTransformOffsets():TransformOffsets
+		{
+			return _postLayoutTransformOffsets;
+		}
+		
+		private function postLayoutTransformOffsetsChangedHandler(e:Event):void
+		{
+			invalidate();       
+		}
+		
+		//----------------------------------
+		//  mirror
+		//----------------------------------
+		
+		private var _mirror:Boolean = false;
+		
+		/**
+		 *  If true the X axis is scaled by -1 and the x coordinate of the origin
+		 *  is translated by the component's width.  
+		 * 
+		 *  The net effect of this "mirror" transform is to flip the direction 
+		 *  that the X axis increases in without changing the layout element's 
+		 *  location relative to the parent's origin.
+		 * 
+		 *  @default false
+		 */
+		public function get mirror():Boolean
+		{
+			return _mirror;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set mirror(value:Boolean):void
+		{
+			_mirror = value;
+			invalidate();
+		}
+		
+		
+		//----------------------------------
+		//  stretchX
+		//----------------------------------
+		
+		private var _stretchX:Number = 1;
+		
+		/**
+		 *  The stretchY is the horizontal component of the stretch scale factor which
+		 *  is applied before any other transformation property.
+		 *  @default 1
+		 */
+		public function get stretchX():Number
+		{
+			return _stretchX;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set stretchX(value:Number):void
+		{
+			if (value == _stretchX)
+				return;         
+			_stretchX = value;
+			invalidate();
+		}
+		
+		//----------------------------------
+		//  stretchY
+		//----------------------------------
+		
+		private var _stretchY:Number = 1;
+		
+		/**
+		 *  The stretchY is the vertical component of the stretch scale factor which
+		 *  is applied before any other transformation property.
+		 *  @default 1
+		 */
+		public function get stretchY():Number
+		{
+			return _stretchY;
+		}
+		
+		/**
+		 *  @private
+		 */
+		public function set stretchY(value:Number):void
+		{
+			if (value == _stretchY)
+				return;         
+			_stretchY = value;
+			invalidate();
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 * @private
+		 * invalidates our various cached values.  Any change to the AdvancedLayoutFeatures object that affects
+		 * the various transforms should call this function.    
+		 * @param reason - the code indicating what changes to cause the invalidation.
+		 * @param affects3D - a flag indicating whether the change affects the 2D/3D nature of the various transforms.
+		 * @param dispatchChangeEvent - if true, the AdvancedLayoutFeatures will dispatch a change indicating that its underlying transforms
+		 * have been modified. 
+		 */
+		private function invalidate():void
+		{                       
+			_flags &= ~COMPUTED_MATRIX_VALID;
+			_flags &= ~COMPUTED_MATRIX3D_VALID;
+		}
+		
+		
+		/**
+		 * the computed matrix, calculated by combining the layout matrix and  and any offsets provided..
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get computedMatrix():Matrix
+		{
+			if (_flags & COMPUTED_MATRIX_VALID)
+				return _computedMatrix;
+			
+			if (!postLayoutTransformOffsets && !mirror && stretchX == 1 && stretchY == 1)
+			{
+				return layout.matrix;
+			}           
+			
+			var m:Matrix = _computedMatrix;
+			if (m == null)
+				m = _computedMatrix = new Matrix();
+			else
+				m.identity();
+			
+			var tx:Number = layout.transformX;
+			var ty:Number = layout.transformY;
+			var sx:Number = layout.scaleX;
+			var sy:Number = layout.scaleY;
+			var rz:Number = layout.rotationZ;
+			var x:Number = layout.x;
+			var y:Number = layout.y;
+			
+			if (mirror)
+			{
+				sx *= -1;
+				x += layoutWidth;
+			}
+			
+			if (postLayoutTransformOffsets)
+			{
+				sx *= postLayoutTransformOffsets.scaleX;
+				sy *= postLayoutTransformOffsets.scaleY;
+				rz += postLayoutTransformOffsets.rotationZ;
+				x += postLayoutTransformOffsets.x;
+				y += postLayoutTransformOffsets.y;
+			}
+			
+			if (stretchX != 1 || stretchY != 1)
+				m.scale(stretchX, stretchY);
+			build2DMatrix(m, tx, ty, sx, sy, rz, x, y);
+			
+			_flags |= COMPUTED_MATRIX_VALID;
+			return m;
+		}
+		
+		/**
+		 * the computed 3D matrix, calculated by combining the 3D layout matrix and  and any offsets provided..
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get computedMatrix3D():Matrix3D
+		{
+			if (_flags & COMPUTED_MATRIX3D_VALID)
+				return _computedMatrix3D;
+			
+			
+			if (!postLayoutTransformOffsets && !mirror && stretchX == 1 && stretchY == 1)
+			{
+				return layout.matrix3D;
+			}
+			
+			var m:Matrix3D = _computedMatrix3D;
+			if (m == null)
+				m = _computedMatrix3D = new Matrix3D();
+			else
+				m.identity();
+			
+			var tx:Number = layout.transformX;
+			var ty:Number = layout.transformY;
+			var tz:Number = layout.transformZ;
+			var sx:Number = layout.scaleX;
+			var sy:Number = layout.scaleY;
+			var sz:Number = layout.scaleZ;
+			var rx:Number = layout.rotationX;
+			var ry:Number = layout.rotationY;
+			var rz:Number = layout.rotationZ;
+			var x:Number = layout.x;
+			var y:Number = layout.y;
+			var z:Number = layout.z;
+			
+			if (mirror)
+			{
+				sx *= -1;
+				x += layoutWidth;
+			}
+			
+			if (postLayoutTransformOffsets)
+			{
+				sx *= postLayoutTransformOffsets.scaleX;
+				sy *= postLayoutTransformOffsets.scaleY;
+				sz *= postLayoutTransformOffsets.scaleZ;
+				rx += postLayoutTransformOffsets.rotationX;
+				ry += postLayoutTransformOffsets.rotationY;
+				rz += postLayoutTransformOffsets.rotationZ;
+				x += postLayoutTransformOffsets.x;
+				y += postLayoutTransformOffsets.y;
+				z += postLayoutTransformOffsets.z;
+			}
+			
+			build3DMatrix(m, tx, ty, tz, sx, sy, sz, rx, ry, rz, x, y, z);
+			// Always prepend last
+			if (stretchX != 1 || stretchY != 1)
+				m.prependScale(stretchX, stretchY, 1);  
+			
+			_flags |= COMPUTED_MATRIX3D_VALID;
+			return m;           
+		}
+		
+		
+		/**
+		 * @private
+		 * convenience function for building a 2D matrix from the convenience properties 
+		 */
+		public static function build2DMatrix(m:Matrix,
+											 tx:Number,ty:Number,
+											 sx:Number,sy:Number,
+											 rz:Number,
+											 x:Number,y:Number):void
+		{
+			m.translate(-tx,-ty);
+			m.scale(sx,sy);
+			m.rotate(rz* RADIANS_PER_DEGREES);
+			m.translate(x+tx,y+ty);         
+		}
+		
+		
+		/**
+		 * @private
+		 * convenience function for building a 3D matrix from the convenience properties 
+		 */
+		public static function build3DMatrix(m:Matrix3D,
+											 tx:Number,ty:Number,tz:Number,
+											 sx:Number,sy:Number,sz:Number,
+											 rx:Number,ry:Number,rz:Number,
+											 x:Number,y:Number,z:Number):void
+		{
+			reVR.x = rx * RADIANS_PER_DEGREES;
+			reVR.y = ry * RADIANS_PER_DEGREES;
+			reVR.z = rz * RADIANS_PER_DEGREES;
+			m.recompose(reV);
+			if (sx == 0)
+				sx = ZERO_REPLACEMENT_IN_3D;
+			if (sy == 0)
+				sy = ZERO_REPLACEMENT_IN_3D;
+			if (sz == 0)
+				sz = ZERO_REPLACEMENT_IN_3D;
+			m.prependScale(sx,sy,sz);
+			m.prependTranslation(-tx,-ty,-tz);
+			m.appendTranslation(tx+x,ty+y,tz+z);
+		}                                   
+		
+		
+		/**
+		 * A utility method to transform a point specified in the local
+		 * coordinates of this object to its location in the object's parent's 
+		 * coordinates. The pre-layout and post-layout result will be set on 
+		 * the <code>position</code> and <code>postLayoutPosition</code>
+		 * parameters, if they are non-null.
+		 * 
+		 * @param propertyIs3D A boolean reflecting whether the calculation needs
+		 * to take into account the 3D matrix of the object.
+		 * @param localPoint The point to be transformed, specified in the
+		 * local coordinates of the object.
+		 * @position A Vector3D point that will hold the pre-layout
+		 * result. If null, the parameter is ignored.
+		 * @postLayoutPosition A Vector3D point that will hold the post-layout
+		 * result. If null, the parameter is ignored.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4
+		 */
+		public function transformPointToParent(propertyIs3D:Boolean,
+											   localPosition:Vector3D, position:Vector3D,
+											   postLayoutPosition:Vector3D):void
+		{
+			var transformedV:Vector3D;
+			var transformedP:Point;
+			tempLocalPosition = 
+				localPosition ?
+				localPosition.clone() :
+				new Vector3D();
+			
+			if (is3D || propertyIs3D) 
+			{
+				if (position != null)
+				{
+					transformedV = transformVector(layoutMatrix3D, tempLocalPosition); 
+					position.x = transformedV.x;
+					position.y = transformedV.y;
+					position.z = transformedV.z;
+				} 
+				
+				if (postLayoutPosition != null)
+				{           
+					// computedMatrix factor in stretchXY, so divide it out of position first
+					tempLocalPosition.x /= stretchX;
+					tempLocalPosition.y /= stretchY;
+					transformedV = transformVector(computedMatrix3D, tempLocalPosition);
+					postLayoutPosition.x = transformedV.x;
+					postLayoutPosition.y = transformedV.y;
+					postLayoutPosition.z = transformedV.z;
+				}
+			}
+			else
+			{
+				var localP:Point = new Point(tempLocalPosition.x, 
+					tempLocalPosition.y);
+				if (position != null)
+				{
+					transformedP = layoutMatrix.transformPoint(localP);
+					position.x = transformedP.x;
+					position.y = transformedP.y;
+					position.z = 0;
+				}
+				
+				if (postLayoutPosition != null)
+				{
+					// computedMatrix factor in stretchXY, so divide it out of position first
+					localP.x /= stretchX;
+					localP.y /= stretchY;
+					transformedP = computedMatrix.transformPoint(localP);
+					postLayoutPosition.x = transformedP.x;
+					postLayoutPosition.y = transformedP.y;
+					postLayoutPosition.z = 0;
+				}
+			}
+		}
+		
+		/**
+		 * @private
+		 * call when you've changed the inputs to the computed transform to make 
+		 * any adjustments to keep a particular point fixed in parent coordinates.
+		 */
+		private function completeTransformCenterAdjustment(changeIs3D:Boolean, 
+														   transformCenter:Vector3D, targetPosition:Vector3D,
+														   targetPostLayoutPosition:Vector3D):void
+		{
+			// TODO (chaase): optimize for transformCenter == (0,0,0)
+			if (is3D || changeIs3D)
+			{
+				if (targetPosition != null)
+				{
+					var adjustedLayoutCenterV:Vector3D = transformVector(layoutMatrix3D, transformCenter); 
+					if (adjustedLayoutCenterV.equals(targetPosition) == false)
+					{
+						layout.translateBy(targetPosition.x - adjustedLayoutCenterV.x,
+							targetPosition.y - adjustedLayoutCenterV.y, 
+							targetPosition.z - adjustedLayoutCenterV.z);
+						invalidate(); 
+					}       
+				}
+				if (targetPostLayoutPosition != null && _postLayoutTransformOffsets != null)
+				{
+					// computedMatrix factor in stretchXY, so divide it out of transform center first
+					var tmpPos:Vector3D = new Vector3D(transformCenter.x, transformCenter.y, transformCenter.z);
+					tmpPos.x /= stretchX;
+					tmpPos.y /= stretchY;
+					var adjustedComputedCenterV:Vector3D = transformVector(computedMatrix3D, tmpPos);
+					if (adjustedComputedCenterV.equals(targetPostLayoutPosition) == false)
+					{
+						postLayoutTransformOffsets.x +=targetPostLayoutPosition.x - adjustedComputedCenterV.x;
+						postLayoutTransformOffsets.y += targetPostLayoutPosition.y - adjustedComputedCenterV.y;
+						postLayoutTransformOffsets.z += targetPostLayoutPosition.z - adjustedComputedCenterV.z;
+						invalidate(); 
+					}       
+				}
+			}
+			else
+			{
+				var transformCenterP:Point = new Point(transformCenter.x,transformCenter.y);
+				if (targetPosition != null)
+				{
+					var currentPositionP:Point = layoutMatrix.transformPoint(transformCenterP);
+					if (currentPositionP.x != targetPosition.x || 
+						currentPositionP.y != targetPosition.y)
+					{
+						layout.translateBy(targetPosition.x - currentPositionP.x,
+							targetPosition.y - currentPositionP.y, 0);
+						invalidate(); 
+					}       
+				}
+				
+				if (targetPostLayoutPosition != null && _postLayoutTransformOffsets != null)
+				{           
+					// computedMatrix factor in stretchXY, so divide it out of transform center first
+					transformCenterP.x /= stretchX;
+					transformCenterP.y /= stretchY;
+					var currentPostLayoutPosition:Point = 
+						computedMatrix.transformPoint(transformCenterP);
+					if (currentPostLayoutPosition.x != targetPostLayoutPosition.x || 
+						currentPostLayoutPosition.y != targetPostLayoutPosition.y)
+					{
+						_postLayoutTransformOffsets.x += targetPostLayoutPosition.x - currentPostLayoutPosition.x;
+						_postLayoutTransformOffsets.y += targetPostLayoutPosition.y - currentPostLayoutPosition.y;
+						invalidate(); 
+					}       
+				}
+			}
+		}   
+		
+		private static var staticTranslation:Vector3D = new Vector3D();
+		private static var staticOffsetTranslation:Vector3D = new Vector3D();
+		
+		/**
+		 * A utility method to update the rotation and scale of the transform 
+		 * while keeping a particular point, specified in the component's own 
+		 * coordinate space, fixed in the parent's coordinate space.  This 
+		 * function will assign the rotation and scale values provided, then 
+		 * update the x/y/z properties as necessary to keep tx/ty/tz fixed.
+		 * @param transformCenter the point, in the component's own coordinates, 
+		 * to keep fixed relative to its parent.
+		 * @param rotation the new values for the rotation of the transform
+		 * @param scale the new values for the scale of the transform
+		 * @param translation the new values for the translation of the transform
+		 */
+		public function transformAround(transformCenter:Vector3D,
+										scale:Vector3D,
+										rotation:Vector3D,
+										transformCenterPosition:Vector3D,
+										postLayoutScale:Vector3D = null,
+										postLayoutRotation:Vector3D = null,
+										postLayoutTransformCenterPosition:Vector3D = null):void
+		{
+			var is3D:Boolean = (scale != null && scale.z != 1) ||
+				(rotation != null && ((rotation.x != 0 ) || (rotation.y != 0))) || 
+				(transformCenterPosition != null && transformCenterPosition.z != 0) ||
+				(postLayoutScale != null && postLayoutScale.z != 1) ||
+				(postLayoutRotation != null && 
+					(postLayoutRotation.x != 0 || postLayoutRotation.y != 0)) || 
+				(postLayoutTransformCenterPosition != null && postLayoutTransformCenterPosition.z != 0);
+			
+			var needOffsets:Boolean = _postLayoutTransformOffsets == null && 
+				(postLayoutScale != null || postLayoutRotation != null || 
+					postLayoutTransformCenterPosition != null);
+			if (needOffsets)
+				_postLayoutTransformOffsets = new TransformOffsets();                                               
+			
+			// now if they gave us a non-trivial transform center, and didn't tell us where they want it, 
+			// we need to calculate where it is so that we can make sure we keep it there.             
+			if (transformCenter != null && 
+				(transformCenterPosition == null || postLayoutTransformCenterPosition == null))
+			{           
+				transformPointToParent(is3D, transformCenter, staticTranslation,
+					staticOffsetTranslation);
+				if (postLayoutTransformCenterPosition == null && transformCenterPosition != null)
+				{
+					staticOffsetTranslation.x = transformCenterPosition.x + staticOffsetTranslation.x - staticTranslation.x;
+					staticOffsetTranslation.y = transformCenterPosition.y + staticOffsetTranslation.y - staticTranslation.y;
+					staticOffsetTranslation.z = transformCenterPosition.z + staticOffsetTranslation.z - staticTranslation.z;
+				}
+				
+			}
+			// if targetPosition/postLayoutTargetPosition is null here, it might be because the caller passed in
+			// requested values, so we haven't calculated it yet.  So that means our target position is the values
+			// they passed in.        
+			var targetPosition:Vector3D = (transformCenterPosition == null)? staticTranslation:transformCenterPosition;
+			var postLayoutTargetPosition:Vector3D = (postLayoutTransformCenterPosition == null)? staticOffsetTranslation:postLayoutTransformCenterPosition;
+			
+			// now update our transform values.     
+			if (rotation != null)
+			{
+				if (!isNaN(rotation.x))
+					layout.rotationX = rotation.x;
+				if (!isNaN(rotation.y))
+					layout.rotationY = rotation.y;
+				if (!isNaN(rotation.z))
+					layout.rotationZ = rotation.z;
+			}
+			if (scale != null)
+			{           
+				if (!isNaN(scale.x))
+					layout.scaleX = scale.x;
+				if (!isNaN(scale.y))
+					layout.scaleY = scale.y;
+				if (!isNaN(scale.z))
+					layout.scaleZ = scale.z;
+			}
+			
+			if (postLayoutRotation != null)
+			{           
+				_postLayoutTransformOffsets.rotationX = postLayoutRotation.x;
+				_postLayoutTransformOffsets.rotationY = postLayoutRotation.y;
+				_postLayoutTransformOffsets.rotationZ = postLayoutRotation.z;
+			}
+			if (postLayoutScale != null)
+			{           
+				_postLayoutTransformOffsets.scaleX = postLayoutScale.x;
+				_postLayoutTransformOffsets.scaleY = postLayoutScale.y;
+				_postLayoutTransformOffsets.scaleZ = postLayoutScale.z;
+			}
+			
+			// if they didn't pass us a transform center, 
+			// then we assume it's the origin. In that case, it's trivially easy
+			// to make sure the origin is at a particular point...we simply set 
+			// the transformCenterPosition portion of our transforms to that point. 
+			if (transformCenter == null)
+			{
+				if (transformCenterPosition != null)
+				{
+					layout.x = transformCenterPosition.x;
+					layout.y = transformCenterPosition.y;
+					layout.z = transformCenterPosition.z;
+				}
+				if (postLayoutTransformCenterPosition != null)
+				{
+					_postLayoutTransformOffsets.x = postLayoutTransformCenterPosition.x - layout.x;
+					_postLayoutTransformOffsets.y = postLayoutTransformCenterPosition.y - layout.y;
+					_postLayoutTransformOffsets.z = postLayoutTransformCenterPosition.z - layout.z;
+				}
+			}
+			invalidate();
+			
+			// if they did pass in a transform center, go do the adjustments necessary to keep it fixed in place.
+			if (transformCenter != null)
+				completeTransformCenterAdjustment(is3D, transformCenter, 
+					targetPosition, postLayoutTargetPosition);
+			
+			
+		}
+		
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/9999c237/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/CompoundTransform.as
----------------------------------------------------------------------
diff --git a/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/CompoundTransform.as b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/CompoundTransform.as
new file mode 100644
index 0000000..7b1916b
--- /dev/null
+++ b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/CompoundTransform.as
@@ -0,0 +1,777 @@
+/**
+ * Licensed 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.core.graphics.utils
+{
+	import flash.geom.Matrix;
+	import flash.geom.Matrix3D;
+	import flash.geom.Vector3D;
+	
+	import __AS3__.vec.Vector;
+	
+	/**
+	 *  A CompoundTransform represents a 2D or 3D matrix transform.  A compound transform represents a matrix that can be queried or set either as a 2D matrix,
+	 *  a 3D matrix, or as individual convenience transform properties such as x, y, scaleX, rotationZ, etc. 
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	public class CompoundTransform
+	{
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		/**
+		 *  Constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function CompoundTransform()
+		{
+		}
+		
+		
+		
+		/**
+		 * @private
+		 * storage for transform properties. These values are concatenated together with the layout properties to
+		 * form the actual computed matrix used to render the object.
+		 */
+		private var _rotationX:Number = 0;
+		private var _rotationY:Number = 0;
+		private var _rotationZ:Number = 0;
+		private var _scaleX:Number = 1;
+		private var _scaleY:Number = 1;
+		private var _scaleZ:Number = 1;     
+		private var _x:Number = 0;
+		private var _y:Number = 0;
+		private var _z:Number = 0;
+		
+		private var _transformX:Number = 0;
+		private var _transformY:Number = 0;
+		private var _transformZ:Number = 0;
+		
+		
+		/**
+		 * @private
+		 * slots for the 2D and 3D matrix transforms.  Note that 
+		 * these are only allocated and computed on demand -- many component instances will never use a 3D
+		 * matrix, for example. 
+		 */
+		private var _matrix:Matrix;
+		private var _matrix3D:Matrix3D;
+		
+		
+		/**
+		 * @private
+		 * bit field flags for indicating which transforms are valid -- the layout properties, the matrices,
+		 * and the 3D matrices.  Since developers can set any of the three programmatically, the last one set
+		 * will always be valid, and the others will be invalid until validated on demand.
+		 */
+		private static const MATRIX_VALID:uint      = 0x20;
+		private static const MATRIX3D_VALID:uint        = 0x40;
+		private static const PROPERTIES_VALID:uint  = 0x80;
+		
+		
+		/**
+		 * @private
+		 * flags for tracking whether the  transform is 3D. A transform is 3D if any of the 3D properties -- rotationX/Y, scaleZ, or z -- are set.
+		 */
+		private static const IS_3D:uint                 = 0x200;
+		private static const M3D_FLAGS_VALID:uint           = 0x400;
+		
+		/**
+		 * @private
+		 * constants to indicate which form of a transform -- the properties, matrix, or matrix3D -- is
+		 *  'the source of truth.'   
+		 */
+		public static const SOURCE_PROPERTIES:uint          = 1;
+		/**
+		 * @private
+		 * constants to indicate which form of a transform -- the properties, matrix, or matrix3D -- is
+		 *  'the source of truth.'   
+		 */
+		public static const SOURCE_MATRIX:uint          = 2;
+		/**
+		 * @private
+		 * constants to indicate which form of a transform -- the properties, matrix, or matrix3D -- is
+		 *  'the source of truth.'   
+		 */
+		public static const SOURCE_MATRIX3D:uint            = 3;
+		
+		/**
+		 * @private
+		 * indicates the 'source of truth' for the transform.  
+		 */
+		public var sourceOfTruth:uint = SOURCE_PROPERTIES;
+		
+		/**
+		 * @private
+		 * general storage for all of ur flags.  
+		 */
+		private var _flags:uint =  PROPERTIES_VALID;
+		
+		/**
+		 * @private
+		 * flags that get passed to the invalidate method indicating why the invalidation is happening.
+		 */
+		private static const INVALIDATE_FROM_NONE:uint =            0;                      
+		private static const INVALIDATE_FROM_PROPERTY:uint =        4;                      
+		private static const INVALIDATE_FROM_MATRIX:uint =          5;                      
+		private static const INVALIDATE_FROM_MATRIX3D:uint =        6;                      
+		
+		/**
+		 * @private
+		 * static data used by utility methods below
+		 */
+		private static var decomposition:Vector.<Number> = new Vector.<Number>();
+		decomposition.push(0);
+		decomposition.push(0);
+		decomposition.push(0);
+		decomposition.push(0);
+		decomposition.push(0);
+		
+		private static const RADIANS_PER_DEGREES:Number = Math.PI / 180;
+		
+		//----------------------------------------------------------------------------
+		
+		/**
+		 *  The x value of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set x(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _x)
+				return;
+			translateBy(value-_x,0,0);
+			invalidate(INVALIDATE_FROM_PROPERTY, false /*affects3D*/);
+		}
+		/**
+		 * @private
+		 */
+		public function get x():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _x;
+		}
+		
+		/**
+		 *  The y value of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set y(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _y)
+				return;
+			translateBy(0,value-_y,0);
+			invalidate(INVALIDATE_FROM_PROPERTY, false /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get y():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _y;
+		}
+		
+		/**
+		 *  The z value of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set z(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _z)
+				return;
+			translateBy(0,0,value-_z);
+			invalidate(INVALIDATE_FROM_PROPERTY, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get z():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _z;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		
+		/**
+		 *  The rotationX, in degrees, of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set rotationX(value:Number):void
+		{
+			// clamp the rotation value between -180 and 180.  This is what 
+			// the Flash player does, so let's mimic it here too.
+			value = MatrixUtil.clampRotation(value);
+			
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _rotationX)
+				return;
+			_rotationX = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get rotationX():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _rotationX;
+		}
+		
+		/**
+		 *  The rotationY, in degrees, of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set rotationY(value:Number):void
+		{
+			// clamp the rotation value between -180 and 180.  This is what 
+			// the Flash player does, so let's mimic it here too.
+			value = MatrixUtil.clampRotation(value);
+			
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _rotationY)
+				return;
+			_rotationY = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get rotationY():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _rotationY;
+		}
+		
+		/**
+		 *  The rotationZ, in degrees, of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set rotationZ(value:Number):void
+		{
+			// clamp the rotation value between -180 and 180.  This is what 
+			// the Flash player does, so let's mimic it here too.
+			value = MatrixUtil.clampRotation(value);
+			
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _rotationZ)
+				return;
+			_rotationZ = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, false /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get rotationZ():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _rotationZ;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		
+		/**
+		 *  The scaleX of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set scaleX(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _scaleX)
+				return;
+			_scaleX = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, false /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get scaleX():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _scaleX;
+		}
+		
+		/**
+		 *  The scaleY of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set scaleY(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _scaleY)
+				return;
+			_scaleY = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, false /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get scaleY():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _scaleY;
+		}
+		
+		
+		/**
+		 *  The scaleZ of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set scaleZ(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _scaleZ)
+				return;
+			_scaleZ = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get scaleZ():Number
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			return _scaleZ;
+		}
+		
+		
+		/**
+		 * @private
+		 * returns true if the transform has 3D values.
+		 */
+		public function get is3D():Boolean
+		{
+			if ((_flags & M3D_FLAGS_VALID) == 0)
+				update3DFlags();
+			return ((_flags & IS_3D) != 0);
+		}
+		
+		//------------------------------------------------------------------------------
+		/**
+		 *  The x value of the transform center. The transform center is kept fixed as rotation and scale are applied. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set transformX(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _transformX)
+				return;
+			_transformX = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get transformX():Number
+		{
+			return _transformX;
+		}
+		
+		//------------------------------------------------------------------------------
+		/**
+		 *  The y value of the tansform center. The transform center is kept fixed as rotation and scale are applied. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set transformY(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _transformY)
+				return;
+			_transformY = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get transformY():Number
+		{
+			return _transformY;
+		}
+		//------------------------------------------------------------------------------
+		/**
+		 *  The z value of the tansform center. The transform center is kept fixed as rotation and scale are applied. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set transformZ(value:Number):void
+		{
+			if ((_flags & PROPERTIES_VALID) == false) validatePropertiesFromMatrix();
+			if (value == _transformZ)
+				return;
+			_transformZ = value;
+			invalidate(INVALIDATE_FROM_PROPERTY, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get transformZ():Number
+		{
+			return _transformZ;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 * @private
+		 * invalidates our various cached values.  Any change to the CompoundTransform object that affects
+		 * the various transforms should call this function. 
+		 * @param reason - the code indicating what changes to cause the invalidation.
+		 * @param affects3D - a flag indicating whether the change affects the 2D/3D nature of the various transforms.
+		 * @param dispatchChangeEvent - if true, the CompoundTransform will dispatch a change indicating that its underlying transforms
+		 * have been modified. 
+		 */
+		private function invalidate(reason:uint, affects3D:Boolean):void
+		{
+			//race("invalidating: " + reason);
+			switch(reason)
+			{
+				case INVALIDATE_FROM_PROPERTY:
+					sourceOfTruth = SOURCE_PROPERTIES;
+					_flags |= PROPERTIES_VALID;
+					_flags &= ~MATRIX_VALID;
+					_flags &= ~MATRIX3D_VALID;
+					break;
+				case INVALIDATE_FROM_MATRIX:
+					sourceOfTruth = SOURCE_MATRIX;
+					_flags |= MATRIX_VALID;
+					_flags &= ~PROPERTIES_VALID;
+					_flags &= ~MATRIX3D_VALID;
+					break;
+				case INVALIDATE_FROM_MATRIX3D:
+					sourceOfTruth = SOURCE_MATRIX3D;
+					_flags |= MATRIX3D_VALID;
+					_flags &= ~PROPERTIES_VALID;
+					_flags &= ~MATRIX_VALID;
+					break;
+			}                       
+			if (affects3D)
+				_flags &= ~M3D_FLAGS_VALID;
+			
+		}
+		
+		private static const EPSILON:Number = .001;
+		/**
+		 * @private
+		 * updates the flags that indicate whether the layout, offset, and/or computed transforms are 3D in nature.  
+		 * Since the user can set either the individual transform properties or the matrices directly, we compute these 
+		 * flags based on what the current 'source of truth' is for each of these values.
+		 */
+		private function update3DFlags():void
+		{           
+			if ((_flags & M3D_FLAGS_VALID) == 0)
+			{
+				var matrixIs3D:Boolean = false;
+				
+				switch(sourceOfTruth)
+				{
+					case SOURCE_PROPERTIES:
+						matrixIs3D = ( // note that rotationZ is the same as rotation, and not a 3D affecting                           
+							(Math.abs(_scaleZ-1) > EPSILON) ||  // property.
+							((Math.abs(_rotationX)+EPSILON)%360) > 2*EPSILON ||
+							((Math.abs(_rotationY)+EPSILON)%360) > 2*EPSILON ||
+							Math.abs(_z) > EPSILON
+						);
+						break;
+					case SOURCE_MATRIX:
+						matrixIs3D = false;
+						break;
+					case SOURCE_MATRIX3D:
+						var rawData:Vector.<Number> = _matrix3D.rawData;                    
+						matrixIs3D = (rawData[2] != 0 ||        // rotation y 
+							rawData[6] != 0 ||      // rotation x
+							rawData[8] !=0 ||       // rotation y
+							rawData[10] != 1 ||     // scalez / rotation x / rotation y
+							rawData[14] != 0);      // translation z
+						break;                              
+				}
+				
+				if (matrixIs3D)
+					_flags |= IS_3D;
+				else
+					_flags &= ~IS_3D;
+				
+				_flags |= M3D_FLAGS_VALID;
+			}
+		}
+		
+		
+		/** 
+		 *  Applies the delta to the transform's translation component. Unlike setting the x, y, or z properties directly,
+		 *  this method can be safely called without changing the transform's concept of 'the source of truth'.
+		 * 
+		 *  @param x The x value of the transform.
+		 *  
+		 *  @param y The y value of the transform.
+		 *  
+		 *  @param z The z value of the transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function translateBy(x:Number,y:Number,z:Number = 0):void
+		{
+			if (_flags & MATRIX_VALID)
+			{
+				_matrix.tx += x;
+				_matrix.ty += y;
+			}
+			if (_flags & PROPERTIES_VALID)
+			{
+				_x += x;
+				_y += y;
+				_z += z;
+			}
+			if (_flags & MATRIX3D_VALID)
+			{
+				var data:Vector.<Number> = _matrix3D.rawData;
+				data[12] += x;
+				data[13] += y;
+				data[14] += z;
+				_matrix3D.rawData = data;           
+			}   
+			invalidate(INVALIDATE_FROM_NONE, z != 0 /*affects3D*/);
+		}
+		
+		
+		/**
+		 *  The 2D matrix either set directly by the user, or composed by combining the transform center, scale, rotation
+		 *  and translation, in that order.  
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get matrix():Matrix
+		{
+			
+			if (_flags & MATRIX_VALID)
+				return _matrix;
+			
+			if ((_flags & PROPERTIES_VALID) == false)
+				validatePropertiesFromMatrix();
+			
+			var m:Matrix = _matrix;
+			if (m == null)
+				m = _matrix = new Matrix();
+			else
+				m.identity();
+			
+			AdvancedLayoutFeatures.build2DMatrix(m,_transformX,_transformY,
+				_scaleX,_scaleY,
+				_rotationZ,
+				_x,_y);   
+			_flags |= MATRIX_VALID;
+			return m;       
+		}
+		
+		/**
+		 * @private
+		 */ 
+		public function set matrix(v:Matrix):void
+		{
+			if (_matrix== null)
+			{
+				_matrix = v.clone();
+			}
+			else
+			{
+				_matrix.identity(); 
+				_matrix.concat(v);          
+			}
+			
+			// affects3D is true since setting matrix changes the transform to 2D
+			invalidate(INVALIDATE_FROM_MATRIX, true /*affects3D*/);
+		}
+		
+		/**
+		 * @private
+		 * decomposes the offset transform matrices down into the convenience offset properties. Note that this is not
+		 * a bi-directional transformation -- it is possible to create a matrix that can't be fully represented in the
+		 * convenience properties. This function will pull from the matrix or matrix3D values, depending on which was most
+		 * recently set
+		 */
+		private function validatePropertiesFromMatrix():void
+		{       
+			if (sourceOfTruth == SOURCE_MATRIX3D)
+			{
+				var result:Vector.<Vector3D> = _matrix3D.decompose();
+				_rotationX = result[1].x / RADIANS_PER_DEGREES;
+				_rotationY = result[1].y / RADIANS_PER_DEGREES;
+				_rotationZ = result[1].z / RADIANS_PER_DEGREES;
+				_scaleX = result[2].x;
+				_scaleY = result[2].y;
+				_scaleZ = result[2].z;
+				
+				if (_transformX != 0 || _transformY != 0 || _transformZ != 0)
+				{
+					var postTransformTCenter:Vector3D = _matrix3D.transformVector(new Vector3D(_transformX,_transformY,_transformZ));
+					_x = postTransformTCenter.x - _transformX;
+					_y = postTransformTCenter.y - _transformY;
+					_z = postTransformTCenter.z - _transformZ;
+				}
+				else
+				{
+					_x = result[0].x;
+					_y = result[0].y;
+					_z = result[0].z;
+				}
+			}                        
+			else if (sourceOfTruth == SOURCE_MATRIX)
+			{
+				MatrixUtil.decomposeMatrix(decomposition,_matrix,_transformX,_transformY);
+				_x = decomposition[0];
+				_y = decomposition[1];
+				_z = 0;
+				_rotationX = 0;
+				_rotationY = 0;
+				_rotationZ = decomposition[2];
+				_scaleX = decomposition[3];
+				_scaleY = decomposition[4];
+				_scaleZ = 1;
+			}
+			_flags |= PROPERTIES_VALID;
+			
+		}
+		
+		
+		
+		/**
+		 *  The 3D matrix either set directly by the user, or composed by combining the transform center, scale, rotation
+		 *  and translation, in that order. 
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function get matrix3D():Matrix3D
+		{
+			if (_flags & MATRIX3D_VALID)
+				return _matrix3D;
+			
+			if ((_flags & PROPERTIES_VALID) == false)
+				validatePropertiesFromMatrix();
+			
+			var m:Matrix3D = _matrix3D;
+			if (m == null)
+				m =  _matrix3D = new Matrix3D();
+			else
+				m.identity();
+			
+			AdvancedLayoutFeatures.build3DMatrix(m,transformX,transformY,transformZ,
+				_scaleX,_scaleY,_scaleZ,
+				_rotationX,_rotationY,_rotationZ,                       
+				_x,_y,_z);
+			_flags |= MATRIX3D_VALID;
+			return m;
+			
+		}
+		
+		/**
+		 * @private
+		 */
+		public function set matrix3D(v:Matrix3D):void
+		{
+			if (_matrix3D == null)
+			{
+				_matrix3D = v.clone();
+			}
+			else
+			{
+				_matrix3D.identity();
+				if (v)
+					_matrix3D.append(v);            
+			}
+			invalidate(INVALIDATE_FROM_MATRIX3D, true /*affects3D*/);
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/9999c237/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/IAssetLayoutFeatures.as
----------------------------------------------------------------------
diff --git a/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/IAssetLayoutFeatures.as b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/IAssetLayoutFeatures.as
new file mode 100644
index 0000000..1e36b60
--- /dev/null
+++ b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/IAssetLayoutFeatures.as
@@ -0,0 +1,371 @@
+/**
+ * Licensed 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.core.graphics.utils
+{
+	import flash.geom.Matrix;
+	import flash.geom.Matrix3D;
+	
+	
+	/**
+	 *  The IAssetLayoutFeatures interface defines the minimum properties and methods 
+	 *  required for an Object to support advanced transforms in embedded assets.
+	 *  
+	 *  @see mx.core.AdvancedLayoutFeatures
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @productversion Flex 4.1
+	 */
+	public interface IAssetLayoutFeatures
+	{
+		
+		/**
+		 *  Layout transform convenience property.  Represents the x value of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutX(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutX():Number;
+		
+		/**
+		 *  Layout transform convenience property.  Represents the y value of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutY(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutY():Number;
+		
+		/**
+		 *  Layout transform convenience property.  Represents the z value of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutZ(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutZ():Number;
+		
+		/**
+		 *  Used by the mirroring transform. See the mirror property.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get layoutWidth():Number;
+		
+		/**
+		 *  @private
+		 */
+		function set layoutWidth(value:Number):void;
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 *  The x value of the point around which any rotation and scale is performed in both the layout and computed matrix.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set transformX(value:Number):void;
+		/**
+		 * @private
+		 */
+		function get transformX():Number;
+		
+		/**
+		 *  The y value of the point around which any rotation and scale is performed in both the layout and computed matrix.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set transformY(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get transformY():Number;
+		
+		/**
+		 *  The z value of the point around which any rotation and scale is performed in both the layout and computed matrix.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set transformZ(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get transformZ():Number;
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 *  Layout transform convenience property.  Represents the rotation around the X axis of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutRotationX(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutRotationX():Number;
+		
+		/**
+		 *  Layout transform convenience property.  Represents the rotation around the Y axis of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutRotationY(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutRotationY():Number;
+		
+		/**
+		 *  Layout transform convenience property.  Represents the rotation around the Z axis of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutRotationZ(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutRotationZ():Number;
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 *  Layout transform convenience property.  Represents the scale along the X axis of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutScaleX(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutScaleX():Number;
+		
+		/**
+		 *  Layout transform convenience property.  Represents the scale along the Y axis of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutScaleY(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutScaleY():Number;
+		
+		/**
+		 *  Layout transform convenience property.  Represents the scale along the Z axis of the layout matrix used in layout and in 
+		 *  the computed transform.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutScaleZ(value:Number):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutScaleZ():Number;
+		
+		/**
+		 *  The 2D matrix used during layout calculations to determine the layout and size of the component and its parent and siblings.
+		 *  
+		 *   @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutMatrix(value:Matrix):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutMatrix():Matrix;
+		
+		/**
+		 *  The 3D matrix used during layout calculations to determine the layout and size of the component and its parent and siblings.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function set layoutMatrix3D(value:Matrix3D):void;
+		
+		/**
+		 * @private
+		 */
+		function get layoutMatrix3D():Matrix3D;
+		
+		/**
+		 *  True if the computed transform has 3D values.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get is3D():Boolean;
+		
+		/**
+		 *  True if the layout transform has 3D values.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get layoutIs3D():Boolean;
+		
+		/**
+		 *  If true the X axis is scaled by -1 and the x coordinate of the origin
+		 *  is translated by the component's width.  
+		 * 
+		 *  The net effect of this "mirror" transform is to flip the direction 
+		 *  that the X axis increases in without changing the layout element's 
+		 *  location relative to the parent's origin.
+		 * 
+		 *  @default false
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get mirror():Boolean;
+		
+		/**
+		 *  @private
+		 */
+		function set mirror(value:Boolean):void;
+		
+		
+		/**
+		 *  The stretchY is the horizontal component of the stretch scale factor which
+		 *  is applied before any other transformation property.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get stretchX():Number;
+		
+		/**
+		 *  @private
+		 */
+		function set stretchX(value:Number):void;
+		
+		/**
+		 *  The stretchY is the vertical component of the stretch scale factor which
+		 *  is applied before any other transformation property.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get stretchY():Number;
+		
+		/**
+		 *  @private
+		 */
+		function set stretchY(value:Number):void;
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 *  The computed matrix, calculated by combining the layout matrix and any offsets provided.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get computedMatrix():Matrix;
+		
+		/**
+		 *  The computed 3D matrix, calculated by combining the 3D layout matrix and any offsets provided.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 1.5
+		 *  @productversion Flex 4.1
+		 */
+		function get computedMatrix3D():Matrix3D;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/9999c237/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/PathHelper.as
----------------------------------------------------------------------
diff --git a/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/PathHelper.as b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/PathHelper.as
index 31bfd0e..5b5e136 100644
--- a/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/PathHelper.as
+++ b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/PathHelper.as
@@ -15,18 +15,25 @@
 package org.apache.flex.core.graphics.utils
 {
 	import flash.display.GraphicsPath;
+	import flash.geom.Rectangle;
 
 	public class PathHelper
 	{
 		private static var segments:PathSegmentsCollection;
 		private static var graphicsPath:GraphicsPath = new GraphicsPath(new Vector.<int>(), new Vector.<Number>());
 		
-		public static function getSegments(data:String):GraphicsPath
+		public static function getSegments(data:String, x:Number=0, y:Number=0):GraphicsPath
 		{
 			segments = new PathSegmentsCollection(data);
-			segments.generateGraphicsPath(graphicsPath, 0, 0, 1, 1);
+			segments.generateGraphicsPath(graphicsPath, x, y, 1, 1);
 			return graphicsPath;	
 		}
+		
+		public static function getBounds(data:String):Rectangle
+		{
+			segments = new PathSegmentsCollection(data);
+			return segments.getBounds();
+		}
 	}
 }
 

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/9999c237/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/TransformOffsets.as
----------------------------------------------------------------------
diff --git a/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/TransformOffsets.as b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/TransformOffsets.as
new file mode 100644
index 0000000..91389ba
--- /dev/null
+++ b/frameworks/as/projects/FlexJSUI/src/org/apache/flex/core/graphics/utils/TransformOffsets.as
@@ -0,0 +1,367 @@
+/**
+ * Licensed 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.core.graphics.utils
+{
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	
+	import __AS3__.vec.Vector;
+
+	
+	/**
+	 *  A CompoundTransform represents a 2D or 3D matrix transform. It can be used in the postLayoutTransformOffsets property on a UIComponent or GraphicElement.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	public class TransformOffsets extends EventDispatcher 
+	{
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		/**
+		 *  Constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function TransformOffsets()
+		{
+		}
+		
+		
+		
+		/**
+		 * @private
+		 * storage for transform properties. These values are concatenated together with the layout properties to
+		 * form the actual computed matrix used to render the object.
+		 */
+		private var _rotationX:Number = 0;
+		private var _rotationY:Number = 0;
+		private var _rotationZ:Number = 0;
+		private var _scaleX:Number = 1;
+		private var _scaleY:Number = 1;
+		private var _scaleZ:Number = 1;		
+		private var _x:Number = 0;
+		private var _y:Number = 0;
+		private var _z:Number = 0;
+		
+		/**
+		 * @private
+		 * flags for tracking whether the  transform is 3D. A transform is 3D if any of the 3D properties -- rotationX/Y, scaleZ, or z -- are set.
+		 */
+		private static const IS_3D:uint 				= 0x200;
+		private static const M3D_FLAGS_VALID:uint			= 0x400;
+		
+		/**
+		 * @private
+		 * general storage for all of our flags.  
+		 */
+		private var _flags:uint =  0;
+		
+		/**
+		 * @private
+		 */
+		public var owner:AdvancedLayoutFeatures;
+		//----------------------------------------------------------------------------
+		
+		/**
+		 * the  x value added to the transform
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set x(value:Number):void
+		{		
+			if (value == _x)
+				return;
+			_x = value;
+			invalidate(false);
+		}
+		/**
+		 * @private
+		 */
+		public function get x():Number
+		{		
+			return _x;
+		}
+		
+		/**
+		 * the y value added to the transform
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set y(value:Number):void
+		{		
+			if (value == _y)
+				return;
+			_y = value;
+			invalidate(false);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get y():Number
+		{		
+			return _y;
+		}
+		
+		/**
+		 * the z value added to the transform
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set z(value:Number):void
+		{		
+			if (value == _z)
+				return;
+			_z = value;
+			invalidate(true);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get z():Number
+		{		
+			return _z;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		
+		/**
+		 * the rotationX, in degrees, added to the transform
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set rotationX(value:Number):void
+		{		
+			if (value == _rotationX)
+				return;
+			_rotationX = value;
+			invalidate(true);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get rotationX():Number
+		{		
+			return _rotationX;
+		}
+		
+		/**
+		 * the rotationY, in degrees, added to the transform
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set rotationY(value:Number):void
+		{		
+			if (value == _rotationY)
+				return;
+			_rotationY = value;
+			invalidate(true);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get rotationY():Number
+		{		
+			return _rotationY;
+		}
+		
+		/**
+		 * the rotationZ, in degrees, added to the transform
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set rotationZ(value:Number):void
+		{		
+			if (value == _rotationZ)
+				return;
+			_rotationZ = value;
+			invalidate(false);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get rotationZ():Number
+		{		
+			return _rotationZ;
+		}
+		
+		//------------------------------------------------------------------------------
+		
+		
+		/**
+		 * the multiplier applied to the scaleX of the transform.  
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set scaleX(value:Number):void
+		{		
+			if (value == _scaleX)
+				return;
+			_scaleX = value;
+			invalidate(false);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get scaleX():Number
+		{
+			return _scaleX;
+		}
+		
+		/**
+		 * the multiplier applied to the scaleY of the transform.  
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set scaleY(value:Number):void
+		{		
+			if (value == _scaleY)
+				return;
+			_scaleY = value;
+			invalidate(false);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get scaleY():Number
+		{		
+			return _scaleY;
+		}
+		
+		
+		/**
+		 * the multiplier applied to the scaleZ of the transform.  
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 9
+		 *  @playerversion AIR 1.1
+		 *  @productversion Flex 3
+		 */
+		public function set scaleZ(value:Number):void
+		{		
+			if (value == _scaleZ)
+				return;
+			_scaleZ = value;
+			invalidate(true);
+		}
+		
+		/**
+		 * @private
+		 */
+		public function get scaleZ():Number
+		{		
+			return _scaleZ;
+		}
+		
+		
+		/**
+		 * @private
+		 * returns true if the transform has 3D values.
+		 */
+		public function get is3D():Boolean
+		{
+			if ((_flags & M3D_FLAGS_VALID) == 0)
+				update3DFlags();
+			return ((_flags & IS_3D) != 0);
+		}
+		
+		
+		//------------------------------------------------------------------------------
+		
+		/**
+		 * @private
+		 * invalidates our various cached values.  Any change to the CompoundTransform object that affects
+		 * the various transforms should call this function. 
+		 * @param reason - the code indicating what changes to cause the invalidation.
+		 * @param affects3D - a flag indicating whether the change affects the 2D/3D nature of the various transforms.
+		 * @param dispatchChangeEvent - if true, the CompoundTransform will dispatch a change indicating that its underlying transforms
+		 * have been modified. 
+		 */
+		private function invalidate(affects3D:Boolean,dispatchChangeEvent:Boolean = true):void
+		{
+			if (affects3D)
+				_flags &= ~M3D_FLAGS_VALID;
+			
+			if (dispatchChangeEvent)
+				dispatchEvent(new Event(Event.CHANGE));	
+		}
+		
+		private static const EPSILON:Number = .001;
+		/**
+		 * @private
+		 * updates the flags that indicate whether the layout, offset, and/or computed transforms are 3D in nature.  
+		 * Since the user can set either the individual transform properties or the matrices directly, we compute these 
+		 * flags based on what the current 'source of truth' is for each of these values.
+		 */
+		private function update3DFlags():void
+		{			
+			if ((_flags & M3D_FLAGS_VALID) == 0)
+			{
+				var matrixIs3D:Boolean = ( // note that rotationZ is the same as rotation, and not a 3D affecting							
+					(Math.abs(_scaleZ-1) > EPSILON) ||  // property.
+					((Math.abs(_rotationX)+EPSILON)%360) > 2*EPSILON ||
+					((Math.abs(_rotationY)+EPSILON)%360) > 2*EPSILON ||
+					Math.abs(_z) > EPSILON
+				);
+				if (matrixIs3D)
+					_flags |= IS_3D;
+				else
+					_flags &= ~IS_3D;				
+				_flags |= M3D_FLAGS_VALID;
+			}
+		}
+		
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/9999c237/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientBase.js
----------------------------------------------------------------------
diff --git a/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientBase.js b/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientBase.js
new file mode 100644
index 0000000..46719ae
--- /dev/null
+++ b/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientBase.js
@@ -0,0 +1,173 @@
+/**
+ * Licensed 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.
+ */
+
+/**
+ * org.apache.flex.core.graphics.GradientBase
+ *
+ * @fileoverview
+ *
+ * @suppress {checkTypes}
+ */
+
+goog.provide('org.apache.flex.core.graphics.GradientBase');
+
+
+/**
+ * @constructor
+ */
+org.apache.flex.core.graphics.GradientBase = function() {
+};
+
+
+/**
+ * @protected
+ * @type {Array}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.colors = [];
+
+
+/**
+ * @protected
+ * @type {Array}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.ratios = [];
+
+
+/**
+ * @protected
+ * @type {Array}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.alphas = [];
+
+
+/**
+ * @private
+ * @type {Array}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype._entries = [];
+
+
+/**
+ * @private
+ * @type {number}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype._rotation = 0.0;
+
+
+/**
+ * @expose
+ * @return {Array}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.get_entries = function() {
+  return this._entries;
+};
+
+
+/**
+ * @expose
+ * @param {Array} value
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.set_entries = function(value) {
+  this._entries = value;
+};
+
+
+/**
+ * @expose
+ *  By default, the LinearGradientStroke defines a transition
+ *  from left to right across the control. 
+ *  Use the <code>rotation</code> property to control the transition direction. 
+ *  For example, a value of 180.0 causes the transition
+ *  to occur from right to left, rather than from left to right. 
+ * @return {number}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.get_rotation = function() {
+  return this._rotation;
+};
+
+
+/**
+ * @expose
+ * @param {number} value
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.set_rotation = function(value) {
+  this._rotation = value;
+};
+
+
+/**
+ * @private
+ * @type {number}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype._x = 0;
+
+
+/**
+ * @expose
+ * @return {number}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.get_x = function() {
+  return this._x;
+};
+
+
+/**
+ * @expose
+ * @param {number} value
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.set_x = function(value) {
+  this._x = value;
+};
+
+
+/**
+ * @private
+ * @type {number}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype._y = 0;
+
+
+/**
+ * @expose
+ * @param {number} value
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.set_y = function(value) {
+  this._y = value;
+};
+
+
+/**
+ * @expose
+ * @return {number}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.get_y = function() {
+  return this._y;
+};
+
+
+/**
+ * @expose
+ * @return {string} A new gradient id value
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.get_newId = function(value) {
+  return String(Math.floor((Math.random() * 100000) + 1));
+};
+
+
+/**
+ * Metadata
+ *
+ * @type {Object.<string, Array.<Object>>}
+ */
+org.apache.flex.core.graphics.GradientBase.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'GradientBase', qName: 'org.apache.flex.core.graphics.GradientBase'}] };

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/9999c237/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientEntry.js
----------------------------------------------------------------------
diff --git a/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientEntry.js b/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientEntry.js
new file mode 100644
index 0000000..8fc7b58
--- /dev/null
+++ b/frameworks/js/FlexJS/src/org/apache/flex/core/graphics/GradientEntry.js
@@ -0,0 +1,143 @@
+/**
+ * Licensed 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.
+ */
+
+/**
+ * org.apache.flex.core.graphics.GradientEntry
+ *
+ * @fileoverview
+ *
+ * @suppress {checkTypes}
+ */
+
+goog.provide('org.apache.flex.core.graphics.GradientEntry');
+
+
+/**
+ * @constructor
+ * @param {number} alpha
+ * @param {number} color
+ * @param {number} ratio
+ */
+org.apache.flex.core.graphics.GradientEntry = function(alpha, color, ratio) {
+  this._alpha = alpha;
+  this._color = color;
+  this._ratio = ratio;
+};
+
+
+/**
+ * @private
+ * @type {number}
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype._alpha = 1.0;
+
+
+/**
+ * @private
+ * @type {number}
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype._color = 0x000000;
+
+
+/**
+ * @private
+ * @type {number}
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype._ratio = 0x000000;
+
+
+/**
+ * @expose
+ * @return {number}
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.get_alpha = function() {
+  return this._alpha;
+};
+
+
+/**
+ * @expose
+ * @param {number} value
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.set_alpha = function(value) {
+  var /** @type {number} */ oldValue = this._alpha;
+  if (value != oldValue) {
+    this._alpha = value;
+  }
+};
+
+
+/**
+ * @expose
+ * @return {number}
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.get_color = function() {
+  return this._color;
+};
+
+
+/**
+ * @expose
+ * @param {number} value
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.set_color = function(value) {
+  var /** @type {number} */ oldValue = this._color;
+  if (value != oldValue) {
+    this._color = value;
+  }
+};
+
+
+/**
+ * @expose
+ * @return {number}
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.get_ratio = function() {
+  return this._ratio;
+};
+
+
+/**
+ * @expose
+ * @param {number} value
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.set_ratio = function(value) {
+  this._ratio = value;
+};
+
+
+/**
+ * @expose
+ * @param {org.apache.flex.core.graphics.GraphicShape} s
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.begin = function(s) {
+  s.get_graphics().beginFill(this.get_color(), this.get_alpha());
+};
+
+
+/**
+ * @expose
+ * @param {org.apache.flex.core.graphics.GraphicShape} s
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.end = function(s) {
+  s.get_graphics().endFill();
+};
+
+
+/**
+ * Metadata
+ *
+ * @type {Object.<string, Array.<Object>>}
+ */
+org.apache.flex.core.graphics.GradientEntry.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'GradientEntry', qName: 'org.apache.flex.core.graphics.GradientEntry'}] };