1 /*
  2     Copyright 2008,2009
  3         Matthias Ehmann,
  4         Michael Gerhaeuser,
  5         Carsten Miller,
  6         Bianca Valentin,
  7         Alfred Wassermann,
  8         Peter Wilfahrt
  9 
 10     This file is part of JSXGraph.
 11 
 12     JSXGraph is free software: you can redistribute it and/or modify
 13     it under the terms of the GNU Lesser General Public License as published by
 14     the Free Software Foundation, either version 3 of the License, or
 15     (at your option) any later version.
 16 
 17     JSXGraph is distributed in the hope that it will be useful,
 18     but WITHOUT ANY WARRANTY; without even the implied warranty of
 19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20     GNU Lesser General Public License for more details.
 21 
 22     You should have received a copy of the GNU Lesser General Public License
 23     along with JSXGraph.  If not, see <http://www.gnu.org/licenses/>.
 24 
 25 */
 26 
 27 /**
 28  * @fileoverview In this file the geometry element Image is defined.
 29  */
 30 
 31 /**
 32  * Construct and handle images
 33  * @class Image:
 34  * It inherits from @see GeometryElement.
 35  * @constructor
 36  */
 37 JXG.Image = function (board, url, coords, size, attributes) {
 38     this.constructor(board, attributes, JXG.OBJECT_TYPE_IMAGE, JXG.OBJECT_CLASS_OTHER);
 39 
 40     this.initialCoords = new JXG.Coords(JXG.COORDS_BY_USER, coords, this.board);  // Still needed?
 41 
 42     if (!JXG.isFunction(coords[0]) && !JXG.isFunction(coords[1])) {
 43         this.isDraggable = true;
 44     }
 45     this.X = JXG.createFunction(coords[0],this.board,'');
 46     this.Y = JXG.createFunction(coords[1],this.board,'');
 47     this.W = JXG.createFunction(size[0],this.board,'');
 48     this.H = JXG.createFunction(size[1],this.board,'');
 49     this.coords = new JXG.Coords(JXG.COORDS_BY_USER, [this.X(),this.Y()], this.board);
 50     this.updateCoords = new Function('','this.coords.setCoordinates(JXG.COORDS_BY_USER,[this.X(),this.Y()]);');
 51     this.updateSize = new Function('','this.coords.setCoordinates(JXG.COORDS_BY_USER,[this.W(),this.H()]);');
 52     this.usrSize = [this.W(), this.H()];
 53     this.size = [this.usrSize[0]*board.unitX,this.usrSize[1]*board.unitY];
 54     this.url = url;
 55 
 56     this.parent = JXG.getRef(attributes.anchor);
 57 
 58     this.id = this.board.setId(this, 'Im');
 59 
 60     this.board.renderer.drawImage(this);
 61     if(!this.visProp.visible) {
 62        this.board.renderer.hide(this);
 63     }
 64 };
 65 
 66 JXG.Image.prototype = new JXG.GeometryElement;
 67 
 68 JXG.extend(JXG.Image.prototype, /** @lends JXG.Image.prototype */ {
 69 
 70     /**
 71      * Checks whether (x,y) is over or near the image;
 72      * @param {int} x Coordinate in x direction, screen coordinates.
 73      * @param {int} y Coordinate in y direction, screen coordinates.
 74      * @return Always returns false
 75      */
 76     hasPoint: function (x,y) {
 77         var dx = x-this.coords.scrCoords[1],
 78             dy = this.coords.scrCoords[2]-y,
 79             r = this.board.options.precision.hasPoint;
 80 
 81         if (dx>=-r && dx/*-this.size[0]*/<=2*r && 
 82             dy>=-r && dy/*-this.size[1]*/<=r) {
 83             return true;
 84         } else {
 85             return false;
 86         }
 87     },
 88 
 89     /**
 90      * Recalculate the coordinates of lower left corner and the width amd the height.
 91      * @private
 92      */
 93     update: function () {
 94         if (this.needsUpdate) {
 95             this.updateCoords();
 96             this.usrSize = [this.W(), this.H()];
 97             this.size = [this.usrSize[0]*this.board.unitX,this.usrSize[1]*this.board.unitY];
 98             this.updateTransform();
 99         }
100         return this;
101     },
102 
103     /**
104      * Send an update request to the renderer.
105      */
106     updateRenderer: function () {
107         if (this.needsUpdate) {
108             this.board.renderer.updateImage(this);
109             this.needsUpdate = false;
110         }
111         return this;
112     },
113 
114     updateTransform: function () {
115         if (this.transformations.length==0) {
116             return;
117         }
118         for (var i=0;i<this.transformations.length;i++) {
119             this.transformations[i].update();
120         }
121     },
122 
123     addTransform: function (transform) {
124         if (JXG.isArray(transform)) {
125             for (var i=0;i<transform.length;i++) {
126                 this.transformations.push(transform[i]);
127             }
128         } else {
129             this.transformations.push(transform);
130         }
131     },
132     
133     /**
134      * Sets x and y coordinate of the image.
135      * @param {number} method The type of coordinates used here. Possible values are {@link JXG.COORDS_BY_USER} and {@link JXG.COORDS_BY_SCREEN}.
136      * @param {number} x x coordinate in screen/user units
137      * @param {number} y y coordinate in screen/user units
138      * @param {number} x optional: previous x coordinate in screen/user units (ignored)
139      * @param {number} y optional: previous y coordinate in screen/user units (ignored)
140      */
141     setPositionDirectly: function (method, x, y, oldx, oldy) {
142         var newCoords, dx, dy;
143             
144         if (method == JXG.COORDS_BY_SCREEN) {
145             newCoords = new JXG.Coords(JXG.COORDS_BY_SCREEN, [x,y], this.board);
146             x = newCoords.usrCoords[1];
147             y = newCoords.usrCoords[2];
148         }
149         //dx = x-this.coords.usrCoords[1];
150         //dy = x-this.coords.usrCoords[2];
151 
152         this.X = JXG.createFunction(x,this.board,'');
153         this.Y = JXG.createFunction(y,this.board,'');
154         //this.coords = new JXG.Coords(JXG.COORDS_BY_USER, [this.X(),this.Y()], this.board);
155         //this.prepareUpdate().update();
156 
157         return this;
158     }
159     
160 });
161 
162 /**
163  * @class Displays an image. 
164  * @pseudo
165  * @description Shows an image. The image can be supplied as an URL or an base64 encoded inline image 
166  * like "data:image/png;base64, /9j/4AAQSkZJRgA..." or a function returning an URL: function(){ return 'xxx.png; }.
167  * @constructor
168  * @name Image
169  * @type JXG.Image
170  * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
171  * @param {String_Array_Array} url, [position of the top left vertice], [width,height] 
172  * @example
173  * var im = board.create('image', ['http://geonext.uni-bayreuth.de/fileadmin/geonext/design/images/logo.gif', [-3,1],[5,5]]);
174  *
175  * </pre><div id="9850cda0-7ea0-4750-981c-68bacf9cca57" style="width: 400px; height: 400px;"></div>
176  * <script type="text/javascript">
177  *   var image_board = JXG.JSXGraph.initBoard('9850cda0-7ea0-4750-981c-68bacf9cca57', {boundingbox: [-4, 4, 4, -4], axis: false, showcopyright: false, shownavigation: false});
178  *   var image_im = image_board.create('image', ['http://jsxgraph.uni-bayreuth.de/distrib/images/uccellino.jpg', [-3,1],[5,5]]);
179  * </script><pre>
180  */
181 JXG.createImage = function(board, parents, attributes) {
182     var url, attr;
183     attr = JXG.copyAttributes(attributes, board.options, 'image');
184     return new JXG.Image(board, parents[0], parents[1], parents[2], attr);
185 };
186 
187 JXG.JSXGraph.registerElement('image', JXG.createImage);
188