1 goog.provide('lime.fill.Image'); 2 3 goog.require('lime.fill.Fill'); 4 5 /** 6 * Image fill. 7 * @param {string|Image|lime.Sprite} img Image. 8 * @constructor 9 * @extends lime.fill.Fill 10 */ 11 lime.fill.Image = function(img) { 12 lime.fill.Fill.call(this); 13 14 /*if ((img instanceof lime.Sprite)) { 15 sprite.setRenderMode( lime.RenderMode.BACKGROUND_CANVAS ); 16 this.image_ = img; 17 goog.events.listenOnce(this.image_.eventTarget, 'update', 18 this.updateHandler_, false, this); 19 } 20 else */ 21 22 if(img && goog.isFunction(img.data)){ 23 img = img.data(); 24 } 25 26 if (goog.isString(img)) { 27 this.url_ = img; 28 if(this.url_.length>50) 29 this.url_ = this.url_.substr(-50); 30 if(lime.fill.Image.loadedImages_[this.url_]){ 31 this.image_ = lime.fill.Image.loadedImages_[this.url_]; 32 } 33 else { 34 this.image_ = new Image(); 35 this.image_.src = img; 36 } 37 } 38 else { 39 this.url_ = img.src; 40 if(this.url_.length>50) 41 this.url_ = this.url_.substr(-50); 42 if(lime.fill.Image.loadedImages_[this.url_]){ 43 this.image_ = lime.fill.Image.loadedImages_[this.url_]; 44 } 45 else { 46 this.image_ = img; 47 } 48 49 } 50 51 if (!this.isLoaded()){ 52 this.addLoadHandler_(); 53 } 54 55 lime.fill.Image.loadedImages_[this.url_] = this.image_; 56 57 58 }; 59 goog.inherits(lime.fill.Image, lime.fill.Fill); 60 61 /** 62 * Already loaded image cache to reuse all img objects. 63 * @private 64 */ 65 lime.fill.Image.loadedImages_ = {}; 66 67 /** 68 * Common name for Image objects 69 * @type {string} 70 */ 71 lime.fill.Image.prototype.id = 'image'; 72 73 /** 74 * @inheritDoc 75 */ 76 lime.fill.Image.prototype.initForSprite = function(sprite){ 77 var size = sprite.getSize(),that = this; 78 if(!size.width && !size.height){ 79 if(!this.isLoaded()){ 80 81 goog.events.listen(this,goog.events.EventType.LOAD,function(){ 82 var size = this.getSize(); 83 if(!size.width && !size.height){ 84 this.setSize(that.image_.width,that.image_.height); 85 } 86 },false,sprite); 87 88 } 89 else { 90 91 sprite.setSize(this.image_.width,this.image_.height); 92 93 } 94 } 95 96 if(!this.isLoaded()){ 97 goog.events.listen(this,goog.events.EventType.LOAD,function(){ 98 sprite.setDirty(lime.Dirty.CONTENT); 99 },false,this); 100 } 101 }; 102 103 /** 104 * @private 105 */ 106 lime.fill.Image.prototype.addLoadHandler_ = function(){ 107 goog.events.listen(this.image_, goog.events.EventType.LOAD, 108 this.imageLoadedHandler_, false, this); 109 } 110 111 /** 112 * Update sprite dimensions after image has been loaded 113 * @param {Event} e Event. 114 * @private 115 */ 116 lime.fill.Image.prototype.imageLoadedHandler_ = function(e) { 117 this.dispatchEvent(e); 118 }; 119 120 /** 121 * Return core DOM Image element for the fill. 122 * @return {Element} Image element. 123 */ 124 lime.fill.Image.prototype.getImageElement = function(){ 125 return this.image_; 126 }; 127 128 /** 129 * Return true if image object has been loaded from network. 130 * @return {boolean} If image has been loaded. 131 */ 132 lime.fill.Image.prototype.isLoaded = function(){ 133 return this.image_ && this.image_.width && this.image_.height; 134 } 135 136 /** 137 * Set the drawing size for the fill. Size can also be passed in 138 * with two numbers. 139 * @param {(goog.math.Size|number)} size Image fill size. 140 * @param {(boolean|number)=} opt_perc If size is relative factor from original. 141 * @return {lime.fill.Image} object itself. 142 */ 143 lime.fill.Image.prototype.setSize = function(size,opt_perc){ 144 if(goog.isNumber(size)){ 145 size = new goog.math.Size(arguments[0],arguments[1]); 146 opt_perc = arguments[2] || false; 147 } 148 this.size_ = size; 149 this.size_perc_ = opt_perc; 150 return this; 151 } 152 153 /** 154 * Set the offset that defines the drawing start position. Default is top-left(0,0). 155 * @param {goog.math.Coordinate} offset Image fill offset. 156 * @param {boolean=} opt_perc If offset is relative factor from size. 157 * @return {lime.fill.Image} object itself. 158 */ 159 lime.fill.Image.prototype.setOffset = function(offset,opt_perc){ 160 if(goog.isNumber(offset)){ 161 offset = new goog.math.Coordinate(arguments[0],arguments[1]); 162 opt_perc = arguments[2] || false; 163 } 164 this.offset_ = offset; 165 this.offset_perc_ = opt_perc; 166 return this; 167 } 168 169 lime.fill.Image.prototype.getPixelSizeAndOffset = function(shape){ 170 var size = shape.getSize().clone(); 171 if(this.size_){ 172 if(this.size_perc_){ 173 size.width*=this.size_.width; 174 size.height*=this.size_.height; 175 } 176 else { 177 size = this.size_; 178 } 179 } 180 var offset = new goog.math.Coordinate(0,0); 181 if(this.offset_){ 182 if(this.offset_perc_){ 183 offset.x=size.width*this.offset_.x; 184 offset.y=size.height*this.offset_.y; 185 } 186 else { 187 offset = this.offset_; 188 } 189 } 190 return [size,offset]; 191 } 192 193 194 /** 195 * Common functionality so it could be reused on Frame 196 * @protected 197 */ 198 lime.fill.Image.prototype.setDOMBackgroundProp_ = function(domEl,shape){ 199 var so = this.getPixelSizeAndOffset(shape),size=so[0],offset=so[1],q = shape.getRelativeQuality(); 200 domEl.style[lime.style.getCSSproperty('BackgroundSize')] = size.width*q+'px '+size.height*q+'px'; 201 var stroke = shape.stroke_?shape.stroke_.width_:0; 202 domEl.style['backgroundPosition'] = (offset.x*q-stroke)+'px '+(offset.y*q-stroke)+'px'; 203 //domEl.style['backgroundRepeat'] = 'no-repeat'; 204 if (this.qualityRenderer) 205 domEl.style['imageRendering'] = 'optimizeQuality'; 206 } 207 208 /** @inheritDoc */ 209 lime.fill.Image.prototype.setDOMStyle = function(domEl,shape) { 210 domEl.style['background'] = 'url(' + this.image_.src + ')'; 211 this.setDOMBackgroundProp_(domEl,shape); 212 }; 213 214 lime.fill.Image.prototype.setCanvasStyle = function(context,shape) { 215 var size = shape.getSize(),frame = shape.getFrame(); 216 if (!size.width || !size.height) return; 217 try { 218 var img = this.getImageElement(); 219 var so = this.getPixelSizeAndOffset(shape),s=so[0],offset=so[1]; 220 /* todo: No idea if drawimage() with loops is faster or if the 221 pattern object needs to be cached. Needs to be tested! */ 222 var ptrn = context.createPattern(img,'repeat'); 223 var aspx = s.width/img.width, aspy =s.height/img.height; 224 context.save(); 225 context.translate(frame.left+offset.x,frame.top+offset.y); 226 context.scale(aspx,aspy); 227 context.fillStyle = ptrn; 228 context.fillRect(-offset.x/aspx,-offset.y/aspy,size.width/aspx, size.height/aspy); 229 context.restore(); 230 }catch(e){} 231 }; 232