1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2005-2007 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.graphics 13{ 14 15import flash.events.Event; 16import flash.events.EventDispatcher; 17import flash.geom.Matrix; 18 19import mx.core.mx_internal; 20import mx.events.PropertyChangeEvent; 21import mx.geom.CompoundTransform; 22 23use namespace mx_internal; 24 25[DefaultProperty("entries")] 26 27/** 28 * The GradientBase class is the base class for 29 * LinearGradient, LinearGradientStroke, and RadialGradient. 30 * 31 * @langversion 3.0 32 * @playerversion Flash 9 33 * @playerversion AIR 1.1 34 * @productversion Flex 3 35 */ 36public class GradientBase extends EventDispatcher 37{ 38 //-------------------------------------------------------------------------- 39 // 40 // Constructor 41 // 42 //-------------------------------------------------------------------------- 43 44 /** 45 * Constructor. 46 * 47 * @langversion 3.0 48 * @playerversion Flash 9 49 * @playerversion AIR 1.1 50 * @productversion Flex 3 51 */ 52 public function GradientBase() 53 { 54 super(); 55 } 56 57 //-------------------------------------------------------------------------- 58 // 59 // Variables 60 // 61 //-------------------------------------------------------------------------- 62 63 /** 64 * @private 65 */ 66 mx_internal var colors:Array /* of uint */ = []; 67 68 /** 69 * @private 70 */ 71 mx_internal var ratios:Array /* of Number */ = []; 72 73 /** 74 * @private 75 */ 76 mx_internal var alphas:Array /* of Number */ = []; 77 78 //-------------------------------------------------------------------------- 79 // 80 // Class Properties 81 // 82 //-------------------------------------------------------------------------- 83 84 85 /** 86 * Value of the width and height of the untransformed gradient 87 * 88 * @langversion 3.0 89 * @playerversion Flash 10 90 * @playerversion AIR 1.5 91 * @productversion Flex 4 92 */ 93 public static const GRADIENT_DIMENSION:Number = 1638.4; 94 95 //-------------------------------------------------------------------------- 96 // 97 // Properties 98 // 99 //-------------------------------------------------------------------------- 100 101 //---------------------------------- 102 // angle 103 //---------------------------------- 104 105 /** 106 * @private 107 * Storage for the angle property. 108 */ 109 mx_internal var _angle:Number; 110 111 [Inspectable(category="General")] 112 [Deprecated(replacement="rotation")] 113 /** 114 * By default, the LinearGradientStroke defines a transition 115 * from left to right across the control. 116 * Use the <code>angle</code> property to control the transition direction. 117 * For example, a value of 180.0 causes the transition 118 * to occur from right to left, rather than from left to right. 119 * 120 * @default 0.0 121 * 122 * @langversion 3.0 123 * @playerversion Flash 9 124 * @playerversion AIR 1.1 125 * @productversion Flex 3 126 */ 127 public function get angle():Number 128 { 129 return _angle / Math.PI * 180; 130 } 131 132 /** 133 * @private 134 */ 135 public function set angle(value:Number):void 136 { 137 var oldValue:Number = _angle; 138 _angle = value / 180 * Math.PI; 139 140 dispatchGradientChangedEvent("angle", oldValue, _angle); 141 } 142 143 //---------------------------------- 144 // compoundTransform 145 //---------------------------------- 146 147 /** 148 * Holds the matrix and the convenience transform properties (<code>x</code>, <code>y</code>, and <code>rotation</code>). 149 * The compoundTransform is only created when the <code>matrix</code> property is set. 150 * 151 * @langversion 3.0 152 * @playerversion Flash 9 153 * @playerversion AIR 1.1 154 * @productversion Flex 3 155 */ 156 protected var compoundTransform:CompoundTransform; 157 158 //---------------------------------- 159 // entries 160 //---------------------------------- 161 162 /** 163 * @private 164 * Storage for the entries property. 165 */ 166 private var _entries:Array = []; 167 168 [Bindable("propertyChange")] 169 [Inspectable(category="General", arrayType="mx.graphics.GradientEntry")] 170 171 /** 172 * An Array of GradientEntry objects 173 * defining the fill patterns for the gradient fill. 174 * 175 * @default [] 176 * 177 * @langversion 3.0 178 * @playerversion Flash 9 179 * @playerversion AIR 1.1 180 * @productversion Flex 3 181 */ 182 public function get entries():Array 183 { 184 return _entries; 185 } 186 187 /** 188 * @private 189 */ 190 public function set entries(value:Array):void 191 { 192 var oldValue:Array = _entries; 193 _entries = value; 194 195 processEntries(); 196 197 dispatchGradientChangedEvent("entries", oldValue, value); 198 } 199 200 //---------------------------------- 201 // interpolationMethod 202 //---------------------------------- 203 204 /** 205 * @private 206 * Storage for the interpolationMethod property. 207 */ 208 private var _interpolationMethod:String = "rgb"; 209 210 [Inspectable(category="General", enumeration="rgb,linearRGB", defaultValue="rgb")] 211 212 /** 213 * A value from the InterpolationMethod class 214 * that specifies which interpolation method to use. 215 * 216 * <p>Valid values are <code>InterpolationMethod.LINEAR_RGB</code> 217 * and <code>InterpolationMethod.RGB</code>.</p> 218 * 219 * @default InterpolationMethod.RGB 220 * 221 * @langversion 3.0 222 * @playerversion Flash 9 223 * @playerversion AIR 1.1 224 * @productversion Flex 3 225 */ 226 public function get interpolationMethod():String 227 { 228 return _interpolationMethod; 229 } 230 231 /** 232 * @private 233 */ 234 public function set interpolationMethod(value:String):void 235 { 236 var oldValue:String = _interpolationMethod; 237 if (value != oldValue) 238 { 239 _interpolationMethod = value; 240 241 dispatchGradientChangedEvent("interpolationMethod", oldValue, value); 242 } 243 } 244 245 //---------------------------------- 246 // matrix 247 //---------------------------------- 248 249 /** 250 * @private 251 * Storage for the matrix property. 252 */ 253 private var _matrix:Matrix; 254 255 [Inspectable(category="General")] 256 257 /** 258 * An array of values used for matrix transformation. 259 * 260 * <p>The gradient <code>scaleX</code> and <code>scaleY</code> properties represent pixels while the Matrix scale properties represent multipliers. 261 * Thus they are not compatible. 262 * Another difference is the most of the transform properties (<code>x</code>, <code>y</code>, <code>scaleX</code>, and <code>scaleY</code>) 263 * support NaN values while the matrix does not. A NaN value means that the gradient will choose an appropriate value.</p> 264 * 265 * <p>The <code>scaleX</code> and <code>scaleY</code> properties can not be represented by the matrix. 266 * Once the matrix is set, <code>scaleX</code> and <code>scaleY</code> can no longer be set. 267 * Also, <code>x</code> and <code>y</code> can not be set to NaN. 268 * The matrix can be set back to null which also resets all of the convenience transform properties back to their default values.</p> 269 * 270 * <p>If the matrix is set, then the gradient draw logic will scale the gradient to fit the bounds of the graphic element. 271 * It will then position the gradient in the upper left corner of the graphic element. 272 * Finally, it will apply the matrix transformations.</p> 273 274 * <p>By default, the LinearGradientStroke defines a transition 275 * from left to right across the control. 276 * Use the <code>rotation</code> property to control the transition direction. 277 * For example, a value of 180.0 causes the transition 278 * to occur from right to left, rather than from left to right.</p> 279 * 280 * @default null 281 * 282 * @langversion 3.0 283 * @playerversion Flash 9 284 * @playerversion AIR 1.1 285 * @productversion Flex 3 286 */ 287 public function get matrix():Matrix 288 { 289 return compoundTransform ? compoundTransform.matrix : null; 290 } 291 292 /** 293 * @private 294 */ 295 public function set matrix(value:Matrix):void 296 { 297 var oldValue:Matrix = matrix; 298 299 var oldX:Number = x; 300 var oldY:Number = y; 301 var oldRotation:Number = rotation; 302 303 if (value == null) 304 { 305 compoundTransform = null; 306 x = NaN; 307 y = NaN; 308 rotation = 0; 309 } 310 else 311 { 312 // Create the transform if none exists. 313 if (compoundTransform == null) 314 compoundTransform = new CompoundTransform(); 315 compoundTransform.matrix = value; // CompoundTransform will create a clone 316 317 dispatchGradientChangedEvent("x", oldX, compoundTransform.x); 318 dispatchGradientChangedEvent("y", oldY, compoundTransform.y); 319 dispatchGradientChangedEvent("rotation", oldRotation, compoundTransform.rotationZ); 320 } 321 } 322 323 //---------------------------------- 324 // rotation 325 //---------------------------------- 326 327 /** 328 * @private 329 * Storage for the rotation property. 330 */ 331 private var _rotation:Number = 0.0; 332 333 [Bindable("propertyChange")] 334 [Inspectable(category="General")] 335 336 /** 337 * By default, the LinearGradientStroke defines a transition 338 * from left to right across the control. 339 * Use the <code>rotation</code> property to control the transition direction. 340 * For example, a value of 180.0 causes the transition 341 * to occur from right to left, rather than from left to right. 342 * 343 * @default 0.0 344 * 345 * @langversion 3.0 346 * @playerversion Flash 9 347 * @playerversion AIR 1.1 348 * @productversion Flex 3 349 */ 350 public function get rotation():Number 351 { 352 return compoundTransform ? compoundTransform.rotationZ : _rotation; 353 } 354 355 /** 356 * @private 357 */ 358 public function set rotation(value:Number):void 359 { 360 if (value != rotation) 361 { 362 var oldValue:Number = rotation; 363 364 if (compoundTransform) 365 compoundTransform.rotationZ = value; 366 else 367 _rotation = value; 368 dispatchGradientChangedEvent("rotation", oldValue, value); 369 } 370 } 371 372 //---------------------------------- 373 // spreadMethod 374 //---------------------------------- 375 376 /** 377 * @private 378 * Storage for the spreadMethod property. 379 */ 380 private var _spreadMethod:String = "pad"; 381 382 [Bindable("propertyChange")] 383 [Inspectable(category="General", enumeration="pad,reflect,repeat", defaultValue="pad")] 384 385 /** 386 * A value from the SpreadMethod class 387 * that specifies which spread method to use. 388 * 389 * <p>Valid values are <code>SpreadMethod.PAD</code>, 390 * <code>SpreadMethod.REFLECT</code>, 391 * and <code>SpreadMethod.REPEAT</code>.</p> 392 * 393 * @default SpreadMethod.PAD 394 * 395 * @langversion 3.0 396 * @playerversion Flash 9 397 * @playerversion AIR 1.1 398 * @productversion Flex 3 399 */ 400 public function get spreadMethod():String 401 { 402 return _spreadMethod; 403 } 404 405 /** 406 * @private 407 */ 408 public function set spreadMethod(value:String):void 409 { 410 var oldValue:String = _spreadMethod; 411 if (value != oldValue) 412 { 413 _spreadMethod = value; 414 dispatchGradientChangedEvent("spreadMethod", oldValue, value); 415 } 416 } 417 418 //---------------------------------- 419 // x 420 //---------------------------------- 421 422 private var _x:Number; 423 424 [Bindable("propertyChange")] 425 [Inspectable(category="General")] 426 427 /** 428 * The distance by which to translate each point along the x axis. 429 * 430 * @langversion 3.0 431 * @playerversion Flash 9 432 * @playerversion AIR 1.1 433 * @productversion Flex 3 434 */ 435 public function get x():Number 436 { 437 return compoundTransform ? compoundTransform.x : _x; 438 } 439 440 /** 441 * @private 442 */ 443 public function set x(value:Number):void 444 { 445 var oldValue:Number = x; 446 if (value != oldValue) 447 { 448 if (compoundTransform) 449 { 450 // If we have a compoundTransform, only non-NaN values are allowed 451 if (!isNaN(value)) 452 compoundTransform.x = value; 453 } 454 else 455 { 456 _x = value; 457 } 458 dispatchGradientChangedEvent("x", oldValue, value); 459 } 460 } 461 462 //---------------------------------- 463 // y 464 //---------------------------------- 465 466 private var _y:Number; 467 468 [Bindable("propertyChange")] 469 [Inspectable(category="General")] 470 471 /** 472 * The distance by which to translate each point along the y axis. 473 * 474 * @langversion 3.0 475 * @playerversion Flash 9 476 * @playerversion AIR 1.1 477 * @productversion Flex 3 478 */ 479 public function get y():Number 480 { 481 return compoundTransform ? compoundTransform.y : _y; 482 } 483 484 /** 485 * @private 486 */ 487 public function set y(value:Number):void 488 { 489 var oldValue:Number = y; 490 if (value != oldValue) 491 { 492 if (compoundTransform) 493 { 494 // If we have a compoundTransform, only non-NaN values are allowed 495 if (!isNaN(value)) 496 compoundTransform.y = value; 497 } 498 else 499 { 500 _y = value; 501 } 502 503 dispatchGradientChangedEvent("y", oldValue, value); 504 } 505 } 506 507 mx_internal function get rotationInRadians():Number 508 { 509 return rotation / 180 * Math.PI; 510 } 511 512 //-------------------------------------------------------------------------- 513 // 514 // Methods 515 // 516 //-------------------------------------------------------------------------- 517 518 /** 519 * @private 520 * Extract the gradient information in the public <code>entries</code> 521 * Array into the internal <code>colors</code>, <code>ratios</code>, 522 * and <code>alphas</code> arrays. 523 */ 524 private function processEntries():void 525 { 526 colors = []; 527 ratios = []; 528 alphas = []; 529 530 if (!_entries || _entries.length == 0) 531 return; 532 533 var ratioConvert:Number = 255; 534 535 var i:int; 536 537 var n:int = _entries.length; 538 for (i = 0; i < n; i++) 539 { 540 var e:GradientEntry = _entries[i]; 541 e.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, 542 entry_propertyChangeHandler, false, 0, true); 543 colors.push(e.color); 544 alphas.push(e.alpha); 545 ratios.push(e.ratio * ratioConvert); 546 } 547 548 if (isNaN(ratios[0])) 549 ratios[0] = 0; 550 551 if (isNaN(ratios[n - 1])) 552 ratios[n - 1] = 255; 553 554 i = 1; 555 556 while (true) 557 { 558 while (i < n && !isNaN(ratios[i])) 559 { 560 i++; 561 } 562 563 if (i == n) 564 break; 565 566 var start:int = i - 1; 567 568 while (i < n && isNaN(ratios[i])) 569 { 570 i++; 571 } 572 573 var br:Number = ratios[start]; 574 var tr:Number = ratios[i]; 575 576 for (var j:int = 1; j < i - start; j++) 577 { 578 ratios[j] = br + j * (tr - br) / (i - start); 579 } 580 } 581 } 582 583 /** 584 * Dispatch a gradientChanged event. 585 * 586 * @langversion 3.0 587 * @playerversion Flash 9 588 * @playerversion AIR 1.1 589 * @productversion Flex 3 590 */ 591 mx_internal function dispatchGradientChangedEvent(prop:String, 592 oldValue:*, value:*):void 593 { 594 dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, prop, 595 oldValue, value)); 596 } 597 598 //-------------------------------------------------------------------------- 599 // 600 // Event handlers 601 // 602 //-------------------------------------------------------------------------- 603 604 /** 605 * @private 606 */ 607 private function entry_propertyChangeHandler(event:Event):void 608 { 609 processEntries(); 610 611 dispatchGradientChangedEvent("entries", entries, entries); 612 } 613} 614 615} 616