Procházet zdrojové kódy

Feature #2044 upgrade to 2.6 alpha (support internal and external libraries, shapes, grid, contextual menu, ...) and hack to get object libraries into a frame

Juan Carlos Raña před 14 roky
rodič
revize
452eba47c1
46 změnil soubory, kde provedl 3251 přidání a 568 odebrání
  1. 395 76
      main/inc/lib/svg-edit/canvg/canvg.js
  2. 198 0
      main/inc/lib/svg-edit/contextmenu/jquery.contextMenu.js
  3. 22 0
      main/inc/lib/svg-edit/contextmenu/jquery.contextMenu.min.js
  4. 56 0
      main/inc/lib/svg-edit/embedapi.html_disabled
  5. 25 16
      main/inc/lib/svg-edit/extensions/ext-connector.js
  6. 150 0
      main/inc/lib/svg-edit/extensions/ext-grid.js
  7. 427 0
      main/inc/lib/svg-edit/extensions/ext-imagelib.js
  8. 14 0
      main/inc/lib/svg-edit/extensions/ext-imagelib.xml
  9. 32 29
      main/inc/lib/svg-edit/extensions/ext-server_opensave.js
  10. 387 0
      main/inc/lib/svg-edit/extensions/ext-shapes.js
  11. 10 0
      main/inc/lib/svg-edit/extensions/ext-shapes.xml
  12. 2 2
      main/inc/lib/svg-edit/extensions/fileopen.php
  13. 4 5
      main/inc/lib/svg-edit/extensions/filesave.php
  14. 30 0
      main/inc/lib/svg-edit/extensions/grid-icon.xml
  15. 64 0
      main/inc/lib/svg-edit/extensions/imagelib/index.html
  16. 12 0
      main/inc/lib/svg-edit/extensions/imagelib/smiley.svg
  17. 2 0
      main/inc/lib/svg-edit/extensions/shapelib/animal.json
  18. 15 0
      main/inc/lib/svg-edit/extensions/shapelib/arrow.json
  19. 9 0
      main/inc/lib/svg-edit/extensions/shapelib/dialog_balloon.json
  20. 20 0
      main/inc/lib/svg-edit/extensions/shapelib/electronics.json
  21. 25 0
      main/inc/lib/svg-edit/extensions/shapelib/flowchart.json
  22. 13 0
      main/inc/lib/svg-edit/extensions/shapelib/game.json
  23. 0 0
      main/inc/lib/svg-edit/extensions/shapelib/index.html
  24. 9 0
      main/inc/lib/svg-edit/extensions/shapelib/math.json
  25. 4 0
      main/inc/lib/svg-edit/extensions/shapelib/misc.json
  26. 10 0
      main/inc/lib/svg-edit/extensions/shapelib/music.json
  27. 1 0
      main/inc/lib/svg-edit/extensions/shapelib/object.json
  28. 12 0
      main/inc/lib/svg-edit/extensions/shapelib/raphael.txt
  29. 8 0
      main/inc/lib/svg-edit/extensions/shapelib/raphael_1.json
  30. 4 0
      main/inc/lib/svg-edit/extensions/shapelib/raphael_2.json
  31. 2 0
      main/inc/lib/svg-edit/extensions/shapelib/symbol.json
  32. 31 2
      main/inc/lib/svg-edit/images/svg_edit_icons.svg
  33. 0 0
      main/inc/lib/svg-edit/jgraduate/jquery.jgraduate.min.js
  34. 1 1
      main/inc/lib/svg-edit/js-hotkeys/jquery.hotkeys.min.js
  35. 1 0
      main/inc/lib/svg-edit/locale/locale.js
  36. 0 1
      main/inc/lib/svg-edit/locale/locale.min.js
  37. 5 3
      main/inc/lib/svg-edit/spinbtn/JQuerySpinBtn.js
  38. 0 0
      main/inc/lib/svg-edit/spinbtn/JQuerySpinBtn.min.js
  39. 212 26
      main/inc/lib/svg-edit/svg-editor.css
  40. 413 123
      main/inc/lib/svg-edit/svg-editor.js
  41. 0 0
      main/inc/lib/svg-edit/svg-editor.min.js
  42. 137 43
      main/inc/lib/svg-edit/svg-editor.php
  43. 398 152
      main/inc/lib/svg-edit/svgcanvas.js
  44. 0 0
      main/inc/lib/svg-edit/svgcanvas.min.js
  45. 91 89
      main/inc/lib/svg-edit/svgicons/jquery.svgicons.js
  46. 0 0
      main/inc/lib/svg-edit/svgicons/jquery.svgicons.min.js

+ 395 - 76
main/inc/lib/svg-edit/canvg/canvg.js

@@ -11,11 +11,29 @@ if(!window.console) {
 	window.console.log = function(str) {};
 	window.console.dir = function(str) {};
 }
+
+// <3 IE
+if(!Array.indexOf){
+	Array.prototype.indexOf = function(obj){
+		for(var i=0; i<this.length; i++){
+			if(this[i]==obj){
+				return i;
+			}
+		}
+		return -1;
+	}
+}
+
 (function(){
 	// canvg(target, s)
 	// target: canvas element or the id of a canvas element
 	// s: svg string or url to svg file
-	this.canvg = function (target, s) {
+	// opts: optional hash of options
+	//		 ignoreMouse: true => ignore mouse events
+	//		 ignoreAnimation: true => ignore animations
+	//		 renderCallback: function => will call the function after the first render is completed
+	//		 forceRedraw: function => will call the function on every frame, if it returns true, will redraw
+	this.canvg = function (target, s, opts) {
 		if (typeof target == 'string') {
 			target = document.getElementById(target);
 		}
@@ -30,6 +48,7 @@ if(!window.console) {
 			svg = target.svg;
 			svg.stop();
 		}
+		svg.opts = opts;
 		
 		var ctx = target.getContext('2d');
 		if (s.substr(0,1) == '<') {
@@ -43,7 +62,7 @@ if(!window.console) {
 	}
 
 	function build() {
-		var svg = {};
+		var svg = { };
 		
 		svg.FRAMERATE = 30;
 		
@@ -52,6 +71,7 @@ if(!window.console) {
 			svg.Definitions = {};
 			svg.Styles = {};
 			svg.Animations = [];
+			svg.Images = [];
 			svg.ctx = ctx;
 			svg.ViewPort = new (function () {
 				this.viewPorts = [];
@@ -69,6 +89,14 @@ if(!window.console) {
 			});
 		}
 		svg.init();
+		
+		// images loaded
+		svg.ImagesLoaded = function() { 
+			for (var i=0; i<svg.Images.length; i++) {
+				if (!svg.Images[i].loaded) return false;
+			}
+			return true;
+		}
 
 		// trim
 		svg.trim = function(s) { return s.replace(/^\s+|\s+$/g, ''); }
@@ -290,6 +318,13 @@ if(!window.console) {
 			this.angleTo = function(p) {
 				return Math.atan2(p.y - this.y, p.x - this.x);
 			}
+			
+			this.applyTransform = function(v) {
+				var xp = this.x * v[0] + this.y * v[2] + v[4];
+				var yp = this.x * v[1] + this.y * v[3] + v[5];
+				this.x = xp;
+				this.y = yp;
+			}
 		}
 		svg.CreatePoint = function(s) {
 			var a = svg.ToNumberArray(s);
@@ -389,6 +424,10 @@ if(!window.console) {
 				}
 			}
 			
+			this.isPointInBox = function(x, y) {
+				return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2);
+			}
+			
 			this.addPoint(x1, y1);
 			this.addPoint(x2, y2);
 		}
@@ -404,6 +443,9 @@ if(!window.console) {
 				this.apply = function(ctx) {
 					ctx.translate(this.p.x || 0.0, this.p.y || 0.0);
 				}
+				this.applyToPoint = function(p) {
+					p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
+				}
 			}
 			
 			// rotate
@@ -417,6 +459,12 @@ if(!window.console) {
 					ctx.rotate(this.angle.Angle.toRadians());
 					ctx.translate(-this.cx, -this.cy);
 				}
+				this.applyToPoint = function(p) {
+					var a = this.angle.Angle.toRadians();
+					p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
+					p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);
+					p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]);
+				}			
 			}
 			
 			this.Type.scale = function(s) {
@@ -424,6 +472,9 @@ if(!window.console) {
 				this.apply = function(ctx) {
 					ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);
 				}
+				this.applyToPoint = function(p) {
+					p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]);
+				}				
 			}
 			
 			this.Type.matrix = function(s) {
@@ -431,6 +482,9 @@ if(!window.console) {
 				this.apply = function(ctx) {
 					ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
 				}
+				this.applyToPoint = function(p) {
+					p.applyTransform(this.m);
+				}					
 			}
 			
 			this.Type.SkewBase = function(s) {
@@ -455,12 +509,19 @@ if(!window.console) {
 			this.Type.skewY.prototype = new this.Type.SkewBase;
 		
 			this.transforms = [];
+			
 			this.apply = function(ctx) {
 				for (var i=0; i<this.transforms.length; i++) {
 					this.transforms[i].apply(ctx);
 				}
 			}
 			
+			this.applyToPoint = function(p) {
+				for (var i=0; i<this.transforms.length; i++) {
+					this.transforms[i].applyToPoint(p);
+				}
+			}
+			
 			var data = v.split(/\s(?=[a-z])/);
 			for (var i=0; i<data.length; i++) {
 				var type = data[i].split('(')[0];
@@ -470,6 +531,43 @@ if(!window.console) {
 			}
 		}
 		
+		// aspect ratio
+		svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
+			// aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
+			aspectRatio = svg.compressSpaces(aspectRatio);
+			aspectRatio = aspectRatio.replace(/^defer\s/,''); // ignore defer
+			var align = aspectRatio.split(' ')[0] || 'xMidYMid';
+			var meetOrSlice = aspectRatio.split(' ')[1] || 'meet';					
+	
+			// calculate scale
+			var scaleX = width / desiredWidth;
+			var scaleY = height / desiredHeight;
+			var scaleMin = Math.min(scaleX, scaleY);
+			var scaleMax = Math.max(scaleX, scaleY);
+			if (meetOrSlice == 'meet') { desiredWidth *= scaleMin; desiredHeight *= scaleMin; }
+			if (meetOrSlice == 'slice') { desiredWidth *= scaleMax; desiredHeight *= scaleMax; }	
+			
+			refX = new svg.Property('refX', refX);
+			refY = new svg.Property('refY', refY);
+			if (refX.hasValue() && refY.hasValue()) {				
+				ctx.translate(-scaleMin * refX.Length.toPixels('x'), -scaleMin * refY.Length.toPixels('y'));
+			} 
+			else {					
+				// align
+				if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0); 
+				if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height / 2.0 - desiredHeight / 2.0); 
+				if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width - desiredWidth, 0); 
+				if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height - desiredHeight); 
+			}
+			
+			// scale
+			if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin); 
+			if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax); 	
+			
+			// translate
+			ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);			
+		}
+		
 		// elements
 		svg.Element = {}
 		
@@ -505,6 +603,9 @@ if(!window.console) {
 			
 			// base render
 			this.render = function(ctx) {
+				// don't render display=none
+				if (this.attribute('display').value == 'none') return;
+			
 				ctx.save();
 				this.setContext(ctx);
 				this.renderChildren(ctx);
@@ -581,10 +682,14 @@ if(!window.console) {
 							this.styles[name] = new svg.Property(name, value);
 						}
 					}
+				}	
+
+				// add id
+				if (this.attribute('id').hasValue()) {
+					if (svg.Definitions[this.attribute('id').value] == null) {
+						svg.Definitions[this.attribute('id').value] = this;
+					}
 				}
-				
-				// set id
-				if (this.attribute('id').hasValue()) svg.Definitions[this.attribute('id').value] = this;				
 			}
 		}
 		
@@ -660,6 +765,7 @@ if(!window.console) {
 			
 			this.renderChildren = function(ctx) {
 				this.path(ctx);
+				svg.Mouse.checkPath(this, ctx);
 				if (ctx.fillStyle != '') ctx.fill();
 				if (ctx.strokeStyle != '') ctx.stroke();
 				
@@ -743,36 +849,17 @@ if(!window.console) {
 					width = viewBox[2];
 					height = viewBox[3];
 					
-					// aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
-					var preserveAspectRatio = svg.compressSpaces(this.attribute('preserveAspectRatio').value);
-					preserveAspectRatio = preserveAspectRatio.replace(/^defer\s/,''); // ignore defer
-					var align = preserveAspectRatio.split(' ')[0] || 'xMidYMid';
-					var meetOrSlice = preserveAspectRatio.split(' ')[1] || 'meet';					
-					
-					// calculate scale
-					var scaleX = svg.ViewPort.width() / width;
-					var scaleY = svg.ViewPort.height() / height;
-					var scaleMin = Math.min(scaleX, scaleY);
-					var scaleMax = Math.max(scaleX, scaleY);
-					if (meetOrSlice == 'meet') { width *= scaleMin; height *= scaleMin; }
-					if (meetOrSlice == 'slice') { width *= scaleMax; height *= scaleMax; }	
-					
-					if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) {
-						ctx.translate(-scaleMin * this.attribute('refX').Length.toPixels('x'), -scaleMin * this.attribute('refY').Length.toPixels('y'));
-					} 
-					else {					
-						// align
-						if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(svg.ViewPort.width() / 2.0 - width / 2.0, 0); 
-						if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, svg.ViewPort.height() / 2.0 - height / 2.0); 
-						if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(svg.ViewPort.width() - width, 0); 
-						if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, svg.ViewPort.height() - height); 
-					}
-					
-					// scale
-					if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin); 
-					if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax); 	
-					ctx.translate(-minX, -minY);	
-					
+					svg.AspectRatio(ctx,
+									this.attribute('preserveAspectRatio').value, 
+									svg.ViewPort.width(), 
+									width,
+									svg.ViewPort.height(),
+									height,
+									minX,
+									minY,
+									this.attribute('refX').value,
+									this.attribute('refY').value);
+										
 					svg.ViewPort.RemoveCurrent();	
 					svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);						
 				}				
@@ -920,6 +1007,7 @@ if(!window.console) {
 			
 			this.getMarkers = function() {
 				var markers = [];
+
 				for (var i=0; i<this.points.length - 1; i++) {
 					markers.push([this.points[i], this.points[i].angleTo(this.points[i+1])]);
 				}
@@ -969,6 +1057,7 @@ if(!window.console) {
 				this.reset = function() {
 					this.i = -1;
 					this.command = '';
+					this.previousCommand = '';
 					this.control = new svg.Point(0, 0);
 					this.current = new svg.Point(0, 0);
 					this.points = [];
@@ -987,7 +1076,7 @@ if(!window.console) {
 				this.isRelativeCommand = function() {
 					return this.command == this.command.toLowerCase();
 				}
-				
+							
 				this.getToken = function() {
 					this.i = this.i + 1;
 					return this.tokens[this.i];
@@ -998,6 +1087,7 @@ if(!window.console) {
 				}
 				
 				this.nextCommand = function() {
+					this.previousCommand = this.command;
 					this.command = this.getToken();
 				}				
 				
@@ -1019,8 +1109,13 @@ if(!window.console) {
 				}
 				
 				this.getReflectedControlPoint = function() {
+					if (this.previousCommand.toLowerCase() != 'c' && this.previousCommand.toLowerCase() != 's') {
+						return this.current;
+					}
+					
+					// reflect point
 					var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);					
-					return this.makeAbsolute(p);
+					return p;
 				}
 				
 				this.makeAbsolute = function(p) {
@@ -1146,7 +1241,6 @@ if(!window.console) {
 							if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
 						}					
 					}
-
 					else if (pp.command.toUpperCase() == 'A') {
 						while (!pp.isCommandOrEnd()) {
 						    var curr = pp.current;
@@ -1304,7 +1398,7 @@ if(!window.console) {
 		// definitions element
 		svg.Element.defs = function(node) {
 			this.base = svg.Element.ElementBase;
-			this.base(node);			
+			this.base(node);	
 			
 			this.render = function(ctx) {
 				// NOOP
@@ -1324,15 +1418,20 @@ if(!window.console) {
 				var child = this.children[i];
 				this.stops.push(child);
 			}	
-
+			
 			this.getGradient = function() {
 				// OVERRIDE ME!
 			}			
 
 			this.createGradient = function(ctx, element) {
+				var stopsContainer = this;
+				if (this.attribute('xlink:href').hasValue()) {
+					stopsContainer = this.attribute('xlink:href').Definition.getDefinition();
+				}
+			
 				var g = this.getGradient(ctx, element);
-				for (var i=0; i<this.stops.length; i++) {
-					g.addColorStop(this.stops[i].offset, this.stops[i].color);
+				for (var i=0; i<stopsContainer.stops.length; i++) {
+					g.addColorStop(stopsContainer.stops[i].offset, stopsContainer.stops[i].color);
 				}
 				return g;				
 			}
@@ -1360,7 +1459,15 @@ if(!window.console) {
 					? bb.y() + bb.height() * this.attribute('y2').numValue()
 					: this.attribute('y2').Length.toPixels('y'));
 				
-				return ctx.createLinearGradient(x1, y1, x2, y2);
+				var p1 = new svg.Point(x1, y1);
+				var p2 = new svg.Point(x2, y2);
+				if (this.attribute('gradientTransform').hasValue()) { 
+					var transform = new svg.Transform(this.attribute('gradientTransform').value);
+					transform.applyToPoint(p1);
+					transform.applyToPoint(p2);
+				}
+				
+				return ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
 			}
 		}
 		svg.Element.linearGradient.prototype = new svg.Element.GradientBase;
@@ -1397,7 +1504,15 @@ if(!window.console) {
 					? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue()
 					: this.attribute('r').Length.toPixels());
 				
-				return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
+				var c = new svg.Point(cx, cy);
+				var f = new svg.Point(fx, fy);
+				if (this.attribute('gradientTransform').hasValue()) { 
+					var transform = new svg.Transform(this.attribute('gradientTransform').value);
+					transform.applyToPoint(c);
+					transform.applyToPoint(f);
+				}				
+				
+				return ctx.createRadialGradient(f.x, f.y, 0, c.x, c.y, r);
 			}
 		}
 		svg.Element.radialGradient.prototype = new svg.Element.GradientBase;
@@ -1555,10 +1670,26 @@ if(!window.console) {
 				var x = this.attribute('x').Length.toPixels('x');
 				var y = this.attribute('y').Length.toPixels('y');
 				for (var i=0; i<this.children.length; i++) {
-					this.children[i].x = x;
-					this.children[i].y = y;
-					this.children[i].render(ctx);
-					x += this.children[i].measureText(ctx);
+					var child = this.children[i];
+				
+					if (child.attribute('x').hasValue()) {
+						child.x = child.attribute('x').Length.toPixels('x');
+					}
+					else {
+						if (child.attribute('dx').hasValue()) x += child.attribute('dx').Length.toPixels('x');
+						child.x = x;
+						x += child.measureText(ctx);
+					}
+					
+					if (child.attribute('y').hasValue()) {
+						child.y = child.attribute('y').Length.toPixels('y');
+					}
+					else {
+						if (child.attribute('dy').hasValue()) y += child.attribute('dy').Length.toPixels('y');
+						child.y = y;
+					}	
+					
+					child.render(ctx);
 				}
 			}
 		}
@@ -1578,7 +1709,9 @@ if(!window.console) {
 			}
 			
 			this.measureText = function(ctx) {
-				return ctx.measureText(svg.compressSpaces(this.getText())).width;
+				var textToMeasure = svg.compressSpaces(this.getText());
+				if (!ctx.measureText) return textToMeasure.length * 10;
+				return ctx.measureText(textToMeasure).width;
 			}
 		}
 		svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase;
@@ -1608,6 +1741,85 @@ if(!window.console) {
 		}
 		svg.Element.tref.prototype = new svg.Element.TextElementBase;		
 		
+		// a element
+		svg.Element.a = function(node) {
+			this.base = svg.Element.TextElementBase;
+			this.base(node);
+			
+			this.hasText = true;
+			for (var i=0; i<node.childNodes.length; i++) {
+				if (node.childNodes[i].nodeType != 3) this.hasText = false;
+			}
+			
+			// this might contain text
+			this.text = this.hasText ? node.childNodes[0].nodeValue : '';
+			this.getText = function() {
+				return this.text;
+			}		
+
+			this.baseRenderChildren = this.renderChildren;
+			this.renderChildren = function(ctx) {
+				if (this.hasText) {
+					// render as text element
+					this.baseRenderChildren(ctx);
+					var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
+					svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.Length.toPixels('y'), this.x + this.measureText(ctx), this.y));					
+				}
+				else {
+					// render as temporary group
+					var g = new svg.Element.g();
+					g.children = this.children;
+					g.parent = this;
+					g.render(ctx);
+				}
+			}
+			
+			this.onclick = function() {
+				window.open(this.attribute('xlink:href').value);
+			}
+			
+			this.onmousemove = function() {
+				svg.ctx.canvas.style.cursor = 'pointer';
+			}
+		}
+		svg.Element.a.prototype = new svg.Element.TextElementBase;		
+		
+		// image element
+		svg.Element.image = function(node) {
+			this.base = svg.Element.RenderedElementBase;
+			this.base(node);
+			
+			svg.Images.push(this);
+			this.img = document.createElement('img');
+			this.loaded = false;
+			var that = this;
+			this.img.onload = function() { that.loaded = true; }
+			this.img.src = this.attribute('xlink:href').value;
+			
+			this.renderChildren = function(ctx) {
+				var x = this.attribute('x').Length.toPixels('x');
+				var y = this.attribute('y').Length.toPixels('y');
+				
+				var width = this.attribute('width').Length.toPixels('x');
+				var height = this.attribute('height').Length.toPixels('y');			
+				if (width == 0 || height == 0) return;
+			
+				ctx.save();
+				ctx.translate(x, y);
+				svg.AspectRatio(ctx,
+								this.attribute('preserveAspectRatio').value,
+								width,
+								this.img.width,
+								height,
+								this.img.height,
+								0,
+								0);	
+				ctx.drawImage(this.img, 0, 0);			
+				ctx.restore();
+			}
+		}
+		svg.Element.image.prototype = new svg.Element.RenderedElementBase;
+		
 		// group element
 		svg.Element.g = function(node) {
 			this.base = svg.Element.RenderedElementBase;
@@ -1621,14 +1833,7 @@ if(!window.console) {
 			this.base(node);
 		}
 		svg.Element.symbol.prototype = new svg.Element.RenderedElementBase;		
-		
-		// a element
-		svg.Element.a = function(node) {
-			this.base = svg.Element.RenderedElementBase;
-			this.base(node);
-		}
-		svg.Element.a.prototype = new svg.Element.RenderedElementBase;
-		
+			
 		// style element
 		svg.Element.style = function(node) { 
 			this.base = svg.Element.ElementBase;
@@ -1658,7 +1863,6 @@ if(!window.console) {
 							svg.Styles[cssClass] = props;
 						}
 					}
-
 				}
 			}
 		}
@@ -1676,8 +1880,17 @@ if(!window.console) {
 				if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').Length.toPixels('y'));
 			}
 			
+			this.getDefinition = function() {
+				return this.attribute('xlink:href').Definition.getDefinition();
+			}
+			
+			this.path = function(ctx) {
+				var element = this.getDefinition();
+				if (element != null) element.path(ctx);
+			}
+			
 			this.renderChildren = function(ctx) {
-				var element = this.attribute('xlink:href').Definition.getDefinition();
+				var element = this.getDefinition();
 				if (element != null) element.render(ctx);
 			}
 		}
