1 goog.provide('lime.Renderer.CANVAS'); 2 3 goog.require('goog.math.Box.size'); 4 goog.require('goog.math.Size.scaleVec2'); 5 goog.require('lime.Renderer'); 6 7 /** 8 * Canvas renderer. This renders as canvas element or just 9 * draws on parent context. 10 * @const 11 * @type {lime.Renderer} 12 */ 13 lime.Renderer.CANVAS = new lime.Renderer(); 14 15 /** 16 * Update the DOM tree relations of the element. 17 * @this {lime.Node} 18 */ 19 lime.Renderer.CANVAS.updateLayout = function() {}; 20 21 /** 22 * Initalize canvas element and start the drawing process 23 * @this {lime.Node} 24 */ 25 lime.Renderer.CANVAS.drawCanvas = function() { 26 var quality = this.getQuality(), 27 bounds = this.measureContents(), 28 rquality = this.relativeQuality_ || 1, 29 ownquality = rquality / quality, 30 sizediff, 31 PADDING = 12; 32 33 34 if (!this.domElement) return; 35 36 if (this.boundsCache && this.boundsCache.contains(bounds) && 37 (sizediff = this.boundsCache.size().area() / bounds.size().area()) && 38 sizediff < 1.6 && sizediff > 0.5) { 39 //use the cached canvas size 40 bounds = this.boundsCache; 41 42 } 43 else { 44 if (this.staticCanvas != 1 && this.children_.length != 0) { 45 if(!(this instanceof lime.Scene)){ 46 bounds.expand(PADDING, PADDING, PADDING, PADDING); 47 } 48 } 49 } 50 51 52 //clip to director 53 /* var dir = this.getDirector(); 54 if (this.rotation_ == 0 && dir) { 55 var fr = dir.getFrame(); 56 var br = dir.localToNode( 57 new goog.math.Coordinate(fr.right, fr.bottom), this); 58 var tl = dir.localToNode( 59 new goog.math.Coordinate(fr.left, fr.top), this); 60 if (br.x < bounds.right) { 61 bounds.right = br.x; 62 } 63 if (br.y < bounds.bottom) { 64 bounds.bottom = br.y; 65 } 66 if (tl.x > bounds.left) { 67 bounds.left = tl.x; 68 } 69 if (tl.y > bounds.top) { 70 bounds.top = tl.y; 71 } 72 }*/ 73 74 this.boundsCache = bounds; //save for later use 75 76 var bsize = bounds.size(); 77 var pxsize = bsize.clone().scale(rquality).ceil(); 78 79 if (this.domElement.width != pxsize.width || 80 this.domElement.height != pxsize.height) { 81 this.domElement.width = pxsize.width; 82 this.domElement.height = pxsize.height; 83 this.redraw_ = 1; 84 // console.log('redraw'); 85 } 86 87 88 89 var realScale = this.getScale().clone(); 90 if (this.transitionsActive_[lime.Transition.SCALE]) { 91 realScale = this.transitionsActive_[lime.Transition.SCALE]; 92 //this.redraw_ = 1; 93 } 94 if (pxsize.width != 0) { 95 realScale.scale(bsize.width * ownquality / pxsize.width); 96 } 97 else { 98 realScale.scale(1 / quality); 99 } 100 101 102 var fr = this.getFrame(); 103 this.ax = (fr.left - bounds.left) * rquality; 104 this.ay = (fr.top - bounds.top) * rquality; 105 106 107 var ap_offset = this.getSize().clone(). 108 scaleVec2(this.getAnchorPoint()).scale(rquality); 109 110 var pos = this.getPosition().clone(); 111 112 if (this.transitionsActive_[lime.Transition.POSITION]) { 113 pos = this.transitionsActive_[lime.Transition.POSITION]; 114 //this.redraw_ = 1; 115 } 116 117 pos.x *= ownquality; 118 pos.y *= ownquality; 119 120 pos.x -= ap_offset.width + this.ax; 121 pos.y -= ap_offset.height + this.ay; 122 123 lime.style.setTransformOrigin(this.domElement, 124 (this.ax + ap_offset.width) / pxsize.width * 100, 125 (this.ay + ap_offset.height) / pxsize.height * 100, true); 126 127 if (!this.transitionsActiveSet_[lime.Transition.POSITION] && !this.transitionsActiveSet_[lime.Transition.SCALE] && !this.transitionsActiveSet_[lime.Transition.ROTATION]) { 128 129 var rotation = -this.getRotation(); 130 if (goog.isDef(this.transitionsActive_[lime.Transition.ROTATION])) { 131 rotation = -this.transitionsActive_[lime.Transition.ROTATION]; 132 } 133 lime.style.setTransform(this.domElement, 134 new lime.style.Transform().setPrecision(.1).translate(pos.x, pos.y). 135 scale(realScale.x, realScale.y).rotate(rotation)); 136 } 137 138 if (this.redraw_) { 139 var context = this.domElement.getContext('2d'); 140 rquality = this.relativeQuality_ || 1; 141 142 context.clearRect(0, 0, pxsize.width, pxsize.height); 143 context.save(); 144 context.translate(this.ax, this.ay); 145 context.scale(rquality, rquality); 146 147 148 var size = this.getSize(), anchor = this.getAnchorPoint(); 149 150 context.translate(size.width * anchor.x, size.height * anchor.y); 151 152 this.renderer.drawCanvasObject.call(this, context); 153 154 context.restore(); 155 this.redraw_ = 0; 156 157 158 } 159 }; 160 161 /** 162 * Update nodes dirty values and call draw after 163 * @this {lime.Node} 164 */ 165 lime.Renderer.CANVAS.update = function() { 166 }; 167 168 169 /** 170 * Draw single object to the canvas context 171 * @param {Object} context Canvas2DContext where to draw. 172 * @this {lime.Node} 173 */ 174 lime.Renderer.CANVAS.drawCanvasObject = function(context) { 175 176 if(!this.inTree_) return; 177 178 if (this.mask_ != this.activeMask_) { 179 if (this.activeMask_) { 180 lime.Renderer.DOM.removeMask.call(this); 181 } 182 183 if (this.mask_) { 184 lime.Renderer.DOM.addMask.call(this); 185 } 186 } 187 188 // if element is mask the only update mask prop and return 189 if (this.maskTarget_) { 190 return; 191 } 192 193 if (this.hidden_ || this.opacity_ == 0 || this.isMask == 1) { 194 return; 195 } 196 197 if (this.opacity_ != 1) { 198 context.globalAlpha *= this.opacity_; 199 } 200 201 if (this.mask_) { 202 lime.Renderer.DOM.calculateMaskPosition.call(this.mask_); 203 var m = this.activeMask_, scale = this.scale_; 204 context.save(); 205 context.save(); 206 context.translate(m.mPos.x, m.mPos.y); 207 context.rotate(-m.mRot); 208 if (this.needsDomElement) { 209 context.rotate(this.getRotation() * Math.PI / 180); 210 } 211 context.beginPath(); 212 context.moveTo(0, 0); 213 context.lineTo(m.mWidth/scale.x, 0); 214 context.lineTo(m.mWidth/scale.x, m.mHeight/scale.y); 215 context.lineTo(0, m.mHeight/scale.y); 216 context.closePath(); 217 context.restore(); 218 context.clip(); 219 } 220 221 222 var zero = new goog.math.Coordinate(0, 0); 223 224 this.renderer.draw.call(this, context); 225 226 for (var i = 0, child; child = this.children_[i]; i++) { 227 var pos = child.localToParent(zero).clone(), rot = child.getRotation(), scale = child.getScale(); 228 context.save(); 229 context.translate(pos.x, pos.y); 230 context.scale(scale.x,scale.y); 231 232 if (rot != 0) { 233 context.rotate(-rot * Math.PI / 180); 234 } 235 this.renderer.drawCanvasObject.call(child, context); 236 context.restore(); 237 238 } 239 240 if (this.opacity_ != 1) { 241 context.globalAlpha /= this.opacity_; 242 } 243 if (this.activeMask_) { 244 context.restore(); 245 } 246 247 }; 248 249