(function(Gear, Global, Constants, Util) {
	
	/**
	 * Shapes are primitive form, such as: rectangles, circles, lines, etc...
	 * @param {Object} config
	 */
	var Shape = function(config) {
		Gear.Node.call(this, config);
		
		this.nodeType = Constants.NODE_TYPE.SHAPE;
		this._colorKey = Gear.Color.getUnique();
		Global.shapes[this._colorKey] = this;
	};

	_.extend(Shape.prototype, Gear.Node.prototype, {

		/**
		 * Get the unique color id for this shape
		 * @return {String} color
		 */
		getColorId: function() {
			return this._colorKey;
		},

		drawScene: function(canvas) {
			// Get the draw. Use getDraw to allow an attr
			// to take precedence, otherwise, use the draw
			// as defined by this
			var draw = this.getDraw() || this.draw;
			if (!draw || !this.isVisible()) { return this; }

			canvas = canvas || this.getLayer().getCanvas();

			var context = canvas.getContext();

			canvas.save();
			canvas.applyOpacity(this);
			canvas.applyLineJoin(this);
			canvas.applyAncestorTransforms(this);
			canvas.applyRotation(this);

			draw.call(this, canvas);
			canvas.restore();
			
			return this;
		},

		drawHit: function() {
			var draw = this.getDraw() || this.draw;
			if (!draw || !this.shouldDrawHit()) { return this; }

			var canvas = this.getLayer().getHitCanvas(),
				context = canvas.getContext();

			canvas.save();
			canvas.applyLineJoin(this);
			canvas.applyAncestorTransforms(this);
			canvas.applyRotation(this);
			draw.call(this, canvas);
			canvas.restore();

			return this;
		},

		getLineJoin: function() {
			return this.attr.lineJoin;
		},
		setLineJoin: function(joint) {
			this.attr.lineJoin = joint;
			return this;
		},

		/**
		 * Whether a stroke is set
		 * @return {Boolean}
		 */
		hasStroke: function() {
			var stroke = this.getStroke();
			return (stroke && stroke.isEnabled() && stroke.getWidth() > 0);
		},
		getStroke: function() {
			return this.attr.stroke;
		},
		setStroke: function(config) {
			if (config instanceof Gear.Stroke) {
				this.attr.stroke = config;
				return this;
			}

			this.attr.stroke = new Gear.Stroke(config);
			return this;
		},

		/**
		 * Whether a fill is set
		 * @return {Boolean}
		 */
		hasFill: function() {
			var fill = this.getFill();
			return (fill && fill.isEnabled());
		},
		getFill: function() {
			return this.attr.fill;
		},
		setFill: function(fill) {
			if (Gear.Fill.isFill(fill)) {
				this.att.fill = fill;
			}
			
			this.attr.fill = Gear.Fill.parse(fill);
			return this;
		},

		/**
		 * Whether a shadow is set
		 * @return {Boolean}
		 */
		hasShadow: function() {
			var shadow = this.getShadow();
			return (shadow && shadow.isEnabled() && shadow.getOpacity() !== 0);
		},
		getShadow: function() {
			return this.attr.shadow;
		},
		setShadow: function(config) {
			if (config instanceof Gear.Shadow) {
				this.attr.shadow = config;
				return this;
			}

			this.attr.shadow = new Gear.Shadow(config);
			return this;
		},

		destroy: function() {
			Gear.Node.prototype.destroy.call(this);
			delete Global.shapes[this.getColorId()];
			return this;
		},

		toString: function() {
			return '[Shape]';
		}
	});
	
	Gear.Shape = Shape;

}(Gear, Gear.Global, Gear.Constants, Gear.Util));
@@ -1039,16 +1039,117 @@
 this);%0A%0A
+%09%09%09if (this._cache) %7B%0A%09%09%09%09canvas.getContext().drawImage(this._cache.getCanvas(), 0, 0);%0A%09%09%09%7D else %7B%0A%09
 %09%09%09draw.
@@ -1160,32 +1160,41 @@
 (this, canvas);%0A
+%09%09%09%7D%0A%09%09%09%0A
 %09%09%09canvas.restor
@@ -3053,16 +3053,463 @@
 ;%0A%09%09%7D,%0A%0A
+%09%09/**%0A%09%09 * Cache %7C Uncahe%0A%09%09 */%0A%09%09_getCacheScene: function() %7B%0A%09%09%09return this._cacheScene %7C%7C (this._cacheScene = new Gear.SceneCanvas());%0A%09%09%7D,%0A%09%09cache: function() %7B%0A%09%09%09var scene = this._getCacheScene(),%0A%09%09%09%09draw = this.getDraw() %7C%7C this.draw;%0A%09%09%09scene.setSize(this.getSize());%0A%09%09%09draw.call(this, scene);%0A%09%09%09this._cache = scene;%0A%09%09%7D,%0A%09%09uncache: function() %7B%0A%09%09%09this._cache = null;%0A%09%09%7D,%0A%0A%09%09/**%0A%09%09 * Destroy%0A%09%09 * @return %7B%5Btype%5D%7D %5Bdescription%5D%0A%09%09 */%0A
 %09%09destro

Implement basic caching