@@ -1732,33 +1945,89 @@ if(!window.console) {
 		// load from xml
 		svg.loadXml = function(ctx, xml) {
 			svg.init(ctx);
+			
+			var mapXY = function(p) {
+				var e = ctx.canvas;
+				while (e) {
+					p.x -= e.offsetLeft;
+					p.y -= e.offsetTop;
+					e = e.offsetParent;
+				}
+				if (window.scrollX) p.x += window.scrollX;
+				if (window.scrollY) p.y += window.scrollY;
+				return p;
+			}
+			
+			// bind mouse
+			if (svg.opts == null || svg.opts['ignoreMouse'] != true) {
+				ctx.canvas.onclick = function(e) {
+					var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
+					svg.Mouse.onclick(p.x, p.y);
+				};
+				ctx.canvas.onmousemove = function(e) {
+					var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
+					svg.Mouse.onmousemove(p.x, p.y);
+				};
+			}
 		
 			var dom = svg.parseXml(xml);
 			var e = svg.CreateElement(dom.documentElement);
-			
-			// set canvas size
-			if (e.attribute('width').hasValue()) {
-				ctx.canvas.width = e.attribute('width').Length.toPixels(ctx.canvas.parentNode.clientWidth);
-			}
-			if (e.attribute('height').hasValue()) {
-				ctx.canvas.height = e.attribute('height').Length.toPixels(ctx.canvas.parentNode.clientHeight);
+					
+			// render loop
+			var isFirstRender = true;
+			var draw = function() {
+				// set canvas size
+				if (e.style('width').hasValue()) {
+					ctx.canvas.width = e.style('width').Length.toPixels(ctx.canvas.parentNode.clientWidth);
+				}
+				if (e.style('height').hasValue()) {
+					ctx.canvas.height = e.style('height').Length.toPixels(ctx.canvas.parentNode.clientHeight);
+				}
+				svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight);			
+			
+				// clear and render
+				ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
+				e.render(ctx);
+				if (isFirstRender) {
+					isFirstRender = false;
+					if (svg.opts != null && typeof(svg.opts['renderCallback']) == 'function') svg.opts['renderCallback']();
+				}			
 			}
-			svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight);
 			
-			// render loop
-			ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
-			e.render(ctx);
+			var waitingForImages = true;
+			if (svg.ImagesLoaded()) {
+				waitingForImages = false;
+				draw();
+			}
 			svg.intervalID = setInterval(function() { 
-				// update animations
 				var needUpdate = false;
-				for (var i=0; i<svg.Animations.length; i++) {
-					needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);
+				
+				if (waitingForImages && svg.ImagesLoaded()) {
+					waitingForImages = false;
+					needUpdate = true;
 				}
 			
+				// need update from mouse events?
+				if (svg.opts == null || svg.opts['ignoreMouse'] != true) {
+					needUpdate = needUpdate | svg.Mouse.hasEvents();
+				}
+			
+				// need update from animations?
+				if (svg.opts == null || svg.opts['ignoreAnimation'] != true) {
+					for (var i=0; i<svg.Animations.length; i++) {
+						needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);
+					}
+				}
+				
+				// need update from redraw?
+				if (svg.opts != null && typeof(svg.opts['forceRedraw']) == 'function') {
+					if (svg.opts['forceRedraw']() == true) needUpdate = true;
+				}
+				
 				// render if needed
 				if (needUpdate) {
-					ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
-					e.render(ctx);
+					draw();				
+					svg.Mouse.runEvents(); // run and clear our events
 				}
 			}, 1000 / svg.FRAMERATE);
 		}
@@ -1769,6 +2038,56 @@ if(!window.console) {
 			}
 		}
 		
+		svg.Mouse = new (function() {
+			this.events = [];
+			this.hasEvents = function() { return this.events.length != 0; }
+		
+			this.onclick = function(x, y) {
+				this.events.push({ type: 'onclick', x: x, y: y, 
+					run: function(e) { if (e.onclick) e.onclick(); }
+				});
+			}
+			
+			this.onmousemove = function(x, y) {
+				this.events.push({ type: 'onmousemove', x: x, y: y,
+					run: function(e) { if (e.onmousemove) e.onmousemove(); }
+				});
+			}			
+			
+			this.eventElements = [];
+			
+			this.checkPath = function(element, ctx) {
+				for (var i=0; i<this.events.length; i++) {
+					var e = this.events[i];
+					if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
+				}
+			}
+			
+			this.checkBoundingBox = function(element, bb) {
+				for (var i=0; i<this.events.length; i++) {
+					var e = this.events[i];
+					if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
+				}			
+			}
+			
+			this.runEvents = function() {
+				svg.ctx.canvas.style.cursor = '';
+				
+				for (var i=0; i<this.events.length; i++) {
+					var e = this.events[i];
+					var element = this.eventElements[i];
+					while (element) {
+						e.run(element);
+						element = element.parent;
+					}
+				}		
+			
+				// done running, clear
+				this.events = []; 
+				this.eventElements = [];
+			}
+		});
+		
 		return svg;
 	}
-})();
+})();

+ 198 - 0
main/inc/lib/svg-edit/contextmenu/jquery.contextMenu.js

@@ -0,0 +1,198 @@
+// jQuery Context Menu Plugin
+//
+// Version 1.01
+//
+// Cory S.N. LaViska
+// A Beautiful Site (http://abeautifulsite.net/)
+// Modified by Alexis Deveria
+//
+// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
+//
+// Terms of Use
+//
+// This plugin is dual-licensed under the GNU General Public License
+//   and the MIT License and is copyright A Beautiful Site, LLC.
+//
+if(jQuery)( function() {
+	$.extend($.fn, {
+		
+		contextMenu: function(o, callback) {
+			// Defaults
+			if( o.menu == undefined ) return false;
+			if( o.inSpeed == undefined ) o.inSpeed = 150;
+			if( o.outSpeed == undefined ) o.outSpeed = 75;
+			// 0 needs to be -1 for expected results (no fade)
+			if( o.inSpeed == 0 ) o.inSpeed = -1;
+			if( o.outSpeed == 0 ) o.outSpeed = -1;
+			// Loop each context menu
+			$(this).each( function() {
+				var el = $(this);
+				var offset = $(el).offset();
+				// Add contextMenu class
+				$('#' + o.menu).addClass('contextMenu');
+				// Simulate a true right click
+				$(this).mousedown( function(e) {
+					var evt = e;
+					$(this).mouseup( function(e) {
+						var srcElement = $(this);
+						$(this).unbind('mouseup');
+						if( evt.button == 2 || o.allowLeft) {
+							e.stopPropagation();
+							// Hide context menus that may be showing
+							$(".contextMenu").hide();
+							// Get this context menu
+							var menu = $('#' + o.menu);
+							
+							if( $(el).hasClass('disabled') ) return false;
+							
+							// Detect mouse position
+							var d = {}, x = e.pageX, y = e.pageY;
+							
+							var x_off = $(window).width() - menu.width(), 
+								y_off = $(window).height() - menu.height();
+							
+							if(x > x_off) x = x_off-15;
+							if(y > y_off) y = y_off-15;
+							
+							// Show the menu
+							$(document).unbind('click');
+							$(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);
+							// Hover events
+							$(menu).find('A').mouseover( function() {
+								$(menu).find('LI.hover').removeClass('hover');
+								$(this).parent().addClass('hover');
+							}).mouseout( function() {
+								$(menu).find('LI.hover').removeClass('hover');
+							});
+							
+							// Keyboard
+							$(document).keypress( function(e) {
+								switch( e.keyCode ) {
+									case 38: // up
+										if( $(menu).find('LI.hover').size() == 0 ) {
+											$(menu).find('LI:last').addClass('hover');
+										} else {
+											$(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
+											if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover');
+										}
+									break;
+									case 40: // down
+										if( $(menu).find('LI.hover').size() == 0 ) {
+											$(menu).find('LI:first').addClass('hover');
+										} else {
+											$(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
+											if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover');
+										}
+									break;
+									case 13: // enter
+										$(menu).find('LI.hover A').trigger('click');
+									break;
+									case 27: // esc
+										$(document).trigger('click');
+									break
+								}
+							});
+							
+							// When items are selected
+							$('#' + o.menu).find('A').unbind('mouseup');
+							$('#' + o.menu).find('LI:not(.disabled) A').mouseup( function() {
+								$(document).unbind('click').unbind('keypress');
+								$(".contextMenu").hide();
+								// Callback
+								if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
+								return false;
+							});
+							
+							// Hide bindings
+							setTimeout( function() { // Delay for Mozilla
+								$(document).click( function() {
+									$(document).unbind('click').unbind('keypress');
+									$(menu).fadeOut(o.outSpeed);
+									return false;
+								});
+							}, 0);
+						}
+					});
+				});
+				
+				// Disable text selection
+				if( $.browser.mozilla ) {
+					$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
+				} else if( $.browser.msie ) {
+					$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
+				} else {
+					$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
+				}
+				// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
+				$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });
+				
+			});
+			return $(this);
+		},
+		
+		// Disable context menu items on the fly
+		disableContextMenuItems: function(o) {
+			if( o == undefined ) {
+				// Disable all
+				$(this).find('LI').addClass('disabled');
+				return( $(this) );
+			}
+			$(this).each( function() {
+				if( o != undefined ) {
+					var d = o.split(',');
+					for( var i = 0; i < d.length; i++ ) {
+						$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
+						
+					}
+				}
+			});
+			return( $(this) );
+		},
+		
+		// Enable context menu items on the fly
+		enableContextMenuItems: function(o) {
+			if( o == undefined ) {
+				// Enable all
+				$(this).find('LI.disabled').removeClass('disabled');
+				return( $(this) );
+			}
+			$(this).each( function() {
+				if( o != undefined ) {
+					var d = o.split(',');
+					for( var i = 0; i < d.length; i++ ) {
+						$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
+						
+					}
+				}
+			});
+			return( $(this) );
+		},
+		
+		// Disable context menu(s)
+		disableContextMenu: function() {
+			$(this).each( function() {
+				$(this).addClass('disabled');
+			});
+			return( $(this) );
+		},
+		
+		// Enable context menu(s)
+		enableContextMenu: function() {
+			$(this).each( function() {
+				$(this).removeClass('disabled');
+			});
+			return( $(this) );
+		},
+		
+		// Destroy context menu(s)
+		destroyContextMenu: function() {
+			// Destroy specified context menus
+			$(this).each( function() {
+				// Disable action
+				$(this).unbind('mousedown').unbind('mouseup');
+			});
+			return( $(this) );
+		}
+		
+	});
+})(jQuery);

+ 22 - 0
main/inc/lib/svg-edit/contextmenu/jquery.contextMenu.min.js

@@ -0,0 +1,22 @@
+// jQuery Context Menu Plugin
+//
+// Version 1.01
+//
+// Cory S.N. LaViska
+// A Beautiful Site (http://abeautifulsite.net/)
+//
+// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
+//
+// Terms of Use
+//
+// This plugin is dual-licensed under the GNU General Public License
+//   and the MIT License and is copyright A Beautiful Site, LLC.
+//
+jQuery&&function(){$.extend($.fn,{contextMenu:function(a,e){if(a.menu==undefined)return false;if(a.inSpeed==undefined)a.inSpeed=150;if(a.outSpeed==undefined)a.outSpeed=75;if(a.inSpeed==0)a.inSpeed=-1;if(a.outSpeed==0)a.outSpeed=-1;$(this).each(function(){var d=$(this),i=$(d).offset();$("#"+a.menu).addClass("contextMenu");$(this).mousedown(function(j){j.stopPropagation();$(this).mouseup(function(f){f.stopPropagation();var k=$(this);$(this).unbind("mouseup");if(j.button==2){$(".contextMenu").hide();
+var b=$("#"+a.menu);if($(d).hasClass("disabled"))return false;var c={},g,h;if(self.innerHeight){c.pageYOffset=self.pageYOffset;c.pageXOffset=self.pageXOffset;c.innerHeight=self.innerHeight;c.innerWidth=self.innerWidth}else if(document.documentElement&&document.documentElement.clientHeight){c.pageYOffset=document.documentElement.scrollTop;c.pageXOffset=document.documentElement.scrollLeft;c.innerHeight=document.documentElement.clientHeight;c.innerWidth=document.documentElement.clientWidth}else if(document.body){c.pageYOffset=
+document.body.scrollTop;c.pageXOffset=document.body.scrollLeft;c.innerHeight=document.body.clientHeight;c.innerWidth=document.body.clientWidth}f.pageX?g=f.pageX:g=f.clientX+c.scrollLeft;f.pageY?h=f.pageY:h=f.clientY+c.scrollTop;$(document).unbind("click");$(b).css({top:h,left:g}).fadeIn(a.inSpeed);$(b).find("A").mouseover(function(){$(b).find("LI.hover").removeClass("hover");$(this).parent().addClass("hover")}).mouseout(function(){$(b).find("LI.hover").removeClass("hover")});$(document).keypress(function(l){switch(l.keyCode){case 38:if($(b).find("LI.hover").size()==
+0)$(b).find("LI:last").addClass("hover");else{$(b).find("LI.hover").removeClass("hover").prevAll("LI:not(.disabled)").eq(0).addClass("hover");$(b).find("LI.hover").size()==0&&$(b).find("LI:last").addClass("hover")}break;case 40:if($(b).find("LI.hover").size()==0)$(b).find("LI:first").addClass("hover");else{$(b).find("LI.hover").removeClass("hover").nextAll("LI:not(.disabled)").eq(0).addClass("hover");$(b).find("LI.hover").size()==0&&$(b).find("LI:first").addClass("hover")}break;case 13:$(b).find("LI.hover A").trigger("click");
+break;case 27:$(document).trigger("click");break}});$("#"+a.menu).find("A").unbind("click");$("#"+a.menu).find("LI:not(.disabled) A").click(function(){$(document).unbind("click").unbind("keypress");$(".contextMenu").hide();e&&e($(this).attr("href").substr(1),$(k),{x:g-i.left,y:h-i.top,docX:g,docY:h});return false});setTimeout(function(){$(document).click(function(){$(document).unbind("click").unbind("keypress");$(b).fadeOut(a.outSpeed);return false})},0)}})});if($.browser.mozilla)$("#"+a.menu).each(function(){$(this).css({MozUserSelect:"none"})});
+else $.browser.msie?$("#"+a.menu).each(function(){$(this).bind("selectstart.disableTextSelect",function(){return false})}):$("#"+a.menu).each(function(){$(this).bind("mousedown.disableTextSelect",function(){return false})});$(d).add($("UL.contextMenu")).bind("contextmenu",function(){return false})});return $(this)},disableContextMenuItems:function(a){if(a==undefined){$(this).find("LI").addClass("disabled");return $(this)}$(this).each(function(){if(a!=undefined)for(var e=a.split(","),d=0;d<e.length;d++)$(this).find('A[href="'+
+e[d]+'"]').parent().addClass("disabled")});return $(this)},enableContextMenuItems:function(a){if(a==undefined){$(this).find("LI.disabled").removeClass("disabled");return $(this)}$(this).each(function(){if(a!=undefined)for(var e=a.split(","),d=0;d<e.length;d++)$(this).find('A[href="'+e[d]+'"]').parent().removeClass("disabled")});return $(this)},disableContextMenu:function(){$(this).each(function(){$(this).addClass("disabled")});return $(this)},enableContextMenu:function(){$(this).each(function(){$(this).removeClass("disabled")});
+return $(this)},destroyContextMenu:function(){$(this).each(function(){$(this).unbind("mousedown").unbind("mouseup")});return $(this)}})}(jQuery);

+ 56 - 0
main/inc/lib/svg-edit/embedapi.html_disabled

@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head>
+    <title></title>
+</head>
+<body>
+
+    <script type="text/javascript" src="embedapi.js"></script>
+    <script type="text/javascript">
+        var svgCanvas = null;
+
+        function init_embed() {
+            var frame = document.getElementById('svgedit');
+			svgCanvas = new embedded_svg_edit(frame);
+			
+			// Hide main button, as we will be controlling new/load/save etc from the host document
+			var doc;
+			doc = frame.contentDocument;
+			if (!doc)
+			{
+				doc = frame.contentWindow.document;
+			}
+			
+			var mainButton = doc.getElementById('main_button');
+			mainButton.style.display = 'none';            
+        }
+        
+        function handleSvgData(data, error) {
+			if (error)
+			{
+				alert('error ' + error);
+			}
+            else
+			{
+				alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
+			}			
+        }
+        
+        function loadSvg() {
+            var svgexample = '<svg width="640" height="480" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title><rect stroke-width="5" stroke="#000000" fill="#FF0000" id="svg_1" height="35" width="51" y="35" x="32"/><ellipse ry="15" rx="24" stroke-width="5" stroke="#000000" fill="#0000ff" id="svg_2" cy="60" cx="66"/></g></svg>';
+            svgCanvas.setSvgString(svgexample);
+        }
+		
+		function saveSvg() {			
+			svgCanvas.getSvgString()(handleSvgData);
+		}
+    </script>
+
+
+    <button onclick="loadSvg();">Load example</button>
+    <button onclick="saveSvg();">Save data</button>
+    <br/>
+
+    <iframe src="svg-editor.html" width="900px" height="600px" id="svgedit" onload="init_embed()"></iframe>    
+</body>
+</html>

+ 25 - 16
main/inc/lib/svg-edit/extensions/ext-connector.js

