| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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.core |
| { |
| |
| import flash.display.BitmapData; |
| import flash.display.DisplayObjectContainer; |
| import flash.events.Event; |
| import flash.geom.Point; |
| import flash.system.ApplicationDomain; |
| |
| /** |
| * BitmapAsset is a subclass of the flash.display.Bitmap class |
| * which represents bitmap images that you embed in a Flex application. |
| * It implements the IFlexDisplayObject interface, which makes it |
| * possible for an embedded bitmap image to be displayed in an Image control, |
| * or to be used as a container background or a component skin. |
| * |
| * <p>The bitmap image that you're embedding can be in a JPEG, GIF, |
| * or PNG file. |
| * You can also embed a bitmap symbol that is in a SWF file produced |
| * by Flash. |
| * In each of these cases, the MXML compiler autogenerates a class |
| * that extends BitmapAsset to represent the embedded bitmap image.</p> |
| * |
| * <p>You don't generally have to use the BitmapAsset class directly |
| * when you write a Flex application. |
| * For example, you can embed a GIF file and display the image |
| * in an Image control by writing the gollowing:</p> |
| * |
| * <pre> |
| * <mx:Image id="logo" source="@Embed(source='Logo.gif')"/></pre> |
| * |
| * <p>or use it as the application's background image in CSS syntax |
| * by writing</p> |
| * |
| * <pre> |
| * <fx:Style> |
| * @namespace mx "library://ns.adobe.com/flex/mx" |
| * mx|Application { |
| * backgroundImage: Embed(source="Logo.gif") |
| * } |
| * <fx:Style/></pre> |
| * |
| * <p>without having to understand that the MXML compiler has created |
| * a subclass of BitmapAsset for you.</p> |
| * |
| * <p>However, it may be useful to understand what is happening |
| * at the ActionScript level. |
| * To embed a bitmap image in ActionScript, you declare a variable |
| * of type Class, and put <code>[Embed]</code> metadata on it. |
| * For example, you embed a GIF file like this:</p> |
| * |
| * <pre> |
| * [Bindable] |
| * [Embed(source="Logo.gif")] |
| * private var logoClass:Class;</pre> |
| * |
| * <p>The MXML compiler sees the .gif extension, transcodes the GIF data |
| * into the bitmap format that the player uses, autogenerates |
| * a subclass of the BitmapAsset class, and sets your variable |
| * to be a reference to this autogenerated class. |
| * You can then use this class reference to create instances of the |
| * BitmapAsset using the <code>new</code> operator, and you can use |
| * APIs of the BitmapAsset class on them:</p> |
| * |
| * <pre> |
| * var logo:BitmapAsset = BitmapAsset(new logoClass()); |
| * logo.bitmapData.noise(4);</pre> |
| * |
| * <p>However, you rarely need to create BitmapAsset instances yourself |
| * because image-related properties and styles can simply be set to an |
| * image-producing class, and components will create image instances |
| * as necessary. |
| * For example, to display this image in an Image control, you can |
| * set the Image's <code>source</code> property to <code>logoClass</code>. |
| * In MXML you could do this as follows:</p> |
| * |
| * <pre> |
| * <mx:Image id="logo" source="{logoClass}"/></pre> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class BitmapAsset extends FlexBitmap |
| implements IFlexAsset, IFlexDisplayObject, ILayoutDirectionElement |
| { |
| include "../core/Version.as"; |
| |
| // Softlink FlexVersion and MatrixUtil to remove dependencies of embeds on |
| // framework classes. This helps to reduce swf size in AS-only projects. |
| private static var FlexVersionClass:Class; |
| private static var MatrixUtilClass:Class; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @param bitmapData The data for the bitmap image. |
| * |
| * @param pixelSnapping Whether or not the bitmap is snapped |
| * to the nearest pixel. |
| * |
| * @param smoothing Whether or not the bitmap is smoothed when scaled. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function BitmapAsset(bitmapData:BitmapData = null, |
| pixelSnapping:String = "auto", |
| smoothing:Boolean = false) |
| { |
| super(bitmapData, pixelSnapping, smoothing); |
| |
| if (FlexVersionClass == null) |
| { |
| var appDomain:ApplicationDomain = ApplicationDomain.currentDomain; |
| if (appDomain.hasDefinition("mx.core::FlexVersion")) |
| FlexVersionClass = Class(appDomain.getDefinition("mx.core::FlexVersion")); |
| } |
| |
| if (FlexVersionClass && FlexVersionClass["compatibilityVersion"] >= FlexVersionClass["VERSION_4_0"]) |
| this.addEventListener(Event.ADDED, addedHandler); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| // Softlink AdvancedLayoutFeatures to remove dependencies of embeds on |
| // framework classes. This helps to reduce swf size in AS-only projects. |
| private var layoutFeaturesClass:Class; |
| private var layoutFeatures:IAssetLayoutFeatures; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // x |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get x():Number |
| { |
| // TODO(hmuller): by default get x returns transform.matrix.tx rounded to the nearest 20th. |
| // should do the same here, if we're returning layoutFeatures.layoutX. |
| return (layoutFeatures == null) ? super.x : layoutFeatures.layoutX; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set x(value:Number):void |
| { |
| if (x == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.x = value; |
| } |
| else |
| { |
| layoutFeatures.layoutX = value; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // y |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get y():Number |
| { |
| return (layoutFeatures == null) ? super.y : layoutFeatures.layoutY; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set y(value:Number):void |
| { |
| if (y == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.y = value; |
| } |
| else |
| { |
| layoutFeatures.layoutY = value; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // z |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get z():Number |
| { |
| return (layoutFeatures == null) ? super.z : layoutFeatures.layoutZ; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set z(value:Number):void |
| { |
| if (z == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.z = value; |
| } |
| else |
| { |
| layoutFeatures.layoutZ = value; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // width |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get width():Number |
| { |
| if (layoutFeatures == null) |
| return super.width; |
| |
| // Return bounding box width in mirroring case |
| var p:Point; |
| if (MatrixUtilClass != null) |
| p = MatrixUtilClass["transformSize"](layoutFeatures.layoutWidth, _height, transform.matrix); |
| |
| return p ? p.x : super.width; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set width(value:Number):void |
| { |
| if (width == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.width = value; |
| } |
| else |
| { |
| layoutFeatures.layoutWidth = value; |
| // Calculate scaleX based on initial width. We set scaleX |
| // here because resizing a BitmapAsset normally would adjust |
| // the scale to match. |
| layoutFeatures.layoutScaleX = measuredWidth != 0 ? value / measuredWidth : 0; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // height |
| //---------------------------------- |
| |
| private var _height:Number; |
| |
| /** |
| * @private |
| */ |
| override public function get height():Number |
| { |
| |
| if (layoutFeatures == null) |
| return super.height; |
| |
| // Return bounding box height in mirroring case |
| var p:Point; |
| if (MatrixUtilClass != null) |
| p = MatrixUtilClass["transformSize"](layoutFeatures.layoutWidth, _height, transform.matrix); |
| |
| return p ? p.y : super.height; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set height(value:Number):void |
| { |
| if (height == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.height = value; |
| } |
| else |
| { |
| _height = value; |
| // Calculate scaleY based on initial height. We set scaleY |
| // here because resizing a BitmapAsset normally would adjust |
| // the scale to match. |
| layoutFeatures.layoutScaleY = measuredHeight != 0 ? value / measuredHeight : 0; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // rotation |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get rotationX():Number |
| { |
| return (layoutFeatures == null) ? super.rotationX : layoutFeatures.layoutRotationX; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set rotationX(value:Number):void |
| { |
| if (rotationX == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.rotationX = value; |
| } |
| else |
| { |
| layoutFeatures.layoutRotationX = value; |
| validateTransformMatrix(); |
| } |
| } |
| /** |
| * @private |
| */ |
| override public function get rotationY():Number |
| { |
| return (layoutFeatures == null) ? super.rotationY : layoutFeatures.layoutRotationY; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set rotationY(value:Number):void |
| { |
| if (rotationY == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.rotationY = value; |
| } |
| else |
| { |
| layoutFeatures.layoutRotationY = value; |
| validateTransformMatrix(); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| override public function get rotationZ():Number |
| { |
| return (layoutFeatures == null) ? super.rotationZ : layoutFeatures.layoutRotationZ; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set rotationZ(value:Number):void |
| { |
| if (rotationZ == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.rotationZ = value; |
| } |
| else |
| { |
| layoutFeatures.layoutRotationZ = value; |
| validateTransformMatrix(); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| override public function get rotation():Number |
| { |
| return (layoutFeatures == null) ? super.rotation : layoutFeatures.layoutRotationZ; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set rotation(value:Number):void |
| { |
| if (rotation == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.rotation = value; |
| } |
| else |
| { |
| layoutFeatures.layoutRotationZ = value; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // scaleX |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get scaleX():Number |
| { |
| return (layoutFeatures == null) ? super.scaleX : layoutFeatures.layoutScaleX; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set scaleX(value:Number):void |
| { |
| if (scaleX == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.scaleX = value; |
| } |
| else |
| { |
| layoutFeatures.layoutScaleX = value; |
| layoutFeatures.layoutWidth = Math.abs(value) * measuredWidth; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // scaleY |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get scaleY():Number |
| { |
| return (layoutFeatures == null) ? super.scaleY : layoutFeatures.layoutScaleY; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set scaleY(value:Number):void |
| { |
| if (scaleY == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.scaleY = value; |
| } |
| else |
| { |
| layoutFeatures.layoutScaleY = value; |
| _height = Math.abs(value) * measuredHeight; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //---------------------------------- |
| // scaleZ |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override public function get scaleZ():Number |
| { |
| return (layoutFeatures == null) ? super.scaleZ : layoutFeatures.layoutScaleZ; |
| } |
| |
| /** |
| * @private |
| */ |
| override public function set scaleZ(value:Number):void |
| { |
| if (scaleZ == value) |
| return; |
| |
| if (layoutFeatures == null) |
| { |
| super.scaleZ = value; |
| } |
| else |
| { |
| layoutFeatures.layoutScaleZ = value; |
| validateTransformMatrix(); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // layoutDirection |
| //---------------------------------- |
| |
| // Use "ltr" instead of LayoutDirection.LTR to avoid depending |
| // on that framework class. |
| private var _layoutDirection:String = "ltr"; |
| |
| [Inspectable(category="General", enumeration="ltr,rtl")] |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4.1 |
| */ |
| public function get layoutDirection():String |
| { |
| return _layoutDirection; |
| } |
| |
| public function set layoutDirection(value:String):void |
| { |
| if (value == _layoutDirection) |
| return; |
| |
| _layoutDirection = value; |
| invalidateLayoutDirection(); |
| } |
| |
| //---------------------------------- |
| // measuredHeight |
| //---------------------------------- |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get measuredHeight():Number |
| { |
| if (bitmapData) |
| return bitmapData.height |
| |
| return 0; |
| } |
| |
| //---------------------------------- |
| // measuredWidth |
| //---------------------------------- |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get measuredWidth():Number |
| { |
| if (bitmapData) |
| return bitmapData.width; |
| |
| return 0; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4.1 |
| */ |
| public function invalidateLayoutDirection():void |
| { |
| var p:DisplayObjectContainer = parent; |
| |
| // We check the closest parent's layoutDirection property |
| // to create or destroy layoutFeatures if needed. |
| while (p) |
| { |
| if (p is ILayoutDirectionElement) |
| { |
| // mirror is true if our layoutDirection differs from our parent's. |
| var mirror:Boolean = _layoutDirection != null && |
| ILayoutDirectionElement(p).layoutDirection != null && |
| (_layoutDirection != ILayoutDirectionElement(p).layoutDirection); |
| |
| // If our layoutDirection is different from our parent's and if it used to |
| // be the same, create layoutFeatures to handle mirroring. |
| if (mirror && layoutFeatures == null) |
| { |
| initAdvancedLayoutFeatures(); |
| if (layoutFeatures != null) |
| { |
| layoutFeatures.mirror = mirror; |
| validateTransformMatrix(); |
| } |
| } |
| else if (!mirror && layoutFeatures) |
| { |
| // If our layoutDirection is not different from our parent's and if |
| // it used to be different, then recover our matrix and remove layoutFeatures. |
| layoutFeatures.mirror = mirror; |
| validateTransformMatrix(); |
| layoutFeatures = null; |
| } |
| |
| break; |
| } |
| |
| p = p.parent; |
| } |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function move(x:Number, y:Number):void |
| { |
| this.x = x; |
| this.y = y; |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function setActualSize(newWidth:Number, newHeight:Number):void |
| { |
| width = newWidth; |
| height = newHeight; |
| } |
| |
| /** |
| * @private |
| */ |
| private function addedHandler(event:Event):void |
| { |
| invalidateLayoutDirection(); |
| } |
| |
| /** |
| * @private |
| * Initializes AdvancedLayoutFeatures for this asset when mirroring. |
| */ |
| private function initAdvancedLayoutFeatures():void |
| { |
| // Get AdvancedLayoutFeatures if it exists. |
| if (layoutFeaturesClass == null) |
| { |
| var appDomain:ApplicationDomain = ApplicationDomain.currentDomain; |
| |
| if (appDomain.hasDefinition("mx.core::AdvancedLayoutFeatures")) |
| layoutFeaturesClass = Class(appDomain.getDefinition("mx.core::AdvancedLayoutFeatures")); |
| |
| // Get MatrixUtil class if it exists |
| if (MatrixUtilClass == null) |
| { |
| if (appDomain.hasDefinition("mx.utils::MatrixUtil")) |
| MatrixUtilClass = Class(appDomain.getDefinition("mx.utils::MatrixUtil")); |
| } |
| } |
| |
| if (layoutFeaturesClass != null) |
| { |
| var features:IAssetLayoutFeatures = new layoutFeaturesClass(); |
| |
| features.layoutScaleX = scaleX; |
| features.layoutScaleY = scaleY; |
| features.layoutScaleZ = scaleZ; |
| features.layoutRotationX = rotationX; |
| features.layoutRotationY = rotationY; |
| features.layoutRotationZ = rotation; |
| features.layoutX = x; |
| features.layoutY = y; |
| features.layoutZ = z; |
| features.layoutWidth = width; // for the mirror transform |
| _height = height; // for backing storage |
| layoutFeatures = features; |
| } |
| } |
| |
| /** |
| * @private |
| * Applies the transform matrix calculated by AdvancedLayoutFeatures |
| * so that this bitmap will not be mirrored if a parent is mirrored. |
| */ |
| private function validateTransformMatrix():void |
| { |
| if (layoutFeatures != null) |
| { |
| if (layoutFeatures.is3D) |
| super.transform.matrix3D = layoutFeatures.computedMatrix3D; |
| else |
| super.transform.matrix = layoutFeatures.computedMatrix; |
| } |
| } |
| } |
| |
| } |