Phaser Source: src/pixi/textures/Texture.js

# Source: src/pixi/textures/Texture.js

    /**
     * @author Mat Groves http://matgroves.com/ @Doormat23
     */

    /**
     * TextureSilentFail is a boolean that defaults to `false`.
     * If `true` then `PIXI.Texture.setFrame` will no longer throw an error if the texture dimensions are incorrect.
     * Instead `Texture.valid` will be set to `false` (#1556)
     *
     * @type {boolean}
     */
    PIXI.TextureSilentFail = false;

    /**
     * A texture stores the information that represents an image or part of an image. It cannot be added
     * to the display list directly. Instead use it as the texture for a PIXI.Sprite. If no frame is provided then the whole image is used.
     *
     * @class Texture
     * @uses EventTarget
     * @constructor
     * @param baseTexture {BaseTexture} The base texture source to create the texture from
     * @param frame {Rectangle} The rectangle frame of the texture to show
     * @param [crop] {Rectangle} The area of original texture
     * @param [trim] {Rectangle} Trimmed texture rectangle
     */
    PIXI.Texture = function(baseTexture, frame, crop, trim)
    {
        /**
         * Does this Texture have any frame data assigned to it?
         *
         * @property noFrame
         * @type Boolean
         */
        this.noFrame = false;

        if (!frame)
        {
            this.noFrame = true;
            frame = new PIXI.Rectangle(0,0,1,1);
        }

        if (baseTexture instanceof PIXI.Texture)
        {
            baseTexture = baseTexture.baseTexture;
        }

        /**
         * The base texture that this texture uses.
         *
         * @property baseTexture
         * @type BaseTexture
         */
        this.baseTexture = baseTexture;

        /**
         * The frame specifies the region of the base texture that this texture uses
         *
         * @property frame
         * @type Rectangle
         */
        this.frame = frame;

        /**
         * The texture trim data.
         *
         * @property trim
         * @type Rectangle
         */
        this.trim = trim;

        /**
         * This will let the renderer know if the texture is valid. If it's not then it cannot be rendered.
         *
         * @property valid
         * @type Boolean
         */
        this.valid = false;

        /**
         * Is this a tiling texture? As used by the likes of a TilingSprite.
         *
         * @property isTiling
         * @type Boolean
         */
        this.isTiling = false;

        /**
         * This will let a renderer know that a texture has been updated (used mainly for webGL uv updates)
         *
         * @property requiresUpdate
         * @type Boolean
         */
        this.requiresUpdate = false;

        /**
         * This will let a renderer know that a tinted parent has updated its texture.
         *
         * @property requiresReTint
         * @type Boolean
         */
        this.requiresReTint = false;

        /**
         * The WebGL UV data cache.
         *
         * @property _uvs
         * @type Object
         * @private
         */
        this._uvs = null;

        /**
         * The width of the Texture in pixels.
         *
         * @property width
         * @type Number
         */
        this.width = 0;

        /**
         * The height of the Texture in pixels.
         *
         * @property height
         * @type Number
         */
        this.height = 0;

        /**
         * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering,
         * irrespective of the actual frame size or placement (which can be influenced by trimmed texture atlases)
         *
         * @property crop
         * @type Rectangle
         */
        this.crop = crop || new PIXI.Rectangle(0, 0, 1, 1);

        if (baseTexture.hasLoaded)
        {
            if (this.noFrame) frame = new PIXI.Rectangle(0, 0, baseTexture.width, baseTexture.height);
            this.setFrame(frame);
        }

    };

    PIXI.Texture.prototype.constructor = PIXI.Texture;

    /**
     * Called when the base texture is loaded
     *
     * @method onBaseTextureLoaded
     * @private
     */
    PIXI.Texture.prototype.onBaseTextureLoaded = function()
    {
        var baseTexture = this.baseTexture;

        if (this.noFrame)
        {
            this.frame = new PIXI.Rectangle(0, 0, baseTexture.width, baseTexture.height);
        }

        this.setFrame(this.frame);
    };

    /**
     * Destroys this texture
     *
     * @method destroy
     * @param destroyBase {Boolean} Whether to destroy the base texture as well
     */
    PIXI.Texture.prototype.destroy = function(destroyBase)
    {
        if (destroyBase) this.baseTexture.destroy();

        this.valid = false;
    };

    /**
     * Specifies the region of the baseTexture that this texture will use.
     *
     * @method setFrame
     * @param frame {Rectangle} The frame of the texture to set it to
     */
    PIXI.Texture.prototype.setFrame = function(frame)
    {
        this.noFrame = false;

        this.frame = frame;
        this.width = frame.width;
        this.height = frame.height;

        this.crop.x = frame.x;
        this.crop.y = frame.y;
        this.crop.width = frame.width;
        this.crop.height = frame.height;

        if (!this.trim && (frame.x + frame.width > this.baseTexture.width || frame.y + frame.height > this.baseTexture.height))
        {
            if (!PIXI.TextureSilentFail)
            {
                throw new Error('Texture Error: frame does not fit inside the base Texture dimensions ' + this);
            }

            this.valid = false;
            return;
        }

        this.valid = frame && frame.width && frame.height && this.baseTexture.source && this.baseTexture.hasLoaded;

        if (this.trim)
        {
            this.width = this.trim.width;
            this.height = this.trim.height;
            this.frame.width = this.trim.width;
            this.frame.height = this.trim.height;
        }

        if (this.valid) this._updateUvs();

    };

    /**
     * Updates the internal WebGL UV cache.
     *
     * @method _updateUvs
     * @private
     */
    PIXI.Texture.prototype._updateUvs = function()
    {
        if(!this._uvs)this._uvs = new PIXI.TextureUvs();

        var frame = this.crop;
        var tw = this.baseTexture.width;
        var th = this.baseTexture.height;

        this._uvs.x0 = frame.x / tw;
        this._uvs.y0 = frame.y / th;

        this._uvs.x1 = (frame.x + frame.width) / tw;
        this._uvs.y1 = frame.y / th;

        this._uvs.x2 = (frame.x + frame.width) / tw;
        this._uvs.y2 = (frame.y + frame.height) / th;

        this._uvs.x3 = frame.x / tw;
        this._uvs.y3 = (frame.y + frame.height) / th;
    };

    /**
     * Helper function that creates a new a Texture based on the given canvas element.
     *
     * @static
     * @method fromCanvas
     * @param canvas {Canvas} The canvas element source of the texture
     * @param scaleMode {Number} See {{#crossLink "PIXI/scaleModes:property"}}PIXI.scaleModes{{/crossLink}} for possible values
     * @return {Texture}
     */
    PIXI.Texture.fromCanvas = function(canvas, scaleMode)
    {
        var baseTexture = PIXI.BaseTexture.fromCanvas(canvas, scaleMode);

        return new PIXI.Texture(baseTexture);
    };

    PIXI.TextureUvs = function()
    {
        this.x0 = 0;
        this.y0 = 0;

        this.x1 = 0;
        this.y1 = 0;

        this.x2 = 0;
        this.y2 = 0;

        this.x3 = 0;
        this.y3 = 0;
    };