Newer
Older
pixi.js / src / core / textures / BaseTexture.js
@Mat Groves Mat Groves on 14 Mar 2017 9 KB Sag / image / canvas all in!
import {
    uid, getUrlFileExtension, decomposeDataUri, getSvgSize,
    getResolutionOfUrl, BaseTextureCache, TextureCache,
} from '../utils';

import ImageResource from './resources/ImageResource';
import BufferResource from './resources/BufferResource';
import CanvasResource from './resources/CanvasResource';
import SVGResource from './resources/SVGResource';

import settings from '../settings';
import EventEmitter from 'eventemitter3';
import bitTwiddle from 'bit-twiddle';

export default class BaseTexture extends EventEmitter
{
    constructor(width, height, format, type, resolution)
    {

        super();


        this.uid = uid();

        this.touched = 0;

        /**
         * The width of texture
         *
         * @member {Number}
         */
        this.width = width || -1;
        /**
         * The height of texture
         *
         * @member {Number}
         */
        this.height = height || -1;

        /**
         * The resolution / device pixel ratio of the texture
         *
         * @member {number}
         * @default 1
         */
        this.resolution = resolution || settings.RESOLUTION;

        /**
         * Whether or not the texture is a power of two, try to use power of two textures as much
         * as you can
         *
         * @private
         * @member {boolean}
         */
        this.isPowerOfTwo = false;

        /**
         * If mipmapping was used for this texture, enable and disable with enableMipmap()
         *
         * @member {Boolean}
         */
        this.mipmap = false;//settings.MIPMAP_TEXTURES;

        /**
         * Set to true to enable pre-multiplied alpha
         *
         * @member {Boolean}
         */
        this.premultiplyAlpha = true;

        /**
         * [wrapMode description]
         * @type {[type]}
         */
        this.wrapMode = settings.WRAP_MODE;

        /**
         * The scale mode to apply when scaling this texture
         *
         * @member {number}
         * @default PIXI.settings.SCALE_MODE
         * @see PIXI.SCALE_MODES
         */
        this.scaleMode = settings.SCALE_MODE;

        /**
         * The pixel format of the texture. defaults to gl.RGBA
         *
         * @member {Number}
         */
        this.format = format || 6408//gl.RGBA;
        this.type = type || 5121; //UNSIGNED_BYTE

        this.target = 3553; // gl.TEXTURE_2D

        this._glTextures = {};

        this._new = true;

        this.resource = null;



        this.dirtyId = 0;

        this.valid = false;

        this.validate();
    }

    setResource(resource)
    {
        this.resource = resource;

        this.resource.load.then((resource) => {

            if(this.resource === resource)
            {
                if(resource.width !== -1 && resource.hight !== -1)
                {
                    this.width = resource.width / this.resolution;
                    this.height = resource.height / this.resolution;
                }

                this.validate();

                if(this.valid)
                {
                    this.isPowerOfTwo = bitTwiddle.isPow2(this.realWidth) && bitTwiddle.isPow2(this.realHeight);

                    // we have not swapped half way!
                    this.dirtyId++;
                    this.emit('loaded', this);
                }
            }

        })
    }

    resize(width, height)
    {
        this.width = width;
        this.height = height;

        this.dirtyId++;
    }

    validate()
    {
        let valid = true;

        if(this.width === -1 || this.height === -1)
        {
            valid = false;
        }

        this.valid = valid;
    }

    /**
     * Helper function that creates a base texture from the given image url.
     * If the image is not in the base texture cache it will be created and loaded.
     *
     * @static
     * @param {string} imageUrl - The image url of the texture
     * @param {boolean} [crossorigin=(auto)] - Should use anonymous CORS? Defaults to true if the URL is not a data-URI.
     * @param {number} [scaleMode=PIXI.settings.SCALE_MODE] - See {@link PIXI.SCALE_MODES} for possible values
     * @return {PIXI.BaseTexture} The new base texture.
     */
    static fromImage(imageUrl, crossorigin, scaleMode)
    {
        let baseTexture = BaseTextureCache[imageUrl];

        if (!baseTexture)
        {
            // new Image() breaks tex loading in some versions of Chrome.
            // See https://code.google.com/p/chromium/issues/detail?id=238071
            const resource = ImageResource.from(imageUrl, crossorigin);// document.createElement('img');

            baseTexture = new BaseTexture();//image, scaleMode);
            baseTexture.scaleMode = scaleMode ||  baseTexture.scaleMode;
            baseTexture.resolution = getResolutionOfUrl(imageUrl);
            baseTexture.setResource(resource);
            BaseTextureCache[imageUrl] = baseTexture;
        }

        return baseTexture;
    }

