1 goog.provide('lime.fill.Frame'); 2 3 goog.require('lime.fill.Fill'); 4 goog.require('lime.fill.Image'); 5 goog.require('goog.math.Rect'); 6 goog.require('goog.style'); 7 goog.require('goog.cssom'); 8 goog.require('goog.dom.classes'); 9 goog.require('goog.dom'); 10 11 /** 12 * Image fill. 13 * @param {string|Image|lime.Sprite} img Image. 14 * @param {goog.math.Rect} rect Crop frame. 15 * @constructor 16 * @extends lime.fill.Image 17 */ 18 lime.fill.Frame = function(img,rect,opt_offset,opt_size,opt_rotated) { 19 lime.fill.Image.call(this,img); 20 21 if(goog.isNumber(rect)){ 22 rect = new goog.math.Rect(arguments[1],arguments[2],arguments[3],arguments[4]); 23 opt_offset = false; 24 opt_size = false; 25 opt_rotated = false; 26 } 27 28 this.rect_ = rect; 29 this.coffset_ = opt_offset || new goog.math.Vec2(0,0); 30 this.csize_ = opt_size || new goog.math.Size(this.rect_.width,this.rect_.height); 31 this.rotated_ = opt_rotated || false; 32 33 var r = this.rect_,key = [this.url_,r.width,r.height,r.left,r.top,this.coffset_.x,this.coffset_.y].join('_'); 34 if(goog.isDef(this.dataCache_[key])){ 35 this.data_ = this.dataCache_[key]; 36 if(!this.data_.processed){ 37 goog.events.listen(this.data_.initializer,'processed',function(){ 38 this.dispatchEvent(new goog.events.Event('processed')); 39 },false,this); 40 } 41 } 42 else { 43 this.data_ = {}; 44 this.data_.processed = false; 45 this.data_.initializer = this; 46 this.data_.classname = this.getNextCssClass_(); 47 this.dataCache_[key] = this.data_; 48 49 if(this.USE_CSS_CANVAS){ 50 this.ctx = document.getCSSCanvasContext('2d', this.data_.classname, this.csize_.width, this.csize_.height); 51 } 52 else { 53 //todo: FF4 has support for element backgrounds. probably faster than this png url. 54 this.ctx = this.makeCanvas(); 55 } 56 57 if(this.isLoaded()){ 58 this.makeFrameData_(); 59 } 60 else { 61 goog.events.listen(this,goog.events.EventType.LOAD,this.makeFrameData_,false,this); 62 } 63 } 64 }; 65 goog.inherits(lime.fill.Frame,lime.fill.Image); 66 67 /** 68 * Common name for Frame objects 69 * @type {string} 70 */ 71 lime.fill.Frame.prototype.id = 'frame'; 72 73 /** 74 * @private 75 */ 76 lime.fill.Frame.prototype.dataCache_ = {}; 77 78 /** 79 * @type {boolean} 80 */ 81 lime.fill.Frame.prototype.USE_CSS_CANVAS = goog.isFunction(document.getCSSCanvasContext); 82 83 /** 84 * @inheritDoc 85 */ 86 lime.fill.Frame.prototype.initForSprite = function(sprite){ 87 88 var size = sprite.getSize(); 89 if(size.width==0 && size.height==0){ 90 sprite.setSize(this.csize_.width,this.csize_.height); 91 } 92 93 lime.fill.Image.prototype.initForSprite.call(this,sprite); 94 95 if(!this.isProcessed()){ 96 goog.events.listen(this,'processed',function(){ 97 sprite.setDirty(lime.Dirty.CONTENT); 98 },false,this); 99 } 100 101 //switch to canvas if no support 102 }; 103 104 lime.fill.Frame.prototype.isProcessed = function(){ 105 return this.data_ && this.data_.processed; 106 }; 107 108 (function(){ 109 110 var pfx='cvsbg_'+Math.round(Math.random()*1000)+'_',index=0,styleSheet; 111 112 /** 113 * @private 114 */ 115 lime.fill.Frame.prototype.getNextCssClass_ = function(){ 116 index++; 117 return pfx+index; 118 } 119 120 /** 121 * @private 122 */ 123 lime.fill.Frame.prototype.makeFrameData_ = function(){ 124 this.writeToCanvas(this.ctx); 125 126 if(!this.USE_CSS_CANVAS){ 127 128 var contents = this.cvs.toDataURL("image/png"), 129 rule = '.'+this.data_.classname+'{background-image:url('+contents+') !important}'; 130 if(!styleSheet){ 131 goog.style.installStyles(rule); 132 styleSheet = document.styleSheets[document.styleSheets.length-1]; 133 } 134 else { 135 // why doesn't addCssRule work in IE9??? 136 if(goog.userAgent.IE) styleSheet.cssText+=rule; 137 else goog.cssom.addCssRule(styleSheet,rule); 138 } 139 140 // laoding into image to avoid flickery onf firefox firat load 141 this.data_.img = goog.dom.createDom('img'); 142 this.data_.img.src = contents; 143 144 } 145 146 this.data_.processed = true; 147 this.dispatchEvent(new goog.events.Event('processed')); 148 149 }; 150 151 })(); 152 153 /** 154 * @inheritDoc 155 */ 156 lime.fill.Frame.prototype.getImageElement = function(){ 157 if(!this.frameImgCache_){ 158 if(this.data_.initializer && this.data_.initializer.frameImgCache_){ 159 this.frameImgCache_ = this.data_.initializer.frameImgCache_; 160 } 161 else { 162 if(!this.cvs){ 163 var ctx = this.makeCanvas(); 164 this.writeToCanvas(ctx); 165 } 166 this.frameImgCache_ = this.cvs; 167 } 168 } 169 return this.frameImgCache_; 170 }; 171 172 lime.fill.Frame.prototype.makeCanvas = function(){ 173 this.cvs = goog.dom.createDom('canvas'); 174 var ctx = this.cvs.getContext('2d'); 175 this.cvs.width = this.csize_.width; 176 this.cvs.height = this.csize_.height; 177 return ctx; 178 }; 179 180 lime.fill.Frame.prototype.writeToCanvas = function(ctx){ 181 var r = this.rect_, w = r.width, h = r.height, l = r.left, t = r.top,ox,oy; 182 if(l<0){ 183 w+=l; 184 l=0; 185 } 186 if(t<0){ 187 h+=t; 188 t=0; 189 } 190 if(w+l>this.image_.width) w= this.image_.width-l; 191 if(h+t>this.image_.height) h= this.image_.height-t; 192 if(this.rotated_){ 193 ctx.rotate(-Math.PI*.5); 194 ctx.translate(-this.csize_.height,0); 195 ox = this.csize_.height-this.coffset_.y-w; 196 oy = this.coffset_.x; 197 } 198 else { 199 ox = this.coffset_.x; 200 oy = this.coffset_.y; 201 } 202 203 ctx.drawImage(this.image_,l,t,w,h,ox,oy,w,h); 204 }; 205 206 /** @inheritDoc */ 207 lime.fill.Frame.prototype.setDOMStyle = function(domEl,shape) { 208 if(this.USE_CSS_CANVAS){ 209 domEl.style['background'] = '-webkit-canvas('+this.data_.classname+')'; 210 } 211 else if(this.data_.classname!=shape.cvs_background_class_){ 212 goog.dom.classes.add(domEl,this.data_.classname); 213 domEl.style['background'] = ''; 214 if(shape.cvs_background_class_) 215 goog.dom.classes.remove(domEl,shape.cvs_background_class_); 216 shape.cvs_background_class_ = this.data_.classname; 217 } 218 219 this.setDOMBackgroundProp_(domEl,shape); 220 }; 221 222