1 /**
  2  *Offers support for images in diagrams
  3  *@this {CanvasImage}
  4  *@constructor
  5  *@param {Number} x
  6  *@param {Number} y
  7  *@param {String} src
  8  *@author zack
  9  **/
 10 function CanvasImage(x, y, src){
 11     this.img = null;
 12    
 13     this.noImage = new Image();
 14     this.noImage.src = CanvasImage.NO_IMAGE;
 15 
 16     this.src = src;
 17     this.encoded = "";
 18    
 19     this.width = CanvasImage.DEFAULT_WIDTH;
 20     this.height= CanvasImage.DEFAULT_WIDTH;
 21 
 22     this.fixed = CanvasImage.FIXED_AUTO;
 23     this.vector= [new Point(x,y), new Point(x,y-20), new Point(x+this.width, y+this.height)];
 24 
 25     this.gifTimer = null;
 26    
 27     this.style = new Style();
 28 }
 29 
 30 CanvasImage.DEFAULT_WIDTH = 100;
 31 CanvasImage.NO_IMAGE = "assets/images/selectImage.gif";
 32 CanvasImage.LOADING_IMAGE = "assets/images/loading.gif";
 33 
 34 CanvasImage.FIXED_NONE = 0;
 35 CanvasImage.FIXED_WIDTH = 1;
 36 CanvasImage.FIXED_HEIGHT = 2;
 37 CanvasImage.FIXED_BOTH = 3;
 38 CanvasImage.FIXED_AUTO = 4;
 39 
 40 
 41 /**Creates a {CanvasImage} out of JSON parsed object
 42  *@param {JSONObject} o - the JSON parsed object
 43  *@return {CanvasImage} a newly constructed Point
 44  **/
 45 CanvasImage.load = function(o){
 46     var newCanvasImage = new CanvasImage();
 47     
 48     newCanvasImage.width = o.width;
 49     newCanvasImage.height = o.height;
 50     newCanvasImage.style = Style.load(o.style);
 51     newCanvasImage.src = o.src;
 52     
 53     return newCanvasImage;
 54 }
 55 		
 56 
 57 CanvasImage.prototype = {
 58     getFile:function(){
 59         return ""
 60     },
 61 
 62     setFile:function(figure, file){
 63         this.src = "";
 64         this.noImage.src = CanvasImage.LOADING_IMAGE;
 65         var primNum = 0;
 66         for(var i = 0; i < figure.primitives.length; i++){
 67             if(figure.primitives[i] == this){
 68                 primNum = i;
 69                 break;
 70             }
 71         }
 72         $.ajaxFileUpload({
 73             url:'upload.php?figureID='+figure.id+'&primitive='+primNum,
 74             dataType:'json',
 75             fileElementId: 'fileToUpload',
 76             secureuri: false, 
 77             success: function (data, status){
 78                 var prim = stack.figureGetById(data.figure).primitives[data.primitive];
 79                 prim.img = null;
 80                 prim.src = data.File;
 81                 prim.gifTimer = setTimeout("draw();",333);
 82             },
 83             error: function (data, status, e){
 84                 alert(e);
 85             }
 86         })
 87         return false;
 88     },
 89     
 90     getURL:function(){
 91         return this.src;
 92     },
 93 
 94     setURL:function(figure, url){
 95         this.img = null;
 96         if(url != ""){
 97             this.encoded = "";
 98         }
 99         if(this.src != url){
100             this.image = null;
101             this.src = url;
102         }
103     },
104 
105     getEncoded:function(){
106         return this.encoded;
107     },
108 
109     setEncoded:function(figure, encoded){
110         if(encoded != ""){
111             this.src = "";
112         }
113         if(encoded != this.encoded){
114             this.image = null;
115             this.encoded = encoded;
116         }
117     },
118     
119     drawImage:function(context, img){
120         var fixed;
121         var sWidth;
122         var sHeight;
123         var dWidth;
124         var dHeight;
125         
126         if(img == this.img){//if we are displaying a logo, use the selected scaling
127             fixed = this.fixed;
128         }
129         else{//otherwise (please select, loading), force fit
130             fixed = CanvasImage.FIXED_BOTH;
131         }
132 
133         //determine auto width
134         if(img.width > img.height && fixed == CanvasImage.FIXED_AUTO){
135             fixed = CanvasImage.FIXED_WIDTH;
136         }
137         else if(fixed == CanvasImage.FIXED_AUTO){
138             fixed = CanvasImage.FIXED_HEIGHT;
139         }
140 
141         //set up properties of source width, height and dest width and height, based on which dimension(s) are fixed
142         if(fixed == CanvasImage.FIXED_NONE){
143             sHeight = Math.min(this.height, img.height);
144             dHeight = sHeight;
145             
146             sWidth = Math.min(this.width, img.width);
147             dWidth = sWidth;
148         }
149         else if(fixed == CanvasImage.FIXED_BOTH){
150             sHeight = img.height;
151             dHeight = this.height;
152             
153             sWidth = img.width;
154             dWidth = this.width;
155         }
156         else if(fixed == CanvasImage.FIXED_WIDTH){
157             var ratio = 100 / img.width * this.width;
158             sWidth = img.width;
159             dWidth = this.width;
160 
161             sHeight = img.height;
162             if(this.height >= sHeight / 100 * ratio){
163                 dHeight = sHeight / 100 * ratio;//sWidth / 100 * ratio;
164             }
165             else{
166                 dHeight = this.height;
167                 sHeight = this.height * 100 / ratio;
168             }
169         }
170         else if(fixed == CanvasImage.FIXED_HEIGHT){
171             var ratio = 100 / img.height * this.height;
172             sHeight = img.height;
173             dHeight = this.height;
174             
175             sWidth = img.width;
176             if(this.width >= sWidth / 100 * ratio){
177                 dWidth = sWidth / 100 * ratio;//sWidth / 100 * ratio;
178             }
179             else{
180                 dWidth = this.width;
181                 sWidth = this.width * 100 / ratio;
182             }
183         }context.drawImage(img,
184             0, 0, //sx, sy
185             sWidth,
186             sHeight,
187             this.vector[0].x, this.vector[0].y, //dx,dy
188             dWidth,
189             dHeight
190             );
191         if(img.src.indexOf(".gif") != -1){
192             this.gifTimer = setTimeout("draw();",333);
193         }
194     },
195 
196     paint:function(context){
197         //context.save();
198         if(this.debug){
199             //paint vector
200             context.beginPath();
201             context.moveTo(this.vector[0].x,this.vector[0].y);
202             context.lineTo(this.vector[0].x+this.width,this.vector[0].y+this.height);
203             context.closePath();
204             context.stroke();
205         }
206         var angle = Util.getAngle(this.vector[0],this.vector[1]);
207         
208         context.translate(this.vector[0].x,this.vector[0].y);
209         context.rotate(angle);
210         context.translate(-this.vector[0].x, -this.vector[0].y);
211         if(this.img == null){
212             if(this.src != ""){
213                 this.img = new Image();
214                 /*this.img.onload = function(canvasImage){
215                     return function(event){
216                         if(img.)
217                         canvasImage.drawImage(context, canvasImage.img);
218                     }
219                 }(this);*/
220                 this.img.src = "getImage.php?url="+this.src;
221             }
222             else if(this.encoded != ""){
223                 this.img = new Image();
224                 this.img.src = this.encoded;
225             }
226             this.drawImage(context, this.noImage);
227         }
228         else if(this.img.complete == false){
229             this.noImage.src = CanvasImage.LOADING_IMAGE;
230             this.drawImage(context, this.noImage);
231         }
232         else{
233             this.gifTimer = setTimeout("draw();",1);//its loaded lets make sure it is displayed
234             clearTimeout(this.gifTimer);
235             this.gifTimer = null;
236             this.drawImage(context, this.img);
237         }
238        
239     //context.fill();
240     //context.restore();
241     },
242     
243     transform:function(matrix){
244         this.vector[0].transform(matrix);
245         this.vector[1].transform(matrix);
246         this.vector[2].transform(matrix);
247 
248         //now we need to get it's actual width and height, so lets rotate it back to 0 and set it's width and height
249         var angle = Util.getAngle(this.vector[0], this.vector[1]);
250 
251         this.vector[0].transform(Matrix.rotationMatrix(-angle));
252         this.vector[2].transform(Matrix.rotationMatrix(-angle));
253         
254         this.width = this.vector[2].x - this.vector[0].x;
255         this.height = this.vector[2].y - this.vector[0].y;
256 
257         this.vector[0].transform(Matrix.rotationMatrix(angle));
258         this.vector[2].transform(Matrix.rotationMatrix(angle));
259     },
260 
261     getNormalBounds:function(){
262         var poly = new Polygon();
263         poly.addPoint(new Point(this.vector[0].x, this.vector[0].y));
264         poly.addPoint(new Point(this.vector[0].x+this.width, this.vector[0].y));
265         poly.addPoint(new Point(this.vector[0].x+this.width, this.vector[0].y+this.height));
266         poly.addPoint(new Point(this.vector[0].x, this.vector[0].y+this.height));
267         return poly;
268     },
269 
270     getBounds:function(){
271         var angle = Util.getAngle(this.vector[0],this.vector[1]);
272         var nBounds = this.getNormalBounds();
273         /*if(this.align == Text.ALIGN_LEFT){
274             nBounds.transform(Matrix.translationMatrix(this.getNormalWidth()/2,0));
275         }
276         if(this.align == Text.ALIGN_RIGHT){
277             nBounds.transform(Matrix.translationMatrix(-this.getNormalWidth()/2,0));
278         }*/
279         nBounds.transform(Matrix.translationMatrix(-this.vector[0].x,-this.vector[0].y) );
280         nBounds.transform(Matrix.rotationMatrix(angle));
281         nBounds.transform(Matrix.translationMatrix(this.vector[0].x,this.vector[0].y));
282 
283         return nBounds.getBounds();
284     },
285 
286 
287 
288     contains: function(x,y){
289         var angle = Util.getAngle(this.vector[0],this.vector[1]);
290         var nBounds = this.getNormalBounds();
291         nBounds.transform( Matrix.translationMatrix(-this.vector[0].x,-this.vector[0].y) );
292         nBounds.transform(Matrix.rotationMatrix(angle));
293         nBounds.transform(Matrix.translationMatrix(this.vector[0].x,this.vector[0].y));
294 
295         return nBounds.contains(x,y);
296     },
297 
298 
299     near:function(x, y, radius){
300         var angle = Util.getAngle(this.vector[0],this.vector[1]);
301         var nBounds = this.getNormalBounds();
302         nBounds.transform( Matrix.translationMatrix(-this.vector[0].x,-this.vector[0].y) );
303         nBounds.transform(Matrix.rotationMatrix(angle));
304         nBounds.transform(Matrix.translationMatrix(this.vector[0].x,this.vector[0].y));
305 
306         return nBounds.near(x,y, radius);
307     },
308 
309 
310     equals:function(anotherImage){
311         if(!anotherImage instanceof CanvasImage){
312             return false;
313         }
314 
315         if(
316             this.img.src != anotherImage.img.src
317             || this.x != anotherImage.x
318             || this.y != anotherImage.y
319             || this.width != anotherImage.width
320             || this.height != anotherImage.height){
321             return false;
322         }
323 
324 
325         for(var i=0; i<this.vector.length; i++){
326             if(!this.vector[i].equals(anotherImage.vector[i])){
327                 return false;
328             }
329         }
330 
331         if(!this.style.equals(anotherImage.style)){
332             return false;
333         }
334 
335         //TODO: compare styles too this.style = new Style();
336         return true;
337     },
338 
339 
340     clone: function(){
341         throw 'Image:clone - not implemented';
342     },
343 
344 
345     toString:function(){
346         return 'Image: ' + (this.img == null ? "null" : this.img.src) + ' x:' + this.vector[0].x +  ' y:' + this.vector[0].y;
347     },
348 
349 
350     getPoints:function(){
351         return [];
352     }
353 }