    /**
     * Helper function that creates a base texture from the given canvas element.
     *
     * @static
     * @param {HTMLCanvasElement} canvas - The canvas element source of the texture
     * @param {number} scaleMode - See {@link PIXI.SCALE_MODES} for possible values
     * @return {PIXI.BaseTexture} The new base texture.
     */
    static fromCanvas(canvas, scaleMode)
    {

        if (!canvas._pixiId)
        {
            canvas._pixiId = `canvas_${uid()}`;
        }

        let baseTexture = BaseTextureCache[canvas._pixiId];

        if (!baseTexture)
        {

            const resource = CanvasResource.from(canvas);// document.createElement('img');

            baseTexture = new BaseTexture();
            baseTexture.scaleMode = scaleMode ||  baseTexture.scaleMode;
            baseTexture.setResource(resource);

            BaseTextureCache[canvas._pixiId] = baseTexture;
        }

        return baseTexture;
    }

    /**
     * Helper function that creates a base texture from the given canvas element.
     *
     * @static
     * @param {HTMLCanvasElement} canvas - The canvas element source of the texture
     * @param {number} scaleMode - See {@link PIXI.SCALE_MODES} for possible values
     * @return {PIXI.BaseTexture} The new base texture.
     */
    static fromSVG(url, scale, scaleMode)
    {
        let baseTexture = BaseTextureCache[url];

        if (!baseTexture)
        {
            const resource = SVGResource.from(url);// document.createElement('img');

            baseTexture = new BaseTexture();
            baseTexture.scaleMode = scaleMode ||  baseTexture.scaleMode;
            baseTexture.setResource(resource);

            BaseTextureCache[url] = baseTexture;
        }

        return baseTexture;
    }
    get realWidth()
    {
        return this.width * this.resolution;
    }

    get realHeight()
    {
        return this.height * this.resolution;
    }

    /**
     * Helper function that creates a base texture based on the source you provide.
     * The source can be - image url, image element, canvas element.
     *
     * @static
     * @param {string|HTMLImageElement|HTMLCanvasElement} source - The source to create base texture from.
     * @param {number} [scaleMode=PIXI.settings.SCALE_MODE] - See {@link PIXI.SCALE_MODES} for possible values
     * @param {number} [sourceScale=(auto)] - Scale for the original image, used with Svg images.
     * @return {PIXI.BaseTexture} The new base texture.
     */
    static fromNEW(url)
    {
        var texture = new Texture();

        var image = new Image();
        image.src = url;
        texture.setResource(new ImageResource(image));

        return texture;
    }

    /**
     * Helper function that creates a base texture based on the source you provide.
     * The source can be - image url, image element, canvas element.
     *
     * @static
     * @param {string|HTMLImageElement|HTMLCanvasElement} source - The source to create base texture from.
     * @param {number} [scaleMode=PIXI.settings.SCALE_MODE] - See {@link PIXI.SCALE_MODES} for possible values
     * @param {number} [sourceScale=(auto)] - Scale for the original image, used with Svg images.
     * @return {PIXI.BaseTexture} The new base texture.
     */
    static from(source, scaleMode, sourceScale)
    {
        if (typeof source === 'string')
        {
            return BaseTexture.fromImage(source, undefined, scaleMode, sourceScale);
        }
        else if (source instanceof HTMLImageElement)
        {
            const imageUrl = source.src;
            let baseTexture = BaseTextureCache[imageUrl];

            if (!baseTexture)
            {
                baseTexture = new BaseTexture(source, scaleMode);
                baseTexture.imageUrl = imageUrl;

                if (sourceScale)
                {
                    baseTexture.sourceScale = sourceScale;
                }

                // if there is an @2x at the end of the url we are going to assume its a highres image
                baseTexture.resolution = getResolutionOfUrl(imageUrl);

                BaseTextureCache[imageUrl] = baseTexture;
            }

            return baseTexture;
        }
        else if (source instanceof HTMLCanvasElement)
        {
            return BaseTexture.fromCanvas(source, scaleMode);
        }

        // lets assume its a base texture!
        return source;
    }

    static fromFloat32Array(width, height, float32Array)
    {
        var texture = new Texture(width, height, 6408, 5126);

        float32Array = float32Array || new Float32Array(width*height*4);

        texture.setResource(new BufferResource(float32Array));

        return texture;
    }

    static fromUint8Array(width, height, uint8Array)
    {
        var texture = new Texture(width, height, 6408, 5121);

        uint8Array = uint8Array || new Uint8Array(width*height*4);

        texture.setResource(new BufferResource(uint8Array));

        return texture;
    }

}