@@ -27,6 +27,8 @@ svgEditor.addExtension("Connector", function(S) {
 // 			connect_str = "-SE_CONNECT-",
 		selElems = [];
 		
+	elData = $.data;
+		
 	var lang_list = {
 		"en":[
 			{"id": "mode_connect", "title": "Connect two objects" }
@@ -94,15 +96,15 @@ svgEditor.addExtension("Connector", function(S) {
 // 						var sw = line.getAttribute('stroke-width') * 5;
 			
 			// Update bbox for this element
-			var bb = $(line).data(pre+'_bb');
+			var bb = elData(line, pre+'_bb');
 			bb.x = conn.start_x + diff_x;
 			bb.y = conn.start_y + diff_y;
-			$(line).data(pre+'_bb', bb);
+			elData(line, pre+'_bb', bb);
 			
 			var alt_pre = conn.is_start?'end':'start';
 			
 			// Get center pt of connected element
-			var bb2 = $(line).data(alt_pre+'_bb');
+			var bb2 = elData(line, alt_pre+'_bb');
 			var src_x = bb2.x + bb2.width/2;
 			var src_y = bb2.y + bb2.height/2;
 			
@@ -111,7 +113,7 @@ svgEditor.addExtension("Connector", function(S) {
 			setPoint(line, conn.is_start?0:'end', pt.x, pt.y, true);
 			
 			// Set point of connected element
-			var pt2 = getBBintersect(pt.x, pt.y, $(line).data(alt_pre + '_bb'), getOffset(alt_pre, line));
+			var pt2 = getBBintersect(pt.x, pt.y, elData(line, alt_pre + '_bb'), getOffset(alt_pre, line));
 			setPoint(line, conn.is_start?'end':0, pt2.x, pt2.y, true);
 
 		}
@@ -124,8 +126,8 @@ svgEditor.addExtension("Connector", function(S) {
 
 		// Loop through connectors to see if one is connected to the element
 		connectors.each(function() {
-			var start = $(this).data("c_start");
-			var end = $(this).data("c_end");
+			var start = elData(this, "c_start");
+			var end = elData(this, "c_end");
 			
 			var parts = [getElem(start), getElem(end)];
 			for(var i=0; i<2; i++) {
@@ -177,13 +179,13 @@ svgEditor.addExtension("Connector", function(S) {
 				var bb = svgCanvas.getStrokedBBox([elem]);
 				bb.x = conn.start_x;
 				bb.y = conn.start_y;
-				$(line).data(pre+'_bb', bb);
-				var add_offset = $(line).data(pre+'_off');
+				elData(line, pre+'_bb', bb);
+				var add_offset = elData(line, pre+'_off');
 			
 				var alt_pre = conn.is_start?'end':'start';
 				
 				// Get center pt of connected element
-				var bb2 = $(line).data(alt_pre+'_bb');
+				var bb2 = elData(line, alt_pre+'_bb');
 				var src_x = bb2.x + bb2.width/2;
 				var src_y = bb2.y + bb2.height/2;
 				
@@ -192,7 +194,7 @@ svgEditor.addExtension("Connector", function(S) {
 				setPoint(line, conn.is_start?0:'end', pt.x, pt.y, true);
 				
 				// Set point of connected element
-				var pt2 = getBBintersect(pt.x, pt.y, $(line).data(alt_pre + '_bb'), getOffset(alt_pre, line));
+				var pt2 = getBBintersect(pt.x, pt.y, elData(line, alt_pre + '_bb'), getOffset(alt_pre, line));
 				setPoint(line, conn.is_start?'end':0, pt2.x, pt2.y, true);
 				
 				// Update points attribute manually for webkit
@@ -256,8 +258,9 @@ svgEditor.addExtension("Connector", function(S) {
 		
 		svgCanvas.moveSelectedElements = function() {
 			svgCanvas.removeFromSelection($(conn_sel).toArray());
-			mse.apply(this, arguments);
+			var cmd = mse.apply(this, arguments);
 			updateConnectors();
+			return cmd;
 		}
 		
 		se_ns = svgCanvas.getEditorNS();
@@ -358,7 +361,7 @@ svgEditor.addExtension("Connector", function(S) {
 							"style": "pointer-events:none"
 						}
 					});
-					$(cur_line).data('start_bb', bb);
+					elData(cur_line, 'start_bb', bb);
 				}
 				return {
 					started: true
@@ -382,7 +385,7 @@ svgEditor.addExtension("Connector", function(S) {
 				
 				var sw = cur_line.getAttribute('stroke-width') * 3;
 				// Set start point (adjusts based on bb)
-				var pt = getBBintersect(x, y, $(cur_line).data('start_bb'), getOffset('start', cur_line));
+				var pt = getBBintersect(x, y, elData(cur_line, 'start_bb'), getOffset('start', cur_line));
 				start_x = pt.x;
 				start_y = pt.y;
 				
@@ -396,7 +399,7 @@ svgEditor.addExtension("Connector", function(S) {
 				while(slen--) {
 					var elem = selElems[slen];
 					// Look for selected connector elements
-					if(elem && $(elem).data('c_start')) {
+					if(elem && elData(elem, 'c_start')) {
 						// Remove the "translate" transform given to move
 						svgCanvas.removeFromSelection([elem]);
 						svgCanvas.getTransformList(elem).clear();
@@ -486,6 +489,12 @@ svgEditor.addExtension("Connector", function(S) {
 			}
 		},
 		selectedChanged: function(opts) {
+			// TODO: Find better way to skip operations if no connectors are in use
+			if(!$(svgcontent).find(conn_sel).length) return;
+			
+			if(svgCanvas.getMode() == 'connector') {
+				svgCanvas.setMode('select');
+			}
 			
 			// Use this to update the current selected elements
 			selElems = opts.elems;
@@ -494,7 +503,7 @@ svgEditor.addExtension("Connector", function(S) {
 			
 			while(i--) {
 				var elem = selElems[i];
-				if(elem && $(elem).data('c_start')) {
+				if(elem && elData(elem, 'c_start')) {
 					selManager.requestSelector(elem).showGrips(false);
 					if(opts.selectedElement && !opts.multiselected) {
 						// TODO: Set up context tools and hide most regular line tools
@@ -560,7 +569,7 @@ svgEditor.addExtension("Connector", function(S) {
 			}
 			// Update line if it's a connector
 			if(elem.getAttribute('class') == conn_sel.substr(1)) {
-				var start = getElem($(elem).data('c_start'));
+				var start = getElem(elData(elem, 'c_start'));
 				updateConnectors([start]);
 			} else {
 				updateConnectors();

+ 150 - 0
main/inc/lib/svg-edit/extensions/ext-grid.js

@@ -0,0 +1,150 @@
+/*
+ * ext-grid.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Redou Mine
+ *
+ */
+
+svgEditor.addExtension("view_grid", function(s) {
+    /* 
+    * Config for grid-lines
+    */
+    var gridConfig = {
+        '1x1': { height: 1, width: 1, color: '#CCC', strokeWidth: 0.05, opacity: 1 },
+        '5x5': { height: 5, width: 5, color: '#BBB', strokeWidth: 0.2, opacity: 1 },
+        '10x10': { height: 10, width: 10, color: '#AAA', strokeWidth: 0.2, opacity: 1 },
+        '100x100': { height: 100, width: 100, color: '#888', strokeWidth: 0.2, opacity: 1 }
+    };
+
+    var svgdoc = document.getElementById("svgcanvas").ownerDocument,
+			svgns = "http://www.w3.org/2000/svg",
+			dims = svgEditor.curConfig.dimensions,
+			svgroot = s.svgroot;
+
+    /*
+    * copied from svgcanvas.js line 1138-1157 (version: 2.5 rc1)
+    */
+    var assignAttributes = function(node, attrs, suspendLength, unitCheck) {
+        if (!suspendLength) suspendLength = 0;
+        // Opera has a problem with suspendRedraw() apparently
+        var handle = null;
+        if (!window.opera) svgroot.suspendRedraw(suspendLength);
+
+        for (var i in attrs) {
+            var ns = (i.substr(0, 4) == "xml:" ? xmlns :
+							i.substr(0, 6) == "xlink:" ? xlinkns : null);
+
+            if (ns || !unitCheck) {
+                node.setAttributeNS(ns, i, attrs[i]);
+            } else {
+                setUnitAttr(node, i, attrs[i]);
+            }
+
+        }
+
+        if (!window.opera) svgroot.unsuspendRedraw(handle);
+    };
+
+
+    // create svg for grid
+    var canvasgrid = svgdoc.createElementNS(svgns, "svg");
+    assignAttributes(canvasgrid, {
+        'id': 'canvasGrid',
+        'width': '100%',
+        'height': '100%',
+        'x': 0,
+        'y': 0,
+        'overflow': 'visible',
+        'viewBox': '0 0 ' + dims[0] + ' ' + dims[1],
+        'display': 'none'
+    });
+    $('#canvasBackground').append(canvasgrid);
+
+    // create each grid
+    $.each(gridConfig, function(key, value) {
+        // grid-pattern
+        var gridPattern = svgdoc.createElementNS(svgns, "pattern");
+        assignAttributes(gridPattern, {
+            'id': 'gridpattern' + key,
+            'patternUnits': 'userSpaceOnUse',
+            'x': -(value.strokeWidth / 2), // position for strokewidth
+            'y': -(value.strokeWidth / 2), // position for strokewidth
+            'width': value.width,
+            'height': value.height
+        });
+        var gridPattern_hoLine = svgdoc.createElementNS(svgns, "line");
+        assignAttributes(gridPattern_hoLine, {
+            'fill': 'none',
+            'stroke-width': value.strokeWidth,
+            'x1': 0,
+            'y1': 0,
+            'x2': value.width,
+            'y2': 0,
+            'stroke': value.color
+        });
+        var gridPattern_veLine = svgdoc.createElementNS(svgns, "line");
+        assignAttributes(gridPattern_veLine, {
+            'fill': 'none',
+            'stroke-width': value.strokeWidth,
+            'x1': 0,
+            'y1': 0,
+            'x2': 0,
+            'y2': value.height,
+            'stroke': value.color
+        });
+
+        gridPattern.appendChild(gridPattern_hoLine);
+        gridPattern.appendChild(gridPattern_veLine);
+        $('#svgroot defs').append(gridPattern);
+
+        // grid-box
+        var gridBox = svgdoc.createElementNS(svgns, "rect");
+        assignAttributes(gridBox, {
+            'width': '100%',
+            'height': '100%',
+            'x': 0,
+            'y': 0,
+            'stroke-width': 0,
+            'stroke': 'none',
+            'fill': 'url(#gridpattern' + key + ')',
+            'opacity': value.opacity,
+            'style': 'pointer-events: none; display:visible;'
+        });
+        $('#canvasGrid').append(gridBox);
+    });
+
+    return {
+        name: "view_grid",
+        svgicons: "extensions/grid-icon.xml",
+
+        zoomChanged: function(zoomlevel) {
+            // update size
+            var viewBox = "0 0 " + svgCanvas.contentW + " " + svgCanvas.contentH;
+            $('#canvasGrid').attr("viewBox", viewBox);
+        },
+
+        buttons: [{
+            id: "view_grid",
+            type: "context",
+            panel: "editor_panel",
+            title: "Show/Hide Grid [G]",
+            events: {
+                'click': function() {
+                    var gr = !$('#view_grid').hasClass('push_button_pressed');
+                    if (gr) {
+                        svgEditor.curConfig.gridSnapping = true;
+                        $('#view_grid').addClass('push_button_pressed').removeClass('tool_button');
+                        $('#canvasGrid').attr('display', 'normal');
+                    }
+                    else {
+                        svgEditor.curConfig.gridSnapping = false;
+                        $('#view_grid').removeClass('push_button_pressed').addClass('tool_button');
+                        $('#canvasGrid').attr('display', 'none');
+                    }
+                }
+            }
+}]
+        };
+    });

+ 427 - 0
main/inc/lib/svg-edit/extensions/ext-imagelib.js

@@ -0,0 +1,427 @@
+/*
+ * ext-imagelib.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+
+svgEditor.addExtension("imagelib", function() {
+
+	var img_libs = [{
+			name: 'Demo library (local)',
+			url: 'extensions/imagelib/index.html',
+			description: 'Demonstration library for SVG-edit on this server'
+		}, 
+		{
+			name: 'IAN Symbol Libraries',
+			url: 'http://ian.umces.edu/symbols/catalog/svgedit/album_chooser.php',
+			description: 'Free library of illustrations'
+		}
+	];
+	
+	var xlinkns = "http://www.w3.org/1999/xlink";
+
+	function closeBrowser() {
+		$('#imgbrowse_holder').hide();
+	}
+	
+	function importImage(url) {
+		
+		var newImage = svgCanvas.addSvgElementFromJson({
+			"element": "image",
+			"attr": {
+				"x": 0,
+				"y": 0,
+				"width": 0,
+				"height": 0,
+				"id": svgCanvas.getNextId(),
+				"style": "pointer-events:inherit"
+			}
+		});
+		svgCanvas.clearSelection();
+		svgCanvas.addToSelection([newImage]);
+		svgCanvas.setImageURL(url);
+	}
+
+	var mode = 's';
+	var multi_arr = [];
+	var cur_meta;
+	var tranfer_stopped = false;
+	var pending = {};
+	//Juan Carlos Raña Trabado hack for Chamilo add window.top. on the bottom line to run into a frame
+	 window.top.window.addEventListener("message", function(evt) {
+						 
+		// Receive postMessage data
+		var response = evt.data;
+		
+		if(!response) {
+			// Do nothing
+			return;
+		}
+		
+		var char1 = response.charAt(0);
+		
+		var svg_str;
+		var img_str;
+		
+		if(char1 != "{" && tranfer_stopped) {
+			tranfer_stopped = false;
+			return;
+		}
+		
+		if(char1 == '|') {
+			var secondpos = response.indexOf('|', 1);
+			var id = response.substr(1, secondpos-1);
+			response = response.substr(secondpos+1);
+			char1 = response.charAt(0);
+
+		}
+		
+		
+		// Hide possible transfer dialog box
+		$('#dialog_box').hide();
+		
+		switch (char1) {
+			case '{':
+				// Metadata
+				tranfer_stopped = false;
+				var cur_meta = JSON.parse(response);
+				
+				pending[cur_meta.id] = cur_meta;
+				
+				var message = 'Retrieving "' + (cur_meta.name || 'file') + '"...';
+				
+				if(mode != 'm') {
+					$.process_cancel(message, function() {
+						tranfer_stopped = true;
+						// Should a message be sent back to the frame?
+						
+						$('#dialog_box').hide();
+					});
+				} else {
+					var entry = $('<div>' + message + '</div>').data('id', cur_meta.id);
+					preview.append(entry);
+					cur_meta.entry = entry;
+				}
+				
+				return;
+			case '<':
+				svg_str = true;
+				break;
+			case 'd':
+				if(response.indexOf('data:image/svg+xml') === 0) {
+					var pre = 'data:image/svg+xml;base64,';
+					var src = response.substring(pre.length);
+					response = svgCanvas.Utils.decode64(src);
+					svg_str = true;
+					break;
+				} else if(response.indexOf('data:image/') === 0) {
+					img_str = true;
+					break;
+				}
+				// Else fall through
+			default:
+				// TODO: See if there's a way to base64 encode the binary data stream
+// 				var str = 'data:;base64,' + svgCanvas.Utils.encode64(response, true);
+			
+				// Assume it's raw image data
+// 				importImage(str);
+			
+				// Don't give warning as postMessage may have been used by something else
+				if(mode !== 'm') {
+					closeBrowser();
+				} else {
+					pending[id].entry.remove();
+				}
+// 				$.alert('Unexpected data was returned: ' + response, function() {
+// 					if(mode !== 'm') {
+// 						closeBrowser();
+// 					} else {
+// 						pending[id].entry.remove();
+// 					}
+// 				});
+				return;
+		}
+		
+		switch (mode) {
+			case 's':
+				// Import one
+
+				if(svg_str) {
+					svgCanvas.importSvgString(response);
+				} else if(img_str) {
+					importImage(response);
+				}
+				closeBrowser();
+				break;
+			case 'm':
+				// Import multiple
+				multi_arr.push([(svg_str ? 'svg' : 'img'), response]);
+				var cur_meta = pending[id];
+				if(svg_str) {
+					if(cur_meta && cur_meta.name) {
+						var title = cur_meta.name;
+					}  else {
+						// Try to find a title
+						var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement;
+						var title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
+					}
+					if(cur_meta) {
+						preview.children().each(function() {
+							if($(this).data('id') == id) {
+								if(cur_meta.preview_url) {
+									$(this).html('<img src="' + cur_meta.preview_url + '">' + title);
+								} else {
+									$(this).text(title);
+								}
+								submit.removeAttr('disabled');
+							}
+						});
+					} else {
+						preview.append('<div>'+title+'</div>');
+						submit.removeAttr('disabled');
+					}
+				} else {
+					if(cur_meta && cur_meta.preview_url) {
+						var title = cur_meta.name || '';
+					}
+					if(cur_meta && cur_meta.preview_url) {
+						var entry = '<img src="' + cur_meta.preview_url + '">' + title;
+					} else {
+						var entry = '<img src="' + response + '">';
+					}
+				
+					if(cur_meta) {
+						preview.children().each(function() {
+							if($(this).data('id') == id) {
+								$(this).html(entry);
+								submit.removeAttr('disabled');
+							}
+						});
+					} else {
+						preview.append($('<div>').append(entry));
+						submit.removeAttr('disabled');
+					}
+
+				}
+				break;
+			case 'o':
+				// Open
+				if(!svg_str) break;
+				svgEditor.openPrep(function(ok) {
+					if(!ok) return;
+					svgCanvas.clear();
+					svgCanvas.setSvgString(response);
+					// updateCanvas();
+				});
+				closeBrowser();
+				break;
+		}
+	}, true);
+	
+	var preview, submit;
+
+	function toggleMulti(show) {
+	
+		$('#lib_framewrap, #imglib_opts').css({right: (show ? 200 : 10)});
+		if(!preview) {
+			preview = $('<div id=imglib_preview>').css({
+				position: 'absolute',
+				top: 45,
+				right: 10,
+				width: 180,
+				bottom: 45,
+				background: '#fff',
+				overflow: 'auto'
+			}).insertAfter('#lib_framewrap');
+			
+			submit = $('<button disabled>Import selected-</button>').appendTo('#imgbrowse').click(function() {
+				$.each(multi_arr, function(i) {
+					var type = this[0];
+					var data = this[1];
+					if(type == 'svg') {						
+						svgCanvas.importSvgString(data);
+					} else {
+						importImage(data);
+					}
+					svgCanvas.moveSelectedElements(i*20, i*20, false);
+				});
+				preview.empty();
+				multi_arr = [];
+				$('#imgbrowse_holder').hide();
+			}).css({
+				position: 'absolute',
+				bottom: 10,
+				right: -10
+			});
+
+		}
+		
+		preview.toggle(show);
+		submit.toggle(show);
+	}
+
+	function showBrowser() {
+		var browser = $('#imgbrowse');
+		if(!browser.length) {
+			$('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>\
+			</div></div>').insertAfter('#svg_docprops');
+			browser = $('#imgbrowse');
+
+			var all_libs = 'Select an image library';
+
+			var lib_opts = $('<ul id=imglib_opts>').appendTo(browser);
+			var frame = $('<iframe/>').prependTo(browser).hide().wrap('<div id=lib_framewrap>');
+			
+			var header = $('<h1>').prependTo(browser).text(all_libs).css({
+				position: 'absolute',
+				top: 0,
+				left: 0,
+				width: '100%'
+			});
+			
+			var cancel = $('<button>Cancel</button>').appendTo(browser).click(function() {
+				$('#imgbrowse_holder').hide();
+			}).css({
+				position: 'absolute',
+				top: 5,
+				right: -10
+			});
+			
+			var leftBlock = $('<span>').css({position:'absolute',top:5,left:10}).appendTo(browser);
+			
+			var back = $('<button>Show libraries</button>').appendTo(leftBlock).click(function() {
+				frame.attr('src', 'about:blank').hide();
+				lib_opts.show();
+				header.text(all_libs);
+			}).css({
+				'margin-right': 5
+			});
+			
+			var type = $('<select><option value=s>Import single</option><option value=m>Import multiple</option><option value=o>Open as new document</option></select>').appendTo(leftBlock).change(function() {
+				mode = $(this).val();
+				switch (mode) {
+					case 's':
+					case 'o':
+						toggleMulti(false);
+						break;
+					
+					case 'm':
+						// Import multiple
+						toggleMulti(true);
+				}
+			}).css({
+				'margin-top': 10
+			});
+			
+			cancel.prepend($.getSvgIcon('cancel', true));
+			back.prepend($.getSvgIcon('tool_imagelib', true));
+			
+			$.each(img_libs, function(i, opts) {
+				$('<li>').appendTo(lib_opts).text(opts.name).click(function() {
+					frame.attr('src', opts.url).show();
+					header.text(opts.name);
+					lib_opts.hide();
+				}).append('<span>' + opts.description + '</span>');
+			});
+			
+		} else {
+			$('#imgbrowse_holder').show();
+		}
+	}
+	
+	return {
+		svgicons: "extensions/ext-imagelib.xml",
+		buttons: [{
+			id: "tool_imagelib",
+			type: "app_menu", // _flyout
+			position: 4,
+			title: "Image library",
+			events: {
+				"mouseup": showBrowser
+			}
+		}],
+		callback: function() {
+		
+			$('<style>').text('\
+				#imgbrowse_holder {\
+					position: absolute;\
+					top: 0;\
+					left: 0;\
+					width: 100%;\
+					height: 100%;\
+					background-color: rgba(0, 0, 0, .5);\
+					z-index: 5;\
+				}\
+				\
+				#imgbrowse {\
+					position: absolute;\
+					top: 25px;\
+					left: 25px;\
+					right: 25px;\
+					bottom: 25px;\
+					min-width: 300px;\
+					min-height: 200px;\
+					background: #B0B0B0;\
+					border: 1px outset #777;\
+				}\
+				#imgbrowse h1 {\
+					font-size: 20px;\
+					margin: .4em;\
+					text-align: center;\
+				}\
+				#lib_framewrap,\
+				#imgbrowse > ul {\
+					position: absolute;\
+					top: 45px;\
+					left: 10px;\
+					right: 10px;\
+					bottom: 10px;\
+					background: white;\
+					margin: 0;\
+					padding: 0;\
+				}\
+				#imgbrowse > ul {\
+					overflow: auto;\
+				}\
+				#imgbrowse > div {\
+					border: 1px solid #666;\
+				}\
+				#imglib_preview > div {\
+					padding: 5px;\
+					font-size: 12px;\
+				}\
+				#imglib_preview img {\
+					display: block;\
+					margin: 0 auto;\
+					max-height: 100px;\
+				}\
+				#imgbrowse li {\
+					list-style: none;\
+					padding: .5em;\
+					background: #E8E8E8;\
+					border-bottom: 1px solid #B0B0B0;\
+					line-height: 1.2em;\
+					font-style: sans-serif;\
+					}\
+				#imgbrowse li > span {\
+					color: #666;\
+					font-size: 15px;\
+					display: block;\
+					}\
+				#imgbrowse li:hover {\
+					background: #FFC;\
+					cursor: pointer;\
+					}\
+				#imgbrowse iframe {\
+					width: 100%;\
+					height: 100%;\
+					border: 0;\
+				}\
+			').appendTo('head');
+		}
+	}
+});
+

+ 14 - 0
main/inc/lib/svg-edit/extensions/ext-imagelib.xml

@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+	<g id="tool_imagelib">
+<svg width="201" height="211" xmlns="http://www.w3.org/2000/svg">
+ <g>
+  <path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m2.75,49.51761l56.56,-46.26761c12.73,8.25 25.71001,7 46.44,0.75l-56.03999,47.23944l-22.72002,25.01056l-24.23999,-26.73239z" id="svg_2" stroke-width="7"/>
+  <path fill="#a03333" stroke="#3f3f3f" d="m3.75,203.25002c14.33301,7 30.66699,7 46,0l0,-152.00002c-14.66699,8 -32.33301,8 -47,0l1,152.00002zm45.75,-152.25002l56.25,-46.75l0,151l-56,48.00002m-47.25,-154.25002l57.25,-46.5" id="svg_1" stroke-width="7" stroke-linecap="round"/>
+  <path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m49.75,49.51801l56.56,-46.26801c12.72998,8.25 25.71002,7 46.44,0.75l-56.03998,47.239l-22.72003,25.011l-24.23999,-26.73199z" stroke-width="7" id="svg_5"/>
+  <path fill="#2f8e2f" stroke="#3f3f3f" d="m50.75,202.25c14.33301,7 30.66699,7.04253 46,0.04253l0,-151.04253c-14.66699,8 -32.33301,8 -47,0l1,151zm45.75,-151.25l56.25,-46.75l0,144.01219l-56,51.98782m-47.25,-151.25002l57.25,-46.5" stroke-width="7" stroke-linecap="round" id="svg_6"/>
+  <path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m95.75,49.51801l56.56,-46.26801c12.72998,8.25 25.71002,7 46.44,0.75l-56.03998,47.239l-22.72003,25.011l-24.23999,-26.73199z" stroke-width="7" id="svg_10"/>
+  <path fill="#336393" stroke="#3f3f3f" d="m96.75,200.29445c14.33301,7 30.66699,7 46,0l0,-149.04445c-14.66699,8 -32.33301,8 -47,0l1,149.04445zm45.75,-149.29445l56.25,-46.75l0,148.04445l-56,48m-47.25,-151.29445l57.25,-46.5" stroke-width="7" stroke-linecap="round" id="svg_11"/>
+ </g>
+</svg>
+	</g>
+</svg>

+ 32 - 29
main/inc/lib/svg-edit/extensions/ext-server_opensave.js

@@ -18,11 +18,12 @@ svgEditor.addExtension("server_opensave", {
 	
 		svgEditor.setCustomHandlers({
 			save: function(win, data) {
-				var svg = '<?xml version="1.0" encoding="UTF-8" ?>' + data;// Chamilo add encoding="UTF-8"
+				var svg = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + data; // Chamilo add encoding="UTF-8"
 				
 				var title = svgCanvas.getDocumentTitle();
-				//var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');//Chamilo replace by below  
+				var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');//Chamilo replace by below  
 				var filename =title;//TODO:check if the filter through filesave.php is enough
+				
 				var form = $('<form>').attr({
 					method: 'post',
 					action: save_svg_action,
@@ -42,33 +43,34 @@ svgEditor.addExtension("server_opensave", {
 				
 				c.width = svgCanvas.contentW;
 				c.height = svgCanvas.contentH;
-				canvg(c, data.svg);
-				var datauri = c.toDataURL('image/png');
-				
-				var uiStrings = svgEditor.uiStrings;
-				var note = '';
-				
-				// Check if there's issues
-				if(issues.length) {
-					var pre = "\n \u2022 ";
-					note += ("\n\n" + pre + issues.join(pre));
-				} 
-				
-				if(note.length) {
-					alert(note);
-				}
-				
-				var title = svgCanvas.getDocumentTitle();
-				var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');
-				
-				var form = $('<form>').attr({
-					method: 'post',
-					action: save_png_action,
-					target: 'output_frame'
-				})	.append('<input type="hidden" name="output_png" value="' + datauri + '">')
-					.append('<input type="hidden" name="filename" value="' + filename + '">')
-					.appendTo('body')
-					.submit().remove();
+				canvg(c, data.svg, {renderCallback: function() {
+					var datauri = c.toDataURL('image/png');
+					
+					var uiStrings = svgEditor.uiStrings;
+					var note = '';
+					
+					// Check if there's issues
+					if(issues.length) {
+						var pre = "\n \u2022 ";
+						note += ("\n\n" + pre + issues.join(pre));
+					} 
+					
+					if(note.length) {
+						alert(note);
+					}
+					
+					var title = svgCanvas.getDocumentTitle();
+					var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_');
+					
+					var form = $('<form>').attr({
+						method: 'post',
+						action: save_png_action,
+						target: 'output_frame'
+					})	.append('<input type="hidden" name="output_png" value="' + datauri + '">')
+						.append('<input type="hidden" name="filename" value="' + filename + '">')
+						.appendTo('body')
+						.submit().remove();
+				}});
 	
 				
 			}
@@ -176,3 +178,4 @@ svgEditor.addExtension("server_opensave", {
 		$("#tool_image").prepend(import_img_form);
 	}
 });
+

+ 387 - 0
main/inc/lib/svg-edit/extensions/ext-shapes.js

@@ -0,0 +1,387 @@
+/*
+ * ext-shapes.js
+ *
+ * Licensed under the Apache License, Version 2
+ *
+ * Copyright(c) 2010 Christian Tzurcanu
+ * Copyright(c) 2010 Alexis Deveria
+ *
+ */
+
+svgEditor.addExtension("shapes", function() {
+	
+
+	var current_d, cur_shape_id;
+	var canv = svgEditor.canvas;
+	var cur_shape;
+	var start_x, start_y;
+	var svgroot = canv.getRootElem();
+	var lastBBox = {};
+	
+	// This populates the category list
+	var categories = {
+		basic: 'Basic',
+		object: 'Objects',
+		symbol: 'Symbols',
+		arrow: 'Arrows',
+		flowchart: 'Flowchart',
+		animal: 'Animals',
+		game: 'Cards & Chess',
+		dialog_balloon: 'Dialog balloons',
+		electronics: 'Electronics',
+		math: 'Mathematical',
+		music: 'Music',
+		misc: 'Miscellaneous',
+		raphael_1: 'raphaeljs.com set 1',
+		raphael_2: 'raphaeljs.com set 2'
+	};
+	
+	var library = {
+		'basic': {
+			data: {
+				'heart': 'm150,73c61,-175 300,0 0,225c-300,-225 -61,-400 0,-225z',
+				'frame': 'm0,0l300,0l0,300l-300,0zm35,-265l0,230l230,0l0,-230z',
+				'donut': 'm1,150l0,0c0,-82.29042 66.70958,-149 149,-149l0,0c39.51724,0 77.41599,15.69816 105.35889,43.64108c27.94293,27.94293 43.64111,65.84165 43.64111,105.35892l0,0c0,82.29041 -66.70958,149 -149,149l0,0c-82.29041,0 -149,-66.70959 -149,-149zm74.5,0l0,0c0,41.1452 33.35481,74.5 74.5,74.5c41.14522,0 74.5,-33.3548 74.5,-74.5c0,-41.1452 -33.3548,-74.5 -74.5,-74.5l0,0c-41.14519,0 -74.5,33.35481 -74.5,74.5z',
+				"triangle": "m1,280.375l149,-260.75l149,260.75z",
+				"right_triangle": "m1,299l0,-298l298,298z",
+				"diamond": "m1,150l149,-149l149,149l-149,149l-149,-149z",
+				"pentagon": "m1.00035,116.97758l148.99963,-108.4053l148.99998,108.4053l-56.91267,175.4042l-184.1741,0l-56.91284,-175.4042z",
+				"hexagon": "m1,149.99944l63.85715,-127.71428l170.28572,0l63.85713,127.71428l-63.85713,127.71428l-170.28572,0l-63.85715,-127.71428z",
+				"septagon1": "m0.99917,191.06511l29.51249,-127.7108l119.48833,-56.83673l119.48836,56.83673l29.51303,127.7108l-82.69087,102.41679l-132.62103,0l-82.69031,-102.41679z",
+				"heptagon": "m1,88.28171l87.28172,-87.28171l123.43653,0l87.28172,87.28171l0,123.43654l-87.28172,87.28172l-123.43653,0l-87.28172,-87.28172l0,-123.43654z",
+				"decagon": "m1,150.00093l28.45646,-88.40318l74.49956,-54.63682l92.08794,0l74.50002,54.63682l28.45599,88.40318l-28.45599,88.40318l-74.50002,54.63681l-92.08794,0l-74.49956,-54.63681l-28.45646,-88.40318z",
+				"dodecagon": "m1,110.07421l39.92579,-69.14842l69.14842,-39.92579l79.85159,0l69.14842,39.92579l39.92578,69.14842l0,79.85159l-39.92578,69.14842l-69.14842,39.92578l-79.85159,0l-69.14842,-39.92578l-39.92579,-69.14842l0,-79.85159z",
+				"star_points_5": "m1,116.58409l113.82668,0l35.17332,-108.13487l35.17334,108.13487l113.82666,0l-92.08755,66.83026l35.17514,108.13487l-92.08759,-66.83208l-92.08757,66.83208l35.17515,-108.13487l-92.08758,-66.83026z",
+				"trapezoid": "m1,299l55.875,-298l186.25001,0l55.87498,298z",
+				"arrow_up": "m1.49805,149.64304l148.50121,-148.00241l148.50121,148.00241l-74.25061,0l0,148.71457l-148.5012,0l0,-148.71457z",
+				"vertical_scrool": "m37.375,261.625l0,-242.9375l0,0c0,-10.32083 8.36669,-18.6875 18.6875,-18.6875l224.25,0c10.32083,0 18.6875,8.36667 18.6875,18.6875c0,10.32081 -8.36667,18.6875 -18.6875,18.6875l-18.6875,0l0,242.9375c0,10.32083 -8.36668,18.6875 -18.6875,18.6875l-224.25,0l0,0c-10.32083,0 -18.6875,-8.36667 -18.6875,-18.6875c0,-10.32083 8.36667,-18.6875 18.6875,-18.6875zm37.375,-261.625l0,0c10.32081,0 18.6875,8.36667 18.6875,18.6875c0,10.32081 -8.36669,18.6875 -18.6875,18.6875c-5.1604,0 -9.34375,-4.18335 -9.34375,-9.34375c0,-5.16041 4.18335,-9.34375 9.34375,-9.34375l18.6875,0m186.875,18.6875l-205.5625,0m-37.375,224.25l0,0c5.1604,0 9.34375,4.18335 9.34375,9.34375c0,5.1604 -4.18335,9.34375 -9.34375,9.34375l18.6875,0m-18.6875,18.6875l0,0c10.32081,0 18.6875,-8.36667 18.6875,-18.6875l0,-18.6875",
+				"smiley": "m68.49886,214.78838q81.06408,55.67332 161.93891,0m-144.36983,-109.9558c0,-8.60432 6.97517,-15.57949 15.57948,-15.57949c8.60431,0 15.57948,6.97517 15.57948,15.57949c0,8.60431 -6.97517,15.57947 -15.57948,15.57947c-8.60431,0 -15.57948,-6.97516 -15.57948,-15.57947m95.83109,0c0,-8.60432 6.97517,-15.57949 15.57948,-15.57949c8.60431,0 15.57947,6.97517 15.57947,15.57949c0,8.60431 -6.97516,15.57947 -15.57947,15.57947c-8.60429,0 -15.57948,-6.97516 -15.57948,-15.57947m-181.89903,44.73038l0,0c0,-82.60133 66.96162,-149.56296 149.56296,-149.56296c82.60135,0 149.56296,66.96162 149.56296,149.56296c0,82.60135 -66.96161,149.56296 -149.56296,149.56296c-82.60133,0 -149.56296,-66.96161 -149.56296,-149.56296zm0,0l0,0c0,-82.60133 66.96162,-149.56296 149.56296,-149.56296c82.60135,0 149.56296,66.96162 149.56296,149.56296c0,82.60135 -66.96161,149.56296 -149.56296,149.56296c-82.60133,0 -149.56296,-66.96161 -149.56296,-149.56296z",
+				"left_braket": "m174.24565,298.5c-13.39009,0 -24.24489,-1.80908 -24.24489,-4.04065l0,-140.4187c0,-2.23158 -10.85481,-4.04065 -24.2449,-4.04065l0,0c13.39009,0 24.2449,-1.80907 24.2449,-4.04065l0,-140.4187l0,0c0,-2.23159 10.8548,-4.04066 24.24489,-4.04066",
+				"uml_actor": "m40.5,100l219,0m-108.99991,94.00006l107,105m-107.00009,-106.00006l-100,106m99.5,-231l0,125m33.24219,-158.75781c0,18.35916 -14.88303,33.24219 -33.24219,33.24219c-18.35916,0 -33.2422,-14.88303 -33.2422,-33.24219c0.00002,-18.35915 14.88304,-33.24219 33.2422,-33.24219c18.35916,0 33.24219,14.88304 33.24219,33.24219z",
+				"dialog_balloon_1": "m0.99786,35.96579l0,0c0,-19.31077 15.28761,-34.96524 34.14583,-34.96524l15.52084,0l0,0l74.50001,0l139.68748,0c9.05606,0 17.74118,3.68382 24.14478,10.24108c6.40356,6.55726 10.00107,15.45081 10.00107,24.72416l0,87.41311l0,0l0,52.44785l0,0c0,19.31078 -15.2876,34.96524 -34.14584,34.96524l-139.68748,0l-97.32507,88.90848l22.82506,-88.90848l-15.52084,0c-18.85822,0 -34.14583,-15.65446 -34.14583,-34.96524l0,0l0,-52.44785l0,0z",
+				"cloud": "m182.05086,34.31005c-0.64743,0.02048 -1.27309,0.07504 -1.92319,0.13979c-10.40161,1.03605 -19.58215,7.63722 -24.24597,17.4734l-2.47269,7.44367c0.53346,-2.57959 1.35258,-5.08134 2.47269,-7.44367c-8.31731,-8.61741 -19.99149,-12.59487 -31.52664,-10.72866c-11.53516,1.8662 -21.55294,9.3505 -27.02773,20.19925c-15.45544,-9.51897 -34.72095,-8.94245 -49.62526,1.50272c-14.90431,10.44516 -22.84828,28.93916 -20.43393,47.59753l1.57977,7.58346c-0.71388,-2.48442 -1.24701,-5.01186 -1.57977,-7.58346l-0.2404,0.69894c-12.95573,1.4119 -23.58103,11.46413 -26.34088,24.91708c-2.75985,13.45294 2.9789,27.25658 14.21789,34.21291l17.54914,4.26352c-6.1277,0.50439 -12.24542,-0.9808 -17.54914,-4.26352c-8.66903,9.71078 -10.6639,24.08736 -4.94535,35.96027c5.71854,11.87289 17.93128,18.70935 30.53069,17.15887l7.65843,-2.02692c-2.46413,1.0314 -5.02329,1.70264 -7.65843,2.02692c7.15259,13.16728 19.01251,22.77237 32.93468,26.5945c13.92217,3.82214 28.70987,1.56322 41.03957,-6.25546c10.05858,15.86252 27.91113,24.19412 45.81322,21.38742c17.90208,-2.8067 32.66954,-16.26563 37.91438,-34.52742l1.82016,-10.20447c-0.27254,3.46677 -0.86394,6.87508 -1.82016,10.20447c12.31329,8.07489 27.80199,8.52994 40.52443,1.18819c12.72244,-7.34175 20.6609,-21.34155 20.77736,-36.58929l-4.56108,-22.7823l-17.96776,-15.41455c13.89359,8.70317 22.6528,21.96329 22.52884,38.19685c16.5202,0.17313 30.55292,-13.98268 36.84976,-30.22897c6.29684,-16.24631 3.91486,-34.76801 -6.2504,-48.68089c4.21637,-10.35873 3.96622,-22.14172 -0.68683,-32.29084c-4.65308,-10.14912 -13.23602,-17.69244 -23.55914,-20.65356c-2.31018,-13.45141 -11.83276,-24.27162 -24.41768,-27.81765c-12.58492,-3.54603 -25.98557,0.82654 -34.41142,11.25287l-5.11707,8.63186c1.30753,-3.12148 3.01521,-6.03101 5.11707,-8.63186c-5.93959,-8.19432 -15.2556,-12.8181 -24.96718,-12.51096z",
+				"cylinder": "m299.0007,83.77844c0,18.28676 -66.70958,33.11111 -149.00002,33.11111m149.00002,-33.11111l0,0c0,18.28676 -66.70958,33.11111 -149.00002,33.11111c-82.29041,0 -148.99997,-14.82432 -148.99997,-33.11111m0,0l0,0c0,-18.28674 66.70956,-33.1111 148.99997,-33.1111c82.29044,0 149.00002,14.82436 149.00002,33.1111l0,132.44449c0,18.28674 -66.70958,33.11105 -149.00002,33.11105c-82.29041,0 -148.99997,-14.82431 -148.99997,-33.11105z",
+				"arrow_u_turn": "m1.00059,299.00055l0,-167.62497l0,0c0,-72.00411 58.37087,-130.37499 130.375,-130.37499l0,0l0,0c34.57759,0 67.73898,13.7359 92.18906,38.18595c24.45006,24.45005 38.18593,57.61144 38.18593,92.18904l0,18.625l37.24997,0l-74.49995,74.50002l-74.50002,-74.50002l37.25,0l0,-18.625c0,-30.8589 -25.0161,-55.87498 -55.87498,-55.87498l0,0l0,0c-30.85892,0 -55.875,25.01608 -55.875,55.87498l0,167.62497z",
+				"arrow_left_up": "m0.99865,224.5l74.50004,-74.5l0,37.25l111.74991,0l0,-111.75l-37.25,0l74.5,-74.5l74.5,74.5l-37.25,0l0,186.25l-186.24989,0l0,37.25l-74.50005,-74.5z",
+				"maximize": "m1.00037,150.34581l55.30305,-55.30267l0,27.65093l22.17356,0l0,-44.21833l44.21825,0l0,-22.17357l-27.65095,0l55.30267,-55.30292l55.3035,55.30292l-27.65175,0l0,22.17357l44.21835,0l0,44.21833l22.17357,0l0,-27.65093l55.30345,55.30267l-55.30345,55.3035l0,-27.65175l-22.17357,0l0,44.21834l-44.21835,0l0,22.17355l27.65175,0l-55.3035,55.30348l-55.30267,-55.30348l27.65095,0l0,-22.17355l-44.21825,0l0,-44.21834l-22.17356,0l0,27.65175l-55.30305,-55.3035z",
+				"cross": "m0.99844,99.71339l98.71494,0l0,-98.71495l101.26279,0l0,98.71495l98.71495,0l0,101.2628l-98.71495,0l0,98.71494l-101.26279,0l0,-98.71494l-98.71494,0z",
+				"plaque": "m-0.00197,49.94376l0,0c27.5829,0 49.94327,-22.36036 49.94327,-49.94327l199.76709,0l0,0c0,27.5829 22.36037,49.94327 49.94325,49.94327l0,199.7671l0,0c-27.58289,0 -49.94325,22.36034 -49.94325,49.94325l-199.76709,0c0,-27.58292 -22.36037,-49.94325 -49.94327,-49.94325z",
+				"page": "m249.3298,298.99744l9.9335,-39.73413l39.73413,-9.93355l-49.66763,49.66768l-248.33237,0l0,-298.00001l298.00001,0l0,248.33234"
+
+			},
+			buttons: []
+		}
+	};
+	
+	var cur_lib = library.basic;
+	
+	var mode_id = 'shapelib';
+	
+	function loadIcons() {
+		$('#shape_buttons').empty();
+		
+		// Show lib ones
+		$('#shape_buttons').append(cur_lib.buttons);
+	}
+	
+	function loadLibrary(cat_id) {
+	
+		var lib = library[cat_id];
+		
+		if(!lib) {
+			$('#shape_buttons').html('Loading...');
+			$.getJSON('extensions/shapelib/' + cat_id + '.json', function(result, textStatus) {
+				cur_lib = library[cat_id] = {
+					data: result.data,
+					size: result.size,
+					fill: result.fill
+				}
+				makeButtons(cat_id, result);
+				loadIcons();
+			});
+			return;
+		}
+		
+		cur_lib = lib;
+		if(!lib.buttons.length)	makeButtons(cat_id, lib);
+		loadIcons();
+	}
+	
+	function makeButtons(cat, shapes) {
+		var size = cur_lib.size || 300;
+		var fill = cur_lib.fill || false;
+		var off = size * .05;
+		var vb = [-off, -off, size + off*2, size + off*2].join(' ');
+		var stroke = fill ? 0: (size/30);
+		
+		var shape_icon = new DOMParser().parseFromString(
+			'<svg xmlns="http://www.w3.org/2000/svg"><svg viewBox="' + vb + '"><path fill="'+(fill?'#333':'none')+'" stroke="#000000" stroke-width="' + stroke + '" /><\/svg><\/svg>',
+			'text/xml');
+
+		var width = 24;
+		var height = 24;
+		shape_icon.documentElement.setAttribute('width', width);
+		shape_icon.documentElement.setAttribute('height', height);
+		var svg_elem = $(document.importNode(shape_icon.documentElement,true));
+	
+		var data = shapes.data;
+		
+		cur_lib.buttons = [];
+	
+		for(var id in data) {
+			var path_d = data[id];
+			var icon = svg_elem.clone();
+			icon.find('path').attr('d', path_d);
+			
+			var icon_btn = icon.wrap('<div class="tool_button">').parent().attr({
+				id: mode_id + '_' + id,
+				title: id
+			});
+			
+			
+			// Store for later use
+			cur_lib.buttons.push(icon_btn[0]);
+		}
+		
+	}
+
+	
+	return {
+		svgicons: "extensions/ext-shapes.xml",
+		buttons: [{
+			id: "tool_shapelib",
+			type: "mode_flyout", // _flyout
+			position: 6,
+			title: "Shape library",
+			events: {
+				"click": function() {
+					canv.setMode(mode_id);
+				}
+			}
+		}],
+		callback: function() {
+		
+			$('<style>').text('\
+			#shape_buttons {\
+				overflow: auto;\
+				width: 180px;\
+				max-height: 300px;\
+				display: table-cell;\
+				vertical-align: middle;\
+			}\
+			\
+			#shape_cats {\
+				min-width: 110px;\
+				display: table-cell;\
+				vertical-align: middle;\
+				height: 300px;\
+			}\
+			#shape_cats > div {\
+				line-height: 1em;\
+				padding: .5em;\
+				border:1px solid #B0B0B0;\
+				background: #E8E8E8;\
+				margin-bottom: -1px;\
+			}\
+			#shape_cats div:hover {\
+				background: #FFFFCC;\
+			}\
+			#shape_cats div.current {\
+				font-weight: bold;\
+			}').appendTo('head');
+
+		
+			var btn_div = $('<div id="shape_buttons">');
+			$('#tools_shapelib > *').wrapAll(btn_div);
+			
+			var shower = $('#tools_shapelib_show');
+
+			
+			loadLibrary('basic');
+			
+			// Do mouseup on parent element rather than each button
+			$('#shape_buttons').mouseup(function(evt) {
+				var btn = $(evt.target).closest('div.tool_button');
+				
+				if(!btn.length) return;
+				
+				var copy = btn.children().clone();
+				shower.children(':not(.flyout_arrow_horiz)').remove();
+				shower
+					.append(copy)
+					.attr('data-curopt', '#' + btn[0].id) // This sets the current mode
+					.mouseup();
+				canv.setMode(mode_id);
+				
+				cur_shape_id = btn[0].id.substr((mode_id+'_').length);
+				current_d = cur_lib.data[cur_shape_id];
+				
+				$('.tools_flyout').fadeOut();
+
+			});
+
+// 			
+			var shape_cats = $('<div id="shape_cats">');
+			
+			var cat_str = '';
+			
+			$.each(categories, function(id, label) {
+				cat_str += '<div data-cat=' + id + '>' + label + '</div>';
+			});
+			
+			shape_cats.html(cat_str).children().bind('mouseup', function() {
+				var catlink = $(this);
+				catlink.siblings().removeClass('current');
+				catlink.addClass('current');
+				
+				loadLibrary(catlink.attr('data-cat'));
+				// Get stuff
+				
+				return false;
+			});
+			
+			shape_cats.children().eq(0).addClass('current');
+			
+			$('#tools_shapelib').append(shape_cats);
+
+			shower.mouseup(function() {
+				canv.setMode(current_d ? mode_id : 'select');
+			});
+
+			
+			$('#tool_shapelib').remove();
+			
+			var h = $('#tools_shapelib').height();
+			$('#tools_shapelib').css({
+				'margin-top': -(h/2 - 15),
+				'margin-left': 3
+			});
+
+	
+		},
+		mouseDown: function(opts) {
+			var mode = canv.getMode();
+			if(mode !== mode_id) return;
+			
+			var e = opts.event;
+			var x = start_x = opts.start_x;
+			var y = start_y = opts.start_y;
+			var cur_style = canv.getStyle();
+
+			cur_shape = canv.addSvgElementFromJson({
+				"element": "path",
+				"curStyles": true,
+				"attr": {
+					"d": current_d,
+					"id": canv.getNextId(),
+					"opacity": cur_style.opacity / 2,
+					"style": "pointer-events:none"
+				}
+			});
+			
+			// Make sure shape uses absolute values
+			if(current_d.charAt(0) === 'm') {
+				current_d = cur_lib.data[cur_shape_id] = canv.pathActions.convertPath(cur_shape);
+				cur_shape.setAttribute('d', current_d);
+				canv.pathActions.fixEnd(cur_shape);
+			}
+	
+			cur_shape.setAttribute('transform', "translate(" + x + "," + y + ") scale(0.005) translate(" + -x + "," + -y + ")");
+			
+// 			console.time('b');
+			canv.recalculateDimensions(cur_shape);
+			
+			var tlist = canv.getTransformList(cur_shape);
+			
+			lastBBox = cur_shape.getBBox();
+			
+			return {
+				started: true
+			}
+			// current_d
+		},
+		mouseMove: function(opts) {
+			var mode = canv.getMode();
+			if(mode !== mode_id) return;
+			
+			var zoom = canv.getZoom();
+			var evt = opts.event
+			
+			var x = opts.mouse_x/zoom;
+			var y = opts.mouse_y/zoom;
+			
+			var tlist = canv.getTransformList(cur_shape),
+				box = cur_shape.getBBox(), 
+				left = box.x, top = box.y, width = box.width,
+				height = box.height;
+			var dx = (x-start_x), dy = (y-start_y);
+
+			var newbox = {
+				'x': Math.min(start_x,x),
+				'y': Math.min(start_y,y),
+				'width': Math.abs(x-start_x),
+				'height': Math.abs(y-start_y)
+			};
+
+			var ts = null,
+				tx = 0, ty = 0,
+				sy = height ? (height+dy)/height : 1, 
+				sx = width ? (width+dx)/width : 1;
+
+			var sx = newbox.width / lastBBox.width;
+			var sy = newbox.height / lastBBox.height;
+			
+			sx = sx || 1;
+			sy = sy || 1;
+			
+			// Not perfect, but mostly works...
+			if(x < start_x) {
+				tx = lastBBox.width;
+			}
+			if(y < start_y) ty = lastBBox.height;
+			
+			// update the transform list with translate,scale,translate
+			var translateOrigin = svgroot.createSVGTransform(),
+				scale = svgroot.createSVGTransform(),
+				translateBack = svgroot.createSVGTransform();
+				
+			translateOrigin.setTranslate(-(left+tx), -(top+ty));
+			if(!evt.shiftKey) {
+				var max = Math.min(Math.abs(sx), Math.abs(sy));
+
+				sx = max * (sx < 0 ? -1 : 1);
+				sy = max * (sy < 0 ? -1 : 1);
+			}
+			scale.setScale(sx,sy);
+			
+			translateBack.setTranslate(left+tx, top+ty);
+			var N = tlist.numberOfItems;
+			tlist.appendItem(translateBack);
+			tlist.appendItem(scale);
+			tlist.appendItem(translateOrigin);
+
+			canv.recalculateDimensions(cur_shape);
+			
+			lastBBox = cur_shape.getBBox();
+		},
+		mouseUp: function(opts) {
+			var mode = canv.getMode();
+			if(mode !== mode_id) return;
+			
+			if(opts.mouse_x == start_x && opts.mouse_y == start_y) {
+				return {
+					keep: false,
+					element: cur_shape,
+					started: false
+				}
+			}
+			
+			return {
+				keep: true,
+				element: cur_shape,
+				started: false
+			}
+		}		
+	}
+});
+

+ 10 - 0
main/inc/lib/svg-edit/extensions/ext-shapes.xml

@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+	<g id="tool_shapelib">
+	  <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
+		  <path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,194.72501l0,0c0,-10.30901 35.8172,-18.666 80,-18.666c44.18298,0 80,8.35699 80,18.666l0,74.66699c0,10.30899 -35.81702,18.66699 -80,18.66699c-44.1828,0 -80,-8.358 -80,-18.66699l0,-74.66699z"/>
+		  <path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,114.608l0,0c0,-10.309 35.8172,-18.6668 80,-18.6668c44.18298,0 80,8.3578 80,18.6668l0,74.66699c0,10.30901 -35.81702,18.666 -80,18.666c-44.1828,0 -80,-8.35699 -80,-18.666l0,-74.66699z"/>
+		  <path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,33.6667l0,0c0,-10.3094 35.8172,-18.6667 80,-18.6667c44.18298,0 80,8.3573 80,18.6667l0,74.6663c0,10.31 -35.81702,18.667 -80,18.667c-44.1828,0 -80,-8.357 -80,-18.667l0,-74.6663z"/>
+		  <path id="svg_1" fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m230,32.33334c0,10.30931 -35.81726,18.66666 -80,18.66666c-44.1828,0 -80,-8.35735 -80,-18.66666"/>
+  	</svg>
+	</g>
+</svg>

+ 2 - 2
main/inc/lib/svg-edit/extensions/fileopen.php

@@ -39,8 +39,8 @@ api_block_anonymous_users();
 
 <?php
 if(!isset($_FILES['svg_file']['tmp_name'])) {
-	//echo '<div class="error-message">'. get_lang('lang_no_access_here').'</div>';// from Chamilo
-	//die();
+	echo '<div class="error-message">'. get_lang('lang_no_access_here').'</div>';// from Chamilo
+	die();
 }
 ?>
 <!doctype html>

+ 4 - 5
main/inc/lib/svg-edit/extensions/filesave.php

@@ -47,18 +47,18 @@ if(!isset($_POST['output_svg']) && !isset($_POST['output_png'])) {
 
 $file = '';
 
-//$suffix = isset($_POST['output_svg'])?'.svg':'.png';
+
 $suffix = isset($_POST['output_svg'])?'svg':'png';
 
 if(isset($_POST['filename']) && strlen($_POST['filename']) > 0) {
-	//$file = $_POST['filename'] . $suffix;
+
 	$file = $_POST['filename'];
 } else {
-	//$file = 'image' . $suffix;
+
 	$file = 'image';
 }
 
-//if($suffix == '.svg') {
+
 if($suffix == 'svg') {
 	$mime = 'image/svg+xml';
 	$contents = rawurldecode($_POST['output_svg']);
@@ -69,7 +69,6 @@ if($suffix == 'svg') {
 	$contents = base64_decode(substr($contents, $pos));
 }
 
-/////hack for Chamilo
 
 //get SVG-Edit values
 $filename=$file;//from svg-edit

+ 30 - 0
main/inc/lib/svg-edit/extensions/grid-icon.xml

@@ -0,0 +1,30 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<!-- 
+	Sample icons file. This file looks like an SVG file with groups as its
+	children. Each group element has an ID that must match the ID of the button given
+	in the extension. The SVG inside the group makes up the actual icon, and
+	needs use a viewBox instead of width/height for it to scale	properly.
+	
+	Multiple icons can be included, each within their own group.
+-->
+	<g id="view_grid">
+	  <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+		<g>
+		  <rect fill="#ffffff" stroke="#848484" x="2" y="2" width="20" height="20"/>
+		  <line fill="none" stroke="#848484" x1="11.84375" y1="-1.53125" x2="11.84375" y2="18.46875" transform="rotate(90, 11.8429, 8.46955)"/>
+		  <line fill="none" stroke="#848484" x1="11.90625" y1="5.21875" x2="11.90625" y2="25.21875" transform="rotate(90, 11.9054, 15.2196)"/>
+		  <line fill="none" stroke="#848484" x1="8.5" y1="2.03125" x2="8.5" y2="22.03125"/>
+		  <line fill="none" stroke="#848484" x1="15.5" y1="2.03125" x2="15.5" y2="22.03125"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="3.25" y="3.28125" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="10" y="3.28125" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="16.75" y="3.28125" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="3.28125" y="9.75" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="10.03125" y="9.75" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="16.78125" y="9.75" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="3.3125" y="16.59375" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="10.0625" y="16.59375" width="4" height="4"/>
+		  <rect fill="#d8d8d8" stroke="#000000" stroke-width="0" x="16.8125" y="16.59375" width="4" height="4"/>
+		</g>
+	  </svg>
+	</g>
+</svg>

+ 64 - 0
main/inc/lib/svg-edit/extensions/imagelib/index.html

@@ -0,0 +1,64 @@
+<!doctype html>
+<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
+
+
+<body>
+
+<h1>Select an image:</h1>
+<a href="smiley.svg">smiley.svg</a>
+<br>
+<a href="../../images/logo.png">logo.png</a>
+</body>
+
+<script>
+
+$('a').click(function() {
+	var href = this.href;
+	
+	// Convert Non-SVG images to data URL first 
+	// (this could also have been done server-side by the library)
+	if(this.href.indexOf('.svg') === -1) {
+
+		var meta_str = JSON.stringify({
+			name: $(this).text(),
+			id: href
+		});
+		window.top.postMessage(meta_str, "*");
+	
+		var img = new Image();
+		img.onload = function() {
+			var canvas = document.createElement("canvas");
+			canvas.width = this.width;
+			canvas.height = this.height;
+			// load the raster image into the canvas
+			canvas.getContext("2d").drawImage(this,0,0);
+			// retrieve the data: URL
+			try {
+				var dataurl = canvas.toDataURL();
+			} catch(err) {
+				// This fails in Firefox with file:// URLs :(
+				alert("Data URL conversion failed: " + err);
+				var dataurl = "";
+			}
+			window.top.postMessage('|' + href + '|' + dataurl, "*");
+		}
+		img.src = href;
+	} else {
+		// Send metadata (also indicates file is about to be sent)
+		var meta_str = JSON.stringify({
+			name: $(this).text(),
+			id: href
+		});
+		window.top.postMessage(meta_str, "*");
+		// Do ajax request for image's href value
+		$.get(href, function(data) {
+			data = '|' + href + '|' + data;
+			// This is where the magic happens!
+			window.top.postMessage(data, "*");
+			
+		}, 'html'); // 'html' is necessary to keep returned data as a string
+	}
+	return false;
+});
+
+</script>

+ 12 - 0
main/inc/lib/svg-edit/extensions/imagelib/smiley.svg

@@ -0,0 +1,12 @@
+<svg width="137" height="137" xmlns="http://www.w3.org/2000/svg">
+ <title>Cool smiley</title>
+  <path fill="url(#svg_4)" stroke="#000000" stroke-width="3" d="m32.18682,97.71674q36.3159,24.94076 72.54585,0m-64.67542,-49.25576c0,-3.8554 3.12526,-6.98079 6.98068,-6.98079c3.85449,0 6.97872,3.12539 6.97872,6.98079c0,3.85346 -3.12423,6.97867 -6.97872,6.97867c-3.85542,0 -6.98068,-3.12521 -6.98068,-6.97867m42.93047,0c0,-3.8554 3.12529,-6.98079 6.97963,-6.98079c3.8544,0 6.97971,3.12539 6.97971,6.98079c0,3.85346 -3.12531,6.97867 -6.97971,6.97867c-3.85434,0 -6.97963,-3.12521 -6.97963,-6.97867m-81.48596,20.036l0,0c0,-37.00197 29.99679,-66.99892 67.00095,-66.99892c37.00303,0 66.99998,29.99695 66.99998,66.99892c0,37.00409 -29.99695,67.00101 -66.99998,67.00101c-37.00416,0 -67.00095,-29.99692 -67.00095,-67.00101zm0,0l0,0c0,-37.00197 29.99679,-66.99892 67.00095,-66.99892c37.00303,0 66.99998,29.99695 66.99998,66.99892c0,37.00409 -29.99695,67.00101 -66.99998,67.00101c-37.00416,0 -67.00095,-29.99692 -67.00095,-67.00101z" id="svg_1"/>
+  <path id="svg_5" d="m23.84005,41.03445l17.57052,0l5.42937,-19.67914l5.42941,19.67914l17.5706,0l-14.21488,12.16242l5.42982,19.67939l-14.21495,-12.16281l-14.21489,12.16281l5.42991,-19.67939l-14.21491,-12.16242l0,0z" stroke-width="3" fill="#000000"/>
+  <path id="svg_6" d="m65.84005,41.03445l17.57052,0l5.42937,-19.67914l5.42941,19.67914l17.5706,0l-14.21487,12.16242l5.42982,19.67939l-14.21496,-12.1628l-14.2149,12.1628l5.42992,-19.67939l-14.21491,-12.16242l0,0z" stroke-width="3" fill="#000000"/>
+ <defs>
+  <linearGradient y2="0.25391" x2="0.46484" y1="0.94922" x1="0.44531" id="svg_4">
+   <stop stop-color="#ff0000" offset="0"/>
+   <stop stop-color="#ffff00" offset="1"/>
+  </linearGradient>
+ </defs>
+</svg>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 0
main/inc/lib/svg-edit/extensions/shapelib/animal.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 15 - 0
main/inc/lib/svg-edit/extensions/shapelib/arrow.json


+ 9 - 0
main/inc/lib/svg-edit/extensions/shapelib/dialog_balloon.json

@@ -0,0 +1,9 @@
+{"data": {
+	"1": "m0.99786,35.96579l0,0c0,-19.31077 15.28761,-34.96524 34.14583,-34.96524l15.52084,0l0,0l74.50001,0l139.68748,0c9.05606,0 17.74118,3.68382 24.14478,10.24108c6.40356,6.55726 10.00107,15.45081 10.00107,24.72416l0,87.41311l0,0l0,52.44785l0,0c0,19.31078 -15.2876,34.96524 -34.14584,34.96524l-139.68748,0l-97.32507,88.90848l22.82506,-88.90848l-15.52084,0c-18.85822,0 -34.14583,-15.65446 -34.14583,-34.96524l0,0l0,-52.44785l0,0z",
+	"4": "m1,1l49.66667,0l0,0l74.5,0l173.83334,0l0,115.8889l0,0l0,49.66666l0,33.11111l-173.83334,0l-123.68433,97.37498l49.18433,-97.37498l-49.66667,0l0,-33.11111l0,-49.66666l0,0z",
+	"5": "m3.88165,296.34811l58.64952,-105.30074l0,0c-62.13446,-31.76456 -79.86445,-91.6022 -40.96117,-138.24044c38.90255,-46.63797 121.70818,-64.81269 191.29914,-41.98796c69.59094,22.8246 103.19446,79.17835 77.63046,130.19172c-25.56265,51.01335 -101.92546,79.99094 -176.41714,66.94487l-110.20081,88.39255z",
+	"6": "m4.33333,266.6662c0,-1.854 2.23757,-3.35571 5,-3.35571c2.76243,0 5,1.50171 5,3.35571c0,1.85394 -2.23757,3.35565 -5,3.35565c-2.76243,0 -5,-1.50171 -5,-3.35565zm10.25,-24.11072c0,-4.6351 5.59392,-8.38943 12.50001,-8.38943c6.90608,0 12.5,3.75433 12.5,8.38943c0,4.63489 -5.59392,8.38928 -12.5,8.38928c-6.90609,0 -12.50001,-3.75433 -12.50001,-8.38928zm23.75001,-36.55524c0,-12.81482 19.46685,-23.19473 43.50002,-23.19473c24.0331,0 43.49996,10.37991 43.49996,23.19473c0,12.81473 -19.46686,23.19455 -43.49996,23.19455c-24.03317,0 -43.50002,-10.37982 -43.50002,-23.19455zm-37.33334,-104.99994c0,-55.2486 66.67956,-100 149,-100c82.32047,0 149,44.7514 149,100c0,55.24866 -66.67953,100 -149,100c-82.32044,0 -149,-44.75134 -149,-100z",
+	"scream": "m299.67374,132.67729l-35.72574,1.97192l-9.55817,48.04506l-31.60561,-11.61551l-45.83566,36.86661l-17.45096,-21.51509l-146.98414,92.00807l81.6677,-102.60858l-67.83573,-13.33963l21.22697,-19.84731l-46.57336,-36.42733l33.47025,-8.80944l-10.52427,-47.94958l35.08694,5.02536l28.86619,-44.2482l25.5638,17.26465l59.09183,-26.49832l7.92432,24.02253l70.55626,-0.33542l-12.23108,23.15343l59.61954,25.93398l-28.50317,14.93327l29.75409,43.96953z",
+	"thought": "m12,1c-6.094,0 -11,4.906 -11,11l0,147c0,6.09399 4.906,11 11,11l49.15625,0c-2.03143,2.32526 -3.15625,4.84886 -3.15625,7.5c0,11.32597 20.36188,20.5 45.5,20.5c25.13812,0 45.5,-9.17403 45.5,-20.5c0,-2.65114 -1.12482,-5.17474 -3.15625,-7.5l142.15625,0c6.09399,0 11,-4.90601 11,-11l0,-147c0,-6.094 -4.90601,-11 -11,-11l-276,0zm54,199c-13.81215,0 -25,5.37016 -25,12c0,6.62984 11.18785,12 25,12c13.81216,0 25,-5.37016 25,-12c0,-6.62984 -11.18784,-12 -25,-12zm-25,30c-7.73481,0 -14,4.02762 -14,9c0,4.97238 6.26519,9 14,9c7.73481,0 14,-4.02762 14,-9c0,-4.97238 -6.26519,-9 -14,-9zm-24,22c-4.97238,0 -9,2.23756 -9,5c0,2.76242 4.02762,5 9,5c4.97238,0 9,-2.23758 9,-5c0,-2.76244 -4.02762,-5 -9,-5z"
+	}
+}

+ 20 - 0
main/inc/lib/svg-edit/extensions/shapelib/electronics.json

@@ -0,0 +1,20 @@
+{"data": {
+	"capacitor": "m292.103577,149.999374l-117.073944,-0.445328m-167.175035,0.445328l116.628588,0m0.44532,-72.035179l11.364601,0l0,144.640358l-11.364601,0l0,-144.640358zm38.244209,-0.569977l11.364594,0l0,144.640297l-11.364594,0l0,-144.640297zm-162.171733,68.98156l6.905184,0l0,6.905212l-6.905184,0l0,-6.905212zm291.101741,0.325241l6.905182,0l0,6.905212l-6.905182,0l0,-6.905212z",
+	"diode": "m180.228439,90.39769l21.70816,0l0,117.211075l-21.70816,0l0,-117.211075zm23.345947,59.602753l88.556381,0m-284.3409,-1.995804l85.541058,0l0,-65.011185l87.251961,66.722031l-87.250778,67.291931l0,-68.720001m-92.331572,-3.917542l6.811423,0l0,6.811447l-6.811423,0l0,-6.811447zm291.20439,2.03891l6.811401,0l0,6.811462l-6.811401,0l0,-6.811462z",
+	"gate_and": "m7.454795,178.082489l67.605378,0m-67.605378,-54.850876l67.605393,0.000015m-0.155602,-30.065033l0,113.750015c194.70015,10.208389 199.234482,-124.687454 0,-113.750015zm217.618942,56.662766l-70.312149,0m-221.397258,-29.817062l6.68369,0l0,6.683685l-6.68369,0l0,-6.683685zm-0.314375,54.532364l6.68369,0l0,6.683685l-6.68369,0l0,-6.683685zm291.95109,-27.976547l6.683685,0l0,6.683685l-6.683685,0l0,-6.683685z",
+	"gate_inverter": "m292.351624,149.998962l-70.506393,0m-0.189026,0a19.883057,19.883057 0 1 1-39.766113,0a19.883057,19.883057 0 1 139.766113,0zm-213.972072,2.405243l69.321826,0l0,-61.05407l101.250404,58.4571l-101.19664,58.840652l0,-56.176727m-76.061115,-3.699677l6.780182,0l0,6.779526l-6.780182,0l0,-6.779526zm291.428455,-2.135864l6.780518,0l0,6.780548l-6.780518,0l0,-6.780548z",
+	"gate_nand": "m8.042537,173.038879l60.699101,-0.672531m-60.699101,-49.879471l61.371335,0m-0.785973,-24.868042l0,104.835098c179.441437,9.408417 183.619827,-114.915443 0,-104.835098zm223.921448,50.643158l-64.591507,0m0.637238,0a11.937837,11.937837 0 1 1-23.87648,0a11.937837,11.937837 0 1 123.87648,0zm-227.445681,-29.373505l6.739111,0l0,6.739143l-6.739111,0l0,-6.739143zm-0.150617,50.613495l6.73911,0l0,6.739151l-6.73911,0l0,-6.739151zm291.47287,-24.654327l6.739105,0l0,6.739151l-6.739105,0l0,-6.739151z",
+	"gate_nor": "m292.610077,150.214462l-69.483139,-0.215668m0.147217,0.215668a12.942393,12.942393 0 1 1-25.884689,0a12.942393,12.942393 0 1 125.884689,0zm-215.590108,29.264374l63.620397,0m-63.620397,-54.805801l65.561368,-0.431335m-20.75433,-33.139984c129.343479,0 143.580387,58.405624 143.580387,58.405624l-0.347778,0c-18.514755,69.097885 -143.580379,58.057999 -143.580379,58.057999c59.7962,-58.405655 0.347775,-116.463623 0.347775,-116.463623zm-51.490408,30.117874l6.644974,0l0,6.645012l-6.644974,0l0,-6.645012zm0.003831,54.852463l6.644983,0l0,6.64502l-6.644983,0l0,-6.64502zm291.530706,-29.571609l6.644989,0l0,6.64502l-6.644989,0l0,-6.64502z",
+	"gate_or": "m7.681484,183.57515l71.7616,0m-71.7616,-60.67144l73.093784,-0.000015m-23.092442,-37.784157c143.186604,0 158.947315,64.65654 158.947315,64.65654l75.817307,0l-76.202316,0c-20.49614,76.493118 -158.94717,64.271667 -158.94717,64.271667c66.195942,-64.656525 0.385136,-128.928207 0.385136,-128.928207zm-56.684011,33.939781l6.677925,0l0,6.677956l-6.677925,0l0,-6.677956zm291.510831,27.410866l6.677948,0l0,6.677948l-6.677948,0l0,-6.677948zm-291.404498,33.607208l6.677927,0l0,6.677917l-6.677927,0l0,-6.677917z",
+	"gate_xor": "m80.450493,91.498093c129.22271,0 143.446312,58.351089 143.446312,58.351089l68.423569,0l-68.770889,0c-18.497391,69.033295 -143.446304,58.003708 -143.446304,58.003708c59.740372,-58.351089 0.347511,-116.354797 0.347511,-116.354797zm-22.576313,4.515259c43.415966,54.530457 0,108.018921 0,108.018921m-50.015199,-26.867355l63.560987,0m-63.560987,-54.7547l63.560987,0m-70.418914,-3.722206l6.82584,0l0,6.825867l-6.82584,0l0,-6.825867zm0.057968,54.832268l6.825839,0l0,6.825867l-6.825839,0l0,-6.825867zm291.170364,-27.096024l6.825836,0l0,6.825867l-6.825836,0l0,-6.825867z",
+	"inductor": "m7.783882,182.663147l59.679306,0c0,0 -30.829735,-67.744125 15.054253,-68.81945c42.462807,-0.995041 37.635605,69.357201 24.194321,69.357201c-13.441284,0 -12.903625,-68.81955 22.043701,-68.81955c34.947357,0 40.323868,68.819366 20.968399,68.819366c-19.355423,0 -11.828323,-68.819366 22.58139,-68.819366c34.409683,0 41.399155,68.81955 19.893112,68.81955c-21.506073,0 -9.67775,-68.81955 24.19429,-68.81955c33.87207,0 29.570831,68.819366 18.280151,68.819366c-11.290665,0 57.528732,-0.537659 57.528732,-0.537659m-291.202282,-3.571106l6.772959,0l0,6.772995l-6.772959,0l0,-6.772995zm291.221844,0.301132l6.772949,0l0,6.772995l-6.772949,0l0,-6.772995z",
+	"junction_1": "m0.99971,146.64024l6.71786,0l0,6.7179l-6.71786,0l0,-6.7179zm7.44043,3.36145l283.11684,0m0.72388,-3.35979l6.71786,0l0,6.7179l-6.71786,0l0,-6.7179zm-145.6413,152.35712l0,-6.71786l6.7179,0l0,6.71786l-6.7179,0zm3.36145,-7.44043l0,-283.11688m-3.35944,-0.72348l0,-6.71786l6.71793,0l0,6.71786l-6.71793,0z",
+	"junction_2": "m0.99971,146.64024l6.71786,0l0,6.7179l-6.71786,0l0,-6.7179zm7.44043,3.36145l121.77922,0c0,-29.3896 38.77921,-31.3896 38.77921,0l122.55841,0m0.72391,-3.35979l6.71783,0l0,6.7179l-6.71783,0l0,-6.7179zm-145.6413,152.35712l0,-6.71786l6.7179,0l0,6.71786l-6.7179,0zm3.36145,-7.44043l0,-283.11688m-3.35945,-0.72348l0,-6.71786l6.71794,0l0,6.71786l-6.71794,0z",
+	"junction_3": "m143.58945,150.00009c0,-3.49425 2.83032,-6.32455 6.32455,-6.32455c3.49423,0 6.32455,2.83031 6.32455,6.32455c0,3.49423 -2.83032,6.32455 -6.32455,6.32455c-3.49423,0 -6.32455,-2.83032 -6.32455,-6.32455zm-142.59006,-3.35985l6.71783,0l0,6.7179l-6.71783,0l0,-6.7179zm7.44043,3.36145l283.11682,0m0.72394,-3.35979l6.71783,0l0,6.7179l-6.71783,0l0,-6.7179zm-145.6413,152.35712l0,-6.71786l6.7179,0l0,6.71786l-6.7179,0zm3.36145,-7.44043l0,-283.11688m-3.35947,-0.72348l0,-6.71786l6.71796,0l0,6.71786l-6.71796,0z",
+	"junction_tee": "m149.914,143.67554zm-148.91461,2.96471l6.71783,0l0,6.7179l-6.71783,0l0,-6.7179zm7.44043,3.36145l283.11682,0m0.72394,-3.35979l6.71783,0l0,6.7179l-6.71783,0l0,-6.7179zm-141.61324,2.91669l-0.66661,-141.11688m-3.35947,-0.72348l0,-6.71786l6.71796,0l0,6.71786l-6.71796,0z",
+	"resistor": "m7.868202,151.620193l82.343018,0l11.393402,-32.392784l18.643684,62.356071l20.71521,-63.165901l18.12587,62.356071l19.679459,-61.546242l19.679443,61.951149l10.875488,-30.368195l82.860886,0m-291.18655,-2.813812l6.844604,0l0,6.844635l-6.844604,0l0,-6.844635zm291.194058,-0.465622l6.844604,0l0,6.844635l-6.844604,0l0,-6.844635z",
+	"source_AC_h": "m7.841724,149.837311l67.250737,0m149.928139,0.389923l67.250793,0m-67.653702,-0.227753a74.615135,74.615135 0 1 1-149.230286,0a74.615135,74.615135 0 1 1149.230286,0zm-126.528297,-1.996506c49.250984,-78.535637 61.230949,87.853104 103.826454,2.662094m-200.917796,-4.522659l6.717863,0l0,6.717896l-6.717863,0l0,-6.717896zm291.36706,0.642181l6.717865,0l0,6.717896l-6.717865,0l0,-6.717896z",
+	"source_DC": "m221.862747,94.98175l0,31.813873m-21.510544,-15.906944l43.020996,0m48.613678,39.407722l-121.593582,0m-162.447085,0l115.809275,0m1.040596,-37.757935l7.284134,0l0,75.963058l-7.284134,0l0,-75.963058zm37.461227,-41.623596l7.284134,0l0,158.169647l-7.284134,0l0,-158.169647zm-161.255614,75.613235l6.954941,0l0,6.954971l-6.954941,0l0,-6.954971zm291.012953,0.175003l6.954956,0l0,6.954971l-6.954956,0l0,-6.954971z",
+	"speaker": "m21.35352,187l77,0m-83.70878,3.11937l0,-6.71786l6.71793,0l0,6.71786l-6.71793,0zm6.70878,-76.11937l77,0m-83.70878,3.11937l0,-6.71786l6.71793,0l0,6.71786l-6.71793,0zm155.70878,-32.61937l115,-83l0,296.5l-115,-82.5l0,-131zm-70.99999,0l70.99999,0l0,131l-70.99999,0l0,-131z"
+	}
+}

+ 25 - 0
main/inc/lib/svg-edit/extensions/shapelib/flowchart.json

@@ -0,0 +1,25 @@
+{"data": {
+	"manual_input": "m1,103.64394l298,-30.9037l0,154.51852l-298,0z",
+	"callout_left_right": "m1,150.0006l58.10869,-58.1087l0,29.05434l46.81141,0l0,-87.16304l87.1598,0l0,87.16304l46.8114,0l0,-29.05434l58.1087,58.1087l-58.1087,58.10869l0,-29.05435l-46.8114,0l0,87.16306l-87.1598,0l0,-87.16306l-46.81141,0l0,29.05435l-58.10869,-58.10869z",
+	"card": "m1,60.5l59.5,-59.5l238.5,0l0,298l-298,0l0,-238.5z",
+	"collate": "m0,1l299,0l-149.5,149l149.5,149l-299.00031,0l149.50031,-149l-149.5,-149z",
+	"connector_offpage": "m0.99775,0.99775l297.99984,0l0,238.39982l-149.00002,59.60002l-148.99999,-59.60002l0.00017,-238.39982z",
+	"data_stored": "m50.83397,0.99813l249.16667,0c-27.52219,0 -49.83333,66.78392 -49.83333,149.16604c0,82.38213 22.31114,149.16603 49.83333,149.16603l-249.16667,0l0,0c-27.52219,0 -49.83333,-66.78391 -49.83333,-149.16603c0,-82.38212 22.31114,-149.16604 49.83333,-149.16604z",
+	"data": "m1.00038,249.33351l59.60001,-198.66668l238.40001,0l-59.60001,198.66668z",
+	"decision": "m0.99837,149.99953l148.79352,-102.86476l148.79387,102.86476l-148.79387,102.86476l-148.79352,-102.86476z",
+	"delay": "m1,1l149,0l0,0c82.29044,0 149,66.70957 149,149c0,82.29044 -66.70956,149 -149,149l-149,0z",
+	"display": "m1,149.99924l49.66672,-97.42307l198.66612,0c27.43034,0 49.66716,43.61774 49.66716,97.42307c0,53.80476 -22.23682,97.42308 -49.66716,97.42308l-198.66612,0l-49.66672,-97.42308z",
+	"document_multiple": "m1.00054,45.02563l253.99998,0l0,206.43799c-126.99997,0 -126.99997,78.65668 -253.99998,33.96539zm21.49946,-240.92902l0,-19.5l255,0l0,207l-22.5,1m-210.5,-207l0,-25l255,0l0,207l-21.5,0",
+	"document": "m1.00064,1.00098l298,0l0,242.19891c-149,0 -149,92.28223 -298,39.84915z",
+	"filter1": "m75.5,150l74.5,-149l74.5,149l-74.5,149l-74.5,-149zm0,0l149,0",
+	"or_junction": "m0.99865,149.9991l0,0c0,-82.29043 66.70957,-149 149.00001,-149l0,0c39.51724,0 77.41597,15.69817 105.3589,43.64109c27.94292,27.94292 43.64107,65.84166 43.64107,105.35891l0,0c0,82.29041 -66.70956,148.99998 -148.99997,148.99998l0,0c-82.29044,0 -149.00001,-66.70958 -149.00001,-148.99998zm149.00001,-149l0,297.99998m-149.00001,-148.99998l297.99998,0",
+	"preparation": "m1.00063,150.00006l59.58485,-82.24058l178.75446,0l59.58505,82.24058l-59.58505,82.24086l-178.75446,0l-59.58485,-82.24086z",
+	"process": "m1,51.87891l298,0l0,196.24391l-298,0zm37.25,-196.24391l0,196.24391m223.5,-196.24391l0,196.24391",
+	"punched_tape": "m1.00047,30.80047l0,0c0,16.45808 33.35479,29.8 74.50001,29.8c41.1452,0 74.49998,-13.34192 74.49998,-29.8l0,0c0,-16.45809 33.3548,-29.8 74.50002,-29.8c41.14522,0 74.49998,13.34192 74.49998,29.8l0,238.4c0,-16.45808 -33.35477,-29.80002 -74.49998,-29.80002c-41.14522,0 -74.50002,13.34193 -74.50002,29.80002c0,16.45807 -33.35478,29.79999 -74.49998,29.79999c-41.14522,0 -74.50001,-13.34192 -74.50001,-29.79999z",
+	"sequential_data_storage": "m150,299l0,0c-82.29043,0 -149,-66.70955 -149,-149l0,0c0,-82.29043 66.70957,-149 149,-149l0,0c39.51726,0 77.41599,15.69817 105.3589,43.64108c27.94292,27.94293 43.6411,65.84165 43.6411,105.35892l0,0c0,39.51726 -15.69818,77.41599 -43.6411,105.3589l43.6411,0l0,43.6411z",
+	"sort": "m-0.0038,150.00102l299.00334,0m-299.00334,-0.00002l149.50209,-150.00059l149.50131,150.00059l-149.50131,150.00018l-149.50209,-150.00018z",
+	"storage_internal": "m1,1l297.99997,0l0,297.99997l-297.99997,0zm37.25,-297.99997l0,297.99997m-37.25,-260.74997l297.99997,0",
+	"terminal": "m48.94167,99.12235l202.11729,0l0,0c26.47794,0 47.9425,22.7794 47.9425,50.8792c0,28.09979 -21.46457,50.87918 -47.9425,50.87918l-202.11729,0l0,0c-26.47791,0 -47.9425,-22.77939 -47.9425,-50.87918c0,-28.09981 21.46459,-50.8792 47.9425,-50.8792z",
+	"wave": "m1,37.20809c99.33355,-125.42461 198.66708,125.4246 298.00061,0l0,225.76426c-99.33353,125.42462 -198.66706,-125.42459 -298.00061,0z"
+	}
+}

+ 13 - 0
main/inc/lib/svg-edit/extensions/shapelib/game.json

@@ -0,0 +1,13 @@
+{"data": {
+	"cards_clubs": "m107.57338,275.50809c15.10838,-15.77673 27.93053,-34.56763 33.34637,-55.90254c-16.19595,12.31328 -31.05006,32.11845 -53.64258,31.36813c-17.05595,0.97891 -37.37346,0.99548 -49.37947,-13.26945c-26.83,-21.5751 -34.03729,-64.69673 -12.00568,-92.15404c15.07669,-19.82526 41.4039,-28.23172 65.56467,-25.25816c15.22319,-6.45935 -2.97749,-22.81502 -4.80785,-33.02267c-11.33012,-37.02704 15.36169,-81.44029 54.60988,-85.70572c28.15103,-4.0415 55.67099,14.18231 69.44571,37.83293c7.4856,16.54877 3.58533,35.33045 1.83887,52.49866c-5.88113,8.62766 -20.94342,29.50022 0.55099,27.85616c21.2518,-0.33633 43.69397,5.90277 57.70761,22.8026c20.49747,22.76067 22.37766,60.37286 1.7551,83.63007c-10.90869,14.16582 -27.2782,25.50356 -45.80551,24.87234c-18.13391,1.83067 -37.77023,-2.10338 -50.62924,-15.92061c-5.48438,-3.84309 -18.92297,-18.36311 -18.91833,-15.17883c13.43222,27.98354 28.62112,57.04413 55.49167,74.38477c9.60062,7.71954 -14.62323,2.41226 -20.4874,3.98563c-35.53012,0.0314 -71.06009,0.06342 -106.59021,0.09497c7.31842,-7.63818 14.6373,-15.27603 21.9554,-22.91422z",
+	"cards_diamonds": "m34.92883,153.9321c25.56111,-56.62673 71.64644,-104.95768 110.85236,-152.92286c45.60773,30.78102 85.01025,98.49872 119.29071,145.66264c-30.57587,54.55344 -74.58923,104.23671 -114.23947,153.1615c-42.74368,-44.7616 -79.29648,-95.90262 -115.90359,-145.90128z",
+	"cards_hearts": "m106.76112,245.09012c-77.74644,-57.80281 -105.54389,-94.36783 -105.76917,-139.13003c-0.20544,-40.80623 34.10907,-80.19025 69.67002,-79.96313c17.75755,0.11364 55.84863,15.13257 69.33681,27.33919c6.79614,6.1504 10.01512,5.54391 25.146,-4.73779c41.17987,-27.98239 81.39243,-28.56973 107.43585,-1.56907c41.62292,43.15273 34.04501,94.68497 -21.78392,148.13782c-29.68187,28.41864 -94.50056,78.8349 -101.35565,78.8349c-2.08591,0 -21.29187,-13.01038 -42.67994,-28.9119z",
+	"cards_spades": "m92.84135,287.13989c18.3756,-17.73279 31.81261,-40.18849 43.07161,-62.94162c6.87787,-9.075 0.36623,-17.01425 -9.00183,-9.3188c-24.07579,16.07495 -56.84848,21.58751 -82.91551,6.92194c-29.46779,-15.23779 -42.75618,-51.47162 -36.07021,-83.04361c4.23415,-31.99545 27.52112,-57.07481 52.80524,-75.08997c29.04437,-20.7771 60.40868,-38.61331 86.95355,-62.67224c11.08365,0.22219 19.42508,17.61496 31.35349,22.21747c31.67316,23.59131 69.20874,40.95643 94.15042,72.50237c12.60098,17.9752 19.78281,40.10946 20.58459,61.98948c-3.83926,29.67093 -21.5314,60.96272 -52.04169,69.41241c-26.37521,7.98038 -53.51129,-2.14038 -76.49545,-15.01619c-2.80743,-0.60251 -13.10471,-8.7151 -9.02362,-2.41039c13.74066,28.19803 28.79581,56.19804 50.59952,79.09325c1.28156,2.89285 11.33243,9.75613 5.98334,9.64709c-44.76935,0 -89.53856,0 -134.30794,0c4.78471,-3.7637 9.5696,-7.5275 14.35449,-11.2912z",
+	"chess_bishop": "m61.92021,296.91153c0.43627,-9.82327 20.22808,-4.98053 9.33225,-14.55078c3.63447,-11.80536 14.91982,-19.66748 21.741,-29.79436c5.22913,-8.62125 17.00826,-19.01086 11.31252,-29.67047c-10.46021,-5.58662 -7.49181,-18.00824 5.30239,-15.28014c8.2272,-7.58801 8.79371,-20.26302 11.57766,-30.59467c2.52694,-12.36574 4.07327,-24.95554 3.66998,-37.5896c-14.99698,0.03661 -30.27584,-0.68196 -44.73978,-4.74928c2.8019,-11.20453 20.86148,-8.79659 28.26084,-15.67982c-6.87532,-6.18329 13.89957,-5.56496 8.46355,-15.34472c-0.37302,-11.20033 -9.19685,-14.44135 -16.26585,-22.60765c-9.44371,-12.76132 5.36173,-25.51221 13.58463,-34.13964c9.16566,-9.37672 19.64847,-19.36716 22.45389,-32.62941c-3.77451,-3.10155 -12.3967,-7.54239 -3.59866,-11.78228c12.01596,-2.03703 24.83499,-2.28521 36.61118,1.05654c7.81644,7.61585 -11.93045,8.03119 -3.43417,17.63365c10.07373,12.07176 -3.50795,18.30174 -11.52704,25.27969c-4.66763,5.89621 -18.59915,13.67189 -16.20224,19.78346c13.63968,-0.47554 21.5871,-13.67976 31.31615,-21.49704c10.67101,-13.68708 20.99446,8.43092 27.81822,15.94714c8.40642,11.39094 2.60674,26.70086 -10.05556,31.59287c-6.28001,6.46729 -10.44972,24.88914 4.57674,22.14657c8.72636,3.17196 -8.52979,3.51371 1.37608,6.446c6.58298,2.52787 32.25821,8.30554 18.1142,16.0547c-12.00471,2.71368 -24.40523,2.6017 -36.6002,1.50584c-0.75204,18.52477 1.89484,36.97644 7.35446,54.6958c1.35513,5.04123 2.71027,10.08244 4.06541,15.12361c6.52129,-0.129 19.98573,-1.55484 13.76321,9.18311c-13.08994,7.21928 -5.0789,22.41203 2.17738,31.05447c8.99446,11.37192 22.40833,22.01788 22.98288,37.58719c3.59734,2.14404 15.56946,8.03415 12.10645,12.64545c-57.30759,-0.2937 -114.6481,0.84897 -171.9265,-1.25046l-1.98901,-0.18246l-1.62205,-0.39337l0,0z",
+	"chess_king": "m75.6993,294.60599c-8.08068,-9.43317 12.65705,-9.68567 9.39906,-20.14252c5.95673,-13.85672 21.44485,-22.24414 23.72572,-37.99019c-6.28166,-4.37628 -9.89445,-14.96013 2.0899,-13.70361c8.78859,-6.61539 7.6902,-20.15297 10.33321,-30.0876c2.47588,-16.03471 3.03656,-32.26408 4.10001,-48.43053c-10.16894,-0.78108 -20.58942,-0.23701 -30.49778,-2.84268c0.28501,-10.75136 20.44619,-6.62604 21.3638,-16.77121c14.65907,-0.2649 0.81196,-22.15992 -5.15776,-27.38371c-7.64118,-8.81222 -12.7306,-22.72323 -6.92168,-33.60618c8.30865,-5.52043 27.09519,-2.1601 26.24604,-16.66769c-5.65058,-3.22095 -12.82484,-1.17552 -19.15805,-1.74514c0.38948,-6.7649 0.77895,-13.52979 1.16843,-20.29469c8.37558,-0.64424 16.75118,-1.28853 25.12676,-1.93283c-4.25133,-4.41846 -10.61392,-7.6702 -12.20608,-13.92034c5.41558,-8.90246 18.46751,-8.1166 27.81776,-8.03243c9.09207,-0.62713 25.66919,5.43749 13.27614,15.20592c-1.00447,2.39887 -10.78024,8.36352 -4.73895,7.71326c7.73515,0 15.47028,0 23.20541,0c-0.02223,6.6133 -0.20001,13.29232 1.35312,19.76423c-5.90448,4.39723 -25.05112,-3.75612 -19.59946,9.81149c6.13853,5.67249 15.53992,5.52279 23.32581,8.02098c4.54138,0.45371 8.15405,1.63713 6.5175,6.94557c0.85359,9.85596 -1.63307,19.77049 -8.40776,27.25217c-4.79567,7.80693 -15.56667,17.58031 -12.3781,26.61691c6.03265,-0.98199 10.87871,2.97905 6.06032,7.43356c4.94479,3.66121 22.35728,2.82278 18.59119,11.98875c-8.82205,2.92029 -18.29916,1.70366 -27.45192,2.00166c2.43703,25.01987 5.80666,50.04211 11.43709,74.54305c3.28979,5.43672 16.35808,9.61523 5.63309,16.70296c-4.00256,13.19919 8.78183,23.08223 16.81097,31.55379c8.82797,6.61176 4.54482,19.91519 17.0338,22.03693c9.83562,9.52774 -13.5036,9.27408 -19.49568,9.29486c-39.66827,0.42773 -79.37933,1.02615 -119.03208,-0.25211c-3.24605,-0.40967 -7.25645,-0.31595 -9.56982,-3.08264z",
+	"chess_knight": "m100.17753,299.2356c-10.0382,0.34137 -24.72987,-4.84531 -14.46609,-16.41525c11.17445,-4.40472 -1.98608,-19.00409 9.21265,-25.88123c8.98889,-12.79953 21.20518,-24.48807 24.89179,-40.11865c-0.57252,-10.60066 -13.22608,-16.87427 -7.18922,-28.60765c-5.92265,-18.77635 -4.55389,-40.38806 6.25748,-57.26643c9.18032,-15.67659 20.32635,-32.28713 19.15084,-51.25797c-11.5139,4.80804 -23.70148,9.0206 -36.37307,6.83708c-11.91311,-1.1064 -22.59742,8.54017 -34.74928,3.29494c-12.31807,-2.55921 -19.64501,-19.02957 -10.4606,-28.65753c10.03679,-8.57325 24.78339,-8.84916 34.35549,-18.41713c12.62932,-10.46186 24.31081,-24.61204 41.71716,-26.46155c7.69322,-1.76131 10.99294,-9.49197 15.25148,-15.2854c3.53894,9.18849 9.69408,17.31353 18.95801,21.387c18.83824,10.9118 23.5276,33.98066 30.47462,52.94444c5.13654,14.85179 9.41592,30.35814 18.01733,43.6171c0.09145,6.36343 -9.56343,9.05308 -3.04225,16.51302c3.39153,20.2325 3.53752,40.95071 3.23686,61.41966c-5.72005,10.01691 -10.93028,21.19722 -3.29993,32.69295c5.09689,14.05096 17.7905,23.26645 24.03563,36.52565c3.53024,6.8656 -6.88226,16.83319 6.09091,15.10654c11.84755,6.2681 2.28101,21.56821 -9.50232,17.11713c-44.15834,1.12289 -88.41394,2.24417 -132.5675,0.9133z",
+	"chess_pawn": "m76.17518,297.98557c-10.50418,1.59836 -25.59558,-8.37918 -12.29734,-17.44669c11.25366,-5.8967 0.45475,-21.25174 12.35514,-28.71019c12.10069,-16.52 24.98341,-33.40712 31.01369,-53.22789c-0.84142,-9.49573 -19.64921,-25.21422 -0.595,-28.29408c15.7114,1.82648 9.96503,-21.69583 15.39529,-31.88779c3.26528,-15.46995 5.63882,-31.19783 5.05293,-47.04268c-10.94164,-0.30554 -22.10724,0.96841 -32.83411,-1.63306c-6.84238,-8.98132 15.45903,-13.45317 19.13895,-21.55999c7.72121,-11.65172 -11.3031,-24.52544 -3.15941,-38.29919c5.20168,-20.85055 29.26575,-34.36854 49.62741,-26.73076c21.08499,5.46792 36.67119,30.37529 26.64961,51.09357c-0.80009,3.99703 -7.062,9.17959 -4.97066,12.36269c9.12987,6.33601 19.70087,11.85771 25.48528,21.64108c-8.18987,5.93826 -21.89375,1.4159 -32.1122,4.23674c-9.29645,8.24593 -0.11353,25.10609 0.36266,36.41936c2.90009,12.9261 5.46037,25.96617 8.78381,38.77452c6.98657,2.72525 21.33679,5.88095 13.4649,17.20207c-11.22217,9.11032 -5.7289,23.62137 0.60231,33.84465c7.87996,15.78793 21.40668,27.84862 29.69345,43.27188c3.07736,7.12057 -7.92374,19.7316 5.78708,16.78259c14.86404,3.15744 5.96938,23.76761 -7.3875,18.8981c-49.21407,1.73288 -98.52922,2.43631 -147.74446,0.51953l-2.31185,-0.21448l0,0z",
+	"chess_queen": "m59.54884,298.46313c-11.18457,2.51251 -19.80814,-14.30008 -5.94004,-16.129c12.20336,0.23074 -3.0349,-11.94995 7.98012,-16.05304c12.67021,-12.36537 25.23749,-25.26018 33.3575,-41.17609c-4.09126,-5.42482 -10.84344,-10.60782 -9.96117,-18.03085c7.964,-2.71161 19.82806,-0.87375 20.29981,-13.44502c7.24239,-22.68985 9.1741,-46.67986 10.76167,-70.3136c-7.99255,-6.33596 -24.45116,-0.33371 -35.62089,-3.56097c-16.94488,-4.5746 6.31873,-13.33291 13.78075,-12.6113c6.70493,0.01006 16.63324,-4.12222 5.41084,-7.2804c9.46686,-0.43687 23.08297,-12.44518 7.51486,-16.77373c11.54188,-8.28655 2.64816,-26.31929 -2.17102,-36.68976c-7.265,-12.52285 -19.21146,-21.59242 -32.71435,-26.42871c-2.18616,-12.77 18.63421,-8.99565 27.07909,-9.65835c12.78728,0.48775 25.82639,-0.15282 36.96732,-7.11507c15.05278,-6.96464 27.8495,4.65901 41.61934,7.11611c13.92807,0.89699 28.41634,-2.50577 41.97807,1.44028c4.20209,2.98911 11.18788,7.71034 2.77457,9.97613c-16.06789,8.94404 -31.07338,22.15693 -35.10127,40.92605c-6.0766,10.44077 4.6955,19.50048 -5.15381,26.98807c-0.10249,8.80961 22.85634,10.04067 10.00395,14.37878c8.80815,4.77542 27.69864,1.76332 29.62625,12.3696c-7.99612,6.2903 -19.2092,3.80788 -28.79007,4.39512c-3.2489,1.10706 -11.41316,-2.70125 -10.17032,2.89742c-0.6366,25.08775 5.87923,49.75521 12.1806,73.83221c0.00804,11.79608 29.09497,5.10777 12.92737,18.49597c-11.94247,10.28146 5.56685,24.68452 11.63272,33.82986c8.25099,10.03221 22.89711,15.11021 21.67468,29.8362c8.40468,0.60507 18.40166,13.69095 6.78131,16.95151c-62.8902,1.31946 -125.82766,2.22778 -188.72791,1.83258z",
+	"chess_rock": "m70.40736,299.11804c-15.60727,2.87628 -15.90823,-19.81082 -1.8931,-20.53482c-4.2011,-9.73361 -0.98556,-21.67557 5.22356,-30.68398c8.90442,-15.05035 22.29623,-30.00999 19.52936,-48.8515c-0.95786,-9.8022 -13.10349,-27.37677 5.72565,-24.85997c5.09087,-9.77498 2.13017,-24.16621 5.9483,-35.39389c3.33424,-21.28385 10.75552,-43.9948 2.86147,-65.09612c-4.97705,-11.23243 -17.62387,-18.62589 -16.26645,-32.35733c-1.42947,-13.39034 -0.95647,-26.88279 0.60455,-40.23392c6.07738,0.50975 12.84039,-1.27954 18.38155,1.475c-0.04153,12.96106 12.26991,10.08973 10.7935,-0.92486c3.23881,-1.28251 8.60017,-0.18413 12.6562,-0.55014c18.03256,0 36.06522,0 54.09778,0c-2.06311,7.51434 3.5195,17.19948 10.5887,8.35272c-1.93379,-11.75267 14.25911,-7.86334 10.37854,2.24694c0.22855,13.39515 1.87041,27.25403 -1.89201,40.29753c-6.12787,5.2086 -6.22449,15.45995 -13.90137,21.60233c-6.16908,11.51656 -3.45045,25.43306 -2.7644,37.9428c2.61279,18.51363 6.92676,36.79671 8.00221,55.52328c-0.76923,10.18126 20.18948,7.18474 11.15244,19.71645c-9.87662,8.41151 -4.0954,22.61668 -0.18413,32.66171c7.71916,17.36203 23.99019,32.95758 21.5343,53.32025c-1.94743,8.89606 14.16618,5.88821 9.97758,17.34372c-0.12151,14.11871 -21.10172,5.04239 -30.39526,8.00793c-46.7146,0.56656 -93.44374,1.44144 -140.159,0.99585z"
+	}
+}

+ 0 - 0
main/inc/lib/svg-edit/index.html → main/inc/lib/svg-edit/extensions/shapelib/index.html


+ 9 - 0
main/inc/lib/svg-edit/extensions/shapelib/math.json

@@ -0,0 +1,9 @@
+{"data": {
+	"divide": "m150,0.99785l0,0c25.17819,0 45.58916,20.41097 45.58916,45.58916c0,25.17821 -20.41096,45.58916 -45.58916,45.58916c-25.17822,0 -45.58916,-20.41093 -45.58916,-45.58916c0,-25.1782 20.41093,-45.58916 45.58916,-45.58916zm0,296.25203c-25.17822,0 -45.58916,-20.41095 -45.58916,-45.58917c0,-25.17819 20.41093,-45.58916 45.58916,-45.58916c25.17819,0 45.58916,20.41096 45.58916,45.58916c0,25.17822 -20.41096,45.58917 -45.58916,45.58917zm-134.06754,-193.71518l268.13507,0l0,91.17833l-268.13507,0z",
+	"equal": "m0.99915,31.03476l297.3767,0l0,95.17349l-297.3767,0zm0,47.58677l297.3767,0l0,95.17349l-297.3767,0z",
+	"minus": "m0.99887,102.39503l297.49445,0l0,95.2112l-297.49445,0z",
+	"not_equal": "m40.81188,62.2131l103.7978,0l22.27972,-61.2131l65.67503,23.90375l-13.5795,37.30935l40.20317,0l0,69.88993l-65.64099,0l-12.71893,34.94495l78.35992,0l0,69.88991l-103.79779,0l-22.27972,61.21309l-65.67503,-23.90378l13.57949,-37.30933l-40.20319,0l0,-69.88991l65.64102,0l12.71894,-34.94498l-78.35995,0z",
+	"times": "m1.00089,73.36786l72.36697,-72.36697l76.87431,76.87368l76.87431,-76.87368l72.36765,72.36697l-76.87433,76.87431l76.87433,76.87431l-72.36765,72.36765l-76.87431,-76.87433l-76.87431,76.87433l-72.36697,-72.36765l76.87368,-76.87431l-76.87368,-76.87431z",
+	"plus": "m1.00211,102.40185l101.39974,0l0,-101.39975l95.45412,0l0,101.39975l101.3997,0l0,95.45412l-101.3997,0l0,101.3997l-95.45412,0l0,-101.3997l-101.39974,0z"
+	}
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 4 - 0
main/inc/lib/svg-edit/extensions/shapelib/misc.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 10 - 0
main/inc/lib/svg-edit/extensions/shapelib/music.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1 - 0
main/inc/lib/svg-edit/extensions/shapelib/object.json


+ 12 - 0
main/inc/lib/svg-edit/extensions/shapelib/raphael.txt

@@ -0,0 +1,12 @@
+All Raphaël icons were retrieved from here:
+http://raphaeljs.com/icons/
+
+And fall under the MIT license:
+
+Copyright © 2008 Dmitry Baranovskiy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+The software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 8 - 0
main/inc/lib/svg-edit/extensions/shapelib/raphael_1.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 4 - 0
main/inc/lib/svg-edit/extensions/shapelib/raphael_2.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 0
main/inc/lib/svg-edit/extensions/shapelib/symbol.json


+ 31 - 2
main/inc/lib/svg-edit/images/svg_edit_icons.svg

@@ -540,6 +540,18 @@
  </svg>
 </g>
 
+<g id="context_menu">
+	<svg width="120" height="120" xmlns="http://www.w3.org/2000/svg">
+	  <path stroke-width="0" id="svg_11" d="m4.5,46.5l52,0l-26,38l-26,-38z" stroke="#000" fill="#000"/>
+	  <g id="svg_16">
+	   <line stroke-width="10" id="svg_12" y2="27.5" x2="117.5" y1="27.5" x1="59.5" stroke="#000" fill="#000"/>
+	   <line id="svg_13" stroke-width="10" y2="51.5" x2="117.5" y1="51.5" x1="59.5" stroke="#000" fill="#000"/>
+	   <line id="svg_14" stroke-width="10" y2="73.5" x2="117.5" y1="73.5" x1="59.5" stroke="#000" fill="#000"/>
+	   <line id="svg_15" stroke-width="10" y2="97.5" x2="117.5" y1="97.5" x1="59.5" stroke="#000" fill="#000"/>
+	  </g>
+	</svg>
+</g>
+
 <g id="move_bottom">
 <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
  <defs>
@@ -664,6 +676,23 @@
 </svg>
 </g>
 
+<g id="unlink_use">
+<svg width="222" height="222" xmlns="http://www.w3.org/2000/svg">
+  <path id="svg_1" d="m93.75,118.44922c-4.5,13.58447 -14.66553,11.5 -28.25,11.5l-34,0c-13.58447,0 -24.5,-7.16553 -24.5,-21.5c0,-14.33447 10.91553,-20.5 24.5,-20.5l34,0c13.58447,0 19.75,-2.33447 26.5,10.75" stroke-width="13" stroke="#3f3f3f" fill="none"/>
+  <g id="svg_11">
+   <line id="svg_4" y2="65.94563" x2="83.07683" y1="28.27895" x1="45.41017" stroke-linecap="round" stroke-width="8" stroke="#007fff" fill="none"/>
+   <line id="svg_5" y2="15.01293" x2="109.41467" y1="65.94638" x1="109.41467" stroke-linecap="round" stroke-width="8" stroke="#007fff" fill="none"/>
+   <line id="svg_6" y2="29.31928" x2="177.58937" y1="65.94638" x1="140.96227" stroke-linecap="round" stroke-width="8" stroke="#007fff" fill="none"/>
+  </g>
+  <g id="svg_12" transform="rotate(-180, 108, 172.111)">
+   <line y2="190.94563" x2="79.57683" y1="153.27895" x1="41.91017" stroke-linecap="round" stroke-width="8" stroke="#007fff" fill="none" id="svg_13"/>
+   <line y2="140.01293" x2="105.91467" y1="190.94638" x1="105.91467" stroke-linecap="round" stroke-width="8" stroke="#007fff" fill="none" id="svg_14"/>
+   <line y2="154.31928" x2="174.08937" y1="190.94638" x1="137.46227" stroke-linecap="round" stroke-width="8" stroke="#007fff" fill="none" id="svg_15"/>
+  </g>
+  <path transform="rotate(-180, 172.125, 108.926)" id="svg_2" d="m215.5,118.44901c-4.5,13.58499 -14.6655,11.5 -28.25,11.5l-34,0c-13.5845,0 -24.5,-7.16501 -24.5,-21.5c0,-14.3343 10.9155,-20.4998 24.5,-20.4998l34,0c13.5845,0 19.75,-2.3345 26.5,10.75" stroke-width="13" stroke="#3f3f3f" fill="none"/>
+</svg>
+</g>
+
 <g id="width">
 	<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
 	  <path id="svg_6" d="m19,42.5l-7.5,7.5l7.5,7.5l0,-15zm0,7.5l62,0l0,-7.5l7.5,7.5l-7.5,7.5l0,-7.5" stroke-width="8" stroke="#000000" fill="#000000"/>
@@ -704,8 +733,8 @@
 </g>
 
 <g id="fontsize">
-<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg" xmlns:xml="http://www.w3.org/XML/1998/namespace">
-  <text fill="#606060" stroke="none" x="14.451" y="41.4587" id="svg_2" font-size="26" font-family="serif" text-anchor="middle" xml:space="preserve">T</text>
+<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg">
+  <text fill="#606060" stroke="none" x="14.451" y="41.4587" id="svg_2" font-size="26" font-family="serif" text-anchor="middle">T</text>
   <text fill="#000000" stroke="none" x="28.853" y="41.8685" font-size="52" font-family="serif" text-anchor="middle" xml:space="preserve" id="svg_3">T</text>
 </svg>
 </g>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
main/inc/lib/svg-edit/jgraduate/jquery.jgraduate.min.js


+ 1 - 1
main/inc/lib/svg-edit/js-hotkeys/jquery.hotkeys.min.js

@@ -12,4 +12,4 @@
  * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
 */
 
-(function(b){b.hotkeys={version:"0.8",specialKeys:{8:"backspace",9:"tab",13:"return",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",191:"/",224:"meta"},shiftNums:{"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":": ","'":'"',",":"<",".":">","/":"?","\\":"|"}};function a(d){if(typeof d.data!=="string"){return}var c=d.handler,e=d.data.toLowerCase().split(" ");d.handler=function(n){if(this!==n.target&&(/textarea|select/i.test(n.target.nodeName)||n.target.type==="text")){return}var h=n.type!=="keypress"&&b.hotkeys.specialKeys[n.which],o=String.fromCharCode(n.which).toLowerCase(),k,m="",g={};if(n.altKey&&h!=="alt"){m+="alt+"}if(n.ctrlKey&&h!=="ctrl"){m+="ctrl+"}if(n.metaKey&&!n.ctrlKey&&h!=="meta"){m+="meta+"}if(n.shiftKey&&h!=="shift"){m+="shift+"}if(h){g[m+h]=true}else{g[m+o]=true;g[m+b.hotkeys.shiftNums[o]]=true;if(m==="shift+"){g[b.hotkeys.shiftNums[o]]=true}}for(var j=0,f=e.length;j<f;j++){if(g[e[j]]){return c.apply(this,arguments)}}}}b.each(["keydown","keyup","keypress"],function(){b.event.special[this]={add:a}})})(jQuery);
+(function(b){b.hotkeys={version:"0.8",specialKeys:{8:"backspace",9:"tab",13:"return",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",191:"/",224:"meta",219:"[",221:"]"},shiftNums:{"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":": ","'":'"',",":"<",".":">","/":"?","\\":"|"}};function a(d){if(typeof d.data!=="string"){return}var c=d.handler,e=d.data.toLowerCase().split(" ");d.handler=function(n){if(this!==n.target&&(/textarea|select/i.test(n.target.nodeName)||n.target.type==="text")){return}var h=n.type!=="keypress"&&b.hotkeys.specialKeys[n.which],o=String.fromCharCode(n.which).toLowerCase(),k,m="",g={};if(n.altKey&&h!=="alt"){m+="alt+"}if(n.ctrlKey&&h!=="ctrl"){m+="ctrl+"}if(n.metaKey&&!n.ctrlKey&&h!=="meta"){m+="meta+"}if(n.shiftKey&&h!=="shift"){m+="shift+"}if(h){g[m+h]=true}else{g[m+o]=true;g[m+b.hotkeys.shiftNums[o]]=true;if(m==="shift+"){g[b.hotkeys.shiftNums[o]]=true}}for(var j=0,f=e.length;j<f;j++){if(g[e[j]]){return c.apply(this,arguments)}}}}b.each(["keydown","keyup","keypress"],function(){b.event.special[this]={add:a}})})(jQuery);

+ 1 - 0
main/inc/lib/svg-edit/locale/locale.js

@@ -39,6 +39,7 @@ var svgEditor = (function($, Editor) {
 		var url = conf.langPath + "lang." + lang_param + ".js";
 		
 		var processFile = function(data){
+			if(!data) return;
 			var LangData = eval(data), js_strings;
 			var more = Editor.canvas.runExtensions("addLangData", lang_param, true);
 			$.each(more, function(i, m) {

+ 0 - 1
main/inc/lib/svg-edit/locale/locale.min.js

@@ -1 +0,0 @@
-var svgEditor=(function($,Editor){Editor.putLocale=function(given_param,good_langs){var lang_param;if(given_param){lang_param=given_param}else{lang_param=$.pref("lang");if(!lang_param){if(navigator.userLanguage){lang_param=navigator.userLanguage}else{if(navigator.language){lang_param=navigator.language}}if(lang_param==""){return}}if($.inArray(lang_param,good_langs)==-1){lang_param="en"}if(lang_param.indexOf("en")==0){return}}var conf=Editor.curConfig;var url=conf.langPath+"lang."+lang_param+".js";var processFile=function(data){var LangData=eval(data),js_strings;var more=Editor.canvas.runExtensions("addLangData",lang_param,true);$.each(more,function(i,m){if(m.data){LangData=$.merge(LangData,m.data)}});$.each(LangData,function(i,data){if(data.id){var elem=$("#svg_editor").parent().find("#"+data.id)[0];if(elem){if(data.title){elem.title=data.title}if(data.textContent){$.each(elem.childNodes,function(j,node){if(node.nodeType==3&&$.trim(node.textContent)){node.textContent=data.textContent}})}}}else{if(data.js_strings){js_strings=data.js_strings}}});Editor.setLang(lang_param,js_strings)};$.ajax({url:url,dataType:"text",success:processFile,error:function(xhr){if(xhr.responseText){processFile(xhr.responseText)}}})};return Editor}(jQuery,svgEditor));

+ 5 - 3
main/inc/lib/svg-edit/spinbtn/JQuerySpinBtn.js

@@ -117,10 +117,12 @@ $.fn.SpinButton = function(cfg){
 			var x = e.pageX || e.x;
 			var y = e.pageY || e.y;
 			var el = e.target || e.srcElement;
-			var height = $(el).outerHeight()/2;
+			var scale = svgEditor.tool_scale || 1;
+			var height = $(el).height()/2;
+			
 			var direction = 
-				(x > coord(el,'offsetLeft') + el.offsetWidth - this.spinCfg._btn_width)
-				? ((y < coord(el,'offsetTop') + height) ? 1 : -1) : 0;
+				(x > coord(el,'offsetLeft') + el.offsetWidth*scale - this.spinCfg._btn_width)
+				? ((y < coord(el,'offsetTop') + height*scale) ? 1 : -1) : 0;
 			
 			if (direction !== this.spinCfg._direction) {
 				// Style up/down buttons:

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
main/inc/lib/svg-edit/spinbtn/JQuerySpinBtn.min.js


+ 212 - 26
main/inc/lib/svg-edit/svg-editor.css

@@ -2,6 +2,13 @@
 	background: #D8D8D8;
 }
 
+#svg_editor * {
+	transform-origin: 0 0;
+	-moz-transform-origin: 0 0;
+	-o-transform-origin: 0 0;
+	-webkit-transform-origin: 0 0;
+}
+
 #svg_editor {
 	font-size: 8pt;
 	font-family: Verdana, Helvetica, Arial;
@@ -47,6 +54,59 @@
 	background: -webkit-gradient(radial, center center, 3, center center, 1000, from(#bbb), to(#222));
 }
 
+#rulers > div {
+	position: absolute;
+	background: #DDD;
+	z-index: 1;
+	overflow: hidden;
+}
+
+#ruler_corner {
+	top: 76px;
+	left: 41px;
+	width: 15px;
+	height: 15px;
+}
+
+#ruler_x {
+	height: 15px;
+	top: 76px;
+	left: 56px;
+	right: 30px;
+	border-bottom: 1px solid;
+	border-left: 1px solid #777;
+}
+
+#rulers.moved #ruler_corner,
+#rulers.moved #ruler_x {
+	top: 101px;
+}
+
+#ruler_y {
+	width: 15px;
+	top: 91px;
+	left: 41px;
+	bottom: 78px;
+	border-right: 1px solid;
+	border-top: 1px solid #777;
+}
+
+#rulers.moved #ruler_y {
+	top: 116px;
+}
+
+
+#ruler_x canvas {
+	margin-left: -16px;
+}
+
+#ruler_y canvas {
+	margin-top: -16px;
+}
+
+
+
+
 #svg_editor div#palette_holder {
 	overflow-x: scroll;
 	overflow-y: hidden;
@@ -183,13 +243,13 @@
 	padding: 0px;
 	padding-left: 2px;
 	padding-right: 2px;
-	width: 106px;
+	width: 123px;
 	height: 20px;
 	border-right: 1px solid #FFFFFF;
 	border-bottom: 1px solid #FFFFFF;
 	border-left: 1px solid #808080;
 	border-top: 1px solid #808080;
-	overflow: auto;
+	overflow: hidden;
 }
 
 #svg_editor .layer_button {
@@ -205,6 +265,10 @@
 	margin-right: 3px;
 }
 
+#svg_editor .layer_button:last-child {
+	margin-right: 0;
+}
+
 #svg_editor .layer_buttonpressed {
 	width: 14px;
 	height: 14px;
@@ -219,7 +283,7 @@
 #svg_editor #layerlist {
 	margin: 1px;
 	padding: 0px;
-	width: 110px;
+	width: 127px;
 	border-collapse: collapse;	
 	border: 1px solid #808080;
 	background-color: #FFFFFF;
@@ -278,6 +342,7 @@
 	position: absolute;
 	top: 4px;
 	left: 4px;
+	z-index: 5;
 }
 
 
@@ -436,16 +501,7 @@
 	fill: #FFF !important;
 }
 
-#svg_editor #selected_panel,
-#svg_editor #multiselected_panel,
-#svg_editor #g_panel,
-#svg_editor #rect_panel,
-#svg_editor #circle_panel,
-#svg_editor #ellipse_panel,
-#svg_editor #line_panel,
-#svg_editor #image_panel,
-#svg_editor #text_panel,
-#svg_editor #path_node_panel {
+#tools_top div[id$="_panel"]:not(#editor_panel):not(#history_panel) {
 	display: none;
 }
 
@@ -453,6 +509,28 @@
 	vertical-align: 12px;
 }
 
+#cur_context_panel {
+	position: absolute;
+	top: 70px;
+	left: -10px;
+	right: -2px;
+	overflow: auto;
+	border: 1px solid #777;
+	border-bottom: none;
+	border-right: none;
+	padding-left: 5px;
+	font-size: 12px;
+}
+
+#svg_editor #cur_context_panel a {
+	float: none;
+	text-decoration: none;
+}
+
+#svg_editor #cur_context_panel a:hover {
+	text-decoration: underline;
+}
+
 #svg_editor #tools_top > div, #tools_top {
 	line-height: 26px;
 }
@@ -466,6 +544,11 @@
 	height: 34px;
 }
 
+#svg_editor div.toolset label span {
+/*	outline: 1px solid red;*/
+	padding-top: 3px;
+	display: inline-block;
+}
 
 #tools_top > div > * {
 	float: left;
@@ -691,6 +774,7 @@ span.zoom_tool {
 	display: none;
 	cursor: pointer;
 	width: 400px;
+	z-index: 1;
 }
 
 #svg_editor .tools_flyout_v {
@@ -921,12 +1005,23 @@ span.zoom_tool {
 	z-index: 6;
 }
 
+#save_output_btns {
+	display: none;
+	text-align: left;
+}
+
+#save_output_btns p {
+	margin: .5em 1.5em;
+	display: inline-block;
+}
+
 #bg_blocks {
 	overflow: auto;
 	margin-left: 30px;
 }
 
-#svg_docprops #svg_docprops_container {
+#svg_docprops #svg_docprops_container,
+#svg_prefs #svg_prefs_container {
 	position: absolute;
 	top: 50px;
 	padding: 10px;
@@ -948,40 +1043,45 @@ span.zoom_tool {
 	max-width: 14em;
 }
 
-#tool_docprops_back {
+#tool_docprops_back, 
+#tool_prefs_back {
 	margin-left: 1em;
 	overflow: auto;
 }
 
 #svg_docprops_container #svg_docprops_docprops, 
-#svg_docprops_container #svg_docprops_prefs {
+#svg_prefs #svg_docprops_prefs {
 	float: left;
 	width: 221px;
 	margin: 5px .7em; 
 	overflow: hidden;
 }
 
-#svg_docprops_container #svg_docprops_prefs {
+#svg_prefs_container fieldset + fieldset {
 	float: right;
 }
 
-#svg_docprops legend {
+#svg_docprops legend, 
+#svg_prefs legend {
 	max-width: 195px;
 }
 
-#svg_docprops_docprops > legend, #svg_docprops_prefs > legend {
+#svg_docprops_docprops > legend, 
+#svg_prefs_container > fieldset > legend {
 	font-weight: bold;
 	font-size: 1.1em;
 }
 
 
-#svg_docprops_container fieldset {
+#svg_docprops_container fieldset,
+#svg_prefs fieldset {
 	padding: 5px;
 	margin: 5px;
 	border: 1px solid #DDD;
 }
 
-#svg_docprops_container label {
+#svg_docprops_container label,
+#svg_prefs_container label {
 	display: block;
 	margin: .5em;
 }
@@ -992,8 +1092,9 @@ span.zoom_tool {
 	color: #444;
 }
 
-#canvas_title {
+#canvas_title, #canvas_bg_url {
 	display: block;
+	width: 96%;
 }
 
 #svg_source_editor #svg_source_textarea {
@@ -1010,7 +1111,7 @@ span.zoom_tool {
 	padding-left: 20px;
 }
 
-#svg_docprops_container div.color_block {
+#svg_prefs_container div.color_block {
 	float: left;
 	margin: 2px;
 	padding: 20px;
@@ -1028,12 +1129,14 @@ span.zoom_tool {
 	text-align: left;
 }
 
-#svg_docprops button {
+#svg_docprops button,
+#svg_prefs button {
 	margin-top: 0;
 	margin-bottom: 5px;
 }
 
-#svg_docprops {
+#svg_docprops,
+#svg_prefs {
 	display: none;
 }
 
@@ -1045,7 +1148,8 @@ span.zoom_tool {
 	margin-left: 0;
 }
 
-#svg_docprops #svg_docprops_overlay {
+#svg_docprops #svg_docprops_overlay,
+#svg_prefs #svg_prefs_overlay {
 	position: absolute;
 	top: 0px;
 	right: 0px;
@@ -1056,6 +1160,10 @@ span.zoom_tool {
 	z-index: 20000;
 }
 
+#tool_prefs_option {
+	float: right;
+}
+
 .toolbar_button button {
     border:1px solid #dedede;
     line-height:130%;
@@ -1201,3 +1309,81 @@ span.zoom_tool {
 	-webkit-border-radius: 0px;	
 }
 
+/* Generic context menu styles */
+.contextMenu {
+	position: absolute;
+	z-index: 99999;
+	border: solid 1px rgba(0,0,0,.33);
+	background: rgba(255,255,255,.95);
+	padding: 5px 0;
+	margin: 0px;
+	display: none;
+	font: 12px/15px Lucida Sans, Helvetica, Verdana, sans-serif;
+	border-radius: 5px;
+	-moz-border-radius: 5px;
+	-moz-box-shadow: 2px 5px 10px rgba(0,0,0,.3);
+	-webkit-box-shadow: 2px 5px 10px rgba(0,0,0,.3);
+	box-shadow: 2px 5px 10px rgba(0,0,0,.3);
+}
+
+.contextMenu LI {
+	list-style: none;
+	padding: 0px;
+	margin: 0px;
+}
+
+.contextMenu .shortcut {
+	width: 115px;           
+	text-align:right;
+	float:right;
+}
+
+.contextMenu A {
+	-moz-user-select: none;
+	-webkit-user-select: none;
+	color: #222;
+	text-decoration: none;
+	display: block;
+	line-height: 20px;
+	height: 20px;
+	background-position: 6px center;
+	background-repeat: no-repeat;
+	outline: none;
+	padding: 0px 15px 1px 20px;
+}
+
+.contextMenu LI.hover A {
+	background-color: #2e5dea;
+	color: white;
+	cursor: default;
+}
+
+.contextMenu LI.disabled A {
+	color: #999;
+}
+
+.contextMenu LI.hover.disabled A {
+	background-color: transparent;
+}
+
+.contextMenu LI.separator {
+	border-top: solid 1px #E3E3E3;
+	padding-top: 5px;
+	margin-top: 5px;
+}
+
+/*
+	Adding Icons
+	
+	You can add icons to the context menu by adding
+	classes to the respective LI element(s)
+*/
+/*
+
+.contextMenu LI.edit A { background-image: url(images/page_white_edit.png); }
+.contextMenu LI.cut A { background-image: url(images/cut.png); }
+.contextMenu LI.copy A { background-image: url(images/page_white_copy.png); }
+.contextMenu LI.paste A { background-image: url(images/page_white_paste.png); }
+.contextMenu LI.delete A { background-image: url(images/page_white_delete.png); }
+.contextMenu LI.quit A { background-image: url(images/door.png); }
+*/

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 413 - 123
main/inc/lib/svg-edit/svg-editor.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
main/inc/lib/svg-edit/svg-editor.min.js


+ 137 - 43
main/inc/lib/svg-edit/svg-editor.php

@@ -8,6 +8,9 @@
 require_once '../../../inc/global.inc.php';//hack for Chamilo
 api_protect_course_script();
 api_block_anonymous_users();
+if(!isset($_SESSION['draw_dir'])){
+		die();
+	}
 ?>
 
 <!DOCTYPE html>
@@ -21,36 +24,31 @@ api_block_anonymous_users();
 <link rel="stylesheet" href="jgraduate/css/jgraduate.css" type="text/css"/>
 <link rel="stylesheet" href="svg-editor.css" type="text/css"/>
 <link rel="stylesheet" href="spinbtn/JQuerySpinBtn.css" type="text/css"/>
-
-<!-- Release version of script tags: -->
-<script type="text/javascript" src="jquery.js"></script>
+<!-- Development version of script tags: --><!--Chamilo TODO: compress sgv-editor.js and change all calls by release version -->
+<script type="text/javascript" src="jquery.js"></script><!--chamilo enabled -->
+<!--<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.js"></script> --><!--chamilo disabled -->
 <script type="text/javascript" src="js-hotkeys/jquery.hotkeys.min.js"></script>
-<script type="text/javascript" src="jgraduate/jquery.jgraduate.min.js"></script>
-<script type="text/javascript" src="svgicons/jquery.svgicons.min.js"></script>
+<script type="text/javascript" src="jgraduate/jquery.jgraduate.js"></script>
+<script type="text/javascript" src="svgicons/jquery.svgicons.js"></script>
 <script type="text/javascript" src="jquerybbq/jquery.bbq.min.js"></script>
-<script type="text/javascript" src="spinbtn/JQuerySpinBtn.min.js"></script>
-<script type="text/javascript" src="svgcanvas.min.js"></script>
-<!--<script type="text/javascript" src="svg-editor.min.js"></script> --><!-- Replaced by bottom line. While integration into Chamilo, change compress svg-editor.min.js by svg-editor.js file -->
+<script type="text/javascript" src="spinbtn/JQuerySpinBtn.js"></script>
+<script type="text/javascript" src="contextmenu/jquery.contextMenu.js"></script>
+<script type="text/javascript" src="svgcanvas.js"></script>
 <script type="text/javascript" src="svg-editor.js"></script>
-<script type="text/javascript" src="locale/locale.min.js"></script>
-
-<!-- See http://code.google.com/p/svg-edit/wiki/ConfigOptions for configuration options -->
-
+<script type="text/javascript" src="locale/locale.js"></script>
 <!-- you can load extensions here -->
 <!-- <script type="text/javascript" src="extensions/ext-helloworld.js"></script> -->
 
-
-<!-- Development version of script tags: 
+<!-- Release version of script tags: >
 <script type="text/javascript" src="jquery.js"></script>
-<script type="text/javascript" src="js-hotkeys/jquery.hotkeys.min.js"></script>
-<script type="text/javascript" src="jgraduate/jquery.jgraduate.min.js"></script>
-<script type="text/javascript" src="svgicons/jquery.svgicons.min.js"></script>
+<script type="text/javascript" src="js-hotkeys/jquery.hotkeys-0.7.9.js"></script>
 <script type="text/javascript" src="jquerybbq/jquery.bbq.min.js"></script>
-<script type="text/javascript" src="spinbtn/JQuerySpinBtn.js"></script>
-<script type="text/javascript" src="svgcanvas.js"></script>
-<script type="text/javascript" src="svg-editor.js"></script>
-<script type="text/javascript" src="locale/locale.js"></script>
--->
+<script type="text/javascript" src="jgraduate/jquery.jgraduate.min.js"></script>
+<script type="text/javascript" src="spinbtn/JQuerySpinBtn.min.js"></script>
+<script type="text/javascript" src="svgcanvas.min.js"></script>
+<script type="text/javascript" src="svg-editor.min.js"></script>
+script type="text/javascript" src="locale/locale.min.js"></script-->
+
 
 <!-- always minified scripts -->
 <script type="text/javascript" src="jquery-ui/jquery-ui-1.8.custom.min.js"></script>
@@ -66,9 +64,21 @@ api_block_anonymous_users();
 <body>
 <div id="svg_editor">
 
+<div id="rulers">
+	<div id="ruler_corner"></div>
+	<div id="ruler_x">
+		<canvas height="15"></canvas>
+	</div>
+	<div id="ruler_y">
+		<canvas width="15"></canvas>
+	</div>
+</div>
+
 <div id="workarea">
 <style id="styleoverrides" type="text/css" media="screen" scoped="scoped"></style>
-<div id="svgcanvas"></div>
+<div id="svgcanvas" style="position:relative">
+
+</div>
 </div>
 
 <div id="sidepanels">
@@ -80,6 +90,7 @@ api_block_anonymous_users();
 			<div id="layer_rename" class="layer_button"  title="Rename Layer"></div>
 			<div id="layer_up" class="layer_button"  title="Move Layer Up"></div>
 			<div id="layer_down" class="layer_button"  title="Move Layer Down"></div>
+			<div id="layer_moreopts" class="layer_button"  title="More Options"></div>
 		</fieldset>
 		
 		<table id="layerlist">
@@ -111,7 +122,7 @@ api_block_anonymous_users();
 				<div></div>
 				New Image [N]
 			</li>
-            
+			
 			<li id="tool_open" style="display:none;">
 				<div id="fileinputs">
 					<div></div>
@@ -141,13 +152,18 @@ api_block_anonymous_users();
 				Document Properties [P]
 			</li>
 		</ul>
-		
-		<p
+
+		<p>
 			<!--<a href="http://svg-edit.googlecode.com/" target="_blank">
 				SVG-edit Home Page
-			</a> --><!-- comment for Chamilo -->
+			</a> --><!-- Comment for Chamilo -->
 		</p>
 
+		<button id="tool_prefs_option">
+			Editor Options
+		</button>
+
+
 	</div>
 </div>
 
@@ -174,8 +190,8 @@ api_block_anonymous_users();
 			<div class="push_button" id="tool_clone" title="Clone Element [C]"></div>
 			<div class="push_button" id="tool_delete" title="Delete Element [Delete/Backspace]"></div>
 			<div class="tool_sep"></div>
-			<div class="push_button" id="tool_move_top" title="Move to Top [Shift+Up]"></div>
-			<div class="push_button" id="tool_move_bottom" title="Move to Bottom [Shift+Down]"></div>
+			<div class="push_button" id="tool_move_top" title="Bring to Front [ Ctrl+Shift+] ]"></div>
+			<div class="push_button" id="tool_move_bottom" title="Send to Back [ Ctrl+Shift+[ ]"></div>
 			<div class="push_button" id="tool_topath" title="Convert to Path"></div>
 			<div class="push_button" id="tool_reorient" title="Reorient path"></div>
 			<div class="tool_sep"></div>
@@ -185,7 +201,7 @@ api_block_anonymous_users();
 			</label>
 		</div>
 
-		<label id="tool_angle" title="Change rotation angle">
+		<label id="tool_angle" title="Change rotation angle" class="toolset">
 			<span id="angleLabel" class="icon_label"></span>
 			<input id="angle" size="2" value="0" type="text"/>
 		</label>
@@ -244,11 +260,6 @@ api_block_anonymous_users();
 
 	</div>
 
-	<div id="g_panel">
-		<div class="tool_sep"></div>
-		<div class="push_button" id="tool_ungroup" title="Ungroup Elements [G]"></div>
-	</div>
-
 	<div id="rect_panel">
 		<div class="toolset">
 			<label id="rect_width_tool" title="Change rectangle width">
@@ -260,7 +271,7 @@ api_block_anonymous_users();
 				<input id="rect_height" class="attr_changer" size="3" data-attr="height"/>
 			</label>
 		</div>
-		<label id="cornerRadiusLabel" title="Change Rectangle Corner Radius">
+		<label id="cornerRadiusLabel" title="Change Rectangle Corner Radius" class="toolset">
 			<span class="icon_label"></span>
 			<input id="rect_rx" size="3" value="0" type="text" data-attr="Corner Radius"/>
 		</label>
@@ -371,6 +382,27 @@ api_block_anonymous_users();
 		<!-- Not visible, but still used -->
 		<input id="text" type="text" size="35"/>
 	</div>
+
+	<!-- formerly gsvg_panel -->
+	<div id="container_panel">
+		<div class="tool_sep"></div>
+
+		<!-- Add viewBox field here? -->
+
+		<label id="group_title" title="Group identification label">
+			<span>label:</span>
+			<input id="g_title" data-attr="title" size="10" type="text"/>
+		</label>
+	</div>
+	
+	<div id="use_panel">
+		<div class="push_button" id="tool_unlink_use" title="Break link to reference element (make unique)"></div>
+	</div>
+	
+	<div id="g_panel">
+		<div class="push_button" id="tool_ungroup" title="Ungroup Elements [G]"></div>
+	</div>
+
 	
 	<div id="path_node_panel">
 		<div class="tool_sep"></div>
@@ -392,7 +424,9 @@ api_block_anonymous_users();
 		<div class="tool_button" id="tool_openclose_path" title="Open/close sub-path"></div>
 		<div class="tool_button" id="tool_add_subpath" title="Add sub-path"></div>
 	</div>
-	
+	<div id="cur_context_panel">
+		
+	</div>
 </div> <!-- tools_top -->
 
 <div id="tools_left" class="tools_panel">
@@ -524,7 +558,7 @@ api_block_anonymous_users();
 	<div id="tools_bottom_3">
 		<div id="palette_holder"><div id="palette" title="Click to change fill color, shift-click to change stroke color"></div></div>
 	</div>
-<!--	<div id="copyright"><span id="copyrightLabel">Powered by</span> <a href="http://svg-edit.googlecode.com/" target="_blank">SVG-edit v2.5.1</a></div> --><!-- temporal comment for Chamilo -->
+	<!--<div id="copyright"><span id="copyrightLabel">Powered by</span> <a href="http://svg-edit.googlecode.com/" target="_blank">SVG-edit v2.6-alpha</a></div> --><!-- Comment for Chamilo -->
 </div>
 
 <div id="option_lists">
@@ -563,12 +597,17 @@ api_block_anonymous_users();
 			<button id="tool_source_save">Apply Changes</button>
 			<button id="tool_source_cancel">Cancel</button>
 		</div>
+		<div id="save_output_btns">
+			<p id="copy_save_note">Copy the contents of this box into a text editor, then save the file with a .svg extension.</p>
+			<button id="copy_save_done">Done</button>
+		</div>
 		<form>
 			<textarea id="svg_source_textarea" spellcheck="false"></textarea>
 		</form>
 	</div>
 </div>
 
+
 <div id="svg_docprops">
 	<div id="svg_docprops_overlay"></div>
 	<div id="svg_docprops_container">
@@ -582,7 +621,7 @@ api_block_anonymous_users();
 			<legend id="svginfo_image_props">Image Properties</legend>
 			<label>
 				<span id="svginfo_title">Title:</span>
-				<input type="text" id="canvas_title" size="24"/>
+				<input type="text" id="canvas_title"/>
 			</label>			
 	
 			<fieldset id="change_resolution">
@@ -610,11 +649,20 @@ api_block_anonymous_users();
 				<label><input type="radio" name="image_opt" value="embed" checked="checked"/> <span id="image_opt_embed">Embed data (local files)</span> </label>
 				<label><input type="radio" name="image_opt" value="ref"/> <span id="image_opt_ref">Use file reference</span> </label>
 			</fieldset>			
+		</fieldset>
 
+	</div>
+</div>
 
-		</fieldset>
+<div id="svg_prefs">
+	<div id="svg_prefs_overlay"></div>
+	<div id="svg_prefs_container">
+		<div id="tool_prefs_back" class="toolbar_button">
+			<button id="tool_prefs_save">OK</button>
+			<button id="tool_prefs_cancel">Cancel</button>
+		</div>
 
-		<fieldset id="svg_docprops_prefs">
+		<fieldset>
 			<legend id="svginfo_editor_prefs">Editor Preferences</legend>
 
 			<label><span id="svginfo_lang">Language:</span>
@@ -651,10 +699,34 @@ api_block_anonymous_users();
 			<fieldset id="change_background">
 				<legend id="svginfo_change_background">Editor Background</legend>
 				<div id="bg_blocks"></div>
-				<label><span id="svginfo_bg_url">URL:</span> <input type="text" id="canvas_bg_url" size="21"/></label>
+				<label><span id="svginfo_bg_url">URL:</span> <input type="text" id="canvas_bg_url"/></label>
 				<p id="svginfo_bg_note">Note: Background will not be saved with image.</p>
 			</fieldset>
 			
+			<fieldset id="change_grid">
+				<legend id="svginfo_grid_settings">Grid</legend>
+				<label><span id="svginfo_snap_onoff">Snapping on/off</span><input type="checkbox" value="snapping_on" id="grid_snapping_on"></label>
+				<label><span id="svginfo_snap_step">Snapping Step-Size:</span> <input type="text" id="grid_snapping_step" size="3" value="10"/></label>
+			</fieldset>
+
+			<fieldset id="units_rulers">
+				<legend id="svginfo_units_rulers">Units & Rulers</legend>
+				<label><span id="svginfo_rulers_onoff">Show rulers</span><input type="checkbox" value="show_rulers" id="show_rulers" checked></label>
+				<label>
+					<span id="svginfo_unit">Base Unit:</span>
+					<select id="base_unit">
+						<option value="px" selected>Pixels</option>
+						<option value="cm">Centimeters</option>
+						<option value="mm">Millimeters</option>
+						<option value="pt">Points</option>
+						<option value="pc">Picas</option>
+						<option value="em">Ems</option>
+						<option value="ex">Exs</option>
+					</select>
+				</label>
+				</label>
+			</fieldset>
+	
 		</fieldset>
 
 	</div>
@@ -668,5 +740,27 @@ api_block_anonymous_users();
 	</div>
 </div>
 
+<ul id="cmenu_canvas" class="contextMenu">
+	<li><a href="#cut">Cut</a></li>
+	<li><a href="#copy">Copy</a></li>
+	<li><a href="#paste">Paste</a></li>
+	<li><a href="#paste_in_place">Paste in Place</a></li>
+	<li class="separator"><a href="#delete">Delete</a></li>
+	<li class="separator"><a href="#group">Group<span class="shortcut">G</span></a></li>
+	<li><a href="#ungroup">Ungroup<span class="shortcut">G</span></a></li>
+        <li class="separator"><a href="#move_front">Bring to Front<span class="shortcut">SHFT+CTRL+]</span></a></li>
+	<li><a href="#move_up">Bring Forward<span class="shortcut">CTRL+]</span></a></li>
+	<li><a href="#move_down">Send Backward<span class="shortcut">CTRL+[</span></a></li>
+        <li><a href="#move_back">Send to Back<span class="shortcut">SHFT+CTRL+[</span></a></li>
+</ul>
+
+
+<ul id="cmenu_layers" class="contextMenu">
+	<li><a href="#dupe">Duplicate Layer...</a></li>
+	<li><a href="#delete">Delete Layer</a></li>
+	<li><a href="#merge_down">Merge Down</a></li>
+	<li><a href="#merge_all">Merge All</a></li>
+</ul>
+
 </body>
-</html>
+</html>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 398 - 152
main/inc/lib/svg-edit/svgcanvas.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
main/inc/lib/svg-edit/svgcanvas.min.js


+ 91 - 89
main/inc/lib/svg-edit/svgicons/jquery.svgicons.js

@@ -128,7 +128,7 @@ $(function() {
 
 
 (function($) {
-	var svg_icons = {};
+	var svg_icons = {}, fixIDs;
 
 	$.svgIcons = function(file, opts) {
 		var svgns = "http://www.w3.org/2000/svg",
@@ -144,18 +144,22 @@ $(function() {
 				var data_el = $('<object data="' + file + '" type=image/svg+xml>').appendTo('body').hide();
 				try {
 					svgdoc = data_el[0].contentDocument;
-					// TODO: IE still loads this, shouldn't even bother.
 					data_el.load(getIcons);
 					getIcons(0, true); // Opera will not run "load" event if file is already cached
 				} catch(err1) {
 					useFallback();
 				}
 			} else {
+				var parser = new DOMParser();
 				$.ajax({
 					url: file,
-					dataType: 'xml',
+					dataType: 'string',
 					success: function(data) {
-						svgdoc = data;
+						if(!data) {
+							$(useFallback);
+							return;
+						}
+						svgdoc = parser.parseFromString(data, "text/xml");
 						$(function() {
 							getIcons('ajax');
 						});
@@ -168,11 +172,17 @@ $(function() {
 							});
 						} else {
 							if(err.responseXML) {
-								svgdoc = err.responseXML;
+								svgdoc = parser.parseFromString(err.responseXML, "text/xml");
+
+								if(!svgdoc.childNodes.length) {
+									$(useFallback);									
+								}
 								$(function() {
 									getIcons('ajax');
 								});							
-							} 
+							} else {
+								$(useFallback);
+							}
 						}
 					}
 				});
@@ -198,40 +208,53 @@ $(function() {
 				}
 				data_loaded = true;
 			}
-			// Clean source SVGs (mostly for Inkscape files)
-			// TODO: Find a way to do this without crashing Safari (when converting to IMG)
-			$(svgdoc).find('metadata').remove().end()
-				.find('*').each(function(i, el) {
-				if(el.nodeName.indexOf(':') != -1) {
-					$(el).remove();
-				}
-				var attrs = $.extend(false, el.attributes, {});
-				for(i in attrs) {
-					var attr = attrs[i];
-					var fullattr = attr.prefix?attr.prefix + ':' + attr.localName:'';
-					if(attr.prefix) {
-						el.removeAttribute(attr.localName); // for Opera
-						el.removeAttribute(fullattr); // for Webkit
-					} 
-					if(fullattr == 'xlink:href') {
-						el.setAttribute('xlink:href', attr.nodeValue);
-					}
-				}
-			});
+			
 			elems = $(svgdoc.firstChild).children(); //.getElementsByTagName('foreignContent');
-			var testSrc = data_pre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D';
 			
-			testImg = $(new Image()).attr({
-				src: testSrc,
-				width: 0,
-				height: 0
-			}).appendTo('body')
-			.load(function () {
-				// Safari 4 crashes, Opera and Chrome don't
-				makeIcons(!isSafari);
-			}).error(function () {
-				makeIcons();
-			});
+			if(!opts.no_img) {
+				var testSrc = data_pre + 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D';
+				
+				testImg = $(new Image()).attr({
+					src: testSrc,
+					width: 0,
+					height: 0
+				}).appendTo('body')
+				.load(function () {
+					// Safari 4 crashes, Opera and Chrome don't
+					makeIcons(true);
+				}).error(function () {
+					makeIcons();
+				});
+			} else {
+				setTimeout(function() {
+					if(!icons_made) makeIcons();
+				},500);
+			}
+		}
+		
+		var setIcon = function(target, icon, id, setID) {
+			if(isOpera) icon.css('visibility','hidden');
+			if(opts.replace) {
+				if(setID) icon.attr('id',id);
+				var cl = target.attr('class');
+				if(cl) icon.attr('class','svg_icon '+cl);
+				target.replaceWith(icon);
+			} else {
+				
+				target.append(icon);
+			}
+			if(isOpera) {
+				setTimeout(function() {
+					icon.removeAttr('style');
+				},1);
+			}
+		}
+		
+		var addIcon = function(icon, id) {
+			if(opts.id_match === undefined || opts.id_match !== false) {
+				setIcon(holder, icon, id, true);
+			}
+			svg_icons[id] = icon;
 		}
 		
 		function makeIcons(toImage, fallback) {
@@ -239,31 +262,6 @@ $(function() {
 			if(opts.no_img) toImage = false;
 			var holder;
 			
-			var setIcon = function(target, icon, id, setID) {
-				if(isOpera) icon.css('visibility','hidden');
-				if(opts.replace) {
-					if(setID) icon.attr('id',id);
-					var cl = target.attr('class');
-					if(cl) icon.attr('class','svg_icon '+cl);
-					target.replaceWith(icon);
-				} else {
-					
-					target.append(icon);
-				}
-				if(isOpera) {
-					setTimeout(function() {
-						icon.attr('style','visibility:visible;');
-					},1);
-				}
-			}
-			
-			var addIcon = function(icon, id) {
-				if(opts.id_match === undefined || opts.id_match !== false) {
-					setIcon(holder, icon, id, true);
-				}
-				svg_icons[id] = icon;
-			}
-			
 			if(toImage) {
 				var temp_holder = $(document.createElement('div'));
 				temp_holder.hide().appendTo('body');
@@ -284,13 +282,14 @@ $(function() {
 					addIcon(icon, id);
 				});
 			} else {
-				$.each(elems, function(i, elem) {
-					var id = elem.getAttribute('id');
-					if(id == 'svg_eof') return;
+				var len = elems.length;
+				for(var i = 0; i < len; i++) {
+					var elem = elems[i];
+					var id = elem.id;
+					if(id === 'svg_eof') break;
 					holder = $('#' + id);
-			
 					var svg = elem.getElementsByTagNameNS(svgns, 'svg')[0];
-					var svgroot = svgdoc.createElementNS(svgns, "svg");
+					var svgroot = document.createElementNS(svgns, "svg");
 					svgroot.setAttributeNS(svgns, 'viewBox', [0,0,icon_w,icon_h].join(' '));
 					
 					// Make flexible by converting width/height to viewBox
@@ -304,13 +303,12 @@ $(function() {
 						svg.setAttribute('viewBox', [0,0,w,h].join(' '));
 					}
 					
-					$(svgroot).attr({
-						"xmlns": svgns,
-						"width": icon_w,
-						"height": icon_h,
-						"xmlns:xlink": xlinkns,
-						"class": 'svg_icon'
-					});
+					// Not using jQuery to be a bit faster
+					svgroot.setAttribute('xmlns', svgns);
+					svgroot.setAttribute('width', icon_w);
+					svgroot.setAttribute('height', icon_h);
+					svgroot.setAttribute("xmlns:xlink", xlinkns);
+					svgroot.setAttribute("class", 'svg_icon');
 
 					// Without cloning, Firefox will make another GET request.
 					// With cloning, causes issue in Opera/Win/Non-EN
@@ -330,7 +328,8 @@ $(function() {
 						var icon = fixIDs($(svgroot), i);
 					}
 					addIcon(icon, id);
-				});
+				}
+
 			}
 			
 			if(opts.placement) {
@@ -346,18 +345,15 @@ $(function() {
 			if(!fallback) {
 				if(toImage) temp_holder.remove();
 				if(data_el) data_el.remove();
-				testImg.remove();
+				if(testImg) testImg.remove();
 			}
-
 			if(opts.resize) $.resizeSvgIcons(opts.resize);
-
 			icons_made = true;
-			
+
 			if(opts.callback) opts.callback(svg_icons);
-			
 		}
 		
-		function fixIDs(svg_el, svg_num, force) {
+		fixIDs = function(svg_el, svg_num, force) {
 			var defs = svg_el.find('defs');
 			if(!defs.length) return svg_el;
 			
@@ -367,18 +363,18 @@ $(function() {
 				if(isOpera) no_dupes = false; // Opera didn't clone svg_el, so not reliable
 				// if(!force && no_dupes) return;
 				var new_id = 'x' + id + svg_num + i;
-				$(this).attr('id', new_id);			
-	
+				this.id = new_id;
+
 				svg_el.find('[fill="url(#' + id + ')"]').each(function() {
-					$(this).attr('fill', 'url(#' + new_id + ')');
+					this.setAttribute('fill', 'url(#' + new_id + ')');
 				}).end().find('[stroke="url(#' + id + ')"]').each(function() {
-					$(this).attr('stroke', 'url(#' + new_id + ')');
+					this.setAttribute('stroke', 'url(#' + new_id + ')');
 				}).end().find('use').each(function() {
 					if(this.getAttribute('xlink:href') == '#' + id) {
 						this.setAttributeNS(xlinkns,'href','#' + new_id);
 					}
 				}).end().find('[filter="url(#' + id + ')"]').each(function() {
-					$(this).attr('filter', 'url(#' + new_id + ')');
+					this.setAttribute('filter', 'url(#' + new_id + ')');
 				});
 			});
 			return svg_el;
@@ -431,7 +427,13 @@ $(function() {
 		}
 	}
 	
-	$.getSvgIcon = function(id) { return svg_icons[id]; }
+	$.getSvgIcon = function(id, uniqueClone) { 
+		var icon = svg_icons[id];
+		if(uniqueClone && icon) {
+			icon = fixIDs(icon, 0, true).clone(true);
+		}
+		return icon; 
+	}
 	
 	$.resizeSvgIcons = function(obj) {
 		// FF2 and older don't detect .svg_icon, so we change it detect svg elems instead
@@ -454,4 +456,4 @@ $(function() {
 		});
 	}
 	
-})(jQuery);
+})(jQuery);

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
main/inc/lib/svg-edit/svgicons/jquery.svgicons.min.js


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů