var SystemRenderer = require('../SystemRenderer'), CanvasMaskManager = require('./utils/CanvasMaskManager'), CanvasRenderTarget = require('./utils/CanvasRenderTarget'), mapCanvasBlendModesToPixi = require('./utils/mapCanvasBlendModesToPixi'), utils = require('../../utils'), CONST = require('../../const'); /** * The CanvasRenderer draws the scene and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :) * * @class * @memberof PIXI * @extends PIXI.SystemRenderer * @param [width=800] {number} the width of the canvas view * @param [height=600] {number} the height of the canvas view * @param [options] {object} The optional renderer parameters * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional * @param [options.transparent=false] {boolean} If the render view is transparent, default false * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or * not before the new render pass. * @param [options.roundPixels=false] {boolean} If true Pixi will Math.floor() x/y values when rendering, stopping pixel interpolation. */ function CanvasRenderer(width, height, options) { options = options || {}; SystemRenderer.call(this, 'Canvas', width, height, options); this.type = CONST.RENDERER_TYPE.CANVAS; /** * The canvas 2d context that everything is drawn with. * * @member {CanvasRenderingContext2D} */ this.rootContext = this.view.getContext('2d', { alpha: this.transparent }); this.rootResolution = this.resolution; /** * Boolean flag controlling canvas refresh. * * @member {boolean} */ this.refresh = true; /** * Instance of a CanvasMaskManager, handles masking when using the canvas renderer. * * @member {PIXI.CanvasMaskManager} */ this.maskManager = new CanvasMaskManager(this); /** * The canvas property used to set the canvas smoothing property. * * @member {string} */ this.smoothProperty = 'imageSmoothingEnabled'; if (!this.rootContext.imageSmoothingEnabled) { if (this.rootContext.webkitImageSmoothingEnabled) { this.smoothProperty = 'webkitImageSmoothingEnabled'; } else if (this.rootContext.mozImageSmoothingEnabled) { this.smoothProperty = 'mozImageSmoothingEnabled'; } else if (this.rootContext.oImageSmoothingEnabled) { this.smoothProperty = 'oImageSmoothingEnabled'; } else if (this.rootContext.msImageSmoothingEnabled) { this.smoothProperty = 'msImageSmoothingEnabled'; } } this.initPlugins(); this.blendModes = mapCanvasBlendModesToPixi(); this._activeBlendMode = null; this.context = null; this.renderingToScreen = false; this.resize(width, height); } // constructor CanvasRenderer.prototype = Object.create(SystemRenderer.prototype); CanvasRenderer.prototype.constructor = CanvasRenderer; module.exports = CanvasRenderer; utils.pluginTarget.mixin(CanvasRenderer); /** * Renders the object to this canvas view * * @param displayObject {PIXI.DisplayObject} The object to be rendered * @param [renderTexture] {PIXI.RenderTexture} A render texture to be rendered to. If unset, it will render to the root context. * @param [clear=false] {boolean} Whether to clear the canvas before drawing * @param [transform] {PIXI.Transform} A transformation to be applied * @param skipUpdateTransform {boolean} Whether to skip the update transform */ CanvasRenderer.prototype.render = function (displayObject, renderTexture, clear, transform, skipUpdateTransform) { if (!this.view){ return; } // can be handy to know! this.renderingToScreen = !renderTexture; this.emit('prerender'); if(renderTexture) { renderTexture = renderTexture.baseTexture || renderTexture; if(!renderTexture._canvasRenderTarget) { renderTexture._canvasRenderTarget = new CanvasRenderTarget(renderTexture.width, renderTexture.height, renderTexture.resolution); renderTexture.source = renderTexture._canvasRenderTarget.canvas; renderTexture.valid = true; } this.context = renderTexture._canvasRenderTarget.context; this.resolution = renderTexture._canvasRenderTarget.resolution; } else { this.context = this.rootContext; this.resolution = this.rootResolution; } var context = this.context; this._lastObjectRendered = displayObject; if(!skipUpdateTransform) { // update the scene graph var cacheParent = displayObject.parent; var tempWt = this._tempDisplayObjectParent.transform.worldTransform; if(transform) { transform.copy(tempWt); } else { tempWt.identity(); } displayObject.parent = this._tempDisplayObjectParent; displayObject.updateTransform(); displayObject.parent = cacheParent; // displayObject.hitArea = //TODO add a temp hit area } context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; context.globalCompositeOperation = this.blendModes[CONST.BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) { context.fillStyle = 'black'; context.clear(); } if( clear || this.clearBeforeRender) { if (this.transparent) { context.clearRect(0, 0, this.width, this.height); } else { context.fillStyle = this._backgroundColorString; context.fillRect(0, 0, this.width , this.height); } } // TODO RENDER TARGET STUFF HERE.. var tempContext = this.context; this.context = context; displayObject.renderCanvas(this); this.context = tempContext; this.emit('postrender'); }; CanvasRenderer.prototype.setBlendMode = function (blendMode) { if(this._activeBlendMode === blendMode) { return; } this.context.globalCompositeOperation = this.blendModes[blendMode]; }; /** * Removes everything from the renderer and optionally removes the Canvas DOM element. * * @param [removeView=false] {boolean} Removes the Canvas element from the DOM. */ CanvasRenderer.prototype.destroy = function (removeView) { this.destroyPlugins(); // call the base destroy SystemRenderer.prototype.destroy.call(this, removeView); this.context = null; this.refresh = true; this.maskManager.destroy(); this.maskManager = null; this.smoothProperty = null; }; /** * @extends PIXI.SystemRenderer#resize * * @param {number} w * @param {number} h */ CanvasRenderer.prototype.resize = function (w, h) { SystemRenderer.prototype.resize.call(this, w, h); //reset the scale mode.. oddly this seems to be reset when the canvas is resized. //surely a browser bug?? Let pixi fix that for you.. if(this.smoothProperty) { this.rootContext[this.smoothProperty] = (CONST.SCALE_MODES.DEFAULT === CONST.SCALE_MODES.LINEAR); } };