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.core 13{ 14 15import flash.display.BitmapData; 16import flash.display.DisplayObjectContainer; 17import flash.events.Event; 18import flash.geom.Point; 19import flash.system.ApplicationDomain; 20 21/** 22 * BitmapAsset is a subclass of the flash.display.Bitmap class 23 * which represents bitmap images that you embed in a Flex application. 24 * It implements the IFlexDisplayObject interface, which makes it 25 * possible for an embedded bitmap image to be displayed in an Image control, 26 * or to be used as a container background or a component skin. 27 * 28 * <p>The bitmap image that you're embedding can be in a JPEG, GIF, 29 * or PNG file. 30 * You can also embed a bitmap symbol that is in a SWF file produced 31 * by Flash. 32 * In each of these cases, the MXML compiler autogenerates a class 33 * that extends BitmapAsset to represent the embedded bitmap image.</p> 34 * 35 * <p>You don't generally have to use the BitmapAsset class directly 36 * when you write a Flex application. 37 * For example, you can embed a GIF file and display the image 38 * in an Image control by writing the gollowing:</p> 39 * 40 * <pre> 41 * <mx:Image id="logo" source="@Embed(source='Logo.gif')"/></pre> 42 * 43 * <p>or use it as the application's background image in CSS syntax 44 * by writing</p> 45 * 46 * <pre> 47 * <fx:Style> 48 * @namespace mx "library://ns.adobe.com/flex/mx" 49 * mx|Application { 50 * backgroundImage: Embed(source="Logo.gif") 51 * } 52 * <fx:Style/></pre> 53 * 54 * <p>without having to understand that the MXML compiler has created 55 * a subclass of BitmapAsset for you.</p> 56 * 57 * <p>However, it may be useful to understand what is happening 58 * at the ActionScript level. 59 * To embed a bitmap image in ActionScript, you declare a variable 60 * of type Class, and put <code>[Embed]</code> metadata on it. 61 * For example, you embed a GIF file like this:</p> 62 * 63 * <pre> 64 * [Bindable] 65 * [Embed(source="Logo.gif")] 66 * private var logoClass:Class;</pre> 67 * 68 * <p>The MXML compiler sees the .gif extension, transcodes the GIF data 69 * into the bitmap format that the player uses, autogenerates 70 * a subclass of the BitmapAsset class, and sets your variable 71 * to be a reference to this autogenerated class. 72 * You can then use this class reference to create instances of the 73 * BitmapAsset using the <code>new</code> operator, and you can use 74 * APIs of the BitmapAsset class on them:</p> 75 * 76 * <pre> 77 * var logo:BitmapAsset = BitmapAsset(new logoClass()); 78 * logo.bitmapData.noise(4);</pre> 79 * 80 * <p>However, you rarely need to create BitmapAsset instances yourself 81 * because image-related properties and styles can simply be set to an 82 * image-producing class, and components will create image instances 83 * as necessary. 84 * For example, to display this image in an Image control, you can 85 * set the Image's <code>source</code> property to <code>logoClass</code>. 86 * In MXML you could do this as follows:</p> 87 * 88 * <pre> 89 * <mx:Image id="logo" source="{logoClass}"/></pre> 90 * 91 * @langversion 3.0 92 * @playerversion Flash 9 93 * @playerversion AIR 1.1 94 * @productversion Flex 3 95 */ 96public class BitmapAsset extends FlexBitmap 97 implements IFlexAsset, IFlexDisplayObject, ILayoutDirectionElement 98{ 99 include "../core/Version.as"; 100 101 // Softlink FlexVersion and MatrixUtil to remove dependencies of embeds on 102 // framework classes. This helps to reduce swf size in AS-only projects. 103 private static var FlexVersionClass:Class; 104 private static var MatrixUtilClass:Class; 105 106 //-------------------------------------------------------------------------- 107 // 108 // Constructor 109 // 110 //-------------------------------------------------------------------------- 111 112 /** 113 * Constructor. 114 * 115 * @param bitmapData The data for the bitmap image. 116 * 117 * @param pixelSnapping Whether or not the bitmap is snapped 118 * to the nearest pixel. 119 * 120 * @param smoothing Whether or not the bitmap is smoothed when scaled. 121 * 122 * @langversion 3.0 123 * @playerversion Flash 9 124 * @playerversion AIR 1.1 125 * @productversion Flex 3 126 */ 127 public function BitmapAsset(bitmapData:BitmapData = null, 128 pixelSnapping:String = "auto", 129 smoothing:Boolean = false) 130 { 131 super(bitmapData, pixelSnapping, smoothing); 132 133 if (FlexVersionClass == null) 134 { 135 var appDomain:ApplicationDomain = ApplicationDomain.currentDomain; 136 if (appDomain.hasDefinition("mx.core::FlexVersion")) 137 FlexVersionClass = Class(appDomain.getDefinition("mx.core::FlexVersion")); 138 } 139 140 if (FlexVersionClass && FlexVersionClass["compatibilityVersion"] >= FlexVersionClass["VERSION_4_0"]) 141 this.addEventListener(Event.ADDED, addedHandler); 142 } 143 144 //-------------------------------------------------------------------------- 145 // 146 // Variables 147 // 148 //-------------------------------------------------------------------------- 149 150 // Softlink AdvancedLayoutFeatures to remove dependencies of embeds on 151 // framework classes. This helps to reduce swf size in AS-only projects. 152 private var layoutFeaturesClass:Class; 153 private var layoutFeatures:IAssetLayoutFeatures; 154 155 //-------------------------------------------------------------------------- 156 // 157 // Overridden Properties 158 // 159 //-------------------------------------------------------------------------- 160 161 //---------------------------------- 162 // x 163 //---------------------------------- 164 165 /** 166 * @private 167 */ 168 override public function get x():Number 169 { 170 // TODO(hmuller): by default get x returns transform.matrix.tx rounded to the nearest 20th. 171 // should do the same here, if we're returning layoutFeatures.layoutX. 172 return (layoutFeatures == null) ? super.x : layoutFeatures.layoutX; 173 } 174 175 /** 176 * @private 177 */ 178 override public function set x(value:Number):void 179 { 180 if (x == value) 181 return; 182 183 if (layoutFeatures == null) 184 { 185 super.x = value; 186 } 187 else 188 { 189 layoutFeatures.layoutX = value; 190 validateTransformMatrix(); 191 } 192 } 193 194 //---------------------------------- 195 // y 196 //---------------------------------- 197 198 /** 199 * @private 200 */ 201 override public function get y():Number 202 { 203 return (layoutFeatures == null) ? super.y : layoutFeatures.layoutY; 204 } 205 206 /** 207 * @private 208 */ 209 override public function set y(value:Number):void 210 { 211 if (y == value) 212 return; 213 214 if (layoutFeatures == null) 215 { 216 super.y = value; 217 } 218 else 219 { 220 layoutFeatures.layoutY = value; 221 validateTransformMatrix(); 222 } 223 } 224 225 //---------------------------------- 226 // z 227 //---------------------------------- 228 229 /** 230 * @private 231 */ 232 override public function get z():Number 233 { 234 return (layoutFeatures == null) ? super.z : layoutFeatures.layoutZ; 235 } 236 237 /** 238 * @private 239 */ 240 override public function set z(value:Number):void 241 { 242 if (z == value) 243 return; 244 245 if (layoutFeatures == null) 246 { 247 super.z = value; 248 } 249 else 250 { 251 layoutFeatures.layoutZ = value; 252 validateTransformMatrix(); 253 } 254 } 255 256 //---------------------------------- 257 // width 258 //---------------------------------- 259 260 /** 261 * @private 262 */ 263 override public function get width():Number 264 { 265 if (layoutFeatures == null) 266 return super.width; 267 268 // Return bounding box width in mirroring case 269 var p:Point; 270 if (MatrixUtilClass != null) 271 p = MatrixUtilClass["transformSize"](layoutFeatures.layoutWidth, _height, transform.matrix); 272 273 return p ? p.x : super.width; 274 } 275 276 /** 277 * @private 278 */ 279 override public function set width(value:Number):void 280 { 281 if (width == value) 282 return; 283 284 if (layoutFeatures == null) 285 { 286 super.width = value; 287 } 288 else 289 { 290 layoutFeatures.layoutWidth = value; 291 // Calculate scaleX based on initial width. We set scaleX 292 // here because resizing a BitmapAsset normally would adjust 293 // the scale to match. 294 layoutFeatures.layoutScaleX = measuredWidth != 0 ? value / measuredWidth : 0; 295 validateTransformMatrix(); 296 } 297 } 298 299 //---------------------------------- 300 // height 301 //---------------------------------- 302 303 private var _height:Number; 304 305 /** 306 * @private 307 */ 308 override public function get height():Number 309 { 310 311 if (layoutFeatures == null) 312 return super.height; 313 314 // Return bounding box height in mirroring case 315 var p:Point; 316 if (MatrixUtilClass != null) 317 p = MatrixUtilClass["transformSize"](layoutFeatures.layoutWidth, _height, transform.matrix); 318 319 return p ? p.y : super.height; 320 } 321 322 /** 323 * @private 324 */ 325 override public function set height(value:Number):void 326 { 327 if (height == value) 328 return; 329 330 if (layoutFeatures == null) 331 { 332 super.height = value; 333 } 334 else 335 { 336 _height = value; 337 // Calculate scaleY based on initial height. We set scaleY 338 // here because resizing a BitmapAsset normally would adjust 339 // the scale to match. 340 layoutFeatures.layoutScaleY = measuredHeight != 0 ? value / measuredHeight : 0; 341 validateTransformMatrix(); 342 } 343 } 344 345 //---------------------------------- 346 // rotation 347 //---------------------------------- 348 349 /** 350 * @private 351 */ 352 override public function get rotationX():Number 353 { 354 return (layoutFeatures == null) ? super.rotationX : layoutFeatures.layoutRotationX; 355 } 356 357 /** 358 * @private 359 */ 360 override public function set rotationX(value:Number):void 361 { 362 if (rotationX == value) 363 return; 364 365 if (layoutFeatures == null) 366 { 367 super.rotationX = value; 368 } 369 else 370 { 371 layoutFeatures.layoutRotationX = value; 372 validateTransformMatrix(); 373 } 374 } 375 /** 376 * @private 377 */ 378 override public function get rotationY():Number 379 { 380 return (layoutFeatures == null) ? super.rotationY : layoutFeatures.layoutRotationY; 381 } 382 383 /** 384 * @private 385 */ 386 override public function set rotationY(value:Number):void 387 { 388 if (rotationY == value) 389 return; 390 391 if (layoutFeatures == null) 392 { 393 super.rotationY = value; 394 } 395 else 396 { 397 layoutFeatures.layoutRotationY = value; 398 validateTransformMatrix(); 399 } 400 } 401 402 /** 403 * @private 404 */ 405 override public function get rotationZ():Number 406 { 407 return (layoutFeatures == null) ? super.rotationZ : layoutFeatures.layoutRotationZ; 408 } 409 410 /** 411 * @private 412 */ 413 override public function set rotationZ(value:Number):void 414 { 415 if (rotationZ == value) 416 return; 417 418 if (layoutFeatures == null) 419 { 420 super.rotationZ = value; 421 } 422 else 423 { 424 layoutFeatures.layoutRotationZ = value; 425 validateTransformMatrix(); 426 } 427 } 428 429 /** 430 * @private 431 */ 432 override public function get rotation():Number 433 { 434 return (layoutFeatures == null) ? super.rotation : layoutFeatures.layoutRotationZ; 435 } 436 437 /** 438 * @private 439 */ 440 override public function set rotation(value:Number):void 441 { 442 if (rotation == value) 443 return; 444 445 if (layoutFeatures == null) 446 { 447 super.rotation = value; 448 } 449 else 450 { 451 layoutFeatures.layoutRotationZ = value; 452 validateTransformMatrix(); 453 } 454 } 455 456 //---------------------------------- 457 // scaleX 458 //---------------------------------- 459 460 /** 461 * @private 462 */ 463 override public function get scaleX():Number 464 { 465 return (layoutFeatures == null) ? super.scaleX : layoutFeatures.layoutScaleX; 466 } 467 468 /** 469 * @private 470 */ 471 override public function set scaleX(value:Number):void 472 { 473 if (scaleX == value) 474 return; 475 476 if (layoutFeatures == null) 477 { 478 super.scaleX = value; 479 } 480 else 481 { 482 layoutFeatures.layoutScaleX = value; 483 layoutFeatures.layoutWidth = Math.abs(value) * measuredWidth; 484 validateTransformMatrix(); 485 } 486 } 487 488 //---------------------------------- 489 // scaleY 490 //---------------------------------- 491 492 /** 493 * @private 494 */ 495 override public function get scaleY():Number 496 { 497 return (layoutFeatures == null) ? super.scaleY : layoutFeatures.layoutScaleY; 498 } 499 500 /** 501 * @private 502 */ 503 override public function set scaleY(value:Number):void 504 { 505 if (scaleY == value) 506 return; 507 508 if (layoutFeatures == null) 509 { 510 super.scaleY = value; 511 } 512 else 513 { 514 layoutFeatures.layoutScaleY = value; 515 _height = Math.abs(value) * measuredHeight; 516 validateTransformMatrix(); 517 } 518 } 519 520 //---------------------------------- 521 // scaleZ 522 //---------------------------------- 523 524 /** 525 * @private 526 */ 527 override public function get scaleZ():Number 528 { 529 return (layoutFeatures == null) ? super.scaleZ : layoutFeatures.layoutScaleZ; 530 } 531 532 /** 533 * @private 534 */ 535 override public function set scaleZ(value:Number):void 536 { 537 if (scaleZ == value) 538 return; 539 540 if (layoutFeatures == null) 541 { 542 super.scaleZ = value; 543 } 544 else 545 { 546 layoutFeatures.layoutScaleZ = value; 547 validateTransformMatrix(); 548 } 549 } 550 551 //-------------------------------------------------------------------------- 552 // 553 // Properties 554 // 555 //-------------------------------------------------------------------------- 556 557 //---------------------------------- 558 // layoutDirection 559 //---------------------------------- 560 561 // Use "ltr" instead of LayoutDirection.LTR to avoid depending 562 // on that framework class. 563 private var _layoutDirection:String = "ltr"; 564 565 [Inspectable(category="General", enumeration="ltr,rtl")] 566 567 /** 568 * @inheritDoc 569 * 570 * @langversion 3.0 571 * @playerversion Flash 10 572 * @playerversion AIR 1.5 573 * @productversion Flex 4.1 574 */ 575 public function get layoutDirection():String 576 { 577 return _layoutDirection; 578 } 579 580 public function set layoutDirection(value:String):void 581 { 582 if (value == _layoutDirection) 583 return; 584 585 _layoutDirection = value; 586 invalidateLayoutDirection(); 587 } 588 589 //---------------------------------- 590 // measuredHeight 591 //---------------------------------- 592 593 /** 594 * @inheritDoc 595 * 596 * @langversion 3.0 597 * @playerversion Flash 9 598 * @playerversion AIR 1.1 599 * @productversion Flex 3 600 */ 601 public function get measuredHeight():Number 602 { 603 if (bitmapData) 604 return bitmapData.height 605 606 return 0; 607 } 608 609 //---------------------------------- 610 // measuredWidth 611 //---------------------------------- 612 613 /** 614 * @inheritDoc 615 * 616 * @langversion 3.0 617 * @playerversion Flash 9 618 * @playerversion AIR 1.1 619 * @productversion Flex 3 620 */ 621 public function get measuredWidth():Number 622 { 623 if (bitmapData) 624 return bitmapData.width; 625 626 return 0; 627 } 628 629 //-------------------------------------------------------------------------- 630 // 631 // Methods 632 // 633 //-------------------------------------------------------------------------- 634 635 /** 636 * @inheritDoc 637 * 638 * @langversion 3.0 639 * @playerversion Flash 10 640 * @playerversion AIR 1.5 641 * @productversion Flex 4.1 642 */ 643 public function invalidateLayoutDirection():void 644 { 645 var p:DisplayObjectContainer = parent; 646 647 // We check the closest parent's layoutDirection property 648 // to create or destroy layoutFeatures if needed. 649 while (p) 650 { 651 if (p is ILayoutDirectionElement) 652 { 653 // mirror is true if our layoutDirection differs from our parent's. 654 var mirror:Boolean = _layoutDirection != null && 655 ILayoutDirectionElement(p).layoutDirection != null && 656 (_layoutDirection != ILayoutDirectionElement(p).layoutDirection); 657 658 // If our layoutDirection is different from our parent's and if it used to 659 // be the same, create layoutFeatures to handle mirroring. 660 if (mirror && layoutFeatures == null) 661 { 662 initAdvancedLayoutFeatures(); 663 if (layoutFeatures != null) 664 { 665 layoutFeatures.mirror = mirror; 666 validateTransformMatrix(); 667 } 668 } 669 else if (!mirror && layoutFeatures) 670 { 671 // If our layoutDirection is not different from our parent's and if 672 // it used to be different, then recover our matrix and remove layoutFeatures. 673 layoutFeatures.mirror = mirror; 674 validateTransformMatrix(); 675 layoutFeatures = null; 676 } 677 678 break; 679 } 680 681 p = p.parent; 682 } 683 } 684 685 /** 686 * @inheritDoc 687 * 688 * @langversion 3.0 689 * @playerversion Flash 9 690 * @playerversion AIR 1.1 691 * @productversion Flex 3 692 */ 693 public function move(x:Number, y:Number):void 694 { 695 this.x = x; 696 this.y = y; 697 } 698 699 /** 700 * @inheritDoc 701 * 702 * @langversion 3.0 703 * @playerversion Flash 9 704 * @playerversion AIR 1.1 705 * @productversion Flex 3 706 */ 707 public function setActualSize(newWidth:Number, newHeight:Number):void 708 { 709 width = newWidth; 710 height = newHeight; 711 } 712 713 /** 714 * @private 715 */ 716 private function addedHandler(event:Event):void 717 { 718 invalidateLayoutDirection(); 719 } 720 721 /** 722 * @private 723 * Initializes AdvancedLayoutFeatures for this asset when mirroring. 724 */ 725 private function initAdvancedLayoutFeatures():void 726 { 727 // Get AdvancedLayoutFeatures if it exists. 728 if (layoutFeaturesClass == null) 729 { 730 var appDomain:ApplicationDomain = ApplicationDomain.currentDomain; 731 732 if (appDomain.hasDefinition("mx.core::AdvancedLayoutFeatures")) 733 layoutFeaturesClass = Class(appDomain.getDefinition("mx.core::AdvancedLayoutFeatures")); 734 735 // Get MatrixUtil class if it exists 736 if (MatrixUtilClass == null) 737 { 738 if (appDomain.hasDefinition("mx.utils::MatrixUtil")) 739 MatrixUtilClass = Class(appDomain.getDefinition("mx.utils::MatrixUtil")); 740 } 741 } 742 743 if (layoutFeaturesClass != null) 744 { 745 var features:IAssetLayoutFeatures = new layoutFeaturesClass(); 746 747 features.layoutScaleX = scaleX; 748 features.layoutScaleY = scaleY; 749 features.layoutScaleZ = scaleZ; 750 features.layoutRotationX = rotationX; 751 features.layoutRotationY = rotationY; 752 features.layoutRotationZ = rotation; 753 features.layoutX = x; 754 features.layoutY = y; 755 features.layoutZ = z; 756 features.layoutWidth = width; // for the mirror transform 757 _height = height; // for backing storage 758 layoutFeatures = features; 759 } 760 } 761 762 /** 763 * @private 764 * Applies the transform matrix calculated by AdvancedLayoutFeatures 765 * so that this bitmap will not be mirrored if a parent is mirrored. 766 */ 767 private function validateTransformMatrix():void 768 { 769 if (layoutFeatures != null) 770 { 771 if (layoutFeatures.is3D) 772 super.transform.matrix3D = layoutFeatures.computedMatrix3D; 773 else 774 super.transform.matrix = layoutFeatures.computedMatrix; 775 } 776 } 777} 778 779} 780