flash on 2010-12-15

by grapefrukt
Copyright (c) 2008 Martin Jonasson

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH 
♥0 | Line 94 | Modified 2010-12-15 18:03:09 | MIT License
play

ActionScript3 source code

/**
 * Copyright grapefrukt ( http://wonderfl.net/user/grapefrukt )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/mA7Q
 */

package {

	import flash.display.Sprite;
	import flash.display.Bitmap;
	import flash.display.DisplayObject;
	import flash.display.BitmapData;
	import flash.display.PixelSnapping;
	import flash.filters.BitmapFilter;
	
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.display.BlendMode;
	import flash.geom.ColorTransform;
	
	public class Canvas extends Sprite {
		
		private var _canvasDisplay	:BitmapData;
		private var _canvasBackBuffer	:BitmapData;
		
		private var _bitmap				:Bitmap;
		
		private var _clipRect			:Rectangle;
		private var _colorTransform		:ColorTransform;
		private var _nullPoint			:Point;
		private var _filterList			:Array;
		
		private var _copyMatrix			:Matrix;
		private var _drawMatrix			:Matrix;
		
		private var _clearColor			:uint = 	0x000000;
		private var _clearSprite		:Sprite;
		
		private var _resolutionX				:uint = 	500;
		private var _resolutionY				:uint = 	500;
		private var _bufferScale		:Number = 	1;
		
		private var _clearEachUpdate	:Boolean =	true;
		
		// these are some intermediate vars that we keep in the class to make it go a bit faster
		private var _tmpfilter:BitmapFilter;
		
		/**
		 * Creates a Canvas, which is essentially a double-buffer bitmap with some stuff for adding effects
		 * @param	resolutionX				The canvas width
		 * @param	resolutionY				The canvas height
		 * @param	clearEachUpdate		Set this to fill the canvas with clearColor each update
		 * @param	bufferDivisor		How big the back buffer is in relation to the front, 2 would be half the size, 4 a quarter and so on.
		 */
		
		public function Canvas(resolutionX:uint, resolutionY:uint, clearEachUpdate:Boolean = false, bufferDivisor:Number = 1):void {
			_resolutionX = 			resolutionX;
			_resolutionY = 			resolutionY;
			_bufferScale = 			1 / bufferDivisor;
			_clearEachUpdate = 		clearEachUpdate;
			
			// makes sure the buffer scale is a reasonable value
			if (_bufferScale > 1) _bufferScale = 1;
			if (_bufferScale < 0) _bufferScale = 0;
			
			// initialize a bunch of bitmap stuff, refer to the regular docs for more info on what's going on here.
			_canvasDisplay = 		new BitmapData(_resolutionX, _resolutionY, false, 0x00000000);
			_canvasBackBuffer = 	new BitmapData(_resolutionX * _bufferScale, _resolutionY * _bufferScale, false, 0x00000000);
			_bitmap = 				new Bitmap(_canvasDisplay, PixelSnapping.ALWAYS, false);
			
			// a clipping rectangle used in most drawing/copying operations, this is to speed up copying a bit by helping flash figure out what needs to be copied
			_clipRect = new Rectangle(0, 0, _resolutionX, _resolutionY);
			
			// this is a point at 0,0 it's used in a bunch of drawing/copying operations where no transform or translation is needed
			_nullPoint = new Point(0, 0);
			
			// this matrix is used to scale the front buffer down to the back buffers size
			_copyMatrix = new Matrix();
			_copyMatrix.scale(_bufferScale, _bufferScale);
			
			// this matrix is used to scale it back up again
			_drawMatrix = new Matrix();
			_drawMatrix.scale(1/_bufferScale, 1/_bufferScale);
			
			// a simple sprite is used to clear the buffer since just using draw() is the fastest way
			_clearSprite = new Sprite();
			_clearSprite.graphics.beginFill(0x000000);
			_clearSprite.graphics.drawRect(0, 0, _resolutionX, _resolutionY);
			
			// this inits the filter array
			clearFilters();
			
			// finally we add the bitmap as a child
			addChild(_bitmap);
		}
		
		/**
		 * Adds a filter that is run when update() is called
		 * @param	newFilter The filter to apply
		 */
		public function addFilter(newFilter:BitmapFilter):void {
			_filterList.push(newFilter);
		}
		
		/**
		 * Removes all filters
		 */
		public function clearFilters():void {
			_filterList = new Array();
		}
		
		/**
		 * Draws a DisplayObject to the canvas
		 * @param	data			The DisplayObject to draw, normally you only need to set this
		 * @param	useTransform	Set this to false to ignore any transformation, the clip will be drawn with it's origin at 0-0 and no rotation applied, no transform is a wee bit faster
		 * @param	smooth			Enables/disables smoothing, no smoothing is a wee bit faster
		 * @param	blendMode		If you want to use a blendMode, feed it in here
		 */
		public function draw(data:DisplayObject, useTransform:Boolean = true, smooth:Boolean = true, blendMode:String = null):void {
			if (useTransform) {
				var matrix:Matrix = new Matrix();
				matrix.rotate(data.rotation * Math.PI / 180);
				matrix.scale(data.scaleX, data.scaleY);
				matrix.translate(data.x, data.y);
				_canvasDisplay.draw(data, matrix, null, blendMode, null, smooth);
			} else {
				_canvasDisplay.draw(data, null, null, blendMode, null, smooth);
			}
		}
		
		/**
		 * Clears the canvas
		 */
		public function clear():void {
			_canvasDisplay.draw(_clearSprite, null, null, null, _clipRect, false);
		}
		
		/**
		 * Applies all filters in the filter array and the transform set in colorTransform
		 * @see #colorTransform
		 */
		public function update():void {
			_canvasBackBuffer.draw(_canvasDisplay, _copyMatrix, null, null, _clipRect, true);
			
			if(_clearEachUpdate) clear();
			
			for each(_tmpfilter in _filterList) {
				_canvasBackBuffer.applyFilter(_canvasBackBuffer, _clipRect, _nullPoint, _tmpfilter);
			}
			
			_canvasDisplay.draw(_canvasBackBuffer, _drawMatrix, _colorTransform, BlendMode.NORMAL, _clipRect, true);
		}
		
		/**
		 * The color that is used to clear the canvas.
		 */
		public function get clearColor():uint { return _clearColor; }
		public function set clearColor(value:uint):void {
			_clearColor	= value;
			_clearSprite = new Sprite();
			_clearSprite.graphics.beginFill(_clearColor);
			_clearSprite.graphics.drawRect(0, 0, _resolutionX, _resolutionY);
		}

		/**
		 * The ColorTransform that is applied each update, useful for fades
		 */
		public function get colorTransform():ColorTransform { return _colorTransform };
		public function set colorTransform(value:ColorTransform):void { _colorTransform = value };
		
		
		/**
		 * Sets whether to clear the canvas each update
		 */
		public function get clearEachUpdate():Boolean	{ return _clearEachUpdate };
		public function set clearEachUpdate(value:Boolean):void	{ _clearEachUpdate = value };
		
		
		/**
		 * The canvas heigth, this can't be changed once the canvas has been created
		 */
		public function get resolutionX():uint { return _resolutionX };
		
		/**
		 * The canvas width, this can't be changed once the canvas has been created
		 */
		public function get resolutionY():uint { return _resolutionY };
		
	}
	
}