//////////////////////////////////////////////////////////////////////////////// // // 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 mx.graphics { import flash.events.Event; import flash.events.EventDispatcher; import flash.geom.Matrix; import mx.core.mx_internal; import mx.events.PropertyChangeEvent; import mx.geom.CompoundTransform; use namespace mx_internal; [DefaultProperty("entries")] /** * The GradientBase class is the base class for * LinearGradient, LinearGradientStroke, and RadialGradient. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public class GradientBase extends EventDispatcher { //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function GradientBase() { super(); } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- /** * @private */ mx_internal var colors:Array /* of uint */ = []; /** * @private */ mx_internal var ratios:Array /* of Number */ = []; /** * @private */ mx_internal var alphas:Array /* of Number */ = []; //-------------------------------------------------------------------------- // // Class Properties // //-------------------------------------------------------------------------- /** * Value of the width and height of the untransformed gradient * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public static const GRADIENT_DIMENSION:Number = 1638.4; //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // angle //---------------------------------- /** * @private * Storage for the angle property. */ mx_internal var _angle:Number; [Inspectable(category="General")] [Deprecated(replacement="rotation")] /** * By default, the LinearGradientStroke defines a transition * from left to right across the control. * Use the angle 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. * * @default 0.0 * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get angle():Number { return _angle / Math.PI * 180; } /** * @private */ public function set angle(value:Number):void { var oldValue:Number = _angle; _angle = value / 180 * Math.PI; dispatchGradientChangedEvent("angle", oldValue, _angle); } //---------------------------------- // compoundTransform //---------------------------------- /** * Holds the matrix and the convenience transform properties (x, y, and rotation). * The compoundTransform is only created when the matrix property is set. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ protected var compoundTransform:CompoundTransform; //---------------------------------- // entries //---------------------------------- /** * @private * Storage for the entries property. */ private var _entries:Array = []; [Bindable("propertyChange")] [Inspectable(category="General", arrayType="mx.graphics.GradientEntry")] /** * An Array of GradientEntry objects * defining the fill patterns for the gradient fill. * * @default [] * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get entries():Array { return _entries; } /** * @private */ public function set entries(value:Array):void { var oldValue:Array = _entries; _entries = value; processEntries(); dispatchGradientChangedEvent("entries", oldValue, value); } //---------------------------------- // interpolationMethod //---------------------------------- /** * @private * Storage for the interpolationMethod property. */ private var _interpolationMethod:String = "rgb"; [Inspectable(category="General", enumeration="rgb,linearRGB", defaultValue="rgb")] /** * A value from the InterpolationMethod class * that specifies which interpolation method to use. * *

Valid values are InterpolationMethod.LINEAR_RGB * and InterpolationMethod.RGB.

* * @default InterpolationMethod.RGB * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get interpolationMethod():String { return _interpolationMethod; } /** * @private */ public function set interpolationMethod(value:String):void { var oldValue:String = _interpolationMethod; if (value != oldValue) { _interpolationMethod = value; dispatchGradientChangedEvent("interpolationMethod", oldValue, value); } } //---------------------------------- // matrix //---------------------------------- /** * @private * Storage for the matrix property. */ private var _matrix:Matrix; [Inspectable(category="General")] /** * An array of values used for matrix transformation. * *

The gradient scaleX and scaleY properties represent pixels while the Matrix scale properties represent multipliers. * Thus they are not compatible. * Another difference is the most of the transform properties (x, y, scaleX, and scaleY) * support NaN values while the matrix does not. A NaN value means that the gradient will choose an appropriate value.

* *

The scaleX and scaleY properties can not be represented by the matrix. * Once the matrix is set, scaleX and scaleY can no longer be set. * Also, x and y can not be set to NaN. * The matrix can be set back to null which also resets all of the convenience transform properties back to their default values.

* *

If the matrix is set, then the gradient draw logic will scale the gradient to fit the bounds of the graphic element. * It will then position the gradient in the upper left corner of the graphic element. * Finally, it will apply the matrix transformations.

*

By default, the LinearGradientStroke defines a transition * from left to right across the control. * Use the rotation 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.

