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