* * @default null * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get matrix():Matrix { return compoundTransform ? compoundTransform.matrix : null; } /** * @private */ public function set matrix(value:Matrix):void { var oldValue:Matrix = matrix; var oldX:Number = x; var oldY:Number = y; var oldRotation:Number = rotation; if (value == null) { compoundTransform = null; x = NaN; y = NaN; rotation = 0; } else { // Create the transform if none exists. if (compoundTransform == null) compoundTransform = new CompoundTransform(); compoundTransform.matrix = value; // CompoundTransform will create a clone dispatchGradientChangedEvent("x", oldX, compoundTransform.x); dispatchGradientChangedEvent("y", oldY, compoundTransform.y); dispatchGradientChangedEvent("rotation", oldRotation, compoundTransform.rotationZ); } } //---------------------------------- // rotation //---------------------------------- /** * @private * Storage for the rotation property. */ private var _rotation:Number = 0.0; [Bindable("propertyChange")] [Inspectable(category="General")] /** * By default, the LinearGradientStroke defines a transition * from left to right across the control. * Use the rotation 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. * * @default 0.0 * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get rotation():Number { return compoundTransform ? compoundTransform.rotationZ : _rotation; } /** * @private */ public function set rotation(value:Number):void { if (value != rotation) { var oldValue:Number = rotation; if (compoundTransform) compoundTransform.rotationZ = value; else _rotation = value; dispatchGradientChangedEvent("rotation", oldValue, value); } } //---------------------------------- // spreadMethod //---------------------------------- /** * @private * Storage for the spreadMethod property. */ private var _spreadMethod:String = "pad"; [Bindable("propertyChange")] [Inspectable(category="General", enumeration="pad,reflect,repeat", defaultValue="pad")] /** * A value from the SpreadMethod class * that specifies which spread method to use. * *

Valid values are SpreadMethod.PAD, * SpreadMethod.REFLECT, * and SpreadMethod.REPEAT.

* * @default SpreadMethod.PAD * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get spreadMethod():String { return _spreadMethod; } /** * @private */ public function set spreadMethod(value:String):void { var oldValue:String = _spreadMethod; if (value != oldValue) { _spreadMethod = value; dispatchGradientChangedEvent("spreadMethod", oldValue, value); } } //---------------------------------- // x //---------------------------------- private var _x:Number; [Bindable("propertyChange")] [Inspectable(category="General")] /** * The distance by which to translate each point along the x axis. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get x():Number { return compoundTransform ? compoundTransform.x : _x; } /** * @private */ public function set x(value:Number):void { var oldValue:Number = x; if (value != oldValue) { if (compoundTransform) { // If we have a compoundTransform, only non-NaN values are allowed if (!isNaN(value)) compoundTransform.x = value; } else { _x = value; } dispatchGradientChangedEvent("x", oldValue, value); } } //---------------------------------- // y //---------------------------------- private var _y:Number; [Bindable("propertyChange")] [Inspectable(category="General")] /** * The distance by which to translate each point along the y axis. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get y():Number { return compoundTransform ? compoundTransform.y : _y; } /** * @private */ public function set y(value:Number):void { var oldValue:Number = y; if (value != oldValue) { if (compoundTransform) { // If we have a compoundTransform, only non-NaN values are allowed if (!isNaN(value)) compoundTransform.y = value; } else { _y = value; } dispatchGradientChangedEvent("y", oldValue, value); } } mx_internal function get rotationInRadians():Number { return rotation / 180 * Math.PI; } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * @private * Extract the gradient information in the public entries * Array into the internal colors, ratios, * and alphas arrays. */ private function processEntries():void { colors = []; ratios = []; alphas = []; if (!_entries || _entries.length == 0) return; var ratioConvert:Number = 255; var i:int; var n:int = _entries.length; for (i = 0; i < n; i++) { var e:GradientEntry = _entries[i]; e.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, entry_propertyChangeHandler, false, 0, true); colors.push(e.color); alphas.push(e.alpha); ratios.push(e.ratio * ratioConvert); } if (isNaN(ratios[0])) ratios[0] = 0; if (isNaN(ratios[n - 1])) ratios[n - 1] = 255; i = 1; while (true) { while (i < n && !isNaN(ratios[i])) { i++; } if (i == n) break; var start:int = i - 1; while (i < n && isNaN(ratios[i])) { i++; } var br:Number = ratios[start]; var tr:Number = ratios[i]; for (var j:int = 1; j < i - start; j++) { ratios[j] = br + j * (tr - br) / (i - start); } } } /** * Dispatch a gradientChanged event. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ mx_internal function dispatchGradientChangedEvent(prop:String, oldValue:*, value:*):void { dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, prop, oldValue, value)); } //-------------------------------------------------------------------------- // // Event handlers // //-------------------------------------------------------------------------- /** * @private */ private function entry_propertyChangeHandler(event:Event):void { processEntries(); dispatchGradientChangedEvent("entries", entries, entries); } } }